Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDirk Fauth2023-01-11 10:36:52 +0000
committerDirk Fauth2023-01-11 10:36:52 +0000
commitd442cdfbd33a79fe1dfd55ab427cd34768a65614 (patch)
treef4926875970827f1d324c4b10cdcfa48a6cc9178
parenta5ba5c8859378753672b370fc18f75c495d4f08b (diff)
downloadorg.eclipse.nebula.widgets.nattable-d442cdfbd33a79fe1dfd55ab427cd34768a65614.tar.gz
org.eclipse.nebula.widgets.nattable-d442cdfbd33a79fe1dfd55ab427cd34768a65614.tar.xz
org.eclipse.nebula.widgets.nattable-d442cdfbd33a79fe1dfd55ab427cd34768a65614.zip
Bug 581321 - [GroupBy] list order changed after grouping a filtered list
Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com> Change-Id: I549d26ad661f64aa8fdedca372ad373a516a804e
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowDataProvider.java13
-rw-r--r--org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_808_SortableGroupByWithFilterExample.java5
-rw-r--r--org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_810_SortableGroupByFilterColumnGroupAndFreezeExample.java5
-rw-r--r--org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_813_SortableGroupByWithComboBoxFilterExample.java5
-rw-r--r--org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_814_EditableSortableGroupByWithFilterExample.java5
-rw-r--r--org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_815_SortableGroupByFilterPerformanceColumnGroupAndFreezeExample.java5
-rw-r--r--org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupby/GroupByDataLayerTest.java71
-rw-r--r--org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/GroupByDataLayer.java42
8 files changed, 142 insertions, 9 deletions
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowDataProvider.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowDataProvider.java
index ee9cb59b..eea4bf30 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowDataProvider.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowDataProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2022 Original authors and others.
+ * Copyright (c) 2012, 2023 Original authors and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
@@ -336,4 +336,15 @@ public class FilterRowDataProvider<T> implements IDataProvider, IPersistable {
this.columnHeaderLayer.fireLayerEvent(new FilterAppliedEvent(this.columnHeaderLayer));
}
+ /**
+ *
+ * @return The {@link IFilterStrategy} to which the set filter value should
+ * be applied.
+ *
+ * @since 2.1
+ */
+ public IFilterStrategy<T> getFilterStrategy() {
+ return this.filterStrategy;
+ }
+
}
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_808_SortableGroupByWithFilterExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_808_SortableGroupByWithFilterExample.java
index 008758a9..bd2080ae 100644
--- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_808_SortableGroupByWithFilterExample.java
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_808_SortableGroupByWithFilterExample.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2021 Dirk Fauth and others.
+ * Copyright (c) 2013, 2023 Dirk Fauth and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
@@ -189,6 +189,9 @@ public class _808_SortableGroupByWithFilterExample extends AbstractNatExample {
columnHeaderDataLayer.getDataProvider(),
configRegistry);
+ bodyLayerStack.getBodyDataLayer().enableFilterSupport(
+ filterRowHeaderLayer.getFilterRowDataLayer().getFilterRowDataProvider());
+
// build the row header layer
IDataProvider rowHeaderDataProvider =
new DefaultRowHeaderDataProvider(bodyLayerStack.getBodyDataProvider());
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_810_SortableGroupByFilterColumnGroupAndFreezeExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_810_SortableGroupByFilterColumnGroupAndFreezeExample.java
index b4f1ba21..f087af9a 100644
--- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_810_SortableGroupByFilterColumnGroupAndFreezeExample.java
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_810_SortableGroupByFilterColumnGroupAndFreezeExample.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2021 Dirk Fauth and others.
+ * Copyright (c) 2013, 2023 Dirk Fauth and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
@@ -230,6 +230,9 @@ public class _810_SortableGroupByFilterColumnGroupAndFreezeExample extends Abstr
columnHeaderDataLayer.getDataProvider(),
configRegistry);
+ bodyLayerStack.getBodyDataLayer().enableFilterSupport(
+ filterRowHeaderLayer.getFilterRowDataLayer().getFilterRowDataProvider());
+
// Row header
// Adding the specialized DefaultSummaryRowHeaderDataProvider to
// indicate the summary row in the row header
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_813_SortableGroupByWithComboBoxFilterExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_813_SortableGroupByWithComboBoxFilterExample.java
index 706fb1dc..845712cf 100644
--- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_813_SortableGroupByWithComboBoxFilterExample.java
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_813_SortableGroupByWithComboBoxFilterExample.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2021 Dirk Fauth and others.
+ * Copyright (c) 2016, 2023 Dirk Fauth and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
@@ -227,6 +227,9 @@ public class _813_SortableGroupByWithComboBoxFilterExample extends AbstractNatEx
columnHeaderDataProvider,
configRegistry);
+ bodyLayerStack.getBodyDataLayer().enableFilterSupport(
+ filterRowHeaderLayer.getFilterRowDataLayer().getFilterRowDataProvider());
+
// build the row header layer
IDataProvider rowHeaderDataProvider =
new DefaultRowHeaderDataProvider(bodyLayerStack.getBodyDataProvider());
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_814_EditableSortableGroupByWithFilterExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_814_EditableSortableGroupByWithFilterExample.java
index 471e1609..0a33f3e3 100644
--- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_814_EditableSortableGroupByWithFilterExample.java
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_814_EditableSortableGroupByWithFilterExample.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2021 Dirk Fauth and others.
+ * Copyright (c) 2013, 2023 Dirk Fauth and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
@@ -262,6 +262,9 @@ public class _814_EditableSortableGroupByWithFilterExample extends AbstractNatEx
columnHeaderDataLayer.getDataProvider(),
configRegistry);
+ bodyLayerStack.getBodyDataLayer().enableFilterSupport(
+ filterRowHeaderLayer.getFilterRowDataLayer().getFilterRowDataProvider());
+
// build the row header layer
IDataProvider rowHeaderDataProvider =
new DefaultRowHeaderDataProvider(bodyLayerStack.getBodyDataProvider());
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_815_SortableGroupByFilterPerformanceColumnGroupAndFreezeExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_815_SortableGroupByFilterPerformanceColumnGroupAndFreezeExample.java
index a88f27d4..f4c74702 100644
--- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_815_SortableGroupByFilterPerformanceColumnGroupAndFreezeExample.java
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_815_SortableGroupByFilterPerformanceColumnGroupAndFreezeExample.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2019, 2021 Dirk Fauth and others.
+ * Copyright (c) 2019, 2023 Dirk Fauth and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
@@ -225,6 +225,9 @@ public class _815_SortableGroupByFilterPerformanceColumnGroupAndFreezeExample ex
columnHeaderDataLayer.getDataProvider(),
configRegistry);
+ bodyLayerStack.getBodyDataLayer().enableFilterSupport(
+ filterRowHeaderLayer.getFilterRowDataLayer().getFilterRowDataProvider());
+
// Row header
// Adding the specialized DefaultSummaryRowHeaderDataProvider to
// indicate the summary row in the row header
diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupby/GroupByDataLayerTest.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupby/GroupByDataLayerTest.java
index e615a46c..ced5ef10 100644
--- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupby/GroupByDataLayerTest.java
+++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupby/GroupByDataLayerTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2022 Dirk Fauth and others.
+ * Copyright (c) 2014, 2023 Dirk Fauth and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
@@ -26,15 +26,20 @@ import org.eclipse.nebula.widgets.nattable.config.DefaultComparator;
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.data.convert.DefaultDisplayConverter;
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.GlazedListsSortModel;
+import org.eclipse.nebula.widgets.nattable.extension.glazedlists.filterrow.DefaultGlazedListsFilterStrategy;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByComparator;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByConfigAttributes;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByDataLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByModel;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.GroupByObject;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.summary.SummationGroupBySummaryProvider;
+import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowDataProvider;
+import org.eclipse.nebula.widgets.nattable.filterrow.TextMatchingMode;
+import org.eclipse.nebula.widgets.nattable.filterrow.config.FilterRowConfigAttributes;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
@@ -50,6 +55,7 @@ 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.event.ListEvent;
@@ -67,6 +73,9 @@ public class GroupByDataLayerTest {
SortedList<Person> sortedList;
ISortModel sortModel;
+ FilterList<Person> filterList;
+ FilterRowDataProvider<Person> filterRowDataProvider;
+
static final String MY_LABEL = "myLabel";
// property names of the Person class
@@ -77,10 +86,11 @@ public class GroupByDataLayerTest {
this.groupByModel = new GroupByModel();
EventList<Person> eventList = GlazedLists.eventList(PersonService.getFixedPersons());
this.sortedList = new SortedList<>(eventList, null);
+ this.filterList = new FilterList<>(this.sortedList);
this.columnPropertyAccessor = new ReflectiveColumnPropertyAccessor<>(this.propertyNames);
- this.dataLayer = new GroupByDataLayer<>(this.groupByModel, this.sortedList, this.columnPropertyAccessor, this.configRegistry);
+ this.dataLayer = new GroupByDataLayer<>(this.groupByModel, this.filterList, this.columnPropertyAccessor, this.configRegistry);
this.dataLayer.setConfigLabelAccumulator(new ColumnLabelAccumulator());
}
@@ -147,6 +157,31 @@ public class GroupByDataLayerTest {
DefaultComparator.getInstance());
}
+ void addFilterCapability() {
+ IDataProvider columnHeaderDataProvider =
+ new DefaultColumnHeaderDataProvider(this.propertyNames);
+ DataLayer columnHeaderDataLayer =
+ new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);
+
+ this.filterRowDataProvider = new FilterRowDataProvider<>(
+ new DefaultGlazedListsFilterStrategy<>(
+ this.filterList,
+ this.columnPropertyAccessor,
+ this.configRegistry),
+ columnHeaderDataLayer,
+ columnHeaderDataProvider,
+ this.configRegistry);
+
+ this.configRegistry.registerConfigAttribute(
+ FilterRowConfigAttributes.FILTER_DISPLAY_CONVERTER,
+ new DefaultDisplayConverter());
+ this.configRegistry.registerConfigAttribute(
+ FilterRowConfigAttributes.TEXT_MATCHING_MODE,
+ TextMatchingMode.CONTAINS);
+
+ this.dataLayer.enableFilterSupport(this.filterRowDataProvider);
+ }
+
@Test
public void testOneLevelGrouping() {
assertEquals(18, this.dataLayer.getRowCount());
@@ -1071,4 +1106,36 @@ public class GroupByDataLayerTest {
assertEquals(28, this.dataLayer.getRowCount());
}
+ @Test
+ public void shouldKeepInitialOrderOnFilteredGrouping() {
+ addFilterCapability();
+
+ assertEquals(18, this.dataLayer.getRowCount());
+ assertEquals("Homer", this.dataLayer.getDataValue(0, 0));
+
+ // apply a filter
+ this.filterRowDataProvider.setDataValue(0, 0, "Homer");
+ assertEquals(3, this.dataLayer.getRowCount());
+
+ // group by last name
+ this.groupByModel.addGroupByColumnIndex(1);
+
+ assertEquals(4, this.dataLayer.getRowCount());
+ Object o = this.dataLayer.getTreeList().get(0);
+ assertTrue(o instanceof GroupByObject, "Object is not a GroupByObject");
+ assertEquals("Simpson", ((GroupByObject) o).getValue());
+
+ // ungroup lastname
+ this.groupByModel.removeGroupByColumnIndex(1);
+ assertEquals(3, this.dataLayer.getRowCount());
+
+ // remove the filter
+ this.filterRowDataProvider.setDataValue(0, 0, null);
+ assertEquals(18, this.dataLayer.getRowCount());
+
+ // Homer should be still at the first position
+ // without setting the FilterRowDataProvider to the GroupByDataLayer,
+ // this will fail
+ assertEquals("Homer", this.dataLayer.getDataValue(0, 0));
+ }
}
diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/GroupByDataLayer.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/GroupByDataLayer.java
index c565ca43..017f5178 100644
--- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/GroupByDataLayer.java
+++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/groupBy/GroupByDataLayer.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -39,6 +40,7 @@ import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy.summary.IGroupBySummaryProvider;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.tree.GlazedListTreeData;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.tree.GlazedListTreeRowModel;
+import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowDataProvider;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;
import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
@@ -155,6 +157,12 @@ public class GroupByDataLayer<T> extends DataLayer implements Observer {
private Matcher<Object> groupByMatcher = item -> item instanceof GroupByObject;
/**
+ * The {@link FilterRowDataProvider} that is used in the composition. Needed
+ * to be able to re-apply possible filter states on tree updates.
+ */
+ private FilterRowDataProvider<T> filterRowDataProvider;
+
+ /**
* Create a new {@link GroupByDataLayer} with the given configuration that:
* <ul>
* <li>uses the default <code>GroupByExpansionModel</code> which shows all
@@ -539,6 +547,17 @@ public class GroupByDataLayer<T> extends DataLayer implements Observer {
}
/**
+ * @param provider
+ * The {@link FilterRowDataProvider} that is used in the
+ * composition. Needed to be able to re-apply possible filter
+ * states on tree updates.
+ * @since 2.1
+ */
+ public void enableFilterSupport(FilterRowDataProvider<T> provider) {
+ this.filterRowDataProvider = provider;
+ }
+
+ /**
*
* @param comparator
* The {@link IGroupByComparator} that is necessary to create the
@@ -613,7 +632,7 @@ public class GroupByDataLayer<T> extends DataLayer implements Observer {
// if we know the sort model, we need to clear the sort model to avoid
// strange side effects while updating the tree structure (e.g. not
// applied sorting although showing the sort indicator)
- // for better user experience we remember the sort state and reapply it
+ // for better user experience we remember the sort state and re-apply it
// after the tree update
List<Integer> sortedIndexes = Collections.emptyList();
List<SortDirectionEnum> sortDirections = new ArrayList<>();
@@ -625,8 +644,29 @@ public class GroupByDataLayer<T> extends DataLayer implements Observer {
this.treeFormat.getSortModel().clear();
}
+ // if we know the filter row data provider, we need to remove the filter
+ // to avoid strange side effects while updating the tree structure (e.g.
+ // previously filtered items are not back at the original position but
+ // will be moved to the end of list after the filter is removed)
+ // for better user experience we remember the filter state and re-apply
+ // it after the tree update
+ Map<Integer, Object> filterCopy = Collections.emptyMap();
+ if (this.filterRowDataProvider != null) {
+ Map<Integer, Object> original = this.filterRowDataProvider.getFilterIndexToObjectMap();
+ filterCopy = new HashMap<>(original);
+ original.clear();
+ this.filterRowDataProvider.getFilterStrategy().applyFilter(original);
+ }
+
updateTree();
+ // re-apply the filter after the tree update
+ if (this.filterRowDataProvider != null) {
+ Map<Integer, Object> original = this.filterRowDataProvider.getFilterIndexToObjectMap();
+ original.putAll(filterCopy);
+ this.filterRowDataProvider.getFilterStrategy().applyFilter(original);
+ }
+
// re-apply the sorting after the tree update
if (this.treeFormat.getSortModel() != null) {
for (int i = 0; i < sortedIndexes.size(); i++) {

Back to the top