tmf: Simple warning fixes in tmf.core and tests
[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;
222 }
223 }
224 };
225
226 Listener tableListener = new Listener () {
227 Shell tip = null;
228 Label label = null;
229 @Override
f4c52cea 230 public void handleEvent (Event event) {
631d853f
PT
231 switch (event.type) {
232 case SWT.Dispose:
233 case SWT.KeyDown:
234 case SWT.MouseMove: {
420bceb2
PT
235 if (tip == null) {
236 break;
237 }
631d853f
PT
238 tip.dispose ();
239 tip = null;
240 label = null;
241 break;
242 }
243 case SWT.MouseHover: {
244 TableItem item = fTable.getItem (new Point(event.x, event.y));
245 if (item != null) {
420bceb2 246 for (int i=0; i < fTable.getColumnCount(); i++) {
631d853f
PT
247 Rectangle bounds = item.getBounds(i);
248 if (bounds.contains(event.x,event.y)){
420bceb2
PT
249 if (tip != null && !tip.isDisposed()) {
250 tip.dispose();
251 }
631d853f
PT
252 if (tooltipProvider == null) {
253 return;
254 } else {
255 String tooltipText = tooltipProvider.getTooltip(i, item.getData());
420bceb2
PT
256 if (tooltipText == null) {
257 return;
258 }
631d853f
PT
259 tip = new Shell(fTable.getShell(), SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
260 tip.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
261 FillLayout layout = new FillLayout();
262 layout.marginWidth = 2;
263 tip.setLayout(layout);
264 label = new Label(tip, SWT.WRAP);
265 label.setForeground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
266 label.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
267 label.setData(TOOLTIP_DATA_KEY, item);
268 label.setText(tooltipText);
269
270 label.addListener(SWT.MouseExit, labelListener);
271 label.addListener(SWT.MouseDown, labelListener);
272 label.addListener(SWT.MouseWheel, labelListener);
273 Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT);
274 Point pt = fTable.toDisplay(bounds.x, bounds.y);
275 tip.setBounds(pt.x, pt.y, size.x, size.y);
276 tip.setVisible(true);
277 }
278 break;
279 }
280 }
281 }
282 }
283 }
284 }
285 };
286 fTable.addListener(SWT.Dispose, tableListener);
287 fTable.addListener(SWT.KeyDown, tableListener);
288 fTable.addListener(SWT.MouseMove, tableListener);
289 fTable.addListener(SWT.MouseHover, tableListener);
290 addControlListener(new ControlAdapter() {
291 @Override
292 public void controlResized(ControlEvent event) {
293 resize();
420bceb2
PT
294 if (fTableItemCount > 0) {
295 fSlider.setThumb(Math.max(1, Math.min(fTableRows, fFullyVisibleRows)));
296 }
631d853f
PT
297 }
298 });
299
300 // And display
301 refresh();
302 }
303
304 // ------------------------------------------------------------------------
305 // Table handling
306 // ------------------------------------------------------------------------
307
308 /**
309 * Create the table and add listeners
02023181 310 * @param style int can be H_SCROLL, V_SCROLL, SINGLE, CHECK, FULL_SELECTION, HIDE_SELECTION, NO_SCROLL
631d853f
PT
311 */
312 private void createTable(int style) {
313 fTable = new Table(this, style | SWT.NO_SCROLL);
314
315 fTable.addSelectionListener(new SelectionAdapter() {
316 @Override
317 public void widgetSelected(SelectionEvent event) {
318 if (fTable.getSelectionIndices().length > 0) {
319 handleTableSelection();
320 }
321 }
322 });
9ccc6d01 323
2cc874d6 324 fTable.addKeyListener(new KeyListener() {
631d853f
PT
325 @Override
326 public void keyPressed(KeyEvent event) {
327 handleTableKeyEvent(event);
328 }
329 @Override
330 public void keyReleased(KeyEvent event) {
331 }
332 });
7800a42f
XR
333
334 fTable.addListener(
631d853f
PT
335 SWT.MouseDoubleClick, new Listener() {
336 @Override
337 public void handleEvent(Event event) {
338 if (doubleClickListener != null) {
339 TableItem item = fTable.getItem (new Point (event.x, event.y));
340 if (item != null) {
341 for(int i=0;i<fTable.getColumnCount();i++){
342 Rectangle bounds = item.getBounds(i);
343 if (bounds.contains(event.x,event.y)){
344 doubleClickListener.handleDoubleClick(TmfVirtualTable.this, item, i);
345 break;
346 }
347 }
348 }
349 }
350 }
351 }
352 );
353 }
354
355 /**
356 * Update the rows and selected item
357 */
358 private void handleTableSelection() {
359 int selectedRow = fTable.getSelectionIndices()[0];
360 if (selectedRow < fFrozenRowCount) {
361 fSelectedEventRank = selectedRow;
362 } else {
363 fSelectedEventRank = fTableTopEventRank + selectedRow;
364 }
365
366 /*
367 * Feature in Windows. When a partially visible table item is selected,
368 * after ~500 ms the top index is changed to ensure the selected item is
369 * fully visible. This leaves a blank space at the bottom of the virtual
370 * table. The workaround is to update the top event rank, refresh the
371 * table and reset the top index to 0 after a sufficient delay.
372 */
373 if (selectedRow >= fFullyVisibleRows) {
374 final Display display = fTable.getDisplay();
375 Thread thread = new Thread("Top index check") { //$NON-NLS-1$
376 @Override
377 public void run() {
378 try {
379 Thread.sleep(600);
380 } catch (InterruptedException e) {
381 }
382 display.asyncExec(new Runnable() {
383 @Override
b21305c2 384 public void run() {
420bceb2
PT
385 if (fTable.isDisposed()) {
386 return;
387 }
631d853f
PT
388 int topIndex = fTable.getTopIndex();
389 if (topIndex != 0) {
390 fTableTopEventRank += topIndex;
391 refreshTable();
392 fSlider.setSelection(fTableTopEventRank);
393 fTable.setTopIndex(0);
394 }
395 }
396 });
397 }
398 };
399 thread.start();
400 }
401 }
402
403 /**
404 * Handle key-based navigation in table.
3934297e 405 *
631d853f
PT
406 * @param event
407 */
408 private void handleTableKeyEvent(KeyEvent event) {
409
410 int lastEventRank = fTableItemCount - 1;
411 int lastPageTopEntryRank = Math.max(0, fTableItemCount - fFullyVisibleRows);
412
413 int previousSelectedEventRank = fSelectedEventRank;
414 int selectedRow = fSelectedEventRank - fTableTopEventRank;
415 boolean needsRefresh = false;
416
417 // In all case, perform the following steps:
418 // - Update the selected entry rank (within valid range)
419 // - Update the selected row
420 // - Update the page's top entry if necessary (which also adjusts the selected row)
421 // - If the top displayed entry was changed, table refresh is needed
422 switch (event.keyCode) {
423
424 case SWT.ARROW_DOWN: {
425 event.doit = false;
426 if (fSelectedEventRank < lastEventRank) {
427 fSelectedEventRank++;
428 selectedRow = fSelectedEventRank - fTableTopEventRank;
429 if (selectedRow >= fFullyVisibleRows) {
430 fTableTopEventRank++;
431 needsRefresh = true;
432 }
433 }
434 break;
435 }
436
437 case SWT.ARROW_UP: {
438 event.doit = false;
439 if (fSelectedEventRank > 0) {
440 fSelectedEventRank--;
441 selectedRow = fSelectedEventRank - fTableTopEventRank;
442 if (selectedRow < fFrozenRowCount && fTableTopEventRank > 0) {
443 fTableTopEventRank--;
444 needsRefresh = true;
445 }
446 }
447 break;
448 }
449
450 case SWT.END: {
451 event.doit = false;
452 fTableTopEventRank = lastPageTopEntryRank;
453 fSelectedEventRank = lastEventRank;
454 needsRefresh = true;
455 break;
456 }
457
458 case SWT.HOME: {
459 event.doit = false;
460 fSelectedEventRank = fFrozenRowCount;
461 fTableTopEventRank = 0;
462 needsRefresh = true;
463 break;
464 }
465
466 case SWT.PAGE_DOWN: {
467 event.doit = false;
468 if (fSelectedEventRank < lastEventRank) {
469 fSelectedEventRank += fFullyVisibleRows;
470 if (fSelectedEventRank > lastEventRank) {
471 fSelectedEventRank = lastEventRank;
472 }
473 selectedRow = fSelectedEventRank - fTableTopEventRank;
474 if (selectedRow > fFullyVisibleRows - 1) {
475 fTableTopEventRank += fFullyVisibleRows;
476 if (fTableTopEventRank > lastPageTopEntryRank) {
477 fTableTopEventRank = lastPageTopEntryRank;
478 }
479 needsRefresh = true;
480 }
481 }
482 break;
483 }
484
485 case SWT.PAGE_UP: {
486 event.doit = false;
487 if (fSelectedEventRank > 0) {
488 fSelectedEventRank -= fFullyVisibleRows;
489 if (fSelectedEventRank < fFrozenRowCount) {
490 fSelectedEventRank = fFrozenRowCount;
491 }
492 selectedRow = fSelectedEventRank - fTableTopEventRank;
493 if (selectedRow < 0) {
494 fTableTopEventRank -= fFullyVisibleRows;
495 if (fTableTopEventRank < 0) {
496 fTableTopEventRank = 0;
497 }
498 needsRefresh = true;
499 }
500 }
501 break;
502 }
503 default: {
504 return;
505 }
506 }
507
508 boolean done = true;
509 if (needsRefresh) {
510 done = refreshTable(); // false if table items not updated yet in this thread
511 } else {
512 fTable.select(selectedRow);
513 }
514
515 if (fFullyVisibleRows < fTableItemCount) {
516 fSlider.setSelection(fTableTopEventRank);
517 }
518
420bceb2 519 if (fSelectedEventRank != previousSelectedEventRank && fSelectedEventRank < fTableItemCount) {
631d853f
PT
520 if (done) {
521 Event e = new Event();
522 e.item = fTable.getSelection()[0];
523 fTable.notifyListeners(SWT.Selection, e);
524 } else {
525 fPendingSelection = true;
526 }
527 }
528 }
529
02023181
MK
530 /**
531 * Method setDataItem.
532 * @param index int
533 * @param item TableItem
534 * @return boolean
535 */
631d853f
PT
536 private boolean setDataItem(int index, TableItem item) {
537 if (index != -1) {
538 Event event = new Event();
539 event.item = item;
540 if (index < fFrozenRowCount) {
541 event.index = index;
542 } else {
543 event.index = index + fTableTopEventRank;
544 }
545 event.doit = true;
546 fTable.notifyListeners(SWT.SetData, event);
547 return event.doit; // false if table item not updated yet in this thread
548 }
549 return true;
550 }
551
552 // ------------------------------------------------------------------------
553 // Slider handling
554 // ------------------------------------------------------------------------
555
02023181
MK
556 /**
557 * Method createSlider.
558 * @param style int
559 */
631d853f
PT
560 private void createSlider(int style) {
561 fSlider = new Slider(this, SWT.VERTICAL | SWT.NO_FOCUS);
562 fSlider.setMinimum(0);
563 fSlider.setMaximum(0);
564 if ((style & SWT.V_SCROLL) == 0) {
565 fSlider.setVisible(false);
566 }
567
568 fSlider.addListener(SWT.Selection, new Listener() {
569 @Override
570 public void handleEvent(Event event) {
571 switch (event.detail) {
572 case SWT.ARROW_DOWN:
573 case SWT.ARROW_UP:
574 case SWT.NONE:
575 case SWT.END:
576 case SWT.HOME:
577 case SWT.PAGE_DOWN:
578 case SWT.PAGE_UP: {
579 fTableTopEventRank = fSlider.getSelection();
580 refreshTable();
581 break;
582 }
583 }
584 }
585 });
586 }
587
588 // ------------------------------------------------------------------------
589 // Simulated Table API
590 // ------------------------------------------------------------------------
591
02023181
MK
592 /**
593 * Method setHeaderVisible.
594 * @param b boolean
595 */
631d853f
PT
596 public void setHeaderVisible(boolean b) {
597 fTable.setHeaderVisible(b);
598 }
599
02023181
MK
600 /**
601 * Method setLinesVisible.
602 * @param b boolean
603 */
631d853f
PT
604 public void setLinesVisible(boolean b) {
605 fTable.setLinesVisible(b);
606 }
607
02023181 608 /**
3934297e 609 * Method getSelection.
02023181
MK
610 * @return TableItem[] the items that are selected.
611 */
631d853f
PT
612 public TableItem[] getSelection() {
613 return fTable.getSelection();
614 }
615
02023181
MK
616 /**
617 * Method addListener.
618 * @param eventType int
619 * @param listener Listener
620 */
631d853f 621 @Override
828e5592
PT
622 public void addListener(int eventType, Listener listener) {
623 fTable.addListener(eventType, listener);
624 }
631d853f 625
02023181
MK
626 /**
627 * Method addKeyListener.
628 * @param listener KeyListener
629 */
631d853f
PT
630 @Override
631 public void addKeyListener(KeyListener listener) {
632 fTable.addKeyListener(listener);
633 }
b21305c2 634
828e5592 635
02023181
MK
636 /**
637 * Method addMouseListener.
638 * @param listener MouseListener
639 */
828e5592 640 @Override
631d853f
PT
641 public void addMouseListener(MouseListener listener) {
642 fTable.addMouseListener(listener);
643 }
644
02023181
MK
645 /**
646 * Method addSelectionListener.
647 * @param listener SelectionListener
648 */
631d853f
PT
649 public void addSelectionListener(SelectionListener listener) {
650 fTable.addSelectionListener(listener);
651 }
652
02023181
MK
653 /**
654 * Method setMenu sets the menu
655 * @param menu Menu the menu
656 */
631d853f
PT
657 @Override
658 public void setMenu(Menu menu) {
659 fTable.setMenu(menu);
660 }
661
02023181 662 /**
3934297e 663 * Method clearAll empties a table.
02023181 664 */
631d853f
PT
665 public void clearAll() {
666 setItemCount(0);
667 }
668
02023181
MK
669 /**
670 * Method setItemCount
671 * @param nbItems int the number of items in the table
3934297e 672 *
02023181 673 */
631d853f
PT
674 public void setItemCount(int nbItems) {
675 nbItems = Math.max(0, nbItems);
676
677 if (nbItems != fTableItemCount) {
678 fTableItemCount = nbItems;
679 fTable.remove(fTableItemCount, fTable.getItemCount() - 1);
680 fSlider.setMaximum(nbItems);
681 resize();
682 int tableHeight = Math.max(0, fTable.getClientArea().height - fTable.getHeaderHeight());
683 fFullyVisibleRows = tableHeight / getItemHeight();
684 if (fTableItemCount > 0) {
685 fSlider.setThumb(Math.max(1, Math.min(fTableRows, fFullyVisibleRows)));
686 }
687 }
688 }
689
02023181
MK
690 /**
691 * Method getItemCount.
692 * @return int the number of items in the table
693 */
631d853f
PT
694 public int getItemCount() {
695 return fTableItemCount;
696 }
697
02023181
MK
698 /**
699 * Method getItemHeight.
700 * @return int the height of a table item in pixels. (may vary from one os to another)
701 */
631d853f
PT
702 public int getItemHeight() {
703 /*
704 * Bug in Linux. The method getItemHeight doesn't always return the correct value.
705 */
706 if (fLinuxItemHeight >= 0 && System.getProperty("os.name").contains("Linux")) { //$NON-NLS-1$ //$NON-NLS-2$
707 if (fLinuxItemHeight != 0) {
708 return fLinuxItemHeight;
709 }
710 if (fTable.getItemCount() > 1) {
711 int itemHeight = fTable.getItem(1).getBounds().y - fTable.getItem(0).getBounds().y;
712 if (itemHeight > 0) {
713 fLinuxItemHeight = itemHeight;
714 return fLinuxItemHeight;
715 }
716 }
717 } else {
718 fLinuxItemHeight = -1; // Not Linux, don't perform os.name check anymore
719 }
720 return fTable.getItemHeight();
721 }
722
02023181
MK
723 /**
724 * Method getHeaderHeight.
725 * @return int get the height of the header in pixels.
726 */
ea08e8ed
PT
727 public int getHeaderHeight() {
728 return fTable.getHeaderHeight();
729 }
730
02023181
MK
731 /**
732 * Method getTopIndex.
733 * @return int get the first data item index, if you have a header it is offset.
734 */
631d853f
PT
735 public int getTopIndex() {
736 return fTableTopEventRank + fFrozenRowCount;
737 }
738
02023181
MK
739 /**
740 * Method setTopIndex.
3934297e 741 * @param i int suggested top index for the table.
02023181 742 */
631d853f
PT
743 public void setTopIndex(int i) {
744 if (fTableItemCount > 0) {
745 i = Math.min(i, fTableItemCount - 1);
746 i = Math.max(i, fFrozenRowCount);
747
748 fTableTopEventRank = i - fFrozenRowCount;
749 if (fFullyVisibleRows < fTableItemCount) {
750 fSlider.setSelection(fTableTopEventRank);
751 }
752
753 refreshTable();
754 }
755 }
756
02023181
MK
757 /**
758 * Method indexOf. Return the index of a table item
759 * @param ti TableItem the table item to search for in the table
3934297e 760 * @return int the index of the first match. (there should only be one match)
02023181 761 */
631d853f
PT
762 public int indexOf(TableItem ti) {
763 int index = fTable.indexOf(ti);
764 if (index < fFrozenRowCount) {
765 return index;
766 } else {
767 return (index - fFrozenRowCount) + getTopIndex();
768 }
769 }
770
02023181
MK
771 /**
772 * Method getColumns.
3934297e 773 * @return TableColumn[] the table columns
02023181 774 */
631d853f
PT
775 public TableColumn[] getColumns() {
776 return fTable.getColumns();
777 }
778
02023181
MK
779 /**
780 * Method getItem.
781 * @param point Point the coordinates in the table
3934297e 782 * @return TableItem the corresponding table item
02023181 783 */
631d853f
PT
784 public TableItem getItem(Point point) {
785 return fTable.getItem(point);
786 }
787
02023181
MK
788 /**
789 * Method resize.
790 */
631d853f
PT
791 private void resize() {
792 // Compute the numbers of rows that fit the new area
793 int tableHeight = Math.max(0, getSize().y - fTable.getHeaderHeight());
794 int itemHeight = getItemHeight();
795 fTableRows = Math.min((tableHeight + itemHeight - 1) / itemHeight, fTableItemCount);
796
797 if (fTableTopEventRank + fFullyVisibleRows > fTableItemCount) {
798 // If we are at the end, get elements before to populate
799 fTableTopEventRank = Math.max(0, fTableItemCount - fFullyVisibleRows);
800 refreshTable();
801 } else if (fTableRows > fTable.getItemCount() || fTableItemCount < fTable.getItemCount()) {
802 // Only refresh if new table items are needed or if table items need to be deleted
803 refreshTable();
804 }
805
806 }
807
808 // ------------------------------------------------------------------------
809 // Controls interactions
810 // ------------------------------------------------------------------------
811
02023181
MK
812 /**
813 * Method setFocus.
814 * @return boolean is this visible?
815 */
631d853f
PT
816 @Override
817 public boolean setFocus() {
818 boolean isVisible = isVisible();
819 if (isVisible) {
820 fTable.setFocus();
821 }
822 return isVisible;
823 }
824
02023181
MK
825 /**
826 * Method refresh.
827 */
631d853f
PT
828 public void refresh() {
829 boolean done = refreshTable();
830 if (fPendingSelection && done) {
831 fPendingSelection = false;
832 if (fTable.getSelection().length > 0) {
833 Event e = new Event();
834 e.item = fTable.getSelection()[0];
835 fTable.notifyListeners(SWT.Selection, e);
836 }
837 }
838 }
839
02023181
MK
840 /**
841 * Method setColumnHeaders.
3934297e 842 * @param columnData ColumnData[] the columndata array.
02023181 843 */
631d853f
PT
844 public void setColumnHeaders(ColumnData columnData[]) {
845 for (int i = 0; i < columnData.length; i++) {
846 TableColumn column = new TableColumn(fTable, columnData[i].alignment, i);
847 column.setText(columnData[i].header);
848 if (columnData[i].width > 0) {
849 column.setWidth(columnData[i].width);
850 } else {
851 column.pack();
852 }
853 }
854 }
855
02023181
MK
856 /**
857 * Method removeAll.
858 * @return int 0 the number of elements in the table
859 */
631d853f
PT
860 public int removeAll() {
861 setItemCount(0);
862 fSlider.setMaximum(0);
863 fTable.removeAll();
864 fSelectedEventRank = fFrozenRowCount;
865 return 0;
866 }
867
02023181
MK
868 /**
869 * Method refreshTable.
3934297e 870 * @return boolean did all the items regresh properly?
02023181 871 */
631d853f
PT
872 private boolean refreshTable() {
873 boolean done = true;
874 for (int i = 0; i < fTableRows; i++) {
875 if (i + fTableTopEventRank < fTableItemCount) {
876 TableItem tableItem;
877 if (i < fTable.getItemCount()) {
878 tableItem = fTable.getItem(i);
879 } else {
880 tableItem = new TableItem(fTable, SWT.NONE);
881 }
882 done &= setDataItem(i, tableItem); // false if table item not updated yet in this thread
883 } else {
884 if (fTable.getItemCount() > fTableItemCount - fTableTopEventRank) {
885 fTable.remove(fTableItemCount - fTableTopEventRank);
886 }
887 }
888 }
889
890 int lastRowOffset = fTableTopEventRank + fTableRows - 1;
891 if (fSelectedEventRank < fFrozenRowCount) {
892 fTable.select(fSelectedEventRank);
893 } else if (!done) {
894 fTable.deselectAll();
895 } else if ((fSelectedEventRank >= fTableTopEventRank + fFrozenRowCount) && (fSelectedEventRank <= lastRowOffset)) {
896 int selectedRow = fSelectedEventRank - fTableTopEventRank;
897 fTable.select(selectedRow);
898 } else {
899 fTable.deselectAll();
900 }
901 return done;
902 }
903
02023181
MK
904 /**
905 * Method setSelection.
3934297e 906 * @param i int the item number to select in the table.
02023181 907 */
631d853f
PT
908 public void setSelection(int i) {
909 if (fTableItemCount > 0) {
910 i = Math.min(i, fTableItemCount - 1);
911 i = Math.max(i, 0);
912
913 fSelectedEventRank = i;
914 if ((i < fTableTopEventRank + fFrozenRowCount && i >= fFrozenRowCount) ||
915 (i >= fTableTopEventRank + fFullyVisibleRows)) {
916 fTableTopEventRank = Math.max(0, i - fFrozenRowCount - fFullyVisibleRows / 2);
917 }
918 if (fFullyVisibleRows < fTableItemCount) {
919 fSlider.setSelection(fTableTopEventRank);
920 }
921
922 refreshTable();
923
924 }
925 }
926
02023181
MK
927 /**
928 * Method getSelectionIndex.
929 * @return int the table index of the selected event. not necessarrily the index of the event due to filtering.
930 */
631d853f
PT
931 public int getSelectionIndex() {
932 int index = fTable.getSelectionIndex();
933 if (index == -1) {
934 return fSelectedEventRank;
935 }
936 if (index < fFrozenRowCount) {
937 return index;
938 } else {
939 return (index - fFrozenRowCount) + getTopIndex();
940 }
941 }
942
02023181
MK
943 /**
944 * Method setFrozenRowCount.
945 * @param count int the number of rows to freeze from the top row
946 */
631d853f
PT
947 public void setFrozenRowCount(int count) {
948 fFrozenRowCount = count;
949 refreshTable();
950 }
951
02023181
MK
952 /**
953 * Method createTableEditor.
954 * @return a TableEditor of the table
955 */
631d853f
PT
956 public TableEditor createTableEditor() {
957 return new TableEditor(fTable);
958 }
959
02023181
MK
960 /**
961 * Method createTableEditorControl.
962 * @param control Class<? extends Control>
963 * @return Control
964 */
631d853f
PT
965 public Control createTableEditorControl(Class<? extends Control> control) {
966 try {
420bceb2 967 return control.getConstructor(Composite.class, int.class).newInstance(new Object[] {fTable, SWT.NONE});
631d853f
PT
968 } catch (Exception e) {
969 Activator.getDefault().logError("Error creating table editor control", e); //$NON-NLS-1$
970 }
971 return null;
972 }
973
974 /**
975 * @return the tooltipProvider
02023181 976 */
631d853f
PT
977 public TooltipProvider getTooltipProvider() {
978 return tooltipProvider;
979 }
980
981 /**
982 * @param tooltipProvider the tooltipProvider to set
983 */
984 public void setTooltipProvider(TooltipProvider tooltipProvider) {
985 this.tooltipProvider = tooltipProvider;
986 }
987
988 /**
989 * @return the doubleClickListener
02023181 990 */
631d853f
PT
991 public IDoubleClickListener getDoubleClickListener() {
992 return doubleClickListener;
993 }
994
995 /**
996 * @param doubleClickListener the doubleClickListener to set
997 */
998 public void setDoubleClickListener(IDoubleClickListener doubleClickListener) {
999 this.doubleClickListener = doubleClickListener;
1000 }
1001
9ccc6d01 1002}
This page took 0.098749 seconds and 5 git commands to generate.