tmf: Add the Histogram query API to ITmfStatistics
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / widgets / virtualtable / TmfVirtualTable.java
CommitLineData
9ccc6d01
FC
1/*******************************************************************************
2 * Copyright (c) 2010 Ericsson
3934297e 3 *
9ccc6d01
FC
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
3934297e 8 *
9ccc6d01
FC
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
3934297e 11 * Francois Chouinard - Refactoring, slider support, bug fixing
b21305c2 12 * Patrick Tasse - Improvements and bug fixing
7cc11afa 13 * Xavier Raynaud - Improvements
9ccc6d01
FC
14 ******************************************************************************/
15
fb5cad3d 16package org.eclipse.linuxtools.tmf.ui.widgets.virtualtable;
9ccc6d01 17
8fd82db5 18import org.eclipse.linuxtools.internal.tmf.ui.Activator;
9ccc6d01 19import org.eclipse.swt.SWT;
b21305c2 20import org.eclipse.swt.custom.TableEditor;
9ccc6d01
FC
21import org.eclipse.swt.events.ControlAdapter;
22import org.eclipse.swt.events.ControlEvent;
23import org.eclipse.swt.events.KeyEvent;
24import org.eclipse.swt.events.KeyListener;
25import org.eclipse.swt.events.MouseEvent;
b21305c2 26import org.eclipse.swt.events.MouseListener;
9ccc6d01
FC
27import org.eclipse.swt.events.MouseWheelListener;
28import org.eclipse.swt.events.SelectionAdapter;
29import org.eclipse.swt.events.SelectionEvent;
b21305c2
FC
30import org.eclipse.swt.events.SelectionListener;
31import org.eclipse.swt.graphics.Point;
7800a42f
XR
32import org.eclipse.swt.graphics.Rectangle;
33import org.eclipse.swt.layout.FillLayout;
9ccc6d01
FC
34import org.eclipse.swt.layout.GridData;
35import org.eclipse.swt.layout.GridLayout;
36import org.eclipse.swt.widgets.Composite;
b21305c2
FC
37import org.eclipse.swt.widgets.Control;
38import org.eclipse.swt.widgets.Display;
9ccc6d01 39import org.eclipse.swt.widgets.Event;
7800a42f 40import org.eclipse.swt.widgets.Label;
9ccc6d01 41import org.eclipse.swt.widgets.Listener;
b21305c2 42import org.eclipse.swt.widgets.Menu;
7800a42f 43import org.eclipse.swt.widgets.Shell;
9ccc6d01
FC
44import org.eclipse.swt.widgets.Slider;
45import org.eclipse.swt.widgets.Table;
46import org.eclipse.swt.widgets.TableColumn;
47import org.eclipse.swt.widgets.TableItem;
7800a42f 48import org.eclipse.ui.PlatformUI;
9ccc6d01
FC
49
50/**
51 * <b><u>TmfVirtualTable</u></b>
52 * <p>
53 * TmfVirtualTable allows for the tabular display of arbitrarily large data sets
54 * (well, up to Integer.MAX_VALUE or ~2G rows).
3934297e 55 *
9ccc6d01
FC
56 * It is essentially a Composite of Table and Slider, where the number of rows
57 * in the table is set to fill the table display area. The slider is rank-based.
3934297e 58 *
9ccc6d01
FC
59 * It differs from Table with the VIRTUAL style flag where an empty entry is
60 * created for each virtual row. This does not scale well for very large data sets.
3934297e 61 *
b21305c2
FC
62 * Styles:
63 * H_SCROLL, V_SCROLL, SINGLE, CHECK, FULL_SELECTION, HIDE_SELECTION, NO_SCROLL
02023181 64 * @author Matthew Khouzam, Francois Chouinard, Patrick Tasse, Xavier Raynaud
3934297e 65 * @version $Revision: 1.0
9ccc6d01
FC
66 */
67public class TmfVirtualTable extends Composite {
68
631d853f 69 // The table
02023181
MK
70 /**
71 * Field fTable.
72 */
631d853f 73 private Table fTable;
02023181
MK
74 /**
75 * Field fTableRows.
76 */
631d853f 77 private int fTableRows = 0; // Number of table rows
02023181
MK
78 /**
79 * Field fFullyVisibleRows.
80 */
631d853f 81 private int fFullyVisibleRows = 0; // Number of fully visible table rows
02023181
MK
82 /**
83 * Field fFrozenRowCount.
84 */
631d853f
PT
85 private int fFrozenRowCount = 0; // Number of frozen table rows at top of table
86
02023181
MK
87 /**
88 * Field fTableTopEventRank.
89 */
631d853f 90 private int fTableTopEventRank = 0; // Global rank of the first entry displayed
02023181
MK
91 /**
92 * Field fSelectedEventRank.
93 */
631d853f 94 private int fSelectedEventRank = 0; // Global rank of the selected event
02023181
MK
95 /**
96 * Field fPendingSelection.
97 */
631d853f
PT
98 private boolean fPendingSelection = false; // Pending selection update
99
02023181
MK
100 /**
101 * Field fTableItemCount.
102 */
631d853f
PT
103 private int fTableItemCount = 0;
104
105 // The slider
02023181
MK
106 /**
107 * Field fSlider.
108 */
631d853f
PT
109 private Slider fSlider;
110
02023181
MK
111 /**
112 * Field fLinuxItemHeight.
113 */
631d853f 114 private int fLinuxItemHeight = 0; // Calculated item height for Linux workaround
02023181
MK
115 /**
116 * Field tooltipProvider.
117 */
631d853f 118 private TooltipProvider tooltipProvider = null;
02023181
MK
119 /**
120 * Field doubleClickListener.
121 */
631d853f
PT
122 private IDoubleClickListener doubleClickListener = null;
123
124 // ------------------------------------------------------------------------
125 // Constructor
126 // ------------------------------------------------------------------------
127
128 /**
3934297e
AM
129 * Standard constructor
130 *
631d853f 131 * @param parent
3934297e 132 * The parent composite object
631d853f 133 * @param style
3934297e 134 * The style to use
631d853f
PT
135 */
136 public TmfVirtualTable(Composite parent, int style) {
137 super(parent, style & (~SWT.H_SCROLL) & (~SWT.V_SCROLL) & (~SWT.SINGLE) & (~SWT.FULL_SELECTION) & (~SWT.HIDE_SELECTION) & (~SWT.CHECK));
138
139 // Create the controls
140 createTable(style & (SWT.H_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.HIDE_SELECTION | SWT.CHECK));
141 createSlider(style & SWT.V_SCROLL);
142
143 // Prevent the slider from being traversed
144 setTabList(new Control[] { fTable });
145
146 // Set the layout
147 GridLayout gridLayout = new GridLayout();
148 gridLayout.numColumns = 2;
149 gridLayout.horizontalSpacing = 0;
150 gridLayout.verticalSpacing = 0;
151 gridLayout.marginWidth = 0;
152 gridLayout.marginHeight = 0;
153 setLayout(gridLayout);
154
155 GridData tableGridData = new GridData(SWT.FILL, SWT.FILL, true, true);
156 fTable.setLayoutData(tableGridData);
157
158 GridData sliderGridData = new GridData(SWT.FILL, SWT.FILL, false, true);
159 fSlider.setLayoutData(sliderGridData);
160
161 // Add the listeners
162 fTable.addMouseWheelListener(new MouseWheelListener() {
163 @Override
164 public void mouseScrolled(MouseEvent event) {
165 if (fTableItemCount <= fFullyVisibleRows) {
166 return;
167 }
168 fTableTopEventRank -= event.count;
169 if (fTableTopEventRank < 0) {
170 fTableTopEventRank = 0;
171 }
172 int latestFirstRowOffset = fTableItemCount - fFullyVisibleRows;
173 if (fTableTopEventRank > latestFirstRowOffset) {
174 fTableTopEventRank = latestFirstRowOffset;
175 }
176
177 fSlider.setSelection(fTableTopEventRank);
178 refreshTable();
179 }
180 });
181
182 fTable.addListener(SWT.MouseWheel, new Listener() {
183 // disable mouse scroll of horizontal scroll bar
184 @Override
b21305c2 185 public void handleEvent(Event event) {
631d853f
PT
186 event.doit = false;
187 }
188 });
189
190 fTable.addControlListener(new ControlAdapter() {
191 @Override
192 public void controlResized(ControlEvent event) {
193 int tableHeight = Math.max(0, fTable.getClientArea().height - fTable.getHeaderHeight());
194 fFullyVisibleRows = tableHeight / getItemHeight();
195 if (fTableItemCount > 0) {
196 fSlider.setThumb(Math.max(1, Math.min(fTableRows, fFullyVisibleRows)));
197 }
198 }
199 });
200 // Implement a "fake" tooltip
201 final String TOOLTIP_DATA_KEY = "_TABLEITEM"; //$NON-NLS-1$
202 final Listener labelListener = new Listener () {
203 @Override
f4c52cea 204 public void handleEvent (Event event) {
631d853f
PT
205 Label label = (Label)event.widget;
206 Shell shell = label.getShell ();
207 switch (event.type) {
208 case SWT.MouseDown:
209 Event e = new Event ();
210 e.item = (TableItem) label.getData (TOOLTIP_DATA_KEY);
211 // Assuming table is single select, set the selection as if
212 // the mouse down event went through to the table
213 fTable.setSelection (new TableItem [] {(TableItem) e.item});
214 fTable.notifyListeners (SWT.Selection, e);
215 shell.dispose ();
216 fTable.setFocus();
217 break;
218 case SWT.MouseExit:
219 case SWT.MouseWheel:
220 shell.dispose ();
221 break;
abbdd66a
AM
222 default:
223 break;
631d853f
PT
224 }
225 }
226 };
227
228 Listener tableListener = new Listener () {
229 Shell tip = null;
230 Label label = null;
231 @Override
f4c52cea 232 public void handleEvent (Event event) {
631d853f
PT
233 switch (event.type) {
234 case SWT.Dispose:
235 case SWT.KeyDown:
236 case SWT.MouseMove: {
420bceb2
PT
237 if (tip == null) {
238 break;
239 }
631d853f
PT
240 tip.dispose ();
241 tip = null;
242 label = null;
243 break;
244 }
245 case SWT.MouseHover: {
246 TableItem item = fTable.getItem (new Point(event.x, event.y));
247 if (item != null) {
420bceb2 248 for (int i=0; i < fTable.getColumnCount(); i++) {
631d853f
PT
249 Rectangle bounds = item.getBounds(i);
250 if (bounds.contains(event.x,event.y)){
420bceb2
PT
251 if (tip != null && !tip.isDisposed()) {
252 tip.dispose();
253 }
631d853f
PT
254 if (tooltipProvider == null) {
255 return;
631d853f 256 }
abbdd66a
AM
257 String tooltipText = tooltipProvider.getTooltip(i, item.getData());
258 if (tooltipText == null) {
259 return;
260 }
261 tip = new Shell(fTable.getShell(), SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
262 tip.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
263 FillLayout layout = new FillLayout();
264 layout.marginWidth = 2;
265 tip.setLayout(layout);
266 label = new Label(tip, SWT.WRAP);
267 label.setForeground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
268 label.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
269 label.setData(TOOLTIP_DATA_KEY, item);
270 label.setText(tooltipText);
271
272 label.addListener(SWT.MouseExit, labelListener);
273 label.addListener(SWT.MouseDown, labelListener);
274 label.addListener(SWT.MouseWheel, labelListener);
275 Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT);
276 Point pt = fTable.toDisplay(bounds.x, bounds.y);
277 tip.setBounds(pt.x, pt.y, size.x, size.y);
278 tip.setVisible(true);
631d853f
PT
279 }
280 }
281 }
abbdd66a 282 break;
631d853f 283 }
abbdd66a
AM
284 default:
285 break;
631d853f
PT
286 }
287 }
288 };
289 fTable.addListener(SWT.Dispose, tableListener);
290 fTable.addListener(SWT.KeyDown, tableListener);
291 fTable.addListener(SWT.MouseMove, tableListener);
292 fTable.addListener(SWT.MouseHover, tableListener);
293 addControlListener(new ControlAdapter() {
294 @Override
295 public void controlResized(ControlEvent event) {
296 resize();
420bceb2
PT
297 if (fTableItemCount > 0) {
298 fSlider.setThumb(Math.max(1, Math.min(fTableRows, fFullyVisibleRows)));
299 }
631d853f
PT
300 }
301 });
302
303 // And display
304 refresh();
305 }
306
307 // ------------------------------------------------------------------------
308 // Table handling
309 // ------------------------------------------------------------------------
310
311 /**
312 * Create the table and add listeners
02023181 313 * @param style int can be H_SCROLL, V_SCROLL, SINGLE, CHECK, FULL_SELECTION, HIDE_SELECTION, NO_SCROLL
631d853f
PT
314 */
315 private void createTable(int style) {
316 fTable = new Table(this, style | SWT.NO_SCROLL);
317
318 fTable.addSelectionListener(new SelectionAdapter() {
319 @Override
320 public void widgetSelected(SelectionEvent event) {
321 if (fTable.getSelectionIndices().length > 0) {
322 handleTableSelection();
323 }
324 }
325 });
9ccc6d01 326
2cc874d6 327 fTable.addKeyListener(new KeyListener() {
631d853f
PT
328 @Override
329 public void keyPressed(KeyEvent event) {
330 handleTableKeyEvent(event);
331 }
332 @Override
333 public void keyReleased(KeyEvent event) {
334 }
335 });
7800a42f
XR
336
337 fTable.addListener(
631d853f
PT
338 SWT.MouseDoubleClick, new Listener() {
339 @Override
340 public void handleEvent(Event event) {
341 if (doubleClickListener != null) {
342 TableItem item = fTable.getItem (new Point (event.x, event.y));
343 if (item != null) {
344 for(int i=0;i<fTable.getColumnCount();i++){
345 Rectangle bounds = item.getBounds(i);
346 if (bounds.contains(event.x,event.y)){
347 doubleClickListener.handleDoubleClick(TmfVirtualTable.this, item, i);
348 break;
349 }
350 }
351 }
352 }
353 }
354 }
355 );
356 }
357
358 /**
359 * Update the rows and selected item
360 */
361 private void handleTableSelection() {
362 int selectedRow = fTable.getSelectionIndices()[0];
363 if (selectedRow < fFrozenRowCount) {
364 fSelectedEventRank = selectedRow;
365 } else {
366 fSelectedEventRank = fTableTopEventRank + selectedRow;
367 }
368
369 /*
370 * Feature in Windows. When a partially visible table item is selected,
371 * after ~500 ms the top index is changed to ensure the selected item is
372 * fully visible. This leaves a blank space at the bottom of the virtual
373 * table. The workaround is to update the top event rank, refresh the
374 * table and reset the top index to 0 after a sufficient delay.
375 */
376 if (selectedRow >= fFullyVisibleRows) {
377 final Display display = fTable.getDisplay();
378 Thread thread = new Thread("Top index check") { //$NON-NLS-1$
379 @Override
380 public void run() {
381 try {
382 Thread.sleep(600);
383 } catch (InterruptedException e) {
384 }
385 display.asyncExec(new Runnable() {
386 @Override
b21305c2 387 public void run() {
420bceb2
PT
388 if (fTable.isDisposed()) {
389 return;
390 }
631d853f
PT
391 int topIndex = fTable.getTopIndex();
392 if (topIndex != 0) {
393 fTableTopEventRank += topIndex;
394 refreshTable();
395 fSlider.setSelection(fTableTopEventRank);
396 fTable.setTopIndex(0);
397 }
398 }
399 });
400 }
401 };
402 thread.start();
403 }
404 }
405
406 /**
407 * Handle key-based navigation in table.
3934297e 408 *
631d853f
PT
409 * @param event
410 */
411 private void handleTableKeyEvent(KeyEvent event) {
412
413 int lastEventRank = fTableItemCount - 1;
414 int lastPageTopEntryRank = Math.max(0, fTableItemCount - fFullyVisibleRows);
415
416 int previousSelectedEventRank = fSelectedEventRank;
417 int selectedRow = fSelectedEventRank - fTableTopEventRank;
418 boolean needsRefresh = false;
419
420 // In all case, perform the following steps:
421 // - Update the selected entry rank (within valid range)
422 // - Update the selected row
423 // - Update the page's top entry if necessary (which also adjusts the selected row)
424 // - If the top displayed entry was changed, table refresh is needed
425 switch (event.keyCode) {
426
427 case SWT.ARROW_DOWN: {
428 event.doit = false;
429 if (fSelectedEventRank < lastEventRank) {
430 fSelectedEventRank++;
431 selectedRow = fSelectedEventRank - fTableTopEventRank;
75c271cf 432 if (selectedRow == fFullyVisibleRows) {
631d853f
PT
433 fTableTopEventRank++;
434 needsRefresh = true;
75c271cf
PT
435 } else if (selectedRow < fFrozenRowCount || selectedRow > fFullyVisibleRows) {
436 fTableTopEventRank = Math.max(0, Math.min(fSelectedEventRank - fFrozenRowCount, lastPageTopEntryRank));
437 needsRefresh = true;
631d853f
PT
438 }
439 }
440 break;
441 }
442
443 case SWT.ARROW_UP: {
444 event.doit = false;
445 if (fSelectedEventRank > 0) {
446 fSelectedEventRank--;
447 selectedRow = fSelectedEventRank - fTableTopEventRank;
75c271cf 448 if (selectedRow == fFrozenRowCount - 1 && fTableTopEventRank > 0) {
631d853f
PT
449 fTableTopEventRank--;
450 needsRefresh = true;
75c271cf
PT
451 } else if (selectedRow < fFrozenRowCount || selectedRow > fFullyVisibleRows) {
452 fTableTopEventRank = Math.max(0, Math.min(fSelectedEventRank - fFrozenRowCount, lastPageTopEntryRank));
453 needsRefresh = true;
631d853f
PT
454 }
455 }
456 break;
457 }
458
459 case SWT.END: {
460 event.doit = false;
461 fTableTopEventRank = lastPageTopEntryRank;
462 fSelectedEventRank = lastEventRank;
463 needsRefresh = true;
464 break;
465 }
466
467 case SWT.HOME: {
468 event.doit = false;
469 fSelectedEventRank = fFrozenRowCount;
470 fTableTopEventRank = 0;
471 needsRefresh = true;
472 break;
473 }
474
475 case SWT.PAGE_DOWN: {
476 event.doit = false;
477 if (fSelectedEventRank < lastEventRank) {
478 fSelectedEventRank += fFullyVisibleRows;
479 if (fSelectedEventRank > lastEventRank) {
480 fSelectedEventRank = lastEventRank;
481 }
482 selectedRow = fSelectedEventRank - fTableTopEventRank;
75c271cf 483 if (selectedRow > fFullyVisibleRows + fFrozenRowCount - 1 && selectedRow < 2 * fFullyVisibleRows) {
631d853f
PT
484 fTableTopEventRank += fFullyVisibleRows;
485 if (fTableTopEventRank > lastPageTopEntryRank) {
486 fTableTopEventRank = lastPageTopEntryRank;
487 }
488 needsRefresh = true;
75c271cf
PT
489 } else if (selectedRow < fFrozenRowCount || selectedRow >= 2 * fFullyVisibleRows) {
490 fTableTopEventRank = Math.max(0, Math.min(fSelectedEventRank - fFrozenRowCount, lastPageTopEntryRank));
491 needsRefresh = true;
631d853f
PT
492 }
493 }
494 break;
495 }
496
497 case SWT.PAGE_UP: {
498 event.doit = false;
499 if (fSelectedEventRank > 0) {
500 fSelectedEventRank -= fFullyVisibleRows;
501 if (fSelectedEventRank < fFrozenRowCount) {
502 fSelectedEventRank = fFrozenRowCount;
503 }
504 selectedRow = fSelectedEventRank - fTableTopEventRank;
75c271cf 505 if (selectedRow < fFrozenRowCount && selectedRow > -fFullyVisibleRows) {
631d853f
PT
506 fTableTopEventRank -= fFullyVisibleRows;
507 if (fTableTopEventRank < 0) {
508 fTableTopEventRank = 0;
509 }
510 needsRefresh = true;
75c271cf
PT
511 } else if (selectedRow <= -fFullyVisibleRows || selectedRow >= fFullyVisibleRows) {
512 fTableTopEventRank = Math.max(0, Math.min(fSelectedEventRank - fFrozenRowCount, lastPageTopEntryRank));
513 needsRefresh = true;
631d853f
PT
514 }
515 }
516 break;
517 }
518 default: {
519 return;
520 }
521 }
522
523 boolean done = true;
524 if (needsRefresh) {
525 done = refreshTable(); // false if table items not updated yet in this thread
526 } else {
527 fTable.select(selectedRow);
528 }
529
530 if (fFullyVisibleRows < fTableItemCount) {
531 fSlider.setSelection(fTableTopEventRank);
532 }
533
420bceb2 534 if (fSelectedEventRank != previousSelectedEventRank && fSelectedEventRank < fTableItemCount) {
631d853f
PT
535 if (done) {
536 Event e = new Event();
537 e.item = fTable.getSelection()[0];
538 fTable.notifyListeners(SWT.Selection, e);
539 } else {
540 fPendingSelection = true;
541 }
542 }
543 }
544
02023181
MK
545 /**
546 * Method setDataItem.
547 * @param index int
548 * @param item TableItem
549 * @return boolean
550 */
631d853f
PT
551 private boolean setDataItem(int index, TableItem item) {
552 if (index != -1) {
553 Event event = new Event();
554 event.item = item;
555 if (index < fFrozenRowCount) {
556 event.index = index;
557 } else {
558 event.index = index + fTableTopEventRank;
559 }
560 event.doit = true;
561 fTable.notifyListeners(SWT.SetData, event);
562 return event.doit; // false if table item not updated yet in this thread
563 }
564 return true;
565 }
566
567 // ------------------------------------------------------------------------
568 // Slider handling
569 // ------------------------------------------------------------------------
570
02023181
MK
571 /**
572 * Method createSlider.
573 * @param style int
574 */
631d853f
PT
575 private void createSlider(int style) {
576 fSlider = new Slider(this, SWT.VERTICAL | SWT.NO_FOCUS);
577 fSlider.setMinimum(0);
578 fSlider.setMaximum(0);
579 if ((style & SWT.V_SCROLL) == 0) {
580 fSlider.setVisible(false);
581 }
582
583 fSlider.addListener(SWT.Selection, new Listener() {
584 @Override
585 public void handleEvent(Event event) {
586 switch (event.detail) {
587 case SWT.ARROW_DOWN:
588 case SWT.ARROW_UP:
589 case SWT.NONE:
590 case SWT.END:
591 case SWT.HOME:
592 case SWT.PAGE_DOWN:
593 case SWT.PAGE_UP: {
594 fTableTopEventRank = fSlider.getSelection();
595 refreshTable();
596 break;
597 }
abbdd66a
AM
598 default:
599 break;
631d853f
PT
600 }
601 }
602 });
603 }
604
605 // ------------------------------------------------------------------------
606 // Simulated Table API
607 // ------------------------------------------------------------------------
608
02023181
MK
609 /**
610 * Method setHeaderVisible.
611 * @param b boolean
612 */
631d853f
PT
613 public void setHeaderVisible(boolean b) {
614 fTable.setHeaderVisible(b);
615 }
616
02023181
MK
617 /**
618 * Method setLinesVisible.
619 * @param b boolean
620 */
631d853f
PT
621 public void setLinesVisible(boolean b) {
622 fTable.setLinesVisible(b);
623 }
624
02023181 625 /**
3934297e 626 * Method getSelection.
02023181
MK
627 * @return TableItem[] the items that are selected.
628 */
631d853f
PT
629 public TableItem[] getSelection() {
630 return fTable.getSelection();
631 }
632
02023181
MK
633 /**
634 * Method addListener.
635 * @param eventType int
636 * @param listener Listener
637 */
631d853f 638 @Override
828e5592
PT
639 public void addListener(int eventType, Listener listener) {
640 fTable.addListener(eventType, listener);
641 }
631d853f 642
02023181
MK
643 /**
644 * Method addKeyListener.
645 * @param listener KeyListener
646 */
631d853f
PT
647 @Override
648 public void addKeyListener(KeyListener listener) {
649 fTable.addKeyListener(listener);
650 }
b21305c2 651
828e5592 652
02023181
MK
653 /**
654 * Method addMouseListener.
655 * @param listener MouseListener
656 */
828e5592 657 @Override
631d853f
PT
658 public void addMouseListener(MouseListener listener) {
659 fTable.addMouseListener(listener);
660 }
661
02023181
MK
662 /**
663 * Method addSelectionListener.
664 * @param listener SelectionListener
665 */
631d853f
PT
666 public void addSelectionListener(SelectionListener listener) {
667 fTable.addSelectionListener(listener);
668 }
669
02023181
MK
670 /**
671 * Method setMenu sets the menu
672 * @param menu Menu the menu
673 */
631d853f
PT
674 @Override
675 public void setMenu(Menu menu) {
676 fTable.setMenu(menu);
677 }
678
02023181 679 /**
3934297e 680 * Method clearAll empties a table.
02023181 681 */
631d853f
PT
682 public void clearAll() {
683 setItemCount(0);
684 }
685
02023181
MK
686 /**
687 * Method setItemCount
688 * @param nbItems int the number of items in the table
3934297e 689 *
02023181 690 */
631d853f
PT
691 public void setItemCount(int nbItems) {
692 nbItems = Math.max(0, nbItems);
693
694 if (nbItems != fTableItemCount) {
695 fTableItemCount = nbItems;
696 fTable.remove(fTableItemCount, fTable.getItemCount() - 1);
697 fSlider.setMaximum(nbItems);
698 resize();
699 int tableHeight = Math.max(0, fTable.getClientArea().height - fTable.getHeaderHeight());
700 fFullyVisibleRows = tableHeight / getItemHeight();
701 if (fTableItemCount > 0) {
702 fSlider.setThumb(Math.max(1, Math.min(fTableRows, fFullyVisibleRows)));
703 }
704 }
705 }
706
02023181
MK
707 /**
708 * Method getItemCount.
709 * @return int the number of items in the table
710 */
631d853f
PT
711 public int getItemCount() {
712 return fTableItemCount;
713 }
714
02023181
MK
715 /**
716 * Method getItemHeight.
717 * @return int the height of a table item in pixels. (may vary from one os to another)
718 */
631d853f
PT
719 public int getItemHeight() {
720 /*
721 * Bug in Linux. The method getItemHeight doesn't always return the correct value.
722 */
723 if (fLinuxItemHeight >= 0 && System.getProperty("os.name").contains("Linux")) { //$NON-NLS-1$ //$NON-NLS-2$
724 if (fLinuxItemHeight != 0) {
725 return fLinuxItemHeight;
726 }
727 if (fTable.getItemCount() > 1) {
728 int itemHeight = fTable.getItem(1).getBounds().y - fTable.getItem(0).getBounds().y;
729 if (itemHeight > 0) {
730 fLinuxItemHeight = itemHeight;
731 return fLinuxItemHeight;
732 }
733 }
734 } else {
735 fLinuxItemHeight = -1; // Not Linux, don't perform os.name check anymore
736 }
737 return fTable.getItemHeight();
738 }
739
02023181
MK
740 /**
741 * Method getHeaderHeight.
742 * @return int get the height of the header in pixels.
743 */
ea08e8ed
PT
744 public int getHeaderHeight() {
745 return fTable.getHeaderHeight();
746 }
747
02023181
MK
748 /**
749 * Method getTopIndex.
750 * @return int get the first data item index, if you have a header it is offset.
751 */
631d853f
PT
752 public int getTopIndex() {
753 return fTableTopEventRank + fFrozenRowCount;
754 }
755
02023181
MK
756 /**
757 * Method setTopIndex.
3934297e 758 * @param i int suggested top index for the table.
02023181 759 */
631d853f
PT
760 public void setTopIndex(int i) {
761 if (fTableItemCount > 0) {
762 i = Math.min(i, fTableItemCount - 1);
763 i = Math.max(i, fFrozenRowCount);
764
765 fTableTopEventRank = i - fFrozenRowCount;
766 if (fFullyVisibleRows < fTableItemCount) {
767 fSlider.setSelection(fTableTopEventRank);
768 }
769
770 refreshTable();
771 }
772 }
773
02023181
MK
774 /**
775 * Method indexOf. Return the index of a table item
776 * @param ti TableItem the table item to search for in the table
3934297e 777 * @return int the index of the first match. (there should only be one match)
02023181 778 */
631d853f
PT
779 public int indexOf(TableItem ti) {
780 int index = fTable.indexOf(ti);
781 if (index < fFrozenRowCount) {
782 return index;
631d853f 783 }
abbdd66a 784 return (index - fFrozenRowCount) + getTopIndex();
631d853f
PT
785 }
786
02023181
MK
787 /**
788 * Method getColumns.
3934297e 789 * @return TableColumn[] the table columns
02023181 790 */
631d853f
PT
791 public TableColumn[] getColumns() {
792 return fTable.getColumns();
793 }
794
02023181
MK
795 /**
796 * Method getItem.
797 * @param point Point the coordinates in the table
3934297e 798 * @return TableItem the corresponding table item
02023181 799 */
631d853f
PT
800 public TableItem getItem(Point point) {
801 return fTable.getItem(point);
802 }
803
02023181
MK
804 /**
805 * Method resize.
806 */
631d853f
PT
807 private void resize() {
808 // Compute the numbers of rows that fit the new area
809 int tableHeight = Math.max(0, getSize().y - fTable.getHeaderHeight());
810 int itemHeight = getItemHeight();
811 fTableRows = Math.min((tableHeight + itemHeight - 1) / itemHeight, fTableItemCount);
812
813 if (fTableTopEventRank + fFullyVisibleRows > fTableItemCount) {
814 // If we are at the end, get elements before to populate
815 fTableTopEventRank = Math.max(0, fTableItemCount - fFullyVisibleRows);
816 refreshTable();
817 } else if (fTableRows > fTable.getItemCount() || fTableItemCount < fTable.getItemCount()) {
818 // Only refresh if new table items are needed or if table items need to be deleted
819 refreshTable();
820 }
821
822 }
823
824 // ------------------------------------------------------------------------
825 // Controls interactions
826 // ------------------------------------------------------------------------
827
02023181
MK
828 /**
829 * Method setFocus.
830 * @return boolean is this visible?
831 */
631d853f
PT
832 @Override
833 public boolean setFocus() {
834 boolean isVisible = isVisible();
835 if (isVisible) {
836 fTable.setFocus();
837 }
838 return isVisible;
839 }
840
02023181
MK
841 /**
842 * Method refresh.
843 */
631d853f
PT
844 public void refresh() {
845 boolean done = refreshTable();
846 if (fPendingSelection && done) {
847 fPendingSelection = false;
848 if (fTable.getSelection().length > 0) {
849 Event e = new Event();
850 e.item = fTable.getSelection()[0];
851 fTable.notifyListeners(SWT.Selection, e);
852 }
853 }
854 }
855
02023181
MK
856 /**
857 * Method setColumnHeaders.
3934297e 858 * @param columnData ColumnData[] the columndata array.
02023181 859 */
631d853f
PT
860 public void setColumnHeaders(ColumnData columnData[]) {
861 for (int i = 0; i < columnData.length; i++) {
862 TableColumn column = new TableColumn(fTable, columnData[i].alignment, i);
863 column.setText(columnData[i].header);
864 if (columnData[i].width > 0) {
865 column.setWidth(columnData[i].width);
866 } else {
867 column.pack();
868 }
869 }
870 }
871
02023181
MK
872 /**
873 * Method removeAll.
874 * @return int 0 the number of elements in the table
875 */
631d853f
PT
876 public int removeAll() {
877 setItemCount(0);
878 fSlider.setMaximum(0);
879 fTable.removeAll();
880 fSelectedEventRank = fFrozenRowCount;
881 return 0;
882 }
883
02023181
MK
884 /**
885 * Method refreshTable.
3934297e 886 * @return boolean did all the items regresh properly?
02023181 887 */
631d853f
PT
888 private boolean refreshTable() {
889 boolean done = true;
890 for (int i = 0; i < fTableRows; i++) {
891 if (i + fTableTopEventRank < fTableItemCount) {
892 TableItem tableItem;
893 if (i < fTable.getItemCount()) {
894 tableItem = fTable.getItem(i);
895 } else {
896 tableItem = new TableItem(fTable, SWT.NONE);
897 }
898 done &= setDataItem(i, tableItem); // false if table item not updated yet in this thread
899 } else {
900 if (fTable.getItemCount() > fTableItemCount - fTableTopEventRank) {
901 fTable.remove(fTableItemCount - fTableTopEventRank);
902 }
903 }
904 }
905
906 int lastRowOffset = fTableTopEventRank + fTableRows - 1;
907 if (fSelectedEventRank < fFrozenRowCount) {
908 fTable.select(fSelectedEventRank);
909 } else if (!done) {
910 fTable.deselectAll();
911 } else if ((fSelectedEventRank >= fTableTopEventRank + fFrozenRowCount) && (fSelectedEventRank <= lastRowOffset)) {
912 int selectedRow = fSelectedEventRank - fTableTopEventRank;
913 fTable.select(selectedRow);
914 } else {
915 fTable.deselectAll();
916 }
917 return done;
918 }
919
02023181
MK
920 /**
921 * Method setSelection.
3934297e 922 * @param i int the item number to select in the table.
02023181 923 */
631d853f
PT
924 public void setSelection(int i) {
925 if (fTableItemCount > 0) {
926 i = Math.min(i, fTableItemCount - 1);
927 i = Math.max(i, 0);
928
929 fSelectedEventRank = i;
930 if ((i < fTableTopEventRank + fFrozenRowCount && i >= fFrozenRowCount) ||
931 (i >= fTableTopEventRank + fFullyVisibleRows)) {
932 fTableTopEventRank = Math.max(0, i - fFrozenRowCount - fFullyVisibleRows / 2);
933 }
934 if (fFullyVisibleRows < fTableItemCount) {
935 fSlider.setSelection(fTableTopEventRank);
936 }
937
938 refreshTable();
939
940 }
941 }
942
02023181
MK
943 /**
944 * Method getSelectionIndex.
945 * @return int the table index of the selected event. not necessarrily the index of the event due to filtering.
946 */
631d853f
PT
947 public int getSelectionIndex() {
948 int index = fTable.getSelectionIndex();
949 if (index == -1) {
950 return fSelectedEventRank;
951 }
952 if (index < fFrozenRowCount) {
953 return index;
631d853f 954 }
abbdd66a 955 return (index - fFrozenRowCount) + getTopIndex();
631d853f
PT
956 }
957
02023181
MK
958 /**
959 * Method setFrozenRowCount.
960 * @param count int the number of rows to freeze from the top row
961 */
631d853f
PT
962 public void setFrozenRowCount(int count) {
963 fFrozenRowCount = count;
964 refreshTable();
965 }
966
02023181
MK
967 /**
968 * Method createTableEditor.
969 * @return a TableEditor of the table
970 */
631d853f
PT
971 public TableEditor createTableEditor() {
972 return new TableEditor(fTable);
973 }
974
02023181
MK
975 /**
976 * Method createTableEditorControl.
977 * @param control Class<? extends Control>
978 * @return Control
979 */
631d853f
PT
980 public Control createTableEditorControl(Class<? extends Control> control) {
981 try {
420bceb2 982 return control.getConstructor(Composite.class, int.class).newInstance(new Object[] {fTable, SWT.NONE});
631d853f
PT
983 } catch (Exception e) {
984 Activator.getDefault().logError("Error creating table editor control", e); //$NON-NLS-1$
985 }
986 return null;
987 }
988
989 /**
990 * @return the tooltipProvider
02023181 991 */
631d853f
PT
992 public TooltipProvider getTooltipProvider() {
993 return tooltipProvider;
994 }
995
996 /**
997 * @param tooltipProvider the tooltipProvider to set
998 */
999 public void setTooltipProvider(TooltipProvider tooltipProvider) {
1000 this.tooltipProvider = tooltipProvider;
1001 }
1002
1003 /**
1004 * @return the doubleClickListener
02023181 1005 */
631d853f
PT
1006 public IDoubleClickListener getDoubleClickListener() {
1007 return doubleClickListener;
1008 }
1009
1010 /**
1011 * @param doubleClickListener the doubleClickListener to set
1012 */
1013 public void setDoubleClickListener(IDoubleClickListener doubleClickListener) {
1014 this.doubleClickListener = doubleClickListener;
1015 }
1016
9ccc6d01 1017}
This page took 0.084524 seconds and 5 git commands to generate.