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