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