Java tutorial
/***************************************************************************** * 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: * Christof Klausecker GUP, JKU - initial API and implementation *****************************************************************************/ package eu.geclipse.traceview.logicalgraph; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; 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.IEventMarker; import eu.geclipse.traceview.ILamportEvent; import eu.geclipse.traceview.ILamportProcess; import eu.geclipse.traceview.ILamportTrace; import eu.geclipse.traceview.IProcess; import eu.geclipse.traceview.ITrace; import eu.geclipse.traceview.internal.AbstractGraphPaintListener; import eu.geclipse.traceview.internal.Activator; import eu.geclipse.traceview.internal.LineType; class LogicalGraphPaintListener extends AbstractGraphPaintListener { // size private int zoomfactor; private int xOffset; // visible private int fromClock = 0; private int toClock = 0; private int maxLamport; private ILamportTrace trace; private boolean scrollBarsInitialized = false; LogicalGraphPaintListener(final LogicalGraph eventGraph) { super(eventGraph); this.zoomfactor = 1; } protected int getZoomfactor() { return this.zoomfactor; } @Override public void handleResize() { setScrollBarSizes(); } protected void setScrollBarSizes() { int clockDiff = Math.min((int) ((this.maxLamport + 1.5 - this.fromClock) * this.hSpace), this.width - 31 + this.eventSize); int processDiff = Math.min((int) ((this.numProc - this.fromProcessLine + 0.5) * this.hSpace), this.height - 31 + this.eventSize); if (this.horizontalScrollBar != null) { int selection = this.horizontalScrollBar.getSelection(); this.horizontalScrollBar.setValues(selection, 0, (int) (this.hSpace * (this.maxLamport + 1.5)), clockDiff, 1, this.hSpace); } if (this.verticalScrollBar != null) { int selection = this.verticalScrollBar.getSelection(); this.verticalScrollBar.setValues(selection, 0, (int) (this.vSpace * (this.numProc + 0.5)), processDiff, 1, this.vSpace); } } /** * Draws the messages of the currently invisible events (left, right, top, * bottom) */ private void drawLeftRightTopBottom() { // draw only last couple of events int from = Math.max(this.fromClock - 100, 0); // left // for all processes for (int i = 0; i < this.numProc; i++) { ILamportEvent[] events = ((ILamportProcess) this.eventGraph.getTrace().getProcess(i)) .getEventsByLamportClock(from, this.fromClock - 1); for (ILamportEvent event : events) { // only draw send messages and only the ones which could visible if (event.getType() == EventType.SEND && event.getPartnerLamportClock() >= this.fromClock) { Color messageColor = null; for (IEventMarker eventmarker : this.eventGraph.getEventMarkers()) { if (eventmarker.mark(event) != 0) { Color newColor = eventmarker.getMessageColor(); if (newColor != null) messageColor = newColor; } } if (messageColor != null) { this.gc.setBackground(messageColor); this.gc.setForeground(messageColor); drawConnection(event); } } } } // top // for all processes till the first visible one /* for( int i = 0; i < this.fromProcessLine; i++ ) { ILamportEvent[] events = ( ( ILamportProcess )this.eventGraph.getTrace() .getProcess( i ) ).getEventsByLamportClock( this.fromClock, this.toClock ); for( ILamportEvent event : events ) { // only draw send messages and only the ones which could visible // TODO problems with broadcast if( event.getType() == EventType.SEND && event.getPartnerProcessId() >= this.fromProcessLine ) { drawConnection( event ); } } } // bottom // for all processes from the last visible one for( int i = this.toProcessLine; i < this.numProc; i++ ) { ILamportEvent[] events = ( ( ILamportProcess )this.eventGraph.getTrace() .getProcess( i ) ).getEventsByLamportClock( this.fromClock, this.toClock ); for( ILamportEvent event : events ) { // only messages which could be visible if( event.getType() == EventType.SEND && event.getPartnerProcessId() < this.toProcessLine ) { drawConnection( event ); } } }*/ // TODO right - because of broadcasts } private void drawGraphBackground(final int procId, final ILamportEvent[] events) { if (!procDrawingEnabled(procId)) return; for (ILamportEvent 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 (color != null) { int bgWidth = this.hSpace; ILamportEvent nextEvent = (ILamportEvent) event.getNextEvent(); if (nextEvent != null) { if (lastMarker != null && lastMarker.mark(nextEvent) != IEventMarker.No_Mark && color.equals(lastMarker.getCanvasBackgroundColor())) { bgWidth *= (nextEvent.getLamportClock() - event.getLamportClock()); } } this.gc.setBackground(color); int x = getXPosForClock(event.getLamportClock()) - this.hSpace / 2; int y = getYPosForProcId(event.getProcessId()) - this.vSpace / 2; this.gc.fillRectangle(x, y, bgWidth, this.vSpace); } } } /** * Draws all the visible events and their send & receive connections * @param events * @param i */ private void drawGraph(final int i, final ILamportEvent[] events) { try { if (!procDrawingEnabled(i)) return; for (ILamportEvent event : events) { int x = getXPosForClock(event.getLamportClock()) - this.eventSize / 2; int y = getYPosForProcId(event.getProcessId()) - this.eventSize / 2; // draw event drawEvent(event, x, y); if (event.getType() == EventType.SEND || event.getType() == EventType.RECV) { // this.gc.setLineWidth( 0 ); // printing workaround this.gc.setLineStyle(SWT.LINE_SOLID); // set connections color Color messageColor = null; for (IEventMarker eventmarker : this.eventGraph.getEventMarkers()) { if (eventmarker.mark(event) != 0) { Color newColor = eventmarker.getMessageColor(); if (newColor != null) messageColor = newColor; } if (this.fastRedraw) break; } if (messageColor != null) { this.gc.setBackground(messageColor); this.gc.setForeground(messageColor); drawConnection(event); } } } } catch (Exception exception) { Activator.logException(exception); } } void drawEvent(final ILamportEvent event, final int x, final int y) { final int[] markTypes = { IEventMarker.Diamond_Event, IEventMarker.Triangle_Event, IEventMarker.Ellipse_Event, IEventMarker.Rectangle_Event, IEventMarker.Cross_Event }; for (IEventMarker eventmarker : this.eventGraph.getEventMarkers()) { int mark; if (this.fastRedraw) mark = IEventMarker.Rectangle_Event; else mark = eventmarker.mark(event); if ((mark & 63) != 0) { int markType = 0; for (int i = 0; i < markTypes.length; i++) { markType = markTypes[i]; if ((mark & markType) != 0) break; } int[] poly = null; this.gc.setLineStyle(eventmarker.getLineStyle(markType)); // this.gc.setLineWidth( eventmarker.getLineWidth( markType ) ); // printing workaround if (markType == IEventMarker.Diamond_Event) { poly = new int[] { x + this.eventSize / 2, y, x, y + this.eventSize / 2, x + this.eventSize / 2, y + this.eventSize, x + this.eventSize, y + this.eventSize / 2, x + this.eventSize / 2, y }; } else if (markType == IEventMarker.Triangle_Event) { poly = new int[] { x + this.eventSize / 2, y, x, y + this.eventSize, x + this.eventSize, y + this.eventSize, x + this.eventSize / 2, y }; } Color color; if (this.fastRedraw) color = null; else color = eventmarker.getBackgroundColor(markType); if (color != null) { this.gc.setBackground(color); if (poly != null) this.gc.fillPolygon(poly); else if (markType == IEventMarker.Ellipse_Event) this.gc.fillOval(x, y, this.eventSize, this.eventSize); else if (markType == IEventMarker.Rectangle_Event) this.gc.fillRectangle(x, y, this.eventSize, this.eventSize); } color = eventmarker.getForegroundColor(markType); if (color != null) { int lineOffset = 0; // (int) (2*gc.getLineWidth()); // printing workaround int x2 = x - lineOffset; int y2 = y - lineOffset; this.gc.setForeground(color); if (poly != null) this.gc.drawPolygon(poly); else if (markType == IEventMarker.Ellipse_Event) this.gc.drawOval(x2, y2, this.eventSize, this.eventSize); else if (markType == IEventMarker.Rectangle_Event) this.gc.drawRectangle(x2, y2, this.eventSize, this.eventSize); else if (markType == IEventMarker.Cross_Event) { this.gc.drawLine(x2, y2, x2 + this.eventSize, y2 + this.eventSize); this.gc.drawLine(x2, y2 + this.eventSize, x2 + this.eventSize, y); } } } if (this.fastRedraw) break; } } 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); for (int i = this.fromClock; i <= this.toClock; i++) { int x = getXPosForClock(i); if (i % 10 == 0) { this.gc.drawLine(x, y, x, y + 7); } else if (i % 5 == 0) { this.gc.drawLine(x, y, x, y + 5); } else { this.gc.drawLine(x, y, x, y + 3); } if (this.zoomfactor > 6) { this.gc.drawText(Integer.toString(i), x - this.gc.textExtent(Integer.toString(i)).x / 2, y + 9); } else if (this.zoomfactor > 3 && i % 2 == 0) { this.gc.drawText(Integer.toString(i), x - this.gc.textExtent(Integer.toString(i)).x / 2, y + 9); } else if (i % 5 == 0 && this.zoomfactor < 4 && this.zoomfactor > 1) { this.gc.drawText(Integer.toString(i), x - this.gc.textExtent(Integer.toString(i)).x / 2, y + 9); } else if (i % 10 == 0 && this.zoomfactor == 1) { this.gc.drawText(Integer.toString(i), x - this.gc.textExtent(Integer.toString(i)).x / 2, y + 9); } } } private void drawGridVLines() { this.gc.setForeground(this.line1); LineType vLines = this.eventGraph.getVLines(); if (vLines != LineType.Lines_None) { if (this.fastRedraw) vLines = LineType.Lines_10; for (int i = this.fromClock; i <= this.toClock; i++) { int x = getXPosForClock(i); if (i % 10 == 0) { this.gc.setForeground(this.line10); this.gc.drawLine(x, 1, x, this.height - 31); this.gc.setForeground(this.line1); } else if ((vLines == LineType.Lines_5 || vLines == LineType.Lines_1) && i % 5 == 0) { this.gc.setForeground(this.line5); this.gc.drawLine(x, 1, x, this.height - 31); this.gc.setForeground(this.line1); } else if (vLines == LineType.Lines_1) { this.gc.drawLine(x, 1, x, this.height - 31); } } } } /* * (non-Javadoc) * * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent) */ public void paintControl(final PaintEvent e) { this.gc = e.gc; long drawStartTime = 0; if (this.fastRedraw) { if (this.fullRedrawDuration < 100) this.fastRedraw = false; } if (!this.fastRedraw) { drawStartTime = System.currentTimeMillis(); } if (this.antialiasing && !this.fastRedraw) { this.gc.setAntialias(SWT.ON); } this.height = this.eventGraph.getClientArea().height - 1; this.width = this.eventGraph.getClientArea().width - 1; 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.toClock = Math.min(this.maxLamport, this.fromClock + (this.width - 31 + this.eventSize) / this.hSpace + 2); this.toProcessLine = Math.min(this.eventGraph.getLineToProcessMapping().size(), this.fromProcessLine + (this.height - 31 + this.eventSize) / this.vSpace + 2); // draw the rulers to the control drawVRuler(this.gc, -1); drawHRuler(); // set the clipping to the graph area this.gc.setClipping(31, 1, this.width - 31, this.height - 31); // this.gc.setClipping(0, 0, this.width, this.height); ILamportEvent[][] events = new ILamportEvent[this.trace.getNumberOfProcesses()][]; for (int i = 0; i < this.numProc; i++) { ILamportProcess process = (ILamportProcess) this.eventGraph.getTrace().getProcess(i); events[i] = process.getEventsByLamportClock(this.fromClock, true, this.toClock, false); // Draw background markers of events if (!this.fastRedraw) drawGraphBackground(i, events[i]); } // draw the grid drawGridHLines(); drawGridVLines(); // draw selection drawSelection(); // draw the graph for (int i = 0; i < this.numProc; i++) { drawGraph(i, events[i]); } this.gc.setLineStyle(SWT.LINE_SOLID); this.gc.setLineWidth(0); // draw the additional messages if (!this.fastRedraw) drawLeftRightTopBottom(); if (!this.scrollBarsInitialized) { setScrollBarSizes(); this.scrollBarsInitialized = true; } } if (!this.fastRedraw) { long drawEndTime = System.currentTimeMillis(); this.fullRedrawDuration = drawEndTime - drawStartTime; } this.fastRedraw = false; } void drawSelection() { ISelection selection = null; try { ISelectionProvider provider = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow() .getActivePage().getActivePart().getSite().getSelectionProvider(); if (provider != null) { selection = provider.getSelection(); } } catch (Exception e) { // ignore } if (selection != null && selection instanceof StructuredSelection) { StructuredSelection structuredSelection = (StructuredSelection) selection; for (Object obj : structuredSelection.toList()) { if (obj instanceof ILamportEvent) { ILamportEvent event = (ILamportEvent) obj; if (event.getProcess().getTrace() != this.trace) continue; if (this.fromClock <= event.getLamportClock() && event.getLamportClock() <= this.toClock) { if (procDrawingEnabled(event.getProcessId(), true)) { int x = getXPosForClock(event.getLamportClock()) - this.eventSize / 2; int y = getYPosForProcId(event.getProcessId()) - this.eventSize / 2; this.gc.setForeground(this.selectionColor); this.gc.setBackground(this.selectionColor); this.gc.fillOval(x - this.eventSize / 4, y - this.eventSize / 4, this.eventSize + this.eventSize / 2, this.eventSize + this.eventSize / 2); } } } 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); } } } } } /** * @param selection */ @Override public void setHorizontal(final int selection) { this.fromClock = selection / this.hSpace; this.xOffset = selection % this.hSpace - this.hSpace / 2; } /** * @return clockdiff */ public int getDiff() { return this.toClock - this.fromClock; } @Override public void setTrace(final ITrace trace) { this.trace = (ILamportTrace) trace; if (this.trace != null) { this.maxLamport = this.trace.getMaximumLamportClock(); this.numProc = this.trace.getNumberOfProcesses(); this.setHorizontal(0); this.setVertical(0); this.scrollBarsInitialized = false; } } protected void setZoomfactor(final int zoomfactor) { int hsel = this.horizontalScrollBar.getSelection() / this.zoomfactor; int vsel = this.verticalScrollBar.getSelection() / this.zoomfactor; int hValue = this.horizontalScrollBar.getSelection() / this.hSpace; int vValue = this.verticalScrollBar.getSelection() / this.vSpace; this.hSpace = 6 * zoomfactor; this.vSpace = 6 * zoomfactor; this.eventSize = 2 * zoomfactor; this.zoomfactor = zoomfactor; hsel = hsel * this.zoomfactor; vsel = vsel * this.zoomfactor; this.horizontalScrollBar.setSelection(hValue * this.hSpace); this.verticalScrollBar.setSelection(vValue * this.vSpace); setScrollBarSizes(); setHorizontal(hsel); setVertical(vsel); } @Override public void print(final GC gc2) { this.gc = gc2; this.gc.setLineAttributes(new LineAttributes(1)); drawVRuler(this.gc, -1); drawHRuler(); this.gc.setClipping(31, 1, this.width - 31, this.height - 31); ILamportEvent[][] events = new ILamportEvent[this.trace.getNumberOfProcesses()][]; for (int i = 0; i < this.numProc; i++) { ILamportProcess process = (ILamportProcess) this.eventGraph.getTrace().getProcess(i); events[i] = process.getEventsByLamportClock(this.fromClock, true, this.toClock, false); // Draw background markers of events if (!this.fastRedraw) drawGraphBackground(i, events[i]); } drawGridHLines(); drawGridVLines(); for (int i = 0; i < this.numProc; i++) { drawGraph(i, events[i]); } } @Override public int getArrowSize() { return this.eventSize / 2; } private int getXPosForClock(final int lamportClock) { return (lamportClock - this.fromClock) * this.hSpace + 30 - this.xOffset + this.eventSize / 2; } void drawConnection(final ILamportEvent event) { if (event.getPartnerProcessId() != -1 && procDrawingEnabled(event.getProcessId()) && procDrawingEnabled(event.getPartnerProcessId())) { int x1 = getXPosForClock(event.getLamportClock()); int y1 = getYPosForProcId(event.getProcessId()); int x2 = getXPosForClock(event.getPartnerLamportClock()); int y2 = getYPosForProcId(event.getPartnerProcessId()); if (y1 == y2) return; int lineOffset = 0; // (int) (2*gc.getLineWidth()); // printing workaround x1 -= lineOffset; x2 -= lineOffset; y1 -= lineOffset; y2 -= lineOffset; if (event.getType() == EventType.SEND) { connection(x1, y1, x2, y2, true); } else { if (!this.fastRedraw) connection(x2, y2, x1, y1, true); } } } }