Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
book-of-vaadin.pdf
Скачиваний:
88
Добавлен:
24.03.2015
Размер:
13.43 Mб
Скачать

User Interface Components

Figure 5.52. A Table with a Footer

Handling Mouse Clicks on Headers and Footers

Normally, when the user clicks a column header, the table will be sorted by the column, assuming that the data source is Sortable and sorting is not disabled. In some cases, you might want some other functionality when the user clicks the column header, such as selecting the column in some way.

Clicks in the header cause a HeaderClickEvent, which you can handle with a Table.HeaderClickListener. Click events on the table header (and footer) are, like button clicks, sent immediately to server, so there is no need to set setImmediate().

// Handle the header clicks

table.addListener(new Table.HeaderClickListener() { public void headerClick(HeaderClickEvent event) {

String column = (String) event.getPropertyId(); Notification.show("Clicked " + column +

"with " + event.getButtonName());

}

});

// Disable the default sorting behavior table.setSortDisabled(true);

Setting a click handler does not automatically disable the sorting behavior of the header; you need to disable it explicitly with setSortDisabled(true). Header click events are not sent when the user clicks the column resize handlers to drag them.

The HeaderClickEvent object provides the identity of the clicked column with getPropertyId(). The getButton() reports the mouse button with which the click was made: BUTTON_LEFT, BUTTON_RIGHT, or BUTTON_MIDDLE. The getButtonName() a human-readable button name in English: "left", "right", or "middle". The isShiftKey(), isCtrlKey(), etc., methods indicate if the Shift, Ctrl, Alt or other modifier keys were pressed during the click.

Clicks in the footer cause a FooterClickEvent, which you can handle with a Table.FooterClickListener. Footers do not have any default click behavior, like the sorting in the header. Otherwise, handling clicks in the footer is equivalent to handling clicks in the header.

5.15.5. Generated Table Columns

You might want to have a column that has values calculated from other columns. Or you might want to format table columns in some way, for example if you have columns that display currencies. The ColumnGenerator interface allows defining custom generators for such columns.

You add new generated columns to a Table with addGeneratedColumn(). It takes the column identifier as its parameters. Usually you want to have a more user-friendly and possibly interna-

150

Generated Table Columns

User Interface Components

tionalized column header. You can set the header and a possible icon by calling addContainerProperty() before adding the generated column.

// Define table

columns.

 

table.addContainerProperty(

 

"date",

Date.class, null, "Date",

null, null);

table.addContainerProperty(

 

"quantity",

Double.class, null, "Quantity (l)", null, null);

table.addContainerProperty(

 

"price",

Double.class, null, "Price (e/l)",

null, null);

table.addContainerProperty(

 

"total",

Double.class, null, "Total (e)",

null, null);

// Define the generated columns and their generators. table.addGeneratedColumn("date",

new DateColumnGenerator()); table.addGeneratedColumn("quantity",

new ValueColumnGenerator("%.2f l")); table.addGeneratedColumn("price",

new PriceColumnGenerator()); table.addGeneratedColumn("total",

new ValueColumnGenerator("%.2f e"));

Notice that the addGeneratedColumn() always places the generated columns as the last column, even if you defined some other order previously. You will have to set the proper order with setVisibleColumns().

table.setVisibleColumns(new Object[] {"date", "quantity", "price", "total"});

The generators are objects that implement the Table.ColumnGenerator interface and its generateCell() method.The method gets the identity of the item and column as its parameters, in addition to the table object. It has to return a component object.

The following example defines a generator for formatting Double valued fields according to a format string (as in java.util.Formatter).

/** Formats the value in a column containing Double objects. */ class ValueColumnGenerator implements Table.ColumnGenerator {

String format; /* Format string for the Double values. */

/**

*Creates double value column formatter with the given

*format string.

*/

public ValueColumnGenerator(String format) { this.format = format;

}

/**

*Generates the cell containing the Double value.

*The column is irrelevant in this use case.

*/

public Component generateCell(Table source, Object itemId, Object columnId) {

// Get the object stored in the cell as a property Property prop =

source.getItem(itemId).getItemProperty(columnId); if (prop.getType().equals(Double.class)) {

Label label = new Label(String.format(format,

new Object[] { (Double) prop.getValue() }));

//Set styles for the column: one indicating that it's

//a value and a more specific one with the column

//name in it. This assumes that the column name

//is proper for CSS.

Generated Table Columns

151

User Interface Components

label.addStyleName("column-type-value"); label.addStyleName("column-" + (String) columnId); return label;

}

return null;

}

}

The generator is called for all the visible (or more accurately cached) items in a table. If the user scrolls the table to another position in the table, the columns of the new visible rows are generated dynamically. The columns in the visible (cached) rows are also generated always when an item has a value change. It is therefore usually safe to calculate the value of generated cells from the values of different rows (items).

When you set a table as editable, regular fields will change to editing fields. When the user changes the values in the fields, the generated columns will be updated automatically. Putting a table with generated columns in editable mode has a few quirks. The editable mode of Table does not affect generated columns. You have two alternatives: either you generate the editing fields in the generator or, in case of formatter generators, remove the generator in the editable mode. The example below uses the latter approach.

//Have a check box that allows the user

//to make the quantity and total columns editable. final CheckBox editable = new CheckBox(

"Edit the input values - calculated columns are regenerated");

editable.setImmediate(true); editable.addListener(new ClickListener() {

public void buttonClick(ClickEvent event) { table.setEditable(editable.booleanValue());

//The columns may not be generated when we want to

//have them editable.

if (editable.booleanValue()) { table.removeGeneratedColumn("quantity"); table.removeGeneratedColumn("total");

} else { // Not editable

// Show the formatted values. table.addGeneratedColumn("quantity",

new ValueColumnGenerator("%.2f l")); table.addGeneratedColumn("total",

new ValueColumnGenerator("%.2f e"));

}

//The visible columns are affected by removal

//and addition of generated columns so we have

//to redefine them.

table.setVisibleColumns(new Object[] {"date", "quantity", "price", "total", "consumption", "dailycost"});

}

});

You will also have to set the editing fields in immediate mode to have the update occur immediately when an edit field loses the focus. You can set the fields in immediate mode with the a custom TableFieldFactory, such as the one given below, that just extends the default implementation to set the mode:

public class ImmediateFieldFactory extends DefaultFieldFactory { public Field createField(Container container,

Object itemId, Object propertyId,

Component uiContext) {

// Let the DefaultFieldFactory create the fields...

Field field = super.createField(container, itemId,

152

Generated Table Columns

User Interface Components

propertyId, uiContext);

// ...and just set them as immediate. ((AbstractField)field).setImmediate(true);

return field;

}

}

...

table.setTableFieldFactory(new ImmediateFieldFactory());

If you generate the editing fields with the column generator, you avoid having to use such a field factory, but of course have to generate the fields for both normal and editable modes.

Figure 5.53, “Table with Generated Columns in Normal and Editable Mode” shows a table with columns calculated (blue) and simply formatted (black) with column generators.

Figure 5.53. Table with Generated Columns in Normal and Editable Mode

5.15.6. Formatting Table Columns

The displayed values of properties shown in a table are normally formatted using the toString() method of each property. Customizing the format of a column can be done in several ways:

Using ColumnGenerator to generate a second column that is formatted. The original column needs to be set invisible. See Section 5.15.5, “Generated Table Columns”.

Using a PropertyFormatter as a proxy between the table and the data property. This also normally requires using an mediate container in the table.

Overriding the default formatPropertyValue() in Table.

Formatting Table Columns

153

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]