eu.geclipse.traceview.physicalgraph.PhysicalGraphPaintListener.java Source code

Java tutorial

Introduction

Here is the source code for eu.geclipse.traceview.physicalgraph.PhysicalGraphPaintListener.java

Source

/*****************************************************************************
 * Copyright (c) 2006, 2008 g-Eclipse Consortium 
 * 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
 *
 * Initial development of the original code was made for the
 * g-Eclipse project founded by European Union
 * project number: FP6-IST-034327  http://www.geclipse.eu/
 *
 * Contributors:
 *    Andreas Roesch - initial implementation based on eu.geclipse.traceview.logicalgraph 
 *    Christof Klausecker - source code clean-up, adaptions, speed improvments, fixed drawing errors
 *    
 *****************************************************************************/

package eu.geclipse.traceview.physicalgraph;

import java.io.IOException;

import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.LineAttributes;

import eu.geclipse.traceview.EventType;
import eu.geclipse.traceview.IEvent;
import eu.geclipse.traceview.IEventMarker;
import eu.geclipse.traceview.IPhysicalEvent;
import eu.geclipse.traceview.IPhysicalProcess;
import eu.geclipse.traceview.IPhysicalTrace;
import eu.geclipse.traceview.IProcess;
import eu.geclipse.traceview.ITrace;
import eu.geclipse.traceview.internal.AbstractGraphPaintListener;
import eu.geclipse.traceview.internal.Activator;

class PhysicalGraphPaintListener extends AbstractGraphPaintListener {

    // constants
    private float hzoomfactor;
    private int vzoomfactor;
    private int maxTimeStop;
    private IPhysicalTrace trace;
    private int fromTime = 0;
    private int toTime = 0;
    private int xStep;
    private IEvent selectedEvent = null;
    private int arrowsize;
    private boolean drawMessages = true;

    PhysicalGraphPaintListener(final PhysicalGraph eventGraph) {
        super(eventGraph);
        this.hzoomfactor = 1;
        this.vzoomfactor = 1;
    }

    protected IEvent getSelectedEvent() {
        return this.selectedEvent;
    }

    protected void setSelectedEvent(final IEvent selectedEvent) {
        this.selectedEvent = selectedEvent;
    }

    protected float getHZoomfactor() {
        return this.hzoomfactor;
    }

    protected int getVZoomfactor() {
        return this.vzoomfactor;
    }

    protected boolean isDrawMessages() {
        return this.drawMessages;
    }

    protected void setDrawMessages(final boolean drawMessages) {
        this.drawMessages = drawMessages;
        this.eventGraph.redraw();
    }

    @Override
    public void handleResize() {
        correctScrollbar();
    }

    /**
     * Draws all the visible events and their send & receive connections
     * 
     * @throws IOException
     */
    private void drawGraph() {
        int rectangleHeight = 2 * this.vzoomfactor;
        // draw events from visible processes
        for (int i = 0; i < this.numProc; i++) {
            if (!procDrawingEnabled(i))
                continue;
            // calc vertical position
            int y = getYPosForProcId(i) - this.eventSize / 2;
            // get all visible events for the process
            IPhysicalProcess process = (IPhysicalProcess) (this.eventGraph.getTrace().getProcess(i));
            IPhysicalEvent[] events = process.getEventsByPhysicalClock(this.fromTime - 20, this.toTime);
            this.gc.setForeground(this.black);
            Color drawColor = null;
            Color fillColor = null;
            for (IPhysicalEvent event : events) {
                int x = getXPosForClock(event.getPhysicalStartClock());
                int rectangleWidth = getXPosForClock(event.getPhysicalStopClock()) - x;
                if (rectangleWidth > 1) {
                    for (IEventMarker eventmarker : this.eventGraph.getEventMarkers()) {
                        int mark = eventmarker.mark(event);
                        if (mark != 0) {
                            Color newFillColor = eventmarker.getBackgroundColor(mark);
                            Color newDrawColor = eventmarker.getForegroundColor(mark);
                            if (newFillColor != null)
                                fillColor = newFillColor;
                            if (newDrawColor != null)
                                drawColor = newDrawColor;
                        }
                        if (this.fastRedraw)
                            break;
                    }
                    //          if( drawColor != null )
                    this.gc.setForeground(drawColor);
                    //          if( fillColor != null )
                    this.gc.setBackground(fillColor);

                    if (fillColor != null) {
                        // fix for clipping problems -- TODO look into additional problems
                        if (x < 0)
                            this.gc.fillRectangle(0, y, x + rectangleWidth, rectangleHeight);
                        else
                            this.gc.fillRectangle(x, y, rectangleWidth, rectangleHeight);
                    }
                    if (rectangleWidth > 10 && rectangleHeight > this.fontsize + 2 && !this.fastRedraw) {
                        String name = event.getName();
                        if (name != null) {
                            int textWidth = this.gc.textExtent(name).x;
                            int textHeight = this.gc.textExtent(name).y;
                            if (textWidth < rectangleWidth) {
                                this.gc.drawText(name, x + rectangleWidth / 2 - textWidth / 2,
                                        y + rectangleHeight / 2 - textHeight / 2);
                            }
                        }
                    }
                    if (drawColor != null) {
                        // fix for clipping problems -- TODO look into additional problems
                        if (x < 0)
                            this.gc.drawRectangle(0, y, x + rectangleWidth, rectangleHeight);
                        else
                            this.gc.drawRectangle(x, y, rectangleWidth, rectangleHeight);
                    }
                } else {
                    this.gc.setForeground(this.black);
                    this.gc.drawLine(x, y, x, y + rectangleHeight);
                }
            }
        }
    }

    private void drawConnections() {
        this.arrowsize = this.vzoomfactor;
        if (this.arrowsize > 6) {
            this.arrowsize = 6;
        }
        for (int i = 0; i < this.numProc; i++) {
            IPhysicalEvent[] events = ((IPhysicalProcess) this.eventGraph.getTrace().getProcess(i))
                    .getEventsByPhysicalClock(this.fromTime, this.toTime);
            for (IPhysicalEvent event : events) {
                if (!event.getType().equals(EventType.SEND) && !event.getType().equals(EventType.RECV)) {
                    continue;
                }
                Color messageColor = null;
                for (IEventMarker marker : this.eventGraph.getEventMarkers()) {
                    if (marker.mark(event) != 0) {
                        Color newColor = marker.getMessageColor();
                        if (newColor != null)
                            messageColor = newColor;
                    }
                }
                if (messageColor != null) {
                    this.gc.setBackground(messageColor);
                    this.gc.setForeground(messageColor);
                    drawConnection(event);
                }
            }
        }
    }

    private void calculateXStep() {
        int to = this.fromTime + (int) (this.width / this.hzoomfactor);
        int mid = (to + this.fromTime) / 2;
        int midSize = this.gc.textExtent(Integer.toString(mid)).x + 20;
        this.xStep = (int) (midSize / this.hzoomfactor);
    }

    private void drawHRuler() {
        this.gc.setForeground(this.gc.getDevice().getSystemColor(SWT.COLOR_BLACK));
        this.gc.setFont(this.smallFont);
        int y = this.height - 22;
        this.gc.setClipping(31, this.height - 26, this.width - 31, 26);
        int from = this.fromTime / this.xStep * this.xStep;
        int to = this.toTime / this.xStep * this.xStep + (int) (this.width / this.hzoomfactor);
        for (int i = from; i <= to; i += this.xStep) {
            int x = getXPosForClock(i) - this.gc.textExtent(Integer.toString(i)).x / 2;
            this.gc.drawText(Integer.toString(i), x, y);
        }
    }

    private void drawGridVLines() {
        this.gc.setForeground(this.line1);
        int from = this.fromTime / this.xStep * this.xStep;
        int to = this.toTime / this.xStep * this.xStep + (int) (this.width / this.hzoomfactor);
        for (int i = from; i <= to; i += this.xStep) {
            int x = getXPosForClock(i);
            this.gc.drawLine(x, 1, x, this.height - 31);
        }
    }

    private void drawGraphBackground() {
        for (int i = 0; i < this.numProc; i++) {
            IPhysicalProcess process = (IPhysicalProcess) this.eventGraph.getTrace().getProcess(i);
            if (!procDrawingEnabled(process.getProcessId()))
                continue;
            IPhysicalEvent[] events = process.getEventsByPhysicalClock(this.fromTime - 20, this.toTime);
            for (IPhysicalEvent event : events) {
                Color color = null;
                IEventMarker lastMarker = null;
                for (IEventMarker eventmarker : this.eventGraph.getEventMarkers()) {
                    int mark = eventmarker.mark(event);
                    if (mark != IEventMarker.No_Mark) {
                        Color newColor = eventmarker.getCanvasBackgroundColor();
                        if (newColor != null) {
                            color = newColor;
                            lastMarker = eventmarker;
                        }
                    }
                    if (fastRedraw)
                        break;
                }
                if (color != null) {
                    int x = getXPosForClock(event.getPhysicalStartClock());
                    int bgWidth = getXPosForClock(event.getPhysicalStopClock()) - x;
                    IPhysicalEvent nextEvent = (IPhysicalEvent) event.getNextEvent();
                    if (nextEvent != null) {
                        if (lastMarker.mark(nextEvent) != IEventMarker.No_Mark
                                && color.equals(lastMarker.getCanvasBackgroundColor())) {
                            bgWidth += getXPosForClock(nextEvent.getPhysicalStartClock())
                                    - getXPosForClock(event.getPhysicalStopClock());
                        }
                    }
                    this.gc.setBackground(color);
                    int y = getYPosForProcId(event.getProcessId()) - this.vSpace / 2;
                    this.gc.fillRectangle(x, y, bgWidth, this.vSpace);
                }
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
     */
    public void paintControl(final PaintEvent e) {
        this.gc = e.gc;
        if (this.antialiasing) {
            this.gc.setAntialias(SWT.ON);
        }
        this.height = this.eventGraph.getClientArea().height - 1;
        this.width = this.eventGraph.getClientArea().width - 1;
        correctScrollbar();
        for (IEventMarker eventmarker : this.eventGraph.getEventMarkers()) {
            eventmarker.startMarking();
        }
        // draw controls
        drawBackground();
        // draw rest only if trace is available
        if (this.eventGraph.getTrace() != null) {
            // calculate visible events
            this.toTime = Math.min(this.maxTimeStop, (int) (this.fromTime + this.width / this.hzoomfactor));
            this.toProcessLine = Math.min(this.eventGraph.getLineToProcessMapping().size(),
                    this.fromProcessLine + (this.height - 31 + this.eventSize) / this.vSpace + 2);
            calculateXStep();
            drawVRuler(this.gc, -1);
            drawHRuler();
            // set the clipping to the graph area
            this.gc.setClipping(31, 1, this.width - 31, this.height - 31);
            // Draw background markers of events
            drawGraphBackground();
            drawGridHLines();
            drawGridVLines();
            drawSelection();
            drawGraph();
            if (this.drawMessages)
                drawConnections();
        }
    }

    void drawSelection() {
        ISelection selection = null;
        try {
            selection = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage()
                    .getActivePart().getSite().getSelectionProvider().getSelection();
        } catch (Exception e) {
            // ignore
        }
        if (selection != null && selection instanceof StructuredSelection) {
            StructuredSelection structuredSelection = (StructuredSelection) selection;
            for (Object obj : structuredSelection.toList()) {
                if (obj instanceof IPhysicalEvent) {
                    IPhysicalEvent event = (IPhysicalEvent) obj;
                    if (event.getProcess().getTrace() != this.trace)
                        continue;
                    if (procDrawingEnabled(event.getProcessId(), true)) {
                        if (this.fromTime <= event.getPhysicalStopClock()
                                || event.getPartnerPhysicalStartClock() <= this.toTime) {
                            int y = getYPosForProcId(event.getProcessId()) - this.eventSize / 2;
                            this.gc.setForeground(this.selectionColor);
                            this.gc.setBackground(this.selectionColor);
                            int x = getXPosForClock(event.getPhysicalStartClock());
                            int rectWidth = getXPosForClock(event.getPhysicalStopClock()) - x;
                            this.gc.fillRectangle(x - 2, y - 2, rectWidth + 5, 2 * this.vzoomfactor + 5);
                        }
                    }
                } else if (obj instanceof IProcess) {
                    IProcess process = (IProcess) obj;
                    if (process.getTrace() != this.trace)
                        continue;
                    if (procDrawingEnabled(process.getProcessId(), true)) {
                        int x = 0;
                        int y = getYPosForProcId(process.getProcessId()) - this.eventSize / 2;
                        this.gc.setForeground(this.selectionColor);
                        this.gc.setBackground(this.selectionColor);
                        this.gc.fillRectangle(x, y + this.eventSize / 4, this.width, this.eventSize / 2);
                    }
                }
            }
        }
    }

    private void correctScrollbar() {
        int max = (int) (this.maxTimeStop * this.hzoomfactor - this.width + 250) / 10;
        if (max < 1) {
            this.horizontalScrollBar.setMaximum(1);
            this.fromTime = 0;
        } else {
            this.horizontalScrollBar.setMaximum(max);
        }
        this.verticalScrollBar.setMaximum(this.vSpace * this.numProc);
    }

    /**
     * @param selection
     */
    @Override
    public void setHorizontal(final int selection) {
        this.fromTime = (int) (selection / this.hzoomfactor) * 10;
    }

    /**
     * @return clockdiff
     */
    public int getDiff() {
        return this.toTime - this.fromTime;
    }

    @Override
    public void setTrace(final ITrace trace) {
        this.trace = (IPhysicalTrace) trace;
        if (this.trace != null) {
            this.maxTimeStop = this.trace.getMaximumPhysicalClock();
            this.numProc = this.trace.getNumberOfProcesses();
        }
    }

    void updateMaxTimeStop() {
        this.maxTimeStop = this.trace.getMaximumPhysicalClock();
        correctScrollbar();
    }

    protected int getNumProc() {
        return this.numProc;
    }

    protected int getMaxTimeStop() {
        return this.maxTimeStop;
    }

    protected void setZoomfactor(final int zoomfactor) {
        this.hSpace = 6 * zoomfactor;
        this.vSpace = 6 * zoomfactor;
        this.eventSize = 2 * zoomfactor;
        // this.zoomfactor = zoomfactor;
        // adapt ScrollBar
        correctScrollbar();
        this.horizontalScrollBar.setPageIncrement(this.hSpace);
        this.verticalScrollBar.setPageIncrement(this.vSpace);
    }

    protected void setHZoomfactor(final float zoomfactor) {
        this.hSpace = (int) (6 * zoomfactor);
        if (this.hSpace < 1)
            this.hSpace = 1;
        this.hzoomfactor = zoomfactor;
    }

    protected void setVZoomfactor(final int zoomfactor) {
        this.vSpace = 6 * zoomfactor;
        if (this.vSpace < 12)
            this.vSpace = 12;
        this.eventSize = 2 * zoomfactor;
        this.vzoomfactor = zoomfactor;
        correctScrollbar();
        this.verticalScrollBar.setPageIncrement(this.vSpace);
    }

    protected void setNumProc(final int numProc) {
        this.numProc = numProc;
    }

    @Override
    public void print(final GC gc2) {
        this.gc = gc2;
        this.gc.setLineAttributes(new LineAttributes(1));
        calculateXStep();
        drawVRuler(this.gc, -1);
        drawHRuler();
        // set the clipping to the graph area
        this.gc.setClipping(31, 1, this.width - 31, this.height - 31);
        drawGraphBackground();
        drawGridHLines();
        drawGridVLines();
        drawSelection();
        drawGraph();
        if (this.drawMessages)
            drawConnections();
    }

    @Override
    public int getArrowSize() {
        return this.arrowsize;
    }

    void drawConnection(IPhysicalEvent event) {
        if (event.getPartnerProcessId() != -1 && procDrawingEnabled(event.getProcessId())
                && procDrawingEnabled(event.getPartnerProcessId())) {
            int x1 = getXPosForClock(event.getPhysicalStopClock());
            int y1 = getYPosForProcId(event.getProcessId());
            int x2 = getXPosForClock(event.getPartnerPhysicalStopClock());
            int y2 = getYPosForProcId(event.getPartnerProcessId());
            if (y1 == y2)
                return;
            if (event.getType() == EventType.SEND) {
                connection(x1, y1, x2, y2, false);
            } else {
                connection(x2, y2, x1, y1, false);
            }
        }
    }

    private int getXPosForClock(int physicalClock) {
        return (int) (50 + (physicalClock - this.fromTime) * this.hzoomfactor);
    }
}