tmf: Periodically refresh virtual table while scroll bar is dragged
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / widgets / rawviewer / TmfRawEventViewer.java
CommitLineData
7d048a33 1/*******************************************************************************
812e7197 2 * Copyright (c) 2010, 2015 Ericsson
7d048a33
PT
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 * Patrick Tasse - Initial API and implementation
11 ******************************************************************************/
12
2bdf0193 13package org.eclipse.tracecompass.tmf.ui.widgets.rawviewer;
7d048a33
PT
14
15import java.util.ArrayList;
16import java.util.List;
17
332c750a 18import org.eclipse.jface.resource.ColorRegistry;
812e7197
PT
19import org.eclipse.jface.resource.FontRegistry;
20import org.eclipse.jface.util.IPropertyChangeListener;
21import org.eclipse.jface.util.PropertyChangeEvent;
7d048a33
PT
22import org.eclipse.swt.SWT;
23import org.eclipse.swt.custom.CaretEvent;
24import org.eclipse.swt.custom.CaretListener;
25import org.eclipse.swt.custom.ScrolledComposite;
26import org.eclipse.swt.custom.StyledText;
27import org.eclipse.swt.events.ControlEvent;
28import org.eclipse.swt.events.ControlListener;
29import org.eclipse.swt.events.KeyEvent;
30import org.eclipse.swt.events.KeyListener;
31import org.eclipse.swt.events.MouseAdapter;
32import org.eclipse.swt.events.MouseEvent;
33import org.eclipse.swt.events.MouseMoveListener;
34import org.eclipse.swt.events.MouseTrackListener;
35import org.eclipse.swt.events.MouseWheelListener;
36import org.eclipse.swt.events.SelectionEvent;
37import org.eclipse.swt.events.SelectionListener;
38import org.eclipse.swt.graphics.Color;
39import org.eclipse.swt.graphics.Font;
7d048a33
PT
40import org.eclipse.swt.graphics.Point;
41import org.eclipse.swt.layout.GridData;
42import org.eclipse.swt.layout.GridLayout;
43import org.eclipse.swt.widgets.Composite;
44import org.eclipse.swt.widgets.Control;
45import org.eclipse.swt.widgets.Display;
46import org.eclipse.swt.widgets.Event;
47import org.eclipse.swt.widgets.Listener;
48import org.eclipse.swt.widgets.Menu;
49import org.eclipse.swt.widgets.Slider;
2bdf0193
AM
50import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
51import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
52import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
53import org.eclipse.tracecompass.tmf.core.trace.location.ITmfLocation;
812e7197
PT
54import org.eclipse.ui.PlatformUI;
55import org.eclipse.ui.themes.IThemeManager;
7d048a33
PT
56
57/**
58 * TmfRawEventViewer allows for the display of the raw data for an arbitrarily
59 * large number of TMF events.
60 *
61 * It is essentially a Composite of a StyledText area and a Slider, where the number
62 * of visible lines in the StyledText control is set to fill the viewer display area.
63 * An underlying data model is used to store a cache of event raw text line data.
64 * The slider is ratio-based.
65 *
66 * @version 1.0
67 * @author Patrick Tasse
68 */
69public class TmfRawEventViewer extends Composite implements ControlListener, SelectionListener,
812e7197 70 KeyListener, CaretListener, MouseMoveListener, MouseTrackListener, MouseWheelListener, IPropertyChangeListener {
7d048a33
PT
71
72 private static final Color COLOR_BACKGROUND_ODD = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);
73 private static final Color COLOR_BACKGROUND_EVEN = new Color(Display.getDefault(), 242, 242, 242);
812e7197 74 private static final String FONT_DEFINITION_ID = "org.eclipse.tracecompass.tmf.ui.font.eventraw"; //$NON-NLS-1$
332c750a
PT
75 private static final String HIGHLIGHT_COLOR_DEFINITION_ID = "org.eclipse.tracecompass.tmf.ui.color.eventraw.highlight"; //$NON-NLS-1$
76 private static final String SELECTION_COLOR_DEFINITION_ID = "org.eclipse.tracecompass.tmf.ui.color.eventraw.selection"; //$NON-NLS-1$
7d048a33
PT
77 private static final int MAX_LINE_DATA_SIZE = 1000;
78 private static final int SLIDER_MAX = 1000000;
79
80 private ITmfTrace fTrace;
81 private ITmfContext fBottomContext;
82
83 private ScrolledComposite fScrolledComposite;
84 private Composite fTextArea;
85 private StyledText fStyledText;
86 private Font fFixedFont;
332c750a
PT
87 private Color fHighlightColor;
88 private Color fSelectionColor;
d5efe032
AF
89 private Slider fSlider;
90
91 private final List<LineData> fLines = new ArrayList<>();
92 private boolean fActualRanks = false;
93 private int fTopLineIndex;
94 private int fLastTopLineIndex;
95 private final CaretPosition[] fStoredCaretPosition = new CaretPosition[]
96 { new CaretPosition(0, 0), new CaretPosition(0,0)};
97 private int fNumVisibleLines;
7d048a33
PT
98 private ITmfLocation fSelectedLocation = null;
99 private long fHighlightedRank = Long.MIN_VALUE;
100 private int fCursorYCoordinate = -1;
101 private int fHoldSelection = 0;
102
d5efe032
AF
103 private static class LineData {
104 long rank;
105 ITmfLocation location;
106 String string;
107 public LineData(long rank, ITmfLocation location, String string) {
108 this.rank = rank;
109 this.location = location;
7d048a33
PT
110 if (string.length() == 0) {
111 this.string = " "; // workaround for setLineBackground has no effect on empty line //$NON-NLS-1$
112 } else {
113 this.string = string;
114 }
d5efe032 115 }
7d048a33
PT
116 @Override
117 public String toString() {
118 return rank + " [" + location + "]: " + string; //$NON-NLS-1$ //$NON-NLS-2$
119 }
d5efe032
AF
120 }
121
122 private static class CaretPosition {
123 int time;
124 int caretOffset;
125 public CaretPosition(int time, int caretOffset) {
126 this.time = time;
127 this.caretOffset = caretOffset;
128 }
129 }
130
131 // ------------------------------------------------------------------------
132 // Constructor
133 // ------------------------------------------------------------------------
134
135 /**
136 * Constructor
137 * @param parent The parent composite
138 * @param style The style bits
139 */
140 public TmfRawEventViewer(Composite parent, int style) {
141 super(parent, style & (~SWT.H_SCROLL) & (~SWT.V_SCROLL));
142
143 // Set the layout
144 GridLayout gridLayout = new GridLayout();
145 gridLayout.numColumns = 2;
146 gridLayout.horizontalSpacing = 0;
147 gridLayout.verticalSpacing = 0;
7d048a33
PT
148 gridLayout.marginWidth = 0;
149 gridLayout.marginHeight = 0;
d5efe032 150 setLayout(gridLayout);
7d048a33 151
d5efe032
AF
152 // Create the controls
153 createTextArea(style & SWT.H_SCROLL);
154 createSlider(style & SWT.V_SCROLL);
7d048a33 155
d5efe032
AF
156 // Prevent the slider from being traversed
157 setTabList(new Control[] { fScrolledComposite });
158 }
7d048a33
PT
159
160 @Override
d5efe032 161 public void dispose() {
812e7197 162 PlatformUI.getWorkbench().getThemeManager().removePropertyChangeListener(this);
d5efe032
AF
163 super.dispose();
164 }
7d048a33 165
812e7197 166 // ------------------------------------------------------------------------
332c750a 167 // Font and color handling
812e7197
PT
168 // ------------------------------------------------------------------------
169
170 /**
171 * Initialize the fonts.
172 * @since 1.0
173 */
174 protected void initializeFonts() {
175 FontRegistry fontRegistry = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getFontRegistry();
176 fFixedFont = fontRegistry.get(FONT_DEFINITION_ID);
177 fStyledText.setFont(fFixedFont);
178 }
179
332c750a
PT
180 /**
181 * Initialize the colors.
182 * @since 1.0
183 */
184 protected void initializeColors() {
185 ColorRegistry colorRegistry = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry();
186 fHighlightColor = colorRegistry.get(HIGHLIGHT_COLOR_DEFINITION_ID);
187 fSelectionColor = colorRegistry.get(SELECTION_COLOR_DEFINITION_ID);
188 }
189
812e7197
PT
190 /**
191 * @since 1.0
192 */
193 @Override
194 public void propertyChange(PropertyChangeEvent event) {
195 if ((IThemeManager.CHANGE_CURRENT_THEME.equals(event.getProperty())) ||
196 (FONT_DEFINITION_ID.equals(event.getProperty()))) {
197 initializeFonts();
198 refreshTextArea();
199 }
332c750a
PT
200 if ((IThemeManager.CHANGE_CURRENT_THEME.equals(event.getProperty())) ||
201 (HIGHLIGHT_COLOR_DEFINITION_ID.equals(event.getProperty())) ||
202 (SELECTION_COLOR_DEFINITION_ID.equals(event.getProperty()))) {
203 initializeColors();
204 refreshTextArea();
205 }
812e7197
PT
206 }
207
d5efe032
AF
208 // ------------------------------------------------------------------------
209 // Text area handling
210 // ------------------------------------------------------------------------
7d048a33
PT
211
212 /**
d5efe032
AF
213 * Create the text area and add listeners
214 */
215 private void createTextArea(int style) {
216 fScrolledComposite = new ScrolledComposite(this, style);
217 fScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
218 fTextArea = new Composite(fScrolledComposite, SWT.NONE);
7d048a33
PT
219 fTextArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
220 fScrolledComposite.setContent(fTextArea);
221 fScrolledComposite.setExpandHorizontal(true);
222 fScrolledComposite.setExpandVertical(true);
223 fScrolledComposite.setAlwaysShowScrollBars(true);
224 fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
225 fScrolledComposite.addControlListener(this);
226
227 GridLayout textAreaGridLayout = new GridLayout();
228 textAreaGridLayout.marginHeight = 0;
229 textAreaGridLayout.marginWidth = 0;
230 fTextArea.setLayout(textAreaGridLayout);
231
7d048a33 232 fStyledText = new StyledText(fTextArea, SWT.READ_ONLY);
7d048a33
PT
233 fStyledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
234
812e7197 235 initializeFonts();
332c750a 236 initializeColors();
812e7197
PT
237 PlatformUI.getWorkbench().getThemeManager().addPropertyChangeListener(this);
238
7d048a33
PT
239 fStyledText.addCaretListener(this);
240 fStyledText.addMouseMoveListener(this);
241 fStyledText.addMouseTrackListener(this);
242 fStyledText.addMouseWheelListener(this);
243 fStyledText.addListener(SWT.MouseWheel, new Listener() { // disable mouse scroll of horizontal scroll bar
244 @Override
245 public void handleEvent(Event event) { event.doit = false; }});
246 fStyledText.addKeyListener(this);
247
248 fTextArea.setBackground(fStyledText.getBackground());
249 fTextArea.addMouseListener(new MouseAdapter() {
d5efe032 250 @Override
7d048a33 251 public void mouseDown(MouseEvent e) {
d5efe032 252 fTextArea.setFocus();
7d048a33 253 }});
d5efe032 254 }
7d048a33 255
d5efe032
AF
256 // ------------------------------------------------------------------------
257 // Slider handling
258 // ------------------------------------------------------------------------
7d048a33 259
d5efe032
AF
260 private void createSlider(int style) {
261 fSlider = new Slider(this, SWT.VERTICAL);
7d048a33
PT
262 fSlider.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
263 fSlider.setValues(0, 0, SLIDER_MAX, SLIDER_MAX, 1, 1);
d5efe032 264 fSlider.addSelectionListener(this);
7d048a33
PT
265 if ((style & SWT.V_SCROLL) == 0) {
266 fSlider.setVisible(false);
267 }
d5efe032 268 }
7d048a33 269
d5efe032
AF
270 // ------------------------------------------------------------------------
271 // Controls interactions
272 // ------------------------------------------------------------------------
7d048a33 273
d5efe032
AF
274 @Override
275 public boolean setFocus() {
276 boolean isVisible = isVisible();
277 if (isVisible) {
278 fTextArea.setFocus();
279 }
280 return isVisible;
281 }
7d048a33
PT
282
283 @Override
284 public void setMenu(Menu menu) {
285 fStyledText.setMenu(menu);
286 }
287
288 /**
289 * Sets the trace and updates the content
290 * @param trace The trace to set
291 */
292 public void setTrace(ITmfTrace trace) {
d5efe032
AF
293 fTrace = trace;
294 fTopLineIndex = 0;
295 fLines.clear();
296 refreshEventCount();
297 }
7d048a33
PT
298
299 /**
300 * Refreshes the event count, updates the slider thumb and loads display
301 */
d5efe032
AF
302 public void refreshEventCount() {
303 if (fTrace != null) {
304 if (fTrace.getNbEvents() > 0) {
305 fSlider.setThumb((int) Math.max(SLIDER_MAX / fTrace.getNbEvents(), 1));
306 } else {
307 fSlider.setThumb(SLIDER_MAX);
308 }
309
310 if (!isVisible()) {
7d048a33
PT
311 return;
312 }
313
d5efe032
AF
314 if (fLines.size() == 0) {
315 setTopRank(0);
316 } else if (fLines.size() < fNumVisibleLines) {
317 fBottomContext = null;
318 loadLineData();
319 fillTextArea();
320 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
321 fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));
322 }
7d048a33
PT
323 } else {
324 fBottomContext = null;
325 fillTextArea();
326 fSlider.setThumb(SLIDER_MAX);
327 fSlider.setSelection(0);
d5efe032
AF
328 }
329 }
7d048a33 330
d5efe032
AF
331 /**
332 * Selects the event of given rank and makes it visible.
333 * @param rank The rank of event
334 */
7d048a33
PT
335 public void selectAndReveal(long rank) {
336 if (fTrace == null || !isVisible()) {
337 return;
338 }
339 if (fActualRanks && fTopLineIndex < fLines.size() && rank >= fLines.get(fTopLineIndex).rank) {
340 int lastVisibleIndex = Math.min(fTopLineIndex + fNumVisibleLines, fLines.size()) - 1;
341 if (rank <= fLines.get(lastVisibleIndex).rank) {
342 for (int i = fTopLineIndex; i < fLines.size(); i++) {
343 if (fLines.get(i).rank == rank) {
344 fSelectedLocation = fLines.get(i).location;
345 break;
346 }
347 }
348 refreshLineBackgrounds();
349 return;
350 }
351 }
352 setTopRank(rank);
353 if (fLines.size() > 0 && fHoldSelection == 0) {
354 fSelectedLocation = fLines.get(0).location;
355 refreshLineBackgrounds();
356 }
357 }
358
359 /**
360 * Add a selection listener
361 * @param listener A listener to add
362 */
363 public void addSelectionListener(Listener listener) {
364 checkWidget();
365 if (listener == null) {
366 SWT.error (SWT.ERROR_NULL_ARGUMENT);
367 }
368 addListener (SWT.Selection, listener);
369 }
370
371 /**
372 * Remove selection listener
373 * @param listener A listener to remove
374 */
375 public void removeSelectionListener(Listener listener) {
376 checkWidget();
377 if (listener == null) {
378 SWT.error (SWT.ERROR_NULL_ARGUMENT);
379 }
380 removeListener(SWT.Selection, listener);
381 }
382
383 private void sendSelectionEvent(LineData lineData) {
384 Event event = new Event();
385 if (fActualRanks) {
386 event.data = Long.valueOf(lineData.rank);
387 } else {
388 event.data = lineData.location;
389 }
390 notifyListeners(SWT.Selection, event);
391 }
392
393 private void setTopRank(long rank) {
394 fBottomContext = fTrace.seekEvent(rank);
395 if (fBottomContext == null) {
396 return;
397 }
398 fLines.clear();
399 fActualRanks = true;
400 fTopLineIndex = 0;
401 loadLineData();
402 refreshTextArea();
403 if (fLines.size() == 0) {
404 fSlider.setSelection(0);
405 } else {
406 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
407 fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));
408 }
409 }
410
411 private void setTopPosition(double ratio) {
412 fBottomContext = fTrace.seekEvent(ratio);
413 if (fBottomContext == null) {
414 return;
415 }
416 fBottomContext.setRank(0);
417 fLines.clear();
418 fActualRanks = false;
419 fTopLineIndex = 0;
420 loadLineData();
421 refreshTextArea();
422 }
423
d5efe032 424 private void loadLineData() {
7d048a33
PT
425 if (fTopLineIndex < 0) {
426 //if (fLines.size() > 0 && fLines.get(0).rank > 0) {
427 //long endRank = fLines.get(0).rank;
428 //long startRank = Math.max(0, endRank - fNumVisibleLines);
429 //TmfContext context = fTrace.seekEvent(startRank);
430 //int index = 0;
431 //while (context.getRank() < endRank) {
432 //long rank = context.getRank();
433 //ITmfLocation<?> location = context.getLocation();
434 //TmfEvent event = fTrace.getNextEvent(context);
435 //String[] lines = event.getRawText().split("\r?\n");
436 //for (int i = 0; i < lines.length; i++) {
437 //String line = lines[i];
438 //LineData lineData = new LineData(rank, location, line);
439 //fLines.add(index++, lineData);
440 //fTopLineIndex++;
441 //fLastTopLineIndex++;
442 //}
443 //}
444 //}
445 if (fLines.size() > 0 && fTrace.getLocationRatio(fLines.get(0).location) > 0) {
d5efe032 446 double lastRatio = fTrace.getLocationRatio(fLines.get(fLines.size() - 1).location);
7d048a33
PT
447 double firstRatio = fTrace.getLocationRatio(fLines.get(0).location);
448 double delta;
449 boolean singleEvent = false;
450 if (firstRatio != lastRatio) {
451 // approximate ratio of at least 20 items
452 delta = Math.max(20, fNumVisibleLines) * (lastRatio - firstRatio) / (fLines.size() - 1);
453 } else {
454 delta = Math.pow(10, -15);
455 singleEvent = true;
456 }
457 while (fTopLineIndex < 0) {
458 ITmfLocation endLocation = fLines.get(0).location;
459 firstRatio = Math.max(0, firstRatio - delta);
460 ITmfContext context = fTrace.seekEvent(firstRatio);
461 ITmfLocation location;
462 int index = 0;
463 long rank = 0;
464 while (!context.getLocation().equals(endLocation)) {
465 location = context.getLocation();
466 ITmfEvent event = fTrace.getNext(context);
467 if (event == null) {
d5efe032 468 break;
7d048a33
PT
469 }
470 if (event.getContent() != null && event.getContent().getValue() != null) {
471 String[] lines = event.getContent().getValue().toString().split("\r?\n"); //$NON-NLS-1$
472 for (int i = 0; i < lines.length; i++) {
473 String line = lines[i];
474 LineData lineData = new LineData(rank, location, line);
475 fLines.add(index++, lineData);
476 fTopLineIndex++;
477 fLastTopLineIndex++;
478 }
479 } else {
480 LineData lineData = new LineData(rank, location, ""); //$NON-NLS-1$
481 fLines.add(index++, lineData);
482 fTopLineIndex++;
483 fLastTopLineIndex++;
484 }
485 rank++;
486 }
487 long rankOffset = fLines.get(index).rank - rank;
488 for (int i = 0; i < index; i++) {
489 fLines.get(i).rank += rankOffset;
490 }
491 if (firstRatio == 0) {
492 break;
493 }
494 if (singleEvent) {
d5efe032 495 delta = Math.min(delta * 10, 0.1);
7d048a33
PT
496 }
497 }
498 }
499 if (fTopLineIndex < 0) {
500 fTopLineIndex = 0;
501 }
502 }
503
d5efe032
AF
504 while (fLines.size() - fTopLineIndex < fNumVisibleLines) {
505 if (fBottomContext == null) {
506 if (fLines.size() == 0) {
507 fBottomContext = fTrace.seekEvent(0);
508 } else {
7d048a33 509 //fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).rank + 1);
d5efe032
AF
510 fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).location);
511 fTrace.getNext(fBottomContext);
512 }
513 if (fBottomContext == null) {
514 break;
515 }
516 }
7d048a33
PT
517 long rank = fBottomContext.getRank();
518 ITmfLocation location = fBottomContext.getLocation() != null ? fBottomContext.getLocation() : null;
519 ITmfEvent event = fTrace.getNext(fBottomContext);
520 if (event == null) {
521 break;
522 }
523 if (event.getContent() != null && event.getContent().getValue() != null) {
524 for (String line : event.getContent().getValue().toString().split("\r?\n")) { //$NON-NLS-1$
525 int crPos;
526 if ((crPos = line.indexOf('\r')) != -1) {
d5efe032 527 line = line.substring(0, crPos);
7d048a33
PT
528 }
529 LineData lineData = new LineData(rank, location, line);
530 fLines.add(lineData);
531 }
532 } else {
533 LineData lineData = new LineData(rank, location, ""); //$NON-NLS-1$
534 fLines.add(lineData);
535 }
d5efe032
AF
536 }
537 fTopLineIndex = Math.max(0, Math.min(fTopLineIndex, fLines.size() - 1));
538
539 if (fLines.size() > MAX_LINE_DATA_SIZE) {
540 if (fTopLineIndex < MAX_LINE_DATA_SIZE / 2) {
541 long rank = fLines.get(MAX_LINE_DATA_SIZE - 1).rank;
542 for (int i = MAX_LINE_DATA_SIZE; i < fLines.size(); i++) {
543 if (fLines.get(i).rank > rank) {
544 fLines.subList(i, fLines.size()).clear();
545 fBottomContext = null;
546 break;
547 }
548 }
549 } else {
550 long rank = fLines.get(fLines.size() - MAX_LINE_DATA_SIZE).rank;
551 for (int i = fLines.size() - MAX_LINE_DATA_SIZE - 1; i >= 0; i--) {
7d048a33
PT
552 if (fLines.get(i).rank < rank) {
553 fLines.subList(0, i + 1).clear();
554 fTopLineIndex -= (i + 1);
555 fLastTopLineIndex -= (i + 1);
556 break;
557 }
d5efe032
AF
558 }
559 }
560 }
561 }
7d048a33
PT
562
563 private void refreshTextArea() {
564 fStyledText.setText(""); //$NON-NLS-1$
565 for (int i = 0; i < fLines.size() - fTopLineIndex && i < fNumVisibleLines; i++) {
566 if (i > 0)
567 {
568 fStyledText.append("\n"); //$NON-NLS-1$
569 }
570 LineData lineData = fLines.get(fTopLineIndex + i);
571 fStyledText.append(lineData.string);
572 setLineBackground(i, lineData);
573 }
574 fTextArea.layout();
575 fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
576 fLastTopLineIndex = fTopLineIndex;
577 }
578
579 private void fillTextArea() {
580 int nextLine = fStyledText.getCharCount() == 0 ? 0 : fStyledText.getLineCount();
581 for (int i = nextLine; i < fLines.size() - fTopLineIndex && i < fNumVisibleLines; i++) {
582 if (i > 0)
583 {
584 fStyledText.append("\n"); //$NON-NLS-1$
585 }
586 LineData lineData = fLines.get(fTopLineIndex + i);
587 fStyledText.append(lineData.string);
588 setLineBackground(i, lineData);
589 }
590 int endLine = Math.min(fNumVisibleLines, fLines.size());
591 if (endLine < fStyledText.getLineCount()) {
d5efe032
AF
592 int endOffset = fStyledText.getOffsetAtLine(endLine) - 1;
593 if (endOffset > fStyledText.getCharCount()) {
7d048a33 594 fHoldSelection++;
d5efe032 595 fStyledText.replaceTextRange(endOffset, fStyledText.getCharCount() - endOffset, ""); //$NON-NLS-1$
7d048a33 596 fHoldSelection--;
d5efe032 597 }
7d048a33
PT
598 }
599 fTextArea.layout();
600 fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
601 }
602
d5efe032
AF
603 private void updateTextArea() {
604 if (fTopLineIndex < fLastTopLineIndex) {
605 StringBuffer insertedText = new StringBuffer();
606 for (int i = fTopLineIndex; i < fLastTopLineIndex; i++) {
607 insertedText.append(fLines.get(i).string + "\n"); //$NON-NLS-1$
608 }
609 fStyledText.replaceTextRange(0, 0, insertedText.toString());
7d048a33
PT
610 for (int i = 0; i < fLastTopLineIndex - fTopLineIndex; i++) {
611 LineData lineData = fLines.get(fTopLineIndex + i);
612 setLineBackground(i, lineData);
613 }
d5efe032
AF
614 fLastTopLineIndex = fTopLineIndex;
615 } else if (fTopLineIndex > fLastTopLineIndex) {
616 int length = 0;
617 for (int i = 0; i < fTopLineIndex - fLastTopLineIndex && i < fNumVisibleLines; i++) {
618 length += fLines.get(i + fLastTopLineIndex).string.length();
619 if (i < fStyledText.getLineCount()) {
7d048a33
PT
620 length += 1;
621 }
d5efe032
AF
622 }
623 fStyledText.replaceTextRange(0, length, ""); //$NON-NLS-1$
7d048a33
PT
624 fLastTopLineIndex = fTopLineIndex;
625 fillTextArea();
d5efe032 626 }
7d048a33
PT
627 int endLine = Math.min(fNumVisibleLines, fLines.size());
628 if (endLine < fStyledText.getLineCount()) {
d5efe032
AF
629 int endOffset = fStyledText.getOffsetAtLine(endLine) - 1;
630 if (endOffset > fStyledText.getCharCount()) {
631 fStyledText.replaceTextRange(endOffset, fStyledText.getCharCount() - endOffset, ""); //$NON-NLS-1$
632 }
7d048a33 633 }
d5efe032
AF
634 fTextArea.layout();
635 fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
636 }
7d048a33 637
d5efe032 638 private void refreshLineBackgrounds() {
7d048a33
PT
639 for (int i = 0; (i < fStyledText.getLineCount()) && (i < fNumVisibleLines) && (i < fLines.size() - fTopLineIndex); i++) {
640 LineData lineData = fLines.get(fTopLineIndex + i);
641 setLineBackground(i, lineData);
642 }
d5efe032 643 }
7d048a33 644
d5efe032 645 private void setLineBackground(int index, LineData lineData) {
7d048a33 646 if (lineData.location.equals(fSelectedLocation)) {
332c750a 647 fStyledText.setLineBackground(index, 1, fSelectionColor);
7d048a33 648 } else if (lineData.rank == fHighlightedRank) {
332c750a 649 fStyledText.setLineBackground(index, 1, fHighlightColor);
7d048a33
PT
650 } else if (lineData.rank % 2 == 0) {
651 fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_EVEN);
652 } else {
653 fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_ODD);
654 }
d5efe032
AF
655 }
656
657 private void storeCaretPosition(int time, int caretOffset) {
658 if (fStoredCaretPosition[0].time == time) {
659 fStoredCaretPosition[0].caretOffset = caretOffset;
660 } else {
661 fStoredCaretPosition[1] = fStoredCaretPosition[0];
662 fStoredCaretPosition[0] = new CaretPosition(time, caretOffset);
663 }
664 }
665
666 private int getPreviousCaretOffset(int time) {
667 if (fStoredCaretPosition[0].time == time) {
668 return fStoredCaretPosition[1].caretOffset;
669 }
7d048a33 670 return fStoredCaretPosition[0].caretOffset;
d5efe032 671 }
7d048a33 672
d5efe032 673 private void updateHighlightedRank() {
7d048a33
PT
674 if (fCursorYCoordinate < 0 || fCursorYCoordinate > fStyledText.getSize().y) {
675 if (fHighlightedRank != Long.MIN_VALUE) {
676 fHighlightedRank = Long.MIN_VALUE;
677 refreshLineBackgrounds();
678 }
679 return;
680 }
681 int offset = fStyledText.getOffsetAtLocation(new Point(0, fCursorYCoordinate));
682 int line = fStyledText.getLineAtOffset(offset);
683 if (line < fLines.size() - fTopLineIndex) {
684 LineData lineData = fLines.get(fTopLineIndex + line);
685 if (fHighlightedRank != lineData.rank) {
686 fHighlightedRank = lineData.rank;
687 refreshLineBackgrounds();
688 }
689 } else {
690 if (fHighlightedRank != Long.MIN_VALUE) {
691 fHighlightedRank = Long.MIN_VALUE;
692 refreshLineBackgrounds();
693 }
694 }
d5efe032 695 }
7d048a33
PT
696
697 // ------------------------------------------------------------------------
698 // ControlListener (ScrolledComposite)
699 // ------------------------------------------------------------------------
700
701 @Override
702 public void controlResized(ControlEvent event) {
703 int areaHeight = fScrolledComposite.getSize().y;
704 if (fScrolledComposite.getHorizontalBar() != null) {
705 areaHeight -= fScrolledComposite.getHorizontalBar().getSize().y;
706 }
707 int lineHeight = fStyledText.getLineHeight();
708 fNumVisibleLines = Math.max((areaHeight + lineHeight - 1) / lineHeight, 1);
709
710 if (fBottomContext != null) {
711 loadLineData();
712 fillTextArea();
713 }
714 }
715
716 @Override
717 public void controlMoved(ControlEvent e) {
718 }
719
720 // ------------------------------------------------------------------------
721 // SelectionListener (Slider)
722 // ------------------------------------------------------------------------
723
724 @Override
725 public void widgetSelected(SelectionEvent e) {
d5efe032 726 fTextArea.setFocus();
7d048a33
PT
727 if (fLines.size() == 0) {
728 return;
729 }
730 if (e.detail == SWT.DRAG) {
731 return;
732 }
733 fHoldSelection++;
734 switch (e.detail) {
735 case SWT.NONE: {
736 //long rank = (long) (fTrace.getNbEvents() * ((double) fSlider.getSelection() / SLIDER_MAX));
737 //setTopRank(rank);
d5efe032 738 if (fSlider.getSelection() == 0 || fSlider.getThumb() == SLIDER_MAX) {
7d048a33
PT
739 fLines.clear();
740 setTopPosition(0.0);
741 break;
d5efe032 742 }
7d048a33
PT
743 double ratio = (double) fSlider.getSelection() / (SLIDER_MAX - fSlider.getThumb());
744 double delta = Math.pow(10, -15);
745 fLines.clear();
746 while (fLines.size() == 0) {
747 setTopPosition(ratio);
748 if (ratio == 0.0) {
749 break;
750 }
751 delta = Math.min(delta * 10, 0.1);
752 ratio = Math.max(ratio - delta, 0.0);
753 }
754 break;
755 }
756 case SWT.ARROW_DOWN: {
757 if (fTopLineIndex >= fLines.size()) {
758 break;
759 }
760 fTopLineIndex++;
761 loadLineData();
762 updateTextArea();
763 break;
764 }
765 case SWT.PAGE_DOWN: {
766 fTopLineIndex += Math.max(fNumVisibleLines - 1, 1);
767 loadLineData();
768 updateTextArea();
769 break;
770 }
771 case SWT.ARROW_UP: {
772 //if (fLines.size() == 0 || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
773 if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
774 break;
775 }
776 fTopLineIndex--;
777 loadLineData();
778 updateTextArea();
779 break;
780 }
781 case SWT.PAGE_UP: {
782 fTopLineIndex -= Math.max(fNumVisibleLines - 1, 1);
783 loadLineData();
784 updateTextArea();
785 break;
786 }
787 case SWT.HOME: {
788 //selectAndReveal(0);
789 setTopPosition(0.0);
790 break;
791 }
792 case SWT.END: {
793 //if (fTrace.getNbEvents() > 0) {
794 //selectAndReveal(fTrace.getNbEvents() - 1);
795 //}
796 double ratio = 1.0;
797 double delta = Math.pow(10, -15);
798 fLines.clear();
799 while (fLines.size() == 0) {
800 setTopPosition(ratio);
801 if (ratio == 0.0) {
802 break;
803 }
804 delta = Math.min(delta * 10, 0.1);
805 ratio = Math.max(ratio - delta, 0.0);
806 }
807 break;
808 }
809 default:
810 break;
811 }
812 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
813 if (e.detail != SWT.NONE) {
814 fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));
815 }
816
817 fHoldSelection = 0;
818 }
819
820 @Override
821 public void widgetDefaultSelected(SelectionEvent e) {
822 }
823
824 // ------------------------------------------------------------------------
825 // KeyListener (StyledText)
826 // ------------------------------------------------------------------------
827
828 @Override
829 public void keyPressed(KeyEvent e) {
830 if (fLines.size() == 0) {
831 return;
832 }
833 int caretOffset = fStyledText.getCaretOffset();
834 int previousCaretOffset = getPreviousCaretOffset(e.time);
835 int previousLineAtCaretPosition = fStyledText.getLineAtOffset(previousCaretOffset);
836 int previousColumnAtCaretPosition = getPreviousCaretOffset(e.time) - fStyledText.getOffsetAtLine(previousLineAtCaretPosition);
837 switch (e.keyCode) {
838 case SWT.ARROW_DOWN: {
839 if (previousLineAtCaretPosition < (fNumVisibleLines - 2)) {
840 break;
841 }
842 fHoldSelection++;
843 fTopLineIndex++;
844 loadLineData();
845 updateTextArea();
846 fHoldSelection--;
847 LineData lineData = fLines.get(fTopLineIndex + fStyledText.getLineAtOffset(fStyledText.getCaretOffset()));
848 if (!lineData.location.equals(fSelectedLocation)) {
849 fSelectedLocation = lineData.location;
850 refreshLineBackgrounds();
851 sendSelectionEvent(lineData);
852 }
853 break;
854 }
855 case SWT.PAGE_DOWN: {
856 if (previousLineAtCaretPosition >= (fNumVisibleLines - 1)) {
857 fHoldSelection++;
858 if (fLines.get(fTopLineIndex + previousLineAtCaretPosition).rank % 2 == 0) {
859 fStyledText.setLineBackground(previousLineAtCaretPosition, 1, COLOR_BACKGROUND_EVEN);
860 } else {
861 fStyledText.setLineBackground(previousLineAtCaretPosition, 1, COLOR_BACKGROUND_ODD);
862 }
863 fSelectedLocation = null;
864 fTopLineIndex += Math.max(fNumVisibleLines - 1, 1);
865 loadLineData();
866 updateTextArea();
867 fHoldSelection--;
868 }
869 int line = Math.min(fNumVisibleLines - 1, fStyledText.getLineCount() - 1);
870 int offset = fStyledText.getOffsetAtLine(line);
871 fStyledText.setSelection(offset + Math.min(previousColumnAtCaretPosition, fLines.get(fTopLineIndex + line).string.length()));
872 break;
873 }
874 case SWT.ARROW_RIGHT: {
875 if (previousCaretOffset < fStyledText.getCharCount() || previousLineAtCaretPosition < (fNumVisibleLines - 2)) {
876 break;
877 }
878 fHoldSelection++;
879 fTopLineIndex++;
880 loadLineData();
881 updateTextArea();
882 fHoldSelection--;
883 fStyledText.setSelection(fStyledText.getCaretOffset() + 1);
884 break;
885 }
886 case SWT.ARROW_UP: {
887 if (previousLineAtCaretPosition > 0) {
888 break;
889 }
890 if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
891 break;
892 }
893 fHoldSelection++;
894 fTopLineIndex--;
895 loadLineData();
896 updateTextArea();
897 fHoldSelection--;
898 LineData lineData = fLines.get(fTopLineIndex);
899 if (!lineData.location.equals(fSelectedLocation)) {
900 fSelectedLocation = lineData.location;
901 refreshLineBackgrounds();
902 sendSelectionEvent(lineData);
903 }
904 fStyledText.setSelection(caretOffset);
905 break;
906 }
907 case SWT.PAGE_UP: {
908 if (previousLineAtCaretPosition > 0) {
909 break;
910 }
911 fHoldSelection++;
912 fTopLineIndex -= Math.max(fNumVisibleLines - 1, 1);
913 loadLineData();
914 updateTextArea();
915 fHoldSelection--;
916 LineData lineData = fLines.get(fTopLineIndex);
917 if (!lineData.location.equals(fSelectedLocation)) {
918 fSelectedLocation = lineData.location;
919 refreshLineBackgrounds();
920 sendSelectionEvent(lineData);
921 }
922 fStyledText.setSelection(caretOffset);
923 break;
924 }
925 case SWT.ARROW_LEFT: {
926 if (previousCaretOffset > 0) {
927 break;
928 }
929 if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
930 break;
931 }
932 long topRank = fLines.get(fTopLineIndex).rank;
933 fHoldSelection++;
934 fTopLineIndex--;
935 loadLineData();
936 updateTextArea();
937 fHoldSelection--;
938 LineData lineData = fLines.get(fTopLineIndex);
939 if (!lineData.location.equals(fSelectedLocation)) {
940 fSelectedLocation = lineData.location;
941 refreshLineBackgrounds();
942 sendSelectionEvent(lineData);
943 }
944 if (topRank != fLines.get(fTopLineIndex).rank) {
945 fStyledText.setSelection(fLines.get(fTopLineIndex).string.length());
946 }
947 break;
948 }
949 case SWT.HOME: {
950 if ((e.stateMask & SWT.CTRL) == 0) {
951 break;
952 }
953 //selectAndReveal(0);
954 setTopPosition(0.0);
955 LineData lineData = fLines.get(fTopLineIndex);
956 if (!lineData.location.equals(fSelectedLocation)) {
957 fSelectedLocation = lineData.location;
958 refreshLineBackgrounds();
959 sendSelectionEvent(lineData);
960 }
961 break;
962 }
963 case SWT.END: {
964 if ((e.stateMask & SWT.CTRL) == 0) {
965 break;
966 }
967 //if (fTrace.getNbEvents() > 0) {
968 //selectAndReveal(fTrace.getNbEvents() - 1);
969 //}
970 double ratio = 1.0;
971 double delta = Math.pow(10, -15);
972 fLines.clear();
973 while (fLines.size() == 0) {
974 setTopPosition(ratio);
975 if (ratio == 0.0) {
976 break;
977 }
978 delta = Math.min(delta * 10, 0.1);
979 ratio = Math.max(ratio - delta, 0.0);
980 }
981 LineData lineData = fLines.get(fTopLineIndex);
982 if (!lineData.location.equals(fSelectedLocation)) {
983 fSelectedLocation = lineData.location;
984 refreshLineBackgrounds();
985 sendSelectionEvent(lineData);
986 }
987 break;
988 }
989 default:
990 break;
991 }
992 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
993 updateHighlightedRank();
994 fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));
995 }
996
997 @Override
998 public void keyReleased(KeyEvent e) {
999 }
1000
1001 // ------------------------------------------------------------------------
1002 // CaretListener (StyledText)
1003 // ------------------------------------------------------------------------
1004
1005 @Override
1006 public void caretMoved(CaretEvent event) {
1007 if (fHoldSelection == 0) {
1008 int line = fStyledText.getLineAtOffset(event.caretOffset);
1009 if (fTopLineIndex + line < fLines.size()) {
1010 LineData lineData = fLines.get(fTopLineIndex + line);
1011 if (!lineData.location.equals(fSelectedLocation)) {
1012 fSelectedLocation = lineData.location;
1013 refreshLineBackgrounds();
1014 sendSelectionEvent(lineData);
1015 }
1016 }
1017 }
1018 storeCaretPosition(event.time, event.caretOffset);
1019 if (fHoldSelection == 0) {
1020 Point caret = fStyledText.getLocationAtOffset(fStyledText.getCaretOffset());
1021 Point origin = fScrolledComposite.getOrigin();
1022 if (origin.x > caret.x) {
1023 origin.x = caret.x;
1024 } else if (caret.x - origin.x > fScrolledComposite.getSize().x) {
1025 origin.x = caret.x - fScrolledComposite.getSize().x + 1;
1026 }
1027 fScrolledComposite.setOrigin(origin);
1028 }
1029 }
1030
1031 // ------------------------------------------------------------------------
1032 // MouseMoveListener (StyledText)
1033 // ------------------------------------------------------------------------
1034
1035 @Override
1036 public void mouseMove(MouseEvent e) {
1037 fCursorYCoordinate = e.y;
1038 if (e.y < 0 || e.y > fStyledText.getSize().y) {
1039 if (fHighlightedRank != Long.MIN_VALUE) {
1040 fHighlightedRank = Long.MIN_VALUE;
1041 refreshLineBackgrounds();
1042 }
1043 return;
1044 }
1045 int offset = fStyledText.getOffsetAtLocation(new Point(0, e.y));
1046 int line = fStyledText.getLineAtOffset(offset);
1047 if (line < fLines.size() - fTopLineIndex) {
1048 LineData lineData = fLines.get(fTopLineIndex + line);
1049 if (fHighlightedRank != lineData.rank) {
1050 fHighlightedRank = lineData.rank;
1051 refreshLineBackgrounds();
1052 }
1053 } else {
1054 if (fHighlightedRank != Long.MIN_VALUE) {
1055 fHighlightedRank = Long.MIN_VALUE;
1056 refreshLineBackgrounds();
1057 }
1058 }
1059 }
1060
1061 // ------------------------------------------------------------------------
1062 // MouseTrackListener (StyledText)
1063 // ------------------------------------------------------------------------
1064
1065 @Override
1066 public void mouseExit(MouseEvent e) {
1067 fCursorYCoordinate = -1;
1068 if (fHighlightedRank != Long.MIN_VALUE) {
1069 fHighlightedRank = Long.MIN_VALUE;
1070 refreshLineBackgrounds();
1071 }
1072 }
1073
1074 @Override
1075 public void mouseEnter(MouseEvent e) {
1076 fCursorYCoordinate = e.y;
1077 }
1078
1079 @Override
1080 public void mouseHover(MouseEvent e) {
1081 }
1082
1083 // ------------------------------------------------------------------------
1084 // MouseWheelListener (StyledText)
1085 // ------------------------------------------------------------------------
1086
1087 @Override
1088 public void mouseScrolled(MouseEvent e) {
1089 if (fLines.size() == 0) {
1090 return;
1091 }
1092 fHoldSelection++;
1093 fTopLineIndex -= e.count;
1094 loadLineData();
1095 updateTextArea();
1096 fHoldSelection = 0;
1097 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
1098 updateHighlightedRank();
1099 fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));
1100 }
1101
1102}
This page took 0.115729 seconds and 5 git commands to generate.