--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.utils.ui.workbench.ui;\r
+\r
+import java.util.Comparator;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.eclipse.jface.viewers.IBaseLabelProvider;\r
+import org.eclipse.jface.viewers.ITableLabelProvider;\r
+import org.eclipse.jface.viewers.TableViewer;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.jface.viewers.ViewerSorter;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.widgets.TableColumn;\r
+import org.eclipse.ui.IMemento;\r
+\r
+/**\r
+ * This class adds column sorting functionality to SWT Table widget.\r
+ * <p>\r
+ * Attach this Sorter after you have created all columns.\r
+ * <p>\r
+ * Usage: TableColumnSorter.attachTableColumnSorter(myTable);\r
+ * \r
+ * @author Toni Kalajainen\r
+ */\r
+public class TableColumnSorter {\r
+\r
+ /** The table */\r
+ protected final TableViewer viewer;\r
+ \r
+ /** the sorter */\r
+ protected final ColumnSorter sorter;\r
+ \r
+ /** column specific comparators*/\r
+ protected Map<Integer, Comparator<?>> columnComparators = \r
+ new HashMap<Integer, Comparator<?>>(); \r
+ \r
+ public static TableColumnSorter attachTableColumnSorter(TableViewer viewer) {\r
+ return new TableColumnSorter(viewer);\r
+ }\r
+ \r
+ public static void unattachTableColumnSorter(TableViewer viewer) {\r
+ viewer.setSorter(null);\r
+ }\r
+ \r
+ public void setColumnComparator(int index, Comparator<?> comparator)\r
+ {\r
+ columnComparators.put(index, comparator);\r
+ viewer.refresh();\r
+ }\r
+ \r
+ private final static String PRI_ASC = "PriAsc";\r
+ private final static String SEC_ASC = "SecAsc";\r
+ private final static String PRI_IND = "PriInd";\r
+ private final static String SEC_IND = "SecInd";\r
+ \r
+ public void saveState(String id, IMemento memento) {\r
+ memento.putInteger(id+PRI_ASC, sorter.isAscending()?1:0);\r
+ memento.putInteger(id+SEC_ASC, sorter.isSecondaryAscending()?1:0); \r
+ memento.putInteger(id+PRI_IND, sorter.getIndex());\r
+ memento.putInteger(id+SEC_IND, sorter.getSecondaryIndex());\r
+ }\r
+\r
+ public void restoreState(String id, IMemento memento) {\r
+ if (!hasState(id, memento)) return;\r
+ \r
+ sorter.setAscending( memento.getInteger(id+PRI_ASC)==1 );\r
+ sorter.setSecondaryAscending( memento.getInteger(id+SEC_ASC)==1 );\r
+ sorter.setIndex( memento.getInteger(id+PRI_IND) );\r
+ sorter.setSecondaryIndex( memento.getInteger(id+SEC_IND) );\r
+ \r
+ viewer.refresh();\r
+ }\r
+ \r
+ public boolean hasState(String id, IMemento memento) {\r
+ return (memento.getInteger(id+PRI_ASC)!=null) && \r
+ (memento.getInteger(id+SEC_ASC)!=null) && \r
+ (memento.getInteger(id+PRI_IND)!=null) && \r
+ (memento.getInteger(id+SEC_IND)!=null); \r
+ }\r
+ \r
+ public void setColumnAscending(int index)\r
+ {\r
+ sorter.setIndex(index);\r
+ sorter.setAscending(true);\r
+ viewer.refresh();\r
+ } \r
+ \r
+ private TableColumnSorter(TableViewer viewer) {\r
+ this.viewer = viewer;\r
+ this.sorter = new ColumnSorter();\r
+ \r
+ // Attach columns\r
+ TableColumn columns[] = viewer.getTable().getColumns(); \r
+ for(int i=0; i<columns.length; i++) {\r
+ TableColumn column = columns[i];\r
+ column.setData("index", new Integer(i));\r
+ column.addSelectionListener(new SelectionAdapter() {\r
+ public void widgetSelected(SelectionEvent e) { \r
+ int index = (Integer) e.widget.getData("index");\r
+ if (index == TableColumnSorter.this.sorter.getIndex()) {\r
+ // Reverse order\r
+ TableColumnSorter.this.sorter.setAscending( !TableColumnSorter.this.sorter.isAscending() );\r
+ } else {\r
+ TableColumnSorter.this.sorter.setSecondaryIndex( TableColumnSorter.this.sorter.getIndex() );\r
+ TableColumnSorter.this.sorter.setSecondaryAscending( TableColumnSorter.this.sorter.isAscending() );\r
+ TableColumnSorter.this.sorter.setIndex(index);\r
+ TableColumnSorter.this.sorter.setAscending(true);\r
+ }\r
+ TableColumnSorter.this.viewer.refresh();\r
+ }\r
+ });\r
+ }\r
+ viewer.setSorter(sorter);\r
+ }\r
+ \r
+ \r
+ class ColumnSorter extends ViewerSorter {\r
+ /** Sort direction */\r
+ private boolean ascending = true;\r
+ /** Secondary Sort direction */\r
+ private boolean secondaryAscending = true;\r
+ /** Sort column */\r
+ private int columnIndex = 0;\r
+ /** Secondary sort column */\r
+ private int secondaryColumnIndex = -1;\r
+ /** case sensitive */\r
+ private boolean caseSensitive = false;\r
+ \r
+ public void setAscending(boolean ascending) {\r
+ this.ascending = ascending;\r
+ }\r
+ \r
+ public boolean isAscending() {\r
+ return ascending;\r
+ } \r
+ \r
+ public void setSecondaryAscending(boolean ascending) {\r
+ this.secondaryAscending = ascending;\r
+ }\r
+ \r
+ public boolean isSecondaryAscending() {\r
+ return secondaryAscending;\r
+ } \r
+ \r
+ public void setIndex(int index) {\r
+ this.columnIndex = index;\r
+ }\r
+ \r
+ public int getIndex() {\r
+ return columnIndex;\r
+ }\r
+ \r
+ public void setSecondaryIndex(int index) {\r
+ this.secondaryColumnIndex = index;\r
+ }\r
+ \r
+ public int getSecondaryIndex() {\r
+ return secondaryColumnIndex;\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ private int compare(int columnIndex, String text1, String text2, Object o1, Object o2)\r
+ {\r
+ @SuppressWarnings("rawtypes")\r
+ Comparator c = columnComparators.get(columnIndex);\r
+ if (c==null || o1==null || o2==null)\r
+ return text1.compareTo(text2);\r
+ return c.compare(o1, o2);\r
+ }\r
+ \r
+ public int compare(Viewer viewer, Object e1, Object e2) {\r
+ int result = 0;\r
+ \r
+ TableViewer v = (TableViewer) viewer; \r
+ IBaseLabelProvider blp = v.getLabelProvider();\r
+ if (!(blp instanceof ITableLabelProvider)) {\r
+ return super.compare(viewer, e1, e2);\r
+ }\r
+ ITableLabelProvider tlp = (ITableLabelProvider) blp;\r
+ \r
+ // Primary sort\r
+ String text1 = tlp.getColumnText(e1, columnIndex);\r
+ String text2 = tlp.getColumnText(e2, columnIndex);\r
+ if (text1==null) text1="";\r
+ if (text2==null) text2=""; \r
+ if (!caseSensitive) {\r
+ text1 = text1.toLowerCase();\r
+ text2 = text2.toLowerCase();\r
+ } \r
+ result = compare(columnIndex, text1, text2, e1, e2); \r
+ if (!ascending) return -result;\r
+ \r
+ // secondary sort\r
+ if (result==0 && (secondaryColumnIndex>=0)) {\r
+ text1 = tlp.getColumnText(e1, secondaryColumnIndex);\r
+ text2 = tlp.getColumnText(e2, secondaryColumnIndex);\r
+ if (text1==null) text1="";\r
+ if (text2==null) text2=""; \r
+ if (!caseSensitive) {\r
+ text1 = text1.toLowerCase();\r
+ text2 = text2.toLowerCase();\r
+ } \r
+ result = compare(secondaryColumnIndex, text1, text2, e1, e2);\r
+ \r
+ if (!secondaryAscending) return -result;\r
+ }\r
+ \r
+ return result;\r
+ }\r
+\r
+ public boolean isCaseSensitive() {\r
+ return caseSensitive;\r
+ }\r
+\r
+ public void setCaseSensitive(boolean caseSensitive) {\r
+ this.caseSensitive = caseSensitive;\r
+ }\r
+ }\r
+\r
+ public ColumnSorter getSorter() {\r
+ return sorter;\r
+ }\r
+\r
+}\r