diff --git a/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF b/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF index be4d417d5..622d1db21 100644 --- a/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF +++ b/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF @@ -90,6 +90,7 @@ Export-Package: org.eclipse.nebula.widgets.nattable;version="2.6.0", org.eclipse.nebula.widgets.nattable.group.performance.event;version="2.6.0", org.eclipse.nebula.widgets.nattable.group.performance.gui;version="2.6.0", org.eclipse.nebula.widgets.nattable.group.performance.painter;version="2.6.0", + org.eclipse.nebula.widgets.nattable.groupby;version="2.6.0", org.eclipse.nebula.widgets.nattable.hideshow;version="2.6.0", org.eclipse.nebula.widgets.nattable.hideshow.command;version="2.6.0", org.eclipse.nebula.widgets.nattable.hideshow.event;version="2.6.0", diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/grid/GridRegion.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/grid/GridRegion.java index 0c4043b74..61d0469ac 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/grid/GridRegion.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/grid/GridRegion.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -33,4 +33,8 @@ private GridRegion() { public static final String BODY = "BODY"; //$NON-NLS-1$ public static final String DATAGRID = "DATAGRID"; //$NON-NLS-1$ public static final String FILTER_ROW = "FILTER_ROW"; //$NON-NLS-1$ + /** + * @since 2.6 + */ + public static final String GROUP_BY_REGION = "GROUP_BY_REGION"; //$NON-NLS-1$ } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/groupby/GroupByCommand.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/groupby/GroupByCommand.java new file mode 100644 index 000000000..d9199122c --- /dev/null +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/groupby/GroupByCommand.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2025 Dirk Fauth and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dirk Fauth - initial API and implementation + *******************************************************************************/ +package org.eclipse.nebula.widgets.nattable.groupby; + +import org.eclipse.nebula.widgets.nattable.command.ILayerCommand; +import org.eclipse.nebula.widgets.nattable.layer.ILayer; + +/** + * Command to trigger a groupBy action. + * + * @since 2.6 + */ +public class GroupByCommand implements ILayerCommand { + + public enum GroupByAction { + /** + * Action to add indexes an existing grouping. + */ + ADD, + /** + * Action to clear the existing grouping. + */ + CLEAR, + /** + * Action to remove indexes from an existing grouping. + */ + REMOVE, + /** + * Action to set indexes as new grouping which overrides the existing + * grouping. + */ + SET + }; + + private final GroupByAction action; + private final int[] indexes; + + /** + * Performs the specified groupBy action for the given indexes. + * + * @param action + * The groupBy action to perform + * + * @param indexes + * The indexes of the columns/rows that should be grouped. + */ + public GroupByCommand(GroupByAction action, int... indexes) { + this.action = action; + this.indexes = indexes; + } + + /** + * + * @return The groupBy action to perform. + */ + public GroupByAction getAction() { + return this.action; + } + + /** + * + * @return The indexes of the columns/rows that should be grouped. + */ + public int[] getIndexes() { + return this.indexes; + } + + @Override + public GroupByCommand cloneCommand() { + return this; + } + + @Override + public boolean convertToTargetLayer(ILayer targetLayer) { + return true; + } + +} diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_600_GlazedLists/_605_GroupBy/_6053_GroupBySummaryExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_600_GlazedLists/_605_GroupBy/_6053_GroupBySummaryExample.java index 73df492ca..70f86ed23 100644 --- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_600_GlazedLists/_605_GroupBy/_6053_GroupBySummaryExample.java +++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_600_GlazedLists/_605_GroupBy/_6053_GroupBySummaryExample.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2021 Dirk Fauth and others. + * Copyright (c) 2013, 2025 Dirk Fauth and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -52,6 +52,8 @@ 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.groupby.GroupByCommand; +import org.eclipse.nebula.widgets.nattable.groupby.GroupByCommand.GroupByAction; import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer; import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform; import org.eclipse.nebula.widgets.nattable.layer.CompositeLayer; @@ -350,7 +352,7 @@ public void widgetSelected(SelectionEvent e) { groupLastFirstButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - bodyLayerStack.groupByModel.setGroupByColumnIndexes(1, 0); + natTable.doCommand(new GroupByCommand(GroupByAction.SET, 1, 0)); } }); @@ -359,7 +361,7 @@ public void widgetSelected(SelectionEvent e) { groupFirstLastButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - bodyLayerStack.groupByModel.setGroupByColumnIndexes(0, 1); + natTable.doCommand(new GroupByCommand(GroupByAction.SET, 0, 1)); } }); @@ -368,7 +370,7 @@ public void widgetSelected(SelectionEvent e) { groupLastMarriedButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - bodyLayerStack.groupByModel.setGroupByColumnIndexes(1, 5); + natTable.doCommand(new GroupByCommand(GroupByAction.SET, 1, 5)); } }); @@ -377,7 +379,7 @@ public void widgetSelected(SelectionEvent e) { clearGroupByButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - bodyLayerStack.groupByModel.clearGroupByColumnIndexes(); + natTable.doCommand(new GroupByCommand(GroupByAction.CLEAR)); } }); diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupby/GroupByHeaderLayerTest.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupby/GroupByHeaderLayerTest.java new file mode 100644 index 000000000..40d436110 --- /dev/null +++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupby/GroupByHeaderLayerTest.java @@ -0,0 +1,300 @@ +/******************************************************************************* + * Copyright (c) 2025 Dirk Fauth and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dirk Fauth - initial API and implementation + *******************************************************************************/ +package org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupby; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry; +import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration; +import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor; +import org.eclipse.nebula.widgets.nattable.data.IDataProvider; +import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor; +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.PersonService; +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.fixture.NatTableFixture; +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.GroupByModel; +import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowDataProvider; +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.DefaultRowHeaderDataProvider; +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.groupby.GroupByCommand; +import org.eclipse.nebula.widgets.nattable.groupby.GroupByCommand.GroupByAction; +import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer; +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.cell.ColumnLabelAccumulator; +import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer; +import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer; +import org.eclipse.nebula.widgets.nattable.sort.ISortModel; +import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer; +import org.eclipse.nebula.widgets.nattable.sort.config.DefaultSortConfiguration; +import org.eclipse.nebula.widgets.nattable.tree.TreeLayer; +import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +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; + +public class GroupByHeaderLayerTest { + + private BodyLayerStack bodyLayer; + private NatTableFixture natTable; + + SortedList sortedList; + ISortModel sortModel; + + FilterList filterList; + FilterRowDataProvider filterRowDataProvider; + + static final String MY_LABEL = "myLabel"; + + @BeforeEach + public void setup() { + EventList eventList = GlazedLists.eventList(PersonService.getFixedPersons()); + + // create a new ConfigRegistry which will be needed for GlazedLists + // handling + ConfigRegistry configRegistry = new ConfigRegistry(); + + // property names of the Person class + String[] propertyNames = { "firstName", "lastName", "money", "gender", "married", "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("money", "Money"); + propertyToLabelMap.put("gender", "Gender"); + propertyToLabelMap.put("married", "Married"); + propertyToLabelMap.put("birthday", "Birthday"); + + final IColumnPropertyAccessor columnPropertyAccessor = + new ReflectiveColumnPropertyAccessor<>(propertyNames); + + // to enable the group by summary feature, the GroupByDataLayer needs to + // know the ConfigRegistry + this.bodyLayer = + new BodyLayerStack<>( + eventList, + columnPropertyAccessor, + configRegistry); + + this.bodyLayer.getBodyDataLayer().setConfigLabelAccumulator(new ColumnLabelAccumulator()); + + // build the column header layer + IDataProvider columnHeaderDataProvider = + new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap); + DataLayer columnHeaderDataLayer = + new DefaultColumnHeaderDataLayer(columnHeaderDataProvider); + ILayer columnHeaderLayer = + new ColumnHeaderLayer(columnHeaderDataLayer, this.bodyLayer, this.bodyLayer.getSelectionLayer()); + + // add sorting + this.sortModel = new GlazedListsSortModel<>( + this.bodyLayer.getSortedList(), + columnPropertyAccessor, + configRegistry, + columnHeaderDataLayer); + SortHeaderLayer sortHeaderLayer = new SortHeaderLayer<>( + columnHeaderLayer, + this.sortModel, + false); + + // connect sortModel to GroupByDataLayer to support sorting by group by + // summary values + this.bodyLayer.getBodyDataLayer().initializeTreeComparator( + sortHeaderLayer.getSortModel(), + this.bodyLayer.getTreeLayer(), + true); + + // build the row header layer + IDataProvider rowHeaderDataProvider = + new DefaultRowHeaderDataProvider(this.bodyLayer.getBodyDataProvider()); + DataLayer rowHeaderDataLayer = + new DefaultRowHeaderDataLayer(rowHeaderDataProvider); + ILayer rowHeaderLayer = + new RowHeaderLayer(rowHeaderDataLayer, this.bodyLayer, this.bodyLayer.getSelectionLayer()); + + // build the corner layer + IDataProvider cornerDataProvider = + new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider); + DataLayer cornerDataLayer = + new DataLayer(cornerDataProvider); + ILayer cornerLayer = + new CornerLayer(cornerDataLayer, rowHeaderLayer, sortHeaderLayer); + + // build the grid layer + GridLayer gridLayer = new GridLayer(this.bodyLayer, sortHeaderLayer, rowHeaderLayer, cornerLayer); + + // set the group by header on top of the grid + CompositeLayer compositeGridLayer = new CompositeLayer(1, 2); + final GroupByHeaderLayer groupByHeaderLayer = + new GroupByHeaderLayer(this.bodyLayer.getGroupByModel(), gridLayer, columnHeaderDataProvider); + compositeGridLayer.setChildLayer(GroupByHeaderLayer.GROUP_BY_REGION, groupByHeaderLayer, 0, 0); + compositeGridLayer.setChildLayer("Grid", gridLayer, 0, 1); + + // turn the auto configuration off as we want to add our header menu + // configuration + this.natTable = new NatTableFixture(compositeGridLayer, false); + this.natTable.setConfigRegistry(configRegistry); + this.natTable.addConfiguration(new DefaultNatTableStyleConfiguration()); + this.natTable.addConfiguration(new DefaultSortConfiguration()); + this.natTable.configure(); + } + + @Test + public void shouldUpdateGroupByModelViaGroupByCommand() { + this.natTable.doCommand(new GroupByCommand(GroupByAction.ADD, 1)); + assertEquals(Arrays.asList(1), this.bodyLayer.getGroupByModel().getGroupByColumnIndexes()); + + this.natTable.doCommand(new GroupByCommand(GroupByAction.ADD, 4, 0)); + assertEquals(Arrays.asList(1, 4, 0), this.bodyLayer.getGroupByModel().getGroupByColumnIndexes()); + + this.natTable.doCommand(new GroupByCommand(GroupByAction.REMOVE, 4)); + assertEquals(Arrays.asList(1, 0), this.bodyLayer.getGroupByModel().getGroupByColumnIndexes()); + + this.natTable.doCommand(new GroupByCommand(GroupByAction.SET, 0, 2)); + assertEquals(Arrays.asList(0, 2), this.bodyLayer.getGroupByModel().getGroupByColumnIndexes()); + + this.natTable.doCommand(new GroupByCommand(GroupByAction.CLEAR)); + assertTrue(this.bodyLayer.getGroupByModel().getGroupByColumnIndexes().isEmpty()); + } + + static 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 SelectionLayer selectionLayer; + + private final TreeLayer treeLayer; + + private final GroupByModel groupByModel = new GroupByModel(); + + private final 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); + this.glazedListsEventLayer.setTestMode(true); + + ColumnReorderLayer columnReorderLayer = + new ColumnReorderLayer(this.glazedListsEventLayer); + ColumnHideShowLayer columnHideShowLayer = + new ColumnHideShowLayer(columnReorderLayer); + this.selectionLayer = + new SelectionLayer(columnHideShowLayer); + + // 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())); + + setUnderlyingLayer(viewportLayer); + } + + public ILayer getGlazedListsEventLayer() { + return this.glazedListsEventLayer; + } + + 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; + } + } + +} diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/META-INF/MANIFEST.MF b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/META-INF/MANIFEST.MF index 37d27c21f..188c8bdaf 100644 --- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/META-INF/MANIFEST.MF +++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/META-INF/MANIFEST.MF @@ -45,6 +45,7 @@ Import-Package: ca.odell.glazedlists;version="[1.11.0,2.0.0)", org.eclipse.nebula.widgets.nattable.grid.layer;version="[2.6.0,3.0.0)", org.eclipse.nebula.widgets.nattable.group.performance;version="[2.6.0,3.0.0)", org.eclipse.nebula.widgets.nattable.group.performance.action;version="[2.6.0,3.0.0)", + org.eclipse.nebula.widgets.nattable.groupby;version="[2.6.0,3.0.0)", org.eclipse.nebula.widgets.nattable.hideshow;version="[2.6.0,3.0.0)", org.eclipse.nebula.widgets.nattable.hideshow.command;version="[2.6.0,3.0.0)", org.eclipse.nebula.widgets.nattable.hideshow.event;version="[2.6.0,3.0.0)", diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/GroupByHeaderLayer.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/GroupByHeaderLayer.java index b84f840b5..5655801b7 100644 --- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/GroupByHeaderLayer.java +++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/GroupByHeaderLayer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -15,7 +15,9 @@ import org.eclipse.nebula.widgets.nattable.data.IDataProvider; import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.command.GroupByColumnCommandHandler; +import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.command.GroupByCommandHandler; import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.command.UngroupByColumnCommandHandler; +import org.eclipse.nebula.widgets.nattable.grid.GridRegion; import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer; import org.eclipse.nebula.widgets.nattable.grid.layer.DimensionallyDependentLayer; import org.eclipse.nebula.widgets.nattable.layer.DataLayer; @@ -30,7 +32,7 @@ */ public class GroupByHeaderLayer extends DimensionallyDependentLayer { - public static final String GROUP_BY_REGION = "GROUP_BY_REGION"; //$NON-NLS-1$ + public static final String GROUP_BY_REGION = GridRegion.GROUP_BY_REGION; private final GroupByModel groupByModel; @@ -220,6 +222,7 @@ public int getColumnCount() { registerCommandHandler(new GroupByColumnCommandHandler(this)); registerCommandHandler(new UngroupByColumnCommandHandler(this)); + registerCommandHandler(new GroupByCommandHandler(this)); GroupByHeaderConfiguration configuration = null; if (groupByHeaderConfiguration != null) { @@ -270,5 +273,4 @@ public ILayerCell getCellByPosition(int columnPosition, int rowPosition) { public int getGroupByColumnIndexAtXY(int x, int y) { return this.groupByHeaderPainter.getGroupByColumnIndexAtXY(x, y); } - } diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/GroupByColumnCommandHandler.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/GroupByColumnCommandHandler.java index 8926e4731..f1a7f7d3f 100644 --- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/GroupByColumnCommandHandler.java +++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/GroupByColumnCommandHandler.java @@ -22,8 +22,7 @@ * The {@link ILayerCommandHandler} for handling * {@link GroupByColumnIndexCommand}s. */ -public class GroupByColumnCommandHandler extends - AbstractLayerCommandHandler { +public class GroupByColumnCommandHandler extends AbstractLayerCommandHandler { private final GroupByHeaderLayer groupByHeaderLayer; @@ -40,10 +39,8 @@ public GroupByColumnCommandHandler(GroupByHeaderLayer groupByHeaderLayer) { @Override protected boolean doCommand(GroupByColumnIndexCommand command) { int columnIndex = command.getGroupByColumnIndex(); - if (this.groupByHeaderLayer.getGroupByModel().addGroupByColumnIndex( - columnIndex)) { - this.groupByHeaderLayer.fireLayerEvent(new VisualRefreshEvent( - this.groupByHeaderLayer)); + if (this.groupByHeaderLayer.getGroupByModel().addGroupByColumnIndex(columnIndex)) { + this.groupByHeaderLayer.fireLayerEvent(new VisualRefreshEvent(this.groupByHeaderLayer)); } return true; } diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/GroupByCommandHandler.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/GroupByCommandHandler.java new file mode 100644 index 000000000..b1730d591 --- /dev/null +++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/GroupByCommandHandler.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2025 Dirk Fauth and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dirk Fauth - initial API and implementation + *******************************************************************************/ +package org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.command; + +import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler; +import org.eclipse.nebula.widgets.nattable.command.ILayerCommandHandler; +import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByHeaderLayer; +import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByModel; +import org.eclipse.nebula.widgets.nattable.groupby.GroupByCommand; +import org.eclipse.nebula.widgets.nattable.groupby.GroupByCommand.GroupByAction; +import org.eclipse.nebula.widgets.nattable.layer.event.VisualRefreshEvent; + +/** + * The {@link ILayerCommandHandler} for handling {@link GroupByCommand}s. + * + * @since 2.6 + */ +public class GroupByCommandHandler extends AbstractLayerCommandHandler { + + private final GroupByHeaderLayer groupByHeaderLayer; + + /** + * @param groupByHeaderLayer + * The {@link GroupByHeaderLayer} to which this command handler + * is registered to. Is needed to modify the {@link GroupByModel} + * and fire the update events. + */ + public GroupByCommandHandler(GroupByHeaderLayer groupByHeaderLayer) { + this.groupByHeaderLayer = groupByHeaderLayer; + } + + @Override + protected boolean doCommand(GroupByCommand command) { + GroupByAction action = command.getAction(); + int[] columnIndexes = command.getIndexes(); + boolean fireEvent = false; + switch (action) { + case ADD: + fireEvent = this.groupByHeaderLayer.getGroupByModel().addAllGroupByColumnIndexes(columnIndexes); + break; + case CLEAR: + this.groupByHeaderLayer.getGroupByModel().clearGroupByColumnIndexes(); + fireEvent = true; + break; + case REMOVE: + fireEvent = this.groupByHeaderLayer.getGroupByModel().removeAllGroupByColumnIndexes(columnIndexes); + break; + case SET: + this.groupByHeaderLayer.getGroupByModel().setGroupByColumnIndexes(columnIndexes); + fireEvent = true; + break; + } + + if (fireEvent) { + this.groupByHeaderLayer.fireLayerEvent(new VisualRefreshEvent(this.groupByHeaderLayer)); + } + + return true; + } + + @Override + public Class getCommandClass() { + return GroupByCommand.class; + } + +} diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/UngroupByColumnCommandHandler.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/UngroupByColumnCommandHandler.java index 727550266..6bf0dd37f 100644 --- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/UngroupByColumnCommandHandler.java +++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/command/UngroupByColumnCommandHandler.java @@ -22,8 +22,7 @@ * The {@link ILayerCommandHandler} for handling * {@link UngroupByColumnIndexCommand}s. */ -public class UngroupByColumnCommandHandler extends - AbstractLayerCommandHandler { +public class UngroupByColumnCommandHandler extends AbstractLayerCommandHandler { private final GroupByHeaderLayer groupByHeaderLayer; @@ -40,10 +39,8 @@ public UngroupByColumnCommandHandler(GroupByHeaderLayer groupByHeaderLayer) { @Override protected boolean doCommand(UngroupByColumnIndexCommand command) { int columnIndex = command.getGroupByColumnIndex(); - if (this.groupByHeaderLayer.getGroupByModel().removeGroupByColumnIndex( - columnIndex)) { - this.groupByHeaderLayer.fireLayerEvent(new VisualRefreshEvent( - this.groupByHeaderLayer)); + if (this.groupByHeaderLayer.getGroupByModel().removeGroupByColumnIndex(columnIndex)) { + this.groupByHeaderLayer.fireLayerEvent(new VisualRefreshEvent(this.groupByHeaderLayer)); } return true; }