Composite container = new Composite(parent, SWT.NONE);
container.setLayout(new GridLayout());
// create a new ConfigRegistry which will be needed for GlazedLists
// handling
final ConfigRegistry configRegistry = new ConfigRegistry();
// property names of the ExtendedPersonWithAddress class
String[] propertyNames = { "firstName", "lastName", "age", "money",
"married", "gender", "birthday" };
// mapping from property to label, needed for column header labels
Map<String, String> propertyToLabelMap = new HashMap<String, String>();
propertyToLabelMap.put("firstName", "Firstname");
propertyToLabelMap.put("lastName", "Lastname");
propertyToLabelMap.put("age", "Age");
propertyToLabelMap.put("money", "Money");
propertyToLabelMap.put("married", "Married");
propertyToLabelMap.put("gender", "Gender");
propertyToLabelMap.put("birthday", "Birthday");
final IColumnPropertyAccessor<ExtendedPersonWithAddress> columnPropertyAccessor = new ExtendedReflectiveColumnPropertyAccessor<ExtendedPersonWithAddress>(
propertyNames);
// to enable the group by summary feature, the GroupByDataLayer needs to
// know the ConfigRegistry
final BodyLayerStack<ExtendedPersonWithAddress> bodyLayerStack = new BodyLayerStack<ExtendedPersonWithAddress>(
PersonService.getExtendedPersonsWithAddress(10),
columnPropertyAccessor, configRegistry);
bodyLayerStack.getBodyDataLayer().setConfigLabelAccumulator(
new ColumnLabelAccumulator());
// build the column header layer
IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(
propertyNames, propertyToLabelMap);
DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(
columnHeaderDataProvider);
ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(
columnHeaderDataLayer, bodyLayerStack,
bodyLayerStack.getSelectionLayer());
// add sorting
SortHeaderLayer<ExtendedPersonWithAddress> sortHeaderLayer = new SortHeaderLayer<ExtendedPersonWithAddress>(
columnHeaderLayer,
new GlazedListsSortModel<ExtendedPersonWithAddress>(
bodyLayerStack.getSortedList(), columnPropertyAccessor,
configRegistry, columnHeaderDataLayer), false);
// connect sortModel to GroupByDataLayer to support sorting by group by
// summary values
bodyLayerStack.getBodyDataLayer().setSortModel(
sortHeaderLayer.getSortModel());
ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(
sortHeaderLayer, bodyLayerStack.getSelectionLayer(),
columnGroupModel);
columnGroupHeaderLayer.setCalculateHeight(true);
// add the filter row functionality
final FilterRowHeaderComposite<ExtendedPersonWithAddress> filterRowHeaderLayer = new FilterRowHeaderComposite<ExtendedPersonWithAddress>(
new DefaultGlazedListsFilterStrategy<ExtendedPersonWithAddress>(
bodyLayerStack.getFilterList(), columnPropertyAccessor,
configRegistry), columnGroupHeaderLayer,
columnHeaderDataLayer.getDataProvider(), configRegistry);
// Row header
// Adding the specialized DefaultSummaryRowHeaderDataProvider to
// indicate the summary row in the row header
IDataProvider rowHeaderDataProvider = new DefaultSummaryRowHeaderDataProvider(
bodyLayerStack.getBodyDataLayer().getDataProvider(), "\u2211");
final DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(
rowHeaderDataProvider);
// add a label to the row header summary row cell aswell, so it can be
// styled differently too
// in this case it will simply use the same styling as the summary row
// in the body
rowHeaderDataLayer.setConfigLabelAccumulator(new AbstractOverrider() {
@Override
public void accumulateConfigLabels(LabelStack configLabels,
int columnPosition, int rowPosition) {
if ((rowPosition + 1) == rowHeaderDataLayer.getRowCount()) {
configLabels.addLabel(ROW_HEADER_SUMMARY_ROW);
configLabels
.addLabel(SummaryRowLayer.DEFAULT_SUMMARY_ROW_CONFIG_LABEL);
}
}
});
ILayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer,
bodyLayerStack, bodyLayerStack.getSelectionLayer());
// build the corner layer
IDataProvider cornerDataProvider = new DefaultCornerDataProvider(
columnHeaderDataProvider, rowHeaderDataProvider);
DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
ILayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer,
filterRowHeaderLayer);
// build the grid layer
GridLayer gridLayer = new GridLayer(bodyLayerStack,
filterRowHeaderLayer, rowHeaderLayer, cornerLayer);
// set the group by header on top of the grid
CompositeLayer compositeGridLayer = new CompositeLayer(1, 2);
final GroupByHeaderLayer groupByHeaderLayer = new GroupByHeaderLayer(
bodyLayerStack.getGroupByModel(), gridLayer,
columnHeaderDataProvider);
compositeGridLayer.setChildLayer(GroupByHeaderLayer.GROUP_BY_REGION,
groupByHeaderLayer, 0, 0);
compositeGridLayer.setChildLayer("Grid", gridLayer, 0, 1);
// turn the auto configuration off as we want to add our header menu
// configuration
final NatTable natTable = new NatTable(container, compositeGridLayer,
false);
// as the autoconfiguration of the NatTable is turned off, we have to
// add the
// DefaultNatTableStyleConfiguration and the ConfigRegistry manually
natTable.setConfigRegistry(configRegistry);
natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
// add some additional styling
natTable.addConfiguration(new AbstractRegistryConfiguration() {
@Override
public void configureRegistry(IConfigRegistry configRegistry) {
configRegistry.registerConfigAttribute(
CellConfigAttributes.CELL_PAINTER,
new CheckBoxPainter(), DisplayMode.NORMAL,
ColumnLabelAccumulator.COLUMN_LABEL_PREFIX + 4);
configRegistry.registerConfigAttribute(
CellConfigAttributes.DISPLAY_CONVERTER,
new DefaultDoubleDisplayConverter(),
DisplayMode.NORMAL,
ColumnLabelAccumulator.COLUMN_LABEL_PREFIX + 3);
}
});
// add sorting configuration
natTable.addConfiguration(new SingleClickSortConfiguration());
sumMoneySummaryProvider = new SummationGroupBySummaryProvider<ExtendedPersonWithAddress>(
columnPropertyAccessor);
avgMoneySummaryProvider = new AverageMoneyGroupBySummaryProvider();
// add group by summary configuration
natTable.addConfiguration(new AbstractRegistryConfiguration() {
@Override
public void configureRegistry(IConfigRegistry configRegistry) {
configRegistry.registerConfigAttribute(
GroupByConfigAttributes.GROUP_BY_SUMMARY_PROVIDER,
sumMoneySummaryProvider, DisplayMode.NORMAL,
GroupByDataLayer.GROUP_BY_COLUMN_PREFIX + 3);
configRegistry.registerConfigAttribute(
GroupByConfigAttributes.GROUP_BY_SUMMARY_PROVIDER,
new AverageAgeGroupBySummaryProvider(),
DisplayMode.NORMAL,
GroupByDataLayer.GROUP_BY_COLUMN_PREFIX + 2);
configRegistry.registerConfigAttribute(
GroupByConfigAttributes.GROUP_BY_CHILD_COUNT_PATTERN,
"[{0}] - ({1})");
configRegistry.registerConfigAttribute(
GroupByConfigAttributes.GROUP_BY_HINT,
"Drag columns here");
Style hintStyle = new Style();
hintStyle.setAttributeValue(CellStyleAttributes.FONT, GUIHelper
.getFont(new FontData("Arial", 10, SWT.ITALIC)));
configRegistry.registerConfigAttribute(
GroupByConfigAttributes.GROUP_BY_HINT_STYLE, hintStyle);
// register a groupBy double display converter to avoid
// rendering rounding issues
configRegistry.registerConfigAttribute(
CellConfigAttributes.DISPLAY_CONVERTER,
new SummaryDisplayConverter(
new DefaultDoubleDisplayConverter()),
DisplayMode.NORMAL,
GroupByDataLayer.GROUP_BY_SUMMARY_COLUMN_PREFIX + 3);
configRegistry
.registerConfigAttribute(
SummaryRowConfigAttributes.SUMMARY_PROVIDER,
new SummationSummaryProvider(
bodyLayerStack.bodyDataProvider, false),
DisplayMode.NORMAL,
SummaryRowLayer.DEFAULT_SUMMARY_COLUMN_CONFIG_LABEL_PREFIX + 3);
configRegistry
.registerConfigAttribute(
SummaryRowConfigAttributes.SUMMARY_PROVIDER,
new AverageAgeSummaryProvider(
bodyLayerStack.bodyDataProvider),
DisplayMode.NORMAL,
SummaryRowLayer.DEFAULT_SUMMARY_COLUMN_CONFIG_LABEL_PREFIX + 2);
configRegistry
.registerConfigAttribute(
CellConfigAttributes.DISPLAY_CONVERTER,
new SummaryDisplayConverter(
new DefaultDoubleDisplayConverter()),
DisplayMode.NORMAL,
SummaryRowLayer.DEFAULT_SUMMARY_COLUMN_CONFIG_LABEL_PREFIX + 3);
// the main styling of the summary row cell in the row header is
// done via
// summary row default style, but we need to override the
// alignment
IStyle style = new Style();
style.setAttributeValue(
CellStyleAttributes.HORIZONTAL_ALIGNMENT,
HorizontalAlignmentEnum.CENTER);
configRegistry.registerConfigAttribute(
CellConfigAttributes.CELL_STYLE, style,
DisplayMode.NORMAL, ROW_HEADER_SUMMARY_ROW);
configRegistry.registerConfigAttribute(
CellConfigAttributes.CELL_STYLE, style,
DisplayMode.SELECT, ROW_HEADER_SUMMARY_ROW);
}
});
// add group by header configuration
natTable.addConfiguration(new GroupByHeaderMenuConfiguration(natTable,
groupByHeaderLayer));
natTable.addConfiguration(new AbstractHeaderMenuConfiguration(natTable) {
@Override
protected PopupMenuBuilder createColumnHeaderMenu(NatTable natTable) {
return super.createColumnHeaderMenu(natTable)
.withHideColumnMenuItem().withShowAllColumnsMenuItem()
.withColumnChooserMenuItem()
.withCreateColumnGroupsMenuItem()
.withUngroupColumnsMenuItem()
.withAutoResizeSelectedColumnsMenuItem()
.withColumnRenameDialog().withClearAllFilters()
.withStateManagerMenuItemProvider();
}
@Override
protected PopupMenuBuilder createCornerMenu(NatTable natTable) {
return super.createCornerMenu(natTable)
.withShowAllColumnsMenuItem()
.withStateManagerMenuItemProvider();
}
});
natTable.configure();
natTable.registerCommandHandler(new DisplayPersistenceDialogCommandHandler(
natTable));
DisplayColumnChooserCommandHandler columnChooserCommandHandler = new DisplayColumnChooserCommandHandler(
bodyLayerStack.getSelectionLayer(),
bodyLayerStack.getColumnHideShowLayer(), columnHeaderLayer,
columnHeaderDataLayer, null, null);
natTable.registerCommandHandler(columnChooserCommandHandler);
GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
Composite buttonPanel = new Composite(container, SWT.NONE);
buttonPanel.setLayout(new RowLayout());
GridDataFactory.fillDefaults().grab(true, false).applyTo(buttonPanel);
Button toggleHeaderButton = new Button(buttonPanel, SWT.PUSH);
toggleHeaderButton.setText("Toggle Group By Header");
toggleHeaderButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
groupByHeaderLayer.setVisible(!groupByHeaderLayer.isVisible());
}
});
Button toggleFilterButton = new Button(buttonPanel, SWT.PUSH);
toggleFilterButton.setText("Toggle Filter Row");
toggleFilterButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
filterRowHeaderLayer.setFilterRowVisible(!filterRowHeaderLayer
.isFilterRowVisible());
}
});
Button collapseAllButton = new Button(buttonPanel, SWT.PUSH);
collapseAllButton.setText("Collapse All");
collapseAllButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
natTable.doCommand(new TreeCollapseAllCommand());
}
});
Button expandAllButton = new Button(buttonPanel, SWT.PUSH);
expandAllButton.setText("Expand All");
expandAllButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
natTable.doCommand(new TreeExpandAllCommand());
}
});
Button toggleMoneySummaryButton = new Button(buttonPanel, SWT.PUSH);
toggleMoneySummaryButton
.setText("Toggle Money Group Summary (SUM/AVG)");
toggleMoneySummaryButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// clear the group by summary cache so the new summary
// calculation gets triggered
bodyLayerStack.getBodyDataLayer().clearCache();
useMoneySum = !useMoneySum;
if (useMoneySum) {
configRegistry.registerConfigAttribute(
GroupByConfigAttributes.GROUP_BY_SUMMARY_PROVIDER,
sumMoneySummaryProvider, DisplayMode.NORMAL,
GroupByDataLayer.GROUP_BY_COLUMN_PREFIX + 3);
} else {
configRegistry.registerConfigAttribute(
GroupByConfigAttributes.GROUP_BY_SUMMARY_PROVIDER,
avgMoneySummaryProvider, DisplayMode.NORMAL,
GroupByDataLayer.GROUP_BY_COLUMN_PREFIX + 3);
}
natTable.doCommand(new VisualRefreshCommand());