e6ff77486d7a87a74282f69434837407ba1fbb91
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / widgets / rawviewer / TmfRawEventViewer.java
1 /*******************************************************************************
2 * Copyright (c) 2010, 2012 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.rawviewer;
14
15 import java.util.ArrayList;
16 import java.util.List;
17
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;
51
52 /**
53 * TmfRawEventViewer allows for the display of the raw data for an arbitrarily
54 * large number of TMF events.
55 *
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.
60 *
61 * @version 1.0
62 * @author Patrick Tasse
63 */
64 public class TmfRawEventViewer extends Composite implements ControlListener, SelectionListener,
65 KeyListener, CaretListener, MouseMoveListener, MouseTrackListener, MouseWheelListener {
66
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;
73
74 private ITmfTrace<?> fTrace;
75 private ITmfContext fBottomContext;
76
77 private ScrolledComposite fScrolledComposite;
78 private Composite fTextArea;
79 private StyledText fStyledText;
80 private Font fFixedFont;
81 private Slider fSlider;
82
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;
94
95 private static class LineData {
96 long rank;
97 ITmfLocation<?> location;
98 String string;
99 public LineData(long rank, ITmfLocation<?> location, String string) {
100 this.rank = rank;
101 this.location = location;
102 if (string.length() == 0) {
103 this.string = " "; // workaround for setLineBackground has no effect on empty line //$NON-NLS-1$
104 } else {
105 this.string = string;
106 }
107 }
108 @Override
109 public String toString() {
110 return rank + " [" + location + "]: " + string; //$NON-NLS-1$ //$NON-NLS-2$
111 }
112 }
113
114 private static class CaretPosition {
115 int time;
116 int caretOffset;
117 public CaretPosition(int time, int caretOffset) {
118 this.time = time;
119 this.caretOffset = caretOffset;
120 }
121 }
122
123 // ------------------------------------------------------------------------
124 // Constructor
125 // ------------------------------------------------------------------------
126
127 /**
128 * Constructor
129 * @param parent The parent composite
130 * @param style The style bits
131 */
132 public TmfRawEventViewer(Composite parent, int style) {
133 super(parent, style & (~SWT.H_SCROLL) & (~SWT.V_SCROLL));
134
135 // Set the layout
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);
143
144 // Create the controls
145 createTextArea(style & SWT.H_SCROLL);
146 createSlider(style & SWT.V_SCROLL);
147
148 // Prevent the slider from being traversed
149 setTabList(new Control[] { fScrolledComposite });
150 }
151
152 @Override
153 public void dispose() {
154 if (fFixedFont != null) {
155 fFixedFont.dispose();
156 fFixedFont = null;
157 }
158 super.dispose();
159 }
160
161 // ------------------------------------------------------------------------
162 // Text area handling
163 // ------------------------------------------------------------------------
164
165 /**
166 * Create the text area and add listeners
167 */
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);
179
180 GridLayout textAreaGridLayout = new GridLayout();
181 textAreaGridLayout.marginHeight = 0;
182 textAreaGridLayout.marginWidth = 0;
183 fTextArea.setLayout(textAreaGridLayout);
184
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$
188 } else {
189 fFixedFont = new Font(Display.getCurrent(), new FontData("Monospace", 10, SWT.NORMAL)); //$NON-NLS-1$
190 }
191 }
192
193 fStyledText = new StyledText(fTextArea, SWT.READ_ONLY);
194 fStyledText.setFont(fFixedFont);
195 fStyledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
196
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
202 @Override
203 public void handleEvent(Event event) { event.doit = false; }});
204 fStyledText.addKeyListener(this);
205
206 fTextArea.setBackground(fStyledText.getBackground());
207 fTextArea.addMouseListener(new MouseAdapter() {
208 @Override
209 public void mouseDown(MouseEvent e) {
210 fTextArea.setFocus();
211 }});
212 }
213
214 // ------------------------------------------------------------------------
215 // Slider handling
216 // ------------------------------------------------------------------------
217
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);
225 }
226 }
227
228 // ------------------------------------------------------------------------
229 // Controls interactions
230 // ------------------------------------------------------------------------
231
232 @Override
233 public boolean setFocus() {
234 boolean isVisible = isVisible();
235 if (isVisible) {
236 fTextArea.setFocus();
237 }
238 return isVisible;
239 }
240
241 @Override
242 public void setMenu(Menu menu) {
243 fStyledText.setMenu(menu);
244 }
245
246 /**
247 * Sets the trace and updates the content
248 * @param trace The trace to set
249 */
250 public void setTrace(ITmfTrace<?> trace) {
251 fTrace = trace;
252 fTopLineIndex = 0;
253 fLines.clear();
254 refreshEventCount();
255 }
256
257 /**
258 * Refreshes the event count, updates the slider thumb and loads display
259 */
260 public void refreshEventCount() {
261 if (fTrace != null) {
262 if (fTrace.getNbEvents() > 0) {
263 fSlider.setThumb((int) Math.max(SLIDER_MAX / fTrace.getNbEvents(), 1));
264 } else {
265 fSlider.setThumb(SLIDER_MAX);
266 }
267
268 if (!isVisible()) return;
269
270 if (fLines.size() == 0) {
271 setTopRank(0);
272 } else if (fLines.size() < fNumVisibleLines) {
273 fBottomContext = null;
274 loadLineData();
275 fillTextArea();
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)));
278 }
279 }
280 }
281
282 /**
283 * Selects the event of given rank and makes it visible.
284 * @param rank The rank of event
285 */
286 public void selectAndReveal(long rank) {
287 if (fTrace == null || !isVisible()) {
288 return;
289 }
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;
296 break;
297 }
298 }
299 refreshLineBackgrounds();
300 return;
301 }
302 }
303 setTopRank(rank);
304 if (fLines.size() > 0 && fHoldSelection == 0) {
305 fSelectedLocation = fLines.get(0).location;
306 refreshLineBackgrounds();
307 }
308 }
309 /**
310 * Add a selection listener
311 * @param listener A listener to add
312 */
313 public void addSelectionListener(Listener listener) {
314 checkWidget();
315 if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
316 addListener (SWT.Selection, listener);
317 }
318
319 /**
320 * Remove selection listener
321 * @param listener A listener to remove
322 */
323 public void removeSelectionListener(Listener listener) {
324 checkWidget();
325 if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
326 removeListener(SWT.Selection, listener);
327 }
328
329 private void sendSelectionEvent(LineData lineData) {
330 Event event = new Event();
331 if (fActualRanks) {
332 event.data = Long.valueOf(lineData.rank);
333 } else {
334 event.data = lineData.location;
335 }
336 notifyListeners(SWT.Selection, event);
337 }
338
339 private void setTopRank(long rank) {
340 fBottomContext = fTrace.seekEvent(rank);
341 if (fBottomContext == null) {
342 return;
343 }
344 fLines.clear();
345 fActualRanks = true;
346 fTopLineIndex = 0;
347 loadLineData();
348 refreshTextArea();
349 if (fLines.size() == 0) {
350 fSlider.setSelection(0);
351 } else {
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)));
354 }
355 }
356
357 private void setTopPosition(double ratio) {
358 fBottomContext = fTrace.seekEvent(ratio);
359 if (fBottomContext == null) {
360 return;
361 }
362 fBottomContext.setRank(0);
363 fLines.clear();
364 fActualRanks = false;
365 fTopLineIndex = 0;
366 loadLineData();
367 refreshTextArea();
368 }
369
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);
376 //int index = 0;
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);
386 //fTopLineIndex++;
387 //fLastTopLineIndex++;
388 //}
389 //}
390 //}
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);
394 double delta;
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);
399 } else {
400 delta = Math.pow(10, -15);
401 singleEvent = true;
402 }
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;
408 int index = 0;
409 long rank = 0;
410 while (!context.getLocation().equals(endLocation)) {
411 location = context.getLocation().clone();
412 ITmfEvent event = fTrace.getNext(context);
413 if (event == null) {
414 break;
415 }
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);
422 fTopLineIndex++;
423 fLastTopLineIndex++;
424 }
425 } else {
426 LineData lineData = new LineData(rank, location, ""); //$NON-NLS-1$
427 fLines.add(index++, lineData);
428 fTopLineIndex++;
429 fLastTopLineIndex++;
430 }
431 rank++;
432 }
433 long rankOffset = fLines.get(index).rank - rank;
434 for (int i = 0; i < index; i++) {
435 fLines.get(i).rank += rankOffset;
436 }
437 if (firstRatio == 0) {
438 break;
439 }
440 if (singleEvent) {
441 delta = Math.min(delta * 10, 0.1);
442 }
443 }
444 }
445 if (fTopLineIndex < 0) {
446 fTopLineIndex = 0;
447 }
448 }
449
450 while (fLines.size() - fTopLineIndex < fNumVisibleLines) {
451 if (fBottomContext == null) {
452 if (fLines.size() == 0) {
453 fBottomContext = fTrace.seekEvent(0);
454 } else {
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);
458 }
459 if (fBottomContext == null) {
460 break;
461 }
462 }
463 long rank = fBottomContext.getRank();
464 ITmfLocation<?> location = fBottomContext.getLocation() != null ? fBottomContext.getLocation().clone() : null;
465 ITmfEvent event = fTrace.getNext(fBottomContext);
466 if (event == null) {
467 break;
468 }
469 if (event.getContent() != null && event.getContent().getValue() != null) {
470 for (String line : event.getContent().getValue().toString().split("\r?\n")) { //$NON-NLS-1$
471 int crPos;
472 if ((crPos = line.indexOf('\r')) != -1) {
473 line = line.substring(0, crPos);
474 }
475 LineData lineData = new LineData(rank, location, line);
476 fLines.add(lineData);
477 }
478 } else {
479 LineData lineData = new LineData(rank, location, ""); //$NON-NLS-1$
480 fLines.add(lineData);
481 }
482 }
483 fTopLineIndex = Math.max(0, Math.min(fTopLineIndex, fLines.size() - 1));
484
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;
492 break;
493 }
494 }
495 } else {
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);
502 break;
503 }
504 }
505 }
506 }
507 }
508
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);
516 }
517 fTextArea.layout();
518 fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
519 fLastTopLineIndex = fTopLineIndex;
520 }
521
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);
529 }
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()) {
534 fHoldSelection++;
535 fStyledText.replaceTextRange(endOffset, fStyledText.getCharCount() - endOffset, ""); //$NON-NLS-1$
536 fHoldSelection--;
537 }
538 }
539 fTextArea.layout();
540 fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
541 }
542
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$
548 }
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);
553 }
554 fLastTopLineIndex = fTopLineIndex;
555 } else if (fTopLineIndex > fLastTopLineIndex) {
556 int length = 0;
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;
560 }
561 fStyledText.replaceTextRange(0, length, ""); //$NON-NLS-1$
562 fLastTopLineIndex = fTopLineIndex;
563 fillTextArea();
564 }
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$
570 }
571 }
572 fTextArea.layout();
573 fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
574 }
575
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);
580 }
581 }
582
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);
590 } else {
591 fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_ODD);
592 }
593 }
594
595 private void storeCaretPosition(int time, int caretOffset) {
596 if (fStoredCaretPosition[0].time == time) {
597 fStoredCaretPosition[0].caretOffset = caretOffset;
598 } else {
599 fStoredCaretPosition[1] = fStoredCaretPosition[0];
600 fStoredCaretPosition[0] = new CaretPosition(time, caretOffset);
601 }
602 }
603
604 private int getPreviousCaretOffset(int time) {
605 if (fStoredCaretPosition[0].time == time) {
606 return fStoredCaretPosition[1].caretOffset;
607 } else {
608 return fStoredCaretPosition[0].caretOffset;
609 }
610 }
611
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();
617 }
618 return;
619 }
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();
627 }
628 } else {
629 if (fHighlightedRank != Long.MIN_VALUE) {
630 fHighlightedRank = Long.MIN_VALUE;
631 refreshLineBackgrounds();
632 }
633 }
634 }
635
636 // ------------------------------------------------------------------------
637 // ControlListener (ScrolledComposite)
638 // ------------------------------------------------------------------------
639
640 @Override
641 public void controlResized(ControlEvent event) {
642 int areaHeight = fScrolledComposite.getSize().y;
643 if (fScrolledComposite.getHorizontalBar() != null) {
644 areaHeight -= fScrolledComposite.getHorizontalBar().getSize().y;
645 }
646 int lineHeight = fStyledText.getLineHeight();
647 fNumVisibleLines = Math.max((areaHeight + lineHeight - 1) / lineHeight, 1);
648
649 if (fBottomContext != null) {
650 loadLineData();
651 fillTextArea();
652 }
653 }
654
655 @Override
656 public void controlMoved(ControlEvent e) {
657 }
658
659 // ------------------------------------------------------------------------
660 // SelectionListener (Slider)
661 // ------------------------------------------------------------------------
662
663 @Override
664 public void widgetSelected(SelectionEvent e) {
665 fTextArea.setFocus();
666 if (fLines.size() == 0) {
667 return;
668 }
669 if (e.detail == SWT.DRAG) {
670 return;
671 }
672 fHoldSelection++;
673 switch (e.detail) {
674 case SWT.NONE: {
675 //long rank = (long) (fTrace.getNbEvents() * ((double) fSlider.getSelection() / SLIDER_MAX));
676 //setTopRank(rank);
677 if (fSlider.getSelection() == 0 || fSlider.getThumb() == SLIDER_MAX) {
678 fLines.clear();
679 setTopPosition(0.0);
680 break;
681 }
682 double ratio = (double) fSlider.getSelection() / (SLIDER_MAX - fSlider.getThumb());
683 double delta = Math.pow(10, -15);
684 fLines.clear();
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);
690 }
691 break;
692 }
693 case SWT.ARROW_DOWN: {
694 if (fTopLineIndex >= fLines.size()) {
695 break;
696 }
697 fTopLineIndex++;
698 loadLineData();
699 updateTextArea();
700 break;
701 }
702 case SWT.PAGE_DOWN: {
703 fTopLineIndex += Math.max(fNumVisibleLines - 1, 1);
704 loadLineData();
705 updateTextArea();
706 break;
707 }
708 case SWT.ARROW_UP: {
709 //if (fLines.size() == 0 || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
710 if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
711 break;
712 }
713 fTopLineIndex--;
714 loadLineData();
715 updateTextArea();
716 break;
717 }
718 case SWT.PAGE_UP: {
719 fTopLineIndex -= Math.max(fNumVisibleLines - 1, 1);
720 loadLineData();
721 updateTextArea();
722 break;
723 }
724 case SWT.HOME: {
725 //selectAndReveal(0);
726 setTopPosition(0.0);
727 break;
728 }
729 case SWT.END: {
730 //if (fTrace.getNbEvents() > 0) {
731 //selectAndReveal(fTrace.getNbEvents() - 1);
732 //}
733 double ratio = 1.0;
734 double delta = Math.pow(10, -15);
735 fLines.clear();
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);
741 }
742 break;
743 }
744 }
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)));
748 }
749
750 fHoldSelection = 0;
751 }
752
753 @Override
754 public void widgetDefaultSelected(SelectionEvent e) {
755 }
756
757 // ------------------------------------------------------------------------
758 // KeyListener (StyledText)
759 // ------------------------------------------------------------------------
760
761 @Override
762 public void keyPressed(KeyEvent e) {
763 if (fLines.size() == 0) {
764 return;
765 }
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);
770 switch (e.keyCode) {
771 case SWT.ARROW_DOWN: {
772 if (previousLineAtCaretPosition < (fNumVisibleLines - 2)) {
773 break;
774 }
775 fHoldSelection++;
776 fTopLineIndex++;
777 loadLineData();
778 updateTextArea();
779 fHoldSelection--;
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);
785 }
786 break;
787 }
788 case SWT.PAGE_DOWN: {
789 if (previousLineAtCaretPosition >= (fNumVisibleLines - 1)) {
790 fHoldSelection++;
791 if (fLines.get(fTopLineIndex + previousLineAtCaretPosition).rank % 2 == 0) {
792 fStyledText.setLineBackground(previousLineAtCaretPosition, 1, COLOR_BACKGROUND_EVEN);
793 } else {
794 fStyledText.setLineBackground(previousLineAtCaretPosition, 1, COLOR_BACKGROUND_ODD);
795 }
796 fSelectedLocation = null;
797 fTopLineIndex += Math.max(fNumVisibleLines - 1, 1);
798 loadLineData();
799 updateTextArea();
800 fHoldSelection--;
801 }
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()));
805 break;
806 }
807 case SWT.ARROW_RIGHT: {
808 if (previousCaretOffset < fStyledText.getCharCount() || previousLineAtCaretPosition < (fNumVisibleLines - 2)) {
809 break;
810 }
811 fHoldSelection++;
812 fTopLineIndex++;
813 loadLineData();
814 updateTextArea();
815 fHoldSelection--;
816 fStyledText.setSelection(fStyledText.getCaretOffset() + 1);
817 break;
818 }
819 case SWT.ARROW_UP: {
820 if (previousLineAtCaretPosition > 0) {
821 break;
822 }
823 if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
824 break;
825 }
826 fHoldSelection++;
827 fTopLineIndex--;
828 loadLineData();
829 updateTextArea();
830 fHoldSelection--;
831 LineData lineData = fLines.get(fTopLineIndex);
832 if (!lineData.location.equals(fSelectedLocation)) {
833 fSelectedLocation = lineData.location;
834 refreshLineBackgrounds();
835 sendSelectionEvent(lineData);
836 }
837 fStyledText.setSelection(caretOffset);
838 break;
839 }
840 case SWT.PAGE_UP: {
841 if (previousLineAtCaretPosition > 0) {
842 break;
843 }
844 fHoldSelection++;
845 fTopLineIndex -= Math.max(fNumVisibleLines - 1, 1);
846 loadLineData();
847 updateTextArea();
848 fHoldSelection--;
849 LineData lineData = fLines.get(fTopLineIndex);
850 if (!lineData.location.equals(fSelectedLocation)) {
851 fSelectedLocation = lineData.location;
852 refreshLineBackgrounds();
853 sendSelectionEvent(lineData);
854 }
855 fStyledText.setSelection(caretOffset);
856 break;
857 }
858 case SWT.ARROW_LEFT: {
859 if (previousCaretOffset > 0) {
860 break;
861 }
862 if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
863 break;
864 }
865 long topRank = fLines.get(fTopLineIndex).rank;
866 fHoldSelection++;
867 fTopLineIndex--;
868 loadLineData();
869 updateTextArea();
870 fHoldSelection--;
871 LineData lineData = fLines.get(fTopLineIndex);
872 if (!lineData.location.equals(fSelectedLocation)) {
873 fSelectedLocation = lineData.location;
874 refreshLineBackgrounds();
875 sendSelectionEvent(lineData);
876 }
877 if (topRank != fLines.get(fTopLineIndex).rank) {
878 fStyledText.setSelection(fLines.get(fTopLineIndex).string.length());
879 }
880 break;
881 }
882 case SWT.HOME: {
883 if ((e.stateMask & SWT.CTRL) == 0) {
884 break;
885 }
886 //selectAndReveal(0);
887 setTopPosition(0.0);
888 LineData lineData = fLines.get(fTopLineIndex);
889 if (!lineData.location.equals(fSelectedLocation)) {
890 fSelectedLocation = lineData.location;
891 refreshLineBackgrounds();
892 sendSelectionEvent(lineData);
893 }
894 break;
895 }
896 case SWT.END: {
897 if ((e.stateMask & SWT.CTRL) == 0) {
898 break;
899 }
900 //if (fTrace.getNbEvents() > 0) {
901 //selectAndReveal(fTrace.getNbEvents() - 1);
902 //}
903 double ratio = 1.0;
904 double delta = Math.pow(10, -15);
905 fLines.clear();
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);
911 }
912 LineData lineData = fLines.get(fTopLineIndex);
913 if (!lineData.location.equals(fSelectedLocation)) {
914 fSelectedLocation = lineData.location;
915 refreshLineBackgrounds();
916 sendSelectionEvent(lineData);
917 }
918 break;
919 }
920 }
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)));
924 }
925
926 @Override
927 public void keyReleased(KeyEvent e) {
928 }
929
930 // ------------------------------------------------------------------------
931 // CaretListener (StyledText)
932 // ------------------------------------------------------------------------
933
934 @Override
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);
944 }
945 }
946 }
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) {
952 origin.x = caret.x;
953 } else if (caret.x - origin.x > fScrolledComposite.getSize().x) {
954 origin.x = caret.x - fScrolledComposite.getSize().x + 1;
955 }
956 fScrolledComposite.setOrigin(origin);
957 }
958 }
959
960 // ------------------------------------------------------------------------
961 // MouseMoveListener (StyledText)
962 // ------------------------------------------------------------------------
963
964 @Override
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();
971 }
972 return;
973 }
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();
981 }
982 } else {
983 if (fHighlightedRank != Long.MIN_VALUE) {
984 fHighlightedRank = Long.MIN_VALUE;
985 refreshLineBackgrounds();
986 }
987 }
988 }
989
990 // ------------------------------------------------------------------------
991 // MouseTrackListener (StyledText)
992 // ------------------------------------------------------------------------
993
994 @Override
995 public void mouseExit(MouseEvent e) {
996 fCursorYCoordinate = -1;
997 if (fHighlightedRank != Long.MIN_VALUE) {
998 fHighlightedRank = Long.MIN_VALUE;
999 refreshLineBackgrounds();
1000 }
1001 }
1002
1003 @Override
1004 public void mouseEnter(MouseEvent e) {
1005 fCursorYCoordinate = e.y;
1006 }
1007
1008 @Override
1009 public void mouseHover(MouseEvent e) {
1010 }
1011
1012 // ------------------------------------------------------------------------
1013 // MouseWheelListener (StyledText)
1014 // ------------------------------------------------------------------------
1015
1016 @Override
1017 public void mouseScrolled(MouseEvent e) {
1018 if (fLines.size() == 0) {
1019 return;
1020 }
1021 fHoldSelection++;
1022 fTopLineIndex -= e.count;
1023 loadLineData();
1024 updateTextArea();
1025 fHoldSelection = 0;
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)));
1029 }
1030
1031 }
This page took 0.053586 seconds and 5 git commands to generate.