Home » Eclipse Projects » NatTable » Filtering combo box filtering
| |
Re: Filtering combo box filtering [message #1738365 is a reply to message #1737536] |
Tue, 19 July 2016 09:58 |
Naveen Sabapathy Messages: 46 Registered: July 2016 |
Member |
|
|
Hello Dirk,
I'm also using the Filter list as the base list.
new ComboBoxFilterRowHeaderComposite(
bodyLayerStack.getFilterList(),
bodyLayerStack.getGlazedListsEventLayer(),
bodyLayerStack.getSortedList(),
columnPropertyAccessor,
columnHeaderLayer,
columnHeaderDataProvider,
configRegistry);
My Desired Behaviour is
No | baseValue | Sub Value |
---------------------------------
1 | A | AA |
2 | A | AB |
3 | B | BA |
4 | B | BB |
---------------------------------
1) If I select the combo box value of A in base value, I need to get filter values of AA and AB in subvalue. (Right now its displaying the always AA, AB, BA &BB irrespective of selection.)
2) if I select AA in subvalue, then I need to get A alone in the base value. (Rightnow it displays A& B irrespective of selection).
Kindly let me know, how to get this desired behaviour.
|
|
|
Re: Filtering combo box filtering [message #1738380 is a reply to message #1738365] |
Tue, 19 July 2016 10:59 |
Dirk Fauth Messages: 2903 Registered: July 2012 |
Senior Member |
|
|
Quote:Kindly let me know, how to get this desired behaviour.
I already gave the answer to solve your issue.
Quote:IIRC you need to use the FilterList as the base list on creating the filter header. Please check the Javadoc
If you would have checked the javadoc, you would have seen this:
* @param baseCollection
* The base collection that is used to fill the body. Needed to
* determine the values to show in the filter comboboxes and
* initially pre-select them.
baseCollection is the third parameter. You are talking about the first parameter, which is filterList. And that is required to be able to filter.
If you change your code to the following snippet, it should work the way you desire
new ComboBoxFilterRowHeaderComposite(
bodyLayerStack.getFilterList(),
bodyLayerStack.getGlazedListsEventLayer(),
bodyLayerStack.getFilterList(),
columnPropertyAccessor,
columnHeaderLayer,
columnHeaderDataProvider,
configRegistry);
|
|
|
Re: Filtering combo box filtering [message #1738386 is a reply to message #1738380] |
Tue, 19 July 2016 11:53 |
Naveen Sabapathy Messages: 46 Registered: July 2016 |
Member |
|
|
Thank you. I have modified the code as you suggested. Now I'm getting Index out of bounds error at some "StandaloneNatExampleRunner.run(new _6034_ExcelLikeFilterRowExample());".
/*******************************************************************************
* Copyright (c) 2013, 2015 Dirk Fauth and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Dirk Fauth - initial API and implementation
*******************************************************************************/
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
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.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.dataset.person.Address;
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.dataset.person.PersonWithAddress;
import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
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.filterrow.ComboBoxFilterRowHeaderComposite;
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.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.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.persistence.command.DisplayPersistenceDialogCommandHandler;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.ui.menu.HeaderMenuConfiguration;
import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;
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.layout.GridLayout;
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;
/**
* Example showing how to add the filter row to the layer composition of a grid
* that looks like the Excel filter.
*/
public class _6034_ExcelLikeFilterRowExample extends AbstractNatExample {
public static void main(String[] args) throws Exception {
StandaloneNatExampleRunner.run(new _6034_ExcelLikeFilterRowExample());
}
@Override
public String getDescription() {
return "This example shows the usage of the filter row within a grid that looks like the Excel"
+ " filter row.";
}
@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
ConfigRegistry configRegistry = new ConfigRegistry();
// property names of the Person class
String[] propertyNames = { "firstName", "lastName", "gender",
"married", "birthday", "address.street", "address.housenumber",
"address.postalCode", "address.city" };
// mapping from property to label, needed for column header labels
Map propertyToLabelMap = new HashMap();
propertyToLabelMap.put("firstName", "Firstname");
propertyToLabelMap.put("lastName", "Lastname");
propertyToLabelMap.put("gender", "Gender");
propertyToLabelMap.put("married", "Married");
propertyToLabelMap.put("birthday", "Birthday");
propertyToLabelMap.put("address.street", "Street");
propertyToLabelMap.put("address.housenumber", "Housenumber");
propertyToLabelMap.put("address.postalCode", "Postal Code");
propertyToLabelMap.put("address.city", "City");
IColumnPropertyAccessor columnPropertyAccessor =
new ExtendedReflectiveColumnPropertyAccessor(propertyNames);
final BodyLayerStack bodyLayerStack =
new BodyLayerStack(
PersonService.getPersonsWithAddress(50),
columnPropertyAccessor);
// build the column header layer
IDataProvider columnHeaderDataProvider =
new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
DataLayer columnHeaderDataLayer =
new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);
ILayer columnHeaderLayer =
new ColumnHeaderLayer(
columnHeaderDataLayer,
bodyLayerStack,
bodyLayerStack.getSelectionLayer());
ComboBoxFilterRowHeaderComposite filterRowHeaderLayer =
new ComboBoxFilterRowHeaderComposite(
bodyLayerStack.getFilterList(),
bodyLayerStack.getGlazedListsEventLayer(),
bodyLayerStack.getFilterList(),
columnPropertyAccessor,
columnHeaderLayer,
columnHeaderDataProvider,
configRegistry);
// build the row header layer
IDataProvider rowHeaderDataProvider =
new DefaultRowHeaderDataProvider(bodyLayerStack.getBodyDataProvider());
DataLayer rowHeaderDataLayer =
new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
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);
// turn the auto configuration off as we want to add our header menu
// configuration
NatTable natTable = new NatTable(container, gridLayer, false);
// as the autoconfiguration of the NatTable is turned off, we have to
// add the DefaultNatTableStyleConfiguration and the ConfigRegistry
// manually
natTable.setConfigRegistry(configRegistry);
natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
natTable.addConfiguration(new HeaderMenuConfiguration(natTable) {
@Override
protected PopupMenuBuilder createCornerMenu(NatTable natTable) {
return super.createCornerMenu(natTable)
.withStateManagerMenuItemProvider();
}
});
natTable.addConfiguration(new AbstractRegistryConfiguration() {
@Override
public void configureRegistry(IConfigRegistry configRegistry) {
configRegistry.registerConfigAttribute(
EditConfigAttributes.CELL_EDITABLE_RULE,
IEditableRule.ALWAYS_EDITABLE);
}
});
natTable.configure();
natTable.registerCommandHandler(
new DisplayPersistenceDialogCommandHandler(natTable));
GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
Button button = new Button(container, SWT.PUSH);
button.setText("Add Row");
button.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");
PersonWithAddress person = new PersonWithAddress(42, "Ralph",
"Wiggum", Gender.MALE, false, new Date(), address);
bodyLayerStack.getSortedList().add(person);
}
});
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 SortedList sortedList;
private final FilterList filterList;
private final IDataProvider bodyDataProvider;
private final DataLayer bodyDataLayer;
private final GlazedListsEventLayer glazedListsEventLayer;
private final SelectionLayer selectionLayer;
public BodyLayerStack(List values, IColumnPropertyAccessor columnPropertyAccessor) {
// wrapping of the list to show into GlazedLists
// see http://publicobject.com/glazedlists/ for further information
EventList eventList = GlazedLists.eventList(values);
TransformedList rowObjectsGlazedList = GlazedLists.threadSafeList(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);
this.bodyDataProvider =
new ListDataProvider(this.filterList, columnPropertyAccessor);
this.bodyDataLayer = new DataLayer(getBodyDataProvider());
// layer for event handling of GlazedLists and PropertyChanges
this.glazedListsEventLayer =
new GlazedListsEventLayer(this.bodyDataLayer, this.filterList);
this.selectionLayer = new SelectionLayer(getGlazedListsEventLayer());
ViewportLayer viewportLayer = new ViewportLayer(getSelectionLayer());
FreezeLayer freezeLayer = new FreezeLayer(this.selectionLayer);
CompositeFreezeLayer compositeFreezeLayer =
new CompositeFreezeLayer(freezeLayer, viewportLayer, this.selectionLayer);
setUnderlyingLayer(compositeFreezeLayer);
}
public SelectionLayer getSelectionLayer() {
return this.selectionLayer;
}
public SortedList getSortedList() {
return this.sortedList;
}
public FilterList getFilterList() {
return this.filterList;
}
public IDataProvider getBodyDataProvider() {
return this.bodyDataProvider;
}
public DataLayer getBodyDataLayer() {
return this.bodyDataLayer;
}
public GlazedListsEventLayer getGlazedListsEventLayer() {
return this.glazedListsEventLayer;
}
}
}
|
|
| | | | | | | |
Re: Filtering combo box filtering [message #1805261 is a reply to message #1802889] |
Wed, 10 April 2019 13:57 |
Andreas Sturm Messages: 20 Registered: August 2018 |
Junior Member |
|
|
Hey Dirk,
we did some deeper investigation on the topic and want to present our findings and possible approach.
Problem1: For a big Nattable of size > 1000 rows, when user applies filters, sorting and delete a row the filters are lost.
Solution1: We were able to re-load the Nattable state before deletion, this maintained the filters and column sorting
BUT introduced a new problem.
Problem2_In_Solution1: The problem is that after restoring the Nattable state, the focus is set back to row 1 i.e. if user
Selects row 500 and deletes it, restoring the state will move the focus on row 1. i.e. the Nattable is scrolled back to row 1.
Solution_Of_Problem2: We tried to scroll back to the row number which is selected for deletion and we got success.
But we got success by using deprecated API "ShowRowInViewportCommand"
Below code is to get the row number that is selected for deletion:-
TreeMap<Integer,V4BPCPtiTableRow> selectedRows = tableviewer.getNatTableView().getSelectedRows();
Set<Integer> keys = selectedRows.keySet();
Integer rownumber=selectedRows.firstKey();
Below code is to select a particular row of the nattable (this scrolls the Nattable to 'rownumber'
Properties prop = userState.get(V4BPCMessages.CONFIG_DEFAULT);
natTable.loadState(V4BPCMessages.CONFIG_DEFAULT,prop);
natTable.doCommand(new ShowRowInViewportCommand(tableviewer.getNatTableView().getBodyLayerStack().getViewportLayer(), rownumber));
natTable.doCommand(new SelectRowsCommand(tableviewer.getNatTableView().getGlazedListsGridLayer().getBodyLayer(), 0, rownumber, false, false));
Findings: We observed that the Solution_Of_Problem2 works only when using both "ShowRowInViewportCommand" and "SelectRowsCommand" together.
Using only "SelectRowsCommand" does not work.
Help : Please help us to achieve our goal.
We are using below nattable jars.
org.eclipse.nebula.widgets.nattable.core_1.6.0.201810101910.jar
org.eclipse.nebula.widgets.nattable.extension.glazedlists_1.6.0.201810101910.jar
org.eclipse.nebula.widgets.nattable.extension.poi_1.5.1.201810101910.jar
|
|
| |
Re: Filtering combo box filtering [message #1805275 is a reply to message #1805265] |
Thu, 11 April 2019 05:36 |
Dirk Fauth Messages: 2903 Registered: July 2012 |
Senior Member |
|
|
Hi,
thanks for the observation results. Some comments:
1. Like I tried to explain before, the issue is a concurrency issue. When sorting a bigger table, even with GlazedLists, the sorting may take some time. But we refresh every 100ms from the GlazedListsEventLayer. So it can happen that because of the refresh at such an interval the list seems to be empty. And an empty list is handled which results in clearing the filter as it looks like the values do not exist in the list anymore.
2. With regards to reloading, well reload is first clearing all states and then applies the stored ones. Could either also be a concurrency issue that the table shows from the top (not sure what you mean with focus, as NatTable has no focus on cells) or the selection is lost because of the StructuralChangeEvent. And filtering and sorting is surely a structural change.
3. The ShowRowInViewportCommand is not deprecated API. Only the constructor you are using is deprecated. And I deprecated the constructor with layer parameter because actually this is pretty nonsense. If you specify a layer and a position, then the position is related to the layer. But with using the ViewportLayer the row position can only be something that is currently visible (remember that the ViewportLayer is used to only handle visible cells). So you are not able to bring a row into the viewport that is currently not visible, because the command is not processed. I introduced a constructor that only takes a row position as parameter. And that position has to be related to the layer that is underlying the ViewportLayer (typically the SelectionLayer). This way the command is processed definitely and you are able to bring a cell in the viewport that is currently not visible.
Another option could be to use the PreserveSelectionModel, although I am not sure if you would phase also the issue that the selection is lost because of concurrency issues. I think the concurrency topic is something that needs to be looked at really closely.
Unfortunately I can't send a PM via forum because that feature is disabled for the Eclipse forum. But you should be able to drop me an email to get in contact. My email address should be visible in many NatTable classes in the copyright header. ;)
[Updated on: Thu, 11 April 2019 05:43] Report message to a moderator
|
|
|
Re: Filtering combo box filtering [message #1805342 is a reply to message #1805275] |
Fri, 12 April 2019 06:11 |
Andreas Sturm Messages: 20 Registered: August 2018 |
Junior Member |
|
|
Thanks for your comments.
As suggested by you we performed three use cases with change of constructor "ShowRowInViewportCommand" on the nattable with > 1000 rows.
Use Case 1:
Logical implementation through code:
1. Store the nattable state
2. Get the row number that is selected for deletion
3. Load the Nattable state and
4. Select the same row number of the nattable which was deleted (this should scroll the Nattable to 'rownumber')
Below code is to save table state and get the row number that is selected for deletion:-
NatTable natTable = tableviewer.getTable();
natTable.saveState(V4BPCMessages.CONFIG_DEFAULT, currenProp);
userState.put(V4BPCMessages.CONFIG_DEFAULT, currenProp);
TreeMap<Integer,V4BPCPtiTableRow> selectedRows = tableviewer.getNatTableView().getSelectedRows();
Set<Integer> keys = selectedRows.keySet();
Integer rownumber=selectedRows.firstKey();
Below code is to load the table state and select a particular row of the nattable (this scrolls the Nattable to 'rownumber')
Properties prop = userState.get(V4BPCMessages.CONFIG_DEFAULT);
natTable.loadState(V4BPCMessages.CONFIG_DEFAULT,prop);
natTable.doCommand(new ShowRowInViewportCommand(rownumber));
natTable.doCommand(new SelectRowsCommand(tableviewer.getNatTableView().getGlazedListsGridLayer().getBodyLayer(), 0, rownumber, false, false));
User actions on Nattable:
1. Select row number 600 and delete the row 600.
Result: the nattable table was set from row number 600 at the bottom.
2. Now, select row number 590 and delete the row 590.
Result: The row deletion worked as expected i.e. the table was reset correctly, i.e. visually we saw that only row number 590 got deleted and rest of the table remained as it is.
3. Scroll up or down 20 or 30 rows, perform 1, we get the same result.
Use Case 2:
Logical implementation through code:
1. Store the nattable state
2. Get the row number that is selected for deletion
3. Select the same row number of the nattable which was deleted (this should scroll the Nattable to 'rownumber')
Please note nattable state is NOT loaded
Below code is to save table state and get the row number that is selected for deletion:-
NatTable natTable = tableviewer.getTable();
natTable.saveState(V4BPCMessages.CONFIG_DEFAULT, currenProp);
userState.put(V4BPCMessages.CONFIG_DEFAULT, currenProp);
TreeMap<Integer,V4BPCPtiTableRow> selectedRows = tableviewer.getNatTableView().getSelectedRows();
Set<Integer> keys = selectedRows.keySet();
Integer rownumber=selectedRows.firstKey();
Below code is to select a particular row of the nattable (this scrolls the Nattable to 'rownumber')
// Commented out the below code which loads the state.
/*Properties prop = userState.get(V4BPCMessages.CONFIG_DEFAULT);
natTable.loadState(V4BPCMessages.CONFIG_DEFAULT,prop);*/
natTable.doCommand(new ShowRowInViewportCommand(rownumber));
natTable.doCommand(new SelectRowsCommand(tableviewer.getNatTableView().getGlazedListsGridLayer().getBodyLayer(), 0, rownumber, false, false));
User actions on Nattable: This behavior is different from use case 1.
1. Select row number 600 and delete the row 600.
Result: the nattable table was visible from row number 600 +1 from the TOP i.e. from row 601.
2. Now, select row number 590 and delete the row 590.
Result: The row deletion worked as expected i.e. the table was reset correctly, i.e. visually we saw that only row number 590 got deleted and rest of the table remained as it is.
3. Scroll up or down 20 or 30 rows, perform 1, we get the same result as that of step 1.
Observation: The filters were not cleared when the table state is stored but table state is not re-loaded through code.
Use Case 3:
Logical implementation through code:
1. Get the row number that is selected for deletion
2. Select the same row number of the nattable which was deleted (this should scroll the Nattable to 'rownumber')
Please note nattable state is NOT stored and not loaded.
Below code is to get the row number that is selected for deletion:-
TreeMap<Integer,V4BPCPtiTableRow> selectedRows = tableviewer.getNatTableView().getSelectedRows();
Set<Integer> keys = selectedRows.keySet();
Integer rownumber=selectedRows.firstKey();
Below code is to select a particular row of the nattable (this scrolls the Nattable to 'rownumber')
natTable.doCommand(new ShowRowInViewportCommand(rownumber));
natTable.doCommand(new SelectRowsCommand(tableviewer.getNatTableView().getGlazedListsGridLayer().getBodyLayer(), 0, rownumber, false, false));
Test performed on the > 1000 rows of nattable.
1. Select row number 600 and delete the row 600.
Result: the nattable table was visible from row number 600 +1 from the top i.e from row 601.
2. Now, select row number 590 and delete the row 590.
Result: The row deletion worked as expected i.e. the table was reset correctly, i.e. visually we saw that only row number 590 got deleted and rest of the table remained as it is.
3. Scroll up or down 20 or 30 rows, perform 1, we get the same result as that of step 1.
Observation: The filters were cleared when the table state was NOT Stored and NOT re-loaded.
Important NOTE:
In all of the above testing it was observed that the command "SelectRowsCommand" never selected the Row number which is passed to it, it only scrolls the Nattable to that particular index.
We are expecting that the row will ALSO get selected.
The table, in the first place, was never visible with the correct row number in reference to the visible screen, either it was scrolled to the top or to the bottom, see scenario 1 and 2. Only when the scrolling was not changed, it worked well, see steps 2 in scenario 1 and 2.
Please let us know your comments on this.
|
|
| | | | | |
Goto Forum:
Current Time: Wed Sep 25 08:24:17 GMT 2024
Powered by FUDForum. Page generated in 0.69449 seconds
|