* Patrick Tasse, Ericsson - Refactoring
* Geneviève Bastien, École Polytechnique de Montréal - Move code to
* provide base classes for time graph view
+ * Add display of links between items
*****************************************************************************/
package org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.ViewerFilter;
-import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTimestamp;
import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.timestamp.TmfNanoTimestamp;
import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestampDelta;
import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider;
import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider2;
import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTreeListener;
import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.StateItem;
import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTreeExpansionEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ILinkEvent;
import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
import org.eclipse.swt.SWT;
redraw();
}
+ /**
+ * Refresh the links (arrows) of this widget
+ *
+ * @param events The link events to refresh
+ * @since 2.1
+ */
+ public void refreshArrows(List<ILinkEvent> events) {
+ fItemData.refreshArrows(events);
+ }
+
/**
* Adjust the scoll bars
*/
// draw items
drawItems(bounds, fTimeProvider, fItemData.fExpandedItems, fTopIndex, nameSpace, gc);
+ drawLinks(bounds, fTimeProvider, fItemData.fLinks, nameSpace, gc);
+ fTimeGraphProvider.postDrawControl(bounds, gc);
int alpha = gc.getAlpha();
gc.setAlpha(100);
Item item = items[i];
drawItem(item, bounds, timeProvider, i, nameSpace, gc);
}
- fTimeGraphProvider.postDrawControl(bounds, gc);
}
/**
fTimeGraphProvider.postDrawEntry(entry, rect, gc);
}
+ /**
+ * Draw the links
+ *
+ * @param bounds
+ * The rectangle of the area
+ * @param timeProvider
+ * The time provider
+ * @param links
+ * The array items to draw
+ * @param nameSpace
+ * The width reserved for the names
+ * @param gc
+ * Reference to the SWT GC object
+ * @since 2.1
+ */
+ public void drawLinks(Rectangle bounds, ITimeDataProvider timeProvider,
+ List<ILinkEvent> links, int nameSpace, GC gc) {
+ for (ILinkEvent event : links) {
+ drawLink(event, bounds, timeProvider, nameSpace, gc);
+ }
+ }
+
+ /**
+ * Draws the link type events of this item
+ *
+ * @param event
+ * the item to draw
+ * @param bounds
+ * the container rectangle
+ * @param timeProvider
+ * Time provider
+ * @param nameSpace
+ * the name space
+ * @param gc
+ * Graphics context
+ * @since 2.1
+ */
+ protected void drawLink(ILinkEvent event, Rectangle bounds, ITimeDataProvider timeProvider, int nameSpace, GC gc) {
+ int srcIndex = fItemData.findItemIndex(event.getEntry());
+ int destIndex = fItemData.findItemIndex(event.getDestinationEntry());
+
+ if ((srcIndex == -1) || (destIndex == -1)) {
+ return;
+ }
+
+ Rectangle src = getStatesRect(bounds, srcIndex, nameSpace);
+ Rectangle dst = getStatesRect(bounds, destIndex, nameSpace);
+
+ int x0 = getXForTime(event.getTime());
+ int x1 = getXForTime(event.getTime() + event.getDuration());
+ int y0 = src.y + src.height / 2;
+ int y1 = dst.y + dst.height / 2;
+ drawArrow(getColorScheme(), event, new Rectangle(x0, y0, x1 - x0, y1 - y0), gc);
+ }
+
+ /**
+ * Draw the state (color fill)
+ *
+ * @param colors
+ * Color scheme
+ * @param event
+ * Time event for which we're drawing the state
+ * @param rect
+ * Where to draw
+ * @param gc
+ * Graphics context
+ * @return true if the state was drawn
+ * @since 2.1
+ */
+ protected boolean drawArrow(TimeGraphColorScheme colors, ITimeEvent event,
+ Rectangle rect, GC gc) {
+
+ int colorIdx = fTimeGraphProvider.getStateTableIndex(event);
+ if (colorIdx < 0) {
+ return false;
+ }
+ boolean visible = ((rect.height == 0) && (rect.width == 0)) ? false : true;
+
+ if (visible) {
+ Color stateColor = null;
+ if (colorIdx < fEventColorMap.length) {
+ stateColor = fEventColorMap[colorIdx];
+ } else {
+ stateColor = Display.getDefault().getSystemColor(SWT.COLOR_BLACK);
+ }
+
+ gc.setForeground(stateColor);
+ gc.setBackground(stateColor);
+
+ /* Draw the arrow */
+ gc.drawLine(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
+ drawArrowHead(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height, gc);
+
+ }
+ fTimeGraphProvider.postDrawEvent(event, rect, gc);
+ return visible;
+ }
+
+ /*
+ * @author Francis Giraldeau
+ *
+ * Inspiration:
+ * http://stackoverflow.com/questions/3010803/draw-arrow-on-line-algorithm
+ *
+ * The algorithm was taken from this site, not the code itself
+ */
+ private static void drawArrowHead(int x0, int y0, int x1, int y1, GC gc)
+ {
+ int factor = 10;
+ double cos = 0.9510;
+ double sin = 0.3090;
+ int lenx = x1 - x0;
+ int leny = y1 - y0;
+ double len = Math.sqrt(lenx * lenx + leny * leny);
+
+ double dx = factor * lenx / len;
+ double dy = factor * leny / len;
+ int end1X = (int) Math.round((x1 - (dx * cos + dy * -sin)));
+ int end1Y = (int) Math.round((y1 - (dx * sin + dy * cos)));
+ int end2X = (int) Math.round((x1 - (dx * cos + dy * sin)));
+ int end2Y = (int) Math.round((y1 - (dx * -sin + dy * cos)));
+ int[] arrow = new int[] { x1, y1, end1X, end1Y, end2X, end2Y, x1, y1 };
+ gc.fillPolygon(arrow);
+ }
+
/**
* Draw the name of an item.
*
long time = getTimeAtX(x);
if (time >= 0) {
message.append("T: "); //$NON-NLS-1$
- message.append(new CtfTmfTimestamp(time).toString());
+ message.append(new TmfNanoTimestamp(time).toString());
message.append(" T1: "); //$NON-NLS-1$
if (fTimeProvider instanceof ITimeDataProvider2) {
long selectionBegin = ((ITimeDataProvider2) fTimeProvider).getSelectionBegin();
long selectionEnd = ((ITimeDataProvider2) fTimeProvider).getSelectionEnd();
- message.append(new CtfTmfTimestamp(Math.min(selectionBegin, selectionEnd)).toString());
+ message.append(new TmfNanoTimestamp(Math.min(selectionBegin, selectionEnd)).toString());
if (selectionBegin != selectionEnd) {
message.append(" T2: "); //$NON-NLS-1$
- message.append(new CtfTmfTimestamp(Math.max(selectionBegin, selectionEnd)).toString());
+ message.append(new TmfNanoTimestamp(Math.max(selectionBegin, selectionEnd)).toString());
message.append(" \u0394: "); //$NON-NLS-1$
message.append(new TmfTimestampDelta(Math.abs(selectionBegin - selectionEnd), ITmfTimestamp.NANOSECOND_SCALE));
}
} else {
@SuppressWarnings("deprecation")
long selectedTime = fTimeProvider.getSelectedTime();
- message.append(new CtfTmfTimestamp(selectedTime));
+ message.append(new TmfNanoTimestamp(selectedTime));
}
}
} else if (fDragState == DRAG_SELECTION || fDragState == DRAG_ZOOM) {
long time0 = fDragTime0;
long time = getTimeAtX(fDragX);
message.append("T1: "); //$NON-NLS-1$
- message.append(new CtfTmfTimestamp(Math.min(time, time0)).toString());
+ message.append(new TmfNanoTimestamp(Math.min(time, time0)).toString());
if (time != time0) {
message.append(" T2: "); //$NON-NLS-1$
- message.append(new CtfTmfTimestamp(Math.max(time, time0)).toString());
+ message.append(new TmfNanoTimestamp(Math.max(time, time0)).toString());
message.append(" \u0394: "); //$NON-NLS-1$
message.append(new TmfTimestampDelta(Math.abs(time - time0), ITmfTimestamp.NANOSECOND_SCALE));
}
private Item[] fExpandedItems = new Item[0];
private Item[] fItems = new Item[0];
private ITimeGraphEntry fTraces[] = new ITimeGraphEntry[0];
+ private List<ILinkEvent> fLinks = new ArrayList<ILinkEvent>();
private boolean fTraceFilter[] = new boolean[0];
private final ArrayList<ITimeGraphEntry> fFilteredOut = new ArrayList<ITimeGraphEntry>();
refreshData();
}
+ public void refreshArrows(List<ILinkEvent> events) {
+ /* If links are null, reset the list */
+ if (events != null) {
+ fLinks = events;
+ } else {
+ fLinks = new ArrayList<ILinkEvent>();
+ }
+ }
+
public ITimeGraphEntry[] getTraces() {
return fTraces;
}