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