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