Re-structure LTTng sub-project as per the Linux Tools guidelines
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / widgets / TmfRawEventViewer.java
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
6c13869b
FC
17import org.eclipse.linuxtools.tmf.core.event.TmfEvent;\r
18import org.eclipse.linuxtools.tmf.core.trace.ITmfLocation;\r
19import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;\r
20import org.eclipse.linuxtools.tmf.core.trace.TmfContext;\r
c76c54bb
FC
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
d86b9d98
FC
258\r
259 if (!isVisible()) return;\r
260 \r
261 if (fLines.size() == 0) {\r
c76c54bb
FC
262 setTopRank(0);\r
263 } else if (fLines.size() < fNumVisibleLines) {\r
264 fBottomContext = null;\r
265 loadLineData();\r
266 fillTextArea();\r
267 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));\r
268 fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));\r
269 }\r
270 }\r
271 }\r
272 \r
273 public void selectAndReveal(long rank) {\r
274 if (fTrace == null || !isVisible()) {\r
275 return;\r
276 }\r
277 if (fActualRanks && fTopLineIndex < fLines.size() && rank >= fLines.get(fTopLineIndex).rank) {\r
278 int lastVisibleIndex = Math.min(fTopLineIndex + fNumVisibleLines, fLines.size()) - 1;\r
279 if (rank <= fLines.get(lastVisibleIndex).rank) {\r
280 for (int i = fTopLineIndex; i < fLines.size(); i++) {\r
281 if (fLines.get(i).rank == rank) {\r
282 fSelectedLocation = fLines.get(i).location;\r
283 break;\r
284 }\r
285 }\r
286 refreshLineBackgrounds();\r
287 return;\r
288 }\r
289 }\r
290 setTopRank(rank);\r
291 if (fLines.size() > 0 && fHoldSelection == 0) {\r
292 fSelectedLocation = fLines.get(0).location;\r
293 refreshLineBackgrounds();\r
294 }\r
295 }\r
296 \r
297 public void addSelectionListener(SelectionListener listener) {\r
298 checkWidget();\r
299 if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);\r
300 TypedListener typedListener = new TypedListener(listener);\r
301 addListener (SWT.Selection, typedListener);\r
302 }\r
303\r
304 public void removeSelectionListener(SelectionListener listener) {\r
305 checkWidget();\r
306 if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);\r
307 removeListener(SWT.Selection, listener);\r
308 }\r
309\r
310 private void sendSelectionEvent(LineData lineData) {\r
311 Event event = new Event();\r
312 if (fActualRanks) {\r
313 event.data = new Long(lineData.rank);\r
314 } else {\r
315 event.data = lineData.location;\r
316 }\r
317 notifyListeners(SWT.Selection, event);\r
318 }\r
319 \r
320 private void setTopRank(long rank) {\r
321 fBottomContext = fTrace.seekEvent(rank);\r
322 if (fBottomContext == null) {\r
323 return;\r
324 }\r
325 fLines.clear();\r
326 fActualRanks = true;\r
327 fTopLineIndex = 0;\r
328 loadLineData();\r
329 refreshTextArea();\r
330 if (fLines.size() == 0) {\r
331 fSlider.setSelection(0);\r
332 } else {\r
333 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));\r
334 fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));\r
335 }\r
336 }\r
337 \r
338 private void setTopPosition(double ratio) {\r
339 fBottomContext = fTrace.seekLocation(ratio);\r
340 if (fBottomContext == null) {\r
341 return;\r
342 }\r
343 fBottomContext.setRank(0);\r
344 fLines.clear();\r
345 fActualRanks = false;\r
346 fTopLineIndex = 0;\r
347 loadLineData();\r
348 refreshTextArea();\r
349 }\r
350 \r
351 private void loadLineData() {\r
352 if (fTopLineIndex < 0) {\r
353 //if (fLines.size() > 0 && fLines.get(0).rank > 0) {\r
354 //long endRank = fLines.get(0).rank;\r
355 //long startRank = Math.max(0, endRank - fNumVisibleLines);\r
356 //TmfContext context = fTrace.seekEvent(startRank);\r
357 //int index = 0;\r
358 //while (context.getRank() < endRank) {\r
359 //long rank = context.getRank();\r
360 //ITmfLocation<?> location = context.getLocation();\r
361 //TmfEvent event = fTrace.getNextEvent(context);\r
362 //String[] lines = event.getRawText().split("\r?\n");\r
363 //for (int i = 0; i < lines.length; i++) {\r
364 //String line = lines[i];\r
365 //LineData lineData = new LineData(rank, location, line); \r
366 //fLines.add(index++, lineData);\r
367 //fTopLineIndex++;\r
368 //fLastTopLineIndex++;\r
369 //}\r
370 //}\r
371 //}\r
372 if (fLines.size() > 0 && fTrace.getLocationRatio(fLines.get(0).location) > 0) {\r
373 double lastRatio = fTrace.getLocationRatio(fLines.get(fLines.size() - 1).location);\r
374 double firstRatio = fTrace.getLocationRatio(fLines.get(0).location);\r
375 double delta;\r
376 boolean singleEvent = false;\r
377 if (firstRatio != lastRatio) {\r
378 // approximate ratio of at least 20 items\r
379 delta = Math.max(20, fNumVisibleLines) * (lastRatio - firstRatio) / (fLines.size() - 1);\r
380 } else {\r
381 delta = Math.pow(10, -15);\r
382 singleEvent = true;\r
383 }\r
384 while (fTopLineIndex < 0) {\r
385 ITmfLocation<?> endLocation = fLines.get(0).location;\r
386 firstRatio = Math.max(0, firstRatio - delta);\r
387 TmfContext context = fTrace.seekLocation(firstRatio);\r
388 ITmfLocation<?> location = context.getLocation();\r
389 int index = 0;\r
390 long rank = 0;\r
391 while (!context.getLocation().equals(endLocation)) {\r
392 location = context.getLocation();\r
393 TmfEvent event = fTrace.getNextEvent(context);\r
394 if (event == null) {\r
395 break;\r
396 }\r
397 String[] lines = event.getRawText().split("\r?\n"); //$NON-NLS-1$\r
398 for (int i = 0; i < lines.length; i++) {\r
399 String line = lines[i];\r
400 LineData lineData = new LineData(rank, location, line); \r
401 fLines.add(index++, lineData);\r
402 fTopLineIndex++;\r
403 fLastTopLineIndex++;\r
404 }\r
405 rank++;\r
406 }\r
407 long rankOffset = fLines.get(index).rank - rank;\r
408 for (int i = 0; i < index; i++) {\r
409 fLines.get(i).rank += rankOffset;\r
410 }\r
411 if (firstRatio == 0) {\r
412 break;\r
413 }\r
414 if (singleEvent) {\r
415 delta = Math.min(delta * 10, 0.1);\r
416 }\r
417 }\r
418 }\r
419 if (fTopLineIndex < 0) {\r
420 fTopLineIndex = 0;\r
421 }\r
422 }\r
423 \r
424 while (fLines.size() - fTopLineIndex < fNumVisibleLines) {\r
425 if (fBottomContext == null) {\r
426 if (fLines.size() == 0) {\r
427 fBottomContext = fTrace.seekEvent(0);\r
428 } else {\r
429 //fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).rank + 1);\r
430 fBottomContext = fTrace.seekLocation(fLines.get(fLines.size() - 1).location);\r
431 fTrace.getNextEvent(fBottomContext);\r
432 }\r
433 if (fBottomContext == null) {\r
434 break;\r
435 }\r
436 }\r
437 long rank = fBottomContext.getRank();\r
438 ITmfLocation<?> location = fBottomContext.getLocation();\r
439 TmfEvent event = fTrace.getNextEvent(fBottomContext);\r
440 if (event == null) {\r
441 break;\r
442 }\r
443 for (String line : event.getRawText().split("\r?\n")) { //$NON-NLS-1$\r
444 int crPos;\r
445 if ((crPos = line.indexOf('\r')) != -1) {\r
446 line = line.substring(0, crPos);\r
447 }\r
448 LineData lineData = new LineData(rank, location, line); \r
449 fLines.add(lineData);\r
450 }\r
451 }\r
452 fTopLineIndex = Math.max(0, Math.min(fTopLineIndex, fLines.size() - 1));\r
453 \r
454 if (fLines.size() > MAX_LINE_DATA_SIZE) {\r
455 if (fTopLineIndex < MAX_LINE_DATA_SIZE / 2) {\r
456 long rank = fLines.get(MAX_LINE_DATA_SIZE - 1).rank;\r
457 for (int i = MAX_LINE_DATA_SIZE; i < fLines.size(); i++) {\r
458 if (fLines.get(i).rank > rank) {\r
459 fLines.subList(i, fLines.size()).clear();\r
460 fBottomContext = null;\r
461 break;\r
462 }\r
463 }\r
464 } else {\r
465 long rank = fLines.get(fLines.size() - MAX_LINE_DATA_SIZE).rank;\r
466 for (int i = fLines.size() - MAX_LINE_DATA_SIZE - 1; i >= 0; i--) {\r
467 if (fLines.get(i).rank < rank) {\r
468 fLines.subList(0, i + 1).clear();\r
469 fTopLineIndex -= (i + 1);\r
470 fLastTopLineIndex -= (i + 1);\r
471 break;\r
472 }\r
473 }\r
474 }\r
475 }\r
476 }\r
477 \r
478 private void refreshTextArea() {\r
479 fStyledText.setText(""); //$NON-NLS-1$\r
480 for (int i = 0; i < fLines.size() - fTopLineIndex && i < fNumVisibleLines; i++) {\r
481 if (i > 0) fStyledText.append("\n"); //$NON-NLS-1$\r
482 LineData lineData = fLines.get(fTopLineIndex + i);\r
483 fStyledText.append(lineData.string);\r
484 setLineBackground(i, lineData);\r
485 }\r
486 fTextArea.layout();\r
487 fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));\r
488 fLastTopLineIndex = fTopLineIndex;\r
489 }\r
490\r
491 private void fillTextArea() {\r
492 int nextLine = fStyledText.getCharCount() == 0 ? 0 : fStyledText.getLineCount();\r
493 for (int i = nextLine; i < fLines.size() - fTopLineIndex && i < fNumVisibleLines; i++) {\r
494 if (i > 0) fStyledText.append("\n"); //$NON-NLS-1$\r
495 LineData lineData = fLines.get(fTopLineIndex + i);\r
496 fStyledText.append(lineData.string);\r
497 setLineBackground(i, lineData);\r
498 }\r
499 int endLine = Math.min(fNumVisibleLines, fLines.size());\r
500 if (endLine < fStyledText.getLineCount()) {\r
501 int endOffset = fStyledText.getOffsetAtLine(endLine) - 1;\r
502 if (endOffset > fStyledText.getCharCount()) {\r
503 fHoldSelection++;\r
504 fStyledText.replaceTextRange(endOffset, fStyledText.getCharCount() - endOffset, ""); //$NON-NLS-1$\r
505 fHoldSelection--;\r
506 }\r
507 }\r
508 fTextArea.layout();\r
509 fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));\r
510 }\r
511\r
512 private void updateTextArea() {\r
513 if (fTopLineIndex < fLastTopLineIndex) {\r
514 StringBuffer insertedText = new StringBuffer();\r
515 for (int i = fTopLineIndex; i < fLastTopLineIndex; i++) {\r
516 insertedText.append(fLines.get(i).string + "\n"); //$NON-NLS-1$\r
517 }\r
518 fStyledText.replaceTextRange(0, 0, insertedText.toString());\r
519 for (int i = 0; i < fLastTopLineIndex - fTopLineIndex; i++) {\r
520 LineData lineData = fLines.get(fTopLineIndex + i);\r
521 setLineBackground(i, lineData);\r
522 }\r
523 fLastTopLineIndex = fTopLineIndex;\r
524 } else if (fTopLineIndex > fLastTopLineIndex) {\r
525 int length = 0;\r
526 for (int i = 0; i < fTopLineIndex - fLastTopLineIndex && i < fNumVisibleLines; i++) {\r
527 length += fLines.get(i + fLastTopLineIndex).string.length();\r
528 if (i < fStyledText.getLineCount()) length += 1;\r
529 }\r
530 fStyledText.replaceTextRange(0, length, ""); //$NON-NLS-1$\r
531 fLastTopLineIndex = fTopLineIndex;\r
532 fillTextArea();\r
533 }\r
534 int endLine = Math.min(fNumVisibleLines, fLines.size());\r
535 if (endLine < fStyledText.getLineCount()) {\r
536 int endOffset = fStyledText.getOffsetAtLine(endLine) - 1;\r
537 if (endOffset > fStyledText.getCharCount()) {\r
538 fStyledText.replaceTextRange(endOffset, fStyledText.getCharCount() - endOffset, ""); //$NON-NLS-1$\r
539 }\r
540 }\r
541 fTextArea.layout();\r
542 fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));\r
543 }\r
544 \r
545 private void refreshLineBackgrounds() {\r
546 for (int i = 0; (i < fStyledText.getLineCount()) && (i < fNumVisibleLines) && (i < fLines.size() - fTopLineIndex); i++) {\r
547 LineData lineData = fLines.get(fTopLineIndex + i);\r
548 setLineBackground(i, lineData);\r
549 }\r
550 }\r
551\r
552 private void setLineBackground(int index, LineData lineData) {\r
553 if (lineData.location.equals(fSelectedLocation)) {\r
554 fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_SELECTED);\r
555 } else if (lineData.rank == fHighlightedRank) {\r
556 fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_HIGHLIGHTED);\r
557 } else if (lineData.rank % 2 == 0) {\r
558 fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_EVEN);\r
559 } else {\r
560 fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_ODD);\r
561 }\r
562 }\r
563\r
564 private void storeCaretPosition(int time, int caretOffset) {\r
565 if (fStoredCaretPosition[0].time == time) {\r
566 fStoredCaretPosition[0].caretOffset = caretOffset;\r
567 } else {\r
568 fStoredCaretPosition[1] = fStoredCaretPosition[0];\r
569 fStoredCaretPosition[0] = new CaretPosition(time, caretOffset);\r
570 }\r
571 }\r
572 \r
573 private int getPreviousCaretOffset(int time) {\r
574 if (fStoredCaretPosition[0].time == time) {\r
575 return fStoredCaretPosition[1].caretOffset;\r
576 } else {\r
577 return fStoredCaretPosition[0].caretOffset;\r
578 }\r
579 }\r
580\r
581 private void updateHighlightedRank() {\r
582 if (fCursorYCoordinate < 0 || fCursorYCoordinate > fStyledText.getSize().y) {\r
583 if (fHighlightedRank != Long.MIN_VALUE) {\r
584 fHighlightedRank = Long.MIN_VALUE;\r
585 refreshLineBackgrounds();\r
586 }\r
587 return;\r
588 }\r
589 int offset = fStyledText.getOffsetAtLocation(new Point(0, fCursorYCoordinate));\r
590 int line = fStyledText.getLineAtOffset(offset);\r
591 if (line < fLines.size() - fTopLineIndex) {\r
592 LineData lineData = fLines.get(fTopLineIndex + line);\r
593 if (fHighlightedRank != lineData.rank) {\r
594 fHighlightedRank = lineData.rank;\r
595 refreshLineBackgrounds();\r
596 }\r
597 } else {\r
598 if (fHighlightedRank != Long.MIN_VALUE) {\r
599 fHighlightedRank = Long.MIN_VALUE;\r
600 refreshLineBackgrounds();\r
601 }\r
602 }\r
603 }\r
604 \r
605 // ------------------------------------------------------------------------\r
606 // ControlListener (ScrolledComposite)\r
607 // ------------------------------------------------------------------------\r
608 \r
609 @Override\r
610 public void controlResized(ControlEvent event) {\r
611 int areaHeight = fScrolledComposite.getSize().y;\r
612 if (fScrolledComposite.getHorizontalBar() != null) {\r
613 areaHeight -= fScrolledComposite.getHorizontalBar().getSize().y;\r
614 }\r
615 int lineHeight = fStyledText.getLineHeight();\r
616 fNumVisibleLines = Math.max((areaHeight + lineHeight - 1) / lineHeight, 1);\r
617\r
618 if (fBottomContext != null) {\r
619 loadLineData();\r
620 fillTextArea();\r
621 }\r
622 }\r
623\r
624 @Override\r
625 public void controlMoved(ControlEvent e) {\r
626 }\r
627 \r
628 // ------------------------------------------------------------------------\r
629 // SelectionListener (Slider)\r
630 // ------------------------------------------------------------------------\r
631 \r
632 @Override\r
633 public void widgetSelected(SelectionEvent e) {\r
634 fTextArea.setFocus();\r
635 if (fLines.size() == 0) {\r
636 return;\r
637 }\r
638 if (e.detail == SWT.DRAG) {\r
639 return;\r
640 }\r
641 fHoldSelection++;\r
642 switch (e.detail) {\r
643 case SWT.NONE: {\r
644 //long rank = (long) (fTrace.getNbEvents() * ((double) fSlider.getSelection() / SLIDER_MAX));\r
645 //setTopRank(rank);\r
646 if (fSlider.getSelection() == 0 || fSlider.getThumb() == SLIDER_MAX) {\r
647 fLines.clear();\r
648 setTopPosition(0.0);\r
649 break;\r
650 }\r
651 double ratio = (double) fSlider.getSelection() / (SLIDER_MAX - fSlider.getThumb());\r
652 double delta = Math.pow(10, -15);\r
653 fLines.clear();\r
654 while (fLines.size() == 0) {\r
655 setTopPosition(ratio);\r
656 if (ratio == 0.0) break;\r
657 delta = Math.min(delta * 10, 0.1);\r
658 ratio = Math.max(ratio - delta, 0.0);\r
659 }\r
660 break;\r
661 }\r
662 case SWT.ARROW_DOWN: {\r
663 if (fTopLineIndex >= fLines.size()) {\r
664 break;\r
665 }\r
666 fTopLineIndex++;\r
667 loadLineData();\r
668 updateTextArea();\r
669 break;\r
670 }\r
671 case SWT.PAGE_DOWN: {\r
672 fTopLineIndex += Math.max(fNumVisibleLines - 1, 1);\r
673 loadLineData();\r
674 updateTextArea();\r
675 break;\r
676 }\r
677 case SWT.ARROW_UP: {\r
678 //if (fLines.size() == 0 || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {\r
679 if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {\r
680 break;\r
681 }\r
682 fTopLineIndex--;\r
683 loadLineData();\r
684 updateTextArea();\r
685 break;\r
686 }\r
687 case SWT.PAGE_UP: {\r
688 fTopLineIndex -= Math.max(fNumVisibleLines - 1, 1);\r
689 loadLineData();\r
690 updateTextArea();\r
691 break;\r
692 }\r
693 case SWT.HOME: {\r
694 //selectAndReveal(0);\r
695 setTopPosition(0.0);\r
696 break;\r
697 }\r
698 case SWT.END: {\r
699 //if (fTrace.getNbEvents() > 0) {\r
700 //selectAndReveal(fTrace.getNbEvents() - 1);\r
701 //}\r
702 double ratio = 1.0;\r
703 double delta = Math.pow(10, -15);\r
704 fLines.clear();\r
705 while (fLines.size() == 0) {\r
706 setTopPosition(ratio);\r
707 if (ratio == 0.0) break;\r
708 delta = Math.min(delta * 10, 0.1);\r
709 ratio = Math.max(ratio - delta, 0.0);\r
710 }\r
711 break;\r
712 }\r
713 }\r
714 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));\r
715 if (e.detail != SWT.NONE) {\r
716 fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));\r
717 }\r
718 \r
719 fHoldSelection = 0;\r
720 }\r
721\r
722 @Override\r
723 public void widgetDefaultSelected(SelectionEvent e) {\r
724 }\r
725\r
726 // ------------------------------------------------------------------------\r
727 // KeyListener (StyledText)\r
728 // ------------------------------------------------------------------------\r
729 \r
730 @Override\r
731 public void keyPressed(KeyEvent e) {\r
732 if (fLines.size() == 0) {\r
733 return;\r
734 }\r
735 int caretOffset = fStyledText.getCaretOffset();\r
736 int previousCaretOffset = getPreviousCaretOffset(e.time);\r
737 int previousLineAtCaretPosition = fStyledText.getLineAtOffset(previousCaretOffset);\r
738 int previousColumnAtCaretPosition = getPreviousCaretOffset(e.time) - fStyledText.getOffsetAtLine(previousLineAtCaretPosition);\r
739 switch (e.keyCode) {\r
740 case SWT.ARROW_DOWN: {\r
741 if (previousLineAtCaretPosition < (fNumVisibleLines - 2)) {\r
742 break;\r
743 }\r
744 fHoldSelection++;\r
745 fTopLineIndex++;\r
746 loadLineData();\r
747 updateTextArea();\r
748 fHoldSelection--;\r
749 LineData lineData = fLines.get(fTopLineIndex + fStyledText.getLineAtOffset(fStyledText.getCaretOffset()));\r
750 if (!lineData.location.equals(fSelectedLocation)) {\r
751 fSelectedLocation = lineData.location;\r
752 refreshLineBackgrounds();\r
753 sendSelectionEvent(lineData);\r
754 }\r
755 break;\r
756 }\r
757 case SWT.PAGE_DOWN: {\r
758 if (previousLineAtCaretPosition >= (fNumVisibleLines - 1)) {\r
759 fHoldSelection++;\r
760 if (fLines.get(fTopLineIndex + previousLineAtCaretPosition).rank % 2 == 0) {\r
761 fStyledText.setLineBackground(previousLineAtCaretPosition, 1, COLOR_BACKGROUND_EVEN);\r
762 } else {\r
763 fStyledText.setLineBackground(previousLineAtCaretPosition, 1, COLOR_BACKGROUND_ODD);\r
764 }\r
765 fSelectedLocation = null;\r
766 fTopLineIndex += Math.max(fNumVisibleLines - 1, 1);\r
767 loadLineData();\r
768 updateTextArea();\r
769 fHoldSelection--;\r
770 }\r
771 int line = Math.min(fNumVisibleLines - 1, fStyledText.getLineCount() - 1);\r
772 int offset = fStyledText.getOffsetAtLine(line);\r
773 fStyledText.setSelection(offset + Math.min(previousColumnAtCaretPosition, fLines.get(fTopLineIndex + line).string.length()));\r
774 break;\r
775 }\r
776 case SWT.ARROW_RIGHT: {\r
777 if (previousCaretOffset < fStyledText.getCharCount() || previousLineAtCaretPosition < (fNumVisibleLines - 2)) {\r
778 break;\r
779 }\r
780 fHoldSelection++;\r
781 fTopLineIndex++;\r
782 loadLineData();\r
783 updateTextArea();\r
784 fHoldSelection--;\r
785 fStyledText.setSelection(fStyledText.getCaretOffset() + 1);\r
786 break;\r
787 }\r
788 case SWT.ARROW_UP: {\r
789 if (previousLineAtCaretPosition > 0) {\r
790 break;\r
791 }\r
792 if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {\r
793 break;\r
794 }\r
795 fHoldSelection++;\r
796 fTopLineIndex--;\r
797 loadLineData();\r
798 updateTextArea();\r
799 fHoldSelection--;\r
800 LineData lineData = fLines.get(fTopLineIndex);\r
801 if (!lineData.location.equals(fSelectedLocation)) {\r
802 fSelectedLocation = lineData.location;\r
803 refreshLineBackgrounds();\r
804 sendSelectionEvent(lineData);\r
805 }\r
806 fStyledText.setSelection(caretOffset);\r
807 break;\r
808 }\r
809 case SWT.PAGE_UP: {\r
810 if (previousLineAtCaretPosition > 0) {\r
811 break;\r
812 }\r
813 fHoldSelection++;\r
814 fTopLineIndex -= Math.max(fNumVisibleLines - 1, 1);\r
815 loadLineData();\r
816 updateTextArea();\r
817 fHoldSelection--;\r
818 LineData lineData = fLines.get(fTopLineIndex);\r
819 if (!lineData.location.equals(fSelectedLocation)) {\r
820 fSelectedLocation = lineData.location;\r
821 refreshLineBackgrounds();\r
822 sendSelectionEvent(lineData);\r
823 }\r
824 fStyledText.setSelection(caretOffset);\r
825 break;\r
826 }\r
827 case SWT.ARROW_LEFT: {\r
828 if (previousCaretOffset > 0) {\r
829 break;\r
830 }\r
831 if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {\r
832 break;\r
833 }\r
834 long topRank = fLines.get(fTopLineIndex).rank;\r
835 fHoldSelection++;\r
836 fTopLineIndex--;\r
837 loadLineData();\r
838 updateTextArea();\r
839 fHoldSelection--;\r
840 LineData lineData = fLines.get(fTopLineIndex);\r
841 if (!lineData.location.equals(fSelectedLocation)) {\r
842 fSelectedLocation = lineData.location;\r
843 refreshLineBackgrounds();\r
844 sendSelectionEvent(lineData);\r
845 }\r
846 if (topRank != fLines.get(fTopLineIndex).rank) {\r
847 fStyledText.setSelection(fLines.get(fTopLineIndex).string.length());\r
848 }\r
849 break;\r
850 }\r
851 case SWT.HOME: {\r
852 if ((e.stateMask & SWT.CTRL) == 0) {\r
853 break;\r
854 }\r
855 //selectAndReveal(0);\r
856 setTopPosition(0.0);\r
857 LineData lineData = fLines.get(fTopLineIndex);\r
858 if (!lineData.location.equals(fSelectedLocation)) {\r
859 fSelectedLocation = lineData.location;\r
860 refreshLineBackgrounds();\r
861 sendSelectionEvent(lineData);\r
862 }\r
863 break;\r
864 }\r
865 case SWT.END: {\r
866 if ((e.stateMask & SWT.CTRL) == 0) {\r
867 break;\r
868 }\r
869 //if (fTrace.getNbEvents() > 0) {\r
870 //selectAndReveal(fTrace.getNbEvents() - 1);\r
871 //}\r
872 double ratio = 1.0;\r
873 double delta = Math.pow(10, -15);\r
874 fLines.clear();\r
875 while (fLines.size() == 0) {\r
876 setTopPosition(ratio);\r
877 if (ratio == 0.0) break;\r
878 delta = Math.min(delta * 10, 0.1);\r
879 ratio = Math.max(ratio - delta, 0.0);\r
880 }\r
881 LineData lineData = fLines.get(fTopLineIndex);\r
882 if (!lineData.location.equals(fSelectedLocation)) {\r
883 fSelectedLocation = lineData.location;\r
884 refreshLineBackgrounds();\r
885 sendSelectionEvent(lineData);\r
886 }\r
887 break;\r
888 }\r
889 }\r
890 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));\r
891 updateHighlightedRank();\r
892 fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));\r
893 }\r
894\r
895 @Override\r
896 public void keyReleased(KeyEvent e) {\r
897 }\r
898\r
899 // ------------------------------------------------------------------------\r
900 // CaretListener (StyledText)\r
901 // ------------------------------------------------------------------------\r
902 \r
903 @Override\r
904 public void caretMoved(CaretEvent event) {\r
905 if (fHoldSelection == 0) {\r
906 int line = fStyledText.getLineAtOffset(event.caretOffset);\r
907 if (fTopLineIndex + line < fLines.size()) {\r
908 LineData lineData = fLines.get(fTopLineIndex + line);\r
909 if (!lineData.location.equals(fSelectedLocation)) {\r
910 fSelectedLocation = lineData.location;\r
911 refreshLineBackgrounds();\r
912 sendSelectionEvent(lineData);\r
913 }\r
914 }\r
915 }\r
916 storeCaretPosition(event.time, event.caretOffset);\r
917 if (fHoldSelection == 0) {\r
918 Point caret = fStyledText.getLocationAtOffset(fStyledText.getCaretOffset());\r
919 Point origin = fScrolledComposite.getOrigin();\r
920 if (origin.x > caret.x) {\r
921 origin.x = caret.x;\r
922 } else if (caret.x - origin.x > fScrolledComposite.getSize().x) {\r
923 origin.x = caret.x - fScrolledComposite.getSize().x + 1;\r
924 }\r
925 fScrolledComposite.setOrigin(origin);\r
926 }\r
927 }\r
928\r
929 // ------------------------------------------------------------------------\r
930 // MouseMoveListener (StyledText)\r
931 // ------------------------------------------------------------------------\r
932 \r
933 @Override\r
934 public void mouseMove(MouseEvent e) {\r
935 fCursorYCoordinate = e.y;\r
936 if (e.y < 0 || e.y > fStyledText.getSize().y) {\r
937 if (fHighlightedRank != Long.MIN_VALUE) {\r
938 fHighlightedRank = Long.MIN_VALUE;\r
939 refreshLineBackgrounds();\r
940 }\r
941 return;\r
942 }\r
943 int offset = fStyledText.getOffsetAtLocation(new Point(0, e.y));\r
944 int line = fStyledText.getLineAtOffset(offset);\r
945 if (line < fLines.size() - fTopLineIndex) {\r
946 LineData lineData = fLines.get(fTopLineIndex + line);\r
947 if (fHighlightedRank != lineData.rank) {\r
948 fHighlightedRank = lineData.rank;\r
949 refreshLineBackgrounds();\r
950 }\r
951 } else {\r
952 if (fHighlightedRank != Long.MIN_VALUE) {\r
953 fHighlightedRank = Long.MIN_VALUE;\r
954 refreshLineBackgrounds();\r
955 }\r
956 }\r
957 }\r
958\r
959 // ------------------------------------------------------------------------\r
960 // MouseTrackListener (StyledText)\r
961 // ------------------------------------------------------------------------\r
962 \r
963 @Override\r
964 public void mouseExit(MouseEvent e) {\r
965 fCursorYCoordinate = -1;\r
966 if (fHighlightedRank != Long.MIN_VALUE) {\r
967 fHighlightedRank = Long.MIN_VALUE;\r
968 refreshLineBackgrounds();\r
969 }\r
970 }\r
971\r
972 @Override\r
973 public void mouseEnter(MouseEvent e) {\r
974 fCursorYCoordinate = e.y;\r
975 }\r
976\r
977 @Override\r
978 public void mouseHover(MouseEvent e) {\r
979 }\r
980\r
981 // ------------------------------------------------------------------------\r
982 // MouseWheelListener (StyledText)\r
983 // ------------------------------------------------------------------------\r
984 \r
985 @Override\r
986 public void mouseScrolled(MouseEvent e) {\r
987 if (fLines.size() == 0) {\r
988 return;\r
989 }\r
990 fHoldSelection++;\r
991 fTopLineIndex -= e.count;\r
992 loadLineData();\r
993 updateTextArea();\r
994 fHoldSelection = 0;\r
995 //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));\r
996 updateHighlightedRank();\r
997 fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));\r
998 }\r
999 \r
1000}\r
This page took 0.0993 seconds and 5 git commands to generate.