]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.ui.workbench/src/org/simantics/utils/ui/workbench/ui/TreeColumnSorter.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.utils.ui.workbench / src / org / simantics / utils / ui / workbench / ui / TreeColumnSorter.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 /*\r
13  * 4.7.2006\r
14  */\r
15 package org.simantics.utils.ui.workbench.ui;\r
16 \r
17 import java.util.Comparator;\r
18 import java.util.HashMap;\r
19 import java.util.Map;\r
20 \r
21 import org.eclipse.jface.viewers.IBaseLabelProvider;\r
22 import org.eclipse.jface.viewers.ITableLabelProvider;\r
23 import org.eclipse.jface.viewers.TreeViewer;\r
24 import org.eclipse.jface.viewers.Viewer;\r
25 import org.eclipse.jface.viewers.ViewerSorter;\r
26 import org.eclipse.swt.events.SelectionAdapter;\r
27 import org.eclipse.swt.events.SelectionEvent;\r
28 import org.eclipse.swt.widgets.TreeColumn;\r
29 import org.eclipse.ui.IMemento;\r
30 \r
31 /**\r
32  * This class adds column sorting functionality to SWT Tree widget.\r
33  * <p>\r
34  * Attach this Sorter after you have created all columns.\r
35  * <p>\r
36  * Usage: TreeColumnSorter.attachTreeColumnSorter(myTree);\r
37  * \r
38  * @author Toni Kalajainen\r
39  */\r
40 public class TreeColumnSorter {\r
41 \r
42     /** The tree */\r
43     protected final TreeViewer viewer;\r
44     \r
45     /** the sorter */\r
46     protected final ColumnSorter sorter;\r
47     \r
48     /** column specific comparators*/\r
49     protected Map<Integer, Comparator<?>> columnComparators = \r
50         new HashMap<Integer, Comparator<?>>();\r
51     \r
52     public static TreeColumnSorter attachTreeColumnSorter(TreeViewer viewer) {\r
53         return new TreeColumnSorter(viewer);\r
54     }\r
55     \r
56     public static void unattachTreeColumnSorter(TreeViewer viewer) {\r
57         viewer.setSorter(null);\r
58     }\r
59     \r
60     private TreeColumnSorter(TreeViewer viewer) {\r
61         this.viewer = viewer;\r
62         this.sorter = new ColumnSorter();\r
63         \r
64         // Attach columns\r
65         TreeColumn columns[] = viewer.getTree().getColumns(); \r
66         for(int i=0; i<columns.length; i++) {\r
67             TreeColumn column = columns[i];\r
68             column.setData("index", new Integer(i));\r
69             column.addSelectionListener(new SelectionAdapter() {\r
70                 public void widgetSelected(SelectionEvent e) {                    \r
71                     int index = (Integer) e.widget.getData("index");\r
72                     if (index == TreeColumnSorter.this.sorter.getIndex()) {\r
73                         // Reverse order\r
74                         TreeColumnSorter.this.sorter.setAscending( !TreeColumnSorter.this.sorter.isAscending() );\r
75                     } else {\r
76                         TreeColumnSorter.this.sorter.setSecondaryIndex( TreeColumnSorter.this.sorter.getIndex() );\r
77                         TreeColumnSorter.this.sorter.setSecondaryAscending( TreeColumnSorter.this.sorter.isAscending() );\r
78                         TreeColumnSorter.this.sorter.setIndex(index);\r
79                         TreeColumnSorter.this.sorter.setAscending(true);\r
80                     }\r
81                     TreeColumnSorter.this.viewer.refresh();\r
82                 }\r
83             });\r
84         }\r
85         viewer.setSorter(sorter);\r
86     }\r
87     \r
88     public void setColumnComparator(int index, Comparator<?> comparator)\r
89     {\r
90         columnComparators.put(index, comparator);\r
91         viewer.refresh();\r
92     }\r
93     \r
94     public void setColumnAscending(int index)\r
95     {\r
96         sorter.setIndex(index);\r
97         sorter.setAscending(true);\r
98         viewer.refresh();\r
99     }\r
100     \r
101     private final static String PRI_ASC = "TPriAsc";\r
102     private final static String SEC_ASC = "TSecAsc";\r
103     private final static String PRI_IND = "TPriInd";\r
104     private final static String SEC_IND = "TSecInd";    \r
105     \r
106     public void saveState(String id, IMemento memento) {\r
107         memento.putInteger(id+PRI_ASC, sorter.isAscending()?1:0);\r
108         memento.putInteger(id+SEC_ASC, sorter.isSecondaryAscending()?1:0);        \r
109         memento.putInteger(id+PRI_IND, sorter.getIndex());\r
110         memento.putInteger(id+SEC_IND, sorter.getSecondaryIndex());\r
111     }\r
112 \r
113     public void restoreState(String id, IMemento memento) {\r
114         if (!hasState(id, memento)) return;\r
115             \r
116         sorter.setAscending( memento.getInteger(id+PRI_ASC)==1 );\r
117         sorter.setSecondaryAscending( memento.getInteger(id+SEC_ASC)==1 );\r
118         sorter.setIndex( memento.getInteger(id+PRI_IND) );\r
119         sorter.setSecondaryIndex( memento.getInteger(id+SEC_IND) );\r
120         \r
121         viewer.refresh();\r
122     }\r
123     \r
124     public boolean hasState(String id, IMemento memento) {\r
125         return (memento.getInteger(id+PRI_ASC)==null) && \r
126                (memento.getInteger(id+SEC_ASC)==null) && \r
127                (memento.getInteger(id+PRI_IND)==null) && \r
128                (memento.getInteger(id+SEC_IND)==null); \r
129     } \r
130     \r
131     class ColumnSorter extends ViewerSorter {\r
132         /** Sort direction */\r
133         private boolean ascending = true;\r
134         /** Secondary Sort direction */\r
135         private boolean secondaryAscending = true;\r
136         /** Sort column */\r
137         private int columnIndex = 0;\r
138         /** Secondary sort column */\r
139         private int secondaryColumnIndex = -1;\r
140         /** case sensitive */\r
141         private boolean caseSensitive = false;\r
142         \r
143         public void setAscending(boolean ascending) {\r
144             this.ascending = ascending;\r
145         }\r
146                 \r
147         public boolean isAscending() {\r
148             return ascending;\r
149         }        \r
150         \r
151         public void setSecondaryAscending(boolean ascending) {\r
152             this.secondaryAscending = ascending;\r
153         }\r
154                 \r
155         public boolean isSecondaryAscending() {\r
156             return secondaryAscending;\r
157         }        \r
158         \r
159         public void setIndex(int index) {\r
160             this.columnIndex = index;\r
161         }\r
162         \r
163         public int getIndex() {\r
164             return columnIndex;\r
165         }\r
166         \r
167         public void setSecondaryIndex(int index) {\r
168             this.secondaryColumnIndex = index;\r
169         }\r
170         \r
171         public int getSecondaryIndex() {\r
172             return secondaryColumnIndex;\r
173         }\r
174 \r
175         @SuppressWarnings("unchecked")\r
176         private int compare(int columnIndex, String text1, String text2, Object o1, Object o2)\r
177         {\r
178             @SuppressWarnings("rawtypes")\r
179             Comparator c = columnComparators.get(columnIndex);\r
180             if (c==null || o1==null || o2==null)\r
181                 return text1.compareTo(text2);\r
182             return c.compare(o1, o2);\r
183         }\r
184         \r
185         public int compare(Viewer viewer, Object e1, Object e2) {\r
186             int result = 0;\r
187             \r
188             TreeViewer v = (TreeViewer) viewer;            \r
189             IBaseLabelProvider blp = v.getLabelProvider();\r
190             if (!(blp instanceof ITableLabelProvider)) {\r
191                 return super.compare(viewer, e1, e2);\r
192             }\r
193             ITableLabelProvider tlp = (ITableLabelProvider) blp;\r
194             \r
195             // Primary sort\r
196             String text1 = tlp.getColumnText(e1, columnIndex);\r
197             String text2 = tlp.getColumnText(e2, columnIndex);\r
198             if (text1==null) text1="";\r
199             if (text2==null) text2="";            \r
200             if (!caseSensitive) {\r
201                 text1 = text1.toLowerCase();\r
202                 text2 = text2.toLowerCase();\r
203             }            \r
204             result = compare(columnIndex, text1, text2, e1, e2);\r
205             if (!ascending) return -result;\r
206             \r
207             // secondary sort\r
208             if (result==0 && (secondaryColumnIndex>=0)) {\r
209                 text1 = tlp.getColumnText(e1, secondaryColumnIndex);\r
210                 text2 = tlp.getColumnText(e2, secondaryColumnIndex);\r
211                 if (text1==null) text1="";\r
212                 if (text2==null) text2="";            \r
213                 if (!caseSensitive) {\r
214                     text1 = text1.toLowerCase();\r
215                     text2 = text2.toLowerCase();\r
216                 }            \r
217                 result = compare(secondaryColumnIndex, text1, text2, e1, e2);\r
218                 \r
219                 if (!secondaryAscending) return -result;\r
220             }\r
221             \r
222             return result;\r
223         }\r
224 \r
225         public boolean isCaseSensitive() {\r
226             return caseSensitive;\r
227         }\r
228 \r
229         public void setCaseSensitive(boolean caseSensitive) {\r
230             this.caseSensitive = caseSensitive;\r
231         }\r
232     }\r
233 \r
234     public ColumnSorter getSorter() {\r
235         return sorter;\r
236     }\r
237 \r
238 }\r