use of org.eclipse.tracecompass.internal.tmf.ui.widgets.timegraph.TimeGraphRender.PostDrawEvent in project tracecompass by tracecompass.
the class TimeGraphControl method paint.
@Override
void paint(Rectangle bounds, PaintEvent e) {
try (ScopeLog sl = new ScopeLog(LOGGER, Level.FINE, fPaintScopeLabel)) {
GC gc = e.gc;
fPostDrawEntries.clear();
fPostDrawArrows.clear();
fLines.clear();
fPoints.clear();
fSelectedRectangles.clear();
if (bounds.width < 2 || bounds.height < 2 || null == fTimeProvider) {
return;
}
fIdealNameSpace = 0;
int nameSpace = fTimeProvider.getNameSpace();
try (ScopeLog bgScope = new ScopeLog(LOGGER, Level.FINEST, fBackgroundScopeLabel)) {
// draw the background layer
drawBackground(bounds, nameSpace, gc);
}
try (ScopeLog glScope = new ScopeLog(LOGGER, Level.FINEST, fGridLinesScopeLabel)) {
// draw the grid lines
drawGridLines(bounds, gc);
}
try (ScopeLog bgmScope = new ScopeLog(LOGGER, Level.FINEST, fBgmScopeLabel)) {
// draw the background markers
drawMarkers(bounds, fTimeProvider, fMarkers, false, nameSpace, gc);
}
try (ScopeLog itemsScope = new ScopeLog(LOGGER, Level.FINEST, fItemsScopeLabel)) {
// draw the items
drawItems(bounds, fTimeProvider, fItemData.fExpandedItems, fTopIndex, nameSpace, gc);
}
try (ScopeLog markerScope = new ScopeLog(LOGGER, Level.FINEST, fMarkersScopeLabel)) {
// draw the foreground markers
drawMarkers(bounds, fTimeProvider, fMarkers, true, nameSpace, gc);
}
try (ScopeLog linksScope = new ScopeLog(LOGGER, Level.FINEST, fLinksScopeLabel)) {
// draw the links (arrows)
drawLinks(bounds, fTimeProvider, fItemData.fLinks, nameSpace, gc);
}
gc.setAlpha(OPAQUE * 2 / 5);
long time0 = fTimeProvider.getTime0();
long time1 = fTimeProvider.getTime1();
long selectionBegin = fTimeProvider.getSelectionBegin();
long selectionEnd = fTimeProvider.getSelectionEnd();
double pixelsPerNanoSec = (bounds.width - nameSpace <= RIGHT_MARGIN) ? 0 : (double) (bounds.width - nameSpace - RIGHT_MARGIN) / (time1 - time0);
int x0 = SaturatedArithmetic.add(bounds.x + nameSpace, (int) ((selectionBegin - time0) * pixelsPerNanoSec));
int x1 = SaturatedArithmetic.add(bounds.x + nameSpace, (int) ((selectionEnd - time0) * pixelsPerNanoSec));
// draw selection lines
if (fDragState != DRAG_SELECTION) {
gc.setForeground(getColorScheme().getColor(TimeGraphColorScheme.SELECTED_TIME));
if (x0 >= nameSpace && x0 < bounds.x + bounds.width) {
gc.drawLine(x0, bounds.y, x0, bounds.y + bounds.height);
}
if (x1 != x0) {
if (x1 >= nameSpace && x1 < bounds.x + bounds.width) {
gc.drawLine(x1, bounds.y, x1, bounds.y + bounds.height);
}
}
}
// draw selection background
if (selectionBegin != 0 && selectionEnd != 0 && fDragState != DRAG_SELECTION) {
x0 = Math.max(nameSpace, Math.min(bounds.x + bounds.width, x0));
x1 = Math.max(nameSpace, Math.min(bounds.x + bounds.width, x1));
gc.setBackground(getColorScheme().getBkColor(false, false, true));
if (x1 - x0 > 1) {
gc.fillRectangle(new Rectangle(x0 + 1, bounds.y, x1 - x0 - 1, bounds.height));
} else if (x0 - x1 > 1) {
gc.fillRectangle(new Rectangle(x1 + 1, bounds.y, x0 - x1 - 1, bounds.height));
}
}
// draw drag selection background
if (fDragState == DRAG_ZOOM || fDragState == DRAG_SELECTION) {
gc.setBackground(getColorScheme().getBkColor(false, false, true));
if (fDragX0 < fDragX) {
gc.fillRectangle(new Rectangle(fDragX0, bounds.y, fDragX - fDragX0, bounds.height));
} else if (fDragX0 > fDragX) {
gc.fillRectangle(new Rectangle(fDragX, bounds.y, fDragX0 - fDragX, bounds.height));
}
}
// draw split line
if (DRAG_SPLIT_LINE == fDragState || (DRAG_NONE == fDragState && fMouseOverSplitLine && fTimeProvider.getNameSpace() > 0)) {
gc.setBackground(getColorScheme().getColor(TimeGraphColorScheme.DARK_GRAY));
} else {
gc.setBackground(getColorScheme().getColor(TimeGraphColorScheme.GRAY));
}
gc.fillRectangle(bounds.x + nameSpace - SNAP_WIDTH, bounds.y, SNAP_WIDTH, bounds.height);
if (DRAG_ZOOM == fDragState && Math.max(fDragX, fDragX0) > nameSpace) {
gc.setForeground(getColorScheme().getColor(TimeGraphColorScheme.TOOL_FOREGROUND));
gc.drawLine(fDragX0, bounds.y, fDragX0, bounds.y + bounds.height - 1);
if (fDragX != fDragX0) {
gc.drawLine(fDragX, bounds.y, fDragX, bounds.y + bounds.height - 1);
}
} else if (DRAG_SELECTION == fDragState && Math.max(fDragX, fDragX0) > nameSpace) {
gc.setForeground(getColorScheme().getColor(TimeGraphColorScheme.SELECTED_TIME));
gc.drawLine(fDragX0, bounds.y, fDragX0, bounds.y + bounds.height - 1);
if (fDragX != fDragX0) {
gc.drawLine(fDragX, bounds.y, fDragX, bounds.y + bounds.height - 1);
}
}
gc.setAlpha(OPAQUE);
for (PostDrawEvent postDrawEvent : fPostDrawArrows) {
postDrawEvent.draw(fTimeGraphProvider, gc);
}
fPostDrawEntries.clear();
fPostDrawArrows.clear();
fTimeGraphProvider.postDrawControl(bounds, gc);
}
}
use of org.eclipse.tracecompass.internal.tmf.ui.widgets.timegraph.TimeGraphRender.PostDrawEvent in project tracecompass by tracecompass.
the class TimeGraphControl method drawArrow.
/**
* Draw an arrow
*
* @param colors
* Color scheme
* @param event
* Time event for which we're drawing the arrow
* @param rect
* The arrow rectangle
* @param gc
* Graphics context
* @return true if the arrow was drawn
*/
protected boolean drawArrow(TimeGraphColorScheme colors, @NonNull ITimeEvent event, Rectangle rect, GC gc) {
if (rect == null || ((rect.height == 0) && (rect.width == 0))) {
return false;
}
StyleManager styleManager = getStyleManager();
OutputElementStyle elementStyle = getElementStyle(event);
if (elementStyle == null) {
return false;
}
RGBAColor rgba = styleManager.getColorStyle(elementStyle, StyleProperties.COLOR);
rgba = (rgba != null) ? rgba : BLACK;
int colorInt = rgba.toInt();
Color color = TimeGraphRender.getColor(colorInt);
int alpha = rgba.getAlpha();
int prevAlpha = gc.getAlpha();
gc.setAlpha(alpha);
gc.setForeground(color);
gc.setBackground(color);
int old = gc.getLineWidth();
Float widthFactor = styleManager.getFactorStyle(elementStyle, StyleProperties.WIDTH);
if (widthFactor == null) {
Float heightFactor = styleManager.getFactorStyle(elementStyle, StyleProperties.HEIGHT);
widthFactor = (heightFactor != null) ? heightFactor * 10.0f : 1.0f;
}
widthFactor = Math.max(1.0f, Math.min(10.0f, widthFactor));
gc.setLineWidth(widthFactor.intValue());
/* Draw the arrow */
Point newEndpoint = drawArrowHead(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height, widthFactor, gc);
gc.drawLine(rect.x, rect.y, newEndpoint.x, newEndpoint.y);
gc.setLineWidth(old);
gc.setAlpha(prevAlpha);
if (!Boolean.TRUE.equals(styleManager.getStyle(elementStyle, ITimeEventStyleStrings.annotated()))) {
fPostDrawArrows.add(new PostDrawEvent(event, rect));
}
return true;
}
use of org.eclipse.tracecompass.internal.tmf.ui.widgets.timegraph.TimeGraphRender.PostDrawEvent in project tracecompass by tracecompass.
the class TimeGraphControl method drawState.
/**
* Draw the state (color fill)
*
* @param colors
* Color scheme
* @param event
* Time event for which we're drawing the state
* @param rect
* The state rectangle
* @param gc
* Graphics context
* @param selected
* Is this time event currently selected (so it appears
* highlighted)
* @param timeSelected
* Is the timestamp currently selected
* @return true if the state was drawn
*/
protected boolean drawState(TimeGraphColorScheme colors, @NonNull ITimeEvent event, Rectangle rect, GC gc, boolean selected, boolean timeSelected) {
StyleManager styleManager = getStyleManager();
OutputElementStyle elementStyle = getElementStyle(event);
if (elementStyle == null) {
return false;
}
boolean transparent = elementStyle.getParentKey() == null && elementStyle.getStyleValues().isEmpty();
boolean visible = rect.width <= 0 ? false : true;
rect.width = Math.max(1, rect.width);
Float heightFactor = styleManager.getFactorStyle(elementStyle, StyleProperties.HEIGHT);
heightFactor = (heightFactor != null) ? Math.max(0.0f, Math.min(1.0f, heightFactor)) : DEFAULT_STATE_WIDTH;
int height = 0;
if (heightFactor != 0.0f && rect.height != 0) {
height = Math.max(1, (int) (rect.height * heightFactor));
}
Rectangle drawRect = new Rectangle(rect.x, rect.y + ((rect.height - height) / 2), rect.width, height);
Color black = TimeGraphRender.getColor(BLACK.toInt());
gc.setForeground(black);
List<DeferredItem> states = fCurrentDeferredEntry.getItems();
if (transparent) {
if (visible) {
// Avoid overlapping transparent states
int x = Math.max(fLastTransparentX, drawRect.x);
drawRect.width = drawRect.x + drawRect.width - x;
if (drawRect.width > 0) {
// Draw transparent background
RGBAColor bgColor = fTransparentGrayColor;
DeferredItem deferredItem = new DeferredTransparentState(drawRect, bgColor);
if (states.isEmpty() || !states.get(states.size() - 1).getBounds().intersects(drawRect)) {
states.add(deferredItem);
deferredItem.add(new PostDrawEvent(event, drawRect));
}
fLastTransparentX = Math.max(fLastTransparentX, drawRect.x + drawRect.width);
} else {
// clamp it to 0, just in case
drawRect.width = 0;
}
if (drawRect.width <= 2) {
// Draw point over state
addPoint(fPoints, rect.x, rect.y - 2);
if (drawRect.width == 2) {
addPoint(fPoints, rect.x + 1, rect.y - 2);
}
}
} else {
addPoint(fPoints, rect.x, rect.y - 2);
}
return false;
}
int arc = Math.min(drawRect.height + 1, drawRect.width) / 2;
RGBAColor rgba = styleManager.getColorStyle(elementStyle, StyleProperties.BACKGROUND_COLOR);
@NonNull RGBAColor bgColor = (rgba != null) ? rgba : BLACK;
boolean reallySelected = timeSelected && selected;
// fill all rect area
boolean draw = visible || fBlendSubPixelEvents;
DeferredItem last = null;
if (draw) {
if (!states.isEmpty()) {
DeferredItem state = states.get(states.size() - 1);
while ((state instanceof DeferredTransparentState) && (state.getBounds().x == drawRect.x)) {
states.remove(states.size() - 1);
state = states.isEmpty() ? null : states.get(states.size() - 1);
}
}
RGBAColor borderColor = BLACK;
int lineWidth = DeferredItem.NO_BORDER;
Object borderStyle = styleManager.getStyle(elementStyle, StyleProperties.BORDER_STYLE);
boolean hasBorders = borderStyle != null && !BorderStyle.NONE.equals(borderStyle);
if (hasBorders) {
Object borderWidth = styleManager.getStyle(elementStyle, StyleProperties.BORDER_WIDTH);
lineWidth = 1;
if (borderWidth instanceof Integer) {
lineWidth = (int) borderWidth;
}
borderColor = styleManager.getColorStyle(elementStyle, StyleProperties.BORDER_COLOR);
if (borderColor == null) {
borderColor = BLACK;
}
}
/*
* This has been tested in Linux and Windows, results may vary. The
* rounded rectangle is not noticeable for adjacent states of the
* same color until width=6 (arc=3) with antialiasing, or width=8
* (arc=4) without antialiasing.
*
* In other words, only draw rounded rectangles if the arc is
* noticeable.
*/
if (arc >= 2) {
last = new DeferredState(drawRect, bgColor, Objects.requireNonNull(borderColor), arc, lineWidth, fLabelsVisible ? event.getLabel() : null);
states.add(last);
} else {
DeferredTinyState tinyCandidate = new DeferredTinyState(drawRect, bgColor, Objects.requireNonNull(borderColor), lineWidth);
boolean skipState = false;
if (!states.isEmpty()) {
DeferredItem prev = states.get(states.size() - 1);
if (prev instanceof DeferredTinyState) {
DeferredTinyState tinyState = (DeferredTinyState) prev;
if (fBlendSubPixelEvents) {
skipState = tinyState.squash(tinyCandidate);
} else if (tinyState.extend(tinyCandidate)) {
skipState = true;
}
}
}
if (!skipState) {
states.add(tinyCandidate);
}
last = tinyCandidate;
}
}
if (reallySelected) {
fSelectedRectangles.add(drawRect);
}
if (!visible) {
addPoint(fPoints, rect.x, rect.y - 2);
}
if (visible && !Boolean.TRUE.equals(styleManager.getStyle(elementStyle, ITimeEventStyleStrings.annotated())) && last != null) {
last.add(new PostDrawEvent(event, drawRect));
}
return visible && !event.isPropertyActive(IFilterProperty.DIMMED);
}
Aggregations