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