/* * Copyright (C) 2007 Snorre Gylterud, Stein Magnus Jodal, Johannes Knutsen, * Erik Bagge Ottesen, Ralf Bjarne Taraldset, and Iterate AS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. */ package no.ntnu.mmfplanner.ui.graph; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import java.awt.geom.Line2D.Double; import java.util.HashMap; import no.ntnu.mmfplanner.model.Mmf; import no.ntnu.mmfplanner.model.Project; import no.ntnu.mmfplanner.util.TangoColor; import edu.umd.cs.piccolo.PNode; import edu.umd.cs.piccolo.util.PBounds; import edu.umd.cs.piccolo.util.PPaintContext; /** * Handles layout of MMFs and PrecursorNodes. * * Paints white/gray areas to separate each period. The first period is drawn in * white, the second in gray, etc. The width of a period is given by * MmfNode.WIDTH + MmfNode.PADDING_WIDTH. */ public class PrecedenceGraphNode extends ProjectGraphNode { private static final long serialVersionUID = 1L; public PrecedenceGraphNode(Project project) { super(project); } private static final Color PERIOD_COLOR_EVEN = Color.WHITE; private static final Color PERIOD_COLOR_ODD = TangoColor.ALUMINIUM_1; @Override protected void invalidateModel() { // XXX: should we update only the relevant nodes? in a project with // dependencies this could be quite a lot of nodes anyway -bagge removeAllChildren(); // add all MMFs HashMap<Mmf, MmfNode> mmfNodes = new HashMap<Mmf, MmfNode>(); for (int i = 0; i < project.size(); i++) { Mmf mmf = project.get(i); MmfNode node = new MmfNode(mmf); addChild(node); mmfNodes.put(mmf, node); } // add all precursors for (Mmf target : mmfNodes.keySet()) { for (Mmf source : target.getPrecursors()) { PrecursorNode node = new PrecursorNode(mmfNodes.get(source), mmfNodes.get(target)); addChild(0, node); } } } @Override protected void layoutChildren() { int maxSwimlane = 0; for (int i = 0; i < getChildrenCount(); i++) { PNode node = getChild(i); if (node instanceof MmfNode) { layoutNode((MmfNode) node); maxSwimlane = Math.max(maxSwimlane, ((MmfNode) node).getMmf() .getSwimlane()); } } for (int i = 0; i < getChildrenCount(); i++) { PNode node = getChild(i); if (node instanceof PrecursorNode) { ((PrecursorNode) node).updateLine(); } } // set bounds double width = project.getPeriods() * (MmfNode.WIDTH + MmfNode.PADDING_WIDTH); double height = (maxSwimlane + 1) * (MmfNode.HEIGHT + MmfNode.PADDING_HEIGHT); setBounds(0, 0, width, height); } private void layoutNode(MmfNode node) { Mmf mmf = node.getMmf(); double x = (mmf.getPeriod() - 1) * (MmfNode.WIDTH + MmfNode.PADDING_WIDTH) + MmfNode.PADDING_WIDTH / 2; node.setX(x); double y = (mmf.getSwimlane() - 1) * (MmfNode.HEIGHT + MmfNode.PADDING_HEIGHT) + MmfNode.PADDING_HEIGHT / 2; node.setY(y); node.setWidth(MmfNode.WIDTH); node.setHeight(MmfNode.HEIGHT); } @Override protected void paint(PPaintContext paintContext) { Graphics2D g2 = paintContext.getGraphics(); PBounds viewBounds = paintContext.getCamera().getViewBounds(); // double height = Math.max(getHeight(), viewBounds.getY() + // viewBounds.getHeight()); double height = getHeight(); double y = Math.min(0, viewBounds.getY()); // Draw rectangular background double periodWidth = MmfNode.WIDTH + MmfNode.PADDING_WIDTH; int maxX = (int) Math.ceil(getWidth() / periodWidth); Rectangle2D r = new Rectangle2D.Double(); for (int x = 0; x < maxX; x++) { g2.setColor(x % 2 == 0 ? PERIOD_COLOR_EVEN : PERIOD_COLOR_ODD); r.setRect(x * periodWidth, y, periodWidth, height); g2.fill(localToParent(r)); } // Draw swimlane lines double swimlaneHeight = MmfNode.HEIGHT + MmfNode.PADDING_HEIGHT; int maxY = (int) Math.ceil(height / swimlaneHeight); double x = Math.min(0, viewBounds.getX()); double width = Math.max(getWidth(), viewBounds.getX() + viewBounds.getWidth()); r = new Rectangle2D.Double(); Double l = new Line2D.Double(); for (y = 0; y < maxY; y++) { g2.setColor(Color.LIGHT_GRAY); g2.setStroke(new BasicStroke(1)); l.setLine(x, y * swimlaneHeight, width, y * swimlaneHeight); g2.draw(l); } // Shade periods outside Project settings periods if (width - (project.getPeriods() * periodWidth) > 0) { g2.setColor(Color.GRAY); r.setRect(project.getPeriods() * periodWidth, 0, width - (project.getPeriods() * periodWidth), height); g2.fill(localToParent(r)); } } }