1 /*******************************************************************************
2 * Copyright (c) 2010, 2015 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
.tracecompass
.tmf
.ui
.widgets
.rawviewer
;
15 import java
.util
.ArrayList
;
16 import java
.util
.List
;
18 import org
.eclipse
.jface
.resource
.FontRegistry
;
19 import org
.eclipse
.jface
.util
.IPropertyChangeListener
;
20 import org
.eclipse
.jface
.util
.PropertyChangeEvent
;
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
.Point
;
40 import org
.eclipse
.swt
.layout
.GridData
;
41 import org
.eclipse
.swt
.layout
.GridLayout
;
42 import org
.eclipse
.swt
.widgets
.Composite
;
43 import org
.eclipse
.swt
.widgets
.Control
;
44 import org
.eclipse
.swt
.widgets
.Display
;
45 import org
.eclipse
.swt
.widgets
.Event
;
46 import org
.eclipse
.swt
.widgets
.Listener
;
47 import org
.eclipse
.swt
.widgets
.Menu
;
48 import org
.eclipse
.swt
.widgets
.Slider
;
49 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
50 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
51 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
52 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.ITmfLocation
;
53 import org
.eclipse
.ui
.PlatformUI
;
54 import org
.eclipse
.ui
.themes
.IThemeManager
;
57 * TmfRawEventViewer allows for the display of the raw data for an arbitrarily
58 * large number of TMF events.
60 * It is essentially a Composite of a StyledText area and a Slider, where the number
61 * of visible lines in the StyledText control is set to fill the viewer display area.
62 * An underlying data model is used to store a cache of event raw text line data.
63 * The slider is ratio-based.
66 * @author Patrick Tasse
68 public class TmfRawEventViewer
extends Composite
implements ControlListener
, SelectionListener
,
69 KeyListener
, CaretListener
, MouseMoveListener
, MouseTrackListener
, MouseWheelListener
, IPropertyChangeListener
{
71 private static final Color COLOR_BACKGROUND_ODD
= Display
.getCurrent().getSystemColor(SWT
.COLOR_WHITE
);
72 private static final Color COLOR_BACKGROUND_EVEN
= new Color(Display
.getDefault(), 242, 242, 242);
73 private static final Color COLOR_BACKGROUND_SELECTED
= new Color(Display
.getDefault(), 231, 246, 254);
74 private static final Color COLOR_BACKGROUND_HIGHLIGHTED
= new Color(Display
.getDefault(), 246, 252, 255);
75 private static final String FONT_DEFINITION_ID
= "org.eclipse.tracecompass.tmf.ui.font.eventraw"; //$NON-NLS-1$
76 private static final int MAX_LINE_DATA_SIZE
= 1000;
77 private static final int SLIDER_MAX
= 1000000;
79 private ITmfTrace fTrace
;
80 private ITmfContext fBottomContext
;
82 private ScrolledComposite fScrolledComposite
;
83 private Composite fTextArea
;
84 private StyledText fStyledText
;
85 private Font fFixedFont
;
86 private Slider fSlider
;
88 private final List
<LineData
> fLines
= new ArrayList
<>();
89 private boolean fActualRanks
= false;
90 private int fTopLineIndex
;
91 private int fLastTopLineIndex
;
92 private final CaretPosition
[] fStoredCaretPosition
= new CaretPosition
[]
93 { new CaretPosition(0, 0), new CaretPosition(0,0)};
94 private int fNumVisibleLines
;
95 private ITmfLocation fSelectedLocation
= null;
96 private long fHighlightedRank
= Long
.MIN_VALUE
;
97 private int fCursorYCoordinate
= -1;
98 private int fHoldSelection
= 0;
100 private static class LineData
{
102 ITmfLocation location
;
104 public LineData(long rank
, ITmfLocation location
, String string
) {
106 this.location
= location
;
107 if (string
.length() == 0) {
108 this.string
= " "; // workaround for setLineBackground has no effect on empty line //$NON-NLS-1$
110 this.string
= string
;
114 public String
toString() {
115 return rank
+ " [" + location
+ "]: " + string
; //$NON-NLS-1$ //$NON-NLS-2$
119 private static class CaretPosition
{
122 public CaretPosition(int time
, int caretOffset
) {
124 this.caretOffset
= caretOffset
;
128 // ------------------------------------------------------------------------
130 // ------------------------------------------------------------------------
134 * @param parent The parent composite
135 * @param style The style bits
137 public TmfRawEventViewer(Composite parent
, int style
) {
138 super(parent
, style
& (~SWT
.H_SCROLL
) & (~SWT
.V_SCROLL
));
141 GridLayout gridLayout
= new GridLayout();
142 gridLayout
.numColumns
= 2;
143 gridLayout
.horizontalSpacing
= 0;
144 gridLayout
.verticalSpacing
= 0;
145 gridLayout
.marginWidth
= 0;
146 gridLayout
.marginHeight
= 0;
147 setLayout(gridLayout
);
149 // Create the controls
150 createTextArea(style
& SWT
.H_SCROLL
);
151 createSlider(style
& SWT
.V_SCROLL
);
153 // Prevent the slider from being traversed
154 setTabList(new Control
[] { fScrolledComposite
});
158 public void dispose() {
159 PlatformUI
.getWorkbench().getThemeManager().removePropertyChangeListener(this);
163 // ------------------------------------------------------------------------
165 // ------------------------------------------------------------------------
168 * Initialize the fonts.
171 protected void initializeFonts() {
172 FontRegistry fontRegistry
= PlatformUI
.getWorkbench().getThemeManager().getCurrentTheme().getFontRegistry();
173 fFixedFont
= fontRegistry
.get(FONT_DEFINITION_ID
);
174 fStyledText
.setFont(fFixedFont
);
181 public void propertyChange(PropertyChangeEvent event
) {
182 if ((IThemeManager
.CHANGE_CURRENT_THEME
.equals(event
.getProperty())) ||
183 (FONT_DEFINITION_ID
.equals(event
.getProperty()))) {
189 // ------------------------------------------------------------------------
190 // Text area handling
191 // ------------------------------------------------------------------------
194 * Create the text area and add listeners
196 private void createTextArea(int style
) {
197 fScrolledComposite
= new ScrolledComposite(this, style
);
198 fScrolledComposite
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
199 fTextArea
= new Composite(fScrolledComposite
, SWT
.NONE
);
200 fTextArea
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
201 fScrolledComposite
.setContent(fTextArea
);
202 fScrolledComposite
.setExpandHorizontal(true);
203 fScrolledComposite
.setExpandVertical(true);
204 fScrolledComposite
.setAlwaysShowScrollBars(true);
205 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
206 fScrolledComposite
.addControlListener(this);
208 GridLayout textAreaGridLayout
= new GridLayout();
209 textAreaGridLayout
.marginHeight
= 0;
210 textAreaGridLayout
.marginWidth
= 0;
211 fTextArea
.setLayout(textAreaGridLayout
);
213 fStyledText
= new StyledText(fTextArea
, SWT
.READ_ONLY
);
214 fStyledText
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, false));
217 PlatformUI
.getWorkbench().getThemeManager().addPropertyChangeListener(this);
219 fStyledText
.addCaretListener(this);
220 fStyledText
.addMouseMoveListener(this);
221 fStyledText
.addMouseTrackListener(this);
222 fStyledText
.addMouseWheelListener(this);
223 fStyledText
.addListener(SWT
.MouseWheel
, new Listener() { // disable mouse scroll of horizontal scroll bar
225 public void handleEvent(Event event
) { event
.doit
= false; }});
226 fStyledText
.addKeyListener(this);
228 fTextArea
.setBackground(fStyledText
.getBackground());
229 fTextArea
.addMouseListener(new MouseAdapter() {
231 public void mouseDown(MouseEvent e
) {
232 fTextArea
.setFocus();
236 // ------------------------------------------------------------------------
238 // ------------------------------------------------------------------------
240 private void createSlider(int style
) {
241 fSlider
= new Slider(this, SWT
.VERTICAL
);
242 fSlider
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, false, true));
243 fSlider
.setValues(0, 0, SLIDER_MAX
, SLIDER_MAX
, 1, 1);
244 fSlider
.addSelectionListener(this);
245 if ((style
& SWT
.V_SCROLL
) == 0) {
246 fSlider
.setVisible(false);
250 // ------------------------------------------------------------------------
251 // Controls interactions
252 // ------------------------------------------------------------------------
255 public boolean setFocus() {
256 boolean isVisible
= isVisible();
258 fTextArea
.setFocus();
264 public void setMenu(Menu menu
) {
265 fStyledText
.setMenu(menu
);
269 * Sets the trace and updates the content
270 * @param trace The trace to set
272 public void setTrace(ITmfTrace trace
) {
280 * Refreshes the event count, updates the slider thumb and loads display
282 public void refreshEventCount() {
283 if (fTrace
!= null) {
284 if (fTrace
.getNbEvents() > 0) {
285 fSlider
.setThumb((int) Math
.max(SLIDER_MAX
/ fTrace
.getNbEvents(), 1));
287 fSlider
.setThumb(SLIDER_MAX
);
294 if (fLines
.size() == 0) {
296 } else if (fLines
.size() < fNumVisibleLines
) {
297 fBottomContext
= null;
300 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
301 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
304 fBottomContext
= null;
306 fSlider
.setThumb(SLIDER_MAX
);
307 fSlider
.setSelection(0);
312 * Selects the event of given rank and makes it visible.
313 * @param rank The rank of event
315 public void selectAndReveal(long rank
) {
316 if (fTrace
== null || !isVisible()) {
319 if (fActualRanks
&& fTopLineIndex
< fLines
.size() && rank
>= fLines
.get(fTopLineIndex
).rank
) {
320 int lastVisibleIndex
= Math
.min(fTopLineIndex
+ fNumVisibleLines
, fLines
.size()) - 1;
321 if (rank
<= fLines
.get(lastVisibleIndex
).rank
) {
322 for (int i
= fTopLineIndex
; i
< fLines
.size(); i
++) {
323 if (fLines
.get(i
).rank
== rank
) {
324 fSelectedLocation
= fLines
.get(i
).location
;
328 refreshLineBackgrounds();
333 if (fLines
.size() > 0 && fHoldSelection
== 0) {
334 fSelectedLocation
= fLines
.get(0).location
;
335 refreshLineBackgrounds();
340 * Add a selection listener
341 * @param listener A listener to add
343 public void addSelectionListener(Listener listener
) {
345 if (listener
== null) {
346 SWT
.error (SWT
.ERROR_NULL_ARGUMENT
);
348 addListener (SWT
.Selection
, listener
);
352 * Remove selection listener
353 * @param listener A listener to remove
355 public void removeSelectionListener(Listener listener
) {
357 if (listener
== null) {
358 SWT
.error (SWT
.ERROR_NULL_ARGUMENT
);
360 removeListener(SWT
.Selection
, listener
);
363 private void sendSelectionEvent(LineData lineData
) {
364 Event event
= new Event();
366 event
.data
= Long
.valueOf(lineData
.rank
);
368 event
.data
= lineData
.location
;
370 notifyListeners(SWT
.Selection
, event
);
373 private void setTopRank(long rank
) {
374 fBottomContext
= fTrace
.seekEvent(rank
);
375 if (fBottomContext
== null) {
383 if (fLines
.size() == 0) {
384 fSlider
.setSelection(0);
386 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
387 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
391 private void setTopPosition(double ratio
) {
392 fBottomContext
= fTrace
.seekEvent(ratio
);
393 if (fBottomContext
== null) {
396 fBottomContext
.setRank(0);
398 fActualRanks
= false;
404 private void loadLineData() {
405 if (fTopLineIndex
< 0) {
406 //if (fLines.size() > 0 && fLines.get(0).rank > 0) {
407 //long endRank = fLines.get(0).rank;
408 //long startRank = Math.max(0, endRank - fNumVisibleLines);
409 //TmfContext context = fTrace.seekEvent(startRank);
411 //while (context.getRank() < endRank) {
412 //long rank = context.getRank();
413 //ITmfLocation<?> location = context.getLocation();
414 //TmfEvent event = fTrace.getNextEvent(context);
415 //String[] lines = event.getRawText().split("\r?\n");
416 //for (int i = 0; i < lines.length; i++) {
417 //String line = lines[i];
418 //LineData lineData = new LineData(rank, location, line);
419 //fLines.add(index++, lineData);
421 //fLastTopLineIndex++;
425 if (fLines
.size() > 0 && fTrace
.getLocationRatio(fLines
.get(0).location
) > 0) {
426 double lastRatio
= fTrace
.getLocationRatio(fLines
.get(fLines
.size() - 1).location
);
427 double firstRatio
= fTrace
.getLocationRatio(fLines
.get(0).location
);
429 boolean singleEvent
= false;
430 if (firstRatio
!= lastRatio
) {
431 // approximate ratio of at least 20 items
432 delta
= Math
.max(20, fNumVisibleLines
) * (lastRatio
- firstRatio
) / (fLines
.size() - 1);
434 delta
= Math
.pow(10, -15);
437 while (fTopLineIndex
< 0) {
438 ITmfLocation endLocation
= fLines
.get(0).location
;
439 firstRatio
= Math
.max(0, firstRatio
- delta
);
440 ITmfContext context
= fTrace
.seekEvent(firstRatio
);
441 ITmfLocation location
;
444 while (!context
.getLocation().equals(endLocation
)) {
445 location
= context
.getLocation();
446 ITmfEvent event
= fTrace
.getNext(context
);
450 if (event
.getContent() != null && event
.getContent().getValue() != null) {
451 String
[] lines
= event
.getContent().getValue().toString().split("\r?\n"); //$NON-NLS-1$
452 for (int i
= 0; i
< lines
.length
; i
++) {
453 String line
= lines
[i
];
454 LineData lineData
= new LineData(rank
, location
, line
);
455 fLines
.add(index
++, lineData
);
460 LineData lineData
= new LineData(rank
, location
, ""); //$NON-NLS-1$
461 fLines
.add(index
++, lineData
);
467 long rankOffset
= fLines
.get(index
).rank
- rank
;
468 for (int i
= 0; i
< index
; i
++) {
469 fLines
.get(i
).rank
+= rankOffset
;
471 if (firstRatio
== 0) {
475 delta
= Math
.min(delta
* 10, 0.1);
479 if (fTopLineIndex
< 0) {
484 while (fLines
.size() - fTopLineIndex
< fNumVisibleLines
) {
485 if (fBottomContext
== null) {
486 if (fLines
.size() == 0) {
487 fBottomContext
= fTrace
.seekEvent(0);
489 //fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).rank + 1);
490 fBottomContext
= fTrace
.seekEvent(fLines
.get(fLines
.size() - 1).location
);
491 fTrace
.getNext(fBottomContext
);
493 if (fBottomContext
== null) {
497 long rank
= fBottomContext
.getRank();
498 ITmfLocation location
= fBottomContext
.getLocation() != null ? fBottomContext
.getLocation() : null;
499 ITmfEvent event
= fTrace
.getNext(fBottomContext
);
503 if (event
.getContent() != null && event
.getContent().getValue() != null) {
504 for (String line
: event
.getContent().getValue().toString().split("\r?\n")) { //$NON-NLS-1$
506 if ((crPos
= line
.indexOf('\r')) != -1) {
507 line
= line
.substring(0, crPos
);
509 LineData lineData
= new LineData(rank
, location
, line
);
510 fLines
.add(lineData
);
513 LineData lineData
= new LineData(rank
, location
, ""); //$NON-NLS-1$
514 fLines
.add(lineData
);
517 fTopLineIndex
= Math
.max(0, Math
.min(fTopLineIndex
, fLines
.size() - 1));
519 if (fLines
.size() > MAX_LINE_DATA_SIZE
) {
520 if (fTopLineIndex
< MAX_LINE_DATA_SIZE
/ 2) {
521 long rank
= fLines
.get(MAX_LINE_DATA_SIZE
- 1).rank
;
522 for (int i
= MAX_LINE_DATA_SIZE
; i
< fLines
.size(); i
++) {
523 if (fLines
.get(i
).rank
> rank
) {
524 fLines
.subList(i
, fLines
.size()).clear();
525 fBottomContext
= null;
530 long rank
= fLines
.get(fLines
.size() - MAX_LINE_DATA_SIZE
).rank
;
531 for (int i
= fLines
.size() - MAX_LINE_DATA_SIZE
- 1; i
>= 0; i
--) {
532 if (fLines
.get(i
).rank
< rank
) {
533 fLines
.subList(0, i
+ 1).clear();
534 fTopLineIndex
-= (i
+ 1);
535 fLastTopLineIndex
-= (i
+ 1);
543 private void refreshTextArea() {
544 fStyledText
.setText(""); //$NON-NLS-1$
545 for (int i
= 0; i
< fLines
.size() - fTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
548 fStyledText
.append("\n"); //$NON-NLS-1$
550 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
551 fStyledText
.append(lineData
.string
);
552 setLineBackground(i
, lineData
);
555 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
556 fLastTopLineIndex
= fTopLineIndex
;
559 private void fillTextArea() {
560 int nextLine
= fStyledText
.getCharCount() == 0 ?
0 : fStyledText
.getLineCount();
561 for (int i
= nextLine
; i
< fLines
.size() - fTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
564 fStyledText
.append("\n"); //$NON-NLS-1$
566 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
567 fStyledText
.append(lineData
.string
);
568 setLineBackground(i
, lineData
);
570 int endLine
= Math
.min(fNumVisibleLines
, fLines
.size());
571 if (endLine
< fStyledText
.getLineCount()) {
572 int endOffset
= fStyledText
.getOffsetAtLine(endLine
) - 1;
573 if (endOffset
> fStyledText
.getCharCount()) {
575 fStyledText
.replaceTextRange(endOffset
, fStyledText
.getCharCount() - endOffset
, ""); //$NON-NLS-1$
580 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
583 private void updateTextArea() {
584 if (fTopLineIndex
< fLastTopLineIndex
) {
585 StringBuffer insertedText
= new StringBuffer();
586 for (int i
= fTopLineIndex
; i
< fLastTopLineIndex
; i
++) {
587 insertedText
.append(fLines
.get(i
).string
+ "\n"); //$NON-NLS-1$
589 fStyledText
.replaceTextRange(0, 0, insertedText
.toString());
590 for (int i
= 0; i
< fLastTopLineIndex
- fTopLineIndex
; i
++) {
591 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
592 setLineBackground(i
, lineData
);
594 fLastTopLineIndex
= fTopLineIndex
;
595 } else if (fTopLineIndex
> fLastTopLineIndex
) {
597 for (int i
= 0; i
< fTopLineIndex
- fLastTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
598 length
+= fLines
.get(i
+ fLastTopLineIndex
).string
.length();
599 if (i
< fStyledText
.getLineCount()) {
603 fStyledText
.replaceTextRange(0, length
, ""); //$NON-NLS-1$
604 fLastTopLineIndex
= fTopLineIndex
;
607 int endLine
= Math
.min(fNumVisibleLines
, fLines
.size());
608 if (endLine
< fStyledText
.getLineCount()) {
609 int endOffset
= fStyledText
.getOffsetAtLine(endLine
) - 1;
610 if (endOffset
> fStyledText
.getCharCount()) {
611 fStyledText
.replaceTextRange(endOffset
, fStyledText
.getCharCount() - endOffset
, ""); //$NON-NLS-1$
615 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
618 private void refreshLineBackgrounds() {
619 for (int i
= 0; (i
< fStyledText
.getLineCount()) && (i
< fNumVisibleLines
) && (i
< fLines
.size() - fTopLineIndex
); i
++) {
620 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
621 setLineBackground(i
, lineData
);
625 private void setLineBackground(int index
, LineData lineData
) {
626 if (lineData
.location
.equals(fSelectedLocation
)) {
627 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_SELECTED
);
628 } else if (lineData
.rank
== fHighlightedRank
) {
629 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_HIGHLIGHTED
);
630 } else if (lineData
.rank
% 2 == 0) {
631 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_EVEN
);
633 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_ODD
);
637 private void storeCaretPosition(int time
, int caretOffset
) {
638 if (fStoredCaretPosition
[0].time
== time
) {
639 fStoredCaretPosition
[0].caretOffset
= caretOffset
;
641 fStoredCaretPosition
[1] = fStoredCaretPosition
[0];
642 fStoredCaretPosition
[0] = new CaretPosition(time
, caretOffset
);
646 private int getPreviousCaretOffset(int time
) {
647 if (fStoredCaretPosition
[0].time
== time
) {
648 return fStoredCaretPosition
[1].caretOffset
;
650 return fStoredCaretPosition
[0].caretOffset
;
653 private void updateHighlightedRank() {
654 if (fCursorYCoordinate
< 0 || fCursorYCoordinate
> fStyledText
.getSize().y
) {
655 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
656 fHighlightedRank
= Long
.MIN_VALUE
;
657 refreshLineBackgrounds();
661 int offset
= fStyledText
.getOffsetAtLocation(new Point(0, fCursorYCoordinate
));
662 int line
= fStyledText
.getLineAtOffset(offset
);
663 if (line
< fLines
.size() - fTopLineIndex
) {
664 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
665 if (fHighlightedRank
!= lineData
.rank
) {
666 fHighlightedRank
= lineData
.rank
;
667 refreshLineBackgrounds();
670 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
671 fHighlightedRank
= Long
.MIN_VALUE
;
672 refreshLineBackgrounds();
677 // ------------------------------------------------------------------------
678 // ControlListener (ScrolledComposite)
679 // ------------------------------------------------------------------------
682 public void controlResized(ControlEvent event
) {
683 int areaHeight
= fScrolledComposite
.getSize().y
;
684 if (fScrolledComposite
.getHorizontalBar() != null) {
685 areaHeight
-= fScrolledComposite
.getHorizontalBar().getSize().y
;
687 int lineHeight
= fStyledText
.getLineHeight();
688 fNumVisibleLines
= Math
.max((areaHeight
+ lineHeight
- 1) / lineHeight
, 1);
690 if (fBottomContext
!= null) {
697 public void controlMoved(ControlEvent e
) {
700 // ------------------------------------------------------------------------
701 // SelectionListener (Slider)
702 // ------------------------------------------------------------------------
705 public void widgetSelected(SelectionEvent e
) {
706 fTextArea
.setFocus();
707 if (fLines
.size() == 0) {
710 if (e
.detail
== SWT
.DRAG
) {
716 //long rank = (long) (fTrace.getNbEvents() * ((double) fSlider.getSelection() / SLIDER_MAX));
718 if (fSlider
.getSelection() == 0 || fSlider
.getThumb() == SLIDER_MAX
) {
723 double ratio
= (double) fSlider
.getSelection() / (SLIDER_MAX
- fSlider
.getThumb());
724 double delta
= Math
.pow(10, -15);
726 while (fLines
.size() == 0) {
727 setTopPosition(ratio
);
731 delta
= Math
.min(delta
* 10, 0.1);
732 ratio
= Math
.max(ratio
- delta
, 0.0);
736 case SWT
.ARROW_DOWN
: {
737 if (fTopLineIndex
>= fLines
.size()) {
745 case SWT
.PAGE_DOWN
: {
746 fTopLineIndex
+= Math
.max(fNumVisibleLines
- 1, 1);
752 //if (fLines.size() == 0 || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
753 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
762 fTopLineIndex
-= Math
.max(fNumVisibleLines
- 1, 1);
768 //selectAndReveal(0);
773 //if (fTrace.getNbEvents() > 0) {
774 //selectAndReveal(fTrace.getNbEvents() - 1);
777 double delta
= Math
.pow(10, -15);
779 while (fLines
.size() == 0) {
780 setTopPosition(ratio
);
784 delta
= Math
.min(delta
* 10, 0.1);
785 ratio
= Math
.max(ratio
- delta
, 0.0);
792 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
793 if (e
.detail
!= SWT
.NONE
) {
794 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
801 public void widgetDefaultSelected(SelectionEvent e
) {
804 // ------------------------------------------------------------------------
805 // KeyListener (StyledText)
806 // ------------------------------------------------------------------------
809 public void keyPressed(KeyEvent e
) {
810 if (fLines
.size() == 0) {
813 int caretOffset
= fStyledText
.getCaretOffset();
814 int previousCaretOffset
= getPreviousCaretOffset(e
.time
);
815 int previousLineAtCaretPosition
= fStyledText
.getLineAtOffset(previousCaretOffset
);
816 int previousColumnAtCaretPosition
= getPreviousCaretOffset(e
.time
) - fStyledText
.getOffsetAtLine(previousLineAtCaretPosition
);
818 case SWT
.ARROW_DOWN
: {
819 if (previousLineAtCaretPosition
< (fNumVisibleLines
- 2)) {
827 LineData lineData
= fLines
.get(fTopLineIndex
+ fStyledText
.getLineAtOffset(fStyledText
.getCaretOffset()));
828 if (!lineData
.location
.equals(fSelectedLocation
)) {
829 fSelectedLocation
= lineData
.location
;
830 refreshLineBackgrounds();
831 sendSelectionEvent(lineData
);
835 case SWT
.PAGE_DOWN
: {
836 if (previousLineAtCaretPosition
>= (fNumVisibleLines
- 1)) {
838 if (fLines
.get(fTopLineIndex
+ previousLineAtCaretPosition
).rank
% 2 == 0) {
839 fStyledText
.setLineBackground(previousLineAtCaretPosition
, 1, COLOR_BACKGROUND_EVEN
);
841 fStyledText
.setLineBackground(previousLineAtCaretPosition
, 1, COLOR_BACKGROUND_ODD
);
843 fSelectedLocation
= null;
844 fTopLineIndex
+= Math
.max(fNumVisibleLines
- 1, 1);
849 int line
= Math
.min(fNumVisibleLines
- 1, fStyledText
.getLineCount() - 1);
850 int offset
= fStyledText
.getOffsetAtLine(line
);
851 fStyledText
.setSelection(offset
+ Math
.min(previousColumnAtCaretPosition
, fLines
.get(fTopLineIndex
+ line
).string
.length()));
854 case SWT
.ARROW_RIGHT
: {
855 if (previousCaretOffset
< fStyledText
.getCharCount() || previousLineAtCaretPosition
< (fNumVisibleLines
- 2)) {
863 fStyledText
.setSelection(fStyledText
.getCaretOffset() + 1);
867 if (previousLineAtCaretPosition
> 0) {
870 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
878 LineData lineData
= fLines
.get(fTopLineIndex
);
879 if (!lineData
.location
.equals(fSelectedLocation
)) {
880 fSelectedLocation
= lineData
.location
;
881 refreshLineBackgrounds();
882 sendSelectionEvent(lineData
);
884 fStyledText
.setSelection(caretOffset
);
888 if (previousLineAtCaretPosition
> 0) {
892 fTopLineIndex
-= Math
.max(fNumVisibleLines
- 1, 1);
896 LineData lineData
= fLines
.get(fTopLineIndex
);
897 if (!lineData
.location
.equals(fSelectedLocation
)) {
898 fSelectedLocation
= lineData
.location
;
899 refreshLineBackgrounds();
900 sendSelectionEvent(lineData
);
902 fStyledText
.setSelection(caretOffset
);
905 case SWT
.ARROW_LEFT
: {
906 if (previousCaretOffset
> 0) {
909 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
912 long topRank
= fLines
.get(fTopLineIndex
).rank
;
918 LineData lineData
= fLines
.get(fTopLineIndex
);
919 if (!lineData
.location
.equals(fSelectedLocation
)) {
920 fSelectedLocation
= lineData
.location
;
921 refreshLineBackgrounds();
922 sendSelectionEvent(lineData
);
924 if (topRank
!= fLines
.get(fTopLineIndex
).rank
) {
925 fStyledText
.setSelection(fLines
.get(fTopLineIndex
).string
.length());
930 if ((e
.stateMask
& SWT
.CTRL
) == 0) {
933 //selectAndReveal(0);
935 LineData lineData
= fLines
.get(fTopLineIndex
);
936 if (!lineData
.location
.equals(fSelectedLocation
)) {
937 fSelectedLocation
= lineData
.location
;
938 refreshLineBackgrounds();
939 sendSelectionEvent(lineData
);
944 if ((e
.stateMask
& SWT
.CTRL
) == 0) {
947 //if (fTrace.getNbEvents() > 0) {
948 //selectAndReveal(fTrace.getNbEvents() - 1);
951 double delta
= Math
.pow(10, -15);
953 while (fLines
.size() == 0) {
954 setTopPosition(ratio
);
958 delta
= Math
.min(delta
* 10, 0.1);
959 ratio
= Math
.max(ratio
- delta
, 0.0);
961 LineData lineData
= fLines
.get(fTopLineIndex
);
962 if (!lineData
.location
.equals(fSelectedLocation
)) {
963 fSelectedLocation
= lineData
.location
;
964 refreshLineBackgrounds();
965 sendSelectionEvent(lineData
);
972 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
973 updateHighlightedRank();
974 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
978 public void keyReleased(KeyEvent e
) {
981 // ------------------------------------------------------------------------
982 // CaretListener (StyledText)
983 // ------------------------------------------------------------------------
986 public void caretMoved(CaretEvent event
) {
987 if (fHoldSelection
== 0) {
988 int line
= fStyledText
.getLineAtOffset(event
.caretOffset
);
989 if (fTopLineIndex
+ line
< fLines
.size()) {
990 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
991 if (!lineData
.location
.equals(fSelectedLocation
)) {
992 fSelectedLocation
= lineData
.location
;
993 refreshLineBackgrounds();
994 sendSelectionEvent(lineData
);
998 storeCaretPosition(event
.time
, event
.caretOffset
);
999 if (fHoldSelection
== 0) {
1000 Point caret
= fStyledText
.getLocationAtOffset(fStyledText
.getCaretOffset());
1001 Point origin
= fScrolledComposite
.getOrigin();
1002 if (origin
.x
> caret
.x
) {
1004 } else if (caret
.x
- origin
.x
> fScrolledComposite
.getSize().x
) {
1005 origin
.x
= caret
.x
- fScrolledComposite
.getSize().x
+ 1;
1007 fScrolledComposite
.setOrigin(origin
);
1011 // ------------------------------------------------------------------------
1012 // MouseMoveListener (StyledText)
1013 // ------------------------------------------------------------------------
1016 public void mouseMove(MouseEvent e
) {
1017 fCursorYCoordinate
= e
.y
;
1018 if (e
.y
< 0 || e
.y
> fStyledText
.getSize().y
) {
1019 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
1020 fHighlightedRank
= Long
.MIN_VALUE
;
1021 refreshLineBackgrounds();
1025 int offset
= fStyledText
.getOffsetAtLocation(new Point(0, e
.y
));
1026 int line
= fStyledText
.getLineAtOffset(offset
);
1027 if (line
< fLines
.size() - fTopLineIndex
) {
1028 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
1029 if (fHighlightedRank
!= lineData
.rank
) {
1030 fHighlightedRank
= lineData
.rank
;
1031 refreshLineBackgrounds();
1034 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
1035 fHighlightedRank
= Long
.MIN_VALUE
;
1036 refreshLineBackgrounds();
1041 // ------------------------------------------------------------------------
1042 // MouseTrackListener (StyledText)
1043 // ------------------------------------------------------------------------
1046 public void mouseExit(MouseEvent e
) {
1047 fCursorYCoordinate
= -1;
1048 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
1049 fHighlightedRank
= Long
.MIN_VALUE
;
1050 refreshLineBackgrounds();
1055 public void mouseEnter(MouseEvent e
) {
1056 fCursorYCoordinate
= e
.y
;
1060 public void mouseHover(MouseEvent e
) {
1063 // ------------------------------------------------------------------------
1064 // MouseWheelListener (StyledText)
1065 // ------------------------------------------------------------------------
1068 public void mouseScrolled(MouseEvent e
) {
1069 if (fLines
.size() == 0) {
1073 fTopLineIndex
-= e
.count
;
1077 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
1078 updateHighlightedRank();
1079 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));