1 /*******************************************************************************
2 * Copyright (c) 2010, 2012 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
.rawviewer
;
15 import java
.util
.ArrayList
;
16 import java
.util
.List
;
18 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
19 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfContext
;
20 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfLocation
;
21 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
22 import org
.eclipse
.swt
.SWT
;
23 import org
.eclipse
.swt
.custom
.CaretEvent
;
24 import org
.eclipse
.swt
.custom
.CaretListener
;
25 import org
.eclipse
.swt
.custom
.ScrolledComposite
;
26 import org
.eclipse
.swt
.custom
.StyledText
;
27 import org
.eclipse
.swt
.events
.ControlEvent
;
28 import org
.eclipse
.swt
.events
.ControlListener
;
29 import org
.eclipse
.swt
.events
.KeyEvent
;
30 import org
.eclipse
.swt
.events
.KeyListener
;
31 import org
.eclipse
.swt
.events
.MouseAdapter
;
32 import org
.eclipse
.swt
.events
.MouseEvent
;
33 import org
.eclipse
.swt
.events
.MouseMoveListener
;
34 import org
.eclipse
.swt
.events
.MouseTrackListener
;
35 import org
.eclipse
.swt
.events
.MouseWheelListener
;
36 import org
.eclipse
.swt
.events
.SelectionEvent
;
37 import org
.eclipse
.swt
.events
.SelectionListener
;
38 import org
.eclipse
.swt
.graphics
.Color
;
39 import org
.eclipse
.swt
.graphics
.Font
;
40 import org
.eclipse
.swt
.graphics
.FontData
;
41 import org
.eclipse
.swt
.graphics
.Point
;
42 import org
.eclipse
.swt
.layout
.GridData
;
43 import org
.eclipse
.swt
.layout
.GridLayout
;
44 import org
.eclipse
.swt
.widgets
.Composite
;
45 import org
.eclipse
.swt
.widgets
.Control
;
46 import org
.eclipse
.swt
.widgets
.Display
;
47 import org
.eclipse
.swt
.widgets
.Event
;
48 import org
.eclipse
.swt
.widgets
.Listener
;
49 import org
.eclipse
.swt
.widgets
.Menu
;
50 import org
.eclipse
.swt
.widgets
.Slider
;
53 * TmfRawEventViewer allows for the display of the raw data for an arbitrarily
54 * large number of TMF events.
56 * It is essentially a Composite of a StyledText area and a Slider, where the number
57 * of visible lines in the StyledText control is set to fill the viewer display area.
58 * An underlying data model is used to store a cache of event raw text line data.
59 * The slider is ratio-based.
62 * @author Patrick Tasse
64 public class TmfRawEventViewer
extends Composite
implements ControlListener
, SelectionListener
,
65 KeyListener
, CaretListener
, MouseMoveListener
, MouseTrackListener
, MouseWheelListener
{
67 private static final Color COLOR_BACKGROUND_ODD
= Display
.getCurrent().getSystemColor(SWT
.COLOR_WHITE
);
68 private static final Color COLOR_BACKGROUND_EVEN
= new Color(Display
.getDefault(), 242, 242, 242);
69 private static final Color COLOR_BACKGROUND_SELECTED
= new Color(Display
.getDefault(), 231, 246, 254);
70 private static final Color COLOR_BACKGROUND_HIGHLIGHTED
= new Color(Display
.getDefault(), 246, 252, 255);
71 private static final int MAX_LINE_DATA_SIZE
= 1000;
72 private static final int SLIDER_MAX
= 1000000;
74 private ITmfTrace fTrace
;
75 private ITmfContext fBottomContext
;
77 private ScrolledComposite fScrolledComposite
;
78 private Composite fTextArea
;
79 private StyledText fStyledText
;
80 private Font fFixedFont
;
81 private Slider fSlider
;
83 private final List
<LineData
> fLines
= new ArrayList
<LineData
>();
84 private boolean fActualRanks
= false;
85 private int fTopLineIndex
;
86 private int fLastTopLineIndex
;
87 private final CaretPosition
[] fStoredCaretPosition
= new CaretPosition
[]
88 { new CaretPosition(0, 0), new CaretPosition(0,0)};
89 private int fNumVisibleLines
;
90 private ITmfLocation fSelectedLocation
= null;
91 private long fHighlightedRank
= Long
.MIN_VALUE
;
92 private int fCursorYCoordinate
= -1;
93 private int fHoldSelection
= 0;
95 private static class LineData
{
97 ITmfLocation location
;
99 public LineData(long rank
, ITmfLocation location
, String string
) {
101 this.location
= location
;
102 if (string
.length() == 0) {
103 this.string
= " "; // workaround for setLineBackground has no effect on empty line //$NON-NLS-1$
105 this.string
= string
;
109 public String
toString() {
110 return rank
+ " [" + location
+ "]: " + string
; //$NON-NLS-1$ //$NON-NLS-2$
114 private static class CaretPosition
{
117 public CaretPosition(int time
, int caretOffset
) {
119 this.caretOffset
= caretOffset
;
123 // ------------------------------------------------------------------------
125 // ------------------------------------------------------------------------
129 * @param parent The parent composite
130 * @param style The style bits
132 public TmfRawEventViewer(Composite parent
, int style
) {
133 super(parent
, style
& (~SWT
.H_SCROLL
) & (~SWT
.V_SCROLL
));
136 GridLayout gridLayout
= new GridLayout();
137 gridLayout
.numColumns
= 2;
138 gridLayout
.horizontalSpacing
= 0;
139 gridLayout
.verticalSpacing
= 0;
140 gridLayout
.marginWidth
= 0;
141 gridLayout
.marginHeight
= 0;
142 setLayout(gridLayout
);
144 // Create the controls
145 createTextArea(style
& SWT
.H_SCROLL
);
146 createSlider(style
& SWT
.V_SCROLL
);
148 // Prevent the slider from being traversed
149 setTabList(new Control
[] { fScrolledComposite
});
153 public void dispose() {
154 if (fFixedFont
!= null) {
155 fFixedFont
.dispose();
161 // ------------------------------------------------------------------------
162 // Text area handling
163 // ------------------------------------------------------------------------
166 * Create the text area and add listeners
168 private void createTextArea(int style
) {
169 fScrolledComposite
= new ScrolledComposite(this, style
);
170 fScrolledComposite
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
171 fTextArea
= new Composite(fScrolledComposite
, SWT
.NONE
);
172 fTextArea
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
173 fScrolledComposite
.setContent(fTextArea
);
174 fScrolledComposite
.setExpandHorizontal(true);
175 fScrolledComposite
.setExpandVertical(true);
176 fScrolledComposite
.setAlwaysShowScrollBars(true);
177 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
178 fScrolledComposite
.addControlListener(this);
180 GridLayout textAreaGridLayout
= new GridLayout();
181 textAreaGridLayout
.marginHeight
= 0;
182 textAreaGridLayout
.marginWidth
= 0;
183 fTextArea
.setLayout(textAreaGridLayout
);
185 if (fFixedFont
== null) {
186 if (System
.getProperty("os.name").contains("Windows")) { //$NON-NLS-1$ //$NON-NLS-2$
187 fFixedFont
= new Font(Display
.getCurrent(), new FontData("Courier New", 10, SWT
.NORMAL
)); //$NON-NLS-1$
189 fFixedFont
= new Font(Display
.getCurrent(), new FontData("Monospace", 10, SWT
.NORMAL
)); //$NON-NLS-1$
193 fStyledText
= new StyledText(fTextArea
, SWT
.READ_ONLY
);
194 fStyledText
.setFont(fFixedFont
);
195 fStyledText
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, false));
197 fStyledText
.addCaretListener(this);
198 fStyledText
.addMouseMoveListener(this);
199 fStyledText
.addMouseTrackListener(this);
200 fStyledText
.addMouseWheelListener(this);
201 fStyledText
.addListener(SWT
.MouseWheel
, new Listener() { // disable mouse scroll of horizontal scroll bar
203 public void handleEvent(Event event
) { event
.doit
= false; }});
204 fStyledText
.addKeyListener(this);
206 fTextArea
.setBackground(fStyledText
.getBackground());
207 fTextArea
.addMouseListener(new MouseAdapter() {
209 public void mouseDown(MouseEvent e
) {
210 fTextArea
.setFocus();
214 // ------------------------------------------------------------------------
216 // ------------------------------------------------------------------------
218 private void createSlider(int style
) {
219 fSlider
= new Slider(this, SWT
.VERTICAL
);
220 fSlider
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, false, true));
221 fSlider
.setValues(0, 0, SLIDER_MAX
, SLIDER_MAX
, 1, 1);
222 fSlider
.addSelectionListener(this);
223 if ((style
& SWT
.V_SCROLL
) == 0) {
224 fSlider
.setVisible(false);
228 // ------------------------------------------------------------------------
229 // Controls interactions
230 // ------------------------------------------------------------------------
233 public boolean setFocus() {
234 boolean isVisible
= isVisible();
236 fTextArea
.setFocus();
242 public void setMenu(Menu menu
) {
243 fStyledText
.setMenu(menu
);
247 * Sets the trace and updates the content
248 * @param trace The trace to set
250 public void setTrace(ITmfTrace trace
) {
258 * Refreshes the event count, updates the slider thumb and loads display
260 public void refreshEventCount() {
261 if (fTrace
!= null) {
262 if (fTrace
.getNbEvents() > 0) {
263 fSlider
.setThumb((int) Math
.max(SLIDER_MAX
/ fTrace
.getNbEvents(), 1));
265 fSlider
.setThumb(SLIDER_MAX
);
272 if (fLines
.size() == 0) {
274 } else if (fLines
.size() < fNumVisibleLines
) {
275 fBottomContext
= null;
278 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
279 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
282 fBottomContext
= null;
284 fSlider
.setThumb(SLIDER_MAX
);
285 fSlider
.setSelection(0);
290 * Selects the event of given rank and makes it visible.
291 * @param rank The rank of event
293 public void selectAndReveal(long rank
) {
294 if (fTrace
== null || !isVisible()) {
297 if (fActualRanks
&& fTopLineIndex
< fLines
.size() && rank
>= fLines
.get(fTopLineIndex
).rank
) {
298 int lastVisibleIndex
= Math
.min(fTopLineIndex
+ fNumVisibleLines
, fLines
.size()) - 1;
299 if (rank
<= fLines
.get(lastVisibleIndex
).rank
) {
300 for (int i
= fTopLineIndex
; i
< fLines
.size(); i
++) {
301 if (fLines
.get(i
).rank
== rank
) {
302 fSelectedLocation
= fLines
.get(i
).location
;
306 refreshLineBackgrounds();
311 if (fLines
.size() > 0 && fHoldSelection
== 0) {
312 fSelectedLocation
= fLines
.get(0).location
;
313 refreshLineBackgrounds();
318 * Add a selection listener
319 * @param listener A listener to add
321 public void addSelectionListener(Listener listener
) {
323 if (listener
== null) {
324 SWT
.error (SWT
.ERROR_NULL_ARGUMENT
);
326 addListener (SWT
.Selection
, listener
);
330 * Remove selection listener
331 * @param listener A listener to remove
333 public void removeSelectionListener(Listener listener
) {
335 if (listener
== null) {
336 SWT
.error (SWT
.ERROR_NULL_ARGUMENT
);
338 removeListener(SWT
.Selection
, listener
);
341 private void sendSelectionEvent(LineData lineData
) {
342 Event event
= new Event();
344 event
.data
= Long
.valueOf(lineData
.rank
);
346 event
.data
= lineData
.location
;
348 notifyListeners(SWT
.Selection
, event
);
351 private void setTopRank(long rank
) {
352 fBottomContext
= fTrace
.seekEvent(rank
);
353 if (fBottomContext
== null) {
361 if (fLines
.size() == 0) {
362 fSlider
.setSelection(0);
364 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
365 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
369 private void setTopPosition(double ratio
) {
370 fBottomContext
= fTrace
.seekEvent(ratio
);
371 if (fBottomContext
== null) {
374 fBottomContext
.setRank(0);
376 fActualRanks
= false;
382 private void loadLineData() {
383 if (fTopLineIndex
< 0) {
384 //if (fLines.size() > 0 && fLines.get(0).rank > 0) {
385 //long endRank = fLines.get(0).rank;
386 //long startRank = Math.max(0, endRank - fNumVisibleLines);
387 //TmfContext context = fTrace.seekEvent(startRank);
389 //while (context.getRank() < endRank) {
390 //long rank = context.getRank();
391 //ITmfLocation<?> location = context.getLocation();
392 //TmfEvent event = fTrace.getNextEvent(context);
393 //String[] lines = event.getRawText().split("\r?\n");
394 //for (int i = 0; i < lines.length; i++) {
395 //String line = lines[i];
396 //LineData lineData = new LineData(rank, location, line);
397 //fLines.add(index++, lineData);
399 //fLastTopLineIndex++;
403 if (fLines
.size() > 0 && fTrace
.getLocationRatio(fLines
.get(0).location
) > 0) {
404 double lastRatio
= fTrace
.getLocationRatio(fLines
.get(fLines
.size() - 1).location
);
405 double firstRatio
= fTrace
.getLocationRatio(fLines
.get(0).location
);
407 boolean singleEvent
= false;
408 if (firstRatio
!= lastRatio
) {
409 // approximate ratio of at least 20 items
410 delta
= Math
.max(20, fNumVisibleLines
) * (lastRatio
- firstRatio
) / (fLines
.size() - 1);
412 delta
= Math
.pow(10, -15);
415 while (fTopLineIndex
< 0) {
416 ITmfLocation endLocation
= fLines
.get(0).location
;
417 firstRatio
= Math
.max(0, firstRatio
- delta
);
418 ITmfContext context
= fTrace
.seekEvent(firstRatio
);
419 ITmfLocation location
;
422 while (!context
.getLocation().equals(endLocation
)) {
423 location
= context
.getLocation();
424 ITmfEvent event
= fTrace
.getNext(context
);
428 if (event
.getContent() != null && event
.getContent().getValue() != null) {
429 String
[] lines
= event
.getContent().getValue().toString().split("\r?\n"); //$NON-NLS-1$
430 for (int i
= 0; i
< lines
.length
; i
++) {
431 String line
= lines
[i
];
432 LineData lineData
= new LineData(rank
, location
, line
);
433 fLines
.add(index
++, lineData
);
438 LineData lineData
= new LineData(rank
, location
, ""); //$NON-NLS-1$
439 fLines
.add(index
++, lineData
);
445 long rankOffset
= fLines
.get(index
).rank
- rank
;
446 for (int i
= 0; i
< index
; i
++) {
447 fLines
.get(i
).rank
+= rankOffset
;
449 if (firstRatio
== 0) {
453 delta
= Math
.min(delta
* 10, 0.1);
457 if (fTopLineIndex
< 0) {
462 while (fLines
.size() - fTopLineIndex
< fNumVisibleLines
) {
463 if (fBottomContext
== null) {
464 if (fLines
.size() == 0) {
465 fBottomContext
= fTrace
.seekEvent(0);
467 //fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).rank + 1);
468 fBottomContext
= fTrace
.seekEvent(fLines
.get(fLines
.size() - 1).location
);
469 fTrace
.getNext(fBottomContext
);
471 if (fBottomContext
== null) {
475 long rank
= fBottomContext
.getRank();
476 ITmfLocation location
= fBottomContext
.getLocation() != null ? fBottomContext
.getLocation() : null;
477 ITmfEvent event
= fTrace
.getNext(fBottomContext
);
481 if (event
.getContent() != null && event
.getContent().getValue() != null) {
482 for (String line
: event
.getContent().getValue().toString().split("\r?\n")) { //$NON-NLS-1$
484 if ((crPos
= line
.indexOf('\r')) != -1) {
485 line
= line
.substring(0, crPos
);
487 LineData lineData
= new LineData(rank
, location
, line
);
488 fLines
.add(lineData
);
491 LineData lineData
= new LineData(rank
, location
, ""); //$NON-NLS-1$
492 fLines
.add(lineData
);
495 fTopLineIndex
= Math
.max(0, Math
.min(fTopLineIndex
, fLines
.size() - 1));
497 if (fLines
.size() > MAX_LINE_DATA_SIZE
) {
498 if (fTopLineIndex
< MAX_LINE_DATA_SIZE
/ 2) {
499 long rank
= fLines
.get(MAX_LINE_DATA_SIZE
- 1).rank
;
500 for (int i
= MAX_LINE_DATA_SIZE
; i
< fLines
.size(); i
++) {
501 if (fLines
.get(i
).rank
> rank
) {
502 fLines
.subList(i
, fLines
.size()).clear();
503 fBottomContext
= null;
508 long rank
= fLines
.get(fLines
.size() - MAX_LINE_DATA_SIZE
).rank
;
509 for (int i
= fLines
.size() - MAX_LINE_DATA_SIZE
- 1; i
>= 0; i
--) {
510 if (fLines
.get(i
).rank
< rank
) {
511 fLines
.subList(0, i
+ 1).clear();
512 fTopLineIndex
-= (i
+ 1);
513 fLastTopLineIndex
-= (i
+ 1);
521 private void refreshTextArea() {
522 fStyledText
.setText(""); //$NON-NLS-1$
523 for (int i
= 0; i
< fLines
.size() - fTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
526 fStyledText
.append("\n"); //$NON-NLS-1$
528 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
529 fStyledText
.append(lineData
.string
);
530 setLineBackground(i
, lineData
);
533 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
534 fLastTopLineIndex
= fTopLineIndex
;
537 private void fillTextArea() {
538 int nextLine
= fStyledText
.getCharCount() == 0 ?
0 : fStyledText
.getLineCount();
539 for (int i
= nextLine
; i
< fLines
.size() - fTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
542 fStyledText
.append("\n"); //$NON-NLS-1$
544 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
545 fStyledText
.append(lineData
.string
);
546 setLineBackground(i
, lineData
);
548 int endLine
= Math
.min(fNumVisibleLines
, fLines
.size());
549 if (endLine
< fStyledText
.getLineCount()) {
550 int endOffset
= fStyledText
.getOffsetAtLine(endLine
) - 1;
551 if (endOffset
> fStyledText
.getCharCount()) {
553 fStyledText
.replaceTextRange(endOffset
, fStyledText
.getCharCount() - endOffset
, ""); //$NON-NLS-1$
558 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
561 private void updateTextArea() {
562 if (fTopLineIndex
< fLastTopLineIndex
) {
563 StringBuffer insertedText
= new StringBuffer();
564 for (int i
= fTopLineIndex
; i
< fLastTopLineIndex
; i
++) {
565 insertedText
.append(fLines
.get(i
).string
+ "\n"); //$NON-NLS-1$
567 fStyledText
.replaceTextRange(0, 0, insertedText
.toString());
568 for (int i
= 0; i
< fLastTopLineIndex
- fTopLineIndex
; i
++) {
569 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
570 setLineBackground(i
, lineData
);
572 fLastTopLineIndex
= fTopLineIndex
;
573 } else if (fTopLineIndex
> fLastTopLineIndex
) {
575 for (int i
= 0; i
< fTopLineIndex
- fLastTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
576 length
+= fLines
.get(i
+ fLastTopLineIndex
).string
.length();
577 if (i
< fStyledText
.getLineCount()) {
581 fStyledText
.replaceTextRange(0, length
, ""); //$NON-NLS-1$
582 fLastTopLineIndex
= fTopLineIndex
;
585 int endLine
= Math
.min(fNumVisibleLines
, fLines
.size());
586 if (endLine
< fStyledText
.getLineCount()) {
587 int endOffset
= fStyledText
.getOffsetAtLine(endLine
) - 1;
588 if (endOffset
> fStyledText
.getCharCount()) {
589 fStyledText
.replaceTextRange(endOffset
, fStyledText
.getCharCount() - endOffset
, ""); //$NON-NLS-1$
593 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
596 private void refreshLineBackgrounds() {
597 for (int i
= 0; (i
< fStyledText
.getLineCount()) && (i
< fNumVisibleLines
) && (i
< fLines
.size() - fTopLineIndex
); i
++) {
598 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
599 setLineBackground(i
, lineData
);
603 private void setLineBackground(int index
, LineData lineData
) {
604 if (lineData
.location
.equals(fSelectedLocation
)) {
605 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_SELECTED
);
606 } else if (lineData
.rank
== fHighlightedRank
) {
607 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_HIGHLIGHTED
);
608 } else if (lineData
.rank
% 2 == 0) {
609 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_EVEN
);
611 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_ODD
);
615 private void storeCaretPosition(int time
, int caretOffset
) {
616 if (fStoredCaretPosition
[0].time
== time
) {
617 fStoredCaretPosition
[0].caretOffset
= caretOffset
;
619 fStoredCaretPosition
[1] = fStoredCaretPosition
[0];
620 fStoredCaretPosition
[0] = new CaretPosition(time
, caretOffset
);
624 private int getPreviousCaretOffset(int time
) {
625 if (fStoredCaretPosition
[0].time
== time
) {
626 return fStoredCaretPosition
[1].caretOffset
;
628 return fStoredCaretPosition
[0].caretOffset
;
631 private void updateHighlightedRank() {
632 if (fCursorYCoordinate
< 0 || fCursorYCoordinate
> fStyledText
.getSize().y
) {
633 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
634 fHighlightedRank
= Long
.MIN_VALUE
;
635 refreshLineBackgrounds();
639 int offset
= fStyledText
.getOffsetAtLocation(new Point(0, fCursorYCoordinate
));
640 int line
= fStyledText
.getLineAtOffset(offset
);
641 if (line
< fLines
.size() - fTopLineIndex
) {
642 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
643 if (fHighlightedRank
!= lineData
.rank
) {
644 fHighlightedRank
= lineData
.rank
;
645 refreshLineBackgrounds();
648 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
649 fHighlightedRank
= Long
.MIN_VALUE
;
650 refreshLineBackgrounds();
655 // ------------------------------------------------------------------------
656 // ControlListener (ScrolledComposite)
657 // ------------------------------------------------------------------------
660 public void controlResized(ControlEvent event
) {
661 int areaHeight
= fScrolledComposite
.getSize().y
;
662 if (fScrolledComposite
.getHorizontalBar() != null) {
663 areaHeight
-= fScrolledComposite
.getHorizontalBar().getSize().y
;
665 int lineHeight
= fStyledText
.getLineHeight();
666 fNumVisibleLines
= Math
.max((areaHeight
+ lineHeight
- 1) / lineHeight
, 1);
668 if (fBottomContext
!= null) {
675 public void controlMoved(ControlEvent e
) {
678 // ------------------------------------------------------------------------
679 // SelectionListener (Slider)
680 // ------------------------------------------------------------------------
683 public void widgetSelected(SelectionEvent e
) {
684 fTextArea
.setFocus();
685 if (fLines
.size() == 0) {
688 if (e
.detail
== SWT
.DRAG
) {
694 //long rank = (long) (fTrace.getNbEvents() * ((double) fSlider.getSelection() / SLIDER_MAX));
696 if (fSlider
.getSelection() == 0 || fSlider
.getThumb() == SLIDER_MAX
) {
701 double ratio
= (double) fSlider
.getSelection() / (SLIDER_MAX
- fSlider
.getThumb());
702 double delta
= Math
.pow(10, -15);
704 while (fLines
.size() == 0) {
705 setTopPosition(ratio
);
709 delta
= Math
.min(delta
* 10, 0.1);
710 ratio
= Math
.max(ratio
- delta
, 0.0);
714 case SWT
.ARROW_DOWN
: {
715 if (fTopLineIndex
>= fLines
.size()) {
723 case SWT
.PAGE_DOWN
: {
724 fTopLineIndex
+= Math
.max(fNumVisibleLines
- 1, 1);
730 //if (fLines.size() == 0 || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
731 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
740 fTopLineIndex
-= Math
.max(fNumVisibleLines
- 1, 1);
746 //selectAndReveal(0);
751 //if (fTrace.getNbEvents() > 0) {
752 //selectAndReveal(fTrace.getNbEvents() - 1);
755 double delta
= Math
.pow(10, -15);
757 while (fLines
.size() == 0) {
758 setTopPosition(ratio
);
762 delta
= Math
.min(delta
* 10, 0.1);
763 ratio
= Math
.max(ratio
- delta
, 0.0);
770 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
771 if (e
.detail
!= SWT
.NONE
) {
772 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
779 public void widgetDefaultSelected(SelectionEvent e
) {
782 // ------------------------------------------------------------------------
783 // KeyListener (StyledText)
784 // ------------------------------------------------------------------------
787 public void keyPressed(KeyEvent e
) {
788 if (fLines
.size() == 0) {
791 int caretOffset
= fStyledText
.getCaretOffset();
792 int previousCaretOffset
= getPreviousCaretOffset(e
.time
);
793 int previousLineAtCaretPosition
= fStyledText
.getLineAtOffset(previousCaretOffset
);
794 int previousColumnAtCaretPosition
= getPreviousCaretOffset(e
.time
) - fStyledText
.getOffsetAtLine(previousLineAtCaretPosition
);
796 case SWT
.ARROW_DOWN
: {
797 if (previousLineAtCaretPosition
< (fNumVisibleLines
- 2)) {
805 LineData lineData
= fLines
.get(fTopLineIndex
+ fStyledText
.getLineAtOffset(fStyledText
.getCaretOffset()));
806 if (!lineData
.location
.equals(fSelectedLocation
)) {
807 fSelectedLocation
= lineData
.location
;
808 refreshLineBackgrounds();
809 sendSelectionEvent(lineData
);
813 case SWT
.PAGE_DOWN
: {
814 if (previousLineAtCaretPosition
>= (fNumVisibleLines
- 1)) {
816 if (fLines
.get(fTopLineIndex
+ previousLineAtCaretPosition
).rank
% 2 == 0) {
817 fStyledText
.setLineBackground(previousLineAtCaretPosition
, 1, COLOR_BACKGROUND_EVEN
);
819 fStyledText
.setLineBackground(previousLineAtCaretPosition
, 1, COLOR_BACKGROUND_ODD
);
821 fSelectedLocation
= null;
822 fTopLineIndex
+= Math
.max(fNumVisibleLines
- 1, 1);
827 int line
= Math
.min(fNumVisibleLines
- 1, fStyledText
.getLineCount() - 1);
828 int offset
= fStyledText
.getOffsetAtLine(line
);
829 fStyledText
.setSelection(offset
+ Math
.min(previousColumnAtCaretPosition
, fLines
.get(fTopLineIndex
+ line
).string
.length()));
832 case SWT
.ARROW_RIGHT
: {
833 if (previousCaretOffset
< fStyledText
.getCharCount() || previousLineAtCaretPosition
< (fNumVisibleLines
- 2)) {
841 fStyledText
.setSelection(fStyledText
.getCaretOffset() + 1);
845 if (previousLineAtCaretPosition
> 0) {
848 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
856 LineData lineData
= fLines
.get(fTopLineIndex
);
857 if (!lineData
.location
.equals(fSelectedLocation
)) {
858 fSelectedLocation
= lineData
.location
;
859 refreshLineBackgrounds();
860 sendSelectionEvent(lineData
);
862 fStyledText
.setSelection(caretOffset
);
866 if (previousLineAtCaretPosition
> 0) {
870 fTopLineIndex
-= Math
.max(fNumVisibleLines
- 1, 1);
874 LineData lineData
= fLines
.get(fTopLineIndex
);
875 if (!lineData
.location
.equals(fSelectedLocation
)) {
876 fSelectedLocation
= lineData
.location
;
877 refreshLineBackgrounds();
878 sendSelectionEvent(lineData
);
880 fStyledText
.setSelection(caretOffset
);
883 case SWT
.ARROW_LEFT
: {
884 if (previousCaretOffset
> 0) {
887 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
890 long topRank
= fLines
.get(fTopLineIndex
).rank
;
896 LineData lineData
= fLines
.get(fTopLineIndex
);
897 if (!lineData
.location
.equals(fSelectedLocation
)) {
898 fSelectedLocation
= lineData
.location
;
899 refreshLineBackgrounds();
900 sendSelectionEvent(lineData
);
902 if (topRank
!= fLines
.get(fTopLineIndex
).rank
) {
903 fStyledText
.setSelection(fLines
.get(fTopLineIndex
).string
.length());
908 if ((e
.stateMask
& SWT
.CTRL
) == 0) {
911 //selectAndReveal(0);
913 LineData lineData
= fLines
.get(fTopLineIndex
);
914 if (!lineData
.location
.equals(fSelectedLocation
)) {
915 fSelectedLocation
= lineData
.location
;
916 refreshLineBackgrounds();
917 sendSelectionEvent(lineData
);
922 if ((e
.stateMask
& SWT
.CTRL
) == 0) {
925 //if (fTrace.getNbEvents() > 0) {
926 //selectAndReveal(fTrace.getNbEvents() - 1);
929 double delta
= Math
.pow(10, -15);
931 while (fLines
.size() == 0) {
932 setTopPosition(ratio
);
936 delta
= Math
.min(delta
* 10, 0.1);
937 ratio
= Math
.max(ratio
- delta
, 0.0);
939 LineData lineData
= fLines
.get(fTopLineIndex
);
940 if (!lineData
.location
.equals(fSelectedLocation
)) {
941 fSelectedLocation
= lineData
.location
;
942 refreshLineBackgrounds();
943 sendSelectionEvent(lineData
);
950 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
951 updateHighlightedRank();
952 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
956 public void keyReleased(KeyEvent e
) {
959 // ------------------------------------------------------------------------
960 // CaretListener (StyledText)
961 // ------------------------------------------------------------------------
964 public void caretMoved(CaretEvent event
) {
965 if (fHoldSelection
== 0) {
966 int line
= fStyledText
.getLineAtOffset(event
.caretOffset
);
967 if (fTopLineIndex
+ line
< fLines
.size()) {
968 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
969 if (!lineData
.location
.equals(fSelectedLocation
)) {
970 fSelectedLocation
= lineData
.location
;
971 refreshLineBackgrounds();
972 sendSelectionEvent(lineData
);
976 storeCaretPosition(event
.time
, event
.caretOffset
);
977 if (fHoldSelection
== 0) {
978 Point caret
= fStyledText
.getLocationAtOffset(fStyledText
.getCaretOffset());
979 Point origin
= fScrolledComposite
.getOrigin();
980 if (origin
.x
> caret
.x
) {
982 } else if (caret
.x
- origin
.x
> fScrolledComposite
.getSize().x
) {
983 origin
.x
= caret
.x
- fScrolledComposite
.getSize().x
+ 1;
985 fScrolledComposite
.setOrigin(origin
);
989 // ------------------------------------------------------------------------
990 // MouseMoveListener (StyledText)
991 // ------------------------------------------------------------------------
994 public void mouseMove(MouseEvent e
) {
995 fCursorYCoordinate
= e
.y
;
996 if (e
.y
< 0 || e
.y
> fStyledText
.getSize().y
) {
997 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
998 fHighlightedRank
= Long
.MIN_VALUE
;
999 refreshLineBackgrounds();
1003 int offset
= fStyledText
.getOffsetAtLocation(new Point(0, e
.y
));
1004 int line
= fStyledText
.getLineAtOffset(offset
);
1005 if (line
< fLines
.size() - fTopLineIndex
) {
1006 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
1007 if (fHighlightedRank
!= lineData
.rank
) {
1008 fHighlightedRank
= lineData
.rank
;
1009 refreshLineBackgrounds();
1012 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
1013 fHighlightedRank
= Long
.MIN_VALUE
;
1014 refreshLineBackgrounds();
1019 // ------------------------------------------------------------------------
1020 // MouseTrackListener (StyledText)
1021 // ------------------------------------------------------------------------
1024 public void mouseExit(MouseEvent e
) {
1025 fCursorYCoordinate
= -1;
1026 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
1027 fHighlightedRank
= Long
.MIN_VALUE
;
1028 refreshLineBackgrounds();
1033 public void mouseEnter(MouseEvent e
) {
1034 fCursorYCoordinate
= e
.y
;
1038 public void mouseHover(MouseEvent e
) {
1041 // ------------------------------------------------------------------------
1042 // MouseWheelListener (StyledText)
1043 // ------------------------------------------------------------------------
1046 public void mouseScrolled(MouseEvent e
) {
1047 if (fLines
.size() == 0) {
1051 fTopLineIndex
-= e
.count
;
1055 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
1056 updateHighlightedRank();
1057 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));