-/*******************************************************************************
- * Copyright (c) 2010, 2012 Ericsson
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Patrick Tasse - Initial API and implementation
- ******************************************************************************/
-
-package org.eclipse.linuxtools.tmf.ui.widgets.rawviewer;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
-import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
-import org.eclipse.linuxtools.tmf.core.trace.ITmfLocation;
-import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.CaretEvent;
-import org.eclipse.swt.custom.CaretListener;
-import org.eclipse.swt.custom.ScrolledComposite;
-import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.ControlListener;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.KeyListener;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseMoveListener;
-import org.eclipse.swt.events.MouseTrackListener;
-import org.eclipse.swt.events.MouseWheelListener;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.Slider;
-
-/**
- * TmfRawEventViewer allows for the display of the raw data for an arbitrarily
- * large number of TMF events.
- *
- * It is essentially a Composite of a StyledText area and a Slider, where the number
- * of visible lines in the StyledText control is set to fill the viewer display area.
- * An underlying data model is used to store a cache of event raw text line data.
- * The slider is ratio-based.
- *
- * @version 1.0
- * @author Patrick Tasse
- */
-public class TmfRawEventViewer extends Composite implements ControlListener, SelectionListener, KeyListener, CaretListener, MouseMoveListener, MouseTrackListener, MouseWheelListener {
-
- private static final Color COLOR_BACKGROUND_ODD = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);
- private static final Color COLOR_BACKGROUND_EVEN = new Color(Display.getDefault(), 242, 242, 242);
- private static final Color COLOR_BACKGROUND_SELECTED = new Color(Display.getDefault(), 231, 246, 254);
- private static final Color COLOR_BACKGROUND_HIGHLIGHTED = new Color(Display.getDefault(), 246, 252, 255);
- private static final int MAX_LINE_DATA_SIZE = 1000;
- private static final int SLIDER_MAX = 1000000;
-
- private ITmfTrace fTrace;
- private ITmfContext fBottomContext;
-
- private ScrolledComposite fScrolledComposite;
- private Composite fTextArea;
- private StyledText fStyledText;
- private Font fFixedFont;
- private Slider fSlider;
-
- private final List<LineData> fLines = new ArrayList<LineData>();
- private boolean fActualRanks = false;
- private int fTopLineIndex;
- private int fLastTopLineIndex;
- private final CaretPosition[] fStoredCaretPosition = new CaretPosition[]
- { new CaretPosition(0, 0), new CaretPosition(0,0)};
- private int fNumVisibleLines;
- private ITmfLocation fSelectedLocation = null;
- private long fHighlightedRank = Long.MIN_VALUE;
- private int fCursorYCoordinate = -1;
- private int fHoldSelection = 0;
-
- private static class LineData {
- long rank;
- ITmfLocation location;
- String string;
- public LineData(long rank, ITmfLocation location, String string) {
- this.rank = rank;
- this.location = location;
- if (string.length() == 0) {
- this.string = " "; // workaround for setLineBackground has no effect on empty line //$NON-NLS-1$
- } else {
- this.string = string;
- }
- }
- @Override
- public String toString() {
- return rank + " [" + location + "]: " + string; //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
-
- private static class CaretPosition {
- int time;
- int caretOffset;
- public CaretPosition(int time, int caretOffset) {
- this.time = time;
- this.caretOffset = caretOffset;
- }
- }
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructor
- * @param parent The parent composite
- * @param style The style bits
- */
- public TmfRawEventViewer(Composite parent, int style) {
- super(parent, style & (~SWT.H_SCROLL) & (~SWT.V_SCROLL));
-
- // Set the layout
- GridLayout gridLayout = new GridLayout();
- gridLayout.numColumns = 2;
- gridLayout.horizontalSpacing = 0;
- gridLayout.verticalSpacing = 0;
- gridLayout.marginWidth = 0;
- gridLayout.marginHeight = 0;
- setLayout(gridLayout);
-
- // Create the controls
- createTextArea(style & SWT.H_SCROLL);
- createSlider(style & SWT.V_SCROLL);
-
- // Prevent the slider from being traversed
- setTabList(new Control[] { fScrolledComposite });
- }
-
- @Override
- public void dispose() {
- if (fFixedFont != null) {
- fFixedFont.dispose();
- fFixedFont = null;
- }
- super.dispose();
- }
-
- // ------------------------------------------------------------------------
- // Text area handling
- // ------------------------------------------------------------------------
-
- /**
- * Create the text area and add listeners
- */
- private void createTextArea(int style) {
- fScrolledComposite = new ScrolledComposite(this, style);
- fScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- fTextArea = new Composite(fScrolledComposite, SWT.NONE);
- fTextArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- fScrolledComposite.setContent(fTextArea);
- fScrolledComposite.setExpandHorizontal(true);
- fScrolledComposite.setExpandVertical(true);
- fScrolledComposite.setAlwaysShowScrollBars(true);
- fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
- fScrolledComposite.addControlListener(this);
-
- GridLayout textAreaGridLayout = new GridLayout();
- textAreaGridLayout.marginHeight = 0;
- textAreaGridLayout.marginWidth = 0;
- fTextArea.setLayout(textAreaGridLayout);
-
- if (fFixedFont == null) {
- if (System.getProperty("os.name").contains("Windows")) { //$NON-NLS-1$ //$NON-NLS-2$
- fFixedFont = new Font(Display.getCurrent(), new FontData("Courier New", 10, SWT.NORMAL)); //$NON-NLS-1$
- } else {
- fFixedFont = new Font(Display.getCurrent(), new FontData("Monospace", 10, SWT.NORMAL)); //$NON-NLS-1$
- }
- }
-
- fStyledText = new StyledText(fTextArea, SWT.READ_ONLY);
- fStyledText.setFont(fFixedFont);
- fStyledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-
- fStyledText.addCaretListener(this);
- fStyledText.addMouseMoveListener(this);
- fStyledText.addMouseTrackListener(this);
- fStyledText.addMouseWheelListener(this);
- fStyledText.addListener(SWT.MouseWheel, new Listener() { // disable mouse scroll of horizontal scroll bar
- @Override
- public void handleEvent(Event event) { event.doit = false; }});
- fStyledText.addKeyListener(this);
-
- fTextArea.setBackground(fStyledText.getBackground());
- fTextArea.addMouseListener(new MouseAdapter() {
- @Override
- public void mouseDown(MouseEvent e) {
- fTextArea.setFocus();
- }});
- }
-
- // ------------------------------------------------------------------------
- // Slider handling
- // ------------------------------------------------------------------------
-
- private void createSlider(int style) {
- fSlider = new Slider(this, SWT.VERTICAL);
- fSlider.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
- fSlider.setValues(0, 0, SLIDER_MAX, SLIDER_MAX, 1, 1);
- fSlider.addSelectionListener(this);
- if ((style & SWT.V_SCROLL) == 0) {
- fSlider.setVisible(false);
- }
- }
-
- // ------------------------------------------------------------------------
- // Controls interactions
- // ------------------------------------------------------------------------
-
- @Override
- public boolean setFocus() {
- boolean isVisible = isVisible();
- if (isVisible) {
- fTextArea.setFocus();
- }
- return isVisible;
- }
-
- @Override
- public void setMenu(Menu menu) {
- fStyledText.setMenu(menu);
- }
-
- /**
- * Sets the trace and updates the content
- * @param trace The trace to set
- */
- public void setTrace(ITmfTrace trace) {
- fTrace = trace;
- fTopLineIndex = 0;
- fLines.clear();
- refreshEventCount();
- }
-
- /**
- * Refreshes the event count, updates the slider thumb and loads display
- */
- public void refreshEventCount() {
- if (fTrace != null) {
- if (fTrace.getNbEvents() > 0) {
- fSlider.setThumb((int) Math.max(SLIDER_MAX / fTrace.getNbEvents(), 1));
- } else {
- fSlider.setThumb(SLIDER_MAX);
- }
-
- if (!isVisible()) {
- return;
- }
-
- if (fLines.size() == 0) {
- setTopRank(0);
- } else if (fLines.size() < fNumVisibleLines) {
- fBottomContext = null;
- loadLineData();
- fillTextArea();
- //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
- fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));
- }
- } else {
- fBottomContext = null;
- fillTextArea();
- fSlider.setThumb(SLIDER_MAX);
- fSlider.setSelection(0);
- }
- }
-
- /**
- * Selects the event of given rank and makes it visible.
- * @param rank The rank of event
- */
- public void selectAndReveal(long rank) {
- if (fTrace == null || !isVisible()) {
- return;
- }
- if (fActualRanks && fTopLineIndex < fLines.size() && rank >= fLines.get(fTopLineIndex).rank) {
- int lastVisibleIndex = Math.min(fTopLineIndex + fNumVisibleLines, fLines.size()) - 1;
- if (rank <= fLines.get(lastVisibleIndex).rank) {
- for (int i = fTopLineIndex; i < fLines.size(); i++) {
- if (fLines.get(i).rank == rank) {
- fSelectedLocation = fLines.get(i).location;
- break;
- }
- }
- refreshLineBackgrounds();
- return;
- }
- }
- setTopRank(rank);
- if (fLines.size() > 0 && fHoldSelection == 0) {
- fSelectedLocation = fLines.get(0).location;
- refreshLineBackgrounds();
- }
- }
-
- /**
- * Add a selection listener
- * @param listener A listener to add
- */
- public void addSelectionListener(Listener listener) {
- checkWidget();
- if (listener == null) {
- SWT.error (SWT.ERROR_NULL_ARGUMENT);
- }
- addListener (SWT.Selection, listener);
- }
-
- /**
- * Remove selection listener
- * @param listener A listener to remove
- */
- public void removeSelectionListener(Listener listener) {
- checkWidget();
- if (listener == null) {
- SWT.error (SWT.ERROR_NULL_ARGUMENT);
- }
- removeListener(SWT.Selection, listener);
- }
-
- private void sendSelectionEvent(LineData lineData) {
- Event event = new Event();
- if (fActualRanks) {
- event.data = Long.valueOf(lineData.rank);
- } else {
- event.data = lineData.location;
- }
- notifyListeners(SWT.Selection, event);
- }
-
- private void setTopRank(long rank) {
- fBottomContext = fTrace.seekEvent(rank);
- if (fBottomContext == null) {
- return;
- }
- fLines.clear();
- fActualRanks = true;
- fTopLineIndex = 0;
- loadLineData();
- refreshTextArea();
- if (fLines.size() == 0) {
- fSlider.setSelection(0);
- } else {
- //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
- fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));
- }
- }
-
- private void setTopPosition(double ratio) {
- fBottomContext = fTrace.seekEvent(ratio);
- if (fBottomContext == null) {
- return;
- }
- fBottomContext.setRank(0);
- fLines.clear();
- fActualRanks = false;
- fTopLineIndex = 0;
- loadLineData();
- refreshTextArea();
- }
-
- private void loadLineData() {
- if (fTopLineIndex < 0) {
- //if (fLines.size() > 0 && fLines.get(0).rank > 0) {
- //long endRank = fLines.get(0).rank;
- //long startRank = Math.max(0, endRank - fNumVisibleLines);
- //TmfContext context = fTrace.seekEvent(startRank);
- //int index = 0;
- //while (context.getRank() < endRank) {
- //long rank = context.getRank();
- //ITmfLocation<?> location = context.getLocation();
- //TmfEvent event = fTrace.getNextEvent(context);
- //String[] lines = event.getRawText().split("\r?\n");
- //for (int i = 0; i < lines.length; i++) {
- //String line = lines[i];
- //LineData lineData = new LineData(rank, location, line);
- //fLines.add(index++, lineData);
- //fTopLineIndex++;
- //fLastTopLineIndex++;
- //}
- //}
- //}
- if (fLines.size() > 0 && fTrace.getLocationRatio(fLines.get(0).location) > 0) {
- double lastRatio = fTrace.getLocationRatio(fLines.get(fLines.size() - 1).location);
- double firstRatio = fTrace.getLocationRatio(fLines.get(0).location);
- double delta;
- boolean singleEvent = false;
- if (firstRatio != lastRatio) {
- // approximate ratio of at least 20 items
- delta = Math.max(20, fNumVisibleLines) * (lastRatio - firstRatio) / (fLines.size() - 1);
- } else {
- delta = Math.pow(10, -15);
- singleEvent = true;
- }
- while (fTopLineIndex < 0) {
- ITmfLocation endLocation = fLines.get(0).location;
- firstRatio = Math.max(0, firstRatio - delta);
- ITmfContext context = fTrace.seekEvent(firstRatio);
- ITmfLocation location;
- int index = 0;
- long rank = 0;
- while (!context.getLocation().equals(endLocation)) {
- location = context.getLocation().clone();
- ITmfEvent event = fTrace.getNext(context);
- if (event == null) {
- break;
- }
- if (event.getContent() != null && event.getContent().getValue() != null) {
- String[] lines = event.getContent().getValue().toString().split("\r?\n"); //$NON-NLS-1$
- for (int i = 0; i < lines.length; i++) {
- String line = lines[i];
- LineData lineData = new LineData(rank, location, line);
- fLines.add(index++, lineData);
- fTopLineIndex++;
- fLastTopLineIndex++;
- }
- } else {
- LineData lineData = new LineData(rank, location, ""); //$NON-NLS-1$
- fLines.add(index++, lineData);
- fTopLineIndex++;
- fLastTopLineIndex++;
- }
- rank++;
- }
- long rankOffset = fLines.get(index).rank - rank;
- for (int i = 0; i < index; i++) {
- fLines.get(i).rank += rankOffset;
- }
- if (firstRatio == 0) {
- break;
- }
- if (singleEvent) {
- delta = Math.min(delta * 10, 0.1);
- }
- }
- }
- if (fTopLineIndex < 0) {
- fTopLineIndex = 0;
- }
- }
-
- while (fLines.size() - fTopLineIndex < fNumVisibleLines) {
- if (fBottomContext == null) {
- if (fLines.size() == 0) {
- fBottomContext = fTrace.seekEvent(0);
- } else {
- //fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).rank + 1);
- fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).location);
- fTrace.getNext(fBottomContext);
- }
- if (fBottomContext == null) {
- break;
- }
- }
- long rank = fBottomContext.getRank();
- ITmfLocation location = fBottomContext.getLocation() != null ? fBottomContext.getLocation().clone() : null;
- ITmfEvent event = fTrace.getNext(fBottomContext);
- if (event == null) {
- break;
- }
- if (event.getContent() != null && event.getContent().getValue() != null) {
- for (String line : event.getContent().getValue().toString().split("\r?\n")) { //$NON-NLS-1$
- int crPos;
- if ((crPos = line.indexOf('\r')) != -1) {
- line = line.substring(0, crPos);
- }
- LineData lineData = new LineData(rank, location, line);
- fLines.add(lineData);
- }
- } else {
- LineData lineData = new LineData(rank, location, ""); //$NON-NLS-1$
- fLines.add(lineData);
- }
- }
- fTopLineIndex = Math.max(0, Math.min(fTopLineIndex, fLines.size() - 1));
-
- if (fLines.size() > MAX_LINE_DATA_SIZE) {
- if (fTopLineIndex < MAX_LINE_DATA_SIZE / 2) {
- long rank = fLines.get(MAX_LINE_DATA_SIZE - 1).rank;
- for (int i = MAX_LINE_DATA_SIZE; i < fLines.size(); i++) {
- if (fLines.get(i).rank > rank) {
- fLines.subList(i, fLines.size()).clear();
- fBottomContext = null;
- break;
- }
- }
- } else {
- long rank = fLines.get(fLines.size() - MAX_LINE_DATA_SIZE).rank;
- for (int i = fLines.size() - MAX_LINE_DATA_SIZE - 1; i >= 0; i--) {
- if (fLines.get(i).rank < rank) {
- fLines.subList(0, i + 1).clear();
- fTopLineIndex -= (i + 1);
- fLastTopLineIndex -= (i + 1);
- break;
- }
- }
- }
- }
- }
-
- private void refreshTextArea() {
- fStyledText.setText(""); //$NON-NLS-1$
- for (int i = 0; i < fLines.size() - fTopLineIndex && i < fNumVisibleLines; i++) {
- if (i > 0)
- {
- fStyledText.append("\n"); //$NON-NLS-1$
- }
- LineData lineData = fLines.get(fTopLineIndex + i);
- fStyledText.append(lineData.string);
- setLineBackground(i, lineData);
- }
- fTextArea.layout();
- fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
- fLastTopLineIndex = fTopLineIndex;
- }
-
- private void fillTextArea() {
- int nextLine = fStyledText.getCharCount() == 0 ? 0 : fStyledText.getLineCount();
- for (int i = nextLine; i < fLines.size() - fTopLineIndex && i < fNumVisibleLines; i++) {
- if (i > 0)
- {
- fStyledText.append("\n"); //$NON-NLS-1$
- }
- LineData lineData = fLines.get(fTopLineIndex + i);
- fStyledText.append(lineData.string);
- setLineBackground(i, lineData);
- }
- int endLine = Math.min(fNumVisibleLines, fLines.size());
- if (endLine < fStyledText.getLineCount()) {
- int endOffset = fStyledText.getOffsetAtLine(endLine) - 1;
- if (endOffset > fStyledText.getCharCount()) {
- fHoldSelection++;
- fStyledText.replaceTextRange(endOffset, fStyledText.getCharCount() - endOffset, ""); //$NON-NLS-1$
- fHoldSelection--;
- }
- }
- fTextArea.layout();
- fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
- }
-
- private void updateTextArea() {
- if (fTopLineIndex < fLastTopLineIndex) {
- StringBuffer insertedText = new StringBuffer();
- for (int i = fTopLineIndex; i < fLastTopLineIndex; i++) {
- insertedText.append(fLines.get(i).string + "\n"); //$NON-NLS-1$
- }
- fStyledText.replaceTextRange(0, 0, insertedText.toString());
- for (int i = 0; i < fLastTopLineIndex - fTopLineIndex; i++) {
- LineData lineData = fLines.get(fTopLineIndex + i);
- setLineBackground(i, lineData);
- }
- fLastTopLineIndex = fTopLineIndex;
- } else if (fTopLineIndex > fLastTopLineIndex) {
- int length = 0;
- for (int i = 0; i < fTopLineIndex - fLastTopLineIndex && i < fNumVisibleLines; i++) {
- length += fLines.get(i + fLastTopLineIndex).string.length();
- if (i < fStyledText.getLineCount()) {
- length += 1;
- }
- }
- fStyledText.replaceTextRange(0, length, ""); //$NON-NLS-1$
- fLastTopLineIndex = fTopLineIndex;
- fillTextArea();
- }
- int endLine = Math.min(fNumVisibleLines, fLines.size());
- if (endLine < fStyledText.getLineCount()) {
- int endOffset = fStyledText.getOffsetAtLine(endLine) - 1;
- if (endOffset > fStyledText.getCharCount()) {
- fStyledText.replaceTextRange(endOffset, fStyledText.getCharCount() - endOffset, ""); //$NON-NLS-1$
- }
- }
- fTextArea.layout();
- fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));
- }
-
- private void refreshLineBackgrounds() {
- for (int i = 0; (i < fStyledText.getLineCount()) && (i < fNumVisibleLines) && (i < fLines.size() - fTopLineIndex); i++) {
- LineData lineData = fLines.get(fTopLineIndex + i);
- setLineBackground(i, lineData);
- }
- }
-
- private void setLineBackground(int index, LineData lineData) {
- if (lineData.location.equals(fSelectedLocation)) {
- fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_SELECTED);
- } else if (lineData.rank == fHighlightedRank) {
- fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_HIGHLIGHTED);
- } else if (lineData.rank % 2 == 0) {
- fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_EVEN);
- } else {
- fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_ODD);
- }
- }
-
- private void storeCaretPosition(int time, int caretOffset) {
- if (fStoredCaretPosition[0].time == time) {
- fStoredCaretPosition[0].caretOffset = caretOffset;
- } else {
- fStoredCaretPosition[1] = fStoredCaretPosition[0];
- fStoredCaretPosition[0] = new CaretPosition(time, caretOffset);
- }
- }
-
- private int getPreviousCaretOffset(int time) {
- if (fStoredCaretPosition[0].time == time) {
- return fStoredCaretPosition[1].caretOffset;
- }
- return fStoredCaretPosition[0].caretOffset;
- }
-
- private void updateHighlightedRank() {
- if (fCursorYCoordinate < 0 || fCursorYCoordinate > fStyledText.getSize().y) {
- if (fHighlightedRank != Long.MIN_VALUE) {
- fHighlightedRank = Long.MIN_VALUE;
- refreshLineBackgrounds();
- }
- return;
- }
- int offset = fStyledText.getOffsetAtLocation(new Point(0, fCursorYCoordinate));
- int line = fStyledText.getLineAtOffset(offset);
- if (line < fLines.size() - fTopLineIndex) {
- LineData lineData = fLines.get(fTopLineIndex + line);
- if (fHighlightedRank != lineData.rank) {
- fHighlightedRank = lineData.rank;
- refreshLineBackgrounds();
- }
- } else {
- if (fHighlightedRank != Long.MIN_VALUE) {
- fHighlightedRank = Long.MIN_VALUE;
- refreshLineBackgrounds();
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // ControlListener (ScrolledComposite)
- // ------------------------------------------------------------------------
-
- @Override
- public void controlResized(ControlEvent event) {
- int areaHeight = fScrolledComposite.getSize().y;
- if (fScrolledComposite.getHorizontalBar() != null) {
- areaHeight -= fScrolledComposite.getHorizontalBar().getSize().y;
- }
- int lineHeight = fStyledText.getLineHeight();
- fNumVisibleLines = Math.max((areaHeight + lineHeight - 1) / lineHeight, 1);
-
- if (fBottomContext != null) {
- loadLineData();
- fillTextArea();
- }
- }
-
- @Override
- public void controlMoved(ControlEvent e) {
- }
-
- // ------------------------------------------------------------------------
- // SelectionListener (Slider)
- // ------------------------------------------------------------------------
-
- @Override
- public void widgetSelected(SelectionEvent e) {
- fTextArea.setFocus();
- if (fLines.size() == 0) {
- return;
- }
- if (e.detail == SWT.DRAG) {
- return;
- }
- fHoldSelection++;
- switch (e.detail) {
- case SWT.NONE: {
- //long rank = (long) (fTrace.getNbEvents() * ((double) fSlider.getSelection() / SLIDER_MAX));
- //setTopRank(rank);
- if (fSlider.getSelection() == 0 || fSlider.getThumb() == SLIDER_MAX) {
- fLines.clear();
- setTopPosition(0.0);
- break;
- }
- double ratio = (double) fSlider.getSelection() / (SLIDER_MAX - fSlider.getThumb());
- double delta = Math.pow(10, -15);
- fLines.clear();
- while (fLines.size() == 0) {
- setTopPosition(ratio);
- if (ratio == 0.0) {
- break;
- }
- delta = Math.min(delta * 10, 0.1);
- ratio = Math.max(ratio - delta, 0.0);
- }
- break;
- }
- case SWT.ARROW_DOWN: {
- if (fTopLineIndex >= fLines.size()) {
- break;
- }
- fTopLineIndex++;
- loadLineData();
- updateTextArea();
- break;
- }
- case SWT.PAGE_DOWN: {
- fTopLineIndex += Math.max(fNumVisibleLines - 1, 1);
- loadLineData();
- updateTextArea();
- break;
- }
- case SWT.ARROW_UP: {
- //if (fLines.size() == 0 || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
- if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
- break;
- }
- fTopLineIndex--;
- loadLineData();
- updateTextArea();
- break;
- }
- case SWT.PAGE_UP: {
- fTopLineIndex -= Math.max(fNumVisibleLines - 1, 1);
- loadLineData();
- updateTextArea();
- break;
- }
- case SWT.HOME: {
- //selectAndReveal(0);
- setTopPosition(0.0);
- break;
- }
- case SWT.END: {
- //if (fTrace.getNbEvents() > 0) {
- //selectAndReveal(fTrace.getNbEvents() - 1);
- //}
- double ratio = 1.0;
- double delta = Math.pow(10, -15);
- fLines.clear();
- while (fLines.size() == 0) {
- setTopPosition(ratio);
- if (ratio == 0.0) {
- break;
- }
- delta = Math.min(delta * 10, 0.1);
- ratio = Math.max(ratio - delta, 0.0);
- }
- break;
- }
- default:
- break;
- }
- //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
- if (e.detail != SWT.NONE) {
- fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));
- }
-
- fHoldSelection = 0;
- }
-
- @Override
- public void widgetDefaultSelected(SelectionEvent e) {
- }
-
- // ------------------------------------------------------------------------
- // KeyListener (StyledText)
- // ------------------------------------------------------------------------
-
- @Override
- public void keyPressed(KeyEvent e) {
- if (fLines.size() == 0) {
- return;
- }
- int caretOffset = fStyledText.getCaretOffset();
- int previousCaretOffset = getPreviousCaretOffset(e.time);
- int previousLineAtCaretPosition = fStyledText.getLineAtOffset(previousCaretOffset);
- int previousColumnAtCaretPosition = getPreviousCaretOffset(e.time) - fStyledText.getOffsetAtLine(previousLineAtCaretPosition);
- switch (e.keyCode) {
- case SWT.ARROW_DOWN: {
- if (previousLineAtCaretPosition < (fNumVisibleLines - 2)) {
- break;
- }
- fHoldSelection++;
- fTopLineIndex++;
- loadLineData();
- updateTextArea();
- fHoldSelection--;
- LineData lineData = fLines.get(fTopLineIndex + fStyledText.getLineAtOffset(fStyledText.getCaretOffset()));
- if (!lineData.location.equals(fSelectedLocation)) {
- fSelectedLocation = lineData.location;
- refreshLineBackgrounds();
- sendSelectionEvent(lineData);
- }
- break;
- }
- case SWT.PAGE_DOWN: {
- if (previousLineAtCaretPosition >= (fNumVisibleLines - 1)) {
- fHoldSelection++;
- if (fLines.get(fTopLineIndex + previousLineAtCaretPosition).rank % 2 == 0) {
- fStyledText.setLineBackground(previousLineAtCaretPosition, 1, COLOR_BACKGROUND_EVEN);
- } else {
- fStyledText.setLineBackground(previousLineAtCaretPosition, 1, COLOR_BACKGROUND_ODD);
- }
- fSelectedLocation = null;
- fTopLineIndex += Math.max(fNumVisibleLines - 1, 1);
- loadLineData();
- updateTextArea();
- fHoldSelection--;
- }
- int line = Math.min(fNumVisibleLines - 1, fStyledText.getLineCount() - 1);
- int offset = fStyledText.getOffsetAtLine(line);
- fStyledText.setSelection(offset + Math.min(previousColumnAtCaretPosition, fLines.get(fTopLineIndex + line).string.length()));
- break;
- }
- case SWT.ARROW_RIGHT: {
- if (previousCaretOffset < fStyledText.getCharCount() || previousLineAtCaretPosition < (fNumVisibleLines - 2)) {
- break;
- }
- fHoldSelection++;
- fTopLineIndex++;
- loadLineData();
- updateTextArea();
- fHoldSelection--;
- fStyledText.setSelection(fStyledText.getCaretOffset() + 1);
- break;
- }
- case SWT.ARROW_UP: {
- if (previousLineAtCaretPosition > 0) {
- break;
- }
- if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
- break;
- }
- fHoldSelection++;
- fTopLineIndex--;
- loadLineData();
- updateTextArea();
- fHoldSelection--;
- LineData lineData = fLines.get(fTopLineIndex);
- if (!lineData.location.equals(fSelectedLocation)) {
- fSelectedLocation = lineData.location;
- refreshLineBackgrounds();
- sendSelectionEvent(lineData);
- }
- fStyledText.setSelection(caretOffset);
- break;
- }
- case SWT.PAGE_UP: {
- if (previousLineAtCaretPosition > 0) {
- break;
- }
- fHoldSelection++;
- fTopLineIndex -= Math.max(fNumVisibleLines - 1, 1);
- loadLineData();
- updateTextArea();
- fHoldSelection--;
- LineData lineData = fLines.get(fTopLineIndex);
- if (!lineData.location.equals(fSelectedLocation)) {
- fSelectedLocation = lineData.location;
- refreshLineBackgrounds();
- sendSelectionEvent(lineData);
- }
- fStyledText.setSelection(caretOffset);
- break;
- }
- case SWT.ARROW_LEFT: {
- if (previousCaretOffset > 0) {
- break;
- }
- if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {
- break;
- }
- long topRank = fLines.get(fTopLineIndex).rank;
- fHoldSelection++;
- fTopLineIndex--;
- loadLineData();
- updateTextArea();
- fHoldSelection--;
- LineData lineData = fLines.get(fTopLineIndex);
- if (!lineData.location.equals(fSelectedLocation)) {
- fSelectedLocation = lineData.location;
- refreshLineBackgrounds();
- sendSelectionEvent(lineData);
- }
- if (topRank != fLines.get(fTopLineIndex).rank) {
- fStyledText.setSelection(fLines.get(fTopLineIndex).string.length());
- }
- break;
- }
- case SWT.HOME: {
- if ((e.stateMask & SWT.CTRL) == 0) {
- break;
- }
- //selectAndReveal(0);
- setTopPosition(0.0);
- LineData lineData = fLines.get(fTopLineIndex);
- if (!lineData.location.equals(fSelectedLocation)) {
- fSelectedLocation = lineData.location;
- refreshLineBackgrounds();
- sendSelectionEvent(lineData);
- }
- break;
- }
- case SWT.END: {
- if ((e.stateMask & SWT.CTRL) == 0) {
- break;
- }
- //if (fTrace.getNbEvents() > 0) {
- //selectAndReveal(fTrace.getNbEvents() - 1);
- //}
- double ratio = 1.0;
- double delta = Math.pow(10, -15);
- fLines.clear();
- while (fLines.size() == 0) {
- setTopPosition(ratio);
- if (ratio == 0.0) {
- break;
- }
- delta = Math.min(delta * 10, 0.1);
- ratio = Math.max(ratio - delta, 0.0);
- }
- LineData lineData = fLines.get(fTopLineIndex);
- if (!lineData.location.equals(fSelectedLocation)) {
- fSelectedLocation = lineData.location;
- refreshLineBackgrounds();
- sendSelectionEvent(lineData);
- }
- break;
- }
- default:
- break;
- }
- //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
- updateHighlightedRank();
- fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));
- }
-
- @Override
- public void keyReleased(KeyEvent e) {
- }
-
- // ------------------------------------------------------------------------
- // CaretListener (StyledText)
- // ------------------------------------------------------------------------
-
- @Override
- public void caretMoved(CaretEvent event) {
- if (fHoldSelection == 0) {
- int line = fStyledText.getLineAtOffset(event.caretOffset);
- if (fTopLineIndex + line < fLines.size()) {
- LineData lineData = fLines.get(fTopLineIndex + line);
- if (!lineData.location.equals(fSelectedLocation)) {
- fSelectedLocation = lineData.location;
- refreshLineBackgrounds();
- sendSelectionEvent(lineData);
- }
- }
- }
- storeCaretPosition(event.time, event.caretOffset);
- if (fHoldSelection == 0) {
- Point caret = fStyledText.getLocationAtOffset(fStyledText.getCaretOffset());
- Point origin = fScrolledComposite.getOrigin();
- if (origin.x > caret.x) {
- origin.x = caret.x;
- } else if (caret.x - origin.x > fScrolledComposite.getSize().x) {
- origin.x = caret.x - fScrolledComposite.getSize().x + 1;
- }
- fScrolledComposite.setOrigin(origin);
- }
- }
-
- // ------------------------------------------------------------------------
- // MouseMoveListener (StyledText)
- // ------------------------------------------------------------------------
-
- @Override
- public void mouseMove(MouseEvent e) {
- fCursorYCoordinate = e.y;
- if (e.y < 0 || e.y > fStyledText.getSize().y) {
- if (fHighlightedRank != Long.MIN_VALUE) {
- fHighlightedRank = Long.MIN_VALUE;
- refreshLineBackgrounds();
- }
- return;
- }
- int offset = fStyledText.getOffsetAtLocation(new Point(0, e.y));
- int line = fStyledText.getLineAtOffset(offset);
- if (line < fLines.size() - fTopLineIndex) {
- LineData lineData = fLines.get(fTopLineIndex + line);
- if (fHighlightedRank != lineData.rank) {
- fHighlightedRank = lineData.rank;
- refreshLineBackgrounds();
- }
- } else {
- if (fHighlightedRank != Long.MIN_VALUE) {
- fHighlightedRank = Long.MIN_VALUE;
- refreshLineBackgrounds();
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // MouseTrackListener (StyledText)
- // ------------------------------------------------------------------------
-
- @Override
- public void mouseExit(MouseEvent e) {
- fCursorYCoordinate = -1;
- if (fHighlightedRank != Long.MIN_VALUE) {
- fHighlightedRank = Long.MIN_VALUE;
- refreshLineBackgrounds();
- }
- }
-
- @Override
- public void mouseEnter(MouseEvent e) {
- fCursorYCoordinate = e.y;
- }
-
- @Override
- public void mouseHover(MouseEvent e) {
- }
-
- // ------------------------------------------------------------------------
- // MouseWheelListener (StyledText)
- // ------------------------------------------------------------------------
-
- @Override
- public void mouseScrolled(MouseEvent e) {
- if (fLines.size() == 0) {
- return;
- }
- fHoldSelection++;
- fTopLineIndex -= e.count;
- loadLineData();
- updateTextArea();
- fHoldSelection = 0;
- //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));
- updateHighlightedRank();
- fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));
- }
-
-}
+/*******************************************************************************\r
+ * Copyright (c) 2010, 2012 Ericsson\r
+ *\r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * Patrick Tasse - Initial API and implementation\r
+ ******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.widgets.rawviewer;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;\r
+import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;\r
+import org.eclipse.linuxtools.tmf.core.trace.ITmfLocation;\r
+import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.CaretEvent;\r
+import org.eclipse.swt.custom.CaretListener;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.custom.StyledText;\r
+import org.eclipse.swt.events.ControlEvent;\r
+import org.eclipse.swt.events.ControlListener;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.MouseAdapter;\r
+import org.eclipse.swt.events.MouseEvent;\r
+import org.eclipse.swt.events.MouseMoveListener;\r
+import org.eclipse.swt.events.MouseTrackListener;\r
+import org.eclipse.swt.events.MouseWheelListener;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.Font;\r
+import org.eclipse.swt.graphics.FontData;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Event;\r
+import org.eclipse.swt.widgets.Listener;\r
+import org.eclipse.swt.widgets.Menu;\r
+import org.eclipse.swt.widgets.Slider;\r
+\r
+/**\r
+ * TmfRawEventViewer allows for the display of the raw data for an arbitrarily\r
+ * large number of TMF events.\r
+ *\r
+ * It is essentially a Composite of a StyledText area and a Slider, where the number\r
+ * of visible lines in the StyledText control is set to fill the viewer display area.\r
+ * An underlying data model is used to store a cache of event raw text line data.\r
+ * The slider is ratio-based.\r
+ *\r
+ * @version 1.0\r
+ * @author Patrick Tasse\r
+ */\r
+public class TmfRawEventViewer extends Composite implements ControlListener, SelectionListener,\r
+ KeyListener, CaretListener, MouseMoveListener, MouseTrackListener, MouseWheelListener {\r
+\r
+ private static final Color COLOR_BACKGROUND_ODD = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);\r
+ private static final Color COLOR_BACKGROUND_EVEN = new Color(Display.getDefault(), 242, 242, 242);\r
+ private static final Color COLOR_BACKGROUND_SELECTED = new Color(Display.getDefault(), 231, 246, 254);\r
+ private static final Color COLOR_BACKGROUND_HIGHLIGHTED = new Color(Display.getDefault(), 246, 252, 255);\r
+ private static final int MAX_LINE_DATA_SIZE = 1000;\r
+ private static final int SLIDER_MAX = 1000000;\r
+\r
+ private ITmfTrace fTrace;\r
+ private ITmfContext fBottomContext;\r
+\r
+ private ScrolledComposite fScrolledComposite;\r
+ private Composite fTextArea;\r
+ private StyledText fStyledText;\r
+ private Font fFixedFont;\r
+ private Slider fSlider;\r
+\r
+ private final List<LineData> fLines = new ArrayList<LineData>();\r
+ private boolean fActualRanks = false;\r
+ private int fTopLineIndex;\r
+ private int fLastTopLineIndex;\r
+ private final CaretPosition[] fStoredCaretPosition = new CaretPosition[]\r
+ { new CaretPosition(0, 0), new CaretPosition(0,0)};\r
+ private int fNumVisibleLines;\r
+ private ITmfLocation fSelectedLocation = null;\r
+ private long fHighlightedRank = Long.MIN_VALUE;\r
+ private int fCursorYCoordinate = -1;\r
+ private int fHoldSelection = 0;\r
+\r
+ private static class LineData {\r
+ long rank;\r
+ ITmfLocation location;\r
+ String string;\r
+ public LineData(long rank, ITmfLocation location, String string) {\r
+ this.rank = rank;\r
+ this.location = location;\r
+ if (string.length() == 0) {\r
+ this.string = " "; // workaround for setLineBackground has no effect on empty line //$NON-NLS-1$\r
+ } else {\r
+ this.string = string;\r
+ }\r
+ }\r
+ @Override\r
+ public String toString() {\r
+ return rank + " [" + location + "]: " + string; //$NON-NLS-1$ //$NON-NLS-2$\r
+ }\r
+ }\r
+\r
+ private static class CaretPosition {\r
+ int time;\r
+ int caretOffset;\r
+ public CaretPosition(int time, int caretOffset) {\r
+ this.time = time;\r
+ this.caretOffset = caretOffset;\r
+ }\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // Constructor\r
+ // ------------------------------------------------------------------------\r
+\r
+ /**\r
+ * Constructor\r
+ * @param parent The parent composite\r
+ * @param style The style bits\r
+ */\r
+ public TmfRawEventViewer(Composite parent, int style) {\r
+ super(parent, style & (~SWT.H_SCROLL) & (~SWT.V_SCROLL));\r
+\r
+ // Set the layout\r
+ GridLayout gridLayout = new GridLayout();\r
+ gridLayout.numColumns = 2;\r
+ gridLayout.horizontalSpacing = 0;\r
+ gridLayout.verticalSpacing = 0;\r
+ gridLayout.marginWidth = 0;\r
+ gridLayout.marginHeight = 0;\r
+ setLayout(gridLayout);\r
+\r
+ // Create the controls\r
+ createTextArea(style & SWT.H_SCROLL);\r
+ createSlider(style & SWT.V_SCROLL);\r
+\r
+ // Prevent the slider from being traversed\r
+ setTabList(new Control[] { fScrolledComposite });\r
+ }\r
+\r
+ @Override\r
+ public void dispose() {\r
+ if (fFixedFont != null) {\r
+ fFixedFont.dispose();\r
+ fFixedFont = null;\r
+ }\r
+ super.dispose();\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // Text area handling\r
+ // ------------------------------------------------------------------------\r
+\r
+ /**\r
+ * Create the text area and add listeners\r
+ */\r
+ private void createTextArea(int style) {\r
+ fScrolledComposite = new ScrolledComposite(this, style);\r
+ fScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+ fTextArea = new Composite(fScrolledComposite, SWT.NONE);\r
+ fTextArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+ fScrolledComposite.setContent(fTextArea);\r
+ fScrolledComposite.setExpandHorizontal(true);\r
+ fScrolledComposite.setExpandVertical(true);\r
+ fScrolledComposite.setAlwaysShowScrollBars(true);\r
+ fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));\r
+ fScrolledComposite.addControlListener(this);\r
+\r
+ GridLayout textAreaGridLayout = new GridLayout();\r
+ textAreaGridLayout.marginHeight = 0;\r
+ textAreaGridLayout.marginWidth = 0;\r
+ fTextArea.setLayout(textAreaGridLayout);\r
+\r
+ if (fFixedFont == null) {\r
+ if (System.getProperty("os.name").contains("Windows")) { //$NON-NLS-1$ //$NON-NLS-2$\r
+ fFixedFont = new Font(Display.getCurrent(), new FontData("Courier New", 10, SWT.NORMAL)); //$NON-NLS-1$\r
+ } else {\r
+ fFixedFont = new Font(Display.getCurrent(), new FontData("Monospace", 10, SWT.NORMAL)); //$NON-NLS-1$\r
+ }\r
+ }\r
+\r
+ fStyledText = new StyledText(fTextArea, SWT.READ_ONLY);\r
+ fStyledText.setFont(fFixedFont);\r
+ fStyledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));\r
+\r
+ fStyledText.addCaretListener(this);\r
+ fStyledText.addMouseMoveListener(this);\r
+ fStyledText.addMouseTrackListener(this);\r
+ fStyledText.addMouseWheelListener(this);\r
+ fStyledText.addListener(SWT.MouseWheel, new Listener() { // disable mouse scroll of horizontal scroll bar\r
+ @Override\r
+ public void handleEvent(Event event) { event.doit = false; }});\r
+ fStyledText.addKeyListener(this);\r
+\r
+ fTextArea.setBackground(fStyledText.getBackground());\r
+ fTextArea.addMouseListener(new MouseAdapter() {\r
+ @Override\r
+ public void mouseDown(MouseEvent e) {\r
+ fTextArea.setFocus();\r
+ }});\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // Slider handling\r
+ // ------------------------------------------------------------------------\r
+\r
+ private void createSlider(int style) {\r
+ fSlider = new Slider(this, SWT.VERTICAL);\r
+ fSlider.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));\r
+ fSlider.setValues(0, 0, SLIDER_MAX, SLIDER_MAX, 1, 1);\r
+ fSlider.addSelectionListener(this);\r
+ if ((style & SWT.V_SCROLL) == 0) {\r
+ fSlider.setVisible(false);\r
+ }\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // Controls interactions\r
+ // ------------------------------------------------------------------------\r
+\r
+ @Override\r
+ public boolean setFocus() {\r
+ boolean isVisible = isVisible();\r
+ if (isVisible) {\r
+ fTextArea.setFocus();\r
+ }\r
+ return isVisible;\r
+ }\r
+\r
+ @Override\r
+ public void setMenu(Menu menu) {\r
+ fStyledText.setMenu(menu);\r
+ }\r
+\r
+ /**\r
+ * Sets the trace and updates the content\r
+ * @param trace The trace to set\r
+ */\r
+ public void setTrace(ITmfTrace trace) {\r
+ fTrace = trace;\r
+ fTopLineIndex = 0;\r
+ fLines.clear();\r
+ refreshEventCount();\r
+ }\r
+\r
+ /**\r
+ * Refreshes the event count, updates the slider thumb and loads display\r
+ */\r
+ public void refreshEventCount() {\r
+ if (fTrace != null) {\r
+ if (fTrace.getNbEvents() > 0) {\r
+ fSlider.setThumb((int) Math.max(SLIDER_MAX / fTrace.getNbEvents(), 1));\r
+ } else {\r
+ fSlider.setThumb(SLIDER_MAX);\r
+ }\r
+\r
+ if (!isVisible()) {\r
+ return;\r
+ }\r
+\r
+ if (fLines.size() == 0) {\r
+ setTopRank(0);\r
+ } else if (fLines.size() < fNumVisibleLines) {\r
+ fBottomContext = null;\r
+ loadLineData();\r
+ fillTextArea();\r
+ //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));\r
+ fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));\r
+ }\r
+ } else {\r
+ fBottomContext = null;\r
+ fillTextArea();\r
+ fSlider.setThumb(SLIDER_MAX);\r
+ fSlider.setSelection(0);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Selects the event of given rank and makes it visible.\r
+ * @param rank The rank of event\r
+ */\r
+ public void selectAndReveal(long rank) {\r
+ if (fTrace == null || !isVisible()) {\r
+ return;\r
+ }\r
+ if (fActualRanks && fTopLineIndex < fLines.size() && rank >= fLines.get(fTopLineIndex).rank) {\r
+ int lastVisibleIndex = Math.min(fTopLineIndex + fNumVisibleLines, fLines.size()) - 1;\r
+ if (rank <= fLines.get(lastVisibleIndex).rank) {\r
+ for (int i = fTopLineIndex; i < fLines.size(); i++) {\r
+ if (fLines.get(i).rank == rank) {\r
+ fSelectedLocation = fLines.get(i).location;\r
+ break;\r
+ }\r
+ }\r
+ refreshLineBackgrounds();\r
+ return;\r
+ }\r
+ }\r
+ setTopRank(rank);\r
+ if (fLines.size() > 0 && fHoldSelection == 0) {\r
+ fSelectedLocation = fLines.get(0).location;\r
+ refreshLineBackgrounds();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Add a selection listener\r
+ * @param listener A listener to add\r
+ */\r
+ public void addSelectionListener(Listener listener) {\r
+ checkWidget();\r
+ if (listener == null) {\r
+ SWT.error (SWT.ERROR_NULL_ARGUMENT);\r
+ }\r
+ addListener (SWT.Selection, listener);\r
+ }\r
+\r
+ /**\r
+ * Remove selection listener\r
+ * @param listener A listener to remove\r
+ */\r
+ public void removeSelectionListener(Listener listener) {\r
+ checkWidget();\r
+ if (listener == null) {\r
+ SWT.error (SWT.ERROR_NULL_ARGUMENT);\r
+ }\r
+ removeListener(SWT.Selection, listener);\r
+ }\r
+\r
+ private void sendSelectionEvent(LineData lineData) {\r
+ Event event = new Event();\r
+ if (fActualRanks) {\r
+ event.data = Long.valueOf(lineData.rank);\r
+ } else {\r
+ event.data = lineData.location;\r
+ }\r
+ notifyListeners(SWT.Selection, event);\r
+ }\r
+\r
+ private void setTopRank(long rank) {\r
+ fBottomContext = fTrace.seekEvent(rank);\r
+ if (fBottomContext == null) {\r
+ return;\r
+ }\r
+ fLines.clear();\r
+ fActualRanks = true;\r
+ fTopLineIndex = 0;\r
+ loadLineData();\r
+ refreshTextArea();\r
+ if (fLines.size() == 0) {\r
+ fSlider.setSelection(0);\r
+ } else {\r
+ //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));\r
+ fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));\r
+ }\r
+ }\r
+\r
+ private void setTopPosition(double ratio) {\r
+ fBottomContext = fTrace.seekEvent(ratio);\r
+ if (fBottomContext == null) {\r
+ return;\r
+ }\r
+ fBottomContext.setRank(0);\r
+ fLines.clear();\r
+ fActualRanks = false;\r
+ fTopLineIndex = 0;\r
+ loadLineData();\r
+ refreshTextArea();\r
+ }\r
+\r
+ private void loadLineData() {\r
+ if (fTopLineIndex < 0) {\r
+ //if (fLines.size() > 0 && fLines.get(0).rank > 0) {\r
+ //long endRank = fLines.get(0).rank;\r
+ //long startRank = Math.max(0, endRank - fNumVisibleLines);\r
+ //TmfContext context = fTrace.seekEvent(startRank);\r
+ //int index = 0;\r
+ //while (context.getRank() < endRank) {\r
+ //long rank = context.getRank();\r
+ //ITmfLocation<?> location = context.getLocation();\r
+ //TmfEvent event = fTrace.getNextEvent(context);\r
+ //String[] lines = event.getRawText().split("\r?\n");\r
+ //for (int i = 0; i < lines.length; i++) {\r
+ //String line = lines[i];\r
+ //LineData lineData = new LineData(rank, location, line);\r
+ //fLines.add(index++, lineData);\r
+ //fTopLineIndex++;\r
+ //fLastTopLineIndex++;\r
+ //}\r
+ //}\r
+ //}\r
+ if (fLines.size() > 0 && fTrace.getLocationRatio(fLines.get(0).location) > 0) {\r
+ double lastRatio = fTrace.getLocationRatio(fLines.get(fLines.size() - 1).location);\r
+ double firstRatio = fTrace.getLocationRatio(fLines.get(0).location);\r
+ double delta;\r
+ boolean singleEvent = false;\r
+ if (firstRatio != lastRatio) {\r
+ // approximate ratio of at least 20 items\r
+ delta = Math.max(20, fNumVisibleLines) * (lastRatio - firstRatio) / (fLines.size() - 1);\r
+ } else {\r
+ delta = Math.pow(10, -15);\r
+ singleEvent = true;\r
+ }\r
+ while (fTopLineIndex < 0) {\r
+ ITmfLocation endLocation = fLines.get(0).location;\r
+ firstRatio = Math.max(0, firstRatio - delta);\r
+ ITmfContext context = fTrace.seekEvent(firstRatio);\r
+ ITmfLocation location;\r
+ int index = 0;\r
+ long rank = 0;\r
+ while (!context.getLocation().equals(endLocation)) {\r
+ location = context.getLocation();\r
+ ITmfEvent event = fTrace.getNext(context);\r
+ if (event == null) {\r
+ break;\r
+ }\r
+ if (event.getContent() != null && event.getContent().getValue() != null) {\r
+ String[] lines = event.getContent().getValue().toString().split("\r?\n"); //$NON-NLS-1$\r
+ for (int i = 0; i < lines.length; i++) {\r
+ String line = lines[i];\r
+ LineData lineData = new LineData(rank, location, line);\r
+ fLines.add(index++, lineData);\r
+ fTopLineIndex++;\r
+ fLastTopLineIndex++;\r
+ }\r
+ } else {\r
+ LineData lineData = new LineData(rank, location, ""); //$NON-NLS-1$\r
+ fLines.add(index++, lineData);\r
+ fTopLineIndex++;\r
+ fLastTopLineIndex++;\r
+ }\r
+ rank++;\r
+ }\r
+ long rankOffset = fLines.get(index).rank - rank;\r
+ for (int i = 0; i < index; i++) {\r
+ fLines.get(i).rank += rankOffset;\r
+ }\r
+ if (firstRatio == 0) {\r
+ break;\r
+ }\r
+ if (singleEvent) {\r
+ delta = Math.min(delta * 10, 0.1);\r
+ }\r
+ }\r
+ }\r
+ if (fTopLineIndex < 0) {\r
+ fTopLineIndex = 0;\r
+ }\r
+ }\r
+\r
+ while (fLines.size() - fTopLineIndex < fNumVisibleLines) {\r
+ if (fBottomContext == null) {\r
+ if (fLines.size() == 0) {\r
+ fBottomContext = fTrace.seekEvent(0);\r
+ } else {\r
+ //fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).rank + 1);\r
+ fBottomContext = fTrace.seekEvent(fLines.get(fLines.size() - 1).location);\r
+ fTrace.getNext(fBottomContext);\r
+ }\r
+ if (fBottomContext == null) {\r
+ break;\r
+ }\r
+ }\r
+ long rank = fBottomContext.getRank();\r
+ ITmfLocation location = fBottomContext.getLocation() != null ? fBottomContext.getLocation() : null;\r
+ ITmfEvent event = fTrace.getNext(fBottomContext);\r
+ if (event == null) {\r
+ break;\r
+ }\r
+ if (event.getContent() != null && event.getContent().getValue() != null) {\r
+ for (String line : event.getContent().getValue().toString().split("\r?\n")) { //$NON-NLS-1$\r
+ int crPos;\r
+ if ((crPos = line.indexOf('\r')) != -1) {\r
+ line = line.substring(0, crPos);\r
+ }\r
+ LineData lineData = new LineData(rank, location, line);\r
+ fLines.add(lineData);\r
+ }\r
+ } else {\r
+ LineData lineData = new LineData(rank, location, ""); //$NON-NLS-1$\r
+ fLines.add(lineData);\r
+ }\r
+ }\r
+ fTopLineIndex = Math.max(0, Math.min(fTopLineIndex, fLines.size() - 1));\r
+\r
+ if (fLines.size() > MAX_LINE_DATA_SIZE) {\r
+ if (fTopLineIndex < MAX_LINE_DATA_SIZE / 2) {\r
+ long rank = fLines.get(MAX_LINE_DATA_SIZE - 1).rank;\r
+ for (int i = MAX_LINE_DATA_SIZE; i < fLines.size(); i++) {\r
+ if (fLines.get(i).rank > rank) {\r
+ fLines.subList(i, fLines.size()).clear();\r
+ fBottomContext = null;\r
+ break;\r
+ }\r
+ }\r
+ } else {\r
+ long rank = fLines.get(fLines.size() - MAX_LINE_DATA_SIZE).rank;\r
+ for (int i = fLines.size() - MAX_LINE_DATA_SIZE - 1; i >= 0; i--) {\r
+ if (fLines.get(i).rank < rank) {\r
+ fLines.subList(0, i + 1).clear();\r
+ fTopLineIndex -= (i + 1);\r
+ fLastTopLineIndex -= (i + 1);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ private void refreshTextArea() {\r
+ fStyledText.setText(""); //$NON-NLS-1$\r
+ for (int i = 0; i < fLines.size() - fTopLineIndex && i < fNumVisibleLines; i++) {\r
+ if (i > 0)\r
+ {\r
+ fStyledText.append("\n"); //$NON-NLS-1$\r
+ }\r
+ LineData lineData = fLines.get(fTopLineIndex + i);\r
+ fStyledText.append(lineData.string);\r
+ setLineBackground(i, lineData);\r
+ }\r
+ fTextArea.layout();\r
+ fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));\r
+ fLastTopLineIndex = fTopLineIndex;\r
+ }\r
+\r
+ private void fillTextArea() {\r
+ int nextLine = fStyledText.getCharCount() == 0 ? 0 : fStyledText.getLineCount();\r
+ for (int i = nextLine; i < fLines.size() - fTopLineIndex && i < fNumVisibleLines; i++) {\r
+ if (i > 0)\r
+ {\r
+ fStyledText.append("\n"); //$NON-NLS-1$\r
+ }\r
+ LineData lineData = fLines.get(fTopLineIndex + i);\r
+ fStyledText.append(lineData.string);\r
+ setLineBackground(i, lineData);\r
+ }\r
+ int endLine = Math.min(fNumVisibleLines, fLines.size());\r
+ if (endLine < fStyledText.getLineCount()) {\r
+ int endOffset = fStyledText.getOffsetAtLine(endLine) - 1;\r
+ if (endOffset > fStyledText.getCharCount()) {\r
+ fHoldSelection++;\r
+ fStyledText.replaceTextRange(endOffset, fStyledText.getCharCount() - endOffset, ""); //$NON-NLS-1$\r
+ fHoldSelection--;\r
+ }\r
+ }\r
+ fTextArea.layout();\r
+ fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));\r
+ }\r
+\r
+ private void updateTextArea() {\r
+ if (fTopLineIndex < fLastTopLineIndex) {\r
+ StringBuffer insertedText = new StringBuffer();\r
+ for (int i = fTopLineIndex; i < fLastTopLineIndex; i++) {\r
+ insertedText.append(fLines.get(i).string + "\n"); //$NON-NLS-1$\r
+ }\r
+ fStyledText.replaceTextRange(0, 0, insertedText.toString());\r
+ for (int i = 0; i < fLastTopLineIndex - fTopLineIndex; i++) {\r
+ LineData lineData = fLines.get(fTopLineIndex + i);\r
+ setLineBackground(i, lineData);\r
+ }\r
+ fLastTopLineIndex = fTopLineIndex;\r
+ } else if (fTopLineIndex > fLastTopLineIndex) {\r
+ int length = 0;\r
+ for (int i = 0; i < fTopLineIndex - fLastTopLineIndex && i < fNumVisibleLines; i++) {\r
+ length += fLines.get(i + fLastTopLineIndex).string.length();\r
+ if (i < fStyledText.getLineCount()) {\r
+ length += 1;\r
+ }\r
+ }\r
+ fStyledText.replaceTextRange(0, length, ""); //$NON-NLS-1$\r
+ fLastTopLineIndex = fTopLineIndex;\r
+ fillTextArea();\r
+ }\r
+ int endLine = Math.min(fNumVisibleLines, fLines.size());\r
+ if (endLine < fStyledText.getLineCount()) {\r
+ int endOffset = fStyledText.getOffsetAtLine(endLine) - 1;\r
+ if (endOffset > fStyledText.getCharCount()) {\r
+ fStyledText.replaceTextRange(endOffset, fStyledText.getCharCount() - endOffset, ""); //$NON-NLS-1$\r
+ }\r
+ }\r
+ fTextArea.layout();\r
+ fScrolledComposite.setMinSize(fTextArea.computeSize(SWT.DEFAULT, SWT.DEFAULT));\r
+ }\r
+\r
+ private void refreshLineBackgrounds() {\r
+ for (int i = 0; (i < fStyledText.getLineCount()) && (i < fNumVisibleLines) && (i < fLines.size() - fTopLineIndex); i++) {\r
+ LineData lineData = fLines.get(fTopLineIndex + i);\r
+ setLineBackground(i, lineData);\r
+ }\r
+ }\r
+\r
+ private void setLineBackground(int index, LineData lineData) {\r
+ if (lineData.location.equals(fSelectedLocation)) {\r
+ fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_SELECTED);\r
+ } else if (lineData.rank == fHighlightedRank) {\r
+ fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_HIGHLIGHTED);\r
+ } else if (lineData.rank % 2 == 0) {\r
+ fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_EVEN);\r
+ } else {\r
+ fStyledText.setLineBackground(index, 1, COLOR_BACKGROUND_ODD);\r
+ }\r
+ }\r
+\r
+ private void storeCaretPosition(int time, int caretOffset) {\r
+ if (fStoredCaretPosition[0].time == time) {\r
+ fStoredCaretPosition[0].caretOffset = caretOffset;\r
+ } else {\r
+ fStoredCaretPosition[1] = fStoredCaretPosition[0];\r
+ fStoredCaretPosition[0] = new CaretPosition(time, caretOffset);\r
+ }\r
+ }\r
+\r
+ private int getPreviousCaretOffset(int time) {\r
+ if (fStoredCaretPosition[0].time == time) {\r
+ return fStoredCaretPosition[1].caretOffset;\r
+ }\r
+ return fStoredCaretPosition[0].caretOffset;\r
+ }\r
+\r
+ private void updateHighlightedRank() {\r
+ if (fCursorYCoordinate < 0 || fCursorYCoordinate > fStyledText.getSize().y) {\r
+ if (fHighlightedRank != Long.MIN_VALUE) {\r
+ fHighlightedRank = Long.MIN_VALUE;\r
+ refreshLineBackgrounds();\r
+ }\r
+ return;\r
+ }\r
+ int offset = fStyledText.getOffsetAtLocation(new Point(0, fCursorYCoordinate));\r
+ int line = fStyledText.getLineAtOffset(offset);\r
+ if (line < fLines.size() - fTopLineIndex) {\r
+ LineData lineData = fLines.get(fTopLineIndex + line);\r
+ if (fHighlightedRank != lineData.rank) {\r
+ fHighlightedRank = lineData.rank;\r
+ refreshLineBackgrounds();\r
+ }\r
+ } else {\r
+ if (fHighlightedRank != Long.MIN_VALUE) {\r
+ fHighlightedRank = Long.MIN_VALUE;\r
+ refreshLineBackgrounds();\r
+ }\r
+ }\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // ControlListener (ScrolledComposite)\r
+ // ------------------------------------------------------------------------\r
+\r
+ @Override\r
+ public void controlResized(ControlEvent event) {\r
+ int areaHeight = fScrolledComposite.getSize().y;\r
+ if (fScrolledComposite.getHorizontalBar() != null) {\r
+ areaHeight -= fScrolledComposite.getHorizontalBar().getSize().y;\r
+ }\r
+ int lineHeight = fStyledText.getLineHeight();\r
+ fNumVisibleLines = Math.max((areaHeight + lineHeight - 1) / lineHeight, 1);\r
+\r
+ if (fBottomContext != null) {\r
+ loadLineData();\r
+ fillTextArea();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void controlMoved(ControlEvent e) {\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // SelectionListener (Slider)\r
+ // ------------------------------------------------------------------------\r
+\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ fTextArea.setFocus();\r
+ if (fLines.size() == 0) {\r
+ return;\r
+ }\r
+ if (e.detail == SWT.DRAG) {\r
+ return;\r
+ }\r
+ fHoldSelection++;\r
+ switch (e.detail) {\r
+ case SWT.NONE: {\r
+ //long rank = (long) (fTrace.getNbEvents() * ((double) fSlider.getSelection() / SLIDER_MAX));\r
+ //setTopRank(rank);\r
+ if (fSlider.getSelection() == 0 || fSlider.getThumb() == SLIDER_MAX) {\r
+ fLines.clear();\r
+ setTopPosition(0.0);\r
+ break;\r
+ }\r
+ double ratio = (double) fSlider.getSelection() / (SLIDER_MAX - fSlider.getThumb());\r
+ double delta = Math.pow(10, -15);\r
+ fLines.clear();\r
+ while (fLines.size() == 0) {\r
+ setTopPosition(ratio);\r
+ if (ratio == 0.0) {\r
+ break;\r
+ }\r
+ delta = Math.min(delta * 10, 0.1);\r
+ ratio = Math.max(ratio - delta, 0.0);\r
+ }\r
+ break;\r
+ }\r
+ case SWT.ARROW_DOWN: {\r
+ if (fTopLineIndex >= fLines.size()) {\r
+ break;\r
+ }\r
+ fTopLineIndex++;\r
+ loadLineData();\r
+ updateTextArea();\r
+ break;\r
+ }\r
+ case SWT.PAGE_DOWN: {\r
+ fTopLineIndex += Math.max(fNumVisibleLines - 1, 1);\r
+ loadLineData();\r
+ updateTextArea();\r
+ break;\r
+ }\r
+ case SWT.ARROW_UP: {\r
+ //if (fLines.size() == 0 || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {\r
+ if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {\r
+ break;\r
+ }\r
+ fTopLineIndex--;\r
+ loadLineData();\r
+ updateTextArea();\r
+ break;\r
+ }\r
+ case SWT.PAGE_UP: {\r
+ fTopLineIndex -= Math.max(fNumVisibleLines - 1, 1);\r
+ loadLineData();\r
+ updateTextArea();\r
+ break;\r
+ }\r
+ case SWT.HOME: {\r
+ //selectAndReveal(0);\r
+ setTopPosition(0.0);\r
+ break;\r
+ }\r
+ case SWT.END: {\r
+ //if (fTrace.getNbEvents() > 0) {\r
+ //selectAndReveal(fTrace.getNbEvents() - 1);\r
+ //}\r
+ double ratio = 1.0;\r
+ double delta = Math.pow(10, -15);\r
+ fLines.clear();\r
+ while (fLines.size() == 0) {\r
+ setTopPosition(ratio);\r
+ if (ratio == 0.0) {\r
+ break;\r
+ }\r
+ delta = Math.min(delta * 10, 0.1);\r
+ ratio = Math.max(ratio - delta, 0.0);\r
+ }\r
+ break;\r
+ }\r
+ default:\r
+ break;\r
+ }\r
+ //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));\r
+ if (e.detail != SWT.NONE) {\r
+ fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));\r
+ }\r
+\r
+ fHoldSelection = 0;\r
+ }\r
+\r
+ @Override\r
+ public void widgetDefaultSelected(SelectionEvent e) {\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // KeyListener (StyledText)\r
+ // ------------------------------------------------------------------------\r
+\r
+ @Override\r
+ public void keyPressed(KeyEvent e) {\r
+ if (fLines.size() == 0) {\r
+ return;\r
+ }\r
+ int caretOffset = fStyledText.getCaretOffset();\r
+ int previousCaretOffset = getPreviousCaretOffset(e.time);\r
+ int previousLineAtCaretPosition = fStyledText.getLineAtOffset(previousCaretOffset);\r
+ int previousColumnAtCaretPosition = getPreviousCaretOffset(e.time) - fStyledText.getOffsetAtLine(previousLineAtCaretPosition);\r
+ switch (e.keyCode) {\r
+ case SWT.ARROW_DOWN: {\r
+ if (previousLineAtCaretPosition < (fNumVisibleLines - 2)) {\r
+ break;\r
+ }\r
+ fHoldSelection++;\r
+ fTopLineIndex++;\r
+ loadLineData();\r
+ updateTextArea();\r
+ fHoldSelection--;\r
+ LineData lineData = fLines.get(fTopLineIndex + fStyledText.getLineAtOffset(fStyledText.getCaretOffset()));\r
+ if (!lineData.location.equals(fSelectedLocation)) {\r
+ fSelectedLocation = lineData.location;\r
+ refreshLineBackgrounds();\r
+ sendSelectionEvent(lineData);\r
+ }\r
+ break;\r
+ }\r
+ case SWT.PAGE_DOWN: {\r
+ if (previousLineAtCaretPosition >= (fNumVisibleLines - 1)) {\r
+ fHoldSelection++;\r
+ if (fLines.get(fTopLineIndex + previousLineAtCaretPosition).rank % 2 == 0) {\r
+ fStyledText.setLineBackground(previousLineAtCaretPosition, 1, COLOR_BACKGROUND_EVEN);\r
+ } else {\r
+ fStyledText.setLineBackground(previousLineAtCaretPosition, 1, COLOR_BACKGROUND_ODD);\r
+ }\r
+ fSelectedLocation = null;\r
+ fTopLineIndex += Math.max(fNumVisibleLines - 1, 1);\r
+ loadLineData();\r
+ updateTextArea();\r
+ fHoldSelection--;\r
+ }\r
+ int line = Math.min(fNumVisibleLines - 1, fStyledText.getLineCount() - 1);\r
+ int offset = fStyledText.getOffsetAtLine(line);\r
+ fStyledText.setSelection(offset + Math.min(previousColumnAtCaretPosition, fLines.get(fTopLineIndex + line).string.length()));\r
+ break;\r
+ }\r
+ case SWT.ARROW_RIGHT: {\r
+ if (previousCaretOffset < fStyledText.getCharCount() || previousLineAtCaretPosition < (fNumVisibleLines - 2)) {\r
+ break;\r
+ }\r
+ fHoldSelection++;\r
+ fTopLineIndex++;\r
+ loadLineData();\r
+ updateTextArea();\r
+ fHoldSelection--;\r
+ fStyledText.setSelection(fStyledText.getCaretOffset() + 1);\r
+ break;\r
+ }\r
+ case SWT.ARROW_UP: {\r
+ if (previousLineAtCaretPosition > 0) {\r
+ break;\r
+ }\r
+ if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {\r
+ break;\r
+ }\r
+ fHoldSelection++;\r
+ fTopLineIndex--;\r
+ loadLineData();\r
+ updateTextArea();\r
+ fHoldSelection--;\r
+ LineData lineData = fLines.get(fTopLineIndex);\r
+ if (!lineData.location.equals(fSelectedLocation)) {\r
+ fSelectedLocation = lineData.location;\r
+ refreshLineBackgrounds();\r
+ sendSelectionEvent(lineData);\r
+ }\r
+ fStyledText.setSelection(caretOffset);\r
+ break;\r
+ }\r
+ case SWT.PAGE_UP: {\r
+ if (previousLineAtCaretPosition > 0) {\r
+ break;\r
+ }\r
+ fHoldSelection++;\r
+ fTopLineIndex -= Math.max(fNumVisibleLines - 1, 1);\r
+ loadLineData();\r
+ updateTextArea();\r
+ fHoldSelection--;\r
+ LineData lineData = fLines.get(fTopLineIndex);\r
+ if (!lineData.location.equals(fSelectedLocation)) {\r
+ fSelectedLocation = lineData.location;\r
+ refreshLineBackgrounds();\r
+ sendSelectionEvent(lineData);\r
+ }\r
+ fStyledText.setSelection(caretOffset);\r
+ break;\r
+ }\r
+ case SWT.ARROW_LEFT: {\r
+ if (previousCaretOffset > 0) {\r
+ break;\r
+ }\r
+ if (fLines.size() == 0) {// || (fTopLineIndex == 0 && fLines.get(0).rank == 0)) {\r
+ break;\r
+ }\r
+ long topRank = fLines.get(fTopLineIndex).rank;\r
+ fHoldSelection++;\r
+ fTopLineIndex--;\r
+ loadLineData();\r
+ updateTextArea();\r
+ fHoldSelection--;\r
+ LineData lineData = fLines.get(fTopLineIndex);\r
+ if (!lineData.location.equals(fSelectedLocation)) {\r
+ fSelectedLocation = lineData.location;\r
+ refreshLineBackgrounds();\r
+ sendSelectionEvent(lineData);\r
+ }\r
+ if (topRank != fLines.get(fTopLineIndex).rank) {\r
+ fStyledText.setSelection(fLines.get(fTopLineIndex).string.length());\r
+ }\r
+ break;\r
+ }\r
+ case SWT.HOME: {\r
+ if ((e.stateMask & SWT.CTRL) == 0) {\r
+ break;\r
+ }\r
+ //selectAndReveal(0);\r
+ setTopPosition(0.0);\r
+ LineData lineData = fLines.get(fTopLineIndex);\r
+ if (!lineData.location.equals(fSelectedLocation)) {\r
+ fSelectedLocation = lineData.location;\r
+ refreshLineBackgrounds();\r
+ sendSelectionEvent(lineData);\r
+ }\r
+ break;\r
+ }\r
+ case SWT.END: {\r
+ if ((e.stateMask & SWT.CTRL) == 0) {\r
+ break;\r
+ }\r
+ //if (fTrace.getNbEvents() > 0) {\r
+ //selectAndReveal(fTrace.getNbEvents() - 1);\r
+ //}\r
+ double ratio = 1.0;\r
+ double delta = Math.pow(10, -15);\r
+ fLines.clear();\r
+ while (fLines.size() == 0) {\r
+ setTopPosition(ratio);\r
+ if (ratio == 0.0) {\r
+ break;\r
+ }\r
+ delta = Math.min(delta * 10, 0.1);\r
+ ratio = Math.max(ratio - delta, 0.0);\r
+ }\r
+ LineData lineData = fLines.get(fTopLineIndex);\r
+ if (!lineData.location.equals(fSelectedLocation)) {\r
+ fSelectedLocation = lineData.location;\r
+ refreshLineBackgrounds();\r
+ sendSelectionEvent(lineData);\r
+ }\r
+ break;\r
+ }\r
+ default:\r
+ break;\r
+ }\r
+ //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));\r
+ updateHighlightedRank();\r
+ fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));\r
+ }\r
+\r
+ @Override\r
+ public void keyReleased(KeyEvent e) {\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // CaretListener (StyledText)\r
+ // ------------------------------------------------------------------------\r
+\r
+ @Override\r
+ public void caretMoved(CaretEvent event) {\r
+ if (fHoldSelection == 0) {\r
+ int line = fStyledText.getLineAtOffset(event.caretOffset);\r
+ if (fTopLineIndex + line < fLines.size()) {\r
+ LineData lineData = fLines.get(fTopLineIndex + line);\r
+ if (!lineData.location.equals(fSelectedLocation)) {\r
+ fSelectedLocation = lineData.location;\r
+ refreshLineBackgrounds();\r
+ sendSelectionEvent(lineData);\r
+ }\r
+ }\r
+ }\r
+ storeCaretPosition(event.time, event.caretOffset);\r
+ if (fHoldSelection == 0) {\r
+ Point caret = fStyledText.getLocationAtOffset(fStyledText.getCaretOffset());\r
+ Point origin = fScrolledComposite.getOrigin();\r
+ if (origin.x > caret.x) {\r
+ origin.x = caret.x;\r
+ } else if (caret.x - origin.x > fScrolledComposite.getSize().x) {\r
+ origin.x = caret.x - fScrolledComposite.getSize().x + 1;\r
+ }\r
+ fScrolledComposite.setOrigin(origin);\r
+ }\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // MouseMoveListener (StyledText)\r
+ // ------------------------------------------------------------------------\r
+\r
+ @Override\r
+ public void mouseMove(MouseEvent e) {\r
+ fCursorYCoordinate = e.y;\r
+ if (e.y < 0 || e.y > fStyledText.getSize().y) {\r
+ if (fHighlightedRank != Long.MIN_VALUE) {\r
+ fHighlightedRank = Long.MIN_VALUE;\r
+ refreshLineBackgrounds();\r
+ }\r
+ return;\r
+ }\r
+ int offset = fStyledText.getOffsetAtLocation(new Point(0, e.y));\r
+ int line = fStyledText.getLineAtOffset(offset);\r
+ if (line < fLines.size() - fTopLineIndex) {\r
+ LineData lineData = fLines.get(fTopLineIndex + line);\r
+ if (fHighlightedRank != lineData.rank) {\r
+ fHighlightedRank = lineData.rank;\r
+ refreshLineBackgrounds();\r
+ }\r
+ } else {\r
+ if (fHighlightedRank != Long.MIN_VALUE) {\r
+ fHighlightedRank = Long.MIN_VALUE;\r
+ refreshLineBackgrounds();\r
+ }\r
+ }\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // MouseTrackListener (StyledText)\r
+ // ------------------------------------------------------------------------\r
+\r
+ @Override\r
+ public void mouseExit(MouseEvent e) {\r
+ fCursorYCoordinate = -1;\r
+ if (fHighlightedRank != Long.MIN_VALUE) {\r
+ fHighlightedRank = Long.MIN_VALUE;\r
+ refreshLineBackgrounds();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void mouseEnter(MouseEvent e) {\r
+ fCursorYCoordinate = e.y;\r
+ }\r
+\r
+ @Override\r
+ public void mouseHover(MouseEvent e) {\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // MouseWheelListener (StyledText)\r
+ // ------------------------------------------------------------------------\r
+\r
+ @Override\r
+ public void mouseScrolled(MouseEvent e) {\r
+ if (fLines.size() == 0) {\r
+ return;\r
+ }\r
+ fHoldSelection++;\r
+ fTopLineIndex -= e.count;\r
+ loadLineData();\r
+ updateTextArea();\r
+ fHoldSelection = 0;\r
+ //fSlider.setSelection((int) (SLIDER_MAX * ((double) fLines.get(fTopLineIndex).rank / fTrace.getNbEvents())));\r
+ updateHighlightedRank();\r
+ fSlider.setSelection((int) (SLIDER_MAX * fTrace.getLocationRatio(fLines.get(fTopLineIndex).location)));\r
+ }\r
+\r
+}\r