1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
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
10 * Alexandre Montplaisir - Initial API and implementation
11 * Matthew Khouzam - Initial API and implementation
12 *******************************************************************************/
14 package org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.table
;
16 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
17 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.nullToEmptyString
;
19 import java
.util
.Collections
;
20 import java
.util
.Comparator
;
22 import org
.eclipse
.jdt
.annotation
.NonNull
;
23 import org
.eclipse
.jdt
.annotation
.Nullable
;
24 import org
.eclipse
.jface
.action
.IMenuListener
;
25 import org
.eclipse
.jface
.action
.IMenuManager
;
26 import org
.eclipse
.jface
.action
.MenuManager
;
27 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
28 import org
.eclipse
.jface
.viewers
.IContentProvider
;
29 import org
.eclipse
.jface
.viewers
.ILabelProvider
;
30 import org
.eclipse
.jface
.viewers
.ISelection
;
31 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
32 import org
.eclipse
.jface
.viewers
.TableViewer
;
33 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
34 import org
.eclipse
.jface
.viewers
.Viewer
;
35 import org
.eclipse
.jface
.viewers
.ViewerCell
;
36 import org
.eclipse
.jface
.viewers
.ViewerComparator
;
37 import org
.eclipse
.jface
.viewers
.deferred
.DeferredContentProvider
;
38 import org
.eclipse
.swt
.SWT
;
39 import org
.eclipse
.swt
.events
.MouseAdapter
;
40 import org
.eclipse
.swt
.events
.MouseEvent
;
41 import org
.eclipse
.swt
.events
.SelectionAdapter
;
42 import org
.eclipse
.swt
.events
.SelectionEvent
;
43 import org
.eclipse
.swt
.graphics
.Point
;
44 import org
.eclipse
.swt
.widgets
.Control
;
45 import org
.eclipse
.swt
.widgets
.Menu
;
46 import org
.eclipse
.swt
.widgets
.Table
;
47 import org
.eclipse
.swt
.widgets
.TableColumn
;
48 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.TmfViewer
;
51 * Generic {@link TableViewer} wrapper with most standard features enabled.
53 * It provides the following features: <br>
54 * - Sortable columns <br>
55 * - Movable columns <br>
56 * - Resizable columns <br>
57 * - Tracking last clicked columns
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}.
65 public class TmfSimpleTableViewer
extends TmfViewer
{
68 * Viewer comparator that ignores the element label strings and uses the
69 * given comparator to compare the elements directly.
71 private static class ElementComparator
<T
> extends ViewerComparator
{
73 private Comparator
<T
> elementComparator
;
75 public ElementComparator(Comparator
<T
> comparator
) {
76 elementComparator
= comparator
;
79 @SuppressWarnings("unchecked")
81 public int compare(Viewer viewer
, Object e1
, Object e2
) {
82 return elementComparator
.compare((T
) e1
, (T
) e2
);
87 * Comparator that compares the text of a column given by the label
88 * provider, using the text's String ordering.
90 private static class ColumnLabelComparator
implements Comparator
<Object
> {
91 private final ILabelProvider fLabelProvider
;
93 public ColumnLabelComparator(ILabelProvider labelProvider
) {
94 fLabelProvider
= labelProvider
;
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
);
105 private final class MouseColumnListener
extends MouseAdapter
{
107 public void mouseDown(MouseEvent e
) {
108 ViewerCell cell
= fTableViewer
.getCell(new Point(e
.x
, e
.y
));
109 fSelectedColumn
= (cell
!= null) ? cell
.getColumnIndex() : -1;
113 private final class ColumnSorter
<T
> extends SelectionAdapter
{
114 private final @NonNull TableColumn fColumn
;
115 private final @NonNull Comparator
<T
> fComparator
;
117 private ColumnSorter(@NonNull TableColumn column
, @NonNull Comparator
<T
> comparator
) {
119 fComparator
= comparator
;
123 public void widgetSelected(SelectionEvent e
) {
124 Table table
= fTableViewer
.getTable();
125 TableColumn prevSortcolumn
= table
.getSortColumn();
126 if (prevSortcolumn
== fColumn
) {
129 table
.setSortDirection(fDirection
);
130 table
.setSortColumn(fColumn
);
131 Comparator
<T
> comparator
;
132 if (fDirection
== SWT
.DOWN
) {
133 comparator
= fComparator
;
135 comparator
= checkNotNull(Collections
.reverseOrder(fComparator
));
137 IContentProvider contentProvider
= fTableViewer
.getContentProvider();
138 if (contentProvider
instanceof DeferredContentProvider
) {
139 DeferredContentProvider deferredContentProvider
= (DeferredContentProvider
) contentProvider
;
140 deferredContentProvider
.setSortOrder(comparator
);
141 } else if (contentProvider
instanceof ISortingLazyContentProvider
) {
142 ISortingLazyContentProvider sortingLazyContentProvider
= (ISortingLazyContentProvider
) contentProvider
;
143 sortingLazyContentProvider
.setSortOrder(comparator
);
145 fTableViewer
.setComparator(new ElementComparator
<>(comparator
));
150 private static final int DEFAULT_COL_WIDTH
= 200;
151 private final TableViewer fTableViewer
;
153 private int fDirection
;
154 private int fSelectedColumn
;
156 private MenuManager fTablePopupMenuManager
;
159 * Constructor that initializes the parent of the viewer
162 * the {@link TableViewer} to wrap
164 public TmfSimpleTableViewer(TableViewer table
) {
165 super(table
.getControl().getParent());
166 fTableViewer
= table
;
168 final Table tableControl
= fTableViewer
.getTable();
169 tableControl
.setHeaderVisible(true);
170 tableControl
.setLinesVisible(true);
172 fDirection
= SWT
.DOWN
;
173 fTableViewer
.setUseHashlookup(true);
174 fTableViewer
.getControl().addMouseListener(new MouseColumnListener());
176 fTablePopupMenuManager
= new MenuManager();
177 fTablePopupMenuManager
.setRemoveAllWhenShown(true);
179 fTablePopupMenuManager
.addMenuListener(new IMenuListener() {
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
);
193 Menu tablePopup
= fTablePopupMenuManager
.createContextMenu(getTableViewer().getTable());
194 getTableViewer().getTable().setMenu(tablePopup
);
198 public void dispose() {
199 if (fTableViewer
!= null) {
200 fTableViewer
.getControl().dispose();
202 if (fTablePopupMenuManager
!= null) {
203 fTablePopupMenuManager
.dispose();
209 * Method to add commands to the context sensitive menu.
213 * the current selection
216 protected void appendToTablePopupMenu(@NonNull IMenuManager manager
, @NonNull IStructuredSelection sel
) {
220 * Create a column for the table. The column will have a default width set,
221 * and will be resizable, moveable and sortable.
224 * the name of the column
226 * the label provider of the column
228 * the comparator associated with clicking on the column, if it
229 * is null, a string comparator on the label will be used
230 * @return the column that was created
233 public final <T
> TableColumn
createColumn(String name
, ColumnLabelProvider provider
, @Nullable Comparator
<T
> comparator
) {
234 TableViewerColumn col
= new TableViewerColumn(fTableViewer
, SWT
.NONE
);
235 col
.setLabelProvider(provider
);
236 final TableColumn column
= col
.getColumn();
237 column
.setWidth(DEFAULT_COL_WIDTH
);
238 column
.setText(name
);
239 column
.setResizable(true);
240 column
.setMoveable(true);
241 if (comparator
== null) {
242 column
.addSelectionListener(new ColumnSorter
<>(column
, new ColumnLabelComparator(provider
)));
244 column
.addSelectionListener(new ColumnSorter
<>(column
, comparator
));
250 * Reverse the sort direction
252 private void flipSortDirection() {
253 if (fDirection
== SWT
.DOWN
) {
256 fDirection
= SWT
.DOWN
;
261 public final Control
getControl() {
262 return fTableViewer
.getControl();
266 * Gets the wrapped table viewer
268 * @return the table viewer
270 public final TableViewer
getTableViewer() {
275 * Get the selected column index
277 * @return the selected column index or -1
279 public final int getColumnIndex() {
280 return fSelectedColumn
;
284 public final void refresh() {
285 fTableViewer
.refresh();