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