Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
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 Go to next message
Naveen Sabapathy is currently offline Naveen SabapathyFriend
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 #1759370 is a reply to message #1759322] Mon, 10 April 2017 20:59 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
It is not explainable for me why loading a state should take several minutes. Typically this is done in few seconds, mostly less than a second. And your properties doesn't look special. I find your size configuration a bit strange, as most of the columns have a width of 40, but the default size is 100, which leads to setting explicit widths for each column. I would have changed the default width to 40 and only change those widths that are not 40.

Nevertheless that doesn't explain such a delay. But there is nothing special for debugging at that place. Step through the loadState() of the layers and IPersistable and see where you loose the time.
Re: Loading Nattable state takes a lot of time. [message #1759410 is a reply to message #1759370] Tue, 11 April 2017 04:53 Go to previous messageGo to next message
Naveen Sabapathy is currently offline Naveen SabapathyFriend
Messages: 46
Registered: July 2016
Member
Quote:
I would have changed the default width to 40 and only change those widths that are not 40.

The column width is a field its different for different users. And user have the facility to change the value.

I have put the break point for the LoadState, it takes a lot of time in notifyObservers() of org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByModel.loadState(String, Properties).
Re: Loading Nattable state takes a lot of time. [message #1759413 is a reply to message #1759410] Tue, 11 April 2017 05:07 Go to previous messageGo to next message
Naveen Sabapathy is currently offline Naveen SabapathyFriend
Messages: 46
Registered: July 2016
Member
And Groupby functionality is very slow. and in somecases the table is getting crashed. Is it problem with my configuration or its the general behaviour of groupby functionality?
Re: Loading Nattable state takes a lot of time. [message #1759414 is a reply to message #1759410] Tue, 11 April 2017 05:08 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
You have a grouping applied in the state? Try to disable the GlazedListsEventLayer before loading the state and enable it again afterwards.
Re: Loading Nattable state takes a lot of time. [message #1759415 is a reply to message #1759414] Tue, 11 April 2017 05:15 Go to previous messageGo to next message
Naveen Sabapathy is currently offline Naveen SabapathyFriend
Messages: 46
Registered: July 2016
Member
Quote:
You have a grouping applied in the state? Try to disable the GlazedListsEventLayer before loading the state and enable it again afterwards.


Its completely dynamic. It can be applied or not.
If the Groupby is applied or not applied. The load state takes time.
Re: Loading Nattable state takes a lot of time. [message #1759419 is a reply to message #1759415] Tue, 11 April 2017 06:29 Go to previous messageGo to next message
Naveen Sabapathy is currently offline Naveen SabapathyFriend
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 #1759443 is a reply to message #1759419] Tue, 11 April 2017 09:49 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
Sorry but I can not reproduce this behavior. Neither with the default example nor your modified example. And by the way the example you modified already implements the necessary feature to load and save. It also contains the header menu item to dynamically switch between view configurations.

But of course I don't know your TestTableStyleConfiguration and I am using the latest NatTable 1.5. Not sure about your setup.
Re: Loading Nattable state takes a lot of time. [message #1759880 is a reply to message #1759443] Wed, 19 April 2017 13:25 Go to previous messageGo to next message
Naveen Sabapathy is currently offline Naveen SabapathyFriend
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);
        }
    }

}


Re: Loading Nattable state takes a lot of time. [message #1759929 is a reply to message #1759880] Thu, 20 April 2017 05:54 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
Sorry but I don't have the time to inspect your code in detail to give you detailed information on what is going wrong. And I can't event start your example without issues. The filter comboboxes are all empty and trying to click on them fires exceptions. Probably because of the initial loading.

And as you don't use generics I see a lot of warnings, which makes it hard to read the code.

I tried the loading with the _813_SortableGroupByWithComboBoxFilterExample which contains groupBy, groupBy summaries and combobox filters. If I apply grouping and filters and then save via right-click on the corner and "Manage view configurations" I can switch between view configurations very fast. It becomes laggy if also sorting is applied to a column that contains a groupby summary. The reason is that the sorting takes the time. If the column has a groupby summary it needs to be calculated for all values in order to do the list ordering. Although this is done in a background thread via CalculatedValueCache, this will take time. The summary values need to be calculcated the first time, they are not persisted, as they are values, not state.

You could try to implement your own ICalculatedValueCache as IPersistable that stores the calculated values on persist and loads them back afterwards. That one needs to be set to the GroupByDataLayer. And feel free to contribute back if that is a suitable solution.

Re: Loading Nattable state takes a lot of time. [message #1760710 is a reply to message #1759929] Tue, 02 May 2017 10:06 Go to previous messageGo to next message
Naveen Sabapathy is currently offline Naveen SabapathyFriend
Messages: 46
Registered: July 2016
Member
And one more query related to storing nattable(with combobox filter) configuration into properties file. While saving the Nattable state through "Save State Manager", the Nattable persistance is working fine.
But When I'm saveState to properties file and loading the properties file is not updating the Combobox filter state properly. What modification need to be done to make this functionality working.

Also, I have observed some random selection issue with Combobox filter (Sometimes, when lase the values is unselected by combobox, then first value is getting selected).



Re: Loading Nattable state takes a lot of time. [message #1760713 is a reply to message #1760710] Tue, 02 May 2017 10:28 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
It is the same functionality. Could you probably have an encoding issue?
Re: Loading Nattable state takes a lot of time. [message #1760717 is a reply to message #1760713] Tue, 02 May 2017 11:08 Go to previous messageGo to next message
Naveen Sabapathy is currently offline Naveen SabapathyFriend
Messages: 46
Registered: July 2016
Member
Quote:
Also, I have observed some random selection issue with Combobox filter (Sometimes, when lase the values is unselected by combobox, then first value is getting selected).


This issue is observed, in all Nattable Combobox example. Randomly select/ Unselect the item. While unselecting the last selection using Check box selection option, We can get this behaviour.

Quote:
When I'm saveState to properties file and loading the properties file is not updating the Combobox filter state properly. What modification need to be done to make this functionality working.


For this issue, choose "_813_SortableGroupByWithComboBoxFilterExample" and add the persisting code Onstart, Onstop. Then this behaviour can be reproduced.
Re: Loading Nattable state takes a lot of time. [message #1760737 is a reply to message #1760717] Tue, 02 May 2017 13:37 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
Looks like a timing issue. On startup the filter is not correctly applied because the filter combo box content is not loaded yet.

Please create a ticket for this issue.
Re: Loading Nattable state takes a lot of time. [message #1760816 is a reply to message #1760737] Wed, 03 May 2017 09:39 Go to previous messageGo to next message
Naveen Sabapathy is currently offline Naveen SabapathyFriend
Messages: 46
Registered: July 2016
Member
Ok... Thanks... I'll create the ticket for that.
And is that the issue
Quote:
Also, I have observed some random selection issue with Combobox filter (Sometimes, when lase the values is unselected by combobox, then first value is getting selected).

is reproducable in your side.

Re: Loading Nattable state takes a lot of time. [message #1760823 is a reply to message #1760816] Wed, 03 May 2017 10:34 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
I don't understand what you explain in that sentence. What happens when? Is the strange effect only coming up when trying to load on startup? Then it is the same issue.
Re: Loading Nattable state takes a lot of time. [message #1760824 is a reply to message #1760823] Wed, 03 May 2017 11:00 Go to previous messageGo to next message
Naveen Sabapathy is currently offline Naveen SabapathyFriend
Messages: 46
Registered: July 2016
Member
Quote:
Is the strange effect only coming up when trying to load on startup?

No its a constant behaviour, when we use the checkbox to select the value.

Refer the video for the actual issue.
Re: Loading Nattable state takes a lot of time. [message #1760827 is a reply to message #1760824] Wed, 03 May 2017 11:30 Go to previous message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
That is another issue I haven't seen before. Please create another ticket for this issue.
Previous Topic:IColumnAccessor.setDataValue is called twice
Next Topic:Cell DisplayMode Changed Event
Goto Forum:
  


Current Time: Thu Sep 20 08:21:33 GMT 2018

Powered by FUDForum. Page generated in 0.14052 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top