1 /*******************************************************************************
2 * Copyright (c) 2010 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 * Matthew Khouzam - Initial API and implementation
11 * Francois Chouinard - Refactoring, slider support, bug fixing
12 ******************************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.ui
.widgets
;
16 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
17 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalManager
;
18 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfTimeSynchSignal
;
19 import org
.eclipse
.swt
.SWT
;
20 import org
.eclipse
.swt
.events
.ControlAdapter
;
21 import org
.eclipse
.swt
.events
.ControlEvent
;
22 import org
.eclipse
.swt
.events
.KeyEvent
;
23 import org
.eclipse
.swt
.events
.KeyListener
;
24 import org
.eclipse
.swt
.events
.MouseEvent
;
25 import org
.eclipse
.swt
.events
.MouseWheelListener
;
26 import org
.eclipse
.swt
.events
.SelectionAdapter
;
27 import org
.eclipse
.swt
.events
.SelectionEvent
;
28 import org
.eclipse
.swt
.layout
.GridData
;
29 import org
.eclipse
.swt
.layout
.GridLayout
;
30 import org
.eclipse
.swt
.widgets
.Composite
;
31 import org
.eclipse
.swt
.widgets
.Event
;
32 import org
.eclipse
.swt
.widgets
.Listener
;
33 import org
.eclipse
.swt
.widgets
.Slider
;
34 import org
.eclipse
.swt
.widgets
.Table
;
35 import org
.eclipse
.swt
.widgets
.TableColumn
;
36 import org
.eclipse
.swt
.widgets
.TableItem
;
39 * <b><u>TmfVirtualTable</u></b>
41 * TmfVirtualTable allows for the tabular display of arbitrarily large data sets
42 * (well, up to Integer.MAX_VALUE or ~2G rows).
44 * It is essentially a Composite of Table and Slider, where the number of rows
45 * in the table is set to fill the table display area. The slider is rank-based.
47 * It differs from Table with the VIRTUAL style flag where an empty entry is
48 * created for each virtual row. This does not scale well for very large data sets.
50 public class TmfVirtualTable
extends Composite
{
54 private int fTableRows
= 0; // Number of table rows
55 private boolean fPartialRowVisible
= false; // Indicates that a row is partially displayed
56 private int fSelectedRow
= 0; // Currently selected row in the table
58 private int fTableTopEventRank
= 0; // Global rank of the first entry displayed
59 private int fSelectedEventRank
= 0; // Global rank of the selected event
61 private TableItem fSelectedItems
[] = new TableItem
[1];
62 private int fTableItemCount
= 0;
63 private TableItem fTableItems
[];
66 private Slider fSlider
;
68 // ------------------------------------------------------------------------
70 // ------------------------------------------------------------------------
76 public TmfVirtualTable(Composite parent
, int style
) {
77 super(parent
, style
| SWT
.BORDER
& (~SWT
.H_SCROLL
) & (~SWT
.V_SCROLL
));
79 // Create the controls
84 GridLayout gridLayout
= new GridLayout();
85 gridLayout
.numColumns
= 2;
86 gridLayout
.horizontalSpacing
= 0;
87 gridLayout
.verticalSpacing
= 0;
88 gridLayout
.marginWidth
= 0;
89 gridLayout
.marginHeight
= 0;
90 setLayout(gridLayout
);
92 GridData tableGridData
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
93 fTable
.setLayoutData(tableGridData
);
95 GridData sliderGridData
= new GridData(SWT
.FILL
, SWT
.FILL
, false, true);
96 fSlider
.setLayoutData(sliderGridData
);
99 fTable
.addMouseWheelListener(new MouseWheelListener() {
101 public void mouseScrolled(MouseEvent event
) {
102 fTableTopEventRank
-= event
.count
;
103 if (fTableTopEventRank
< 0) {
104 fTableTopEventRank
= 0;
106 int latestFirstRowOffset
= fTableItemCount
- fTableRows
;
107 if (fTableTopEventRank
> latestFirstRowOffset
) {
108 fTableTopEventRank
= latestFirstRowOffset
;
111 fSlider
.setSelection(fTableTopEventRank
);
116 addControlListener(new ControlAdapter() {
118 public void controlResized(ControlEvent event
) {
127 // ------------------------------------------------------------------------
129 // ------------------------------------------------------------------------
132 * Create the table and add listeners
134 private void createTable(int style
) {
136 // int tableStyle = SWT.NO_SCROLL | SWT.H_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION;
137 int tableStyle
= SWT
.NO_SCROLL
| SWT
.SINGLE
| SWT
.FULL_SELECTION
;
138 fTable
= new Table(this, tableStyle
);
140 fTable
.addSelectionListener(new SelectionAdapter() {
142 public void widgetSelected(SelectionEvent event
) {
143 handleTableSelection();
147 fTable
.addKeyListener(new KeyListener() {
149 public void keyPressed(KeyEvent event
) {
150 handleTableKeyEvent(event
);
153 public void keyReleased(KeyEvent event
) {
159 * Update the rows and selected item
161 private void handleTableSelection() {
162 fSelectedRow
= fTable
.getSelectionIndices()[0];
163 fSelectedEventRank
= fTableTopEventRank
+ fSelectedRow
;
164 fSelectedItems
[0] = fTable
.getSelection()[0];
168 * Handle key-based navigation in table.
172 private void handleTableKeyEvent(KeyEvent event
) {
174 int lastEventRank
= fTableItemCount
- 1;
175 int lastPageTopEntryRank
= fTableItemCount
- fTableRows
;
177 int lastRowIndex
= ((fTableItemCount
< fTableRows
) ? fTableItemCount
: fTableRows
) - 1;
178 int numberOfFullyVisibleRows
= fTableRows
- ((fPartialRowVisible
) ?
1 : 0);
180 boolean needsRefresh
= false;
182 // We are handling things...
185 // In all case, perform the following steps:
186 // - Update the selected entry rank (within valid range)
187 // - Update the selected row
188 // - Update the page's top entry if necessary (which also adjusts the selected row)
189 // - If the top displayed entry was changed, table refresh is needed
190 switch (event
.keyCode
) {
192 case SWT
.ARROW_DOWN
: {
193 if (fSelectedEventRank
< lastEventRank
) {
194 fSelectedEventRank
++;
195 fSelectedRow
= fSelectedEventRank
- fTableTopEventRank
;
196 if (fSelectedRow
> lastRowIndex
) {
197 fTableTopEventRank
++;
198 fSelectedRow
= lastRowIndex
;
206 if (fSelectedEventRank
> 0) {
207 fSelectedEventRank
--;
208 fSelectedRow
= fSelectedEventRank
- fTableTopEventRank
;
209 if (fSelectedRow
< 0) {
210 fTableTopEventRank
--;
219 fTableTopEventRank
= lastPageTopEntryRank
;
220 fSelectedEventRank
= lastEventRank
;
221 fSelectedRow
= lastRowIndex
;
227 fSelectedEventRank
= 0;
229 fTableTopEventRank
= 0;
234 case SWT
.PAGE_DOWN
: {
235 if (fSelectedEventRank
< lastEventRank
) {
236 fSelectedEventRank
+= numberOfFullyVisibleRows
;
237 if (fSelectedEventRank
> lastEventRank
) {
238 fSelectedEventRank
= lastEventRank
;
240 fSelectedRow
= fSelectedEventRank
- fTableTopEventRank
;
241 if (fSelectedRow
> numberOfFullyVisibleRows
- 1) {
242 fTableTopEventRank
+= numberOfFullyVisibleRows
;
243 if (fTableTopEventRank
> lastPageTopEntryRank
) {
244 fTableTopEventRank
= lastPageTopEntryRank
;
246 fSelectedRow
= fSelectedEventRank
- fTableTopEventRank
;
254 if (fSelectedEventRank
> 0) {
255 fSelectedEventRank
-= numberOfFullyVisibleRows
;
256 if (fSelectedEventRank
< 0) {
257 fSelectedEventRank
= 0;
259 fSelectedRow
= fSelectedEventRank
- fTableTopEventRank
;
260 if (fSelectedRow
< 0) {
262 fTableTopEventRank
-= numberOfFullyVisibleRows
;
263 if (fTableTopEventRank
< 0) {
264 fTableTopEventRank
= 0;
266 fSelectedRow
= fSelectedEventRank
- fTableTopEventRank
;
275 for (int i
= 0; i
< fTableItems
.length
; i
++) {
276 setDataItem(i
, fTableItems
[i
]);
280 notifyUpdatedSelection();
281 // fTable.showSelection();
285 private void setDataItem(int index
, TableItem item
) {
287 Event event
= new Event();
289 event
.index
= index
+ fTableTopEventRank
;
291 notifyListeners(SWT
.SetData
, event
);
295 public void notifyUpdatedSelection() {
296 fSlider
.setSelection(fTableTopEventRank
+ fSelectedRow
);
297 setSelectedRowVisibility();
298 TableItem
[] tableSelection
= fTable
.getSelection();
299 if (tableSelection
.length
> 0 && tableSelection
[0] != null) {
300 fSelectedItems
[0] = tableSelection
[0];
301 TmfTimestamp ts
= (TmfTimestamp
) fSelectedItems
[0].getData();
302 TmfSignalManager
.dispatchSignal(new TmfTimeSynchSignal(this, ts
));
306 // ------------------------------------------------------------------------
308 // ------------------------------------------------------------------------
310 private void createSlider() {
311 fSlider
= new Slider(this, SWT
.VERTICAL
);
312 fSlider
.setMinimum(0);
313 fSlider
.setMaximum(0);
315 fSlider
.addListener(SWT
.Selection
, new Listener() {
317 public void handleEvent(Event event
) {
318 switch (event
.detail
) {
326 fTableTopEventRank
= fSlider
.getSelection();
335 // ------------------------------------------------------------------------
336 // Simulated Table API
337 // ------------------------------------------------------------------------
339 public void setHeaderVisible(boolean b
) {
340 fTable
.setHeaderVisible(b
);
343 public void setLinesVisible(boolean b
) {
344 fTable
.setLinesVisible(b
);
347 public TableItem
[] getSelection() {
348 return fSelectedItems
;
351 public void addSelectionListener(SelectionAdapter sa
) {
352 fTable
.addSelectionListener(sa
);
355 public void setItemCount(int nbItems
) {
356 nbItems
= Math
.max(0, nbItems
);
357 if (nbItems
!= fTableItemCount
) {
358 fTableItemCount
= nbItems
;
359 fSlider
.setMaximum(nbItems
);
364 public int getItemHeight() {
365 return fTable
.getItemHeight();
368 public int getTopIndex() {
369 return fTableTopEventRank
;
372 public void setTopIndex(int i
) {
373 fSlider
.setSelection(i
);
376 public int indexOf(TableItem ti
) {
377 return fTable
.indexOf(ti
) + getTopIndex();
380 public TableColumn
[] getColumns() {
381 return fTable
.getColumns();
384 private void resize() {
386 // Compute the numbers of rows that fit the new area
387 int tableHeight
= fTable
.getClientArea().height
- fTable
.getHeaderHeight();
389 if (tableHeight
< 0) tableHeight
= 0;
390 int itemHeight
= fTable
.getItemHeight();
391 fTableRows
= tableHeight
/ itemHeight
;
392 fPartialRowVisible
= false;
393 if (fTableRows
* itemHeight
< tableHeight
) {
394 fTableRows
++; // For partial rows
395 fPartialRowVisible
= true;
397 if (fTableRows
> fTableItemCount
) {
398 fTableRows
= fTableItemCount
;
401 // If we are at the end, get elements before to populate
402 if (fTableTopEventRank
+ fTableRows
>= fTableItemCount
) {
403 fTableTopEventRank
= fTableItemCount
- fTableRows
;
406 // Set the slider thumb size
407 if (fTableItemCount
> 0) {
408 fSlider
.setThumb(fTableRows
);
411 // Re-size and re-create the virtual table if needed
412 int delta
= fTable
.getItemCount() - fTableRows
;
415 if (fTableItems
!= null) {
416 for (int i
= 0; i
< fTableItems
.length
; i
++) {
417 if (fTableItems
[i
] != null) {
418 fTableItems
[i
].dispose();
420 fTableItems
[i
] = null;
423 fTableItems
= new TableItem
[fTableRows
];
424 for (int i
= 0; i
< fTableItems
.length
; i
++) {
425 fTableItems
[i
] = new TableItem(fTable
, i
);
432 // ------------------------------------------------------------------------
433 // Controls interactions
434 // ------------------------------------------------------------------------
437 public boolean setFocus() {
438 boolean isVisible
= isVisible();
445 public void refresh() {
449 public void setColumnHeaders(ColumnData columnData
[]) {
450 for (int i
= 0; i
< columnData
.length
; i
++) {
451 TableColumn column
= new TableColumn(fTable
, columnData
[i
].alignment
, i
);
452 column
.setText(columnData
[i
].header
);
453 if (columnData
[i
].width
> 0) {
454 column
.setWidth(columnData
[i
].width
);
461 public int removeAll() {
462 fSlider
.setMaximum(0);
467 private void refreshTable() {
468 setSelectedRowVisibility();
470 for (int i
= 0; i
< fTableRows
; i
++) {
471 setDataItem(i
, fTableItems
[i
]);
475 private void setSelectedRowVisibility() {
476 int lastRowOffset
= fTableTopEventRank
+ fTableRows
- 1;
477 if ((fSelectedEventRank
>= fTableTopEventRank
) && (fSelectedEventRank
<= lastRowOffset
)) {
478 fSelectedRow
= fSelectedEventRank
- fTableTopEventRank
;
479 fTable
.setSelection(fSelectedRow
);
481 fTable
.deselect(fSelectedRow
);
485 public void setSelection(int i
) {
486 if (fTableItems
!= null) {
487 i
= Math
.min(i
, fTableItemCount
);
489 fSlider
.setSelection(i
);
491 fSelectedEventRank
= i
;
492 fTableTopEventRank
= i
- (fTableRows
/ 2);
493 if (fTableTopEventRank
< 0) {
494 fTableTopEventRank
= 0;
496 fSelectedRow
= fSelectedEventRank
- fTableTopEventRank
;
This page took 0.042107 seconds and 6 git commands to generate.