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