1 /*******************************************************************************
2 * Copyright (c) 2010 Ericsson
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
10 * Patrick Tasse - Initial API and implementation
11 ******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.ui
.widgets
;
15 import java
.util
.ArrayList
;
17 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
18 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfContext
;
19 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfLocation
;
20 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
21 import org
.eclipse
.swt
.SWT
;
22 import org
.eclipse
.swt
.custom
.CaretEvent
;
23 import org
.eclipse
.swt
.custom
.CaretListener
;
24 import org
.eclipse
.swt
.custom
.ScrolledComposite
;
25 import org
.eclipse
.swt
.custom
.StyledText
;
26 import org
.eclipse
.swt
.events
.ControlEvent
;
27 import org
.eclipse
.swt
.events
.ControlListener
;
28 import org
.eclipse
.swt
.events
.KeyEvent
;
29 import org
.eclipse
.swt
.events
.KeyListener
;
30 import org
.eclipse
.swt
.events
.MouseAdapter
;
31 import org
.eclipse
.swt
.events
.MouseEvent
;
32 import org
.eclipse
.swt
.events
.MouseMoveListener
;
33 import org
.eclipse
.swt
.events
.MouseTrackListener
;
34 import org
.eclipse
.swt
.events
.MouseWheelListener
;
35 import org
.eclipse
.swt
.events
.SelectionEvent
;
36 import org
.eclipse
.swt
.events
.SelectionListener
;
37 import org
.eclipse
.swt
.graphics
.Color
;
38 import org
.eclipse
.swt
.graphics
.Font
;
39 import org
.eclipse
.swt
.graphics
.FontData
;
40 import org
.eclipse
.swt
.graphics
.Point
;
41 import org
.eclipse
.swt
.layout
.GridData
;
42 import org
.eclipse
.swt
.layout
.GridLayout
;
43 import org
.eclipse
.swt
.widgets
.Composite
;
44 import org
.eclipse
.swt
.widgets
.Control
;
45 import org
.eclipse
.swt
.widgets
.Display
;
46 import org
.eclipse
.swt
.widgets
.Event
;
47 import org
.eclipse
.swt
.widgets
.Listener
;
48 import org
.eclipse
.swt
.widgets
.Menu
;
49 import org
.eclipse
.swt
.widgets
.Slider
;
52 * <b><u>TmfRawEventViewer</u></b>
54 * TmfRawEventViewer allows for the display of the raw data for an arbitrarily
55 * large number of TMF events.
57 * It is essentially a Composite of a StyledText area and a Slider, where the number
58 * of visible lines in the StyledText control is set to fill the viewer display area.
59 * An underlying data model is used to store a cache of event raw text line data.
60 * The slider is rank-based.
62 public class TmfRawEventViewer
extends Composite
implements ControlListener
, SelectionListener
,
63 KeyListener
, CaretListener
, MouseMoveListener
, MouseTrackListener
, MouseWheelListener
{
65 private static final Color COLOR_BACKGROUND_ODD
= Display
.getCurrent().getSystemColor(SWT
.COLOR_WHITE
);
66 private static final Color COLOR_BACKGROUND_EVEN
= new Color(Display
.getDefault(), 242, 242, 242);
67 private static final Color COLOR_BACKGROUND_SELECTED
= new Color(Display
.getDefault(), 231, 246, 254);
68 private static final Color COLOR_BACKGROUND_HIGHLIGHTED
= new Color(Display
.getDefault(), 246, 252, 255);
69 private static final int MAX_LINE_DATA_SIZE
= 1000;
70 private static final int SLIDER_MAX
= 1000000;
72 private ITmfTrace
<?
> fTrace
;
73 private ITmfContext fBottomContext
;
75 private ScrolledComposite fScrolledComposite
;
76 private Composite fTextArea
;
77 private StyledText fStyledText
;
78 private Font fFixedFont
;
79 private Slider fSlider
;
81 private ArrayList
<LineData
> fLines
= new ArrayList
<LineData
>();
82 private boolean fActualRanks
= false;
83 private int fTopLineIndex
;
84 private int fLastTopLineIndex
;
85 private CaretPosition
[] fStoredCaretPosition
= new CaretPosition
[]
86 { new CaretPosition(0, 0), new CaretPosition(0,0)};
87 private int fNumVisibleLines
;
88 private ITmfLocation
<?
> fSelectedLocation
= null;
89 private long fHighlightedRank
= Long
.MIN_VALUE
;
90 private int fCursorYCoordinate
= -1;
91 private int fHoldSelection
= 0;
93 private static class LineData
{
95 ITmfLocation
<?
> location
;
97 public LineData(long rank
, ITmfLocation
<?
> location
, String string
) {
99 this.location
= location
;
100 if (string
.length() == 0) {
101 this.string
= " "; // workaround for setLineBackground has no effect on empty line //$NON-NLS-1$
103 this.string
= string
;
107 public String
toString() {
108 return rank
+ " [" + location
+ "]: " + string
; //$NON-NLS-1$ //$NON-NLS-2$
112 private static class CaretPosition
{
115 public CaretPosition(int time
, int caretOffset
) {
117 this.caretOffset
= caretOffset
;
121 // ------------------------------------------------------------------------
123 // ------------------------------------------------------------------------
129 public TmfRawEventViewer(Composite parent
, int style
) {
130 super(parent
, style
& (~SWT
.H_SCROLL
) & (~SWT
.V_SCROLL
));
133 GridLayout gridLayout
= new GridLayout();
134 gridLayout
.numColumns
= 2;
135 gridLayout
.horizontalSpacing
= 0;
136 gridLayout
.verticalSpacing
= 0;
137 gridLayout
.marginWidth
= 0;
138 gridLayout
.marginHeight
= 0;
139 setLayout(gridLayout
);
141 // Create the controls
142 createTextArea(style
& SWT
.H_SCROLL
);
143 createSlider(style
& SWT
.V_SCROLL
);
145 // Prevent the slider from being traversed
146 setTabList(new Control
[] { fScrolledComposite
});
150 public void dispose() {
151 if (fFixedFont
!= null) {
152 fFixedFont
.dispose();
158 // ------------------------------------------------------------------------
159 // Text area handling
160 // ------------------------------------------------------------------------
163 * Create the text area and add listeners
165 private void createTextArea(int style
) {
166 fScrolledComposite
= new ScrolledComposite(this, style
);
167 fScrolledComposite
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
168 fTextArea
= new Composite(fScrolledComposite
, SWT
.NONE
);
169 fTextArea
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
170 fScrolledComposite
.setContent(fTextArea
);
171 fScrolledComposite
.setExpandHorizontal(true);
172 fScrolledComposite
.setExpandVertical(true);
173 fScrolledComposite
.setAlwaysShowScrollBars(true);
174 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
175 fScrolledComposite
.addControlListener(this);
177 GridLayout textAreaGridLayout
= new GridLayout();
178 textAreaGridLayout
.marginHeight
= 0;
179 textAreaGridLayout
.marginWidth
= 0;
180 fTextArea
.setLayout(textAreaGridLayout
);
182 if (fFixedFont
== null) {
183 if (System
.getProperty("os.name").contains("Windows")) { //$NON-NLS-1$ //$NON-NLS-2$
184 fFixedFont
= new Font(Display
.getCurrent(), new FontData("Courier New", 10, SWT
.NORMAL
)); //$NON-NLS-1$
186 fFixedFont
= new Font(Display
.getCurrent(), new FontData("Monospace", 10, SWT
.NORMAL
)); //$NON-NLS-1$
190 fStyledText
= new StyledText(fTextArea
, SWT
.READ_ONLY
);
191 fStyledText
.setFont(fFixedFont
);
192 fStyledText
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, false));
194 fStyledText
.addCaretListener(this);
195 fStyledText
.addMouseMoveListener(this);
196 fStyledText
.addMouseTrackListener(this);
197 fStyledText
.addMouseWheelListener(this);
198 fStyledText
.addListener(SWT
.MouseWheel
, new Listener() { // disable mouse scroll of horizontal scroll bar
200 public void handleEvent(Event event
) { event
.doit
= false; }});
201 fStyledText
.addKeyListener(this);
203 fTextArea
.setBackground(fStyledText
.getBackground());
204 fTextArea
.addMouseListener(new MouseAdapter() {
206 public void mouseDown(MouseEvent e
) {
207 fTextArea
.setFocus();
211 // ------------------------------------------------------------------------
213 // ------------------------------------------------------------------------
215 private void createSlider(int style
) {
216 fSlider
= new Slider(this, SWT
.VERTICAL
);
217 fSlider
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, false, true));
218 fSlider
.setValues(0, 0, SLIDER_MAX
, SLIDER_MAX
, 1, 1);
219 fSlider
.addSelectionListener(this);
220 if ((style
& SWT
.V_SCROLL
) == 0) {
221 fSlider
.setVisible(false);
225 // ------------------------------------------------------------------------
226 // Controls interactions
227 // ------------------------------------------------------------------------
230 public boolean setFocus() {
231 boolean isVisible
= isVisible();
233 fTextArea
.setFocus();
239 public void setMenu(Menu menu
) {
240 fStyledText
.setMenu(menu
);
243 public void setTrace(ITmfTrace
<?
> trace
) {
250 public void refreshEventCount() {
251 if (fTrace
!= null) {
252 if (fTrace
.getNbEvents() > 0) {
253 fSlider
.setThumb((int) Math
.max(SLIDER_MAX
/ fTrace
.getNbEvents(), 1));
255 fSlider
.setThumb(SLIDER_MAX
);
258 if (!isVisible()) return;
260 if (fLines
.size() == 0) {
262 } else if (fLines
.size() < fNumVisibleLines
) {
263 fBottomContext
= null;
266 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
267 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
272 public void selectAndReveal(long rank
) {
273 if (fTrace
== null || !isVisible()) {
276 if (fActualRanks
&& fTopLineIndex
< fLines
.size() && rank
>= fLines
.get(fTopLineIndex
).rank
) {
277 int lastVisibleIndex
= Math
.min(fTopLineIndex
+ fNumVisibleLines
, fLines
.size()) - 1;
278 if (rank
<= fLines
.get(lastVisibleIndex
).rank
) {
279 for (int i
= fTopLineIndex
; i
< fLines
.size(); i
++) {
280 if (fLines
.get(i
).rank
== rank
) {
281 fSelectedLocation
= fLines
.get(i
).location
;
285 refreshLineBackgrounds();
290 if (fLines
.size() > 0 && fHoldSelection
== 0) {
291 fSelectedLocation
= fLines
.get(0).location
;
292 refreshLineBackgrounds();
296 public void addSelectionListener(Listener listener
) {
298 if (listener
== null) SWT
.error (SWT
.ERROR_NULL_ARGUMENT
);
299 addListener (SWT
.Selection
, listener
);
302 public void removeSelectionListener(Listener listener
) {
304 if (listener
== null) SWT
.error (SWT
.ERROR_NULL_ARGUMENT
);
305 removeListener(SWT
.Selection
, listener
);
308 private void sendSelectionEvent(LineData lineData
) {
309 Event event
= new Event();
311 event
.data
= Long
.valueOf(lineData
.rank
);
313 event
.data
= lineData
.location
;
315 notifyListeners(SWT
.Selection
, event
);
318 private void setTopRank(long rank
) {
319 fBottomContext
= fTrace
.seekEvent(rank
);
320 if (fBottomContext
== null) {
328 if (fLines
.size() == 0) {
329 fSlider
.setSelection(0);
331 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
332 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
336 private void setTopPosition(double ratio
) {
337 fBottomContext
= fTrace
.seekEvent(ratio
);
338 if (fBottomContext
== null) {
341 fBottomContext
.setRank(0);
343 fActualRanks
= false;
349 private void loadLineData() {
350 if (fTopLineIndex
< 0) {
351 //if (fLines.size() > 0 && fLines.get(0).rank > 0) {
352 //long endRank = fLines.get(0).rank;
353 //long startRank = Math.max(0, endRank - fNumVisibleLines);
354 //TmfContext context = fTrace.seekEvent(startRank);
356 //while (context.getRank() < endRank) {
357 //long rank = context.getRank();
358 //ITmfLocation<?> location = context.getLocation();
359 //TmfEvent event = fTrace.getNextEvent(context);
360 //String[] lines = event.getRawText().split("\r?\n");
361 //for (int i = 0; i < lines.length; i++) {
362 //String line = lines[i];
363 //LineData lineData = new LineData(rank, location, line);
364 //fLines.add(index++, lineData);
366 //fLastTopLineIndex++;
370 if (fLines
.size() > 0 && fTrace
.getLocationRatio(fLines
.get(0).location
) > 0) {
371 double lastRatio
= fTrace
.getLocationRatio(fLines
.get(fLines
.size() - 1).location
);
372 double firstRatio
= fTrace
.getLocationRatio(fLines
.get(0).location
);
374 boolean singleEvent
= false;
375 if (firstRatio
!= lastRatio
) {
376 // approximate ratio of at least 20 items
377 delta
= Math
.max(20, fNumVisibleLines
) * (lastRatio
- firstRatio
) / (fLines
.size() - 1);
379 delta
= Math
.pow(10, -15);
382 while (fTopLineIndex
< 0) {
383 ITmfLocation
<?
> endLocation
= fLines
.get(0).location
;
384 firstRatio
= Math
.max(0, firstRatio
- delta
);
385 ITmfContext context
= fTrace
.seekEvent(firstRatio
);
386 ITmfLocation
<?
> location
;
389 while (!context
.getLocation().equals(endLocation
)) {
390 location
= context
.getLocation().clone();
391 ITmfEvent event
= fTrace
.readNextEvent(context
);
395 if (event
.getContent() != null && event
.getContent().getValue() != null) {
396 String
[] lines
= event
.getContent().getValue().toString().split("\r?\n"); //$NON-NLS-1$
397 for (int i
= 0; i
< lines
.length
; i
++) {
398 String line
= lines
[i
];
399 LineData lineData
= new LineData(rank
, location
, line
);
400 fLines
.add(index
++, lineData
);
407 long rankOffset
= fLines
.get(index
).rank
- rank
;
408 for (int i
= 0; i
< index
; i
++) {
409 fLines
.get(i
).rank
+= rankOffset
;
411 if (firstRatio
== 0) {
415 delta
= Math
.min(delta
* 10, 0.1);
419 if (fTopLineIndex
< 0) {
424 while (fLines
.size() - fTopLineIndex
< fNumVisibleLines
) {
425 if (fBottomContext
== null) {
426 if (fLines
.size() == 0) {
427 fBottomContext
= fTrace
.seekEvent(0);
429 //fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).rank + 1);
430 fBottomContext
= fTrace
.seekEvent(fLines
.get(fLines
.size() - 1).location
);
431 fTrace
.readNextEvent(fBottomContext
);
433 if (fBottomContext
== null) {
437 long rank
= fBottomContext
.getRank();
438 ITmfLocation
<?
> location
= fBottomContext
.getLocation() != null ? fBottomContext
.getLocation().clone() : null;
439 ITmfEvent event
= fTrace
.readNextEvent(fBottomContext
);
443 if (event
.getContent() != null && event
.getContent().getValue() != null) {
444 for (String line
: event
.getContent().getValue().toString().split("\r?\n")) { //$NON-NLS-1$
446 if ((crPos
= line
.indexOf('\r')) != -1) {
447 line
= line
.substring(0, crPos
);
449 LineData lineData
= new LineData(rank
, location
, line
);
450 fLines
.add(lineData
);
454 fTopLineIndex
= Math
.max(0, Math
.min(fTopLineIndex
, fLines
.size() - 1));
456 if (fLines
.size() > MAX_LINE_DATA_SIZE
) {
457 if (fTopLineIndex
< MAX_LINE_DATA_SIZE
/ 2) {
458 long rank
= fLines
.get(MAX_LINE_DATA_SIZE
- 1).rank
;
459 for (int i
= MAX_LINE_DATA_SIZE
; i
< fLines
.size(); i
++) {
460 if (fLines
.get(i
).rank
> rank
) {
461 fLines
.subList(i
, fLines
.size()).clear();
462 fBottomContext
= null;
467 long rank
= fLines
.get(fLines
.size() - MAX_LINE_DATA_SIZE
).rank
;
468 for (int i
= fLines
.size() - MAX_LINE_DATA_SIZE
- 1; i
>= 0; i
--) {
469 if (fLines
.get(i
).rank
< rank
) {
470 fLines
.subList(0, i
+ 1).clear();
471 fTopLineIndex
-= (i
+ 1);
472 fLastTopLineIndex
-= (i
+ 1);
480 private void refreshTextArea() {
481 fStyledText
.setText(""); //$NON-NLS-1$
482 for (int i
= 0; i
< fLines
.size() - fTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
483 if (i
> 0) fStyledText
.append("\n"); //$NON-NLS-1$
484 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
485 fStyledText
.append(lineData
.string
);
486 setLineBackground(i
, lineData
);
489 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
490 fLastTopLineIndex
= fTopLineIndex
;
493 private void fillTextArea() {
494 int nextLine
= fStyledText
.getCharCount() == 0 ?
0 : fStyledText
.getLineCount();
495 for (int i
= nextLine
; i
< fLines
.size() - fTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
496 if (i
> 0) fStyledText
.append("\n"); //$NON-NLS-1$
497 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
498 fStyledText
.append(lineData
.string
);
499 setLineBackground(i
, lineData
);
501 int endLine
= Math
.min(fNumVisibleLines
, fLines
.size());
502 if (endLine
< fStyledText
.getLineCount()) {
503 int endOffset
= fStyledText
.getOffsetAtLine(endLine
) - 1;
504 if (endOffset
> fStyledText
.getCharCount()) {
506 fStyledText
.replaceTextRange(endOffset
, fStyledText
.getCharCount() - endOffset
, ""); //$NON-NLS-1$
511 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
514 private void updateTextArea() {
515 if (fTopLineIndex
< fLastTopLineIndex
) {
516 StringBuffer insertedText
= new StringBuffer();
517 for (int i
= fTopLineIndex
; i
< fLastTopLineIndex
; i
++) {
518 insertedText
.append(fLines
.get(i
).string
+ "\n"); //$NON-NLS-1$
520 fStyledText
.replaceTextRange(0, 0, insertedText
.toString());
521 for (int i
= 0; i
< fLastTopLineIndex
- fTopLineIndex
; i
++) {
522 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
523 setLineBackground(i
, lineData
);
525 fLastTopLineIndex
= fTopLineIndex
;
526 } else if (fTopLineIndex
> fLastTopLineIndex
) {
528 for (int i
= 0; i
< fTopLineIndex
- fLastTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
529 length
+= fLines
.get(i
+ fLastTopLineIndex
).string
.length();
530 if (i
< fStyledText
.getLineCount()) length
+= 1;
532 fStyledText
.replaceTextRange(0, length
, ""); //$NON-NLS-1$
533 fLastTopLineIndex
= fTopLineIndex
;
536 int endLine
= Math
.min(fNumVisibleLines
, fLines
.size());
537 if (endLine
< fStyledText
.getLineCount()) {
538 int endOffset
= fStyledText
.getOffsetAtLine(endLine
) - 1;
539 if (endOffset
> fStyledText
.getCharCount()) {
540 fStyledText
.replaceTextRange(endOffset
, fStyledText
.getCharCount() - endOffset
, ""); //$NON-NLS-1$
544 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
547 private void refreshLineBackgrounds() {
548 for (int i
= 0; (i
< fStyledText
.getLineCount()) && (i
< fNumVisibleLines
) && (i
< fLines
.size() - fTopLineIndex
); i
++) {
549 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
550 setLineBackground(i
, lineData
);
554 private void setLineBackground(int index
, LineData lineData
) {
555 if (lineData
.location
.equals(fSelectedLocation
)) {
556 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_SELECTED
);
557 } else if (lineData
.rank
== fHighlightedRank
) {
558 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_HIGHLIGHTED
);
559 } else if (lineData
.rank
% 2 == 0) {
560 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_EVEN
);
562 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_ODD
);
566 private void storeCaretPosition(int time
, int caretOffset
) {
567 if (fStoredCaretPosition
[0].time
== time
) {
568 fStoredCaretPosition
[0].caretOffset
= caretOffset
;
570 fStoredCaretPosition
[1] = fStoredCaretPosition
[0];
571 fStoredCaretPosition
[0] = new CaretPosition(time
, caretOffset
);
575 private int getPreviousCaretOffset(int time
) {
576 if (fStoredCaretPosition
[0].time
== time
) {
577 return fStoredCaretPosition
[1].caretOffset
;
579 return fStoredCaretPosition
[0].caretOffset
;
583 private void updateHighlightedRank() {
584 if (fCursorYCoordinate
< 0 || fCursorYCoordinate
> fStyledText
.getSize().y
) {
585 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
586 fHighlightedRank
= Long
.MIN_VALUE
;
587 refreshLineBackgrounds();
591 int offset
= fStyledText
.getOffsetAtLocation(new Point(0, fCursorYCoordinate
));
592 int line
= fStyledText
.getLineAtOffset(offset
);
593 if (line
< fLines
.size() - fTopLineIndex
) {
594 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
595 if (fHighlightedRank
!= lineData
.rank
) {
596 fHighlightedRank
= lineData
.rank
;
597 refreshLineBackgrounds();
600 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
601 fHighlightedRank
= Long
.MIN_VALUE
;
602 refreshLineBackgrounds();
607 // ------------------------------------------------------------------------
608 // ControlListener (ScrolledComposite)
609 // ------------------------------------------------------------------------
612 public void controlResized(ControlEvent event
) {
613 int areaHeight
= fScrolledComposite
.getSize().y
;
614 if (fScrolledComposite
.getHorizontalBar() != null) {
615 areaHeight
-= fScrolledComposite
.getHorizontalBar().getSize().y
;
617 int lineHeight
= fStyledText
.getLineHeight();
618 fNumVisibleLines
= Math
.max((areaHeight
+ lineHeight
- 1) / lineHeight
, 1);
620 if (fBottomContext
!= null) {
627 public void controlMoved(ControlEvent e
) {
630 // ------------------------------------------------------------------------
631 // SelectionListener (Slider)
632 // ------------------------------------------------------------------------
635 public void widgetSelected(SelectionEvent e
) {
636 fTextArea
.setFocus();
637 if (fLines
.size() == 0) {
640 if (e
.detail
== SWT
.DRAG
) {
646 //long rank = (long) (fTrace.getNbEvents() * ((double) fSlider.getSelection() / SLIDER_MAX));
648 if (fSlider
.getSelection() == 0 || fSlider
.getThumb() == SLIDER_MAX
) {
653 double ratio
= (double) fSlider
.getSelection() / (SLIDER_MAX
- fSlider
.getThumb());
654 double delta
= Math
.pow(10, -15);
656 while (fLines
.size() == 0) {
657 setTopPosition(ratio
);
658 if (ratio
== 0.0) break;
659 delta
= Math
.min(delta
* 10, 0.1);
660 ratio
= Math
.max(ratio
- delta
, 0.0);
664 case SWT
.ARROW_DOWN
: {
665 if (fTopLineIndex
>= fLines
.size()) {
673 case SWT
.PAGE_DOWN
: {
674 fTopLineIndex
+= Math
.max(fNumVisibleLines
- 1, 1);
680 //if (fLines.size() == 0 || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
681 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
690 fTopLineIndex
-= Math
.max(fNumVisibleLines
- 1, 1);
696 //selectAndReveal(0);
701 //if (fTrace.getNbEvents() > 0) {
702 //selectAndReveal(fTrace.getNbEvents() - 1);
705 double delta
= Math
.pow(10, -15);
707 while (fLines
.size() == 0) {
708 setTopPosition(ratio
);
709 if (ratio
== 0.0) break;
710 delta
= Math
.min(delta
* 10, 0.1);
711 ratio
= Math
.max(ratio
- delta
, 0.0);
716 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
717 if (e
.detail
!= SWT
.NONE
) {
718 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
725 public void widgetDefaultSelected(SelectionEvent e
) {
728 // ------------------------------------------------------------------------
729 // KeyListener (StyledText)
730 // ------------------------------------------------------------------------
733 public void keyPressed(KeyEvent e
) {
734 if (fLines
.size() == 0) {
737 int caretOffset
= fStyledText
.getCaretOffset();
738 int previousCaretOffset
= getPreviousCaretOffset(e
.time
);
739 int previousLineAtCaretPosition
= fStyledText
.getLineAtOffset(previousCaretOffset
);
740 int previousColumnAtCaretPosition
= getPreviousCaretOffset(e
.time
) - fStyledText
.getOffsetAtLine(previousLineAtCaretPosition
);
742 case SWT
.ARROW_DOWN
: {
743 if (previousLineAtCaretPosition
< (fNumVisibleLines
- 2)) {
751 LineData lineData
= fLines
.get(fTopLineIndex
+ fStyledText
.getLineAtOffset(fStyledText
.getCaretOffset()));
752 if (!lineData
.location
.equals(fSelectedLocation
)) {
753 fSelectedLocation
= lineData
.location
;
754 refreshLineBackgrounds();
755 sendSelectionEvent(lineData
);
759 case SWT
.PAGE_DOWN
: {
760 if (previousLineAtCaretPosition
>= (fNumVisibleLines
- 1)) {
762 if (fLines
.get(fTopLineIndex
+ previousLineAtCaretPosition
).rank
% 2 == 0) {
763 fStyledText
.setLineBackground(previousLineAtCaretPosition
, 1, COLOR_BACKGROUND_EVEN
);
765 fStyledText
.setLineBackground(previousLineAtCaretPosition
, 1, COLOR_BACKGROUND_ODD
);
767 fSelectedLocation
= null;
768 fTopLineIndex
+= Math
.max(fNumVisibleLines
- 1, 1);
773 int line
= Math
.min(fNumVisibleLines
- 1, fStyledText
.getLineCount() - 1);
774 int offset
= fStyledText
.getOffsetAtLine(line
);
775 fStyledText
.setSelection(offset
+ Math
.min(previousColumnAtCaretPosition
, fLines
.get(fTopLineIndex
+ line
).string
.length()));
778 case SWT
.ARROW_RIGHT
: {
779 if (previousCaretOffset
< fStyledText
.getCharCount() || previousLineAtCaretPosition
< (fNumVisibleLines
- 2)) {
787 fStyledText
.setSelection(fStyledText
.getCaretOffset() + 1);
791 if (previousLineAtCaretPosition
> 0) {
794 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
802 LineData lineData
= fLines
.get(fTopLineIndex
);
803 if (!lineData
.location
.equals(fSelectedLocation
)) {
804 fSelectedLocation
= lineData
.location
;
805 refreshLineBackgrounds();
806 sendSelectionEvent(lineData
);
808 fStyledText
.setSelection(caretOffset
);
812 if (previousLineAtCaretPosition
> 0) {
816 fTopLineIndex
-= Math
.max(fNumVisibleLines
- 1, 1);
820 LineData lineData
= fLines
.get(fTopLineIndex
);
821 if (!lineData
.location
.equals(fSelectedLocation
)) {
822 fSelectedLocation
= lineData
.location
;
823 refreshLineBackgrounds();
824 sendSelectionEvent(lineData
);
826 fStyledText
.setSelection(caretOffset
);
829 case SWT
.ARROW_LEFT
: {
830 if (previousCaretOffset
> 0) {
833 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
836 long topRank
= fLines
.get(fTopLineIndex
).rank
;
842 LineData lineData
= fLines
.get(fTopLineIndex
);
843 if (!lineData
.location
.equals(fSelectedLocation
)) {
844 fSelectedLocation
= lineData
.location
;
845 refreshLineBackgrounds();
846 sendSelectionEvent(lineData
);
848 if (topRank
!= fLines
.get(fTopLineIndex
).rank
) {
849 fStyledText
.setSelection(fLines
.get(fTopLineIndex
).string
.length());
854 if ((e
.stateMask
& SWT
.CTRL
) == 0) {
857 //selectAndReveal(0);
859 LineData lineData
= fLines
.get(fTopLineIndex
);
860 if (!lineData
.location
.equals(fSelectedLocation
)) {
861 fSelectedLocation
= lineData
.location
;
862 refreshLineBackgrounds();
863 sendSelectionEvent(lineData
);
868 if ((e
.stateMask
& SWT
.CTRL
) == 0) {
871 //if (fTrace.getNbEvents() > 0) {
872 //selectAndReveal(fTrace.getNbEvents() - 1);
875 double delta
= Math
.pow(10, -15);
877 while (fLines
.size() == 0) {
878 setTopPosition(ratio
);
879 if (ratio
== 0.0) break;
880 delta
= Math
.min(delta
* 10, 0.1);
881 ratio
= Math
.max(ratio
- delta
, 0.0);
883 LineData lineData
= fLines
.get(fTopLineIndex
);
884 if (!lineData
.location
.equals(fSelectedLocation
)) {
885 fSelectedLocation
= lineData
.location
;
886 refreshLineBackgrounds();
887 sendSelectionEvent(lineData
);
892 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
893 updateHighlightedRank();
894 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
898 public void keyReleased(KeyEvent e
) {
901 // ------------------------------------------------------------------------
902 // CaretListener (StyledText)
903 // ------------------------------------------------------------------------
906 public void caretMoved(CaretEvent event
) {
907 if (fHoldSelection
== 0) {
908 int line
= fStyledText
.getLineAtOffset(event
.caretOffset
);
909 if (fTopLineIndex
+ line
< fLines
.size()) {
910 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
911 if (!lineData
.location
.equals(fSelectedLocation
)) {
912 fSelectedLocation
= lineData
.location
;
913 refreshLineBackgrounds();
914 sendSelectionEvent(lineData
);
918 storeCaretPosition(event
.time
, event
.caretOffset
);
919 if (fHoldSelection
== 0) {
920 Point caret
= fStyledText
.getLocationAtOffset(fStyledText
.getCaretOffset());
921 Point origin
= fScrolledComposite
.getOrigin();
922 if (origin
.x
> caret
.x
) {
924 } else if (caret
.x
- origin
.x
> fScrolledComposite
.getSize().x
) {
925 origin
.x
= caret
.x
- fScrolledComposite
.getSize().x
+ 1;
927 fScrolledComposite
.setOrigin(origin
);
931 // ------------------------------------------------------------------------
932 // MouseMoveListener (StyledText)
933 // ------------------------------------------------------------------------
936 public void mouseMove(MouseEvent e
) {
937 fCursorYCoordinate
= e
.y
;
938 if (e
.y
< 0 || e
.y
> fStyledText
.getSize().y
) {
939 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
940 fHighlightedRank
= Long
.MIN_VALUE
;
941 refreshLineBackgrounds();
945 int offset
= fStyledText
.getOffsetAtLocation(new Point(0, e
.y
));
946 int line
= fStyledText
.getLineAtOffset(offset
);
947 if (line
< fLines
.size() - fTopLineIndex
) {
948 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
949 if (fHighlightedRank
!= lineData
.rank
) {
950 fHighlightedRank
= lineData
.rank
;
951 refreshLineBackgrounds();
954 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
955 fHighlightedRank
= Long
.MIN_VALUE
;
956 refreshLineBackgrounds();
961 // ------------------------------------------------------------------------
962 // MouseTrackListener (StyledText)
963 // ------------------------------------------------------------------------
966 public void mouseExit(MouseEvent e
) {
967 fCursorYCoordinate
= -1;
968 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
969 fHighlightedRank
= Long
.MIN_VALUE
;
970 refreshLineBackgrounds();
975 public void mouseEnter(MouseEvent e
) {
976 fCursorYCoordinate
= e
.y
;
980 public void mouseHover(MouseEvent e
) {
983 // ------------------------------------------------------------------------
984 // MouseWheelListener (StyledText)
985 // ------------------------------------------------------------------------
988 public void mouseScrolled(MouseEvent e
) {
989 if (fLines
.size() == 0) {
993 fTopLineIndex
-= e
.count
;
997 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
998 updateHighlightedRank();
999 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));