/******************************************************************************* * Copyright (c) 2012, 2013, 2015 Original authors 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: * Original authors and others - initial API and implementation ******************************************************************************/ package org.eclipse.nebula.widgets.nattable.examples.examples._130_Sorting; import java.util.Comparator; 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.IConfiguration; import org.eclipse.nebula.widgets.nattable.config.NullComparator; import org.eclipse.nebula.widgets.nattable.dataset.fixture.data.RowDataFixture; import org.eclipse.nebula.widgets.nattable.dataset.fixture.data.RowDataListFixture; import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample; import org.eclipse.nebula.widgets.nattable.examples.PersistentNatExampleWrapper; import org.eclipse.nebula.widgets.nattable.examples.fixtures.GlazedListsGridLayer; import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner; import org.eclipse.nebula.widgets.nattable.layer.AbstractLayer; import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnOverrideLabelAccumulator; import org.eclipse.nebula.widgets.nattable.persistence.command.DisplayPersistenceDialogCommandHandler; import org.eclipse.nebula.widgets.nattable.selection.config.DefaultSelectionStyleConfiguration; import org.eclipse.nebula.widgets.nattable.sort.SortConfigAttributes; import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer; import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration; import org.eclipse.nebula.widgets.nattable.style.DisplayMode; import org.eclipse.nebula.widgets.nattable.ui.menu.HeaderMenuConfiguration; import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.GlazedLists; import ca.odell.glazedlists.TransformedList; /** * Example to demonstrate sorting of the columns. */ public class SortableGridExample extends AbstractNatExample { private static final String CUSTOM_COMPARATOR_LABEL = "customComparatorLabel"; protected static final String NO_SORT_LABEL = "noSortLabel"; public static void main(String[] args) { StandaloneNatExampleRunner.run(700, 400, new PersistentNatExampleWrapper(new SortableGridExample())); } @Override public String getDescription() { return "Grid demonstrates sorting moving data.\n" + "\n" + "Features:\n" + "The contents of the grid are kept in sorted order as the rows are added/removed.\n" + "Custom comparators can be applied to each column.\n" + "Ignorecase comparator applied to the 'Rating' column.\n" + "Sorting can be turned off on the selective columns.\n" + "'Ask price' field is not sortable.\n" + "\n" + "Key bindings:\n" + "Sort by left clicking on the column header.\n" + "Add columns to the existing sort by (Alt. + left click) on the column header\n" + "\n" + "Technical information:\n" + "The default implementation uses GlazedLists to sort the backing data source."; } private TransformedList<RowDataFixture, RowDataFixture> rowObjectsGlazedList; private NatTable nattable; /** * @see GlazedListsGridLayer to see the required stack setup. Basically the * {@link SortHeaderLayer} needs to be a part of the Column header * layer stack. */ @Override public Control createExampleControl(Composite parent) { EventList<RowDataFixture> eventList = GlazedLists.eventList(RowDataListFixture.getList()); this.rowObjectsGlazedList = GlazedLists.threadSafeList(eventList); ConfigRegistry configRegistry = new ConfigRegistry(); GlazedListsGridLayer<RowDataFixture> glazedListsGridLayer = new GlazedListsGridLayer<>( this.rowObjectsGlazedList, RowDataListFixture.getPropertyNames(), RowDataListFixture.getPropertyToLabelMap(), configRegistry); this.nattable = new NatTable(parent, glazedListsGridLayer, false); this.nattable.setConfigRegistry(configRegistry); this.nattable.addConfiguration(new DefaultNatTableStyleConfiguration()); // Change the default sort key bindings. Note that 'auto configure' was // turned off for the SortHeaderLayer (setup in the // GlazedListsGridLayer) this.nattable.addConfiguration(new SingleClickSortConfiguration()); this.nattable.addConfiguration( getCustomComparatorConfiguration( glazedListsGridLayer.getColumnHeaderLayerStack().getDataLayer())); this.nattable.addConfiguration(new DefaultSelectionStyleConfiguration()); this.nattable.addConfiguration(new HeaderMenuConfiguration(this.nattable) { @Override protected PopupMenuBuilder createColumnHeaderMenu(NatTable natTable) { return super.createColumnHeaderMenu(natTable) .withStateManagerMenuItemProvider(); } }); this.nattable.configure(); // add the DisplayPersistenceDialogCommandHandler with the created // NatTable instance after configure() so all configuration and states // are correctly applied before storing the default state glazedListsGridLayer.registerCommandHandler( new DisplayPersistenceDialogCommandHandler(this.nattable)); return this.nattable; } /** * NOTE: The labels for the the custom comparators must go on the * columnHeaderDataLayer - since, the SortHeaderLayer will resolve cell * labels with respect to its underlying layer i.e columnHeaderDataLayer */ private IConfiguration getCustomComparatorConfiguration(final AbstractLayer columnHeaderDataLayer) { return new AbstractRegistryConfiguration() { @Override public void configureRegistry(IConfigRegistry configRegistry) { // Add label accumulator ColumnOverrideLabelAccumulator labelAccumulator = new ColumnOverrideLabelAccumulator(columnHeaderDataLayer); columnHeaderDataLayer.setConfigLabelAccumulator(labelAccumulator); // Register labels labelAccumulator.registerColumnOverrides( RowDataListFixture.getColumnIndexOfProperty(RowDataListFixture.RATING_PROP_NAME), CUSTOM_COMPARATOR_LABEL); labelAccumulator.registerColumnOverrides( RowDataListFixture.getColumnIndexOfProperty(RowDataListFixture.ASK_PRICE_PROP_NAME), NO_SORT_LABEL); // Register custom comparator configRegistry.registerConfigAttribute( SortConfigAttributes.SORT_COMPARATOR, getCustomComparator(), DisplayMode.NORMAL, CUSTOM_COMPARATOR_LABEL); // Register null comparator to disable sort configRegistry.registerConfigAttribute( SortConfigAttributes.SORT_COMPARATOR, new NullComparator(), DisplayMode.NORMAL, NO_SORT_LABEL); } }; } private Comparator<?> getCustomComparator() { return new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareToIgnoreCase(o2); } }; }; }