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 List
<LineData
> fLines
= new ArrayList
<LineData
>();
84 private boolean fActualRanks
= false;
85 private int fTopLineIndex
;
86 private int fLastTopLineIndex
;
87 private 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
);
268 if (!isVisible()) return;
270 if (fLines
.size() == 0) {
272 } else if (fLines
.size() < fNumVisibleLines
) {
273 fBottomContext
= null;
276 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
277 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
283 * Selects the event of given rank and makes it visible.
284 * @param rank The rank of event
286 public void selectAndReveal(long rank
) {
287 if (fTrace
== null || !isVisible()) {
290 if (fActualRanks
&& fTopLineIndex
< fLines
.size() && rank
>= fLines
.get(fTopLineIndex
).rank
) {
291 int lastVisibleIndex
= Math
.min(fTopLineIndex
+ fNumVisibleLines
, fLines
.size()) - 1;
292 if (rank
<= fLines
.get(lastVisibleIndex
).rank
) {
293 for (int i
= fTopLineIndex
; i
< fLines
.size(); i
++) {
294 if (fLines
.get(i
).rank
== rank
) {
295 fSelectedLocation
= fLines
.get(i
).location
;
299 refreshLineBackgrounds();
304 if (fLines
.size() > 0 && fHoldSelection
== 0) {
305 fSelectedLocation
= fLines
.get(0).location
;
306 refreshLineBackgrounds();
310 * Add a selection listener
311 * @param listener A listener to add
313 public void addSelectionListener(Listener listener
) {
315 if (listener
== null) SWT
.error (SWT
.ERROR_NULL_ARGUMENT
);
316 addListener (SWT
.Selection
, listener
);
320 * Remove selection listener
321 * @param listener A listener to remove
323 public void removeSelectionListener(Listener listener
) {
325 if (listener
== null) SWT
.error (SWT
.ERROR_NULL_ARGUMENT
);
326 removeListener(SWT
.Selection
, listener
);
329 private void sendSelectionEvent(LineData lineData
) {
330 Event event
= new Event();
332 event
.data
= Long
.valueOf(lineData
.rank
);
334 event
.data
= lineData
.location
;
336 notifyListeners(SWT
.Selection
, event
);
339 private void setTopRank(long rank
) {
340 fBottomContext
= fTrace
.seekEvent(rank
);
341 if (fBottomContext
== null) {
349 if (fLines
.size() == 0) {
350 fSlider
.setSelection(0);
352 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
353 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
357 private void setTopPosition(double ratio
) {
358 fBottomContext
= fTrace
.seekEvent(ratio
);
359 if (fBottomContext
== null) {
362 fBottomContext
.setRank(0);
364 fActualRanks
= false;
370 private void loadLineData() {
371 if (fTopLineIndex
< 0) {
372 //if (fLines.size() > 0 && fLines.get(0).rank > 0) {
373 //long endRank = fLines.get(0).rank;
374 //long startRank = Math.max(0, endRank - fNumVisibleLines);
375 //TmfContext context = fTrace.seekEvent(startRank);
377 //while (context.getRank() < endRank) {
378 //long rank = context.getRank();
379 //ITmfLocation<?> location = context.getLocation();
380 //TmfEvent event = fTrace.getNextEvent(context);
381 //String[] lines = event.getRawText().split("\r?\n");
382 //for (int i = 0; i < lines.length; i++) {
383 //String line = lines[i];
384 //LineData lineData = new LineData(rank, location, line);
385 //fLines.add(index++, lineData);
387 //fLastTopLineIndex++;
391 if (fLines
.size() > 0 && fTrace
.getLocationRatio(fLines
.get(0).location
) > 0) {
392 double lastRatio
= fTrace
.getLocationRatio(fLines
.get(fLines
.size() - 1).location
);
393 double firstRatio
= fTrace
.getLocationRatio(fLines
.get(0).location
);
395 boolean singleEvent
= false;
396 if (firstRatio
!= lastRatio
) {
397 // approximate ratio of at least 20 items
398 delta
= Math
.max(20, fNumVisibleLines
) * (lastRatio
- firstRatio
) / (fLines
.size() - 1);
400 delta
= Math
.pow(10, -15);
403 while (fTopLineIndex
< 0) {
404 ITmfLocation
<?
> endLocation
= fLines
.get(0).location
;
405 firstRatio
= Math
.max(0, firstRatio
- delta
);
406 ITmfContext context
= fTrace
.seekEvent(firstRatio
);
407 ITmfLocation
<?
> location
;
410 while (!context
.getLocation().equals(endLocation
)) {
411 location
= context
.getLocation().clone();
412 ITmfEvent event
= fTrace
.getNext(context
);
416 if (event
.getContent() != null && event
.getContent().getValue() != null) {
417 String
[] lines
= event
.getContent().getValue().toString().split("\r?\n"); //$NON-NLS-1$
418 for (int i
= 0; i
< lines
.length
; i
++) {
419 String line
= lines
[i
];
420 LineData lineData
= new LineData(rank
, location
, line
);
421 fLines
.add(index
++, lineData
);
426 LineData lineData
= new LineData(rank
, location
, ""); //$NON-NLS-1$
427 fLines
.add(index
++, lineData
);
433 long rankOffset
= fLines
.get(index
).rank
- rank
;
434 for (int i
= 0; i
< index
; i
++) {
435 fLines
.get(i
).rank
+= rankOffset
;
437 if (firstRatio
== 0) {
441 delta
= Math
.min(delta
* 10, 0.1);
445 if (fTopLineIndex
< 0) {
450 while (fLines
.size() - fTopLineIndex
< fNumVisibleLines
) {
451 if (fBottomContext
== null) {
452 if (fLines
.size() == 0) {
453 fBottomContext
= fTrace
.seekEvent(0);
455 //fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).rank + 1);
456 fBottomContext
= fTrace
.seekEvent(fLines
.get(fLines
.size() - 1).location
);
457 fTrace
.getNext(fBottomContext
);
459 if (fBottomContext
== null) {
463 long rank
= fBottomContext
.getRank();
464 ITmfLocation
<?
> location
= fBottomContext
.getLocation() != null ? fBottomContext
.getLocation().clone() : null;
465 ITmfEvent event
= fTrace
.getNext(fBottomContext
);
469 if (event
.getContent() != null && event
.getContent().getValue() != null) {
470 for (String line
: event
.getContent().getValue().toString().split("\r?\n")) { //$NON-NLS-1$
472 if ((crPos
= line
.indexOf('\r')) != -1) {
473 line
= line
.substring(0, crPos
);
475 LineData lineData
= new LineData(rank
, location
, line
);
476 fLines
.add(lineData
);
479 LineData lineData
= new LineData(rank
, location
, ""); //$NON-NLS-1$
480 fLines
.add(lineData
);
483 fTopLineIndex
= Math
.max(0, Math
.min(fTopLineIndex
, fLines
.size() - 1));
485 if (fLines
.size() > MAX_LINE_DATA_SIZE
) {
486 if (fTopLineIndex
< MAX_LINE_DATA_SIZE
/ 2) {
487 long rank
= fLines
.get(MAX_LINE_DATA_SIZE
- 1).rank
;
488 for (int i
= MAX_LINE_DATA_SIZE
; i
< fLines
.size(); i
++) {
489 if (fLines
.get(i
).rank
> rank
) {
490 fLines
.subList(i
, fLines
.size()).clear();
491 fBottomContext
= null;
496 long rank
= fLines
.get(fLines
.size() - MAX_LINE_DATA_SIZE
).rank
;
497 for (int i
= fLines
.size() - MAX_LINE_DATA_SIZE
- 1; i
>= 0; i
--) {
498 if (fLines
.get(i
).rank
< rank
) {
499 fLines
.subList(0, i
+ 1).clear();
500 fTopLineIndex
-= (i
+ 1);
501 fLastTopLineIndex
-= (i
+ 1);
509 private void refreshTextArea() {
510 fStyledText
.setText(""); //$NON-NLS-1$
511 for (int i
= 0; i
< fLines
.size() - fTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
512 if (i
> 0) fStyledText
.append("\n"); //$NON-NLS-1$
513 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
514 fStyledText
.append(lineData
.string
);
515 setLineBackground(i
, lineData
);
518 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
519 fLastTopLineIndex
= fTopLineIndex
;
522 private void fillTextArea() {
523 int nextLine
= fStyledText
.getCharCount() == 0 ?
0 : fStyledText
.getLineCount();
524 for (int i
= nextLine
; i
< fLines
.size() - fTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
525 if (i
> 0) fStyledText
.append("\n"); //$NON-NLS-1$
526 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
527 fStyledText
.append(lineData
.string
);
528 setLineBackground(i
, lineData
);
530 int endLine
= Math
.min(fNumVisibleLines
, fLines
.size());
531 if (endLine
< fStyledText
.getLineCount()) {
532 int endOffset
= fStyledText
.getOffsetAtLine(endLine
) - 1;
533 if (endOffset
> fStyledText
.getCharCount()) {
535 fStyledText
.replaceTextRange(endOffset
, fStyledText
.getCharCount() - endOffset
, ""); //$NON-NLS-1$
540 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
543 private void updateTextArea() {
544 if (fTopLineIndex
< fLastTopLineIndex
) {
545 StringBuffer insertedText
= new StringBuffer();
546 for (int i
= fTopLineIndex
; i
< fLastTopLineIndex
; i
++) {
547 insertedText
.append(fLines
.get(i
).string
+ "\n"); //$NON-NLS-1$
549 fStyledText
.replaceTextRange(0, 0, insertedText
.toString());
550 for (int i
= 0; i
< fLastTopLineIndex
- fTopLineIndex
; i
++) {
551 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
552 setLineBackground(i
, lineData
);
554 fLastTopLineIndex
= fTopLineIndex
;
555 } else if (fTopLineIndex
> fLastTopLineIndex
) {
557 for (int i
= 0; i
< fTopLineIndex
- fLastTopLineIndex
&& i
< fNumVisibleLines
; i
++) {
558 length
+= fLines
.get(i
+ fLastTopLineIndex
).string
.length();
559 if (i
< fStyledText
.getLineCount()) length
+= 1;
561 fStyledText
.replaceTextRange(0, length
, ""); //$NON-NLS-1$
562 fLastTopLineIndex
= fTopLineIndex
;
565 int endLine
= Math
.min(fNumVisibleLines
, fLines
.size());
566 if (endLine
< fStyledText
.getLineCount()) {
567 int endOffset
= fStyledText
.getOffsetAtLine(endLine
) - 1;
568 if (endOffset
> fStyledText
.getCharCount()) {
569 fStyledText
.replaceTextRange(endOffset
, fStyledText
.getCharCount() - endOffset
, ""); //$NON-NLS-1$
573 fScrolledComposite
.setMinSize(fTextArea
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
576 private void refreshLineBackgrounds() {
577 for (int i
= 0; (i
< fStyledText
.getLineCount()) && (i
< fNumVisibleLines
) && (i
< fLines
.size() - fTopLineIndex
); i
++) {
578 LineData lineData
= fLines
.get(fTopLineIndex
+ i
);
579 setLineBackground(i
, lineData
);
583 private void setLineBackground(int index
, LineData lineData
) {
584 if (lineData
.location
.equals(fSelectedLocation
)) {
585 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_SELECTED
);
586 } else if (lineData
.rank
== fHighlightedRank
) {
587 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_HIGHLIGHTED
);
588 } else if (lineData
.rank
% 2 == 0) {
589 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_EVEN
);
591 fStyledText
.setLineBackground(index
, 1, COLOR_BACKGROUND_ODD
);
595 private void storeCaretPosition(int time
, int caretOffset
) {
596 if (fStoredCaretPosition
[0].time
== time
) {
597 fStoredCaretPosition
[0].caretOffset
= caretOffset
;
599 fStoredCaretPosition
[1] = fStoredCaretPosition
[0];
600 fStoredCaretPosition
[0] = new CaretPosition(time
, caretOffset
);
604 private int getPreviousCaretOffset(int time
) {
605 if (fStoredCaretPosition
[0].time
== time
) {
606 return fStoredCaretPosition
[1].caretOffset
;
608 return fStoredCaretPosition
[0].caretOffset
;
612 private void updateHighlightedRank() {
613 if (fCursorYCoordinate
< 0 || fCursorYCoordinate
> fStyledText
.getSize().y
) {
614 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
615 fHighlightedRank
= Long
.MIN_VALUE
;
616 refreshLineBackgrounds();
620 int offset
= fStyledText
.getOffsetAtLocation(new Point(0, fCursorYCoordinate
));
621 int line
= fStyledText
.getLineAtOffset(offset
);
622 if (line
< fLines
.size() - fTopLineIndex
) {
623 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
624 if (fHighlightedRank
!= lineData
.rank
) {
625 fHighlightedRank
= lineData
.rank
;
626 refreshLineBackgrounds();
629 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
630 fHighlightedRank
= Long
.MIN_VALUE
;
631 refreshLineBackgrounds();
636 // ------------------------------------------------------------------------
637 // ControlListener (ScrolledComposite)
638 // ------------------------------------------------------------------------
641 public void controlResized(ControlEvent event
) {
642 int areaHeight
= fScrolledComposite
.getSize().y
;
643 if (fScrolledComposite
.getHorizontalBar() != null) {
644 areaHeight
-= fScrolledComposite
.getHorizontalBar().getSize().y
;
646 int lineHeight
= fStyledText
.getLineHeight();
647 fNumVisibleLines
= Math
.max((areaHeight
+ lineHeight
- 1) / lineHeight
, 1);
649 if (fBottomContext
!= null) {
656 public void controlMoved(ControlEvent e
) {
659 // ------------------------------------------------------------------------
660 // SelectionListener (Slider)
661 // ------------------------------------------------------------------------
664 public void widgetSelected(SelectionEvent e
) {
665 fTextArea
.setFocus();
666 if (fLines
.size() == 0) {
669 if (e
.detail
== SWT
.DRAG
) {
675 //long rank = (long) (fTrace.getNbEvents() * ((double) fSlider.getSelection() / SLIDER_MAX));
677 if (fSlider
.getSelection() == 0 || fSlider
.getThumb() == SLIDER_MAX
) {
682 double ratio
= (double) fSlider
.getSelection() / (SLIDER_MAX
- fSlider
.getThumb());
683 double delta
= Math
.pow(10, -15);
685 while (fLines
.size() == 0) {
686 setTopPosition(ratio
);
687 if (ratio
== 0.0) break;
688 delta
= Math
.min(delta
* 10, 0.1);
689 ratio
= Math
.max(ratio
- delta
, 0.0);
693 case SWT
.ARROW_DOWN
: {
694 if (fTopLineIndex
>= fLines
.size()) {
702 case SWT
.PAGE_DOWN
: {
703 fTopLineIndex
+= Math
.max(fNumVisibleLines
- 1, 1);
709 //if (fLines.size() == 0 || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
710 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
719 fTopLineIndex
-= Math
.max(fNumVisibleLines
- 1, 1);
725 //selectAndReveal(0);
730 //if (fTrace.getNbEvents() > 0) {
731 //selectAndReveal(fTrace.getNbEvents() - 1);
734 double delta
= Math
.pow(10, -15);
736 while (fLines
.size() == 0) {
737 setTopPosition(ratio
);
738 if (ratio
== 0.0) break;
739 delta
= Math
.min(delta
* 10, 0.1);
740 ratio
= Math
.max(ratio
- delta
, 0.0);
745 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
746 if (e
.detail
!= SWT
.NONE
) {
747 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
754 public void widgetDefaultSelected(SelectionEvent e
) {
757 // ------------------------------------------------------------------------
758 // KeyListener (StyledText)
759 // ------------------------------------------------------------------------
762 public void keyPressed(KeyEvent e
) {
763 if (fLines
.size() == 0) {
766 int caretOffset
= fStyledText
.getCaretOffset();
767 int previousCaretOffset
= getPreviousCaretOffset(e
.time
);
768 int previousLineAtCaretPosition
= fStyledText
.getLineAtOffset(previousCaretOffset
);
769 int previousColumnAtCaretPosition
= getPreviousCaretOffset(e
.time
) - fStyledText
.getOffsetAtLine(previousLineAtCaretPosition
);
771 case SWT
.ARROW_DOWN
: {
772 if (previousLineAtCaretPosition
< (fNumVisibleLines
- 2)) {
780 LineData lineData
= fLines
.get(fTopLineIndex
+ fStyledText
.getLineAtOffset(fStyledText
.getCaretOffset()));
781 if (!lineData
.location
.equals(fSelectedLocation
)) {
782 fSelectedLocation
= lineData
.location
;
783 refreshLineBackgrounds();
784 sendSelectionEvent(lineData
);
788 case SWT
.PAGE_DOWN
: {
789 if (previousLineAtCaretPosition
>= (fNumVisibleLines
- 1)) {
791 if (fLines
.get(fTopLineIndex
+ previousLineAtCaretPosition
).rank
% 2 == 0) {
792 fStyledText
.setLineBackground(previousLineAtCaretPosition
, 1, COLOR_BACKGROUND_EVEN
);
794 fStyledText
.setLineBackground(previousLineAtCaretPosition
, 1, COLOR_BACKGROUND_ODD
);
796 fSelectedLocation
= null;
797 fTopLineIndex
+= Math
.max(fNumVisibleLines
- 1, 1);
802 int line
= Math
.min(fNumVisibleLines
- 1, fStyledText
.getLineCount() - 1);
803 int offset
= fStyledText
.getOffsetAtLine(line
);
804 fStyledText
.setSelection(offset
+ Math
.min(previousColumnAtCaretPosition
, fLines
.get(fTopLineIndex
+ line
).string
.length()));
807 case SWT
.ARROW_RIGHT
: {
808 if (previousCaretOffset
< fStyledText
.getCharCount() || previousLineAtCaretPosition
< (fNumVisibleLines
- 2)) {
816 fStyledText
.setSelection(fStyledText
.getCaretOffset() + 1);
820 if (previousLineAtCaretPosition
> 0) {
823 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
831 LineData lineData
= fLines
.get(fTopLineIndex
);
832 if (!lineData
.location
.equals(fSelectedLocation
)) {
833 fSelectedLocation
= lineData
.location
;
834 refreshLineBackgrounds();
835 sendSelectionEvent(lineData
);
837 fStyledText
.setSelection(caretOffset
);
841 if (previousLineAtCaretPosition
> 0) {
845 fTopLineIndex
-= Math
.max(fNumVisibleLines
- 1, 1);
849 LineData lineData
= fLines
.get(fTopLineIndex
);
850 if (!lineData
.location
.equals(fSelectedLocation
)) {
851 fSelectedLocation
= lineData
.location
;
852 refreshLineBackgrounds();
853 sendSelectionEvent(lineData
);
855 fStyledText
.setSelection(caretOffset
);
858 case SWT
.ARROW_LEFT
: {
859 if (previousCaretOffset
> 0) {
862 if (fLines
.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
865 long topRank
= fLines
.get(fTopLineIndex
).rank
;
871 LineData lineData
= fLines
.get(fTopLineIndex
);
872 if (!lineData
.location
.equals(fSelectedLocation
)) {
873 fSelectedLocation
= lineData
.location
;
874 refreshLineBackgrounds();
875 sendSelectionEvent(lineData
);
877 if (topRank
!= fLines
.get(fTopLineIndex
).rank
) {
878 fStyledText
.setSelection(fLines
.get(fTopLineIndex
).string
.length());
883 if ((e
.stateMask
& SWT
.CTRL
) == 0) {
886 //selectAndReveal(0);
888 LineData lineData
= fLines
.get(fTopLineIndex
);
889 if (!lineData
.location
.equals(fSelectedLocation
)) {
890 fSelectedLocation
= lineData
.location
;
891 refreshLineBackgrounds();
892 sendSelectionEvent(lineData
);
897 if ((e
.stateMask
& SWT
.CTRL
) == 0) {
900 //if (fTrace.getNbEvents() > 0) {
901 //selectAndReveal(fTrace.getNbEvents() - 1);
904 double delta
= Math
.pow(10, -15);
906 while (fLines
.size() == 0) {
907 setTopPosition(ratio
);
908 if (ratio
== 0.0) break;
909 delta
= Math
.min(delta
* 10, 0.1);
910 ratio
= Math
.max(ratio
- delta
, 0.0);
912 LineData lineData
= fLines
.get(fTopLineIndex
);
913 if (!lineData
.location
.equals(fSelectedLocation
)) {
914 fSelectedLocation
= lineData
.location
;
915 refreshLineBackgrounds();
916 sendSelectionEvent(lineData
);
921 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
922 updateHighlightedRank();
923 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));
927 public void keyReleased(KeyEvent e
) {
930 // ------------------------------------------------------------------------
931 // CaretListener (StyledText)
932 // ------------------------------------------------------------------------
935 public void caretMoved(CaretEvent event
) {
936 if (fHoldSelection
== 0) {
937 int line
= fStyledText
.getLineAtOffset(event
.caretOffset
);
938 if (fTopLineIndex
+ line
< fLines
.size()) {
939 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
940 if (!lineData
.location
.equals(fSelectedLocation
)) {
941 fSelectedLocation
= lineData
.location
;
942 refreshLineBackgrounds();
943 sendSelectionEvent(lineData
);
947 storeCaretPosition(event
.time
, event
.caretOffset
);
948 if (fHoldSelection
== 0) {
949 Point caret
= fStyledText
.getLocationAtOffset(fStyledText
.getCaretOffset());
950 Point origin
= fScrolledComposite
.getOrigin();
951 if (origin
.x
> caret
.x
) {
953 } else if (caret
.x
- origin
.x
> fScrolledComposite
.getSize().x
) {
954 origin
.x
= caret
.x
- fScrolledComposite
.getSize().x
+ 1;
956 fScrolledComposite
.setOrigin(origin
);
960 // ------------------------------------------------------------------------
961 // MouseMoveListener (StyledText)
962 // ------------------------------------------------------------------------
965 public void mouseMove(MouseEvent e
) {
966 fCursorYCoordinate
= e
.y
;
967 if (e
.y
< 0 || e
.y
> fStyledText
.getSize().y
) {
968 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
969 fHighlightedRank
= Long
.MIN_VALUE
;
970 refreshLineBackgrounds();
974 int offset
= fStyledText
.getOffsetAtLocation(new Point(0, e
.y
));
975 int line
= fStyledText
.getLineAtOffset(offset
);
976 if (line
< fLines
.size() - fTopLineIndex
) {
977 LineData lineData
= fLines
.get(fTopLineIndex
+ line
);
978 if (fHighlightedRank
!= lineData
.rank
) {
979 fHighlightedRank
= lineData
.rank
;
980 refreshLineBackgrounds();
983 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
984 fHighlightedRank
= Long
.MIN_VALUE
;
985 refreshLineBackgrounds();
990 // ------------------------------------------------------------------------
991 // MouseTrackListener (StyledText)
992 // ------------------------------------------------------------------------
995 public void mouseExit(MouseEvent e
) {
996 fCursorYCoordinate
= -1;
997 if (fHighlightedRank
!= Long
.MIN_VALUE
) {
998 fHighlightedRank
= Long
.MIN_VALUE
;
999 refreshLineBackgrounds();
1004 public void mouseEnter(MouseEvent e
) {
1005 fCursorYCoordinate
= e
.y
;
1009 public void mouseHover(MouseEvent e
) {
1012 // ------------------------------------------------------------------------
1013 // MouseWheelListener (StyledText)
1014 // ------------------------------------------------------------------------
1017 public void mouseScrolled(MouseEvent e
) {
1018 if (fLines
.size() == 0) {
1022 fTopLineIndex
-= e
.count
;
1026 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
1027 updateHighlightedRank();
1028 fSlider
.setSelection((int) (SLIDER_MAX
* fTrace
.getLocationRatio(fLines
.get(fTopLineIndex
).location
)));