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