/* * @(#)PertFigure.java * * Project: JHotdraw - a GUI framework for technical drawings * http://www.jhotdraw.org * http://jhotdraw.sourceforge.net * Copyright: © by the original author(s) and all contributors * License: Lesser GNU Public License (LGPL) * http://www.opensource.org/licenses/lgpl-license.html */ package CH.ifa.draw.samples.pert; import java.awt.*; import java.util.*; import java.io.*; import CH.ifa.draw.framework.*; import CH.ifa.draw.standard.*; import CH.ifa.draw.figures.*; import CH.ifa.draw.util.*; /** * @version <$CURRENT_VERSION$> */ public class PertFigure extends CompositeFigure { private static final int BORDER = 3; private Rectangle fDisplayBox; private Vector fPreTasks; private Vector fPostTasks; /* * Serialization support. */ private static final long serialVersionUID = -7877776240236946511L; private int pertFigureSerializedDataVersion = 1; public PertFigure() { initialize(); } public int start() { int start = 0; Enumeration i = fPreTasks.elements(); while (i.hasMoreElements()) { PertFigure f = (PertFigure) i.nextElement(); start = Math.max(start, f.end()); } return start; } public int end() { return asInt(2); } public int duration() { return asInt(1); } public void setEnd(int value) { setInt(2, value); } public void addPreTask(PertFigure figure) { if (!fPreTasks.contains(figure)) { fPreTasks.addElement(figure); } } public void addPostTask(PertFigure figure) { if (!fPostTasks.contains(figure)) { fPostTasks.addElement(figure); } } public void removePreTask(PertFigure figure) { fPreTasks.removeElement(figure); } public void removePostTask(PertFigure figure) { fPostTasks.removeElement(figure); } private int asInt(int figureIndex) { NumberTextFigure t = (NumberTextFigure)figureAt(figureIndex); return t.getValue(); } private String taskName() { TextFigure t = (TextFigure)figureAt(0); return t.getText(); } private void setInt(int figureIndex, int value) { NumberTextFigure t = (NumberTextFigure)figureAt(figureIndex); t.setValue(value); } protected void basicMoveBy(int x, int y) { fDisplayBox.translate(x, y); super.basicMoveBy(x, y); } public Rectangle displayBox() { return new Rectangle( fDisplayBox.x, fDisplayBox.y, fDisplayBox.width, fDisplayBox.height); } public void basicDisplayBox(Point origin, Point corner) { fDisplayBox = new Rectangle(origin); fDisplayBox.add(corner); layout(); } private void drawBorder(Graphics g) { super.draw(g); Rectangle r = displayBox(); Figure f = figureAt(0); Rectangle rf = f.displayBox(); g.setColor(Color.gray); g.drawLine(r.x, r.y+rf.height+2, r.x+r.width, r.y + rf.height+2); g.setColor(Color.white); g.drawLine(r.x, r.y+rf.height+3, r.x+r.width, r.y + rf.height+3); g.setColor(Color.white); g.drawLine(r.x, r.y, r.x, r.y + r.height); g.drawLine(r.x, r.y, r.x + r.width, r.y); g.setColor(Color.gray); g.drawLine(r.x + r.width, r.y, r.x + r.width, r.y + r.height); g.drawLine(r.x , r.y + r.height, r.x + r.width, r.y + r.height); } public void draw(Graphics g) { drawBorder(g); super.draw(g); } public Vector handles() { Vector handles = new Vector(); handles.addElement(new NullHandle(this, RelativeLocator.northWest())); handles.addElement(new NullHandle(this, RelativeLocator.northEast())); handles.addElement(new NullHandle(this, RelativeLocator.southWest())); handles.addElement(new NullHandle(this, RelativeLocator.southEast())); handles.addElement(new ConnectionHandle(this, RelativeLocator.east(), new PertDependency()) ); return handles; } private void initialize() { fPostTasks = new Vector(); fPreTasks = new Vector(); fDisplayBox = new Rectangle(0, 0, 0, 0); Font f = new Font("Helvetica", Font.PLAIN, 12); Font fb = new Font("Helvetica", Font.BOLD, 12); TextFigure name = new TextFigure(); name.setFont(fb); name.setText("Task"); //name.setAttribute(FigureAttributeConstant.TEXT_COLOR.getName(), Color.white); add(name); NumberTextFigure duration = new NumberTextFigure(); duration.setValue(0); duration.setFont(fb); add(duration); NumberTextFigure end = new NumberTextFigure(); end.setValue(0); end.setFont(f); end.setReadOnly(true); add(end); } private void layout() { Point partOrigin = new Point(fDisplayBox.x, fDisplayBox.y); partOrigin.translate(BORDER, BORDER); Dimension extent = new Dimension(0, 0); FigureEnumeration k = figures(); while (k.hasMoreElements()) { Figure f = k.nextFigure(); Dimension partExtent = f.size(); Point corner = new Point( partOrigin.x+partExtent.width, partOrigin.y+partExtent.height); f.basicDisplayBox(partOrigin, corner); extent.width = Math.max(extent.width, partExtent.width); extent.height += partExtent.height; partOrigin.y += partExtent.height; } fDisplayBox.width = extent.width + 2*BORDER; fDisplayBox.height = extent.height + 2*BORDER; } private boolean needsLayout() { Dimension extent = new Dimension(0, 0); FigureEnumeration k = figures(); while (k.hasMoreElements()) { Figure f = k.nextFigure(); extent.width = Math.max(extent.width, f.size().width); } int newExtent = extent.width + 2*BORDER; return newExtent != fDisplayBox.width; } public void update(FigureChangeEvent e) { if (e.getFigure() == figureAt(1)) { // duration has changed updateDurations(); } if (needsLayout()) { layout(); changed(); } } public void figureChanged(FigureChangeEvent e) { update(e); } public void figureRemoved(FigureChangeEvent e) { update(e); } public void notifyPostTasks() { Enumeration i = fPostTasks.elements(); while (i.hasMoreElements()) { ((PertFigure) i.nextElement()).updateDurations(); } } public void updateDurations() { int newEnd = start()+duration(); if (newEnd != end()) { setEnd(newEnd); notifyPostTasks(); } } public boolean hasCycle(Figure start) { if (start == this) { return true; } Enumeration i = fPreTasks.elements(); while (i.hasMoreElements()) { if (((PertFigure) i.nextElement()).hasCycle(start)) { return true; } } return false; } //-- store / load ---------------------------------------------- public void write(StorableOutput dw) { super.write(dw); dw.writeInt(fDisplayBox.x); dw.writeInt(fDisplayBox.y); dw.writeInt(fDisplayBox.width); dw.writeInt(fDisplayBox.height); writeTasks(dw, fPreTasks); writeTasks(dw, fPostTasks); } public void writeTasks(StorableOutput dw, Vector v) { dw.writeInt(v.size()); Enumeration i = v.elements(); while (i.hasMoreElements()) { dw.writeStorable((Storable) i.nextElement()); } } public void read(StorableInput dr) throws IOException { super.read(dr); fDisplayBox = new Rectangle( dr.readInt(), dr.readInt(), dr.readInt(), dr.readInt()); layout(); fPreTasks = readTasks(dr); fPostTasks = readTasks(dr); } public Insets connectionInsets() { Rectangle r = fDisplayBox; int cx = r.width/2; int cy = r.height/2; return new Insets(cy, cx, cy, cx); } public Vector readTasks(StorableInput dr) throws IOException { int size = dr.readInt(); Vector v = new Vector(size); for (int i=0; i