Package org.eclipse.nebula.widgets.nattable.examples._500_Layers

Source Code of org.eclipse.nebula.widgets.nattable.examples._500_Layers._509_SortHeaderLayerExample$PersonWithAddressSortModel$PersonWithAddressComparator

/*******************************************************************************
* Copyright (c) 2013 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 <dirk.fauth@gmail.com> - initial API and implementation
*******************************************************************************/
package org.eclipse.nebula.widgets.nattable.examples._500_Layers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.nebula.widgets.nattable.NatTable;
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.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample;
import org.eclipse.nebula.widgets.nattable.examples.data.person.Address;
import org.eclipse.nebula.widgets.nattable.examples.data.person.DataModelConstants;
import org.eclipse.nebula.widgets.nattable.examples.data.person.PersonService;
import org.eclipse.nebula.widgets.nattable.examples.data.person.PersonWithAddress;
import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner;
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.hideshow.ColumnHideShowLayer;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
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.SortDirectionEnum;
import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer;
import org.eclipse.nebula.widgets.nattable.sort.command.SortCommandHandler;
import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;

/**
* Simple example showing how to add the {@link SortHeaderLayer} to the layer
* composition of a grid.
*
* @author Dirk Fauth
*
*/
public class _509_SortHeaderLayerExample extends AbstractNatExample {

    public static void main(String[] args) throws Exception {
        StandaloneNatExampleRunner.run(new _509_SortHeaderLayerExample());
    }

    @Override
    public String getDescription() {
        return "This example shows the usage of the SortHeaderLayer within a grid that uses"
                + " a custom ISortModel.";
    }

    @Override
    public Control createExampleControl(Composite parent) {
        // property names of the Person class
        String[] propertyNames = { "firstName", "lastName", "gender",
                "married", "birthday" };

        // mapping from property to label, needed for column header labels
        Map<String, String> propertyToLabelMap = new HashMap<String, String>();
        propertyToLabelMap.put("firstName", "Firstname");
        propertyToLabelMap.put("lastName", "Lastname");
        propertyToLabelMap.put("gender", "Gender");
        propertyToLabelMap.put("married", "Married");
        propertyToLabelMap.put("birthday", "Birthday");

        // build the body layer stack
        // Usually you would create a new layer stack by extending
        // AbstractIndexLayerTransform and
        // setting the ViewportLayer as underlying layer. But in this case using
        // the ViewportLayer
        // directly as body layer is also working.
        List<PersonWithAddress> data = PersonService.getPersonsWithAddress(10);

        IColumnPropertyAccessor<PersonWithAddress> accessor = new ReflectiveColumnPropertyAccessor<PersonWithAddress>(
                propertyNames);
        IDataProvider bodyDataProvider = new ListDataProvider<PersonWithAddress>(
                data, accessor);
        DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);
        ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(
                bodyDataLayer);
        ColumnHideShowLayer columnHideShowLayer = new ColumnHideShowLayer(
                columnReorderLayer);
        SelectionLayer selectionLayer = new SelectionLayer(columnHideShowLayer);
        ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);

        // build the column header layer
        IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(
                propertyNames, propertyToLabelMap);
        DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(
                columnHeaderDataProvider);
        ILayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer,
                viewportLayer, selectionLayer);

        ConfigRegistry configRegistry = new ConfigRegistry();
        SortHeaderLayer<PersonWithAddress> sortHeaderLayer = new SortHeaderLayer<PersonWithAddress>(
                columnHeaderLayer, new PersonWithAddressSortModel(data));

        // build the row header layer
        IDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(
                bodyDataProvider);
        DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(
                rowHeaderDataProvider);
        ILayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer,
                viewportLayer, selectionLayer);

        // 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(viewportLayer, sortHeaderLayer,
                rowHeaderLayer, cornerLayer);

        // turn the auto configuration off as we want to add custom
        // configurations
        NatTable natTable = new NatTable(parent, gridLayer, false);

        natTable.setConfigRegistry(configRegistry);

        // as the autoconfiguration of the NatTable is turned off, we have to
        // add the
        // DefaultNatTableStyleConfiguration manually
        natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
        // enable sorting on single click on the column header
        natTable.addConfiguration(new SingleClickSortConfiguration());

        natTable.configure();

        return natTable;
    }

    /**
     * A simple implementation for {@link ISortModel} that can be used to sort
     * {@link PersonWithAddress} objects. It uses it's own {@link Comparator}
     * and doesn't support multiple column sorting and it won't be possible to
     * remove the sorting. Of course this can be implemented to work like the
     * default behaviour of the NatTable.
     *
     * @author Dirk Fauth
     */
    class PersonWithAddressSortModel implements ISortModel {

        /**
         * Array that contains the sort direction for every column. Needed to
         * access the current sort state of a column.
         */
        protected SortDirectionEnum[] sortDirections;

        /**
         * Array that contains the sorted flags for every column. Needed to
         * access the current sort state of a column.
         */
        protected boolean[] sorted;

        /**
         * As this implementation only supports single column sorting, this
         * property contains the the column index of the column that is
         * currently used for sorting. Initial value = -1 for no sort column
         */
        protected int currentSortColumn = -1;

        /**
         * As this implementation only supports single column sorting, this
         * property contains the current sort direction of the column that is
         * currently used for sorting.
         */
        protected SortDirectionEnum currentSortDirection = SortDirectionEnum.ASC;

        /**
         * Data list that is sorted
         */
        private List<PersonWithAddress> persons;

        /**
         * Creates a new {@link PersonWithAddressSortModel} for the list of
         * objects.
         *
         * @param persons
         *            the list of objects that should be sorted
         */
        public PersonWithAddressSortModel(List<PersonWithAddress> persons) {
            this.persons = persons;

            sortDirections = new SortDirectionEnum[DataModelConstants.PERSONWITHADDRESS_NUMBER_OF_COLUMNS];
            Arrays.fill(sortDirections, SortDirectionEnum.NONE);

            sorted = new boolean[DataModelConstants.PERSONWITHADDRESS_NUMBER_OF_COLUMNS];
            Arrays.fill(sorted, false);

            // call initial sorting
            sort(0, SortDirectionEnum.ASC, false);
        }

        /**
         * As this is a simple implementation of an {@link ISortModel} and we
         * don't support multiple column sorting, this list returns either a
         * list with one entry for the current sort column or an empty list.
         */
        @Override
        public List<Integer> getSortedColumnIndexes() {
            List<Integer> indexes = new ArrayList<Integer>();
            if (currentSortColumn > -1) {
                indexes.add(Integer.valueOf(currentSortColumn));
            }
            return indexes;
        }

        /**
         * @return TRUE if the column with the given index is sorted at the
         *         moment.
         */
        @Override
        public boolean isColumnIndexSorted(int columnIndex) {
            return sorted[columnIndex];
        }

        /**
         * @return the direction in which the column with the given index is
         *         currently sorted
         */
        @Override
        public SortDirectionEnum getSortDirection(int columnIndex) {
            return sortDirections[columnIndex];
        }

        /**
         * @return 0 as we don't support multiple column sorting.
         */
        @Override
        public int getSortOrder(int columnIndex) {
            return 0;
        }

        /**
         * Remove all sorting
         */
        @Override
        public void clear() {
            Arrays.fill(sortDirections, SortDirectionEnum.NONE);
            Arrays.fill(sorted, false);
            this.currentSortColumn = -1;
        }

        /**
         * This method is called by the {@link SortCommandHandler} in response
         * to a sort command. It is responsible for sorting the requested
         * column.
         */
        @Override
        public void sort(int columnIndex, SortDirectionEnum sortDirection,
                boolean accumulate) {
            if (!isColumnIndexSorted(columnIndex)) {
                clear();
            }

            if (sortDirection.equals(SortDirectionEnum.NONE)) {
                // we don't support NONE as user action
                sortDirection = SortDirectionEnum.ASC;
            }

            Collections.sort(persons, new PersonWithAddressComparator(
                    columnIndex, sortDirection));
            sortDirections[columnIndex] = sortDirection;
            sorted[columnIndex] = sortDirection.equals(SortDirectionEnum.NONE) ? false
                    : true;

            currentSortColumn = columnIndex;
            currentSortDirection = sortDirection;
        }

        /**
         * Custom comparator for {@link PersonWithAddress} objects
         */
        class PersonWithAddressComparator implements
                Comparator<PersonWithAddress> {

            int colIdx = 0;
            SortDirectionEnum sortDirection;

            public PersonWithAddressComparator(int columnIndex,
                    SortDirectionEnum sortDirection) {
                this.colIdx = columnIndex;
                this.sortDirection = sortDirection;
            }

            @SuppressWarnings({ "rawtypes", "unchecked" })
            @Override
            public int compare(PersonWithAddress pwa1, PersonWithAddress pwa2) {
                Comparable compareObject1 = null;
                Comparable compareObject2 = null;
                Address address1 = pwa1.getAddress();
                Address address2 = pwa2.getAddress();

                switch (colIdx) {
                    case DataModelConstants.FIRSTNAME_COLUMN_POSITION:
                        compareObject1 = pwa1.getFirstName();
                        compareObject2 = pwa2.getFirstName();
                        break;
                    case DataModelConstants.LASTNAME_COLUMN_POSITION:
                        compareObject1 = pwa1.getLastName();
                        compareObject2 = pwa2.getLastName();
                        break;
                    case DataModelConstants.GENDER_COLUMN_POSITION:
                        compareObject1 = pwa1.getGender().ordinal();
                        compareObject2 = pwa2.getGender().ordinal();
                        break;
                    case DataModelConstants.MARRIED_COLUMN_POSITION:
                        compareObject1 = pwa1.isMarried();
                        compareObject2 = pwa2.isMarried();
                        break;
                    case DataModelConstants.BIRTHDAY_COLUMN_POSITION:
                        compareObject1 = pwa1.getBirthday();
                        compareObject2 = pwa2.getBirthday();
                        break;
                    case DataModelConstants.STREET_COLUMN_POSITION:
                        compareObject1 = address1.getStreet();
                        compareObject2 = address2.getStreet();
                        break;
                    case DataModelConstants.HOUSENUMBER_COLUMN_POSITION:
                        compareObject1 = address1.getHousenumber();
                        compareObject2 = address2.getHousenumber();
                        break;
                    case DataModelConstants.POSTALCODE_COLUMN_POSITION:
                        compareObject1 = address1.getPostalCode();
                        compareObject2 = address2.getPostalCode();
                        break;
                    case DataModelConstants.CITY_COLUMN_POSITION:
                        compareObject1 = address1.getCity();
                        compareObject2 = address2.getCity();
                        break;
                }

                int result = 0;

                // make null safe compare
                if (compareObject1 == null) {
                    if (compareObject2 != null) {
                        result = -1;
                    } else {
                        result = 0;
                    }
                } else {
                    if (compareObject2 != null) {
                        result = compareObject1.compareTo(compareObject2);
                    } else {
                        result = 1;
                    }
                }

                // negate compare result if sort direction is descending
                if (sortDirection.equals(SortDirectionEnum.DESC)) {
                    result = result * -1;
                }

                return result;
            }

        }

        /*
         * (non-Javadoc)
         *
         * @see org.eclipse.nebula.widgets.nattable.sort.ISortModel#
         * getComparatorsForColumnIndex(int)
         */
        @SuppressWarnings("rawtypes")
        @Override
        public List<Comparator> getComparatorsForColumnIndex(int columnIndex) {
            return null;
        }
    }
}
TOP

Related Classes of org.eclipse.nebula.widgets.nattable.examples._500_Layers._509_SortHeaderLayerExample$PersonWithAddressSortModel$PersonWithAddressComparator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.