tmf: Bug 490400: Leaking widgets due to incorrect cleanup in dispose()
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / viewers / table / TmfSimpleTableViewer.java
CommitLineData
853beb54 1/*******************************************************************************
25033fef 2 * Copyright (c) 2015, 2016 Ericsson
853beb54
MK
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Alexandre Montplaisir - Initial API and implementation
11 * Matthew Khouzam - Initial API and implementation
12 *******************************************************************************/
13
14package org.eclipse.tracecompass.tmf.ui.viewers.table;
15
c8688c7f
AM
16import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
17import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString;
18
19import java.util.Collections;
8b4318bb 20import java.util.Comparator;
853beb54 21
c8688c7f
AM
22import org.eclipse.jdt.annotation.NonNull;
23import org.eclipse.jdt.annotation.Nullable;
d857b6bf
BH
24import org.eclipse.jface.action.IMenuListener;
25import org.eclipse.jface.action.IMenuManager;
26import org.eclipse.jface.action.MenuManager;
853beb54
MK
27import org.eclipse.jface.viewers.ColumnLabelProvider;
28import org.eclipse.jface.viewers.IContentProvider;
c8688c7f 29import org.eclipse.jface.viewers.ILabelProvider;
d857b6bf
BH
30import org.eclipse.jface.viewers.ISelection;
31import org.eclipse.jface.viewers.IStructuredSelection;
853beb54
MK
32import org.eclipse.jface.viewers.TableViewer;
33import org.eclipse.jface.viewers.TableViewerColumn;
c8688c7f 34import org.eclipse.jface.viewers.Viewer;
853beb54
MK
35import org.eclipse.jface.viewers.ViewerCell;
36import org.eclipse.jface.viewers.ViewerComparator;
c8688c7f 37import org.eclipse.jface.viewers.deferred.DeferredContentProvider;
853beb54
MK
38import org.eclipse.swt.SWT;
39import org.eclipse.swt.events.MouseAdapter;
40import org.eclipse.swt.events.MouseEvent;
41import org.eclipse.swt.events.SelectionAdapter;
42import org.eclipse.swt.events.SelectionEvent;
853beb54
MK
43import org.eclipse.swt.graphics.Point;
44import org.eclipse.swt.widgets.Control;
d857b6bf 45import org.eclipse.swt.widgets.Menu;
853beb54
MK
46import org.eclipse.swt.widgets.Table;
47import org.eclipse.swt.widgets.TableColumn;
48import org.eclipse.tracecompass.tmf.ui.viewers.TmfViewer;
49
50/**
c8688c7f
AM
51 * Generic {@link TableViewer} wrapper with most standard features enabled.
52 * <p>
53 * It provides the following features: <br>
54 * - Sortable columns <br>
55 * - Movable columns <br>
56 * - Resizable columns <br>
57 * - Tracking last clicked columns
58 * <p>
59 * The user of this class should add columns to the table by using the
60 * {@link #createColumn(String, ColumnLabelProvider, Comparator)} method, and
61 * set the content provider and input on the supplied {@link TableViewer}.
853beb54 62 *
0336f981 63 * @since 1.1
853beb54
MK
64 */
65public class TmfSimpleTableViewer extends TmfViewer {
66
c8688c7f
AM
67 /**
68 * Viewer comparator that ignores the element label strings and uses the
69 * given comparator to compare the elements directly.
70 */
ed493a07 71 private static class ElementComparator<T> extends ViewerComparator {
c8688c7f 72
ed493a07
PT
73 private Comparator<T> elementComparator;
74
75 public ElementComparator(Comparator<T> comparator) {
76 elementComparator = comparator;
c8688c7f
AM
77 }
78
ed493a07 79 @SuppressWarnings("unchecked")
c8688c7f
AM
80 @Override
81 public int compare(Viewer viewer, Object e1, Object e2) {
ed493a07 82 return elementComparator.compare((T) e1, (T) e2);
c8688c7f
AM
83 }
84 }
85
86 /**
87 * Comparator that compares the text of a column given by the label
88 * provider, using the text's String ordering.
89 */
90 private static class ColumnLabelComparator implements Comparator<Object> {
91 private final ILabelProvider fLabelProvider;
92
93 public ColumnLabelComparator(ILabelProvider labelProvider) {
94 fLabelProvider = labelProvider;
95 }
96
97 @Override
98 public int compare(Object o1, Object o2) {
99 String s1 = nullToEmptyString(fLabelProvider.getText(o1));
100 String s2 = nullToEmptyString(fLabelProvider.getText(o2));
101 return s1.compareTo(s2);
102 }
103 }
104
853beb54
MK
105 private final class MouseColumnListener extends MouseAdapter {
106 @Override
107 public void mouseDown(MouseEvent e) {
108 ViewerCell cell = fTableViewer.getCell(new Point(e.x, e.y));
109 fSelectedColumn = (cell != null) ? cell.getColumnIndex() : -1;
110 }
111 }
112
ed493a07 113 private final class ColumnSorter<T> extends SelectionAdapter {
c8688c7f 114 private final @NonNull TableColumn fColumn;
ed493a07 115 private final @NonNull Comparator<T> fComparator;
853beb54 116
ed493a07 117 private ColumnSorter(@NonNull TableColumn column, @NonNull Comparator<T> comparator) {
853beb54 118 fColumn = column;
c8688c7f 119 fComparator = comparator;
853beb54
MK
120 }
121
122 @Override
123 public void widgetSelected(SelectionEvent e) {
853beb54 124 Table table = fTableViewer.getTable();
853beb54
MK
125 TableColumn prevSortcolumn = table.getSortColumn();
126 if (prevSortcolumn == fColumn) {
127 flipSortDirection();
128 }
8b4318bb 129 table.setSortDirection(fDirection);
853beb54 130 table.setSortColumn(fColumn);
ed493a07 131 Comparator<T> comparator;
853beb54 132 if (fDirection == SWT.DOWN) {
c8688c7f 133 comparator = fComparator;
853beb54 134 } else {
c8688c7f
AM
135 comparator = checkNotNull(Collections.reverseOrder(fComparator));
136 }
137 IContentProvider contentProvider = fTableViewer.getContentProvider();
138 if (contentProvider instanceof DeferredContentProvider) {
139 DeferredContentProvider deferredContentProvider = (DeferredContentProvider) contentProvider;
140 deferredContentProvider.setSortOrder(comparator);
e332c612
FLN
141 } else if (contentProvider instanceof ISortingLazyContentProvider) {
142 ISortingLazyContentProvider sortingLazyContentProvider = (ISortingLazyContentProvider) contentProvider;
143 sortingLazyContentProvider.setSortOrder(comparator);
c8688c7f 144 } else {
ed493a07 145 fTableViewer.setComparator(new ElementComparator<>(comparator));
853beb54 146 }
853beb54 147 }
853beb54
MK
148 }
149
150 private static final int DEFAULT_COL_WIDTH = 200;
151 private final TableViewer fTableViewer;
853beb54
MK
152
153 private int fDirection;
154 private int fSelectedColumn;
155
d857b6bf
BH
156 private MenuManager fTablePopupMenuManager;
157
853beb54
MK
158 /**
159 * Constructor that initializes the parent of the viewer
160 *
161 * @param table
162 * the {@link TableViewer} to wrap
163 */
164 public TmfSimpleTableViewer(TableViewer table) {
165 super(table.getControl().getParent());
166 fTableViewer = table;
853beb54
MK
167
168 final Table tableControl = fTableViewer.getTable();
169 tableControl.setHeaderVisible(true);
170 tableControl.setLinesVisible(true);
171
172 fDirection = SWT.DOWN;
173 fTableViewer.setUseHashlookup(true);
174 fTableViewer.getControl().addMouseListener(new MouseColumnListener());
d857b6bf
BH
175
176 fTablePopupMenuManager = new MenuManager();
177 fTablePopupMenuManager.setRemoveAllWhenShown(true);
178
179 fTablePopupMenuManager.addMenuListener(new IMenuListener() {
180 @Override
181 public void menuAboutToShow(final @Nullable IMenuManager manager) {
182 TableViewer viewer = getTableViewer();
183 ISelection selection = viewer.getSelection();
184 if (selection instanceof IStructuredSelection) {
185 IStructuredSelection sel = (IStructuredSelection) selection;
186 if (manager != null) {
187 appendToTablePopupMenu(manager, sel);
188 }
189 }
190 }
191 });
192
193 Menu tablePopup = fTablePopupMenuManager.createContextMenu(getTableViewer().getTable());
194 getTableViewer().getTable().setMenu(tablePopup);
25033fef
PT
195
196 tableControl.addDisposeListener((e) -> {
197 internalDispose();
198 });
d857b6bf
BH
199 }
200
201 @Override
202 public void dispose() {
b3ddb2d0
AM
203 if (fTableViewer != null) {
204 fTableViewer.getControl().dispose();
205 }
25033fef
PT
206 }
207
208 private void internalDispose() {
d857b6bf
BH
209 if (fTablePopupMenuManager != null) {
210 fTablePopupMenuManager.dispose();
211 }
212 super.dispose();
213 }
214
215 /**
216 * Method to add commands to the context sensitive menu.
217 * @param manager
218 * the menu manager
219 * @param sel
220 * the current selection
5dd0ebfe 221 * @since 2.0
d857b6bf
BH
222 */
223 protected void appendToTablePopupMenu(@NonNull IMenuManager manager, @NonNull IStructuredSelection sel) {
853beb54
MK
224 }
225
226 /**
c8688c7f
AM
227 * Create a column for the table. The column will have a default width set,
228 * and will be resizable, moveable and sortable.
853beb54
MK
229 *
230 * @param name
c8688c7f 231 * the name of the column
853beb54 232 * @param provider
c8688c7f
AM
233 * the label provider of the column
234 * @param comparator
853beb54 235 * the comparator associated with clicking on the column, if it
c8688c7f
AM
236 * is null, a string comparator on the label will be used
237 * @return the column that was created
5dd0ebfe 238 * @since 2.0
853beb54 239 */
ed493a07 240 public final <T> TableColumn createColumn(String name, ColumnLabelProvider provider, @Nullable Comparator<T> comparator) {
853beb54
MK
241 TableViewerColumn col = new TableViewerColumn(fTableViewer, SWT.NONE);
242 col.setLabelProvider(provider);
243 final TableColumn column = col.getColumn();
244 column.setWidth(DEFAULT_COL_WIDTH);
245 column.setText(name);
246 column.setResizable(true);
247 column.setMoveable(true);
c8688c7f 248 if (comparator == null) {
ed493a07 249 column.addSelectionListener(new ColumnSorter<>(column, new ColumnLabelComparator(provider)));
c8688c7f 250 } else {
ed493a07 251 column.addSelectionListener(new ColumnSorter<>(column, comparator));
c8688c7f
AM
252 }
253 return column;
853beb54
MK
254 }
255
8b4318bb
FLN
256 /**
257 * Reverse the sort direction
258 */
853beb54
MK
259 private void flipSortDirection() {
260 if (fDirection == SWT.DOWN) {
261 fDirection = SWT.UP;
262 } else {
263 fDirection = SWT.DOWN;
264 }
853beb54
MK
265 }
266
853beb54
MK
267 @Override
268 public final Control getControl() {
269 return fTableViewer.getControl();
270 }
271
272 /**
273 * Gets the wrapped table viewer
274 *
275 * @return the table viewer
276 */
277 public final TableViewer getTableViewer() {
278 return fTableViewer;
279 }
280
281 /**
282 * Get the selected column index
283 *
284 * @return the selected column index or -1
285 */
286 public final int getColumnIndex() {
287 return fSelectedColumn;
288 }
289
290 @Override
291 public final void refresh() {
292 fTableViewer.refresh();
293 }
8b4318bb 294}
This page took 0.052338 seconds and 5 git commands to generate.