LTTng: Handle cancellation of login gracefully (bug 392197)
[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;
432 if (selectedRow >= fFullyVisibleRows) {
433 fTableTopEventRank++;
434 needsRefresh = true;
435 }
436 }
437 break;
438 }
439
440 case SWT.ARROW_UP: {
441 event.doit = false;
442 if (fSelectedEventRank > 0) {
443 fSelectedEventRank--;
444 selectedRow = fSelectedEventRank - fTableTopEventRank;
445 if (selectedRow < fFrozenRowCount && fTableTopEventRank > 0) {
446 fTableTopEventRank--;
447 needsRefresh = true;
448 }
449 }
450 break;
451 }
452
453 case SWT.END: {
454 event.doit = false;
455 fTableTopEventRank = lastPageTopEntryRank;
456 fSelectedEventRank = lastEventRank;
457 needsRefresh = true;
458 break;
459 }
460
461 case SWT.HOME: {
462 event.doit = false;
463 fSelectedEventRank = fFrozenRowCount;
464 fTableTopEventRank = 0;
465 needsRefresh = true;
466 break;
467 }
468
469 case SWT.PAGE_DOWN: {
470 event.doit = false;
471 if (fSelectedEventRank < lastEventRank) {
472 fSelectedEventRank += fFullyVisibleRows;
473 if (fSelectedEventRank > lastEventRank) {
474 fSelectedEventRank = lastEventRank;
475 }
476 selectedRow = fSelectedEventRank - fTableTopEventRank;
477 if (selectedRow > fFullyVisibleRows - 1) {
478 fTableTopEventRank += fFullyVisibleRows;
479 if (fTableTopEventRank > lastPageTopEntryRank) {
480 fTableTopEventRank = lastPageTopEntryRank;
481 }
482 needsRefresh = true;
483 }
484 }
485 break;
486 }
487
488 case SWT.PAGE_UP: {
489 event.doit = false;
490 if (fSelectedEventRank > 0) {
491 fSelectedEventRank -= fFullyVisibleRows;
492 if (fSelectedEventRank < fFrozenRowCount) {
493 fSelectedEventRank = fFrozenRowCount;
494 }
495 selectedRow = fSelectedEventRank - fTableTopEventRank;
496 if (selectedRow < 0) {
497 fTableTopEventRank -= fFullyVisibleRows;
498 if (fTableTopEventRank < 0) {
499 fTableTopEventRank = 0;
500 }
501 needsRefresh = true;
502 }
503 }
504 break;
505 }
506 default: {
507 return;
508 }
509 }
510
511 boolean done = true;
512 if (needsRefresh) {
513 done = refreshTable(); // false if table items not updated yet in this thread
514 } else {
515 fTable.select(selectedRow);
516 }
517
518 if (fFullyVisibleRows < fTableItemCount) {
519 fSlider.setSelection(fTableTopEventRank);
520 }
521
420bceb2 522 if (fSelectedEventRank != previousSelectedEventRank && fSelectedEventRank < fTableItemCount) {
631d853f
PT
523 if (done) {
524 Event e = new Event();
525 e.item = fTable.getSelection()[0];
526 fTable.notifyListeners(SWT.Selection, e);
527 } else {
528 fPendingSelection = true;
529 }
530 }
531 }
532
02023181
MK
533 /**
534 * Method setDataItem.
535 * @param index int
536 * @param item TableItem
537 * @return boolean
538 */
631d853f
PT
539 private boolean setDataItem(int index, TableItem item) {
540 if (index != -1) {
541 Event event = new Event();
542 event.item = item;
543 if (index < fFrozenRowCount) {
544 event.index = index;
545 } else {
546 event.index = index + fTableTopEventRank;
547 }
548 event.doit = true;
549 fTable.notifyListeners(SWT.SetData, event);
550 return event.doit; // false if table item not updated yet in this thread
551 }
552 return true;
553 }
554
555 // ------------------------------------------------------------------------
556 // Slider handling
557 // ------------------------------------------------------------------------
558
02023181
MK
559 /**
560 * Method createSlider.
561 * @param style int
562 */
631d853f
PT
563 private void createSlider(int style) {
564 fSlider = new Slider(this, SWT.VERTICAL | SWT.NO_FOCUS);
565 fSlider.setMinimum(0);
566 fSlider.setMaximum(0);
567 if ((style & SWT.V_SCROLL) == 0) {
568 fSlider.setVisible(false);
569 }
570
571 fSlider.addListener(SWT.Selection, new Listener() {
572 @Override
573 public void handleEvent(Event event) {
574 switch (event.detail) {
575 case SWT.ARROW_DOWN:
576 case SWT.ARROW_UP:
577 case SWT.NONE:
578 case SWT.END:
579 case SWT.HOME:
580 case SWT.PAGE_DOWN:
581 case SWT.PAGE_UP: {
582 fTableTopEventRank = fSlider.getSelection();
583 refreshTable();
584 break;
585 }
abbdd66a
AM
586 default:
587 break;
631d853f
PT
588 }
589 }
590 });
591 }
592
593 // ------------------------------------------------------------------------
594 // Simulated Table API
595 // ------------------------------------------------------------------------
596
02023181
MK
597 /**
598 * Method setHeaderVisible.
599 * @param b boolean
600 */
631d853f
PT
601 public void setHeaderVisible(boolean b) {
602 fTable.setHeaderVisible(b);
603 }
604
02023181
MK
605 /**
606 * Method setLinesVisible.
607 * @param b boolean
608 */
631d853f
PT
609 public void setLinesVisible(boolean b) {
610 fTable.setLinesVisible(b);
611 }
612
02023181 613 /**
3934297e 614 * Method getSelection.
02023181
MK
615 * @return TableItem[] the items that are selected.
616 */
631d853f
PT
617 public TableItem[] getSelection() {
618 return fTable.getSelection();
619 }
620
02023181
MK
621 /**
622 * Method addListener.
623 * @param eventType int
624 * @param listener Listener
625 */
631d853f 626 @Override
828e5592
PT
627 public void addListener(int eventType, Listener listener) {
628 fTable.addListener(eventType, listener);
629 }
631d853f 630
02023181
MK
631 /**
632 * Method addKeyListener.
633 * @param listener KeyListener
634 */
631d853f
PT
635 @Override
636 public void addKeyListener(KeyListener listener) {
637 fTable.addKeyListener(listener);
638 }
b21305c2 639
828e5592 640
02023181
MK
641 /**
642 * Method addMouseListener.
643 * @param listener MouseListener
644 */
828e5592 645 @Override
631d853f
PT
646 public void addMouseListener(MouseListener listener) {
647 fTable.addMouseListener(listener);
648 }
649
02023181
MK
650 /**
651 * Method addSelectionListener.
652 * @param listener SelectionListener
653 */
631d853f
PT
654 public void addSelectionListener(SelectionListener listener) {
655 fTable.addSelectionListener(listener);
656 }
657
02023181
MK
658 /**
659 * Method setMenu sets the menu
660 * @param menu Menu the menu
661 */
631d853f
PT
662 @Override
663 public void setMenu(Menu menu) {
664 fTable.setMenu(menu);
665 }
666
02023181 667 /**
3934297e 668 * Method clearAll empties a table.
02023181 669 */
631d853f
PT
670 public void clearAll() {
671 setItemCount(0);
672 }
673
02023181
MK
674 /**
675 * Method setItemCount
676 * @param nbItems int the number of items in the table
3934297e 677 *
02023181 678 */
631d853f
PT
679 public void setItemCount(int nbItems) {
680 nbItems = Math.max(0, nbItems);
681
682 if (nbItems != fTableItemCount) {
683 fTableItemCount = nbItems;
684 fTable.remove(fTableItemCount, fTable.getItemCount() - 1);
685 fSlider.setMaximum(nbItems);
686 resize();
687 int tableHeight = Math.max(0, fTable.getClientArea().height - fTable.getHeaderHeight());
688 fFullyVisibleRows = tableHeight / getItemHeight();
689 if (fTableItemCount > 0) {
690 fSlider.setThumb(Math.max(1, Math.min(fTableRows, fFullyVisibleRows)));
691 }
692 }
693 }
694
02023181
MK
695 /**
696 * Method getItemCount.
697 * @return int the number of items in the table
698 */
631d853f
PT
699 public int getItemCount() {
700 return fTableItemCount;
701 }
702
02023181
MK
703 /**
704 * Method getItemHeight.
705 * @return int the height of a table item in pixels. (may vary from one os to another)
706 */
631d853f
PT
707 public int getItemHeight() {
708 /*
709 * Bug in Linux. The method getItemHeight doesn't always return the correct value.
710 */
711 if (fLinuxItemHeight >= 0 && System.getProperty("os.name").contains("Linux")) { //$NON-NLS-1$ //$NON-NLS-2$
712 if (fLinuxItemHeight != 0) {
713 return fLinuxItemHeight;
714 }
715 if (fTable.getItemCount() > 1) {
716 int itemHeight = fTable.getItem(1).getBounds().y - fTable.getItem(0).getBounds().y;
717 if (itemHeight > 0) {
718 fLinuxItemHeight = itemHeight;
719 return fLinuxItemHeight;
720 }
721 }
722 } else {
723 fLinuxItemHeight = -1; // Not Linux, don't perform os.name check anymore
724 }
725 return fTable.getItemHeight();
726 }
727
02023181
MK
728 /**
729 * Method getHeaderHeight.
730 * @return int get the height of the header in pixels.
731 */
ea08e8ed
PT
732 public int getHeaderHeight() {
733 return fTable.getHeaderHeight();
734 }
735
02023181
MK
736 /**
737 * Method getTopIndex.
738 * @return int get the first data item index, if you have a header it is offset.
739 */
631d853f
PT
740 public int getTopIndex() {
741 return fTableTopEventRank + fFrozenRowCount;
742 }
743
02023181
MK
744 /**
745 * Method setTopIndex.
3934297e 746 * @param i int suggested top index for the table.
02023181 747 */
631d853f
PT
748 public void setTopIndex(int i) {
749 if (fTableItemCount > 0) {
750 i = Math.min(i, fTableItemCount - 1);
751 i = Math.max(i, fFrozenRowCount);
752
753 fTableTopEventRank = i - fFrozenRowCount;
754 if (fFullyVisibleRows < fTableItemCount) {
755 fSlider.setSelection(fTableTopEventRank);
756 }
757
758 refreshTable();
759 }
760 }
761
02023181
MK
762 /**
763 * Method indexOf. Return the index of a table item
764 * @param ti TableItem the table item to search for in the table
3934297e 765 * @return int the index of the first match. (there should only be one match)
02023181 766 */
631d853f
PT
767 public int indexOf(TableItem ti) {
768 int index = fTable.indexOf(ti);
769 if (index < fFrozenRowCount) {
770 return index;
631d853f 771 }
abbdd66a 772 return (index - fFrozenRowCount) + getTopIndex();
631d853f
PT
773 }
774
02023181
MK
775 /**
776 * Method getColumns.
3934297e 777 * @return TableColumn[] the table columns
02023181 778 */
631d853f
PT
779 public TableColumn[] getColumns() {
780 return fTable.getColumns();
781 }
782
02023181
MK
783 /**
784 * Method getItem.
785 * @param point Point the coordinates in the table
3934297e 786 * @return TableItem the corresponding table item
02023181 787 */
631d853f
PT
788 public TableItem getItem(Point point) {
789 return fTable.getItem(point);
790 }
791
02023181
MK
792 /**
793 * Method resize.
794 */
631d853f
PT
795 private void resize() {
796 // Compute the numbers of rows that fit the new area
797 int tableHeight = Math.max(0, getSize().y - fTable.getHeaderHeight());
798 int itemHeight = getItemHeight();
799 fTableRows = Math.min((tableHeight + itemHeight - 1) / itemHeight, fTableItemCount);
800
801 if (fTableTopEventRank + fFullyVisibleRows > fTableItemCount) {
802 // If we are at the end, get elements before to populate
803 fTableTopEventRank = Math.max(0, fTableItemCount - fFullyVisibleRows);
804 refreshTable();
805 } else if (fTableRows > fTable.getItemCount() || fTableItemCount < fTable.getItemCount()) {
806 // Only refresh if new table items are needed or if table items need to be deleted
807 refreshTable();
808 }
809
810 }
811
812 // ------------------------------------------------------------------------
813 // Controls interactions
814 // ------------------------------------------------------------------------
815
02023181
MK
816 /**
817 * Method setFocus.
818 * @return boolean is this visible?
819 */
631d853f
PT
820 @Override
821 public boolean setFocus() {
822 boolean isVisible = isVisible();
823 if (isVisible) {
824 fTable.setFocus();
825 }
826 return isVisible;
827 }
828
02023181
MK
829 /**
830 * Method refresh.
831 */
631d853f
PT
832 public void refresh() {
833 boolean done = refreshTable();
834 if (fPendingSelection && done) {
835 fPendingSelection = false;
836 if (fTable.getSelection().length > 0) {
837 Event e = new Event();
838 e.item = fTable.getSelection()[0];
839 fTable.notifyListeners(SWT.Selection, e);
840 }
841 }
842 }
843
02023181
MK
844 /**
845 * Method setColumnHeaders.
3934297e 846 * @param columnData ColumnData[] the columndata array.
02023181 847 */
631d853f
PT
848 public void setColumnHeaders(ColumnData columnData[]) {
849 for (int i = 0; i < columnData.length; i++) {
850 TableColumn column = new TableColumn(fTable, columnData[i].alignment, i);
851 column.setText(columnData[i].header);
852 if (columnData[i].width > 0) {
853 column.setWidth(columnData[i].width);
854 } else {
855 column.pack();
856 }
857 }
858 }
859
02023181
MK
860 /**
861 * Method removeAll.
862 * @return int 0 the number of elements in the table
863 */
631d853f
PT
864 public int removeAll() {
865 setItemCount(0);
866 fSlider.setMaximum(0);
867 fTable.removeAll();
868 fSelectedEventRank = fFrozenRowCount;
869 return 0;
870 }
871
02023181
MK
872 /**
873 * Method refreshTable.
3934297e 874 * @return boolean did all the items regresh properly?
02023181 875 */
631d853f
PT
876 private boolean refreshTable() {
877 boolean done = true;
878 for (int i = 0; i < fTableRows; i++) {
879 if (i + fTableTopEventRank < fTableItemCount) {
880 TableItem tableItem;
881 if (i < fTable.getItemCount()) {
882 tableItem = fTable.getItem(i);
883 } else {
884 tableItem = new TableItem(fTable, SWT.NONE);
885 }
886 done &= setDataItem(i, tableItem); // false if table item not updated yet in this thread
887 } else {
888 if (fTable.getItemCount() > fTableItemCount - fTableTopEventRank) {
889 fTable.remove(fTableItemCount - fTableTopEventRank);
890 }
891 }
892 }
893
894 int lastRowOffset = fTableTopEventRank + fTableRows - 1;
895 if (fSelectedEventRank < fFrozenRowCount) {
896 fTable.select(fSelectedEventRank);
897 } else if (!done) {
898 fTable.deselectAll();
899 } else if ((fSelectedEventRank >= fTableTopEventRank + fFrozenRowCount) && (fSelectedEventRank <= lastRowOffset)) {
900 int selectedRow = fSelectedEventRank - fTableTopEventRank;
901 fTable.select(selectedRow);
902 } else {
903 fTable.deselectAll();
904 }
905 return done;
906 }
907
02023181
MK
908 /**
909 * Method setSelection.
3934297e 910 * @param i int the item number to select in the table.
02023181 911 */
631d853f
PT
912 public void setSelection(int i) {
913 if (fTableItemCount > 0) {
914 i = Math.min(i, fTableItemCount - 1);
915 i = Math.max(i, 0);
916
917 fSelectedEventRank = i;
918 if ((i < fTableTopEventRank + fFrozenRowCount && i >= fFrozenRowCount) ||
919 (i >= fTableTopEventRank + fFullyVisibleRows)) {
920 fTableTopEventRank = Math.max(0, i - fFrozenRowCount - fFullyVisibleRows / 2);
921 }
922 if (fFullyVisibleRows < fTableItemCount) {
923 fSlider.setSelection(fTableTopEventRank);
924 }
925
926 refreshTable();
927
928 }
929 }
930
02023181
MK
931 /**
932 * Method getSelectionIndex.
933 * @return int the table index of the selected event. not necessarrily the index of the event due to filtering.
934 */
631d853f
PT
935 public int getSelectionIndex() {
936 int index = fTable.getSelectionIndex();
937 if (index == -1) {
938 return fSelectedEventRank;
939 }
940 if (index < fFrozenRowCount) {
941 return index;
631d853f 942 }
abbdd66a 943 return (index - fFrozenRowCount) + getTopIndex();
631d853f
PT
944 }
945
02023181
MK
946 /**
947 * Method setFrozenRowCount.
948 * @param count int the number of rows to freeze from the top row
949 */
631d853f
PT
950 public void setFrozenRowCount(int count) {
951 fFrozenRowCount = count;
952 refreshTable();
953 }
954
02023181
MK
955 /**
956 * Method createTableEditor.
957 * @return a TableEditor of the table
958 */
631d853f
PT
959 public TableEditor createTableEditor() {
960 return new TableEditor(fTable);
961 }
962
02023181
MK
963 /**
964 * Method createTableEditorControl.
965 * @param control Class<? extends Control>
966 * @return Control
967 */
631d853f
PT
968 public Control createTableEditorControl(Class<? extends Control> control) {
969 try {
420bceb2 970 return control.getConstructor(Composite.class, int.class).newInstance(new Object[] {fTable, SWT.NONE});
631d853f
PT
971 } catch (Exception e) {
972 Activator.getDefault().logError("Error creating table editor control", e); //$NON-NLS-1$
973 }
974 return null;
975 }
976
977 /**
978 * @return the tooltipProvider
02023181 979 */
631d853f
PT
980 public TooltipProvider getTooltipProvider() {
981 return tooltipProvider;
982 }
983
984 /**
985 * @param tooltipProvider the tooltipProvider to set
986 */
987 public void setTooltipProvider(TooltipProvider tooltipProvider) {
988 this.tooltipProvider = tooltipProvider;
989 }
990
991 /**
992 * @return the doubleClickListener
02023181 993 */
631d853f
PT
994 public IDoubleClickListener getDoubleClickListener() {
995 return doubleClickListener;
996 }
997
998 /**
999 * @param doubleClickListener the doubleClickListener to set
1000 */
1001 public void setDoubleClickListener(IDoubleClickListener doubleClickListener) {
1002 this.doubleClickListener = doubleClickListener;
1003 }
1004
9ccc6d01 1005}
This page took 0.080482 seconds and 5 git commands to generate.