Java tutorial
package com.che.software.testato.util.jung; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Paint; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.AffineTransform; import java.awt.geom.Ellipse2D; import java.awt.geom.RoundRectangle2D; import java.io.Serializable; import org.apache.commons.collections15.Transformer; import org.apache.log4j.Logger; import com.che.software.testato.domain.entity.Element; import com.che.software.testato.domain.entity.Intention; import com.che.software.testato.domain.entity.MapArrow; import com.che.software.testato.domain.entity.ProceduralArrow; import com.che.software.testato.util.ColorUtil; import com.che.software.testato.util.jung.enumeration.DrawingAlgorithm; import edu.uci.ics.jung.algorithms.layout.CircleLayout; import edu.uci.ics.jung.algorithms.layout.FRLayout; import edu.uci.ics.jung.algorithms.layout.FRLayout2; import edu.uci.ics.jung.algorithms.layout.ISOMLayout; import edu.uci.ics.jung.algorithms.layout.KKLayout; import edu.uci.ics.jung.algorithms.layout.Layout; import edu.uci.ics.jung.algorithms.layout.SpringLayout; import edu.uci.ics.jung.algorithms.layout.SpringLayout2; import edu.uci.ics.jung.graph.DirectedGraph; import edu.uci.ics.jung.graph.Graph; import edu.uci.ics.jung.graph.util.Context; import edu.uci.ics.jung.visualization.VisualizationImageServer; import edu.uci.ics.jung.visualization.decorators.EdgeShape; import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position; /** * Static class used to colorize the JUNG diagrams. * * @author Clement HELIOU (clement.heliou@che-software.com). * @copyright Che Software. * @license GNU General Public License. * @see Serializable. * @since July, 2011. * * This file is part of Testato. * * Testato is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * Testato is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with Testato. If not, see <http://www.gnu.org/licenses/>. * * Testato's logo is a creation of Arrioch * (http://arrioch.deviantart.com/) and it's distributed under the terms * of the Creative Commons License. */ public class DiagramGraphistUtil implements Serializable { /** * Constants. */ private static final double DEFAULT_CHOICE_SHAPE_ROTATION = 0.7854; // Radians. private static final double[] DEFAULT_CIRCLE_SIZE = { -5, -20, 80, 80 }, DEFAULT_ELLIPSE_SIZE = { -5, -20, 100, 40 }, DEFAULT_RECTANGLE_SIZE = { -5, -20, 100, 40, 10, 10 }; private static final int LABEL_OFFSET = 20; private static final int[] DEFAULT_DIAMOND_SIZE = { -5, -20, 50, 50 }, DEFAULT_POLYGON_X_POINTS = { -15, 15, 30, 30, 15, -15, -30, -30 }, DEFAULT_POLYGON_Y_POINTS = { 30, 30, 15, -15, -30, -30, -15, 15, 30 }; private static final Logger LOGGER = Logger.getLogger(DiagramGraphistUtil.class); private static final long serialVersionUID = 989685570695060055L; private static final String BLUE_HEXA = "92CDDC", DARK_BLUE_HEXA = "17365D", ORANGE_HEXA = "FF9900"; private static final Stroke DEFAULT_MAP_STROKE = new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); private static final Stroke DEFAULT_PROC_STROKE = new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL); private static final Transformer<Element, Font> PROC_ELEMENT_FONT = new Transformer<Element, Font>() { @Override public Font transform(Element arg0) { return ColorUtil.DEFAULT_FONT; } }; private static final Transformer<Element, Paint> PROC_BORDER_ELEMENT_PAINT = new Transformer<Element, Paint>() { @Override public Paint transform(Element element) { return ColorUtil.getHSBColor(ColorUtil.DARK_BLUE_COLOR[0], ColorUtil.DARK_BLUE_COLOR[1], ColorUtil.DARK_BLUE_COLOR[2]); } }; private static final Transformer<Element, Paint> PROC_ELEMENT_PAINT = new Transformer<Element, Paint>() { @Override public Paint transform(Element element) { return ColorUtil.getHSBColor(ColorUtil.GREY_COLOR[0], ColorUtil.GREY_COLOR[1], ColorUtil.GREY_COLOR[2]); } }; private static final Transformer<Element, Shape> PROC_ELEMENT_SHAPE = new Transformer<Element, Shape>() { @Override public Shape transform(Element element) { if (0 != element.getActivityId()) { return new RoundRectangle2D.Double(DEFAULT_RECTANGLE_SIZE[0], DEFAULT_RECTANGLE_SIZE[1], DEFAULT_RECTANGLE_SIZE[2], DEFAULT_RECTANGLE_SIZE[3], DEFAULT_RECTANGLE_SIZE[4], DEFAULT_RECTANGLE_SIZE[5]); } switch (element.getPointType()) { case CHOICE: AffineTransform at = new AffineTransform(); at.rotate(DEFAULT_CHOICE_SHAPE_ROTATION); return at.createTransformedShape(new Rectangle(DEFAULT_DIAMOND_SIZE[0], DEFAULT_DIAMOND_SIZE[1], DEFAULT_DIAMOND_SIZE[2], DEFAULT_DIAMOND_SIZE[3])); case JOIN: return new Polygon(DEFAULT_POLYGON_X_POINTS, DEFAULT_POLYGON_Y_POINTS, DEFAULT_POLYGON_X_POINTS.length); case NEGATIVE_END: case POSITIVE_END: case START: return new Ellipse2D.Double(DEFAULT_CIRCLE_SIZE[0], DEFAULT_CIRCLE_SIZE[1], DEFAULT_CIRCLE_SIZE[2], DEFAULT_CIRCLE_SIZE[3]); default: return null; // Doesn't happened. } } }; private static final Transformer<Element, String> PROC_ELEMENT_LABEL = new Transformer<Element, String>() { @Override public String transform(Element element) { return "<html><font color=\"#" + DARK_BLUE_HEXA + "\">" + element + "</font></html>"; } }; private static final Transformer<Element, Stroke> PROC_ELEMENT_STROKE = new Transformer<Element, Stroke>() { @Override public Stroke transform(Element arg0) { return DEFAULT_PROC_STROKE; } }; private static final Transformer<Intention, Font> MAP_NODE_FONT = new Transformer<Intention, Font>() { @Override public Font transform(Intention arg0) { return ColorUtil.DEFAULT_FONT; } }; private static final Transformer<Intention, Paint> MAP_NODE_PAINT = new Transformer<Intention, Paint>() { @Override public Paint transform(Intention intention) { return ColorUtil.getHSBColor(ColorUtil.GREY_COLOR[0], ColorUtil.GREY_COLOR[1], ColorUtil.GREY_COLOR[2]); } }; private static final Transformer<Intention, Paint> MAP_BORDER_NODE_PAINT = new Transformer<Intention, Paint>() { @Override public Paint transform(Intention intention) { return ColorUtil.getHSBColor(ColorUtil.DARK_BLUE_COLOR[0], ColorUtil.DARK_BLUE_COLOR[1], ColorUtil.DARK_BLUE_COLOR[2]); } }; private static final Transformer<Intention, Shape> MAP_NODE_SHAPE = new Transformer<Intention, Shape>() { @Override public Shape transform(Intention intention) { return new Ellipse2D.Double(DEFAULT_ELLIPSE_SIZE[0], DEFAULT_ELLIPSE_SIZE[1], DEFAULT_ELLIPSE_SIZE[2], DEFAULT_ELLIPSE_SIZE[3]); } }; private static final Transformer<Intention, String> MAP_NODE_LABEL = new Transformer<Intention, String>() { @Override public String transform(Intention intention) { return "<html><font color=\"#" + DARK_BLUE_HEXA + "\">" + intention + "</font></html>"; } }; private static final Transformer<Intention, Stroke> MAP_NODE_STROKE = new Transformer<Intention, Stroke>() { @Override public Stroke transform(Intention intention) { return DEFAULT_MAP_STROKE; } }; private static final Transformer<MapArrow, Font> MAP_ARROW_FONT = new Transformer<MapArrow, Font>() { @Override public Font transform(MapArrow arrow) { return ColorUtil.DEFAULT_FONT; } }; private static final Transformer<MapArrow, Paint> MAP_ARROW_PAINT = new Transformer<MapArrow, Paint>() { @Override public Paint transform(MapArrow arrow) { return (arrow.isOperationalized()) ? ColorUtil.getHSBColor(ColorUtil.ORANGE_COLOR[0], ColorUtil.ORANGE_COLOR[1], ColorUtil.ORANGE_COLOR[2]) : (arrow.isRefined()) ? ColorUtil.getHSBColor(ColorUtil.BLUE_COLOR[0], ColorUtil.BLUE_COLOR[1], ColorUtil.BLUE_COLOR[2]) : ColorUtil.getHSBColor(ColorUtil.DARK_BLUE_COLOR[0], ColorUtil.DARK_BLUE_COLOR[1], ColorUtil.DARK_BLUE_COLOR[2]); } }; private static final Transformer<MapArrow, String> MAP_ARROW_LABEL = new Transformer<MapArrow, String>() { @Override public String transform(MapArrow arrow) { return "<html><font color=\"#" + ((arrow.isOperationalized()) ? ORANGE_HEXA : (arrow.isRefined()) ? BLUE_HEXA : DARK_BLUE_HEXA) + "\">" + arrow + "</font></html>"; } }; private static final Transformer<MapArrow, Stroke> MAP_ARROW_STROKE = new Transformer<MapArrow, Stroke>() { @Override public Stroke transform(MapArrow arrow) { return DEFAULT_MAP_STROKE; } }; private static final Transformer<ProceduralArrow, Font> PROC_ARROW_FONT = new Transformer<ProceduralArrow, Font>() { @Override public Font transform(ProceduralArrow arrow) { return ColorUtil.DEFAULT_FONT; } }; private static final Transformer<ProceduralArrow, Paint> PROC_ARROW_PAINT = new Transformer<ProceduralArrow, Paint>() { @Override public Paint transform(ProceduralArrow arrow) { return ColorUtil.getHSBColor(ColorUtil.DARK_BLUE_COLOR[0], ColorUtil.DARK_BLUE_COLOR[1], ColorUtil.DARK_BLUE_COLOR[2]); } }; private static final Transformer<ProceduralArrow, String> PROC_ARROW_LABEL = new Transformer<ProceduralArrow, String>() { @Override public String transform(ProceduralArrow arrow) { return "<html><font color=\"#" + ((null != arrow.getLabel() && !"".equals(arrow.getLabel())) ? BLUE_HEXA : DARK_BLUE_HEXA) + "\">" + arrow + "</font></html>"; } }; private static final Transformer<ProceduralArrow, Stroke> PROC_ARROW_STROKE = new Transformer<ProceduralArrow, Stroke>() { @Override public Stroke transform(ProceduralArrow arrow) { return DEFAULT_PROC_STROKE; } }; private static final Transformer<Context<Graph<Intention, MapArrow>, MapArrow>, Shape> MAP_ARROW_SHAPE = new Transformer<Context<Graph<Intention, MapArrow>, MapArrow>, Shape>() { @Override public Shape transform(Context<Graph<Intention, MapArrow>, MapArrow> context) { return new EdgeShape.QuadCurve<Intention, MapArrow>().transform(context); } }; private static final Transformer<Context<Graph<Element, ProceduralArrow>, ProceduralArrow>, Shape> PROC_ARROW_SHAPE = new Transformer<Context<Graph<Element, ProceduralArrow>, ProceduralArrow>, Shape>() { @Override public Shape transform(Context<Graph<Element, ProceduralArrow>, ProceduralArrow> context) { return new EdgeShape.BentLine<Element, ProceduralArrow>().transform(context); } }; /** * Private default builder; the class can't be instancied. */ private DiagramGraphistUtil() { } /** * Returns the object containing the colorized version of a map diagram. * * @author Clement HELIOU (clement.heliou@che-software.com). * @param mapDiagram the map diagram to colorized. * @return the resulting object. * @since July, 2011. */ public static VisualizationImageServer<Intention, MapArrow> getColorizedMapDiagram( DirectedGraph<Intention, MapArrow> mapDiagram) { LOGGER.debug("getColorizedMapDiagram(" + mapDiagram + ")."); return DiagramGraphistUtil.getColorizedMapDiagramFromAlgorithmAndSize(mapDiagram, DrawingAlgorithm.KK, ColorUtil.REDUCE_SIZE); } /** * Returns the object containing the colorized version of a map diagram with * given algorithm and size. * * @author Clement HELIOU (clement.heliou@che-software.com). * @param mapDiagram the map diagram to colorized. * @param algorithm the algorithm to used. * @param imageSize the desired image size. * @return the resulting object. * @since July, 2011. */ public static VisualizationImageServer<Intention, MapArrow> getColorizedMapDiagramFromAlgorithmAndSize( DirectedGraph<Intention, MapArrow> mapDiagram, DrawingAlgorithm algorithm, Dimension imageSize) { LOGGER.debug("getColorizedMapDiagramFromAlgorithmAndSize(" + mapDiagram + "," + algorithm + ")."); Layout<Intention, MapArrow> layout = DiagramGraphistUtil.getMapLayoutFromAlgorithmAndSize(mapDiagram, algorithm, imageSize); VisualizationImageServer<Intention, MapArrow> vis = new VisualizationImageServer<Intention, MapArrow>( layout, imageSize); vis.getRenderContext().setArrowDrawPaintTransformer(MAP_ARROW_PAINT); vis.getRenderContext().setEdgeArrowStrokeTransformer(MAP_ARROW_STROKE); vis.getRenderContext().setEdgeDrawPaintTransformer(MAP_ARROW_PAINT); vis.getRenderContext().setEdgeFontTransformer(MAP_ARROW_FONT); vis.getRenderContext().setEdgeLabelTransformer(MAP_ARROW_LABEL); vis.getRenderContext().setEdgeShapeTransformer(MAP_ARROW_SHAPE); vis.getRenderContext().setEdgeStrokeTransformer(MAP_ARROW_STROKE); vis.getRenderContext().setLabelOffset(LABEL_OFFSET); vis.getRenderContext().setVertexDrawPaintTransformer(MAP_BORDER_NODE_PAINT); vis.getRenderContext().setVertexFillPaintTransformer(MAP_NODE_PAINT); vis.getRenderContext().setVertexFontTransformer(MAP_NODE_FONT); vis.getRenderContext().setVertexLabelTransformer(MAP_NODE_LABEL); vis.getRenderContext().setVertexShapeTransformer(MAP_NODE_SHAPE); vis.getRenderContext().setVertexStrokeTransformer(MAP_NODE_STROKE); vis.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR); vis.setBackground(Color.WHITE); vis.validate(); return vis; } /** * Returns the object containing the colorized version of a procedural * diagram. * * @author Clement HELIOU (clement.heliou@che-software.com). * @param proceduralDiagram the procedural diagram to colorized. * @return the resulting object. * @since July, 2011. */ public static VisualizationImageServer<Element, ProceduralArrow> getColorizedProceduralDiagram( DirectedGraph<Element, ProceduralArrow> proceduralDiagram) { LOGGER.debug("getColorizedProceduralDiagram(" + proceduralDiagram + ")."); return DiagramGraphistUtil.getColorizedProceduralDiagramFromAlgorithmAndSize(proceduralDiagram, DrawingAlgorithm.ISOM, ColorUtil.REDUCE_SIZE); } /** * Returns the object containing the colorized version of a procedural * diagram with given algorithm and size. * * @author Clement HELIOU (clement.heliou@che-software.com). * @param proceduralDiagram the procedural diagram to colorized. * @param algorithm the algorithm to used. * @param imageSize the desired image size. * @return the resulting object. * @since July, 2011. */ public static VisualizationImageServer<Element, ProceduralArrow> getColorizedProceduralDiagramFromAlgorithmAndSize( DirectedGraph<Element, ProceduralArrow> proceduralDiagram, DrawingAlgorithm algorithm, Dimension imageSize) { LOGGER.debug("getColorizedProceduralDiagramFromAlgorithmAndSize(" + proceduralDiagram + "," + algorithm + "," + imageSize.getHeight() + "," + imageSize.getWidth() + ")."); Layout<Element, ProceduralArrow> layout = DiagramGraphistUtil .getProceduralLayoutFromAlgorithmAndSize(proceduralDiagram, algorithm, imageSize); VisualizationImageServer<Element, ProceduralArrow> vis = new VisualizationImageServer<Element, ProceduralArrow>( layout, imageSize); vis.getRenderContext().setArrowDrawPaintTransformer(PROC_ARROW_PAINT); vis.getRenderContext().setArrowFillPaintTransformer(PROC_ARROW_PAINT); vis.getRenderContext().setEdgeArrowStrokeTransformer(PROC_ARROW_STROKE); vis.getRenderContext().setEdgeDrawPaintTransformer(PROC_ARROW_PAINT); vis.getRenderContext().setEdgeFontTransformer(PROC_ARROW_FONT); vis.getRenderContext().setEdgeLabelTransformer(PROC_ARROW_LABEL); vis.getRenderContext().setEdgeShapeTransformer(PROC_ARROW_SHAPE); vis.getRenderContext().setEdgeStrokeTransformer(PROC_ARROW_STROKE); vis.getRenderContext().setLabelOffset(LABEL_OFFSET); vis.getRenderContext().setVertexDrawPaintTransformer(PROC_BORDER_ELEMENT_PAINT); vis.getRenderContext().setVertexFillPaintTransformer(PROC_ELEMENT_PAINT); vis.getRenderContext().setVertexFontTransformer(PROC_ELEMENT_FONT); vis.getRenderContext().setVertexLabelTransformer(PROC_ELEMENT_LABEL); vis.getRenderContext().setVertexShapeTransformer(PROC_ELEMENT_SHAPE); vis.getRenderContext().setVertexStrokeTransformer(PROC_ELEMENT_STROKE); vis.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR); vis.setBackground(Color.WHITE); vis.validate(); return vis; } /** * Return the layout corresponding to the parameters. * * @author Clement HELIOU (clement.heliou@che-software.com). * @param mapDiagram the map diagram to put into the layout. * @param algorithm the desired algorithm. * @param imageSize the desired image size. * @return the resulting layout object. * @since July, 2011. */ private static Layout<Intention, MapArrow> getMapLayoutFromAlgorithmAndSize( DirectedGraph<Intention, MapArrow> mapDiagram, DrawingAlgorithm algorithm, Dimension imageSize) { LOGGER.debug("getMapLayoutFromAlgorithmAndSize(" + algorithm + "," + imageSize.getHeight() + "," + imageSize.getWidth() + ")."); Layout<Intention, MapArrow> layout = null; switch (algorithm) { case CIRCLE: layout = new CircleLayout<Intention, MapArrow>(mapDiagram); break; case FR: layout = new FRLayout<Intention, MapArrow>(mapDiagram); break; case FR2: layout = new FRLayout2<Intention, MapArrow>(mapDiagram); break; case ISOM: layout = new ISOMLayout<Intention, MapArrow>(mapDiagram); break; case KK: layout = new KKLayout<Intention, MapArrow>(mapDiagram); break; case SPRING: layout = new SpringLayout<Intention, MapArrow>(mapDiagram); break; case SPRING2: layout = new SpringLayout2<Intention, MapArrow>(mapDiagram); break; default: // Doesn't happened. break; } layout.setSize(imageSize); return layout; } /** * Return the layout corresponding to the parameters. * * @author Clement HELIOU (clement.heliou@che-software.com). * @param proceduralDiagram the procedural diagram to put into the layout. * @param algorithm the desired algorithm. * @param imageSize the desired image size. * @return the resulting layout object. * @since July, 2011. */ private static Layout<Element, ProceduralArrow> getProceduralLayoutFromAlgorithmAndSize( DirectedGraph<Element, ProceduralArrow> proceduralDiagram, DrawingAlgorithm algorithm, Dimension imageSize) { LOGGER.debug("getProceduralLayoutFromAlgorithmAndSize(" + proceduralDiagram + "," + algorithm + "," + imageSize.getHeight() + "," + imageSize.getWidth() + ")."); Layout<Element, ProceduralArrow> layout = null; switch (algorithm) { case CIRCLE: layout = new CircleLayout<Element, ProceduralArrow>(proceduralDiagram); break; case FR: layout = new FRLayout<Element, ProceduralArrow>(proceduralDiagram); break; case FR2: layout = new FRLayout2<Element, ProceduralArrow>(proceduralDiagram); break; case ISOM: layout = new ISOMLayout<Element, ProceduralArrow>(proceduralDiagram); break; case KK: layout = new KKLayout<Element, ProceduralArrow>(proceduralDiagram); break; case SPRING: layout = new SpringLayout<Element, ProceduralArrow>(proceduralDiagram); break; case SPRING2: layout = new SpringLayout2<Element, ProceduralArrow>(proceduralDiagram); break; default: // Doesn't happened. break; } layout.setSize(imageSize); return layout; } }