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