Home » Eclipse Projects » NatTable » Loading Nattable state takes a lot of time.
Loading Nattable state takes a lot of time. [message #1759322] |
Mon, 10 April 2017 06:30 |
Naveen Sabapathy Messages: 46 Registered: July 2016 |
Member |
|
|
I have configured a Nattable, I'm storing the properties into database and loading it back into the Nattable.While loading the Nattable it takes a lot of time(approx. 20mins just for the loadstate). Also Table sort configuration has not retrived.
Are there any way to debug this delay process.
Below is the property file I'm using to load the Nattable.
current.Grid.BODY.FROZEN_ROW_REGION.rowHeight.sizes 0:21,1:21,
current.Grid.COLUMN_HEADER.FILTER_ROW.rowHeight.percentageSizing false
current.GROUP_BY_REGION.columnWidth.percentageSizing false
current.Grid.ROW_HEADER.rowHeight.resizableByDefault true
current.Grid.BODY.NONFROZEN_REGION.columnIndexOrder 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,
current.Grid.COLUMN_HEADER.columnHeader.renamedColumnHeaders 2:SD|
current.Grid.BODY.FROZEN_ROW_REGION.columnWidth.percentageSizing false
current.Grid.BODY.NONFROZEN_REGION.rowHeight.resizableByDefault true
current.Grid.BODY.FROZEN_REGION.rowHeight.resizableByDefault true
current.Grid.BODY.FROZEN_ROW_REGION.rowHeight.defaultSize 20
current.Grid.BODY.FROZEN_COLUMN_REGION.columnWidth.resizableByDefault true
current.Grid.BODY.FROZEN_REGION.columnWidth.defaultSize 100
current.Grid.ROW_HEADER.rowHeight.defaultSize 40
current.Grid.BODY.FROZEN_COLUMN_REGION.rowHeight.percentageSizing false
current.Grid.COLUMN_HEADER.columnHeader.SortHeaderLayer.sortingState 24:ASC:0|
current.Grid.BODY.FROZEN_ROW_REGION.rowHeight.percentageSizing false
current.Grid.BODY.FROZEN_COLUMN_REGION.columnIndexOrder 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,
current.Grid.COLUMN_HEADER.columnHeader.columnWidth.resizableByDefault true
current.Grid.CORNER.rowHeight.defaultSize 20
current.Grid.BODY.NONFROZEN_REGION.columnWidth.defaultSize 100
current.Grid.BODY.FROZEN_REGION.columnWidth.sizes 0:20,1:40,2:60,3:50,4:50,5:50,6:70,7:20,8:20,9:294,10:120,11:40,12:55,13:40,14:40,15:40,16:40,17:40,18:40,19:40,20:40,21:40,22:40,23:40,24:253,25:40,26:40,27:40,28:40,29:40,30:40,31:40,32:40,33:40,34:40,35:40,36:40,37:40,38:40,39:40,40:40,41:40,42:40,43:40,44:40,45:40,46:40,47:40,48:40,49:40,50:40,51:40,52:40,53:40,54:40,55:40,56:40,57:40,58:40,59:40,60:40,61:40,62:40,63:40,64:40,65:40,66:40,67:40,68:40,69:40,70:40,71:40,72:40,73:40,74:40,75:40,76:40,77:40,78:40,79:40,80:40,81:40,82:40,83:40,84:40,85:40,86:40,
current.Grid.CORNER.columnWidth.percentageSizing false
current.Grid.COLUMN_HEADER.FILTER_ROW.columnWidth.defaultSize 100
current.Grid.COLUMN_HEADER.columnHeader.columnWidth.defaultSize 100
current.Grid.CORNER.columnWidth.defaultSize 100
current.Grid.BODY.FROZEN_COLUMN_REGION.rowHeight.resizableByDefault true
current.Grid.BODY.FROZEN_REGION.columnIndexOrder 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,
current.Grid.COLUMN_HEADER.columnHeader.rowHeight.defaultSize 20
current.Grid.COLUMN_HEADER.columnHeader.columnWidth.percentageSizing false
current.Grid.BODY.NONFROZEN_REGION.rowHeight.defaultSize 20
current.Grid.BODY.FROZEN_REGION.rowHeight.percentageSizing false
current.Grid.BODY.freezeTopLeftPosition -1,-1
current.GROUP_BY_REGION.rowHeight.resizableByDefault true
current.Grid.COLUMN_HEADER.FILTER_ROW.columnWidth.percentageSizing false
current.Grid.BODY.NONFROZEN_REGION.rowHeight.percentageSizing false
current.Grid.BODY.FROZEN_ROW_REGION.rowHeight.resizableByDefault true
current.GROUP_BY_REGION.rowHeight.defaultSize 20
current.Grid.BODY.FROZEN_ROW_REGION.columnWidth.sizes 0:20,1:40,2:60,3:50,4:50,5:50,6:70,7:20,8:20,9:294,10:120,11:40,12:55,13:40,14:40,15:40,16:40,17:40,18:40,19:40,20:40,21:40,22:40,23:40,24:253,25:40,26:40,27:40,28:40,29:40,30:40,31:40,32:40,33:40,34:40,35:40,36:40,37:40,38:40,39:40,40:40,41:40,42:40,43:40,44:40,45:40,46:40,47:40,48:40,49:40,50:40,51:40,52:40,53:40,54:40,55:40,56:40,57:40,58:40,59:40,60:40,61:40,62:40,63:40,64:40,65:40,66:40,67:40,68:40,69:40,70:40,71:40,72:40,73:40,74:40,75:40,76:40,77:40,78:40,79:40,80:40,81:40,82:40,83:40,84:40,85:40,86:40,
current.GROUP_BY_REGION.rowHeight.sizes 0:30,
current.Grid.BODY.FROZEN_COLUMN_REGION.rowHeight.sizes 0:21,1:21,
current.GROUP_BY_REGION.rowHeight.percentageSizing false
current.Grid.ROW_HEADER.columnWidth.percentageSizing false
current.Grid.BODY.FROZEN_COLUMN_REGION.rowHeight.defaultSize 20
current.Grid.BODY.NONFROZEN_REGION.columnWidth.resizableByDefault true
current.Grid.BODY.FROZEN_REGION.rowHeight.defaultSize 20
current.Grid.BODY.NONFROZEN_REGION.columnWidth.sizes 0:20,1:40,2:60,3:50,4:50,5:50,6:70,7:20,8:20,9:294,10:120,11:40,12:55,13:40,14:40,15:40,16:40,17:40,18:40,19:40,20:40,21:40,22:40,23:40,24:253,25:40,26:40,27:40,28:40,29:40,30:40,31:40,32:40,33:40,34:40,35:40,36:40,37:40,38:40,39:40,40:40,41:40,42:40,43:40,44:40,45:40,46:40,47:40,48:40,49:40,50:40,51:40,52:40,53:40,54:40,55:40,56:40,57:40,58:40,59:40,60:40,61:40,62:40,63:40,64:40,65:40,66:40,67:40,68:40,69:40,70:40,71:40,72:40,73:40,74:40,75:40,76:40,77:40,78:40,79:40,80:40,81:40,82:40,83:40,84:40,85:40,86:40,
current.Grid.CORNER.rowHeight.percentageSizing false
current.Grid.BODY.FROZEN_REGION.columnWidth.percentageSizing false
current.Grid.BODY.FROZEN_REGION.rowHeight.sizes 0:21,1:21,
current.GROUP_BY_REGION.columnWidth.resizableByDefault true
current.GROUP_BY_REGION.columnWidth.defaultSize 100
current.Grid.BODY.NONFROZEN_REGION.columnWidth.percentageSizing false
current.Grid.ROW_HEADER.rowHeight.percentageSizing false
current.Grid.COLUMN_HEADER.columnHeader.rowHeight.percentageSizing false
current.Grid.BODY.NONFROZEN_REGION.rowHeight.sizes 0:21,1:21,
current.Grid.BODY.FROZEN_ROW_REGION.columnIndexOrder 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,
current.Grid.COLUMN_HEADER.columnHeader.columnGroups
current.Grid.BODY.FROZEN_ROW_REGION.columnWidth.defaultSize 100
current.Grid.BODY.FROZEN_ROW_REGION.columnWidth.resizableByDefault true
current.Grid.BODY.FROZEN_REGION.columnWidth.resizableByDefault true
current.Grid.CORNER.rowHeight.resizableByDefault true
current.Grid.BODY.freezeBottomRightPosition -1,-1
current.Grid.COLUMN_HEADER.FILTER_ROW.rowHeight.resizableByDefault true
current.Grid.COLUMN_HEADER.FILTER_ROW.columnWidth.resizableByDefault true
current.Grid.BODY.FROZEN_COLUMN_REGION.columnWidth.sizes 0:20,1:40,2:60,3:50,4:50,5:50,6:70,7:20,8:20,9:294,10:120,11:40,12:55,13:40,14:40,15:40,16:40,17:40,18:40,19:40,20:40,21:40,22:40,23:40,24:253,25:40,26:40,27:40,28:40,29:40,30:40,31:40,32:40,33:40,34:40,35:40,36:40,37:40,38:40,39:40,40:40,41:40,42:40,43:40,44:40,45:40,46:40,47:40,48:40,49:40,50:40,51:40,52:40,53:40,54:40,55:40,56:40,57:40,58:40,59:40,60:40,61:40,62:40,63:40,64:40,65:40,66:40,67:40,68:40,69:40,70:40,71:40,72:40,73:40,74:40,75:40,76:40,77:40,78:40,79:40,80:40,81:40,82:40,83:40,84:40,85:40,86:40,
current.Grid.ROW_HEADER.columnWidth.resizableByDefault true
current.Grid.COLUMN_HEADER.columnHeader.rowHeight.resizableByDefault true
current.Grid.BODY.FROZEN_COLUMN_REGION.columnWidth.defaultSize 100
current.GROUP_BY_REGION.groupByColumnIndexes
current.Grid.COLUMN_HEADER.FILTER_ROW.rowHeight.defaultSize 20
current.Grid.CORNER.columnWidth.resizableByDefault true
current.Grid.BODY.FROZEN_COLUMN_REGION.columnWidth.percentageSizing false
current.Grid.ROW_HEADER.columnWidth.defaultSize 40
|
|
| | | | | |
Re: Loading Nattable state takes a lot of time. [message #1759419 is a reply to message #1759415] |
Tue, 11 April 2017 06:29 |
Naveen Sabapathy Messages: 46 Registered: July 2016 |
Member |
|
|
I have modified the Nattable Example. The groupby feature for 10,000 row Table takes about 3 mins for first level and Second level takes more than 5mins.
package org.eclipse.nebula.widgets.nattable.examples._400_Configuration;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.columnChooser.command.DisplayColumnChooserCommandHandler;
import org.eclipse.nebula.widgets.nattable.config.AbstractLayerConfiguration;
import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
import org.eclipse.nebula.widgets.nattable.config.EditableRule;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.IEditableRule;
import org.eclipse.nebula.widgets.nattable.data.ExtendedReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider;
import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultDoubleDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.validate.DefaultDataValidator;
import org.eclipse.nebula.widgets.nattable.dataset.person.Address;
import org.eclipse.nebula.widgets.nattable.dataset.person.ExtendedPersonWithAddress;
import org.eclipse.nebula.widgets.nattable.dataset.person.Person;
import org.eclipse.nebula.widgets.nattable.dataset.person.Person.Gender;
import org.eclipse.nebula.widgets.nattable.dataset.person.PersonService;
import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
import org.eclipse.nebula.widgets.nattable.edit.command.EditCellCommandHandler;
import org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommand;
import org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommandHandler;
import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditBindings;
import org.eclipse.nebula.widgets.nattable.edit.editor.TextCellEditor;
import org.eclipse.nebula.widgets.nattable.edit.event.InlineCellEditEventHandler;
import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample;
import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEventLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsSortModel;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.filterrow.DefaultGlazedListsFilterStrategy;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByConfigAttributes;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByConfigLabelModifier;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByDataLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByHeaderLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByHeaderMenuConfiguration;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByModel;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.ModernGroupByThemeExtension;
import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowDataLayer;
import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowHeaderComposite;
import org.eclipse.nebula.widgets.nattable.filterrow.TextMatchingMode;
import org.eclipse.nebula.widgets.nattable.filterrow.config.FilterRowConfigAttributes;
import org.eclipse.nebula.widgets.nattable.freeze.CompositeFreezeLayer;
import org.eclipse.nebula.widgets.nattable.freeze.FreezeLayer;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultSummaryRowHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupExpandCollapseLayer;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupHeaderLayer;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupReorderLayer;
import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayer;
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.CompositeLayer;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
import org.eclipse.nebula.widgets.nattable.layer.cell.AbstractOverrider;
import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnLabelAccumulator;
import org.eclipse.nebula.widgets.nattable.painter.NatTableBorderOverlayPainter;
import org.eclipse.nebula.widgets.nattable.painter.cell.CheckBoxPainter;
import org.eclipse.nebula.widgets.nattable.persistence.command.DisplayPersistenceDialogCommandHandler;
import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.selection.preserve.PreserveSelectionModel;
import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer;
import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;
import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
import org.eclipse.nebula.widgets.nattable.style.HorizontalAlignmentEnum;
import org.eclipse.nebula.widgets.nattable.style.IStyle;
import org.eclipse.nebula.widgets.nattable.style.Style;
import org.eclipse.nebula.widgets.nattable.style.theme.ModernNatTableThemeConfiguration;
import org.eclipse.nebula.widgets.nattable.style.theme.ThemeConfiguration;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummaryDisplayConverter;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummaryRowConfigAttributes;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummaryRowLayer;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummationSummaryProvider;
import org.eclipse.nebula.widgets.nattable.tree.TreeLayer;
import org.eclipse.nebula.widgets.nattable.tree.command.TreeCollapseAllCommand;
import org.eclipse.nebula.widgets.nattable.tree.command.TreeExpandAllCommand;
import org.eclipse.nebula.widgets.nattable.ui.menu.AbstractHeaderMenuConfiguration;
import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;
import org.eclipse.nebula.widgets.nattable.util.GUIHelper;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.TransformedList;
/**
* Simple example showing how to add the group by feature to the layer
* composition of a grid in conjunction with showing summary values of
* groupings.
*/
public class _810_SortableGroupByFilterColumnGroupAndFreezeExample extends AbstractNatExample {
private static final String ROW_HEADER_SUMMARY_ROW = "rowHeaderSummaryRowLabel";
private ColumnGroupModel columnGroupModel = new ColumnGroupModel();
private CompositeLayer compositeGridLayer;
public static void main(String[] args) throws Exception {
StandaloneNatExampleRunner.run(new _810_SortableGroupByFilterColumnGroupAndFreezeExample());
}
@Override
public String getDescription() {
return "This example shows the usage of the group by feature in conjunction with summary values of the groupings.";
}
@Override
public Control createExampleControl(Composite parent) {
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
final String[] propertyNames = { "firstName", "lastName", "age", "money",
"married", "gender", "birthday" };
// mapping from property to label, needed for column header labels
Map propertyToLabelMap = new HashMap();
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 columnPropertyAccessor =
new ExtendedReflectiveColumnPropertyAccessor(propertyNames);
// to enable the group by summary feature, the GroupByDataLayer needs to
// know the ConfigRegistry
final BodyLayerStack bodyLayerStack =
new BodyLayerStack(
PersonService.getExtendedPersonsWithAddress(10000),
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 sortHeaderLayer = new SortHeaderLayer(
columnHeaderLayer,
new GlazedListsSortModel(
bodyLayerStack.getSortedList(),
columnPropertyAccessor,
configRegistry,
columnHeaderDataLayer),
false);
// connect sortModel to GroupByDataLayer to support sorting by group by
// summary values
bodyLayerStack.getBodyDataLayer().initializeTreeComparator(
sortHeaderLayer.getSortModel(),
bodyLayerStack.getTreeLayer(),
true);
ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(
sortHeaderLayer,
bodyLayerStack.getSelectionLayer(),
this.columnGroupModel);
columnGroupHeaderLayer.setCalculateHeight(true);
// add the filter row functionality
final FilterRowHeaderComposite filterRowHeaderLayer =
new FilterRowHeaderComposite(
new DefaultGlazedListsFilterStrategy(
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, false);
// set the group by header on top of the grid
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);
compositeGridLayer.addConfiguration(new AbstractLayerConfiguration<AbstractLayer>() {
@Override
public void configureRegistry(IConfigRegistry configRegistry) {
configRegistry.registerConfigAttribute(
EditConfigAttributes.CELL_EDITABLE_RULE,
IEditableRule.ALWAYS_EDITABLE);
configRegistry.registerConfigAttribute(
EditConfigAttributes.CELL_EDITOR,
new TextCellEditor());
configRegistry.registerConfigAttribute(
EditConfigAttributes.DATA_VALIDATOR,
new DefaultDataValidator());
configRegistry.registerConfigAttribute(
EditConfigAttributes.OPEN_ADJACENT_EDITOR, Boolean.TRUE);
}
@Override
public void configureTypedLayer(AbstractLayer layer) {
layer.registerCommandHandler(new EditCellCommandHandler());
layer.registerEventHandler(new InlineCellEditEventHandler(layer));
}
});
compositeGridLayer.addConfiguration(new DefaultEditBindings());
// 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);
// 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);
configRegistry.registerConfigAttribute(
EditConfigAttributes.CELL_EDITABLE_RULE,
EditableRule.ALWAYS_EDITABLE);
/**
* This is added to include multiple word search operation for the free text filter.
* @param configRegistry - config registry to update registry values.
* @author Naveen.
*/
configRegistry.registerConfigAttribute(
FilterRowConfigAttributes.TEXT_DELIMITER, "&");
//Naveen 30-10-2016
// Regular expression applied for all the columns.
for (int i = 0; i < propertyNames.length; i++) {
configRegistry.registerConfigAttribute(
FilterRowConfigAttributes.TEXT_MATCHING_MODE,
TextMatchingMode.REGULAR_EXPRESSION,
DisplayMode.NORMAL,
FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX
+ i);
}
}
});
// add sorting configuration
natTable.addConfiguration(new SingleClickSortConfiguration());
// add group by summary configuration
natTable.addConfiguration(new AbstractRegistryConfiguration() {
@Override
public void configureRegistry(IConfigRegistry configRegistry) {
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);
configRegistry.registerConfigAttribute(
SummaryRowConfigAttributes.SUMMARY_PROVIDER,
new SummationSummaryProvider(bodyLayerStack.bodyDataProvider, false),
DisplayMode.NORMAL,
SummaryRowLayer.DEFAULT_SUMMARY_COLUMN_CONFIG_LABEL_PREFIX + 3);
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.addConfiguration(new TestTableStyleConfiguration(configRegistry));
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());
}
});
// this button adds data to the grid
// try to group by last name, sort by last name desc and then add
// dynamic data for verification
Button addDynamicDataButton = new Button(buttonPanel, SWT.PUSH);
addDynamicDataButton.setText("Add Data");
addDynamicDataButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Address address = new Address();
address.setStreet("Some Street");
address.setHousenumber(42);
address.setPostalCode(12345);
address.setCity("In the clouds");
Person person = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
ExtendedPersonWithAddress entry = new ExtendedPersonWithAddress(person, address,
"0000", "The little Ralphy", PersonService.createRandomMoneyAmount(),
new ArrayList(), new ArrayList());
bodyLayerStack.getEventList().add(entry);
person = new Person(42, "Clancy", "Wiggum", Gender.MALE, true, new Date());
entry = new ExtendedPersonWithAddress(person, address,
"XXXL", "It is Chief Wiggum", PersonService.createRandomMoneyAmount(),
new ArrayList(), new ArrayList());
bodyLayerStack.getEventList().add(entry);
person = new Person(42, "Sarah", "Wiggum", Gender.FEMALE, true, new Date());
entry = new ExtendedPersonWithAddress(person, address,
"mommy", "Little Ralphy's mother", PersonService.createRandomMoneyAmount(),
new ArrayList(), new ArrayList());
bodyLayerStack.getEventList().add(entry);
}
});
// add modern styling
ThemeConfiguration theme = new ModernNatTableThemeConfiguration();
theme.addThemeExtension(new ModernGroupByThemeExtension());
natTable.setTheme(theme);
// add a border on every side of the table
natTable.addOverlayPainter(new NatTableBorderOverlayPainter());
this.natTable = natTable;
return container;
}
/**
* Always encapsulate the body layer stack in an AbstractLayerTransform to
* ensure that the index transformations are performed in later commands.
*
* @param
*/
class BodyLayerStack extends AbstractLayerTransform {
private final EventList eventList;
private final SortedList sortedList;
private final FilterList filterList;
private final IDataProvider bodyDataProvider;
private final GroupByDataLayer bodyDataLayer;
private final ColumnHideShowLayer columnHideShowLayer;
private final SelectionLayer selectionLayer;
private final TreeLayer treeLayer;
private final GroupByModel groupByModel = new GroupByModel();
public BodyLayerStack(List values,
IColumnPropertyAccessor columnPropertyAccessor,
ConfigRegistry configRegistry) {
// wrapping of the list to show into GlazedLists
// see http://publicobject.com/glazedlists/ for further information
this.eventList = GlazedLists.eventList(values);
TransformedList rowObjectsGlazedList = GlazedLists.threadSafeList(this.eventList);
// use the SortedList constructor with 'null' for the Comparator
// because the Comparator
// will be set by configuration
this.sortedList = new SortedList(rowObjectsGlazedList, null);
// wrap the SortedList with the FilterList
this.filterList = new FilterList(this.sortedList);
// Use the GroupByDataLayer instead of the default DataLayer
this.bodyDataLayer = new GroupByDataLayer(
getGroupByModel(),
this.filterList,
columnPropertyAccessor,
configRegistry);
// get the IDataProvider that was created by the GroupByDataLayer
this.bodyDataProvider = this.bodyDataLayer.getDataProvider();
// layer for event handling of GlazedLists and PropertyChanges
GlazedListsEventLayer glazedListsEventLayer =
new GlazedListsEventLayer(this.bodyDataLayer, this.filterList);
SummaryRowLayer summaryRowLayer =
new SummaryRowLayer(glazedListsEventLayer, configRegistry, false);
ColumnReorderLayer columnReorderLayer =
new ColumnReorderLayer(summaryRowLayer);
ColumnGroupReorderLayer columnGroupReorderLayer =
new ColumnGroupReorderLayer(
columnReorderLayer,
_810_SortableGroupByFilterColumnGroupAndFreezeExample.this.columnGroupModel);
this.columnHideShowLayer =
new ColumnHideShowLayer(columnGroupReorderLayer);
ColumnGroupExpandCollapseLayer columnGroupExpandCollapseLayer =
new ColumnGroupExpandCollapseLayer(
this.columnHideShowLayer,
_810_SortableGroupByFilterColumnGroupAndFreezeExample.this.columnGroupModel);
this.selectionLayer = new SelectionLayer(columnGroupExpandCollapseLayer);
// add a tree layer to visualise the grouping
this.treeLayer = new TreeLayer(this.selectionLayer, this.bodyDataLayer.getTreeRowModel());
ViewportLayer viewportLayer = new ViewportLayer(this.treeLayer);
// this will avoid tree specific rendering regarding alignment and
// indentation in case no grouping is active
viewportLayer.setConfigLabelAccumulator(new GroupByConfigLabelModifier(getGroupByModel()));
FreezeLayer freezeLayer = new FreezeLayer(viewportLayer);
CompositeFreezeLayer compositeFreezeLayer =
new CompositeFreezeLayer(freezeLayer, viewportLayer, this.selectionLayer);
setUnderlyingLayer(compositeFreezeLayer);
// we register a custom UpdateDataCommandHandler that ensures to
// update the tree structure
this.bodyDataLayer.unregisterCommandHandler(UpdateDataCommand.class);
PreserveSelectionModel selectionModel = new PreserveSelectionModel(selectionLayer, (IRowDataProvider) bodyDataProvider, getRowIdAccessor());
selectionLayer.setSelectionModel(selectionModel);
this.bodyDataLayer.registerCommandHandler(new UpdateDataCommandHandler(this.bodyDataLayer) {
@SuppressWarnings("unchecked")
@Override
protected boolean doCommand(UpdateDataCommand command) {
if (super.doCommand(command)) {
ExtendedPersonWithAddress o = (ExtendedPersonWithAddress) ((IRowDataProvider) BodyLayerStack.this.bodyDataProvider).getRowObject(command.getRowPosition());
int rowIndex = filterList.indexOf(o);
if (rowIndex >= 0) {
filterList.set(rowIndex, o);
}
return true;
}
return false;
}
});
}
public ColumnHideShowLayer getColumnHideShowLayer() {
return this.columnHideShowLayer;
}
public TreeLayer getTreeLayer() {
return this.treeLayer;
}
public SelectionLayer getSelectionLayer() {
return this.selectionLayer;
}
public EventList getEventList() {
return this.eventList;
}
public SortedList getSortedList() {
return this.sortedList;
}
public FilterList getFilterList() {
return this.filterList;
}
public IDataProvider getBodyDataProvider() {
return this.bodyDataProvider;
}
public GroupByDataLayer getBodyDataLayer() {
return this.bodyDataLayer;
}
public GroupByModel getGroupByModel() {
return this.groupByModel;
}
}
public static final String PROPERTIES_FILE = "myState.properties";
public NatTable natTable;
@Override
public void onStart() {
Properties properties = new Properties();
try {
System.out.println("Loading NatTable state from " + PROPERTIES_FILE);
properties.load(new FileInputStream(new File(PROPERTIES_FILE)));
this.natTable.loadState("", properties);
} catch (FileNotFoundException e) {
// No file found, oh well, move along
System.out.println(PROPERTIES_FILE + " not found, skipping load");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public IRowIdAccessor getRowIdAccessor() {
return new IRowIdAccessor() {
@Override
public Serializable getRowId(Object rowObject) {
if(rowObject instanceof ExtendedPersonWithAddress)
return ((ExtendedPersonWithAddress)rowObject).getId();
return null;
}
};
}
@Override
public void onStop() {
Properties properties = new Properties();
this.natTable.saveState("", properties);
try {
System.out.println("Saving NatTable state to " + PROPERTIES_FILE);
properties.store(new FileOutputStream(new File(PROPERTIES_FILE)), "NatTable state");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
|
|
| |
Re: Loading Nattable state takes a lot of time. [message #1759880 is a reply to message #1759443] |
Wed, 19 April 2017 13:25 |
Naveen Sabapathy Messages: 46 Registered: July 2016 |
Member |
|
|
Sorry for the wrong information. The behaviour is reproduceable with combobox filter, Not with normal filter.
package org.eclipse.nebula.widgets.nattable.examples._800_Integration;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.columnChooser.command.DisplayColumnChooserCommandHandler;
import org.eclipse.nebula.widgets.nattable.config.AbstractLayerConfiguration;
import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.EditableRule;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.IEditableRule;
import org.eclipse.nebula.widgets.nattable.data.ExtendedReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider;
import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultDoubleDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.validate.DefaultDataValidator;
import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
import org.eclipse.nebula.widgets.nattable.edit.command.EditCellCommandHandler;
import org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommand;
import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditBindings;
import org.eclipse.nebula.widgets.nattable.edit.editor.TextCellEditor;
import org.eclipse.nebula.widgets.nattable.edit.event.InlineCellEditEventHandler;
import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample;
import org.eclipse.nebula.widgets.nattable.examples.data.person.ExtendedPersonWithAddress;
import org.eclipse.nebula.widgets.nattable.examples.data.person.PersonService;
import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEventLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsSortModel;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.filterrow.ComboBoxFilterRowHeaderComposite;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.filterrow.DefaultGlazedListsFilterStrategy;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByConfigAttributes;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByConfigLabelModifier;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByDataLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByHeaderLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByHeaderMenuConfiguration;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByModel;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.ModernGroupByThemeExtension;
import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowDataLayer;
import org.eclipse.nebula.widgets.nattable.filterrow.TextMatchingMode;
import org.eclipse.nebula.widgets.nattable.filterrow.config.FilterRowConfigAttributes;
import org.eclipse.nebula.widgets.nattable.freeze.CompositeFreezeLayer;
import org.eclipse.nebula.widgets.nattable.freeze.FreezeLayer;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultSummaryRowHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupExpandCollapseLayer;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupHeaderLayer;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupReorderLayer;
import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayer;
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.CompositeLayer;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
import org.eclipse.nebula.widgets.nattable.layer.cell.AbstractOverrider;
import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnLabelAccumulator;
import org.eclipse.nebula.widgets.nattable.painter.NatTableBorderOverlayPainter;
import org.eclipse.nebula.widgets.nattable.painter.cell.CheckBoxPainter;
import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.selection.preserve.PreserveSelectionModel;
import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer;
import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;
import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
import org.eclipse.nebula.widgets.nattable.style.HorizontalAlignmentEnum;
import org.eclipse.nebula.widgets.nattable.style.IStyle;
import org.eclipse.nebula.widgets.nattable.style.Style;
import org.eclipse.nebula.widgets.nattable.style.theme.ModernNatTableThemeConfiguration;
import org.eclipse.nebula.widgets.nattable.style.theme.ThemeConfiguration;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummaryDisplayConverter;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummaryRowConfigAttributes;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummaryRowLayer;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummationSummaryProvider;
import org.eclipse.nebula.widgets.nattable.tree.TreeLayer;
import org.eclipse.nebula.widgets.nattable.tree.command.TreeCollapseAllCommand;
import org.eclipse.nebula.widgets.nattable.tree.command.TreeExpandAllCommand;
import org.eclipse.nebula.widgets.nattable.ui.menu.AbstractHeaderMenuConfiguration;
import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;
import org.eclipse.nebula.widgets.nattable.util.GUIHelper;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.TransformedList;
/**
* Simple example showing how to add the group by feature to the layer
* composition of a grid in conjunction with showing summary values of
* groupings.
*/
public class NaveenTest extends AbstractNatExample {
private static final String ROW_HEADER_SUMMARY_ROW = "rowHeaderSummaryRowLabel";
private ColumnGroupModel columnGroupModel = new ColumnGroupModel();
private CompositeLayer compositeGridLayer;
private DefaultGlazedListsFilterStrategy filerSteatergy;
private ComboBoxFilterRowHeaderComposite filterRowHeaderLayer;
public static void main(String[] args) throws Exception {
StandaloneNatExampleRunner.run(new NaveenTest());
}
@Override
public String getDescription() {
return "This example shows the usage of the group by feature in conjunction with summary values of the groupings.";
}
@Override
public Control createExampleControl(Composite parent) {
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
final String[] propertyNames = { "firstName", "lastName", "age", "money",
"married", "gender", "birthday" };
// mapping from property to label, needed for column header labels
Map propertyToLabelMap = new HashMap();
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 columnPropertyAccessor = new ExtendedReflectiveColumnPropertyAccessor(propertyNames);
// to enable the group by summary feature, the GroupByDataLayer needs to
// know the ConfigRegistry
final BodyLayerStack bodyLayerStack = new BodyLayerStack(PersonService.getExtendedPersonsWithAddress(10000), 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 sortHeaderLayer = new SortHeaderLayer(columnHeaderLayer, new GlazedListsSortModel(bodyLayerStack.getSortedList(), columnPropertyAccessor, configRegistry, columnHeaderDataLayer), false);
// connect sortModel to GroupByDataLayer to support sorting by group by
// summary values
bodyLayerStack.getBodyDataLayer().initializeTreeComparator(sortHeaderLayer.getSortModel(), bodyLayerStack.getTreeLayer(), true);
ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(sortHeaderLayer, bodyLayerStack.getSelectionLayer(), this.columnGroupModel);
columnGroupHeaderLayer.setCalculateHeight(true);
this.filerSteatergy = new DefaultGlazedListsFilterStrategy(bodyLayerStack.getFilterList(), columnPropertyAccessor, configRegistry);
this.filterRowHeaderLayer = new ComboBoxFilterRowHeaderComposite(bodyLayerStack.getFilterList(), bodyLayerStack.getGlazedListsEventLayer(), bodyLayerStack
.getSortedList(), columnPropertyAccessor, columnGroupHeaderLayer, columnHeaderDataProvider, configRegistry);
// final IComboBoxDataProvider comboBoxDataProvider =
// this.filterRowHeaderLayer
// .getComboBoxDataProvider();
//
// final V4BPCFilterRowComboBoxCellEditor filterEditor = new
// V4BPCFilterRowComboBoxCellEditor(comboBoxDataProvider, 5);
// filterEditor.setShowDropdownFilter(true);
// this.filterRowHeaderLayer
// .addConfiguration(new ComboBoxFilterRowConfiguration() {
// {
// this.cellEditor = filterEditor;
// this.filterIconPainter = new
// ComboBoxFilterIconPainter(comboBoxDataProvider, GUIHelper
// .getImage("filter"), null);
// }
// });
// filterRowHeaderLayer =
// new FilterRowHeaderComposite(
// new DefaultGlazedListsFilterStrategy(
// 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, this.filterRowHeaderLayer);
// build the grid layer
GridLayer gridLayer = new GridLayer(bodyLayerStack, this.filterRowHeaderLayer, rowHeaderLayer, cornerLayer, false);
// set the group by header on top of the grid
this.compositeGridLayer = new CompositeLayer(1, 2);
final GroupByHeaderLayer groupByHeaderLayer = new GroupByHeaderLayer(bodyLayerStack.getGroupByModel(), gridLayer, columnHeaderDataProvider);
this.compositeGridLayer.setChildLayer(GroupByHeaderLayer.GROUP_BY_REGION, groupByHeaderLayer, 0, 0);
this.compositeGridLayer.setChildLayer("Grid", gridLayer, 0, 1);
this.compositeGridLayer.addConfiguration(new AbstractLayerConfiguration<AbstractLayer>() {
@Override
public void configureRegistry(IConfigRegistry configRegistry) {
configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITABLE_RULE, IEditableRule.ALWAYS_EDITABLE);
configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITOR, new TextCellEditor());
configRegistry.registerConfigAttribute(EditConfigAttributes.DATA_VALIDATOR, new DefaultDataValidator());
configRegistry.registerConfigAttribute(EditConfigAttributes.OPEN_ADJACENT_EDITOR, Boolean.TRUE);
}
@Override
public void configureTypedLayer(AbstractLayer layer) {
layer.registerCommandHandler(new EditCellCommandHandler());
layer.registerEventHandler(new InlineCellEditEventHandler(layer));
}
});
this.compositeGridLayer.addConfiguration(new DefaultEditBindings());
// turn the auto configuration off as we want to add our header menu
// configuration
final NatTable natTable = new NatTable(container, this.compositeGridLayer, false);
// as the autoconfiguration of the NatTable is turned off, we have to
// add the DefaultNatTableStyleConfiguration and the ConfigRegistry
// manually
natTable.setConfigRegistry(configRegistry);
// 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);
configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITABLE_RULE, EditableRule.ALWAYS_EDITABLE);
/**
* This is added to include multiple word search operation for
* the free text filter.
*
* @param configRegistry
* - config registry to update registry values.
* @author Naveen.
*/
configRegistry.registerConfigAttribute(FilterRowConfigAttributes.TEXT_DELIMITER, "&");
// Naveen 30-10-2016
// Regular expression applied for all the columns.
for (int i = 0; i < propertyNames.length; i++) {
configRegistry.registerConfigAttribute(FilterRowConfigAttributes.TEXT_MATCHING_MODE, TextMatchingMode.REGULAR_EXPRESSION, DisplayMode.NORMAL, FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX
+ i);
}
}
});
// add sorting configuration
natTable.addConfiguration(new SingleClickSortConfiguration());
// add group by summary configuration
natTable.addConfiguration(new AbstractRegistryConfiguration() {
@Override
public void configureRegistry(IConfigRegistry configRegistry) {
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);
configRegistry
.registerConfigAttribute(SummaryRowConfigAttributes.SUMMARY_PROVIDER, new SummationSummaryProvider(bodyLayerStack.bodyDataProvider, false), DisplayMode.NORMAL, SummaryRowLayer.DEFAULT_SUMMARY_COLUMN_CONFIG_LABEL_PREFIX
+ 3);
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) {
NaveenTest.this.filterRowHeaderLayer.setFilterRowVisible(!NaveenTest.this.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());
}
});
// add modern styling
ThemeConfiguration theme = new ModernNatTableThemeConfiguration();
theme.addThemeExtension(new ModernGroupByThemeExtension());
natTable.setTheme(theme);
// add a border on every side of the table
natTable.addOverlayPainter(new NatTableBorderOverlayPainter());
this.natTable = natTable;
return container;
}
/**
* Always encapsulate the body layer stack in an AbstractLayerTransform to
* ensure that the index transformations are performed in later commands.
*
* @param
*/
class BodyLayerStack extends AbstractLayerTransform {
private final EventList eventList;
private final SortedList sortedList;
private final FilterList filterList;
private final IDataProvider bodyDataProvider;
private final GroupByDataLayer bodyDataLayer;
private final ColumnHideShowLayer columnHideShowLayer;
private final SelectionLayer selectionLayer;
private final TreeLayer treeLayer;
private final GroupByModel groupByModel = new GroupByModel();
private GlazedListsEventLayer glazedListsEventLayer;
public BodyLayerStack(List values,
IColumnPropertyAccessor columnPropertyAccessor,
ConfigRegistry configRegistry) {
// wrapping of the list to show into GlazedLists
// see http://publicobject.com/glazedlists/ for further information
this.eventList = GlazedLists.eventList(values);
TransformedList rowObjectsGlazedList = GlazedLists.threadSafeList(this.eventList);
// use the SortedList constructor with 'null' for the Comparator
// because the Comparator
// will be set by configuration
this.sortedList = new SortedList(rowObjectsGlazedList, null);
// wrap the SortedList with the FilterList
this.filterList = new FilterList(this.sortedList);
// Use the GroupByDataLayer instead of the default DataLayer
this.bodyDataLayer = new GroupByDataLayer(getGroupByModel(), this.filterList, columnPropertyAccessor, configRegistry);
// get the IDataProvider that was created by the GroupByDataLayer
this.bodyDataProvider = this.bodyDataLayer.getDataProvider();
// layer for event handling of GlazedLists and PropertyChanges
this.glazedListsEventLayer = new GlazedListsEventLayer(this.bodyDataLayer, this.filterList);
ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(this.glazedListsEventLayer);
ColumnGroupReorderLayer columnGroupReorderLayer = new ColumnGroupReorderLayer(columnReorderLayer, NaveenTest.this.columnGroupModel);
this.columnHideShowLayer = new ColumnHideShowLayer(columnGroupReorderLayer);
ColumnGroupExpandCollapseLayer columnGroupExpandCollapseLayer = new ColumnGroupExpandCollapseLayer(this.columnHideShowLayer, NaveenTest.this.columnGroupModel);
this.selectionLayer = new SelectionLayer(columnGroupExpandCollapseLayer);
// add a tree layer to visualise the grouping
this.treeLayer = new TreeLayer(this.selectionLayer, this.bodyDataLayer.getTreeRowModel());
ViewportLayer viewportLayer = new ViewportLayer(this.treeLayer);
// this will avoid tree specific rendering regarding alignment and
// indentation in case no grouping is active
viewportLayer.setConfigLabelAccumulator(new GroupByConfigLabelModifier(getGroupByModel()));
FreezeLayer freezeLayer = new FreezeLayer(viewportLayer);
CompositeFreezeLayer compositeFreezeLayer = new CompositeFreezeLayer(freezeLayer, viewportLayer, this.selectionLayer);
setUnderlyingLayer(compositeFreezeLayer);
// we register a custom UpdateDataCommandHandler that ensures to
// update the tree structure
this.bodyDataLayer.unregisterCommandHandler(UpdateDataCommand.class);
PreserveSelectionModel selectionModel = new PreserveSelectionModel(this.selectionLayer, (IRowDataProvider) this.bodyDataProvider, getRowIdAccessor());
this.selectionLayer.setSelectionModel(selectionModel);
// this.bodyDataLayer.registerCommandHandler(new
// UpdateDataCommandHandler(this.bodyDataLayer) {
// @SuppressWarnings("unchecked")
// @Override
// protected boolean doCommand(UpdateDataCommand command) {
// if (super.doCommand(command)) {
// ExtendedPersonWithAddress o = (ExtendedPersonWithAddress)
// ((IRowDataProvider)
// BodyLayerStack.this.bodyDataProvider).getRowObject(command.getRowPosition());
// int rowIndex = BodyLayerStack.this.filterList.indexOf(o);
// if (rowIndex >= 0) {
// BodyLayerStack.this.filterList.set(rowIndex, o);
// }
// return true;
// }
// return false;
// }
// });
}
public GlazedListsEventLayer getGlazedListsEventLayer() {
return this.glazedListsEventLayer;
}
public ColumnHideShowLayer getColumnHideShowLayer() {
return this.columnHideShowLayer;
}
public TreeLayer getTreeLayer() {
return this.treeLayer;
}
public SelectionLayer getSelectionLayer() {
return this.selectionLayer;
}
public EventList getEventList() {
return this.eventList;
}
public SortedList getSortedList() {
return this.sortedList;
}
public FilterList getFilterList() {
return this.filterList;
}
public IDataProvider getBodyDataProvider() {
return this.bodyDataProvider;
}
public GroupByDataLayer getBodyDataLayer() {
return this.bodyDataLayer;
}
public GroupByModel getGroupByModel() {
return this.groupByModel;
}
}
public static final String PROPERTIES_FILE = "myState.properties";
public NatTable natTable;
@Override
public void onStart() {
Properties properties = new Properties();
try {
System.out.println("Loading NatTable state from " + PROPERTIES_FILE);
properties.load(new FileInputStream(new File(PROPERTIES_FILE)));
this.natTable.loadState("", properties);
} catch (FileNotFoundException e) {
// No file found, oh well, move along
System.out.println(PROPERTIES_FILE + " not found, skipping load");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public IRowIdAccessor getRowIdAccessor() {
return new IRowIdAccessor() {
@Override
public Serializable getRowId(Object rowObject) {
if (rowObject instanceof ExtendedPersonWithAddress)
return ((ExtendedPersonWithAddress) rowObject).getId();
return null;
}
};
}
@Override
public void onStop() {
Properties properties = new Properties();
this.natTable.saveState("", properties);
try {
System.out.println("Saving NatTable state to " + PROPERTIES_FILE);
properties.store(new FileOutputStream(new File(PROPERTIES_FILE)), "NatTable state");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
|
|
| | | | | | | | | |
Goto Forum:
Current Time: Tue Sep 24 08:51:51 GMT 2024
Powered by FUDForum. Page generated in 0.07532 seconds
|