From 85ad30b381a0322fedcf6dc0deac6b642e0a515e Mon Sep 17 00:00:00 2001 From: Arnaud Roques Date: Sun, 5 Apr 2020 17:13:04 +0200 Subject: [PATCH] version 1.2020.6 --- src/jcckit/GraphicsPlotCanvas.java | 228 ++++++++ src/jcckit/data/DataContainer.java | 182 +++++++ src/jcckit/data/DataCurve.java | 93 ++++ src/jcckit/data/DataElement.java | 40 ++ src/jcckit/data/DataEvent.java | 128 +++++ src/jcckit/data/DataEventType.java | 35 ++ src/jcckit/data/DataListener.java | 33 ++ src/jcckit/data/DataPlot.java | 74 +++ src/jcckit/data/DataPoint.java | 40 ++ src/jcckit/graphic/Anchor.java | 129 +++++ .../graphic/BasicGraphicAttributes.java | 202 +++++++ src/jcckit/graphic/BasicGraphicalElement.java | 58 ++ src/jcckit/graphic/ClippingRectangle.java | 81 +++ src/jcckit/graphic/ClippingShape.java | 47 ++ src/jcckit/graphic/FillAttributes.java | 35 ++ src/jcckit/graphic/FontStyle.java | 82 +++ src/jcckit/graphic/GraphPoint.java | 43 ++ src/jcckit/graphic/GraphicAttributes.java | 36 ++ src/jcckit/graphic/GraphicalComposite.java | 106 ++++ .../graphic/GraphicalCompositeRenderer.java | 40 ++ src/jcckit/graphic/GraphicalElement.java | 41 ++ src/jcckit/graphic/LineAttributes.java | 52 ++ src/jcckit/graphic/Oval.java | 54 ++ src/jcckit/graphic/OvalRenderer.java | 30 ++ src/jcckit/graphic/Polygon.java | 85 +++ src/jcckit/graphic/PolygonRenderer.java | 30 ++ src/jcckit/graphic/Rectangle.java | 76 +++ src/jcckit/graphic/RectangleRenderer.java | 30 ++ src/jcckit/graphic/Renderer.java | 27 + src/jcckit/graphic/ShapeAttributes.java | 104 ++++ src/jcckit/graphic/Text.java | 67 +++ src/jcckit/graphic/TextAttributes.java | 75 +++ src/jcckit/graphic/TextRenderer.java | 30 ++ src/jcckit/plot/AbstractSymbolFactory.java | 120 +++++ src/jcckit/plot/AttributesHint.java | 39 ++ src/jcckit/plot/AxisParameters.java | 496 ++++++++++++++++++ src/jcckit/plot/BarFactory.java | 131 +++++ .../plot/CartesianCoordinateSystem.java | 206 ++++++++ src/jcckit/plot/CircleSymbolFactory.java | 54 ++ src/jcckit/plot/CoordinateSystem.java | 55 ++ src/jcckit/plot/Curve.java | 64 +++ src/jcckit/plot/CurveFactory.java | 42 ++ src/jcckit/plot/ErrorBarFactory.java | 136 +++++ src/jcckit/plot/Hint.java | 32 ++ src/jcckit/plot/Legend.java | 250 +++++++++ src/jcckit/plot/Plot.java | 377 +++++++++++++ src/jcckit/plot/PlotCanvas.java | 135 +++++ src/jcckit/plot/PlotEvent.java | 88 ++++ src/jcckit/plot/PlotEventType.java | 36 ++ src/jcckit/plot/PlotListener.java | 29 + src/jcckit/plot/PositionHint.java | 75 +++ src/jcckit/plot/ShapeAttributesHint.java | 140 +++++ src/jcckit/plot/SimpleCurve.java | 185 +++++++ src/jcckit/plot/SimpleCurveFactory.java | 80 +++ src/jcckit/plot/SquareSymbolFactory.java | 54 ++ src/jcckit/plot/Symbol.java | 56 ++ src/jcckit/plot/SymbolFactory.java | 65 +++ src/jcckit/plot/TicLabelMap.java | 136 +++++ src/jcckit/renderer/Graphics2DRenderer.java | 313 +++++++++++ src/jcckit/renderer/Transformation.java | 107 ++++ .../CartesianTransformation.java | 96 ++++ src/jcckit/transformation/Transformation.java | 44 ++ src/jcckit/util/AppletBasedConfigData.java | 53 ++ src/jcckit/util/ConfigData.java | 55 ++ src/jcckit/util/ConfigParameters.java | 320 +++++++++++ .../util/ConfigParametersBasedConfigData.java | 74 +++ src/jcckit/util/Factory.java | 120 +++++ src/jcckit/util/FactoryException.java | 79 +++ src/jcckit/util/FlatConfigData.java | 187 +++++++ src/jcckit/util/Format.java | 208 ++++++++ src/jcckit/util/FormatElement.java | 242 +++++++++ src/jcckit/util/Point.java | 65 +++ .../util/PropertiesBasedConfigData.java | 81 +++ src/jcckit/util/TicLabelFormat.java | 33 ++ src/jcckit/util/Util.java | 47 ++ .../plantuml/LineBreakStrategy.java | 5 + .../sourceforge/plantuml/PSystemBuilder.java | 14 +- src/net/sourceforge/plantuml/Run.java | 3 +- .../activitydiagram3/ActivityDiagram3.java | 67 ++- .../activitydiagram3/InstructionRepeat.java | 6 +- .../command/CommandBackward3.java | 13 +- .../activitydiagram3/ftile/CenteredText.java | 59 +++ .../ftile/FtileFactoryDelegator.java | 2 +- .../activitydiagram3/ftile/ISwimlanesA.java | 62 +++ .../activitydiagram3/ftile/LaneDivider.java | 123 +++++ .../activitydiagram3/ftile/Snake.java | 4 +- .../activitydiagram3/ftile/Swimlane.java | 5 +- .../activitydiagram3/ftile/SwimlanesA.java | 76 +-- .../activitydiagram3/ftile/SwimlanesAAA.java | 436 +++++++++++++++ .../activitydiagram3/ftile/SwimlanesB.java | 6 +- .../activitydiagram3/ftile/SwimlanesC.java | 1 - .../plantuml/activitydiagram3/ftile/Worm.java | 4 +- .../AbstractParallelFtilesBuilder.java | 2 +- .../ftile/vcompact/FtileGroup.java | 20 +- .../ftile/vcompact/FtileRepeat.java | 6 +- .../ftile/vcompact/ParallelBuilderSplit.java | 1 - .../vcompact/cond/ConditionalBuilder.java | 6 +- .../cond/FtileSwitchWithDiamonds.java | 2 +- .../vcompact/cond/FtileSwitchWithOneLink.java | 5 - .../ftile/vertical/FtileBlackBlock.java | 2 +- .../ftile/vertical/FtileBox.java | 1 - .../classdiagram/ClassDiagramFactory.java | 2 + .../command/CommandAddMethod.java | 2 +- .../command/CommandCreateClassMultilines.java | 51 +- .../plantuml/creole/SheetBlock1.java | 4 +- .../plantuml/creole/atom/AtomText.java | 5 - .../plantuml/cucadiagram/Bodier.java | 198 +------ .../plantuml/cucadiagram/BodierImpl.java | 243 +++++++++ .../plantuml/cucadiagram/BodierMap.java | 112 ++++ .../plantuml/cucadiagram/BodyEnhanced.java | 2 +- .../plantuml/cucadiagram/BodyEnhanced2.java | 2 +- .../plantuml/cucadiagram/Display.java | 24 +- .../plantuml/cucadiagram/GroupRoot.java | 4 + .../plantuml/cucadiagram/HideOrShow2.java | 15 + .../plantuml/cucadiagram/IEntity.java | 3 + .../plantuml/cucadiagram/LeafType.java | 2 +- .../cucadiagram/MethodsOrFieldsArea.java | 2 +- .../plantuml/cucadiagram/TextBlockMap.java | 210 ++++++++ .../cucadiagram/dot/GraphvizUtils.java | 9 + .../cucadiagram/entity/EntityFactory.java | 9 +- .../cucadiagram/entity/EntityImpl.java | 12 + .../command/CommandCreateElementFull.java | 5 + .../plantuml/donors/PSystemDonors.java | 37 +- .../plantuml/error/PSystemError.java | 65 +-- .../plantuml/graphic/GraphicStrings.java | 2 +- .../plantuml/graphic/QuoteUtils.java | 10 +- .../plantuml/graphic/SpecialText.java | 67 +++ .../plantuml/graphic/TextBlockTitle.java | 2 +- .../plantuml/graphic/USymbolFrame.java | 47 +- .../plantuml/jcckit/PSystemJcckit.java | 88 ++++ .../plantuml/jcckit/PSystemJcckitFactory.java | 120 +++++ .../objectdiagram/ObjectDiagramFactory.java | 115 ---- .../objectdiagram/command/CommandAddData.java | 2 +- .../CommandCreateEntityObjectMultilines.java | 2 +- .../command/CommandCreateMap.java | 144 +++++ .../plantuml/project/GanttDiagram.java | 2 +- .../sequencediagram/teoz/AbstractTile.java | 6 +- .../sequencediagram/teoz/GroupingTile.java | 21 +- .../sequencediagram/teoz/PlayingSpace.java | 22 +- .../plantuml/sequencediagram/teoz/Tile.java | 2 +- .../sequencediagram/teoz/TileParallel.java | 9 +- .../sequencediagram/teoz/YPositionedTile.java | 4 +- .../skin/AbstractTextualComponent.java | 2 +- .../skin/rose/ComponentRoseActiveLine.java | 4 + .../statediagram/command/CommandAddField.java | 2 +- .../command/CommandCreateState.java | 2 +- .../plantuml/svek/GeneralImageBuilder.java | 6 +- src/net/sourceforge/plantuml/svek/Line.java | 2 +- .../plantuml/svek/UGraphicForSnake.java | 2 +- .../plantuml/svek/image/EntityImageMap.java | 222 ++++++++ .../plantuml/svek/image/EntityImageState.java | 4 +- .../EntityImageStateEmptyDescription.java | 2 +- .../sourceforge/plantuml/svg/SvgGraphics.java | 4 +- .../plantuml/ugraphic/AbstractUGraphic.java | 5 + .../plantuml/ugraphic/LimitFinder.java | 8 +- .../sourceforge/plantuml/ugraphic/UPath.java | 27 +- .../plantuml/ugraphic/UPolygon.java | 10 +- .../plantuml/ugraphic/URectangle.java | 64 ++- .../UShapeIgnorableForCompression.java | 46 ++ .../ugraphic/comp/CompressionTransform.java | 2 +- .../ugraphic/comp/CompressionXorYBuilder.java | 56 ++ .../plantuml/ugraphic/comp/Expand.java | 80 +++ .../ugraphic/comp/ExpandTransform.java | 71 +++ .../plantuml/ugraphic/comp/ExpandType.java | 42 ++ .../comp/PiecewiseAffineComposition.java | 52 ++ ...java => PiecewiseAffineOnXorYBuilder.java} | 45 +- .../comp/PiecewiseAffineTransform.java | 41 ++ .../plantuml/ugraphic/comp/SlotFinder.java | 45 +- .../ugraphic/comp/UGraphicCompressOnXorY.java | 59 ++- .../sourceforge/plantuml/version/Version.java | 4 +- stdlib/logos-abx.repx | Bin 11300 -> 11326 bytes stdlib/logos-dex.repx | Bin 273114 -> 273188 bytes 172 files changed, 10466 insertions(+), 675 deletions(-) create mode 100644 src/jcckit/GraphicsPlotCanvas.java create mode 100644 src/jcckit/data/DataContainer.java create mode 100644 src/jcckit/data/DataCurve.java create mode 100644 src/jcckit/data/DataElement.java create mode 100644 src/jcckit/data/DataEvent.java create mode 100644 src/jcckit/data/DataEventType.java create mode 100644 src/jcckit/data/DataListener.java create mode 100644 src/jcckit/data/DataPlot.java create mode 100644 src/jcckit/data/DataPoint.java create mode 100644 src/jcckit/graphic/Anchor.java create mode 100644 src/jcckit/graphic/BasicGraphicAttributes.java create mode 100644 src/jcckit/graphic/BasicGraphicalElement.java create mode 100644 src/jcckit/graphic/ClippingRectangle.java create mode 100644 src/jcckit/graphic/ClippingShape.java create mode 100644 src/jcckit/graphic/FillAttributes.java create mode 100644 src/jcckit/graphic/FontStyle.java create mode 100644 src/jcckit/graphic/GraphPoint.java create mode 100644 src/jcckit/graphic/GraphicAttributes.java create mode 100644 src/jcckit/graphic/GraphicalComposite.java create mode 100644 src/jcckit/graphic/GraphicalCompositeRenderer.java create mode 100644 src/jcckit/graphic/GraphicalElement.java create mode 100644 src/jcckit/graphic/LineAttributes.java create mode 100644 src/jcckit/graphic/Oval.java create mode 100644 src/jcckit/graphic/OvalRenderer.java create mode 100644 src/jcckit/graphic/Polygon.java create mode 100644 src/jcckit/graphic/PolygonRenderer.java create mode 100644 src/jcckit/graphic/Rectangle.java create mode 100644 src/jcckit/graphic/RectangleRenderer.java create mode 100644 src/jcckit/graphic/Renderer.java create mode 100644 src/jcckit/graphic/ShapeAttributes.java create mode 100644 src/jcckit/graphic/Text.java create mode 100644 src/jcckit/graphic/TextAttributes.java create mode 100644 src/jcckit/graphic/TextRenderer.java create mode 100644 src/jcckit/plot/AbstractSymbolFactory.java create mode 100644 src/jcckit/plot/AttributesHint.java create mode 100644 src/jcckit/plot/AxisParameters.java create mode 100644 src/jcckit/plot/BarFactory.java create mode 100644 src/jcckit/plot/CartesianCoordinateSystem.java create mode 100644 src/jcckit/plot/CircleSymbolFactory.java create mode 100644 src/jcckit/plot/CoordinateSystem.java create mode 100644 src/jcckit/plot/Curve.java create mode 100644 src/jcckit/plot/CurveFactory.java create mode 100644 src/jcckit/plot/ErrorBarFactory.java create mode 100644 src/jcckit/plot/Hint.java create mode 100644 src/jcckit/plot/Legend.java create mode 100644 src/jcckit/plot/Plot.java create mode 100644 src/jcckit/plot/PlotCanvas.java create mode 100644 src/jcckit/plot/PlotEvent.java create mode 100644 src/jcckit/plot/PlotEventType.java create mode 100644 src/jcckit/plot/PlotListener.java create mode 100644 src/jcckit/plot/PositionHint.java create mode 100644 src/jcckit/plot/ShapeAttributesHint.java create mode 100644 src/jcckit/plot/SimpleCurve.java create mode 100644 src/jcckit/plot/SimpleCurveFactory.java create mode 100644 src/jcckit/plot/SquareSymbolFactory.java create mode 100644 src/jcckit/plot/Symbol.java create mode 100644 src/jcckit/plot/SymbolFactory.java create mode 100644 src/jcckit/plot/TicLabelMap.java create mode 100644 src/jcckit/renderer/Graphics2DRenderer.java create mode 100644 src/jcckit/renderer/Transformation.java create mode 100644 src/jcckit/transformation/CartesianTransformation.java create mode 100644 src/jcckit/transformation/Transformation.java create mode 100644 src/jcckit/util/AppletBasedConfigData.java create mode 100644 src/jcckit/util/ConfigData.java create mode 100644 src/jcckit/util/ConfigParameters.java create mode 100644 src/jcckit/util/ConfigParametersBasedConfigData.java create mode 100644 src/jcckit/util/Factory.java create mode 100644 src/jcckit/util/FactoryException.java create mode 100644 src/jcckit/util/FlatConfigData.java create mode 100644 src/jcckit/util/Format.java create mode 100644 src/jcckit/util/FormatElement.java create mode 100644 src/jcckit/util/Point.java create mode 100644 src/jcckit/util/PropertiesBasedConfigData.java create mode 100644 src/jcckit/util/TicLabelFormat.java create mode 100644 src/jcckit/util/Util.java create mode 100644 src/net/sourceforge/plantuml/activitydiagram3/ftile/CenteredText.java create mode 100644 src/net/sourceforge/plantuml/activitydiagram3/ftile/ISwimlanesA.java create mode 100644 src/net/sourceforge/plantuml/activitydiagram3/ftile/LaneDivider.java create mode 100644 src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesAAA.java create mode 100644 src/net/sourceforge/plantuml/cucadiagram/BodierImpl.java create mode 100644 src/net/sourceforge/plantuml/cucadiagram/BodierMap.java create mode 100644 src/net/sourceforge/plantuml/cucadiagram/TextBlockMap.java create mode 100644 src/net/sourceforge/plantuml/graphic/SpecialText.java create mode 100644 src/net/sourceforge/plantuml/jcckit/PSystemJcckit.java create mode 100644 src/net/sourceforge/plantuml/jcckit/PSystemJcckitFactory.java delete mode 100644 src/net/sourceforge/plantuml/objectdiagram/ObjectDiagramFactory.java create mode 100644 src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateMap.java create mode 100644 src/net/sourceforge/plantuml/svek/image/EntityImageMap.java create mode 100644 src/net/sourceforge/plantuml/ugraphic/UShapeIgnorableForCompression.java create mode 100644 src/net/sourceforge/plantuml/ugraphic/comp/CompressionXorYBuilder.java create mode 100644 src/net/sourceforge/plantuml/ugraphic/comp/Expand.java create mode 100644 src/net/sourceforge/plantuml/ugraphic/comp/ExpandTransform.java create mode 100644 src/net/sourceforge/plantuml/ugraphic/comp/ExpandType.java create mode 100644 src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineComposition.java rename src/net/sourceforge/plantuml/ugraphic/comp/{TextBlockCompressedOnXorY.java => PiecewiseAffineOnXorYBuilder.java} (62%) create mode 100644 src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineTransform.java diff --git a/src/jcckit/GraphicsPlotCanvas.java b/src/jcckit/GraphicsPlotCanvas.java new file mode 100644 index 00000000000..5d2b41b4ad6 --- /dev/null +++ b/src/jcckit/GraphicsPlotCanvas.java @@ -0,0 +1,228 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; + +import jcckit.graphic.GraphicalElement; +import jcckit.graphic.Renderer; +import jcckit.plot.Plot; +import jcckit.plot.PlotCanvas; +import jcckit.renderer.Graphics2DRenderer; +import jcckit.renderer.Transformation; +import jcckit.util.ConfigParameters; +import jcckit.util.Factory; + +/** + * Class which handles plotting into a Graphics context based on the + * {@link jcckit.renderer.GraphicsRenderer}. This class is not a subclass of + * java.awt.Component. The actual AWT component presenting the plot + * is an innerclass. Its instance wrapped by GraphicsPlotCanvas can + * be obtained with {@link #getGraphicsCanvas}. + *

+ * The plot is painted by using double-buffering and pre-rendered view of the + * coordinate system. That is, the coordinate system is drawn into an off-screen + * image. It will be redrawn only if the size of the embedding AWT component is + * changed. + * + * @author Franz-Josef Elmer + */ +public class GraphicsPlotCanvas extends PlotCanvas { + /** Key of a configuration parameter. */ + public static final String BACKGROUND_KEY = "background"; + public static final String FOREGROUND_KEY = "foreground"; + public static final String DOUBLE_BUFFERING_KEY = "doubleBuffering"; + + /** + * Class which does the actual painting. Needs the Component into + * which the plot is painted for some resources like size, background color, + * etc. + * + * @author Franz-Josef Elmer + */ + private final BufferedImage img3; + + private final Graphics2D g3; + + private Transformation _transformation; + private String _renderer = "jcckit.renderer.GraphicsRenderer"; + + private GraphicalElement _marker; + + /** + * Creates an instance from the specified configuration parameters. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
background = default background color of the wrapped + * AWT componentColornoBackground color of the wrapped AWT component.
foreground = default foreground color of the wrapped + * AWT componentColornoForeground color of the wrapped AWT component.
doubleBuffering = truebooleannoIf true the plot will be painted by using + * double-buffering and pre-rendered view of the coordinate system. + *
+ * In addition the configuration parameters of the + * + * constructor of the superclass {@link jcckit.plot.PlotCanvas} apply. + */ + public GraphicsPlotCanvas(ConfigParameters config, BufferedImage img3) { + super(config); + this.img3 = img3; + setRenderer("jcckit.renderer.Graphics2DRenderer"); + + g3 = img3.createGraphics(); + g3.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + // _doubleBuffering = config.getBoolean(DOUBLE_BUFFERING_KEY, true); + background = config.getColor(BACKGROUND_KEY, Color.WHITE); + foreground = config.getColor(FOREGROUND_KEY, Color.BLACK); + } + + private final Color background; + private final Color foreground; + + /** + * Paints the plot. If {@link GraphicsPlotCanvas#_doubleBuffering} is set + * double-buffering and pre-rendered view of the coordinate system is used. + */ + public void paint() { + Dimension size = new Dimension(img3.getWidth(), img3.getHeight()); + g3.setColor(background); + g3.fillRect(0, 0, size.width + 1, size.height + 1); + + init(size); + + _transformation.apply(g3); + Plot plot = getPlot(); + drawCoordinateSystem(size, plot); + drawPlot(plot); + if (_marker != null) { + _marker.renderWith(createRenderer()); + } + } + + private void drawPlot(Plot plot) { + prepare(); + Renderer renderer = createRenderer(); + GraphicalElement[] curves = plot.getCurves(); + for (int i = 0; i < curves.length; i++) { + curves[i].renderWith(renderer); + } + GraphicalElement annotation = plot.getAnnotation(); + if (annotation != null) { + annotation.renderWith(renderer); + } + if (plot.isLegendVisible()) { + plot.getLegend().renderWith(renderer); + } + } + + private void init(Dimension size) { + calculateTransformation(size); + } + + private void drawCoordinateSystem(Dimension size, Plot plot) { + g3.setColor(foreground); + plot.getCoordinateSystem().renderWith(createRenderer()); + } + + /** + * Prepare graphics context before drawing the pre-rendered view of the + * coordinate system. Does nothing but will be used in subclasses. + */ + protected void prepare() { + } + + /** + * Calculate the transformation form device-independent coordinates into + * device-dependent coordinates according to the specified canvas size. + */ + protected void calculateTransformation(Dimension size) { + _transformation = new Transformation(size.width, size.height, getPaper(), getHorizontalAnchor(), + getVerticalAnchor()); + } + + /** + * Creates an appropriated {@link Renderer} for the specified + * Graphics context. + */ + protected Renderer createRenderer() { + return ((Graphics2DRenderer) Factory.create(_renderer)).init(g3); + // return ((GraphicsRenderer) Factory.create(_renderer)).init(g, null, + // _transformation); + } + + /** + * Sets the renderer used to render the plot. The default value is + * {@link GraphicsRenderer}. + * + * @param className + * Fully qualified name of the renderer class. + */ + public void setRenderer(String className) { + _renderer = className; + } + + // /** + // * Maps the cursor position onto a point in device-independent + // coordinates. + // * + // * @param x + // * X-coordinate of the cursor. + // * @param y + // * Y-coordinate of the cursor. + // */ + // public GraphPoint mapCursorPosition(int x, int y) { + // return _transformation.transformBack(x, y); + // } + + /** + * Defines a graphical marker which will be drawn on top of the plot. To + * remove the marker call this method with argument null. + * + * @param marker + * Marker element. Can be null. + */ + public void setMarker(GraphicalElement marker) { + _marker = marker; + } + +} diff --git a/src/jcckit/data/DataContainer.java b/src/jcckit/data/DataContainer.java new file mode 100644 index 00000000000..831ad0b320d --- /dev/null +++ b/src/jcckit/data/DataContainer.java @@ -0,0 +1,182 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.data; + +import java.text.MessageFormat; +import java.util.Vector; + +/** + * Abstract superclass of all data containers. A data container holds an + * ordered list of {@link DataElement DataElements} of the same type. + *

+ * Data elements can be added, inserted, removed, or replaced. + * Such an action leads to a {@link DataEvent} which will be delivered to + * all {@link DataListener DataListeners} observing this + * DataContainer. If this data container also implements + * {@link DataEvent} (as {@link DataCurve} does) also the listeners + * registrated at the data container containg this container will be notified. + * As a consequence a DataListener must only be registered at the + * {@link DataPlot} instance and it will automatically also received events + * caused by manipulating one of its DataCurves. + *

+ * Concrete subclasses have to implement {@link #isValid} which + * checks whether the added or inserted DataElement is of the right + * type. This is an application of the Template Method Design Pattern. + * + * @author Franz-Josef Elmer + */ +public abstract class DataContainer { + private final static String TEMPLATE + = "Invalid operation: {0}, Element: {1}, Container: {2}"; + final static String ADD = "add", + REPLACE = "replace", + INSERT = "insert"; + + private final Vector _listeners = new Vector(); + private final Vector _container = new Vector(); + + /** Adds a {@link DataListener}. Does nothing if already added. */ + public void addDataListener(DataListener listener) { + if (!_listeners.contains(listener)) { + _listeners.addElement(listener); + } + } + + /** Removes a {@link DataListener}. Does nothing if already removed. */ + public void removeDataListener(DataListener listener) { + _listeners.removeElement(listener); + } + + private void notifyListeners(DataEvent event) { + for (int i = 0, n = _listeners.size(); i < n; i++) { + ((DataListener) _listeners.elementAt(i)).dataChanged(event); + } + // Notifies also parent container + if (this instanceof DataElement) { + DataContainer container = ((DataElement) this).getContainer(); + if (container != null) { + container.notifyListeners(event); + } + } + } + + /** Returns the number of elements of this container. */ + public int getNumberOfElements() { + return _container.size(); + } + + /** Returns the element for the specified index. */ + public DataElement getElement(int index) { + return (DataElement) _container.elementAt(index); + } + + /** + * Returns the index of the specified element. + * @param element Element to be looked for. + * @return -1 if not found. + */ + public int getIndexOf(DataElement element) { + return _container.indexOf(element); + } + + /** + * Adds a {@link DataElement}. After the element has been successfully + * added all {@link DataListener DataListeners} will be informed. + * @param element DataElement to be added. + * @throws IllegalArgumentException if element is not of the correct + * type which will be checked by the method {@link #isValid}. + */ + public void addElement(DataElement element) { + if (isValid(element)) { + _container.addElement(element); + element.setContainer(this); + notifyListeners(DataEvent.createAddEvent(this)); + } else { + throwException(ADD, element); + } + } + + /** + * Inserts a {@link DataElement} at the specified index. + * After the element has been successfully inserted + * all {@link DataListener DataListeners} will be informed. + * @param index Index at which element will be inserted. + * All elements with an index >= index will be shifted. + * @param element DataElement to be added. + * @throws IllegalArgumentException if element is not of the correct + * type which will be checked by the method {@link #isValid}. + */ + public void insertElementAt(int index, DataElement element) { + if (isValid(element)) { + _container.insertElementAt(element, index); + element.setContainer(this); + notifyListeners(DataEvent.createInsertEvent(this, index)); + } else { + throwException(INSERT, element); + } + } + + /** + * Removes a {@link DataElement} at the specified index. + * After the element has been successfully removed + * all {@link DataListener DataListeners} will be informed. + * @param index Index of the element which will be removed. + * All elements with an index > index will be shifted. + */ + public void removeElementAt(int index) { + DataElement element = (DataElement) _container.elementAt(index); + element.setContainer(null); + _container.removeElementAt(index); + notifyListeners(DataEvent.createRemoveEvent(this, index, element)); + } + + /** + * Replaces the {@link DataElement} at the specified index. + * After the element has been successfully replaced + * all {@link DataListener DataListeners} will be informed. + * @param index Index of the element which will be replaced by + * element. + * @param element The new DataElement. + * @throws IllegalArgumentException if element is not of the correct + * type which will be checked by the method {@link #isValid}. + */ + public void replaceElementAt(int index, DataElement element) { + if (isValid(element)) { + DataElement oldElement = (DataElement) _container.elementAt(index); + oldElement.setContainer(null); + _container.setElementAt(element, index); + element.setContainer(this); + notifyListeners(DataEvent.createReplaceEvent(this, index, oldElement)); + } else { + throwException(REPLACE, element); + } + } + + private void throwException(String operation, DataElement element) { + throw new IllegalArgumentException(MessageFormat.format(TEMPLATE, + new Object[] {operation, element, this.getClass().getName()})); + } + + /** + * Returns true if the specified {@link DataElement} has the + * correct type. Concrete subclasses have to implement this method. + * @param element DataElement to be checked. + */ + protected abstract boolean isValid(DataElement element); +} diff --git a/src/jcckit/data/DataCurve.java b/src/jcckit/data/DataCurve.java new file mode 100644 index 00000000000..caf94f3fcc0 --- /dev/null +++ b/src/jcckit/data/DataCurve.java @@ -0,0 +1,93 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.data; + +import jcckit.util.ConfigParameters; + +/** + * A curve is a {@link DataContainer} of {@link DataPoint DataPoints}. + * + * @author Franz-Josef Elmer + */ +public class DataCurve extends DataContainer implements DataElement { + /** Config parameter key. */ + public static final String X_KEY = "x", + Y_KEY = "y", + TITLE_KEY = "title"; + + private final String _title; + private DataContainer _container; + + /** Creates an empty instance with the specified title. */ + public DataCurve(String title) { + _title = title; + } + + /** + * Creates an instance from the specified config parameters. + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
title = empty stringStringnoCurve title.
xdouble[]yesx-coordinates of the curve points.
ydouble[]yesy-coordinates of the curve points.
+ */ + public DataCurve(ConfigParameters config) { + this(config.get(TITLE_KEY, "")); + double[] xPoints = config.getDoubleArray(X_KEY); + double[] yPoints = config.getDoubleArray(Y_KEY); + int n = Math.min(xPoints.length, yPoints.length); + for (int i = 0; i < n; i++) { + addElement(new DataPoint(xPoints[i], yPoints[i])); + } + } + + /** + * Returns the {@link DataPlot} containing this curve. + */ + public DataContainer getContainer() { + return _container; + } + + + /** + * Sets the {@link DataPlot} where this is a curve of. + */ + public void setContainer(DataContainer container) { + _container = container; + } + + /** Returns the title of this curve. */ + public String getTitle() { + return _title; + } + + /** + * Returns true if element is an instance of + * {@link DataPoint}. + */ + protected boolean isValid(DataElement element) { + return element instanceof DataPoint; + } +} diff --git a/src/jcckit/data/DataElement.java b/src/jcckit/data/DataElement.java new file mode 100644 index 00000000000..a66ce49935c --- /dev/null +++ b/src/jcckit/data/DataElement.java @@ -0,0 +1,40 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.data; + +/** + * Interface for all kinds of data elements. + * + * @author Franz-Josef Elmer + */ +public interface DataElement { + /** + * Returns the container containing this element. + * @return null if this element is not an element of a container. + */ + public DataContainer getContainer(); + + /** + * Sets the container which should contain this element. + * This method should not used outside {@link DataContainer}.. + * @param container Container which should contains this element. Cann be + * null if this element does not belong to a container. + */ + public void setContainer(DataContainer container); +} diff --git a/src/jcckit/data/DataEvent.java b/src/jcckit/data/DataEvent.java new file mode 100644 index 00000000000..8839f1350ee --- /dev/null +++ b/src/jcckit/data/DataEvent.java @@ -0,0 +1,128 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.data; + +/** + * Event to be sent to a {@link DataListener}. + * + * @author Franz-Josef Elmer + */ +public class DataEvent { + private final DataContainer _container; + private final DataEventType _type; + private final int _index; + private final DataElement _deletedElement; + + /** + * Creates an instance for the specified parameters. + * @param container The container which has been changed. + * @param type Type of change. + * @param index Index of the element which has been added, inserted, + * replaced, or removed. + * @param deletedElement Element which has been replaced or removed. + */ + private DataEvent(DataContainer container, DataEventType type, int index, + DataElement deletedElement) { + _container = container; + _type = type; + _index = index; + _deletedElement = deletedElement; + } + + /** + * Creates an event of type {@link DataEventType#ELEMENT_ADDED} for the + * specified container. + * @param container Container where an element has been added. + * @return ELEMENT_ADDED event. + */ + public static final DataEvent createAddEvent(DataContainer container) { + return new DataEvent(container, DataEventType.ELEMENT_ADDED, + container.getNumberOfElements() - 1, null); + } + + /** + * Creates an event of type {@link DataEventType#ELEMENT_INSERTED} for the + * specified container. + * @param container Container where an element has been inserted. + * @param index Index at which an element has been inserted. + * @return ELEMENT_INSERTED event. + */ + public static final DataEvent createInsertEvent(DataContainer container, + int index) { + return new DataEvent(container, DataEventType.ELEMENT_INSERTED, index, + null); + } + + /** + * Creates an event of type {@link DataEventType#ELEMENT_REPLACED} for the + * specified container. + * @param container Container where an element has been replaced. + * @param index Index of the replaced element. + * @param replacedElement The previous element at index. + * @return ELEMENT_REPLACED event. + */ + public static final DataEvent createReplaceEvent(DataContainer container, + int index, DataElement replacedElement) { + return new DataEvent(container, DataEventType.ELEMENT_REPLACED, index, + replacedElement); + } + + /** + * Creates an event of type {@link DataEventType#ELEMENT_REMOVED} for the + * specified container. + * @param container Container where an element has been removed. + * @param index Index of the removed element. + * @param removedElement The previous element at index. + * @return ELEMENT_REMOVED event. + */ + public static final DataEvent createRemoveEvent(DataContainer container, + int index, DataElement removedElement) { + return new DataEvent(container, DataEventType.ELEMENT_REMOVED, index, + removedElement); + } + + /** Returns the container. */ + public DataContainer getContainer() { + return _container; + } + + /** + * Returns the event type. Will be one of the constants + * {@link DataEventType#ELEMENT_ADDED}, + * {@link DataEventType#ELEMENT_INSERTED}, + * {@link DataEventType#ELEMENT_REMOVED}, or + * {@link DataEventType#ELEMENT_REPLACED}. + */ + public DataEventType getType() { + return _type; + } + + /** Returns the index. */ + public int getIndex() { + return _index; + } + + /** + * Returns the deleted element. + * @return null if either an element has been added or inserted. + */ + public DataElement getDeletedElement() { + return _deletedElement; + } +} diff --git a/src/jcckit/data/DataEventType.java b/src/jcckit/data/DataEventType.java new file mode 100644 index 00000000000..116139b33d6 --- /dev/null +++ b/src/jcckit/data/DataEventType.java @@ -0,0 +1,35 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.data; + +/** + * Type of a {@link DataEvent}. Implements the typesafe enumeration pattern. + * + * @author Franz-Josef Elmer + */ +public class DataEventType { + private DataEventType() {} + + /** Event type. */ + public static final DataEventType ELEMENT_ADDED = new DataEventType(), + ELEMENT_INSERTED = new DataEventType(), + ELEMENT_REPLACED = new DataEventType(), + ELEMENT_REMOVED = new DataEventType(); + +} diff --git a/src/jcckit/data/DataListener.java b/src/jcckit/data/DataListener.java new file mode 100644 index 00000000000..cd2c708412f --- /dev/null +++ b/src/jcckit/data/DataListener.java @@ -0,0 +1,33 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.data; + +/** + * An interface all observers of {@link DataEvent DataEvents} + * have to implement. + * + * @author Franz-Josef Elmer + */ +public interface DataListener { + /** + * Sends the specified data event to this object. + * @param event Data event informing where and what happened. + */ + public void dataChanged(DataEvent event); +} diff --git a/src/jcckit/data/DataPlot.java b/src/jcckit/data/DataPlot.java new file mode 100644 index 00000000000..4ebf14f9442 --- /dev/null +++ b/src/jcckit/data/DataPlot.java @@ -0,0 +1,74 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.data; + +import java.util.StringTokenizer; + +import jcckit.util.ConfigParameters; + +/** + * A plot is a {@link DataContainer} of {@link DataCurve DataCurves}. + * + * @author Franz-Josef Elmer + */ +public class DataPlot extends DataContainer { + /** Config parameter key. */ + public static final String CURVES_KEY = "curves", + DATA_KEY = "data"; + + /** Creates an empty instance. */ + public DataPlot() {} + + /** + * Creates an instance from the specified config parameters. + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
curvesString[]yesList of keys denoting data curves. Each key refers to + * config parameters used in the + * + * constructor of {@link DataCurve}.
+ */ + public DataPlot(ConfigParameters config) { + StringTokenizer tokenizer = new StringTokenizer(config.get(CURVES_KEY)); + while (tokenizer.hasMoreTokens()) { + addElement(new DataCurve(config.getNode(tokenizer.nextToken()))); + } + } + + /** + * Convenient method to create a DataPlot based on the specified + * config parameters. It is a short-cut of + * new DataPlot(config.getNode("data")). + */ + public static DataPlot create(ConfigParameters config) { + return new DataPlot(config.getNode(DATA_KEY)); + } + + /** + * Returns true if element is an instance of + * {@link DataCurve}. + */ + protected boolean isValid(DataElement element) { + return element instanceof DataCurve; + } +} + diff --git a/src/jcckit/data/DataPoint.java b/src/jcckit/data/DataPoint.java new file mode 100644 index 00000000000..38810ebf3ac --- /dev/null +++ b/src/jcckit/data/DataPoint.java @@ -0,0 +1,40 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.data; + +import jcckit.util.Point; + +/** + * Immutable two-dimensional point in data coordinates. + * + * @author Franz-Josef Elmer + */ +public class DataPoint extends Point implements DataElement { + public DataPoint(double x, double y) { + super(x, y); + } + + /** Returns always null. */ + public DataContainer getContainer() { + return null; + } + + /** Does nothing. */ + public void setContainer(DataContainer container) {} +} diff --git a/src/jcckit/graphic/Anchor.java b/src/jcckit/graphic/Anchor.java new file mode 100644 index 00000000000..71ad63638e8 --- /dev/null +++ b/src/jcckit/graphic/Anchor.java @@ -0,0 +1,129 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +import jcckit.util.ConfigParameters; +import jcckit.util.FactoryException; + +/** + * Anchor of a graphical element. There exist only the three + * instances {@link #LEFT_BOTTOM}, {@link #CENTER}, and + * {@link #RIGHT_TOP}. + *

+ * The anchor factor can be used in a position formular. Its value + * for the three instances reads: + *

+ *

+ * + * + * + * + * + *
InstanceFactor
LEFT_BOTTOM0
CENTER1
RIGHT_TOP2
+ *
+ * + * @author Franz-Josef Elmer + */ +public class Anchor { + /** Anchor constant. */ + public static final Anchor LEFT_BOTTOM = new Anchor(0), + CENTER = new Anchor(1), + RIGHT_TOP = new Anchor(2); + private static final String LEFT_VALUE = "left", + RIGHT_VALUE = "right", + CENTER_VALUE = "center", + TOP_VALUE = "top", + BOTTOM_VALUE = "bottom"; + + /** + * Returns form the specified configuration parameters the + * horizontal anchor defined by the specified key or the + * specified default value. + * @param config Configuration parameters. + * @param key The key of the anchor. null is not allowed. + * @param defaultValue The default value. + * @return one of the three instances of Anchor. + * @throws FactoryException if the value of key is + * neither left, center, + * nor right. + * Note, that {@link FactoryException#getClassName()} + * returns the invalid value. + */ + public static Anchor getHorizontalAnchor(ConfigParameters config, String key, + Anchor defaultValue) { + Anchor result = defaultValue; + String anchor = config.get(key, null); + if (anchor != null) { + if (anchor.equals(LEFT_VALUE)) { + result = Anchor.LEFT_BOTTOM; + } else if (anchor.equals(CENTER_VALUE)) { + result = Anchor.CENTER; + } else if (anchor.equals(RIGHT_VALUE)) { + result = Anchor.RIGHT_TOP; + } else { + throw new FactoryException(config, key, "Invalid horizontal anchor."); + } + } + return result; + } + + /** + * Returns form the specified configuration parameters the + * vertical anchor defined by the specified key or the + * specified default value. + * @param config Configuration parameters. + * @param key The key of the anchor. null is not allowed. + * @param defaultValue The default value. + * @return one of the three instances of Anchor. + * @throws FactoryException if the value of key is + * neither top, center, + * nor bottom. + * Note, that {@link FactoryException#getClassName()} + * returns the invalid value. + */ + public static Anchor getVerticalAnchor(ConfigParameters config, String key, + Anchor defaultValue) { + Anchor result = defaultValue; + String anchor = config.get(key, null); + if (anchor != null) { + if (anchor.equals(BOTTOM_VALUE)) { + result = Anchor.LEFT_BOTTOM; + } else if (anchor.equals(CENTER_VALUE)) { + result = Anchor.CENTER; + } else if (anchor.equals(TOP_VALUE)) { + result = Anchor.RIGHT_TOP; + } else { + throw new FactoryException(config, key, "Invalid vertcal anchor."); + } + } + return result; + } + + private final int _factor; + + private Anchor(int factor) { + _factor = factor; + } + + /** Returns the factor. */ + public int getFactor() { + return _factor; + } +} + diff --git a/src/jcckit/graphic/BasicGraphicAttributes.java b/src/jcckit/graphic/BasicGraphicAttributes.java new file mode 100644 index 00000000000..5b63ff161d5 --- /dev/null +++ b/src/jcckit/graphic/BasicGraphicAttributes.java @@ -0,0 +1,202 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +import java.awt.Color; + +import jcckit.util.ConfigParameters; + +/** + * The basic attributes of any {@link BasicGraphicalElement}. This is an + * extension of {@link ShapeAttributes} implementing {@link TextAttributes}. + * + * @author Franz-Josef Elmer + */ +public class BasicGraphicAttributes extends ShapeAttributes + implements TextAttributes { + /** Configuration parameter key. */ + public static final String TEXT_COLOR_KEY = "textColor", + FONT_NAME_KEY = "fontName", + FONT_STYLE_KEY = "fontStyle", + FONT_SIZE_KEY = "fontSize", + HORIZONTAL_ANCHOR_KEY = "horizontalAnchor", + VERTICAL_ANCHOR_KEY = "verticalAnchor", + ORIENTATION_ANGLE_KEY = "orientationAngle"; + + private final Color _textColor; + private final String _fontName; + private final FontStyle _fontStyle; + private final double _fontSize; + private final double _orientationAngle; + private final Anchor _horizontalAnchor; + private final Anchor _verticalAnchor; + + /** + * Creates a new instance based on the specified configuration + * parameters. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
textColor = default foreground color of the + * rendererColornoThe text color.
fontName = default font name of the + * rendererStringnoThe name of the text font. The standard Java font name + * "Serif", "SansSerif", and "Monospaced" can be used. + * Other font names depend on the actual {@link Renderer} + * rendering the corresponding {@link BasicGraphicalElement}. + *
fontStyle = normalString + * noThe font style. Possible values are: + *
  • normal
  • bold
  • italic + *
  • bold italic
+ *
fontSize = default font size of the + * rendererdoublenoThe font size in units of the device-independent + * coordinates.
orientationAngle = 0doublenoThe orientation angle of the text (in degree). + * Zero means normal orientation whereas a positive value means + * a rotation in counter-clockweise direction.
horizontalAnchor = leftString + * noAnchor for horizontal text position. Possible values are + * left, center, and right.
verticalAnchor = centerString + * noAnchor for vertical text position. Possible values are + * top, center, and bottom.
+ * Additional configuration parameters are explained in the + * {@link ShapeAttributes#ShapeAttributes constructor} + * of the superclass {@link ShapeAttributes}. + */ + public BasicGraphicAttributes(ConfigParameters config) { + super(config); + _textColor = config.getColor(TEXT_COLOR_KEY, null); + _fontName = config.get(FONT_NAME_KEY, null); + _fontStyle = FontStyle.getFontStyle(config, FONT_STYLE_KEY, + FontStyle.NORMAL); + _fontSize = config.getDouble(FONT_SIZE_KEY, 0); + _orientationAngle = config.getDouble(ORIENTATION_ANGLE_KEY, 0); + + _horizontalAnchor = Anchor.getHorizontalAnchor(config, + HORIZONTAL_ANCHOR_KEY, Anchor.LEFT_BOTTOM); + _verticalAnchor = Anchor.getVerticalAnchor(config, + VERTICAL_ANCHOR_KEY, Anchor.CENTER); + } + + /** + * Creates a new instance. + * @param fillColor The fill color. May be null. + * @param lineColor The line color. May be null. + * @param lineThickness Thickness of the line. + * Negative numbers will be trimmed to zero. + * @param linePattern Line pattern. May be null. + * @param textColor The text color. May be null. + * @param fontName The font name. May be null. + * @param fontStyle The font style. May be null. + * @param fontSize The font size in units of the device-independent + * coordinates. May be null. + * @param orientationAngle Orientation angle of the text. + * @param horizontalAnchor Horizontal text anchor. + * @param verticalAnchor Vertical text anchor. + */ + public BasicGraphicAttributes(Color fillColor, Color lineColor, + double lineThickness, + double[] linePattern, Color textColor, + String fontName, FontStyle fontStyle, + double fontSize, double orientationAngle, + Anchor horizontalAnchor, + Anchor verticalAnchor) { + super(fillColor, lineColor, lineThickness, linePattern); + _textColor = textColor; + _fontName = fontName; + _fontStyle = fontStyle; + _fontSize = fontSize; + _orientationAngle = orientationAngle; + _horizontalAnchor = horizontalAnchor; + _verticalAnchor = verticalAnchor; + } + + /** + * Returns the text color. + * @return null means default color of the renderer. + */ + public Color getTextColor() { + return _textColor; + } + + /** + * Returns the font name. + * @return null means default font name of the renderer. + */ + public String getFontName() { + return _fontName; + } + + /** + * Returns the font style. + * @return null means default font style of the renderer. + */ + public FontStyle getFontStyle() { + return _fontStyle; + } + + /** + * Returns the font size in units of the device-independent coordinates. + */ + public double getFontSize() { + return _fontSize; + } + + /** + * Returns the orientation angle in degree. Zero means + * normal text orientation. Any positive angle means a + * counter-clockwise rotation of the text. + */ + public double getOrientationAngle() { + return _orientationAngle; + } + + /** + * Returns the anchor for horizontal position of the text. + * Note, that the anchor is related to the text before + * it is rotated by the orientation angle. + * @return one of the three instances of Anchor. + */ + public Anchor getHorizontalAnchor() { + return _horizontalAnchor; + } + + /** + * Returns the anchor for vertical position of the text. + * Note, that the anchor is related to the text before + * it is rotated by the orientation angle. + * @return one of the three instances of Anchor. + */ + public Anchor getVerticalAnchor() { + return _verticalAnchor; + } +} + diff --git a/src/jcckit/graphic/BasicGraphicalElement.java b/src/jcckit/graphic/BasicGraphicalElement.java new file mode 100644 index 00000000000..37ed247ff23 --- /dev/null +++ b/src/jcckit/graphic/BasicGraphicalElement.java @@ -0,0 +1,58 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Abstract superclass of all basic {@link GraphicalElement + * GraphicalElements}. Concrete subclasses have to implement + * the method {@link GraphicalElement#renderWith}. + * + * @author Franz-Josef Elmer + */ +public abstract class BasicGraphicalElement implements GraphicalElement { + private final GraphicAttributes _attributes; + + /** + * Creates an instance with the specified drawing attributes. + * Note, that a {@link Renderer} should use default attributes + * in the case no attributes are defined. + * @param attributes Drawing attributes or null if undefined. + */ + public BasicGraphicalElement(GraphicAttributes attributes) { + _attributes = attributes; + } + + /** + * Returns the drawing attributes. + * @return null if undefined. + */ + public GraphicAttributes getGraphicAttributes() { + return _attributes; + } + + /** + * Returns whether this basic graphical element has a closed shape + * or not. By default always true. Subclasses may override + * this behaviour. + * @return true if the shape is closed. + */ + public boolean isClosed() { + return true; + } +} diff --git a/src/jcckit/graphic/ClippingRectangle.java b/src/jcckit/graphic/ClippingRectangle.java new file mode 100644 index 00000000000..3c56241c2a3 --- /dev/null +++ b/src/jcckit/graphic/ClippingRectangle.java @@ -0,0 +1,81 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Immutable class of a rectangular clipping area. + * + * @author Franz-Josef Elmer + */ +public class ClippingRectangle implements ClippingShape { + private final double _minX, _minY, _maxX, _maxY; + + /** + * Creates an instance for the specified coordinates of + * two opposite corner points. + */ + public ClippingRectangle(double x1, double y1, double x2, double y2) { + _minX = Math.min(x1, x2); + _minY = Math.min(y1, y2); + _maxX = Math.max(x1, x2); + _maxY = Math.max(y1, y2); + } + + /** + * Returns true if the specified point is inside this + * rectangle. + */ + public boolean isInside(GraphPoint point) { + double x = point.getX(); + double y = point.getY(); + return _minX <= x && x <= _maxX && _minY <= y && y <= _maxY; + } + + /** Returns the minimum x value. */ + public double getMinX() { + return _minX; + } + + /** Returns the maximum x value. */ + public double getMaxX() { + return _maxX; + } + + /** Returns the minimum y value. */ + public double getMinY() { + return _minY; + } + + /** Returns the maximum y value. */ + public double getMaxY() { + return _maxY; + } + + /** Returns this instance. */ + public ClippingRectangle getBoundingBox() { + return this; + } + + /** Returns a {@link Rectangle}. */ + public BasicGraphicalElement getGraphicalElement() { + return new Rectangle(new GraphPoint(0.5 * (_minX + _maxX), + 0.5 * (_minY + _maxY)), + _maxX - _minX, _maxY - _minY, null); + } +} diff --git a/src/jcckit/graphic/ClippingShape.java b/src/jcckit/graphic/ClippingShape.java new file mode 100644 index 00000000000..8559a9e8bc7 --- /dev/null +++ b/src/jcckit/graphic/ClippingShape.java @@ -0,0 +1,47 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Defining a clipping shape applied to all {@link GraphicalElement + * GraphicalElements} of a {@link GraphicalComposite}. + * + * @author Franz-Josef Elmer + */ +public interface ClippingShape { + /** + * Returns true if the specified point is inside this + * clipping shape. + */ + public boolean isInside(GraphPoint point); + + /** + * Returns the bounding box of this clipping shape. + * This method will be used by renderers who supports only + * rectangular clipping shapes. + */ + public ClippingRectangle getBoundingBox(); + + /** + * Returns a basic graphical element (such as {@link Rectangle} + * or {@link Polygon}) which may be used by renderers to + * define the clipping shape for the output device. + */ + public BasicGraphicalElement getGraphicalElement(); +} diff --git a/src/jcckit/graphic/FillAttributes.java b/src/jcckit/graphic/FillAttributes.java new file mode 100644 index 00000000000..7af1b56f298 --- /dev/null +++ b/src/jcckit/graphic/FillAttributes.java @@ -0,0 +1,35 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +import java.awt.Color; + +/** + * Interface for fill attributes. + * + * @author Franz-Josef Elmer + */ +public interface FillAttributes extends GraphicAttributes { + /** + * Returns the fill color. + * @return null means no filling. + */ + public Color getFillColor(); +} + diff --git a/src/jcckit/graphic/FontStyle.java b/src/jcckit/graphic/FontStyle.java new file mode 100644 index 00000000000..7c037d9c32b --- /dev/null +++ b/src/jcckit/graphic/FontStyle.java @@ -0,0 +1,82 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +import java.util.Hashtable; + +import jcckit.util.ConfigParameters; +import jcckit.util.FactoryException; + +/** + * Font style constants. + * This class is based on the typesafe enumeration pattern. + * + * @author Franz-Josef Elmer + */ +public class FontStyle { + private static final Hashtable REPOSITORY = new Hashtable(); + static final String NORMAL_TXT = "normal", + BOLD_TXT = "bold", + ITALIC_TXT = "italic", + BOLD_ITALIC_TXT = "bold italic"; + /** Font style constant. */ + public static final FontStyle NORMAL = new FontStyle(NORMAL_TXT), + BOLD = new FontStyle(BOLD_TXT), + ITALIC = new FontStyle(ITALIC_TXT), + BOLD_ITALIC = new FontStyle(BOLD_ITALIC_TXT); + + private final String _description; + + /** Non-public constructor to control the number of instances. */ + private FontStyle(String description) { + _description = description; + REPOSITORY.put(description, this); + } + + /** + * Returns from the specified configuration parameters the font style + * defined by the specified key or the specified default value. + * @param config Configuration parameters. + * @param key The key of the font style. + * @param defaultValue The default value. + * @return one of the four instances of FontStyle. + * @throws FactoryException if the value of the key-value pair denoted + * by key is neither normal, bold, + * italic, nor bold italic, + * Note, that {@link FactoryException#getClassName()} + * returns the invalid value. + */ + public static FontStyle getFontStyle(ConfigParameters config, String key, + FontStyle defaultValue) { + FontStyle result = defaultValue; + String value = config.get(key, null); + if (value != null) { + result = (FontStyle) REPOSITORY.get(value); + if (result == null) { + throw new FactoryException(config, key, "Invalid font style."); + } + } + return result; + } + + /** Returns a human readable description for pretty printing. */ + public String toString() { + return _description; + } +} diff --git a/src/jcckit/graphic/GraphPoint.java b/src/jcckit/graphic/GraphPoint.java new file mode 100644 index 00000000000..a85de78a30f --- /dev/null +++ b/src/jcckit/graphic/GraphPoint.java @@ -0,0 +1,43 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +import jcckit.util.Point; + +/** + * Immutable class of a two-dimensional point in the device-independent + * coordinate system. + * + * @author Franz-Josef Elmer + */ +public class GraphPoint extends Point { + /** + * Creates an instance for the specified vector. + * If vector is null or not long enough the + * default value 0 will be used instead. + */ + public GraphPoint(double[] vector) { + super(vector); + } + + /** Creates an instance for the specified coordinates. */ + public GraphPoint(double x, double y) { + super(x, y); + } +} diff --git a/src/jcckit/graphic/GraphicAttributes.java b/src/jcckit/graphic/GraphicAttributes.java new file mode 100644 index 00000000000..a418c1cd14a --- /dev/null +++ b/src/jcckit/graphic/GraphicAttributes.java @@ -0,0 +1,36 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Marker interface for all types of graphic attributes + * of a {@link BasicGraphicalElement}. Graphic attributes are only + * hints for {@link Renderer Renderers} how to render a + * BasicGraphicalElement. Whether they are used and how + * they are interpreted depends on the concrete Renderer. + *

+ * This is only a marker interface. There are several subinterfaces + * specifying various attributes grouped by the type of element to + * be rendered. + * + * @author Franz-Josef Elmer + */ +public interface GraphicAttributes { +} + diff --git a/src/jcckit/graphic/GraphicalComposite.java b/src/jcckit/graphic/GraphicalComposite.java new file mode 100644 index 00000000000..b981343d7b6 --- /dev/null +++ b/src/jcckit/graphic/GraphicalComposite.java @@ -0,0 +1,106 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +import java.util.Vector; + +/** + * Container for {@link GraphicalElement GraphicalElements}. + * + * @author Franz-Josef Elmer + */ +public class GraphicalComposite implements GraphicalElement { + private final Vector _elements = new Vector(); + private final ClippingShape _clippingShape; + + /** + * Creates an instance with the specified clipping shape. + * @param clippingShape Clipping shape or null if no clipping. + */ + public GraphicalComposite(ClippingShape clippingShape) { + _clippingShape = clippingShape; + } + + /** + * Returns the clipping shape. + * @return null if no clipping should be applied. + */ + public ClippingShape getClippingShape() { + return _clippingShape; + } + + /** + * Adds the specified element at the end of the list of elements. + * @param element Element to be added. null is not allowed. + * @throws NullPointerException if element == null + */ + public void addElement(GraphicalElement element) { + if (element == null) { + throwNullPointerException(); + } else { + _elements.addElement(element); + } + } + + /** Remove all elements. */ + public void removeAllElements() { + _elements.removeAllElements(); + } + + /** + * Replaces the specified element at the specified index of + * the list of elements. + * @param element New element. null is not allowed. + * @throws NullPointerException if element == null + */ + public void replaceElementAt(int index, GraphicalElement element) { + if (element == null) { + throwNullPointerException(); + } else { + _elements.setElementAt(element, index); + } + } + + private void throwNullPointerException() { + throw new NullPointerException( + "A null as an GraphicalElement is not allowed"); + } + + /** + * Renders all {@link GraphicalElement GraphicalElements} in the sequence + * they have been added. + * @param renderer Renderer which implements all renderer interfaces + * necessary to render the child elements. + * @throws IllegalArgumentException if renderer is not + * an instance of GraphicalCompositeRenderer. + */ + public void renderWith(Renderer renderer) { + if (renderer instanceof GraphicalCompositeRenderer) { + GraphicalCompositeRenderer r = (GraphicalCompositeRenderer) renderer; + r.startRendering(this); + for (int i = 0, n = _elements.size(); i < n; i++) { + ((GraphicalElement) _elements.elementAt(i)).renderWith(r); + } + r.finishRendering(this); + } else { + throw new IllegalArgumentException(renderer + + " does not implements GraphicalCompositeRenderer."); + } + } +} diff --git a/src/jcckit/graphic/GraphicalCompositeRenderer.java b/src/jcckit/graphic/GraphicalCompositeRenderer.java new file mode 100644 index 00000000000..f3c7ba4027f --- /dev/null +++ b/src/jcckit/graphic/GraphicalCompositeRenderer.java @@ -0,0 +1,40 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Interface of all {@link Renderer Renderers} who render a + * {@link GraphicalComposite}. Note, that a + * GraphicalCompositeRenderer does not + * render the element of a GraphicalComposite + * + * @author Franz-Josef Elmer + */ +public interface GraphicalCompositeRenderer extends Renderer { + /** + * Starts rendering of the specified composite before its + * elements are rendererd. Implementations of this method + * usually obtain the {@link ClippingShape} from + * composite. + */ + public void startRendering(GraphicalComposite composite); + + /** Finishes rendering of the specified composite. */ + public void finishRendering(GraphicalComposite composite); +} diff --git a/src/jcckit/graphic/GraphicalElement.java b/src/jcckit/graphic/GraphicalElement.java new file mode 100644 index 00000000000..2b28fa40ade --- /dev/null +++ b/src/jcckit/graphic/GraphicalElement.java @@ -0,0 +1,41 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Interface all graphical elements have to implement. + * Together with the marker interface {@link Renderer} it + * realizes the Anticyclic Visitor Pattern, a variant of the + * GoF Visitor Pattern. This allows not only to extend JCCKit with + * new renderers but also with new types of GraphicalElements + * without touching existing code. + * + * @author Franz-Josef Elmer + */ +public interface GraphicalElement { + /** + * Renders this element according to the type of renderer. + * Concrete GraphicalElements who are not instances of + * {@link GraphicalComposite} dynamically cast renderer. + * If it does not implement the type of renderer specific for + * the concrete GraphicalElement it should throw an + * IllegalArgumentException. + */ + public abstract void renderWith(Renderer renderer); +} diff --git a/src/jcckit/graphic/LineAttributes.java b/src/jcckit/graphic/LineAttributes.java new file mode 100644 index 00000000000..2d8f7a17809 --- /dev/null +++ b/src/jcckit/graphic/LineAttributes.java @@ -0,0 +1,52 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +import java.awt.Color; + +/** + * Interface for line attributes. + * + * @author Franz-Josef Elmer + */ +public interface LineAttributes extends GraphicAttributes { + /** + * Returns the line color. + * @return null means default color of the renderer. + */ + public Color getLineColor(); + + /** + * Returns the line tickness. 0 means that the line thickness is + * chosen as thin as possible. + * Implementations have to guarantee that the returned value is + * never negative. + */ + public double getLineThickness(); + + /** + * Returns the line pattern. This is a sequence of length where the + * pen is down or up. The first element is the length where the + * pen is down. The next element is the length where the pen is up. + * The pattern is cyclically repeated. + * @return null means solid line. + */ + public double[] getLinePattern(); +} + diff --git a/src/jcckit/graphic/Oval.java b/src/jcckit/graphic/Oval.java new file mode 100644 index 00000000000..9d49621a608 --- /dev/null +++ b/src/jcckit/graphic/Oval.java @@ -0,0 +1,54 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * An oval (i.e. an ellipse). + * + * @author Franz-Josef Elmer + */ +public class Oval extends Rectangle { + /** + * Creates a new instance. + * @param center The position of the center of this element. + * @param width The width. + * @param height The height. + * @param attributes Drawing attributes. Can be null. + */ + public Oval(GraphPoint center, double width, double height, + GraphicAttributes attributes) { + super(center, width, height, attributes); + } + + /** + * Renders this oval with the specified {@link Renderer}. + * @param renderer An instance of {@link OvalRenderer}. + * @throws IllegalArgumentException if renderer is not + * an instance of OvalRenderer. + */ + public void renderWith(Renderer renderer) { + if (renderer instanceof OvalRenderer) { + ((OvalRenderer) renderer).render(this); + } else { + throw new IllegalArgumentException(renderer + + " does not implements OvalRenderer."); + } + } +} + diff --git a/src/jcckit/graphic/OvalRenderer.java b/src/jcckit/graphic/OvalRenderer.java new file mode 100644 index 00000000000..97108eb2eef --- /dev/null +++ b/src/jcckit/graphic/OvalRenderer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Interface of all {@link Renderer Renderers} who render a + * {@link Oval}. + * + * @author Franz-Josef Elmer + */ +public interface OvalRenderer extends Renderer { + /** Renders the specified oval. */ + public void render(Oval oval); +} diff --git a/src/jcckit/graphic/Polygon.java b/src/jcckit/graphic/Polygon.java new file mode 100644 index 00000000000..45245b4d897 --- /dev/null +++ b/src/jcckit/graphic/Polygon.java @@ -0,0 +1,85 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +import java.util.Vector; + +/** + * A polygon or polyline. + * + * @author Franz-Josef Elmer + */ +public class Polygon extends BasicGraphicalElement { + private final Vector _points = new Vector(); + private final boolean _closed; + + /** + * Creates an instance of the specified graphic attributes. + * @param closed true if this polygon is closed. + */ + public Polygon(GraphicAttributes attributes, boolean closed) { + super(attributes); + _closed = closed; + } + + /** Returns true if this polygon is closed. */ + public boolean isClosed() { + return _closed; + } + + /** Returns the number points. */ + public int getNumberOfPoints() { + return _points.size(); + } + + /** Returns the point for the specified index. */ + public GraphPoint getPoint(int index) { + return (GraphPoint) _points.elementAt(index); + } + + /** Adds a new point to the end of the list of points. */ + public void addPoint(GraphPoint point) { + _points.addElement(point); + } + + /** Removes all points. */ + public void removeAllPoints() { + _points.removeAllElements(); + } + + /** Replaces the point at the specified index by a new one. */ + public void replacePointAt(int index, GraphPoint point) { + _points.setElementAt(point, index); + } + + /** + * Renders this line with the specified {@link Renderer}. + * @param renderer An instance of {@link PolygonRenderer}. + * @throws IllegalArgumentException if renderer is not + * an instance of PolygonRenderer. + */ + public void renderWith(Renderer renderer) { + if (renderer instanceof PolygonRenderer) { + ((PolygonRenderer) renderer).render(this); + } else { + throw new IllegalArgumentException(renderer + + " does not implements PolygonRenderer."); + } + } +} diff --git a/src/jcckit/graphic/PolygonRenderer.java b/src/jcckit/graphic/PolygonRenderer.java new file mode 100644 index 00000000000..0c07f905d7c --- /dev/null +++ b/src/jcckit/graphic/PolygonRenderer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Interface of all {@link Renderer Renderers} who render an + * instance of {@link Polygon}. + * + * @author Franz-Josef Elmer + */ +public interface PolygonRenderer extends Renderer { + /** Renders the specified Polygon instance. */ + public void render(Polygon polygon); +} diff --git a/src/jcckit/graphic/Rectangle.java b/src/jcckit/graphic/Rectangle.java new file mode 100644 index 00000000000..f66a3c5f105 --- /dev/null +++ b/src/jcckit/graphic/Rectangle.java @@ -0,0 +1,76 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * A rectangle. + * + * @author Franz-Josef Elmer + */ +public class Rectangle extends BasicGraphicalElement { + private final GraphPoint _center; + private final double _width; + private final double _height; + + /** + * Creates a new instance. + * @param center The position of the center of this element. + * @param width The width. + * @param height The height. + * @param attributes Drawing attributes. Can be null. + */ + public Rectangle(GraphPoint center, double width, double height, + GraphicAttributes attributes) { + super(attributes); + _center = center; + _width = width; + _height = height; + } + + /** Returns the center of this element. */ + public GraphPoint getCenter() { + return _center; + } + + /** Returns the width of this element. */ + public double getWidth() { + return _width; + } + + /** Returns the height of this element. */ + public double getHeight() { + return _height; + } + + /** + * Renders this rectangle with the specified {@link Renderer}. + * @param renderer An instance of {@link RectangleRenderer}. + * @throws IllegalArgumentException if renderer is not + * an instance of RectangleRenderer. + */ + public void renderWith(Renderer renderer) { + if (renderer instanceof RectangleRenderer) { + ((RectangleRenderer) renderer).render(this); + } else { + throw new IllegalArgumentException(renderer + + " does not implements RectangleRenderer."); + } + } +} + diff --git a/src/jcckit/graphic/RectangleRenderer.java b/src/jcckit/graphic/RectangleRenderer.java new file mode 100644 index 00000000000..6a1d01c66fb --- /dev/null +++ b/src/jcckit/graphic/RectangleRenderer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Interface of all {@link Renderer Renderers} who render a + * {@link Rectangle}. + * + * @author Franz-Josef Elmer + */ +public interface RectangleRenderer extends Renderer { + /** Renders the specified rectangle. */ + public void render(Rectangle rectangle); +} diff --git a/src/jcckit/graphic/Renderer.java b/src/jcckit/graphic/Renderer.java new file mode 100644 index 00000000000..b3d722645a9 --- /dev/null +++ b/src/jcckit/graphic/Renderer.java @@ -0,0 +1,27 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Marker interface. Each subclass is an interface for a specific + * type of {@link GraphicalElement}. + * + * @author Franz-Josef Elmer + */ +public interface Renderer {} diff --git a/src/jcckit/graphic/ShapeAttributes.java b/src/jcckit/graphic/ShapeAttributes.java new file mode 100644 index 00000000000..362f3037d6c --- /dev/null +++ b/src/jcckit/graphic/ShapeAttributes.java @@ -0,0 +1,104 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +import java.awt.Color; + +import jcckit.util.ConfigParameters; + +/** + * Basic attributes for shapes. + * + * @author Franz-Josef Elmer + */ +public class ShapeAttributes implements LineAttributes, FillAttributes { + /** Configuration parameter key. */ + public static final String FILL_COLOR_KEY = "fillColor", + LINE_COLOR_KEY = "lineColor", + LINE_THICKNESS_KEY = "lineThickness", + LINE_PATTERN_KEY = "linePattern"; + + private final Color _fillColor; + private final Color _lineColor; + private final double _lineThickness; + private final double[] _linePattern; + + /** + * Creates a new instance based on the specified configuration + * parameters. + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
fillColor = no fillingColornoThe fill color of the shape.
lineColor = no lineColornoThe color of a line, a polygon, or the border of a shape.
lineThickness = 0doublenoThe thickness of a line. A thickness of zero means that + * the renderer will draw the thinest line possible.
linePattern = solid linedouble[]noA sequence of lengths where the pen is alternatively + * down or up. For example, 0.1 0.1 will lead to a dashed + * line whereas 0.02 0.02 is the pattern of a dotted + * line and 0.02 0.02 0.1 0.02 of a dashed-dotted + * line.
+ */ + public ShapeAttributes(ConfigParameters config) { + this(config.getColor(FILL_COLOR_KEY, null), + config.getColor(LINE_COLOR_KEY, null), + config.getDouble(LINE_THICKNESS_KEY, 0), + config.getDoubleArray(LINE_PATTERN_KEY, null)); + } + + /** + * Creates a new instance. + * @param fillColor The fill color. May be null. + * @param lineColor The line color. May be null. + * @param lineThickness Thickness of the line. + * Negative numbers will be trimmed to zero. + * @param linePattern Line pattern. May be null. + */ + public ShapeAttributes(Color fillColor, Color lineColor, + double lineThickness, double[] linePattern) { + _fillColor = fillColor; + _lineColor = lineColor; + _lineThickness = Math.max(0, lineThickness); + _linePattern = linePattern; + } + + public Color getFillColor() { + return _fillColor; + } + + public Color getLineColor() { + return _lineColor; + } + + public double getLineThickness() { + return _lineThickness; + } + + public double[] getLinePattern() { + return _linePattern; + } +} + diff --git a/src/jcckit/graphic/Text.java b/src/jcckit/graphic/Text.java new file mode 100644 index 00000000000..23133c26015 --- /dev/null +++ b/src/jcckit/graphic/Text.java @@ -0,0 +1,67 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * A single line of text. + * + * @author Franz-Josef Elmer + */ +public class Text extends BasicGraphicalElement { + private final GraphPoint _position; + private final String _text; + + + /** + * Creates an instance with the specified parameters. + * @param position Position of the text. + * @param text Text. + * @param attributes Drawing attributes. Can be null. + */ + public Text(GraphPoint position, String text, GraphicAttributes attributes) { + super(attributes); + _position = position; + _text = text; + } + + /** Returns the position. */ + public GraphPoint getPosition() { + return _position; + } + + /** Returns the text string. */ + public String getText() { + return _text; + } + + /** + * Renders this line with the specified {@link Renderer}. + * @param renderer An instance of {@link TextRenderer}. + * @throws IllegalArgumentException if renderer is not + * an instance of TextRenderer. + */ + public void renderWith(Renderer renderer) { + if (renderer instanceof TextRenderer) { + ((TextRenderer) renderer).render(this); + } else { + throw new IllegalArgumentException(renderer + + " does not implements TextRenderer."); + } + } +} diff --git a/src/jcckit/graphic/TextAttributes.java b/src/jcckit/graphic/TextAttributes.java new file mode 100644 index 00000000000..3e6080d8565 --- /dev/null +++ b/src/jcckit/graphic/TextAttributes.java @@ -0,0 +1,75 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +import java.awt.Color; + +/** + * Interface for text attributes. + * + * @author Franz-Josef Elmer + */ +public interface TextAttributes extends GraphicAttributes { + /** + * Returns the text color. + * @return null means default color of the renderer. + */ + public Color getTextColor(); + + /** + * Returns the font name. + * @return null means default font name of the renderer. + */ + public String getFontName(); + + /** + * Returns the font style. + * @return null means default font style of the renderer. + */ + public FontStyle getFontStyle(); + + /** + * Returns the font size in units of the device-independent coordinates. + */ + public double getFontSize(); + + /** + * Returns the orientation angle in degree. Zero means + * normal text orientation. Any positive angle means a + * counter-clockwise rotation of the text. + */ + public double getOrientationAngle(); + + /** + * Returns the anchor for horizontal position of the text. + * Note, that the anchor is related to the text before + * it is rotated by the orientation angle. + * @return one of the three instances of Anchor. + */ + public Anchor getHorizontalAnchor(); + + /** + * Returns the anchor for vertical position of the text. + * Note, that the anchor is related to the text before + * it is rotated by the orientation angle. + * @return one of the three instances of Anchor. + */ + public Anchor getVerticalAnchor(); +} + diff --git a/src/jcckit/graphic/TextRenderer.java b/src/jcckit/graphic/TextRenderer.java new file mode 100644 index 00000000000..98f2124ee66 --- /dev/null +++ b/src/jcckit/graphic/TextRenderer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.graphic; + +/** + * Interface of all {@link Renderer Renderers} who render an + * instance of {@link Text}. + * + * @author Franz-Josef Elmer + */ +public interface TextRenderer extends Renderer { + /** Renders the specified Text instance. */ + public void render(Text text); +} diff --git a/src/jcckit/plot/AbstractSymbolFactory.java b/src/jcckit/plot/AbstractSymbolFactory.java new file mode 100644 index 00000000000..f88f18abd96 --- /dev/null +++ b/src/jcckit/plot/AbstractSymbolFactory.java @@ -0,0 +1,120 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicAttributes; +import jcckit.graphic.GraphicalElement; +import jcckit.util.ConfigParameters; +import jcckit.util.Factory; + +/** + * Abstract superclass of all {@link SymbolFactory SymbolFactories}. + * Subclasses have to implement {@link #createPlainSymbol createPlainSymbol()}. + * + * @author Franz-Josef Elmer + */ +public abstract class AbstractSymbolFactory implements SymbolFactory { + /** Size of all symbols. */ + protected final double _size; + + /** Attributes of all symbols. */ + protected final GraphicAttributes _attributes; + + /** + * Creates an instance from the specified configuration parameters. + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
size = 0.01doublenoSize of the symbol in device-independent units.
attributesConfigParametersnoConfiguration parameters for the attributes of the symbol. + * className has to be a class which is an instance of + * {@link GraphicAttributes}.
+ */ + public AbstractSymbolFactory(ConfigParameters config) { + _size = config.getDouble(SIZE_KEY, DEFAULT_SIZE); + _attributes = (GraphicAttributes) Factory.createOrGet( + config.getNode(ATTRIBUTES_KEY), null); + } + + /** + * Creates a symbol. + * Evaluate hintFromPreviousPoint if it is a {@link AttributesHint}. + * Calls {@link #createSymbol(GraphPoint, GraphicAttributes, Hint, Hint)}. + * @param point Symbol position. + * @param hintFromPreviousPoint Hint from the previous point. + * @param hintFromPreviousCurve Hint from the previous curve. + */ + public Symbol createSymbol(GraphPoint point, Hint hintFromPreviousPoint, + Hint hintFromPreviousCurve) { + GraphicAttributes attributes = _attributes; + Hint hintForNextPoint = hintFromPreviousPoint; + if (hintFromPreviousPoint instanceof AttributesHint) { + attributes = ((AttributesHint) hintFromPreviousPoint).getAttributes(); + hintForNextPoint + = ((AttributesHint) hintFromPreviousPoint).getNextHint(); + } + return createSymbol(point, attributes, hintForNextPoint, + hintFromPreviousCurve); + } + + /** + * Creates a symbol. + * Uses {@link #createPlainSymbol createPlainSymbol()}. + * @param point Symbol position. + * @param attributes Symbol attributes. + * @param hintForNextPoint Hint for the next point. Will be delivered + * unchanged in the return Symbol object. + * @param hintFromPreviousCurve Hint from the previous curve. + * Will be delivered unchanged in the return Symbol object. + * Subclasses may override this behavior. + */ + protected Symbol createSymbol(GraphPoint point, GraphicAttributes attributes, + Hint hintForNextPoint, + Hint hintFromPreviousCurve) { + return new Symbol(createPlainSymbol(point, _size, attributes), + hintForNextPoint, hintFromPreviousCurve); + } + + /** + * Creates a symbol for the legend at the specified position. + * Uses {@link #createPlainSymbol createPlainSymbol()} + * @param centerPosition Center position of the symbol. + * @param size The size of the symbol. Will be ignored because the value + * given in the constructor will be used. + */ + public GraphicalElement createLegendSymbol(GraphPoint centerPosition, + double size) { + return createPlainSymbol(centerPosition, _size, _attributes); + } + + /** + * Creates the graphical element of the plain symbol. + * @param centerPosition Center position of the symbol. + * @param size The size of the symbol. + * @param attributes The attributes of the symbol. + */ + protected abstract GraphicalElement createPlainSymbol( + GraphPoint centerPosition, double size, GraphicAttributes attributes); +} diff --git a/src/jcckit/plot/AttributesHint.java b/src/jcckit/plot/AttributesHint.java new file mode 100644 index 00000000000..0ab44166ff9 --- /dev/null +++ b/src/jcckit/plot/AttributesHint.java @@ -0,0 +1,39 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.GraphicAttributes; + +/** + * A {@link Hint} which wraps a {@link GraphicAttributes} instance. + * In addition the method {@link #getNextHint()} creates a new instance + * with different attributes derivated from the wrapped attributes. + * + * @author Franz-Josef Elmer + */ +public interface AttributesHint extends Hint { + /** + * Returns the hint for the next {@link Symbol} of a {@link Curve}. + * The new hint has a different {@link GraphicAttributes}. + */ + public AttributesHint getNextHint(); + + /** Returns the attributes value. */ + public GraphicAttributes getAttributes(); +} diff --git a/src/jcckit/plot/AxisParameters.java b/src/jcckit/plot/AxisParameters.java new file mode 100644 index 00000000000..3fd2aa089f6 --- /dev/null +++ b/src/jcckit/plot/AxisParameters.java @@ -0,0 +1,496 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import java.util.Properties; + +import jcckit.graphic.BasicGraphicAttributes; +import jcckit.graphic.GraphPoint; +import jcckit.graphic.LineAttributes; +import jcckit.graphic.ShapeAttributes; +import jcckit.graphic.TextAttributes; +import jcckit.util.ConfigData; +import jcckit.util.ConfigParameters; +import jcckit.util.ConfigParametersBasedConfigData; +import jcckit.util.Factory; +import jcckit.util.Format; +import jcckit.util.PropertiesBasedConfigData; +import jcckit.util.TicLabelFormat; +import jcckit.util.Util; + +/** + * Helper class with various parameters defining an axis. + * This helper class is used by {@link CartesianCoordinateSystem} + * to set up a coordinate systems. + *

+ * This class holds more than a dozen parameters. There are two factory + * methods creating instances for x- and y-axis based on + * {@link ConfigParameters}. They differ in their default parameters for + * those axes. + *

+ * Note, that there is a direct access of these parameters without getters + * and setters but only for classes in the package jcckit.plot. + * + * @author Franz-Josef Elmer + */ +public class AxisParameters { + /** Configuration parameter key. */ + public static final String LOG_SCALE_KEY = "logScale", + MINIMUM_KEY = "minimum", + MAXIMUM_KEY = "maximum", + AXIS_LENGTH_KEY = "axisLength", + AXIS_ATTRIBUTES_KEY = "axisAttributes", + AXIS_LABEL_KEY = "axisLabel", + AXIS_LABEL_POSITION_KEY = "axisLabelPosition", + AXIS_LABEL_ATTRIBUTES_KEY = "axisLabelAttributes", + AUTOMATIC_TIC_CALCULATION_KEY + = "automaticTicCalculation", + MINIMUM_TIC_KEY = "minimumTic", + MAXIMUM_TIC_KEY = "maximumTic", + NUMBER_OF_TICS_KEY = "numberOfTics", + TIC_LENGTH_KEY = "ticLength", + TIC_ATTRIBUTES_KEY = "ticAttributes", + TIC_LABEL_FORMAT_KEY = "ticLabelFormat", + TIC_LABEL_POSITION_KEY = "ticLabelPosition", + TIC_LABEL_ATTRIBUTES_KEY = "ticLabelAttributes", + GRID_KEY = "grid", + GRID_ATTRIBUTES_KEY = "gridAttributes"; + + private static final double LN10 = Math.log(10); + + /** If true the scale is logarithmic otherwise linear. */ + boolean logScale; + /** Minimum data value represented by the axis. */ + double minimum; + /** Maximum data value represented by the axis. */ + double maximum; + /** Length of the axis in device-independent graphical units. */ + double axisLength; + /** + * Line attributes of the axis. + * Can be null which means default attributes. + */ + LineAttributes axisAttributes; + + boolean automaticTicCalculation; + double minimumTic; + double maximumTic; + int numberOfTics; + /** + * Length of the tics in device-independent graphical units. + * If 0 no tics and tics label will be drawn. + */ + double ticLength; + /** + * Attributes of the tics. + * Can be null which means default attributes. + */ + LineAttributes ticAttributes; + /** Tic label formatter. */ + TicLabelFormat ticLabelFormat; + /** Position of the tic label relative to the tic. */ + GraphPoint ticLabelPosition; + /** Text attributes of the tic labels. */ + TextAttributes ticLabelAttributes; + + /** If true grid lines are drawn. */ + boolean grid; + /** + * Attributes of the grid lines. + * Can be null which means default attributes. + */ + LineAttributes gridAttributes; + + /** Axis label. */ + String axisLabel; + /** Position of the axis label relative to the center of the axis. */ + GraphPoint axisLabelPosition; + /** Text attributes of the axis label. */ + TextAttributes axisLabelAttributes; + + /** + * Calculate the tics based on minimumTic, maximumTic, + * and numberOfTics. If automaticTicCalculation == true + * appropriated values for these fields are calculated. + */ + double[] calculateTics() { + if (automaticTicCalculation) { + calculateTicsParameters(); + } + double[] result = new double[numberOfTics]; + if (numberOfTics > 0) { + double b = Util.log(minimumTic, logScale); + double a = Util.log(maximumTic, logScale); + a = numberOfTics > 1 ? (a - b) / (numberOfTics - 1) : 0; + for (int i = 0; i < result.length; i++) { + result[i] = Util.exp(a * i + b, logScale); + } + result[0] = adjust(minimum, result[0]); + result[numberOfTics - 1] = adjust(maximum, result[numberOfTics - 1]); + } + return result; + } + + private void calculateTicsParameters() { + double min = Math.min(minimum, maximum); + double max = Math.max(minimum, maximum); + if (logScale) { + int minExponent = (int) (199.9999 + Math.log(min) / LN10) - 199; + int maxExponent = (int) (200.0001 + Math.log(max) / LN10) - 200; + minimumTic = Math.exp(LN10 * minExponent); + maximumTic = Math.exp(LN10 * maxExponent); + numberOfTics = maxExponent - minExponent + 1; + } else { + int baseExponent = (int) (199.69 + Math.log(max - min) / LN10) - 200; + double base = 0.2 * Math.exp(LN10 * baseExponent); + do + { + base *= 5; + int minInt = (int) (999999.999999 + min / base) - 999999; + int maxInt = (int) (1000000.000001 + max / base) - 1000000; + minimumTic = minInt * base; + maximumTic = maxInt * base; + numberOfTics = maxInt - minInt + 1; + } while (numberOfTics > 11); + } + } + + /** + * Returns adjustingValue if value is very close + * to adjustingValue. Otherwise value is returned. + */ + private static double adjust(double adjustingValue, double value) { + return value != 0 && Math.abs(adjustingValue / value - 1) < 1e-11 + ? adjustingValue : value; + } + + /** + * Returns a Properties object with those default parameters + * which are common for x- and y-axis. + */ + private static Properties createDefaultAxisProperties() { + Properties p = new Properties(); + p.put(LOG_SCALE_KEY, "false"); + p.put(MINIMUM_KEY, "0"); + p.put(MAXIMUM_KEY, "1"); + p.put(AXIS_LENGTH_KEY, "0.8"); + p.put(AXIS_ATTRIBUTES_KEY + '/' + Factory.CLASS_NAME_KEY, + ShapeAttributes.class.getName()); + p.put(AXIS_LABEL_KEY, "x"); + p.put(AXIS_LABEL_POSITION_KEY, "0 -0.05"); + p.put(AXIS_LABEL_ATTRIBUTES_KEY + '/' + Factory.CLASS_NAME_KEY, + BasicGraphicAttributes.class.getName()); + p.put(AXIS_LABEL_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.HORIZONTAL_ANCHOR_KEY, "center"); + p.put(AUTOMATIC_TIC_CALCULATION_KEY, "true"); + p.put(TIC_LENGTH_KEY, "0.01"); + p.put(TIC_ATTRIBUTES_KEY + '/' + Factory.CLASS_NAME_KEY, + ShapeAttributes.class.getName()); + p.put(TIC_LABEL_POSITION_KEY, "0 -0.01"); + p.put(TIC_LABEL_FORMAT_KEY, "%1.1f"); + p.put(TIC_LABEL_ATTRIBUTES_KEY + '/' + Factory.CLASS_NAME_KEY, + BasicGraphicAttributes.class.getName()); + p.put(TIC_LABEL_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.HORIZONTAL_ANCHOR_KEY, "center"); + p.put(TIC_LABEL_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.VERTICAL_ANCHOR_KEY, "top"); + p.put(GRID_KEY, "false"); + p.put(GRID_ATTRIBUTES_KEY + '/' + Factory.CLASS_NAME_KEY, + ShapeAttributes.class.getName()); + return p; + } + + /** + * Returns a Properties object of the default parameters for + * an x-axis. + */ + private static Properties createDefaultXAxisProperties() { + Properties p = createDefaultAxisProperties(); + p.put(AXIS_LABEL_KEY, "x"); + p.put(AXIS_LABEL_POSITION_KEY, "0 -0.05"); + p.put(AXIS_LABEL_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.VERTICAL_ANCHOR_KEY, "top"); + p.put(TIC_LABEL_POSITION_KEY, "0 -0.01"); + p.put(TIC_LABEL_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.HORIZONTAL_ANCHOR_KEY, "center"); + p.put(TIC_LABEL_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.VERTICAL_ANCHOR_KEY, "top"); + return p; + } + + /** + * Creates an x axis based on the specified configuration parameters. + * All numbers (lengths, fontsizes, linethicknesses, etc.) are in + * device-independent units. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
automaticTicCalculation = truebooleannoHas to be true if the tics should be calculated + * automatically.
axisAttributes = default values of + * {@link ShapeAttributes}ConfigParametersnoAttributes of the axis box.
axisLabel = xStringnoAxis label.
axisLabelAttributes = default values of + * {@link BasicGraphicAttributes} with a text anchor CENTER + * TOP.ConfigParametersnoText attributes of axis label.
axisLabelPosition = 0 -0.05double[]noPosition of the anchor of the axis + * label relative to the center of the x-axis line.
axisLength = 0.8doublenoLength of the x-axis.
grid = falsebooleannoIf true grid lines will be drawn through the axis + * tics.
gridAttributes = default values of + * {@link ShapeAttributes}ConfigParametersnoAttributes of the grid lines.
logScale = falsebooleannoIf true the axis will be logarithmic. Otherwise + * the axis is linear.
maximum = 1doublenoThe corresponding data value of one end of the axis.
maximumTic = result from automatic calculationdoublenoThe corresponding data value of the tic nearest the maximum end + * of the axis.
minimum = 0doublenoThe corresponding data value of one end of the axis.
minimumTic = result from automatic calculationdoublenoThe corresponding data value of the tic nearest the minimum end + * of the axis.
numberOfTics = result from automatic calculationintnoNumber of tics. The tics between the minimum and maximum tic + * are spaced equidistantly.
ticAttributes = default values of + * {@link ShapeAttributes}ConfigParametersnoAttributes of the tics.
ticLabelAttributes = default values of + * {@link BasicGraphicAttributes} with a text anchor CENTER + * TOP.ConfigParametersnoText attributes of tic labels.
ticLabelFormat = %1.1fString or ConfigParametersnoDefines rendering of the tic label. By default a + * printf-like format string is given (see {@link Format}). + * Note, that an empty string means that tic labels are dropped. + *

+ * For non-numerical rendering an implementation of a + * {@link TicLabelFormat} can be specified (e.g. + * {@link TicLabelMap}). Note, that a configuration sub tree with + * a className key-value pair overwrites any string + * definition.

ticLabelPosition = 0 -0.01double[]noPosition of the anchor of the tic label relative to the + * tic position on the axis.
ticLength = 0.01doublenoLength of the tics. Negative/positive values mean tics + * inside/outside the box.
+ */ + public static AxisParameters createXAxis(ConfigParameters config) { + return createAxis(config, createDefaultXAxisProperties()); + } + + /** + * Returns a Properties object of the default parameters for + * an x-axis. + */ + private static Properties createDefaultYAxisProperties() { + Properties p = createDefaultAxisProperties(); + p.put(AXIS_LENGTH_KEY, "0.45"); + p.put(AXIS_LABEL_KEY, "y"); + p.put(AXIS_LABEL_POSITION_KEY, "-0.1 0"); + p.put(AXIS_LABEL_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.VERTICAL_ANCHOR_KEY, "bottom"); + p.put(AXIS_LABEL_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.ORIENTATION_ANGLE_KEY, "90"); + p.put(TIC_LABEL_POSITION_KEY, "-0.01 0"); + p.put(TIC_LABEL_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.HORIZONTAL_ANCHOR_KEY, "right"); + p.put(TIC_LABEL_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.VERTICAL_ANCHOR_KEY, "center"); + return p; + } + + /** + * Creates an y axis based on the specified configuration parameters. + * All numbers (lengths, fontsizes, linethicknesses, etc.) are in + * device-independent units. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
automaticTicCalculation = truebooleannoHas to be true if the tics should be calculated + * automatically.
axisAttributes = default values of + * {@link ShapeAttributes}ConfigParametersnoAttributes of the axis box.
axisLabel = yStringnoAxis label.
axisLabelAttributes = default values of + * {@link BasicGraphicAttributes} with a text anchor CENTER + * BOTTOM and the text rotated by 90 degree.ConfigParametersnoText attributes of axis label.
axisLabelPosition = -0.1 0double[]noPosition of the anchor of the axis + * label relative to the center of the y-axis line.
axisLength = 0.45doublenoLength of the y-axis.
grid = falsebooleannoIf true grid lines will be drawn through the axis + * tics.
gridAttributes = default values of + * {@link ShapeAttributes}ConfigParametersnoAttributes of the grid lines.
logScale = falsebooleannoIf true the axis will be logarithmic. Otherwise + * the axis is linear.
maximum = 1doublenoThe corresponding data value of one end of the axis.
maximumTic = result from automatic calculationdoublenoThe corresponding data value of the tic nearest the maximum end + * of the axis.
minimum = 0doublenoThe corresponding data value of one end of the axis.
minimumTic = result from automatic calculationdoublenoThe corresponding data value of the tic nearest the minimum end + * of the axis.
numberOfTics = result from automatic calculationintnoNumber of tics. The tics between the minimum and maximum tic + * are spaced equidistantly.
ticAttributes = default values of + * {@link ShapeAttributes}ConfigParametersnoAttributes of the tics.
ticLabelAttributes = default values of + * {@link BasicGraphicAttributes} with a text anchor RIGHT CENTER. + * ConfigParametersnoText attributes of tic labels.
ticLabelFormat = %1.1fStringnoDefines rendering of the tic label. By default a + * printf-like format string is given (see {@link Format}). + * Note, that an empty string means that tic labels are dropped. + *

+ * For non-numerical rendering an implementation of a + * {@link TicLabelFormat} can be specified (e.g. + * {@link TicLabelMap}). Note, that a configuration sub tree with + * a className key-value pair overwrites any string + * definition.

ticLabelPosition = -0.01 0double[]noPosition of the anchor of the tic label relative to the + * tic position on the axis.
ticLength = 0.01doublenoLength of the tics. Negative/positive values mean tics + * inside/outside the box.
+ */ + public static AxisParameters createYAxis(ConfigParameters config) { + return createAxis(config, createDefaultYAxisProperties()); + } + + private static AxisParameters createAxis(ConfigParameters config, + Properties p) { + ConfigData cd = new PropertiesBasedConfigData(p); + ConfigParameters c = new ConfigParameters(cd); + cd = new ConfigParametersBasedConfigData(config, c); + c = new ConfigParameters(cd); + + AxisParameters a = new AxisParameters(); + a.logScale = c.getBoolean(LOG_SCALE_KEY); + a.minimum = c.getDouble(MINIMUM_KEY); + a.maximum = c.getDouble(MAXIMUM_KEY); + a.axisLength = c.getDouble(AXIS_LENGTH_KEY); + a.axisAttributes + = (LineAttributes) Factory.create(c.getNode(AXIS_ATTRIBUTES_KEY)); + a.axisLabel = c.get(AXIS_LABEL_KEY); + a.axisLabelPosition + = new GraphPoint(c.getDoubleArray(AXIS_LABEL_POSITION_KEY)); + a.axisLabelAttributes = (TextAttributes) Factory.create( + c.getNode(AXIS_LABEL_ATTRIBUTES_KEY)); + a.ticLength = c.getDouble(TIC_LENGTH_KEY); + a.automaticTicCalculation + = c.getBoolean(AUTOMATIC_TIC_CALCULATION_KEY); + if (!a.automaticTicCalculation) { + a.calculateTicsParameters(); // calculate default parameters + a.minimumTic = c.getDouble(MINIMUM_TIC_KEY, a.minimumTic); + a.maximumTic = c.getDouble(MAXIMUM_TIC_KEY, a.maximumTic); + a.numberOfTics = c.getInt(NUMBER_OF_TICS_KEY, a.numberOfTics); + } + a.ticAttributes + = (LineAttributes) Factory.create(c.getNode(TIC_ATTRIBUTES_KEY)); + a.ticLabelFormat = createTicLabelFormat(c); + a.ticLabelPosition + = new GraphPoint(c.getDoubleArray(TIC_LABEL_POSITION_KEY)); + a.ticLabelAttributes = (TextAttributes) Factory.create( + c.getNode(TIC_LABEL_ATTRIBUTES_KEY)); + a.grid = c.getBoolean(GRID_KEY); + a.gridAttributes + = (LineAttributes) Factory.create(c.getNode(GRID_ATTRIBUTES_KEY)); + return a; + } + + private static TicLabelFormat createTicLabelFormat(ConfigParameters c) + { + TicLabelFormat result = Format.create(c, TIC_LABEL_FORMAT_KEY); + ConfigParameters node = c.getNode(TIC_LABEL_FORMAT_KEY); + if (node.get(Factory.CLASS_NAME_KEY, null) != null) { + result = (TicLabelFormat) Factory.create(node); + } + return result; + } +} diff --git a/src/jcckit/plot/BarFactory.java b/src/jcckit/plot/BarFactory.java new file mode 100644 index 00000000000..6a452a1e665 --- /dev/null +++ b/src/jcckit/plot/BarFactory.java @@ -0,0 +1,131 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.ClippingShape; +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicAttributes; +import jcckit.graphic.GraphicalElement; +import jcckit.graphic.Rectangle; +import jcckit.util.ConfigParameters; + +/** + * A factory of bars. The bars are {@link Rectangle Rectangles}. + * Depending on the configuration parameters the bars can be + * horizontal or vertical. Bars of several curves can be side by side or + * stacked. The bar length is determined by the x or y value of the + * curve point in device-independent coordinates. If the value is negative + * the bar goes into the negative direction. For stacked bars the values + * should always be positive. + *

+ * When used inside a {@link SimpleCurve} soft clipping should always be + * switched off (see + * {@link SimpleCurve#SimpleCurve(ConfigParameters, int, int, ClippingShape, Legend)}). + * + * @author Franz-Josef Elmer + */ +public class BarFactory extends AbstractSymbolFactory { + /** Configuration parameter key. */ + public static final String STACKED_KEY = "stacked", + HORIZONTAL_BARS_KEY = "horizontalBars"; + + private final boolean _stacked; + private final boolean _horizontalBars; + + /** + * Creates an instance from the specified configuration parameters. + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
horizontalBars = falsebooleannoIf true horizontal bars will be drawn. Otherwise + * vertical bars are drawn.
stacked = falsebooleannoIf true the bars of several curves will be + * stacked.
+ * In addition the configuration parameters of the + * + * constructor of the superclass {@link AbstractSymbolFactory} apply. + */ + public BarFactory(ConfigParameters config) { + super(config); + _horizontalBars = config.getBoolean(HORIZONTAL_BARS_KEY, false); + _stacked = config.getBoolean(STACKED_KEY, false); + } + + /** + * Creates a bar at the specified point. + * If hintFromPreviousCurve + * is not an instance of {@link PositionHint} the values of + * origin and position will be (0,0). + * @param hintFromPreviousCurve Hint from previous curve. Will be used + * to calculate symbol shape and hint for the next curve. + */ + protected Symbol createSymbol(GraphPoint point, GraphicAttributes attributes, + Hint hintForNextPoint, + Hint hintFromPreviousCurve) { + GraphPoint origin = new GraphPoint(null); + GraphPoint position = origin; + if (hintFromPreviousCurve instanceof PositionHint) { + origin = ((PositionHint) hintFromPreviousCurve).getOrigin(); + position = ((PositionHint) hintFromPreviousCurve).getPosition(); + } + double px = position.getX(); + double py = position.getY(); + double x = point.getX() - origin.getX(); + double y = point.getY() - origin.getY(); + if (_horizontalBars) { + y = _size; + position = new GraphPoint(px + 0.5 * x, point.getY() + py); + px += _stacked ? x : 0; + py += _stacked ? 0 : _size; + } else { + x = _size; + position = new GraphPoint(point.getX() + px, py + 0.5 * y); + px += _stacked ? 0 : _size; + py += _stacked ? y : 0; + } + Hint hintForNextCurve = new PositionHint(origin, new GraphPoint(px, py)); + return new Symbol(new Rectangle(position, Math.abs(x), Math.abs(y), + attributes), + hintForNextPoint, hintForNextCurve); + } + + /** + * Creates a symbol for the legend at the specified position. + * @param centerPosition Center position of the symbol. + * @param size The size of the symbol. + */ + public GraphicalElement createLegendSymbol(GraphPoint centerPosition, + double size) { + return new Rectangle(centerPosition, size, size, _attributes); + } + + /** + * Returns null because this method isn't needed but has to be + * implemented. + */ + protected GraphicalElement createPlainSymbol( + GraphPoint centerPosition, double size, GraphicAttributes attributes) { + return null; + } +} diff --git a/src/jcckit/plot/CartesianCoordinateSystem.java b/src/jcckit/plot/CartesianCoordinateSystem.java new file mode 100644 index 00000000000..dbfaae8dbe3 --- /dev/null +++ b/src/jcckit/plot/CartesianCoordinateSystem.java @@ -0,0 +1,206 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.data.DataPoint; +import jcckit.graphic.ClippingRectangle; +import jcckit.graphic.ClippingShape; +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicAttributes; +import jcckit.graphic.GraphicalComposite; +import jcckit.graphic.GraphicalElement; +import jcckit.graphic.LineAttributes; +import jcckit.graphic.Polygon; +import jcckit.graphic.Text; +import jcckit.transformation.CartesianTransformation; +import jcckit.transformation.Transformation; +import jcckit.util.ConfigParameters; + +/** + * A Cartesian coordinate system. One or both axes can be logarithmic. + * + * @author Franz-Josef Elmer + */ +public class CartesianCoordinateSystem implements CoordinateSystem { + /** Configuration parameter key. */ + public static final String ORIGIN_KEY = "origin", + X_AXIS_KEY = "xAxis", + Y_AXIS_KEY = "yAxis"; + + private final CartesianTransformation _transformation; + private final GraphicalComposite _view; + private final ClippingRectangle _clippingRectangle; + + /** + * Creates an instance from the specified configuration parameters. + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
origin = 0.15, 0.1double[]noPosition (in device-independent coordinates) of the lower-left + * corner of the axis box.
xAxisConfigParametersnoParameters defining the x-axis. For definitions and default + * values see {@link AxisParameters#createXAxis + * AxisParameters.createXAxis()}.
yAxisConfigParametersnoParameters defining the y-axis. For definitions and default + * values see {@link AxisParameters#createYAxis + * AxisParameters.createYAxis()}.
+ */ + public CartesianCoordinateSystem(ConfigParameters config) { + this(new GraphPoint(config.getDoubleArray(ORIGIN_KEY, + new double[] {0.15, 0.1})), + AxisParameters.createXAxis(config.getNode(X_AXIS_KEY)), + AxisParameters.createYAxis(config.getNode(Y_AXIS_KEY))); + } + + /** + * Creates an instance for the specified origin and parameters + * of both axes. + * @param origin Position (in device-independent coordinates) of the + * lower-left corner of the axis box. + * @param xAxisParameters Parameters of the x-axis. + * @param yAxisParameters Parameters of the y-axis. + */ + public CartesianCoordinateSystem(GraphPoint origin, + AxisParameters xAxisParameters, + AxisParameters yAxisParameters) { + double x = origin.getX(); + double y = origin.getY(); + _transformation = new CartesianTransformation(xAxisParameters.logScale, + yAxisParameters.logScale, + new DataPoint(xAxisParameters.minimum, yAxisParameters.minimum), + new GraphPoint(x, y), + new DataPoint(xAxisParameters.maximum, yAxisParameters.maximum), + new GraphPoint(x + xAxisParameters.axisLength, + y + yAxisParameters.axisLength)); + _clippingRectangle = new ClippingRectangle(x, y, + x + xAxisParameters.axisLength, + y + yAxisParameters.axisLength); + _view = new GraphicalComposite(null); + createView(origin, xAxisParameters, yAxisParameters); + } + + /** Creates the graphical representation of this coordinate system. */ + private void createView(GraphPoint origin, + AxisParameters xAxisParameters, + AxisParameters yAxisParameters) { + double x0 = origin.getX(); + double x1 = x0 + xAxisParameters.axisLength; + double y0 = origin.getY(); + double y1 = y0 + yAxisParameters.axisLength; + GraphPoint lowerLeftCorner = new GraphPoint(x0, y0); + GraphPoint upperLeftCorner = new GraphPoint(x0, y1); + GraphPoint lowerRightCorner = new GraphPoint(x1, y0); + GraphPoint upperRightCorner = new GraphPoint(x1, y1); + LineAttributes xLineAttributes = xAxisParameters.axisAttributes; + LineAttributes yLineAttributes = yAxisParameters.axisAttributes; + createTicsAndGrid(true, y0, y1, xAxisParameters); + createTicsAndGrid(false, x0, x1, yAxisParameters); + addLine(lowerLeftCorner, lowerRightCorner, xLineAttributes); + addLine(lowerLeftCorner, upperLeftCorner, yLineAttributes); + addLine(upperLeftCorner, upperRightCorner, xLineAttributes); + addLine(lowerRightCorner, upperRightCorner, yLineAttributes); + createLabel(0.5 * (x0 + x1), y0, xAxisParameters); + createLabel(x0, 0.5 * (y0 + y1), yAxisParameters); + } + + private void createLabel(double x, double y, AxisParameters parameters) { + if (parameters.axisLabel.length() > 0) { + _view.addElement(new Text( + new GraphPoint(x + parameters.axisLabelPosition.getX(), + y + parameters.axisLabelPosition.getY()), + parameters.axisLabel, parameters.axisLabelAttributes)); + } + } + + private void createTicsAndGrid(boolean isXAxis, double low, double high, + AxisParameters parameters) { + double[] tics = parameters.calculateTics(); + int offIndex = isXAxis ? 1 : 0; + double[] point = new double[2]; // helper array + for (int i = 0; i < tics.length; i++) { + point[1 - offIndex] = tics[i]; + point[offIndex] = 1; + GraphPoint gPoint1 = + _transformation.transformToGraph(new DataPoint(point[0], point[1])); + point[0] = gPoint1.getX(); + point[1] = gPoint1.getY(); + point[offIndex] = high; + gPoint1 = new GraphPoint(point[0], point[1]); + point[offIndex] += parameters.ticLength; + addLine(gPoint1, new GraphPoint(point[0], point[1]), + parameters.ticAttributes); + point[offIndex] = low; + GraphPoint gPoint2 = new GraphPoint(point[0], point[1]); + if (parameters.grid) { + addLine(gPoint1, gPoint2, parameters.gridAttributes); + } + point[offIndex] -= parameters.ticLength; + addLine(gPoint2, new GraphPoint(point[0], point[1]), + parameters.ticAttributes); + if (parameters.ticLabelFormat != null) { + point[offIndex] += parameters.ticLength; + point[0] += parameters.ticLabelPosition.getX(); + point[1] += parameters.ticLabelPosition.getY(); + _view.addElement(new Text(new GraphPoint(point[0], point[1]), + parameters.ticLabelFormat.form(tics[i]), + parameters.ticLabelAttributes)); + } + } + } + + private void addLine(GraphPoint point1, GraphPoint point2, + GraphicAttributes attributes) { + Polygon line = new Polygon(attributes, false); + line.addPoint(point1); + line.addPoint(point2); + _view.addElement(line); + } + + /** + * Returns the graphical representation of the coordinate system. + * In each call the same instance is returned. + */ + public GraphicalElement getView() { + return _view; + } + + /** + * Returns the clipping rectangle of specified by the axis. + * In each call the same instance is returned. + */ + public ClippingShape getClippingShape() { + return _clippingRectangle; + } + + /** + * Returns the transformation of data coordinates into the device-independent + * coordinates of the axis box. + * In each call the same instance is returned. + */ + public Transformation getTransformation() { + return _transformation; + } +} diff --git a/src/jcckit/plot/CircleSymbolFactory.java b/src/jcckit/plot/CircleSymbolFactory.java new file mode 100644 index 00000000000..b9eb9a6b9f2 --- /dev/null +++ b/src/jcckit/plot/CircleSymbolFactory.java @@ -0,0 +1,54 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicAttributes; +import jcckit.graphic.GraphicalElement; +import jcckit.graphic.Oval; +import jcckit.util.ConfigParameters; + +/** + * A factory of circle symbols. + * + * @author Franz-Josef Elmer + */ +public class CircleSymbolFactory extends AbstractSymbolFactory { + /** + * Creates an instance from the specified configuration parameters. + * For the configuration parameters see the + * + * constructor of the superclass {@link AbstractSymbolFactory}. + */ + public CircleSymbolFactory(ConfigParameters config) { + super(config); + } + + /** + * Creates a circle. + * @param centerPosition Position of the center of the circle. + * @param size Diameter of the circle. + * @param attributes Circle attributes. + */ + protected GraphicalElement createPlainSymbol(GraphPoint centerPosition, + double size, + GraphicAttributes attributes) { + return new Oval(centerPosition, size, size, attributes); + } +} diff --git a/src/jcckit/plot/CoordinateSystem.java b/src/jcckit/plot/CoordinateSystem.java new file mode 100644 index 00000000000..11ac628388b --- /dev/null +++ b/src/jcckit/plot/CoordinateSystem.java @@ -0,0 +1,55 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.ClippingShape; +import jcckit.graphic.GraphicalElement; +import jcckit.transformation.Transformation; + +/** + * Interface for all generators of coordinate systems. A + * CoordinateSystem creates a + * {@link jcckit.graphic.GraphicalComposite} which contains all the + * {@link GraphicalElement GraphicalElements} defining axes, labels, grid, etc. + * + * @author Franz-Josef Elmer + */ +public interface CoordinateSystem { + /** + * Returns the graphical representation of a coordinate + * system. Different invocations of this method may return + * different coordinate systems, e.g., due to changes in the + * transformation or clipping shapes. + */ + public GraphicalElement getView(); + + /** + * Returns the clipping chape of {@link Curve Curves} drawn on top + * of the coordinates system. Different invocations of + * this method may return different clipping shapes. + */ + public ClippingShape getClippingShape(); + + /** + * Returns the transformation between data coordinates and + * device-independent graphcial coordinates. Different invocations + * of this method may return different transformations. + */ + public Transformation getTransformation(); +} diff --git a/src/jcckit/plot/Curve.java b/src/jcckit/plot/Curve.java new file mode 100644 index 00000000000..03cb3cb789d --- /dev/null +++ b/src/jcckit/plot/Curve.java @@ -0,0 +1,64 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicalElement; + +/** + * A curve is defined by a sequence of points in device-independent + * coordinates. The points can be decorated by symbols and/or + * connected by lines.{@link Hint Hints} are used to determine additional + * properties of the symbol. This is especially important for + * charts with bars. + *

+ * In accordance with the Factory Method Pattern + * the symbols are created by a {@link SymbolFactory}. + * + * @author Franz-Josef Elmer + */ +public interface Curve { + /** + * Returns the graphical representation of a curve. + * Different invocations of this method might return + * different instances. + * This is especially true after adding, inserting, removing, or + * repplacing a point of the curve. + */ + public GraphicalElement getView(); + + /** + * Returns a symbol which can be used to create the legend for the curve. + * For example, it should return a horizontal line with the symbol + * in the middle if the curve is a line with points decorated by symbols. + */ + public GraphicalElement getLegendSymbol(); + + /** + * Appends a new point to the curve. + * @param point Position in device-independent coordinates. + * @param hintFromPreviousCurve Hint which may be used to calculate + * the corresponding {@link GraphicalElement}. + * @return hint for next curve. + */ + public Hint addPoint(GraphPoint point, Hint hintFromPreviousCurve); + + /** Removes all points from the curve. */ + public void removeAllPoints(); +} diff --git a/src/jcckit/plot/CurveFactory.java b/src/jcckit/plot/CurveFactory.java new file mode 100644 index 00000000000..0e6ee53fa42 --- /dev/null +++ b/src/jcckit/plot/CurveFactory.java @@ -0,0 +1,42 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.ClippingShape; + +/** + * Interface of a curve factory. A curve factory creates a new instance + * of a {@link Curve}. + * + * @author Franz-Josef Elmer + */ +public interface CurveFactory { + /** + * Creates a new curve instance. + * @param curveIndex The index of the curve in the {@link Plot} to which + * it should belong. + * @param numberOfCurves Number of curves. Will be needed to calculate the + * y-coordinate of the legend symbol. + * @param clippingShape Clipping shape applied to the curve. + * @param legend The legend which will show the curve symbol. + * @return an empty instance. + */ + public Curve create(int curveIndex, int numberOfCurves, + ClippingShape clippingShape, Legend legend); +} diff --git a/src/jcckit/plot/ErrorBarFactory.java b/src/jcckit/plot/ErrorBarFactory.java new file mode 100644 index 00000000000..2c55462d3e6 --- /dev/null +++ b/src/jcckit/plot/ErrorBarFactory.java @@ -0,0 +1,136 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicAttributes; +import jcckit.graphic.GraphicalComposite; +import jcckit.graphic.GraphicalElement; +import jcckit.graphic.Rectangle; +import jcckit.util.ConfigParameters; +import jcckit.util.Factory; + +/** + * Symbol factory for creating symbols with error bars. It wraps + * a {@link SymbolFactory} for creating the symbol. The error bars + * are {@link Rectangle Rectangles}. + *

+ * Curves with error bars are based on two + * {@link jcckit.data.DataCurve DataCurves}: + *

  1. The plain curve. + *
  2. An instance which stores the errors in x and y. + * It is assumed that the errors are positive values defining + * the error symmetrically around the curve points. + *
+ *

+ * The ErrorBarFactory needs an instance of {@link PositionHint} + * as initial {@link Hint} for the next curve. Its origin must be + * the origin of the data coordinate system in device-independent coordinates. + * The position of PositionHint must be undefined. + * + * @author Franz-Josef Elmer + */ +public class ErrorBarFactory implements SymbolFactory { + /** Configuration parameter key. */ + public static final String SYMBOL_FACTORY_KEY = "symbolFactory"; + + private final SymbolFactory _symbolFactory; + private final GraphicAttributes _attributes; + private final double _size; + + /** + * Creates an instance from the specified configuration parameters. + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
symbolFactory = nullConfigParametersnoDefinition of the wrapped {@link SymbolFactory} which generates + * the curve symbol without bars. By default an empty + * {@link GraphicalComposite} will be created.
size = 0doublenoWidth of the error bars.
attributes = nullConfigParametersnoDefinition of the {@link GraphicAttributes} of the error + * bars.
+ */ + public ErrorBarFactory(ConfigParameters config) { + _symbolFactory = (SymbolFactory) Factory.createOrGet( + config.getNode(SYMBOL_FACTORY_KEY), null); + _size = config.getDouble(SIZE_KEY, 0); + _attributes = (GraphicAttributes) Factory.createOrGet( + config.getNode(ATTRIBUTES_KEY), null); + } + + /** + * Creates the legend symbol. Calls the wrapped {@link SymbolFactory} + * or returns an empty instance of {@link GraphicalComposite} if undefined. + */ + public GraphicalElement createLegendSymbol(GraphPoint centerPosition, + double size) { + return _symbolFactory == null ? new GraphicalComposite(null) + : _symbolFactory.createLegendSymbol(centerPosition, size); + } + + /** + * Creates either the curve symbol or the error bars. Error bars are + * created when hintFromPreviousCurve is an instance of + * {@link PositionHint} and its position attribute is not null. + * Otherwise the curve symbol is created. The position attributes stores + * the curve point (in device-independent coordinates). The origin is + * always as set in the initial PositionHint. The hint for + * the next curve wrapped by the returned Symbol is always + * a PositionHint. + */ + public Symbol createSymbol(GraphPoint point, Hint hintFromPreviousPoint, + Hint hintFromPreviousCurve) { + GraphPoint origin = new GraphPoint(null); + GraphPoint position = null; + if (hintFromPreviousCurve instanceof PositionHint) { + origin = ((PositionHint) hintFromPreviousCurve).getOrigin(); + position = ((PositionHint) hintFromPreviousCurve).getPosition(); + } + if (position == null) { + if (_symbolFactory == null) { + return new Symbol(new GraphicalComposite(null), hintFromPreviousPoint, + new PositionHint(origin, point)); + } else { + return _symbolFactory.createSymbol(point, hintFromPreviousPoint, + new PositionHint(origin, point)); + } + } else { + double xError = point.getX() - origin.getX(); + double yError = point.getY() - origin.getY(); + GraphicalComposite errorBars = new GraphicalComposite(null); + if (xError > 0) { + errorBars.addElement(new Rectangle(position, 2 * xError, _size, + _attributes)); + } + if (yError > 0) { + errorBars.addElement(new Rectangle(position, _size, 2 * yError, + _attributes)); + } + return new Symbol(errorBars, hintFromPreviousPoint, + new PositionHint(origin, null)); + } + } +} diff --git a/src/jcckit/plot/Hint.java b/src/jcckit/plot/Hint.java new file mode 100644 index 00000000000..ff565b8f481 --- /dev/null +++ b/src/jcckit/plot/Hint.java @@ -0,0 +1,32 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + + +/** + * Marker interface of all types of hints. Hints are used to calculate + * {@link jcckit.graphic.GraphicalElement} representing a point in a {@link + * Curve}. For example, in a chart with stacked + * bars the data determines the height of a bar but the foot of + * a bar is determined by the height of the bar below. Its value will be + * stored in a {@link PositionHint}. + * + * @author Franz-Josef Elmer + */ +public interface Hint {} diff --git a/src/jcckit/plot/Legend.java b/src/jcckit/plot/Legend.java new file mode 100644 index 00000000000..3feea40c8ca --- /dev/null +++ b/src/jcckit/plot/Legend.java @@ -0,0 +1,250 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import java.util.Properties; + +import jcckit.graphic.BasicGraphicAttributes; +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicAttributes; +import jcckit.graphic.GraphicalComposite; +import jcckit.graphic.GraphicalElement; +import jcckit.graphic.Polygon; +import jcckit.graphic.Rectangle; +import jcckit.graphic.ShapeAttributes; +import jcckit.graphic.Text; +import jcckit.graphic.TextAttributes; +import jcckit.util.ConfigData; +import jcckit.util.ConfigParameters; +import jcckit.util.ConfigParametersBasedConfigData; +import jcckit.util.Factory; +import jcckit.util.PropertiesBasedConfigData; + + +/** + * Helper class for creating the legend of a {@link Plot}. + * + * @author Franz-Josef Elmer + */ +public class Legend { + /** Configuration parameter key. */ + public static final String UPPER_RIGHT_CORNER_KEY = "upperRightCorner", + BOX_WIDTH_KEY = "boxWidth", + BOX_HEIGHT_KEY = "boxHeight", + BOX_ATTRIBUTES_KEY = "boxAttributes", + TITLE_KEY = "title", + TITLE_DISTANCE_KEY = "titleDistance", + TITLE_ATTRIBUTES_KEY = "titleAttributes", + LEFT_DISTANCE_KEY = "leftDistance", + BOTTOM_DISTANCE_KEY = "bottomDistance", + TOP_DISTANCE_KEY = "topDistance", + LINE_LENGTH_KEY = "lineLength", + SYMBOL_SIZE_KEY = "symbolSize", + CURVE_TITLE_DISTANCE_KEY = "curveTitleDistance", + CURVE_TITLE_ATTRIBUTES_KEY + = "curveTitleAttributes"; + + private final GraphicalComposite _box; + private final TextAttributes _curveTitleAttributes; + private final double _xSymbol; + private final double _xText; + private final double _yBase; + private final double _yLastRow; + private final double _length; + private final double _size; + + /** + * Creates an instance from the specified configuration parameters. + * All numbers (lengths, fontsizes, linethicknesses, etc.) are in + * device-independent units. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
bottomDistance = 0.02doublenoDistance between the last row and the bottom of the legend box. + *
boxAttributes = default values of + * {@link ShapeAttributes} with a white fill color.ConfigParametersnoAttributes of the legend box.
boxHeight = 0.1doublenoHeight of the legend box.
boxWidth = 0.2doublenoWidth of the legend box.
curveTitleAttributes = default values of + * {@link BasicGraphicAttributes}ConfigParametersnoText attributes of curve titles printed in the legend.
curveTitleDistance = 0.005doublenoHorizontal distance between the line part of the legend symbol + * and the curve title.
leftDistance = 0.01doublenoHorizontal distance between the line part of the legend symbol + * and the left border of the legend box.
lineLength = 0.035doublenoLength of the line part of the legend symbol.
symbolSize = 0.01doublenoSize of the symbol part of the legend symbol. Will be the + * size argument of {@link SymbolFactory#createLegendSymbol + * createLegendSymbol} in a {@link SymbolFactory}.
titleAttributes = default values of + * {@link BasicGraphicAttributes} with a text anchor CENTER + * TOP.ConfigParametersnoText attributes of the title of the legend box.
title = LegendStringnoTitle of the legend box.
titleDistance = 0.005doublenoDistance between the center of the upper line of the legend box + * and the anchor of the legend title.
topDistance = 0.04doublenoDistance between the first row and the top of the legend box. + *
upperRightCorner = 0.94, 0.54double[]noPosition of the upper-right corner of the legend box.
+ */ + public Legend(ConfigParameters config) { + config = mergeWithDefaultConfig(config); + GraphPoint corner + = new GraphPoint(config.getDoubleArray(UPPER_RIGHT_CORNER_KEY, + new double[] {0.94, 0.54})); + double width = config.getDouble(BOX_WIDTH_KEY, 0.2); + double height = config.getDouble(BOX_HEIGHT_KEY, 0.1); + _curveTitleAttributes = (TextAttributes) Factory.create( + config.getNode(CURVE_TITLE_ATTRIBUTES_KEY)); + _xSymbol = corner.getX() - width + + config.getDouble(LEFT_DISTANCE_KEY, 0.01); + _yBase = corner.getY() - config.getDouble(TOP_DISTANCE_KEY, 0.04); + _yLastRow = corner.getY() - height + + config.getDouble(BOTTOM_DISTANCE_KEY, 0.02); + _length = config.getDouble(LINE_LENGTH_KEY, 0.035); + _size = config.getDouble(SYMBOL_SIZE_KEY, 0.01); + _xText = _xSymbol + _length + + config.getDouble(CURVE_TITLE_DISTANCE_KEY, 0.005); + + _box = new GraphicalComposite(null); + double xCenter = corner.getX() - width / 2; + _box.addElement(new Rectangle( + new GraphPoint(xCenter, corner.getY() - height / 2), width, height, + (GraphicAttributes) Factory.create( + config.getNode(BOX_ATTRIBUTES_KEY)))); + _box.addElement(new Text( + new GraphPoint(xCenter, corner.getY() + - config.getDouble(TITLE_DISTANCE_KEY, 0.005)), + config.get(TITLE_KEY, "Legend"), + (TextAttributes) Factory.create( + config.getNode(TITLE_ATTRIBUTES_KEY)))); + } + + private ConfigParameters mergeWithDefaultConfig(ConfigParameters config) { + Properties p = new Properties(); + p.put(BOX_ATTRIBUTES_KEY + '/' + Factory.CLASS_NAME_KEY, + ShapeAttributes.class.getName()); + p.put(BOX_ATTRIBUTES_KEY + '/' + + ShapeAttributes.FILL_COLOR_KEY, "0xffffff"); + p.put(BOX_ATTRIBUTES_KEY + '/' + + ShapeAttributes.LINE_COLOR_KEY, "0"); + p.put(TITLE_ATTRIBUTES_KEY + '/' + Factory.CLASS_NAME_KEY, + BasicGraphicAttributes.class.getName()); + p.put(TITLE_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.HORIZONTAL_ANCHOR_KEY, "center"); + p.put(TITLE_ATTRIBUTES_KEY + '/' + + BasicGraphicAttributes.VERTICAL_ANCHOR_KEY, "top"); + p.put(CURVE_TITLE_ATTRIBUTES_KEY + '/' + Factory.CLASS_NAME_KEY, + BasicGraphicAttributes.class.getName()); + ConfigData cd = new PropertiesBasedConfigData(p); + cd = new ConfigParametersBasedConfigData(config, new ConfigParameters(cd)); + return new ConfigParameters(cd); + } + + /** + * Returns the legend box with title but without legend symbols and curve + * titles. + */ + public GraphicalElement getBox() { + return _box; + } + + /** + * Creates the symbol part of a legend symbol. + * @param curveIndex Index of the curve. Will be needed to calculate the + * y-coordinate of the symbol. + * @param numberOfCurves Number of curves. Will be needed to calculate the + * y-coordinate of the symbol. + * @param factory Factory for the symbol part of the legend symbol. + * Can be null. + * @param withLine true if the line part of the legend symbol + * should be created. + * @param lineAttributes Attributes of the line part. + */ + public GraphicalElement createSymbol(int curveIndex, int numberOfCurves, + SymbolFactory factory, + boolean withLine, + GraphicAttributes lineAttributes) { + GraphicalComposite result = new GraphicalComposite(null); + double y = calculateBaseLine(curveIndex, numberOfCurves); + if (withLine) { + Polygon line = new Polygon(lineAttributes, false); + line.addPoint(new GraphPoint(_xSymbol, y)); + line.addPoint(new GraphPoint(_xSymbol + _length, y)); + result.addElement(line); + } + if (factory != null) { + result.addElement(factory.createLegendSymbol( + new GraphPoint(_xSymbol + _length / 2, y), _size)); + } + return result; + } + + private double calculateBaseLine(int curveIndex, int numberOfCurves) { + if (numberOfCurves > 1) { + return _yBase + ((_yLastRow - _yBase) / (numberOfCurves - 1)) + * curveIndex; + } else { + return 0.5 * (_yBase + _yLastRow); + } + } + + /** + * Creates the title part of a legend symbol. + * @param curveIndex Index of the curve. Will be needed to calculate the + * y-coordinate of the title. + * @param numberOfCurves Number of curves. Will be needed to calculate the + * y-coordinate of the symbol. + * @param title Title text. + */ + public GraphicalElement createCurveTitle(int curveIndex, int numberOfCurves, + String title) { + return new Text(new GraphPoint(_xText, calculateBaseLine(curveIndex, + numberOfCurves)), + title, _curveTitleAttributes); + } +} diff --git a/src/jcckit/plot/Plot.java b/src/jcckit/plot/Plot.java new file mode 100644 index 00000000000..0a2c7d27453 --- /dev/null +++ b/src/jcckit/plot/Plot.java @@ -0,0 +1,377 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import java.util.Vector; + +import jcckit.data.DataCurve; +import jcckit.data.DataEvent; +import jcckit.data.DataListener; +import jcckit.data.DataPlot; +import jcckit.data.DataPoint; +import jcckit.graphic.ClippingShape; +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicalComposite; +import jcckit.graphic.GraphicalElement; +import jcckit.transformation.Transformation; +import jcckit.util.ConfigParameters; +import jcckit.util.Factory; + +/** + * A plot is determined by a {@link CoordinateSystem}, {@link Curve Curves}, + * an optional annotation layer and an optional {@link Legend}. When rendered + * these components are draw in this order. + *

+ * Registrated {@link PlotListener PlotListeners} will be informed + * when the plot changes. + *

+ * A {@link DataPlot} can be connected with a Plot instance. + * This is done with the method {@link #connect connect()} which registrates + * this Plot instance as + * a {@link DataListener} at the connected DataPlot. + * After an received {@link DataEvent DataEvents} has been handled + * the registrated PlotListeners will receive a + * {@link PlotEvent} of the type {@link PlotEventType#DATA_PLOT_CHANGED}. + * + * @author Franz-Josef Elmer + */ +public class Plot implements DataListener { + /** Configuration parameter key. */ + public static final String COORDINATE_SYSTEM_KEY = "coordinateSystem", + CURVE_FACTORY_KEY = "curveFactory", + LEGEND_VISIBLE_KEY = "legendVisible", + LEGEND_KEY = "legend", + INITIAL_HINT_FOR_NEXT_CURVE_KEY + = "initialHintForNextCurve"; + private final Vector _plotListeners = new Vector(); + private DataPlot _dataPlot; + private final CurveFactory _curveFactory; + private final Vector _curves = new Vector(); + private final Vector _nextCurveHints = new Vector(); + private final Hint _initialHintForNextCurve; + private final Legend _legend; + private final boolean _legendVisibility; + + private GraphicalElement _coordinateSystemView; + private ClippingShape _clippingShape; + private Transformation _transformation; + private GraphicalElement _annotation; + private GraphicalComposite _legendView = new GraphicalComposite(null); + + /** + * Creates an instance from the specified configuration parameters. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
coordinateSystem = {@link CartesianCoordinateSystem}ConfigParametersnoDefinition of the {@link CoordinateSystem}.
curveFactory = {@link SimpleCurveFactory}ConfigParametersnoDefinition of the {@link CurveFactory}.
initialHintForNextCurve = nullConfigParametersnoDefinition of the initial {@link Hint} which is needed by some + * {@link SymbolFactory SymbolFactories} like {@link BarFactory}. + *
legend = default values of {@link Legend}ConfigParametersnoConfiguration parameters of a {@link Legend}.
legendVisible = truebooleannoIf true the {@link Legend} will be created.
+ */ + public Plot(ConfigParameters config) { + CoordinateSystem coordinateSystem = (CoordinateSystem) Factory.create( + config.getNode(COORDINATE_SYSTEM_KEY), + CartesianCoordinateSystem.class.getName()); + setCoordinateSystem(coordinateSystem); + _curveFactory = (CurveFactory) Factory.create( + config.getNode(CURVE_FACTORY_KEY), + SimpleCurveFactory.class.getName()); + _initialHintForNextCurve = (Hint) Factory.createOrGet( + config.getNode(INITIAL_HINT_FOR_NEXT_CURVE_KEY), null); + _legend = new Legend(config.getNode(LEGEND_KEY)); + _legendVisibility = config.getBoolean(LEGEND_VISIBLE_KEY, true); + } + + /** + * Sets the coordinate system. All curves will be regenerated and a + * {@link PlotEvent} of type {@link PlotEventType#COODINATE_SYSTEM_CHANGED} + * will be fired. + * + * @param coordinateSystem New coordinate system. + */ + public void setCoordinateSystem(CoordinateSystem coordinateSystem) + { + _coordinateSystemView = coordinateSystem.getView(); + _clippingShape = coordinateSystem.getClippingShape(); + _transformation = coordinateSystem.getTransformation(); + if (_dataPlot != null) + { + generateCurves(_dataPlot); + } + notifyListeners( + new PlotEvent(this, PlotEventType.COODINATE_SYSTEM_CHANGED, null)); + } + + /** + * Adds the specified {@link PlotListener}. Does nothing if + * already added. + */ + public void addPlotListener(PlotListener listener) { + if (!_plotListeners.contains(listener)) { + _plotListeners.addElement(listener); + } + } + + /** + * Removes the specfied {@link PlotListener}. Does nothing if + * already removed. + */ + public void removePlotListener(PlotListener listener) { + _plotListeners.removeElement(listener); + } + + /** + * Sends all registrated {@link PlotListener PlotListeners} + * the specified event. + */ + protected void notifyListeners(PlotEvent event) { + for (int i = 0, n = _plotListeners.size(); i < n; i++) { + ((PlotListener) _plotListeners.elementAt(i)).plotChanged(event); + } + } + + /** + * Connect the specified {@link DataPlot} with this instance. + *

+ * If this Plot instance is already connected with a + * DataPlot the connection will be released and a + * {@link PlotEvent} of the type {@link PlotEventType#DATA_PLOT_DISCONNECTED} + * will be sent to all registrated {@link PlotListener PlotListeners}. + *

+ * It registers itself at dataPlot and + * all its {@link DataCurve DataCurves}. + *

+ * Finally all curves will be generated and a PlotEvent + * of the type {@link PlotEventType#DATA_PLOT_CONNECTED} will be transmitted. + * @param dataPlot Data to be connected with this plot instance. + * Can be null in order to disconnect this instance from + * any DataPlot. + */ + public void connect(DataPlot dataPlot) { + if (_dataPlot != null) { + _dataPlot.removeDataListener(this); + notifyListeners(new PlotEvent(this, PlotEventType.DATA_PLOT_DISCONNECTED, + _dataPlot)); + } + _dataPlot = dataPlot; + if (_dataPlot != null) + { + _dataPlot.addDataListener(this); + generateCurves(_dataPlot); + notifyListeners(new PlotEvent(this, PlotEventType.DATA_PLOT_CONNECTED, + _dataPlot)); + } + } + + /** + * Transforms a point from device-independent coordinates into + * data coordinates. + * @param point Point in device-independent coordinates. + * @return transform point. + */ + public DataPoint transform(GraphPoint point) { + return _transformation.transformToData(point); + } + + /** + * Creates a graphical representation of the complete plot. + * @return GraphicalComposite containing the views of the + * coordinate system, the curves, and optionally the legend (in this order). + */ + public GraphicalComposite getCompletePlot() { + GraphicalComposite result = new GraphicalComposite(null); + result.addElement(_coordinateSystemView); + GraphicalElement[] curves = getCurves(); + for (int i = 0; i < curves.length; i++) { + result.addElement(curves[i]); + } + if (_annotation != null) { + result.addElement(_annotation); + } + if (_legendVisibility) { + result.addElement(getLegend()); + } + return result; + } + + /** Returns the view of the coordinate system. */ + public GraphicalElement getCoordinateSystem() { + return _coordinateSystemView; + } + + /** Returns the graphical representations of all curves. */ + public GraphicalElement[] getCurves() { + synchronized (_curves) { + GraphicalElement[] curves = new GraphicalElement[_curves.size()]; + for (int i = 0; i < curves.length; i++) { + curves[i] = ((Curve) _curves.elementAt(i)).getView(); + } + return curves; + } + } + + /** + * Returns the annotation layer. + * @return null if no annotation layer. + */ + public GraphicalElement getAnnotation() + { + return _annotation; + } + + /** + * Sets the annotation layer. + * @param annotation Any kind of graphics which will be drawn on the + * top of the curves but may be covered by the legend. + * Can be null. + */ + public void setAnnotation(GraphicalElement annotation) + { + _annotation = annotation; + } + + /** Returns true if the legend is visible. */ + public boolean isLegendVisible() { + return _legendVisibility; + } + + /** Returns the graphical representations of the legend. */ + public GraphicalElement getLegend() { + return _legendView; + } + + /** + * Handles the received {@link DataEvent} and notifies + * {@link PlotListener PlotListeners} by an event of the type + * {@link PlotEventType#DATA_CURVE_CHANGED} or + * {@link PlotEventType#DATA_PLOT_CHANGED}. The following table shows what + * this method does: + * + * + * + * + * + * + * + *
Source of eventAll hints for the next curve are null?ActionType of sent {@link PlotEvent}
{@link DataCurve}YesRecreate changed curve. + * DATA_CURVE_CHANGED
{@link DataCurve}NoRecreate changed curve + * and all curves with large curve index. + * DATA_PLOT_CHANGED
{@link DataPlot}-Recreate all curves + * and {@link Legend} view. + * DATA_PLOT_CHANGED
+ */ + public void dataChanged(DataEvent event) { + Integer index = new Integer(0); + PlotEventType type = PlotEventType.DATA_PLOT_CHANGED; + synchronized (_curves) { + int numberOfCurves = _curves.size(); + if (event.getContainer() instanceof DataCurve + && numberOfCurves == _dataPlot.getNumberOfElements()) { + DataCurve curve = (DataCurve) event.getContainer(); + index = new Integer(curve.getContainer().getIndexOf(curve)); + type = PlotEventType.DATA_CURVE_CHANGED; + fillCurve(index.intValue(), curve); + if (index.intValue() < numberOfCurves - 1) { + Vector curveHints + = (Vector) _nextCurveHints.elementAt(index.intValue()); + for (int i = 0, n = curveHints.size(); i < n; i++) { + if (curveHints.elementAt(i) != null) { + type = PlotEventType.DATA_PLOT_CHANGED; + for (int j = index.intValue()+1; j < numberOfCurves; j++) { + fillCurve(j, (DataCurve) _dataPlot.getElement(j)); + } + break; + } + } + } + } else { + generateCurves(_dataPlot); + } + } + notifyListeners(new PlotEvent(Plot.this, type, index)); + } + + /** + * Generates all curves based on the specified data. + * In addition the legend view is created. + */ + private void generateCurves(DataPlot dataPlot) { + synchronized (_curves) { + _legendView = new GraphicalComposite(null); + _legendView.addElement(_legend.getBox()); + _curves.setSize(0); + _nextCurveHints.setSize(0); + for (int i = 0, n = dataPlot.getNumberOfElements(); i < n; i++) { + Curve curve = _curveFactory.create(i, n, _clippingShape, _legend); + _curves.addElement(curve); + _nextCurveHints.addElement(new Vector()); + DataCurve dataCurve = (DataCurve) dataPlot.getElement(i); + _legendView.addElement(curve.getLegendSymbol()); + _legendView.addElement( + _legend.createCurveTitle(i, n, dataCurve.getTitle())); + fillCurve(i, dataCurve); + } + } + } + + private void fillCurve(int curveIndex, DataCurve dataCurve) { + Vector curveHints = (Vector) _nextCurveHints.elementAt(curveIndex); + Curve curve = (Curve) _curves.elementAt(curveIndex); + curve.removeAllPoints(); + for (int i = 0, n = dataCurve.getNumberOfElements(); i < n; i++) { + setHintForNextCurve(curveHints, i, + curve.addPoint(_transformation.transformToGraph( + (DataPoint) dataCurve.getElement(i)), + getHintForNextCurve(curveIndex - 1, i))); + } + } + + private Hint getHintForNextCurve(int curveIndex, int pointIndex) { + Hint result = _initialHintForNextCurve; + if (curveIndex >= 0) { + Vector curveHints = (Vector) _nextCurveHints.elementAt(curveIndex); + result = pointIndex < curveHints.size() ? + (Hint) curveHints.elementAt(pointIndex) + : getHintForNextCurve(curveIndex - 1, pointIndex); + } + return result; + } + + private void setHintForNextCurve(Vector curveHints, int pointIndex, + Hint hint) { + while (curveHints.size() <= pointIndex) { + curveHints.addElement(_initialHintForNextCurve); + } + curveHints.setElementAt(hint, pointIndex); + } +} diff --git a/src/jcckit/plot/PlotCanvas.java b/src/jcckit/plot/PlotCanvas.java new file mode 100644 index 00000000000..9c5480d5b30 --- /dev/null +++ b/src/jcckit/plot/PlotCanvas.java @@ -0,0 +1,135 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.data.DataPlot; +import jcckit.graphic.Anchor; +import jcckit.graphic.ClippingRectangle; +import jcckit.util.ConfigParameters; + +/** + * An abstract canvas containg a single {@link Plot}. The canvas is specified + * by a {@link ClippingRectangle}, called paper. A horizontal and + * vertical {@link Anchor} determine the position of the paper on the actual + * device. + * + * @author Franz-Josef Elmer + */ +public class PlotCanvas implements PlotListener { + /** Configuration parameter key. */ + public static final String PAPER_KEY = "paper", HORIZONTAL_ANCHOR_KEY = "horizontalAnchor", + VERTICAL_ANCHOR_KEY = "verticalAnchor", PLOT_KEY = "plot"; + private final ClippingRectangle _paper; + private final Anchor _horizontalAnchor; + private final Anchor _verticalAnchor; + private final Plot _plot; + + /** + * Creates an instance from the specified configuration parameters. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
horizontalAnchor = centerStringnoHorizontal position of the paper relative to the device border. + * Possible values are left, center, and + * right.
paper = 0, 0, 1, 0.6double[]noRectangle defining the paper. The first two values determine the x- + * and y- coordinates (in device-independent units) of the lower-left + * corner. The last two values determine the upper-right corner.
plot = default values of {@link Plot}ConfigParametersnoDefinition of the {@link Plot}.
verticalAnchor = centerStringnoVertical position of the paper relative to the device border. + * Possible values are top, center, and + * bottom.
+ *

+ * Note, that this instance registers itself at the wrapped {@link Plot} + * instance. + */ + public PlotCanvas(ConfigParameters config) { + double[] paper = config.getDoubleArray(PAPER_KEY, new double[] { 0, 0, 1, 0.6 }); + _paper = new ClippingRectangle(paper[0], paper[1], paper[2], paper[3]); + _horizontalAnchor = Anchor.getHorizontalAnchor(config, HORIZONTAL_ANCHOR_KEY, Anchor.CENTER); + _verticalAnchor = Anchor.getVerticalAnchor(config, VERTICAL_ANCHOR_KEY, Anchor.CENTER); + _plot = new Plot(config.getNode(PLOT_KEY)); + _plot.addPlotListener(this); + } + + /** Returns the paper definition. */ + public ClippingRectangle getPaper() { + return _paper; + } + + /** Returns the horizontal anchor. */ + public Anchor getHorizontalAnchor() { + return _horizontalAnchor; + } + + /** Returns the vertical anchor. */ + public Anchor getVerticalAnchor() { + return _verticalAnchor; + } + + /** Returns the plot. */ + public Plot getPlot() { + return _plot; + } + + /** + * Connects the wrapped {@link Plot} instance with the specified + * {@link DataPlot}. + * + * @param dataPlot + * Data to be connected with this plot canvas. Can be + * null in order to disconnect this instance from a + * DataPlot. + */ + public void connect(DataPlot dataPlot) { + _plot.connect(dataPlot); + } + + /** + * Handles the spcified event. Here nothing is done. But subclass may + * override this method. + */ + public void plotChanged(PlotEvent event) { + } +} diff --git a/src/jcckit/plot/PlotEvent.java b/src/jcckit/plot/PlotEvent.java new file mode 100644 index 00000000000..b1fecc3825e --- /dev/null +++ b/src/jcckit/plot/PlotEvent.java @@ -0,0 +1,88 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +/** + * A plot event signales some changes of a {@link Plot}. + * It has three attributes: + *

+ * + * + * @author Franz-Josef Elmer + */ +public class PlotEvent { + private final Plot _source; + private final PlotEventType _type; + private final Object _message; + + /** + * Creates a new event for the specified source, type, and message. + * @param source Plot causing this event. + * @param type Type of the event. Possible values are + * {@link PlotEventType#DATA_PLOT_CHANGED}, + * {@link PlotEventType#DATA_CURVE_CHANGED}, + * {@link PlotEventType#DATA_PLOT_CONNECTED}, and + * {@link PlotEventType#DATA_PLOT_DISCONNECTED}. + * @param message Message object. Can be null + */ + public PlotEvent(Plot source, PlotEventType type, Object message) { + _source = source; + _type = type; + _message = message; + } + + /** Returns the source of this event. */ + public Plot getSource() { + return _source; + } + + /** + * Returns the event type. + * @return either {@link PlotEventType#DATA_PLOT_CHANGED}, + * {@link PlotEventType#DATA_CURVE_CHANGED}, + * {@link PlotEventType#DATA_PLOT_CONNECTED}, or + * {@link PlotEventType#DATA_PLOT_DISCONNECTED}. + */ + public PlotEventType getType() { + return _type; + } + + /** Returns the message object. */ + public Object getMessage() { + return _message; + } +} diff --git a/src/jcckit/plot/PlotEventType.java b/src/jcckit/plot/PlotEventType.java new file mode 100644 index 00000000000..24a2a3cfc65 --- /dev/null +++ b/src/jcckit/plot/PlotEventType.java @@ -0,0 +1,36 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +/** + * Types of {@link PlotEvent PlotEvents}. Using the typesafe enumeration + * pattern. + * + * @author Franz-Josef Elmer + */ +public class PlotEventType { + /** Event type. */ + public static final PlotEventType DATA_PLOT_CONNECTED = new PlotEventType(), + DATA_PLOT_DISCONNECTED = new PlotEventType(), + COODINATE_SYSTEM_CHANGED = new PlotEventType(), + DATA_CURVE_CHANGED = new PlotEventType(), + DATA_PLOT_CHANGED = new PlotEventType(); + + private PlotEventType() {} +} diff --git a/src/jcckit/plot/PlotListener.java b/src/jcckit/plot/PlotListener.java new file mode 100644 index 00000000000..ed37113f808 --- /dev/null +++ b/src/jcckit/plot/PlotListener.java @@ -0,0 +1,29 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +/** + * Listener for changes of plots, diagrams, and charts. + * + * @author Franz-Josef Elmer + */ +public interface PlotListener { + /** Receives the specified plot event.*/ + public void plotChanged(PlotEvent event); +} diff --git a/src/jcckit/plot/PositionHint.java b/src/jcckit/plot/PositionHint.java new file mode 100644 index 00000000000..d068e29707b --- /dev/null +++ b/src/jcckit/plot/PositionHint.java @@ -0,0 +1,75 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.GraphPoint; +import jcckit.util.ConfigParameters; + +/** + * An immutable {@link Hint} capsulating two {@link GraphPoint GraphPoints}. + * + * @author Franz-Josef Elmer + */ +public class PositionHint implements Hint { + /** Configuration parameter key. */ + public static final String POSITION_KEY = "position", + ORIGIN_KEY = "origin"; + private final GraphPoint _position; + private final GraphPoint _origin; + + /** + * Creates an instance from the specified configuration parameters. + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
position = nulldouble[]noDefinition of position.
origin = position or (0,0) if position + * undefineddouble[]noDefinition of origin.
+ */ + public PositionHint(ConfigParameters config) { + double[] point = config.getDoubleArray(POSITION_KEY, null); + _position = point == null ? null : new GraphPoint(point); + _origin = new GraphPoint(config.getDoubleArray(ORIGIN_KEY, point)); + } + + /** + * Creates an instance based on two points. + * @param origin The origin. + * @param position The position. + */ + public PositionHint(GraphPoint origin, GraphPoint position) { + _origin = origin; + _position = position; + } + + /** Returns the position. */ + public GraphPoint getPosition() { + return _position; + } + + /** Returns the origin. */ + public GraphPoint getOrigin() { + return _origin; + } +} diff --git a/src/jcckit/plot/ShapeAttributesHint.java b/src/jcckit/plot/ShapeAttributesHint.java new file mode 100644 index 00000000000..4c71835af85 --- /dev/null +++ b/src/jcckit/plot/ShapeAttributesHint.java @@ -0,0 +1,140 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import java.awt.Color; + +import jcckit.graphic.GraphicAttributes; +import jcckit.graphic.ShapeAttributes; +import jcckit.util.ConfigParameters; + +/** + * An {@link AttributesHint} which wraps {@link ShapeAttributes}. + * Each call of {@link #getNextHint()} returns a new instance of + * ShapeAttributes where fill color, line color and/or + * line thickness has been increased by a constant amount. + * + * @author Franz-Josef Elmer + */ +public class ShapeAttributesHint implements AttributesHint, Cloneable { + /** Configuration parameter key. */ + public static final String INITIAL_ATTRIBUTES_KEY = "initialAttributes", + FILL_COLOR_HSB_INCREMENT_KEY + = "fillColorHSBIncrement", + LINE_COLOR_HSB_INCREMENT_KEY + = "lineColorHSBIncrement", + LINE_THICKNESS_INCREMENT_KEY + = "lineThicknessIncrement"; + private static float[] extractHSB(Color color) { + return color == null ? null + : Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), + null); + } + + private static Color createColor(float[] colorHSB) { + return colorHSB == null ? null + : Color.getHSBColor(colorHSB[0], colorHSB[1], colorHSB[2]); + } + + private static float[] incrementColor(float[] colorHSB, + double[] increments) { + float[] result = null; + if (colorHSB != null) { + result = (float[]) colorHSB.clone(); + for (int i = 0; i < 3; i++) { + result[i] += increments[i]; + } + } + return result; + } + + private float[] _fillColorHSB; + private float[] _lineColorHSB; + private double _lineThickness; + private double[] _linePattern; + private double[] _fillColorHSBIncrement; + private double[] _lineColorHSBIncrement; + private double _lineThicknessIncrement; + + /** + * Creates an instance from the specified configuration parameters. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
initialAttributes = default values of + * {@link ShapeAttributes}ConfigParametersnoInitial values of shape attributes. Note, that default + * fill and line colors are undefined (they depend on the + * Renderer). In this case color increments have no effects. + *
fillColorHSBIncrement = 0 0 0double[]noHue, saturation, and brightness increments of the fill color. + *
lineColorHSBIncrement = 0 0 0double[]noHue, saturation, and brightness increments of the line color. + *
lineThicknessIncrement = 0doublenoLine thickness increment.
+ */ + public ShapeAttributesHint(ConfigParameters config) { + ShapeAttributes attributes + = new ShapeAttributes(config.getNode(INITIAL_ATTRIBUTES_KEY)); + _fillColorHSB = extractHSB(attributes.getFillColor()); + _lineColorHSB = extractHSB(attributes.getLineColor()); + _lineThickness = attributes.getLineThickness(); + _linePattern = attributes.getLinePattern(); + + _fillColorHSBIncrement + = config.getDoubleArray(FILL_COLOR_HSB_INCREMENT_KEY, new double[3]); + _lineColorHSBIncrement + = config.getDoubleArray(LINE_COLOR_HSB_INCREMENT_KEY, new double[3]); + _lineThicknessIncrement + = config.getDouble(LINE_THICKNESS_INCREMENT_KEY, 0); + } + + /** + * Creates a new ShapeAttributesHint where all attributes has been + * incremented. + */ + public AttributesHint getNextHint() { + ShapeAttributesHint nextHint = null; + try { + nextHint = (ShapeAttributesHint) clone(); + } catch (CloneNotSupportedException e) {} + nextHint._fillColorHSB + = incrementColor(_fillColorHSB, _fillColorHSBIncrement); + nextHint._lineColorHSB + = incrementColor(_lineColorHSB, _lineColorHSBIncrement); + nextHint._lineThickness + = Math.max(0, _lineThickness + _lineThicknessIncrement); + return nextHint; + } + + /** Returns the wrapped {@link ShapeAttributes} instance. */ + public GraphicAttributes getAttributes() { + return new ShapeAttributes(createColor(_fillColorHSB), + createColor(_lineColorHSB), + _lineThickness, _linePattern); + } +} diff --git a/src/jcckit/plot/SimpleCurve.java b/src/jcckit/plot/SimpleCurve.java new file mode 100644 index 00000000000..7477d2c2434 --- /dev/null +++ b/src/jcckit/plot/SimpleCurve.java @@ -0,0 +1,185 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import java.awt.Color; + +import jcckit.graphic.ClippingShape; +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicalComposite; +import jcckit.graphic.GraphicalElement; +import jcckit.graphic.LineAttributes; +import jcckit.graphic.Polygon; +import jcckit.graphic.ShapeAttributes; +import jcckit.util.ConfigParameters; +import jcckit.util.Factory; + +/** + * A simple curve is the basic implementation of the {@link Curve} interface. + * + * @author Franz-Josef Elmer + */ +public class SimpleCurve implements Curve { + /** Configuration parameter key. */ + public static final String SYMBOL_FACTORY_KEY = "symbolFactory", + WITH_LINE_KEY = "withLine", + SOFT_CLIPPING_KEY = "softClipping", + LINE_ATTRIBUTES_KEY = "lineAttributes", + INITIAL_HINT_FOR_NEXT_POINT_KEY + = "initialHintForNextPoint"; + private final ClippingShape _clippingShape; + private final SymbolFactory _symbolFactory; + private final GraphicalComposite _symbols; + private final GraphicalComposite _completeCurve; + private final GraphicalElement _legendSymbol; + private final Hint _initialHintForNextPoint; + private final Polygon _curve; + private final boolean _softClipping; + private Hint _hintForNextPoint; + + /** + * Creates a new curve. The parameter config contains: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
initialHintForNextPoint = nullConfigParametersnoDefinition of an initial {@link Hint} for the first curve point. + *
lineAttributes = a {@link ShapeAttributes} + * instances with default values and line colors based on + * the formula Color.getHSBColor(curveIndex/6,1,0.8)ConfigParametersnoConfiguration parameters of an instances of + * {@link jcckit.graphic.GraphicAttributes} for the + * {@link Polygon Polygons} connecting curve points.
symbolFactory = nullConfigParametersnoConfiguration parameters defining an instances of + * {@link SymbolFactory} for the {@link Symbol Symbols} + * decorating curve points.
softClipping = truebooleannoIf true no explicit clipping takes + * place but the symbol is not drawn if the corresponding curve + * point is outside the axis box.
+ * If false the symbol is + * drawn in any case but it may be clipped by the axis box. + * Soft-clipping should be set to false if the + * symbols are not located around the curve point (like for bars). + *
withLine = truebooleannoIf true curve points are connected by a + * {@link jcckit.graphic.Polygon}.
+ * @param config Configuration parameters described above. + * @param curveIndex Index of this curve in the collection of curves + * defining a {@link Plot}. + * @param numberOfCurves Number of curves in this collection. + * @param clippingShape Clipping shape. Can be null. + * @param legend Legend. Will be used to calculate the legend symbol. + * @throws IllegalArgumentException if symbolFactory == null and + * withLine == false. + * + */ + public SimpleCurve(ConfigParameters config, int curveIndex, + int numberOfCurves, ClippingShape clippingShape, + Legend legend) { + _symbolFactory = (SymbolFactory) Factory.createOrGet( + config.getNode(SYMBOL_FACTORY_KEY), null); + boolean withLine = config.getBoolean(WITH_LINE_KEY, true); + LineAttributes lineAttributes = (LineAttributes) Factory.createOrGet( + config.getNode(LINE_ATTRIBUTES_KEY), + new ShapeAttributes(null, Color.getHSBColor((curveIndex % 6) / 6f, + 1f, 0.8f), + 0, null)); + if (_symbolFactory != null || withLine) { + _clippingShape = clippingShape; + _completeCurve = new GraphicalComposite(null); + if (withLine) { + GraphicalComposite container = new GraphicalComposite(clippingShape); + _curve = new Polygon(lineAttributes, false); + container.addElement(_curve); + _completeCurve.addElement(container); + } else { + _curve = null; + } + _softClipping = config.getBoolean(SOFT_CLIPPING_KEY, true); + if (_symbolFactory != null) { + _symbols = new GraphicalComposite(_softClipping ? null + : clippingShape); + _completeCurve.addElement(_symbols); + } else { + _symbols = null; + } + } else { + throw new IllegalArgumentException( + "Either a SymbolFactory must exist or withLines == true."); + } + _hintForNextPoint = _initialHintForNextPoint + = (Hint) Factory.createOrGet( + config.getNode(INITIAL_HINT_FOR_NEXT_POINT_KEY), null); + _legendSymbol = legend.createSymbol(curveIndex, numberOfCurves, + _symbolFactory, withLine, + lineAttributes); + } + + /** + * Returns the graphical representation of a curve. + * @return always the same instance. + */ + public GraphicalElement getView() { + return _completeCurve; + } + + /** Returns the legend symbol. */ + public GraphicalElement getLegendSymbol() { + return _legendSymbol; + } + + /** Appends a new point to the curve if inside the clipping shape. */ + public Hint addPoint(GraphPoint point, Hint hintFromPreviousCurve) { + if (_curve != null) { + _curve.addPoint(point); + } + Hint hintForNextCurve = hintFromPreviousCurve; + if (_symbolFactory != null) { + Symbol symbol = _symbolFactory.createSymbol(point, _hintForNextPoint, + hintFromPreviousCurve); + if (_clippingShape == null || !_softClipping + || _clippingShape.isInside(point)) { + _symbols.addElement(symbol.getSymbol()); + } + _hintForNextPoint = symbol.getHintForNextPoint(); + hintForNextCurve = symbol.getHintForNextCurve(); + } + return hintForNextCurve; + } + + public void removeAllPoints() { + if (_curve != null) { + _curve.removeAllPoints(); + } + if (_symbols != null) { + _symbols.removeAllElements(); + } + _hintForNextPoint = _initialHintForNextPoint; + } +} diff --git a/src/jcckit/plot/SimpleCurveFactory.java b/src/jcckit/plot/SimpleCurveFactory.java new file mode 100644 index 00000000000..4d7b2bc0279 --- /dev/null +++ b/src/jcckit/plot/SimpleCurveFactory.java @@ -0,0 +1,80 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import java.util.Properties; +import java.util.StringTokenizer; + +import jcckit.graphic.ClippingShape; +import jcckit.util.ConfigParameters; +import jcckit.util.PropertiesBasedConfigData; + +/** + * Factory for {@link SimpleCurve SimpleCurves}. + * + * @author Franz-Josef Elmer + */ +public class SimpleCurveFactory implements CurveFactory { + /** Configuration parameter key. */ + public static final String DEFINITIONS_KEY = "definitions"; + + private ConfigParameters[] _configs = new ConfigParameters[] + {new ConfigParameters(new PropertiesBasedConfigData(new Properties()))}; + + /** + * Creates an instance from the specified configuration parameter. + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
definitions = one empty ConfigParameters + * instanceString[]noKeys of subtrees defining {@link ConfigParameters} + * used by the {@link SimpleCurve#SimpleCurve constructor} of + * {@link SimpleCurve}.
+ */ + public SimpleCurveFactory(ConfigParameters config) { + String value = config.get(DEFINITIONS_KEY, null); + if (value != null) { + StringTokenizer tokenizer = new StringTokenizer(value); + _configs = new ConfigParameters[tokenizer.countTokens()]; + for (int i = 0; i < _configs.length; i++) { + _configs[i] = config.getNode(tokenizer.nextToken()); + } + } + } + + /** + * Creates an instance of {@link SimpleCurve}. + * @param curveIndex Index of the curve. Will be used to select the + * {@link ConfigParameters} object and the line attributes. + * In addition it will be used to calculate the y-coordinate + * of the legend symbol. + * @param numberOfCurves Number of curves. Will be needed to calculate + * the y-coordinate of the legend symbol. + * @param clippingShape The clipping shape. + * @param legend The legend. Will be needed to create the legend symbol. + */ + public Curve create(int curveIndex, int numberOfCurves, + ClippingShape clippingShape, Legend legend) { + return new SimpleCurve(_configs[curveIndex % _configs.length], curveIndex, + numberOfCurves, clippingShape, legend); + } +} diff --git a/src/jcckit/plot/SquareSymbolFactory.java b/src/jcckit/plot/SquareSymbolFactory.java new file mode 100644 index 00000000000..4dc37726800 --- /dev/null +++ b/src/jcckit/plot/SquareSymbolFactory.java @@ -0,0 +1,54 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicAttributes; +import jcckit.graphic.GraphicalElement; +import jcckit.graphic.Rectangle; +import jcckit.util.ConfigParameters; + +/** + * A factory of square symbols. + * + * @author Franz-Josef Elmer + */ +public class SquareSymbolFactory extends AbstractSymbolFactory { + /** + * Creates an instance from the specified configuration parameters. + * For the configuration parameters see the + * + * constructor of the superclass {@link AbstractSymbolFactory}. + */ + public SquareSymbolFactory(ConfigParameters config) { + super(config); + } + + /** + * Creates a {@link Rectangle}. + * @param centerPosition Position of the center of the rectangle. + * @param size Diameter of the rectangle. + * @param attributes Rectangle attributes. + */ + protected GraphicalElement createPlainSymbol(GraphPoint centerPosition, + double size, + GraphicAttributes attributes) { + return new Rectangle(centerPosition, size, size, attributes); + } +} diff --git a/src/jcckit/plot/Symbol.java b/src/jcckit/plot/Symbol.java new file mode 100644 index 00000000000..69a2aa5db7f --- /dev/null +++ b/src/jcckit/plot/Symbol.java @@ -0,0 +1,56 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.GraphicalElement; + +/** + * Immutable class holding the graphical represention of the symbol and + * two {@link Hint Hints}. + * + * @author Franz-Josef Elmer + */ +public class Symbol { + private final GraphicalElement _symbol; + private final Hint _hintForNextPoint; + private final Hint _hintForNextCurve; + + /** Creates an instance for the specified symbol and hints. */ + public Symbol(GraphicalElement symbol, Hint hintForNextPoint, + Hint hintForNextCurve) { + _symbol = symbol; + _hintForNextPoint = hintForNextPoint; + _hintForNextCurve = hintForNextCurve; + } + + /** Returns the graphical symbol. */ + public GraphicalElement getSymbol() { + return _symbol; + } + + /** Returns the hint for the next point. */ + public Hint getHintForNextPoint() { + return _hintForNextPoint; + } + + /** Returns the hint for the next curve. */ + public Hint getHintForNextCurve() { + return _hintForNextCurve; + } +} diff --git a/src/jcckit/plot/SymbolFactory.java b/src/jcckit/plot/SymbolFactory.java new file mode 100644 index 00000000000..d354bc09596 --- /dev/null +++ b/src/jcckit/plot/SymbolFactory.java @@ -0,0 +1,65 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicalElement; + +/** + * Interface of a symbol factory. A symbol is a {@link GraphicalElement} + * or {@link jcckit.graphic.GraphicalComposite}. A symbol factory creates + * the same type of symbols. In general, they have all the same size. + * But they are distinguished from each other by their positions. + * In addition they may also differ in other properties which will + * be determined by {@link Hint Hints}. + * + * @author Franz-Josef Elmer + */ +public interface SymbolFactory { + /** Common configuration parameter key need by implementing classes. */ + public static final String SIZE_KEY = "size", + ATTRIBUTES_KEY = "attributes"; + + /** Default size of a symbol = 0.01. */ + public static final double DEFAULT_SIZE = 0.01; + + /** + * Creates a symbol for the specified point taking into account + * the specified hints. + * @param point The position of the symbol. In general it is a transformation + * of a corresponding {@link jcckit.data.DataPoint} into a + * {@link GraphPoint}. + * @param hintFromPreviousPoint Hint from the previous point of the same + * {@link Curve} or null. + * @param hintFromPreviousCurve Hint from the previous + * {@link Curve} or null. + */ + public Symbol createSymbol(GraphPoint point, Hint hintFromPreviousPoint, + Hint hintFromPreviousCurve); + + /** + * Creates a symbol for the legend at the specified position. + * @param centerPosition Center position of the symbol. + * @param size The size of the symbol. Will not be used if the symbol + * of the curve points have all the same size. In this case + * the symbol for the legend has the size of the curve symbols. + */ + public GraphicalElement createLegendSymbol(GraphPoint centerPosition, + double size); +} diff --git a/src/jcckit/plot/TicLabelMap.java b/src/jcckit/plot/TicLabelMap.java new file mode 100644 index 00000000000..d2989e48128 --- /dev/null +++ b/src/jcckit/plot/TicLabelMap.java @@ -0,0 +1,136 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.plot; + +import java.util.StringTokenizer; + +import jcckit.util.ConfigParameters; +import jcckit.util.TicLabelFormat; + +/** + * Map of number intervals onto a text label. The map is defined by a + * map description string provided by configuration data. + *

+ * The map description is a list + * of conditions separated by ';'. The conditions are tested from left to + * right until a condition is fulfilled for the tic value. If no condition + * is fullfilled a '?' will be returned. + *

+ * A condition description has one of the following forms: + *

<label>
+ *
<number>=<label>
+ *
<number1>:<number2>=<label>
+ *

+ * The first type of condition is always fulfilled. It will return + * <label>. This is a kind of else condtion + * which is put at the end of the condition list. + *

+ * The second form maps a particular number onto a label. In order to be + * equal with the sepcified number the tic value should not deviate more + * than 1 ppm (part per millions) from <number>. + *

+ * The third form maps an interval onto a label. The condition reads + *

+ * <number1> <= tic label < <number2> + *

+ * Examples: + *


+ * 1=monday;2=tuesday;3=wednesday;4=thursday;5=friday;6=saturday;7=sunday 
+ * 0.5:1.5=I; 1.5:2.5 = II; 2.5:3.5 = III; the rest 
+ * 
+ * + * @author Franz-Josef Elmer + */ +public class TicLabelMap implements TicLabelFormat { + public static final String MAP_KEY = "map"; + + private static class MapItem { + private double _min = Double.MIN_VALUE; + private double _max = Double.MAX_VALUE; + private final String label; + public MapItem(String item) { + int index = item.indexOf('='); + if (index < 0) { + label = item; + } else { + label = item.substring(index + 1).trim(); + item = item.substring(0, index).trim(); + index = item.indexOf(':'); + if (index < 0) { + _min = new Double(item).doubleValue(); + _max = _min == 0 ? Double.MIN_VALUE : _min * 1.000001d; + _min = _min * 0.999999d; + if (_min > _max) { + double z = _min; + _min = _max; + _max = z; + } + } else { + _min = new Double(item.substring(0, index)).doubleValue(); + _max = new Double(item.substring(index + 1)).doubleValue(); + } + } + } + public boolean isInside(double value) { + return value >= _min && value < _max; + } + } + + private final MapItem[] _map; + + /** + * Creates an instance from the specified configuration parameters. + * + * + * + * + * + * + *
Key & Default ValueTypeMandatoryDescription
mapStringyesMap description as explained above.
+ */ + public TicLabelMap(ConfigParameters config) { + StringTokenizer tokenizer = new StringTokenizer(config.get(MAP_KEY), ";"); + _map = new MapItem[tokenizer.countTokens()]; + for (int i = 0; i < _map.length; i++) + { + String item = tokenizer.nextToken(); + try { + _map[i] = new MapItem(item.trim()); + } catch (NumberFormatException e) { + throw new NumberFormatException("Item '" + item + "' of " + + config.getFullKey(MAP_KEY) + " has an invalid number."); + } + } + } + + /** + * Maps the specified tic value onto a text label in accordance + * with the map description. + */ + public String form(double ticValue) { + String result = "?"; + for (int i = 0; i < _map.length; i++) { + if (_map[i].isInside(ticValue)) { + result = _map[i].label; + break; + } + } + return result; + } +} diff --git a/src/jcckit/renderer/Graphics2DRenderer.java b/src/jcckit/renderer/Graphics2DRenderer.java new file mode 100644 index 00000000000..9b229ebf90f --- /dev/null +++ b/src/jcckit/renderer/Graphics2DRenderer.java @@ -0,0 +1,313 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.renderer; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import jcckit.graphic.BasicGraphicalElement; +import jcckit.graphic.ClippingRectangle; +import jcckit.graphic.ClippingShape; +import jcckit.graphic.FillAttributes; +import jcckit.graphic.FontStyle; +import jcckit.graphic.GraphPoint; +import jcckit.graphic.GraphicAttributes; +import jcckit.graphic.GraphicalComposite; +import jcckit.graphic.GraphicalCompositeRenderer; +import jcckit.graphic.LineAttributes; +import jcckit.graphic.Oval; +import jcckit.graphic.OvalRenderer; +import jcckit.graphic.Polygon; +import jcckit.graphic.PolygonRenderer; +import jcckit.graphic.Rectangle; +import jcckit.graphic.RectangleRenderer; +import jcckit.graphic.Text; +import jcckit.graphic.TextAttributes; +import jcckit.graphic.TextRenderer; + +/** + * Renderer who draws the {@link jcckit.graphic.GraphicalElement + * GraphicalElements} into a java.awt.Graphics2D context. + *

+ * The default color for lines and texts is determined by the current color of + * the Graphics2D context when a new instance of + * Graphics2DRenderer is created. + *

+ * The default font is SansSerif-12. + * + * @author Franz-Josef Elmer + */ +public class Graphics2DRenderer implements GraphicalCompositeRenderer, PolygonRenderer, OvalRenderer, TextRenderer, + RectangleRenderer { + private static final int FS = 1; + private static final String DEFAULT_FONT_NAME = "SansSerif"; + private static final FontStyle DEFAULT_FONT_STYLE = FontStyle.NORMAL; + private static final int DEFAULT_FONT_SIZE = 12; + + private Color _defaultColor; + private Graphics2D _graphics; + + /** + * Initializes this instance. During renderering the current transformation + * will be leaved unchanged. But the current Clip may be cleared. + * + * @param graphics + * Graphics2D context into which the + * {@link BasicGraphicalElement BaiscGraphicalElements} are + * painted. + * @return this instance. + */ + public Graphics2DRenderer init(Graphics2D graphics) { + _graphics = graphics; + _defaultColor = graphics.getColor(); // the foreground color + return this; + } + + /** + * Starts rendering of the specified composite. Does nothing except if + * composite has a {@link ClippingShape}. In this case the Clip + * of the Graphics2D context becomes the clipping rectangle + * determined by the bounding box of the ClippingShape. + */ + public void startRendering(GraphicalComposite composite) { + ClippingShape shape = composite.getClippingShape(); + if (shape != null) { + ClippingRectangle rect = shape.getBoundingBox(); + _graphics.clip(new Rectangle2D.Double(rect.getMinX(), rect.getMinY(), rect.getMaxX() - rect.getMinX(), rect + .getMaxY() + - rect.getMinY())); + } + } + + /** + * Finishes rendering of the specified composite. Does nothing except if + * composite has a {@link ClippingShape}. In this case the Clip + * of the Graphics2D context will be cleared. + */ + public void finishRendering(GraphicalComposite composite) { + _graphics.setClip(null); + } + + /** Paints the specified polygon into the Graphics2D context. */ + public void render(Polygon polygon) { + int numberOfPoints = polygon.getNumberOfPoints(); + if (numberOfPoints > 0) { + Color currentColor = _graphics.getColor(); + GeneralPath p = new GeneralPath(GeneralPath.WIND_EVEN_ODD, numberOfPoints); + p.moveTo((float) polygon.getPoint(0).getX(), (float) polygon.getPoint(0).getY()); + for (int i = 1; i < numberOfPoints; i++) { + p.lineTo((float) polygon.getPoint(i).getX(), (float) polygon.getPoint(i).getY()); + } + if (polygon.isClosed()) { + p.closePath(); + } + drawShape(p, polygon, currentColor); + } + } + + /** + * Paints the specified rectangle into the current Graphics + * context. + */ + public void render(Rectangle rectangle) { + Color currentColor = _graphics.getColor(); + GraphPoint center = rectangle.getCenter(); + double width = rectangle.getWidth(); + double height = rectangle.getHeight(); + Rectangle2D rect = new Rectangle2D.Double(center.getX() - 0.5 * width, center.getY() - 0.5 * height, width, + height); + drawShape(rect, rectangle, currentColor); + } + + /** + * Paints the specified oval into the current Graphics context. + */ + public void render(Oval oval) { + Color currentColor = _graphics.getColor(); + GraphPoint center = oval.getCenter(); + double width = oval.getWidth(); + double height = oval.getHeight(); + Ellipse2D ellipse = new Ellipse2D.Double(center.getX() - 0.5 * width, center.getY() - 0.5 * height, width, + height); + drawShape(ellipse, oval, currentColor); + } + + private void drawShape(Shape shape, BasicGraphicalElement element, Color backupColor) { + GraphicAttributes attributes = element.getGraphicAttributes(); + Color fillColor = null; + if (element.isClosed() && attributes instanceof FillAttributes) { + fillColor = ((FillAttributes) attributes).getFillColor(); + } + if (fillColor != null) { + _graphics.setColor(fillColor); + _graphics.fill(shape); + } + Color lineColor = _defaultColor; + if (attributes instanceof LineAttributes) { + LineAttributes la = (LineAttributes) attributes; + BasicStroke stroke = new BasicStroke((float) la.getLineThickness()); + double[] linePattern = la.getLinePattern(); + if (linePattern != null) { + float[] dash = new float[linePattern.length]; + for (int i = 0; i < dash.length; i++) { + dash[i] = (float) la.getLinePattern()[i]; + } + stroke = new BasicStroke(stroke.getLineWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, + dash, 0f); + } + _graphics.setStroke(stroke); + if (la.getLineColor() != null || fillColor != null) { + lineColor = la.getLineColor(); + } + } + if (lineColor != null) { + _graphics.setColor(lineColor); + _graphics.draw(shape); + } + _graphics.setColor(backupColor); + } + + /** + * Paints the specified text into the current Graphics context. + *

+ * If the font size is zero the default font size will be used. + *

+ * If the orientation angle is unequal zero the text will first be painted + * into an off-screen image and rotated. Finally, it will be drawn into the + * current Graphics context. Note, that only integer multiples of + * 90 degree rotation are performed. Other orientation angles will be + * adjusted to the nearest integer multiple of 90 degree. + */ + public void render(Text text) { + final GraphicAttributes ga = text.getGraphicAttributes(); + if (ga instanceof TextAttributes) { + final TextAttributes ta = (TextAttributes) ga; + final Color currentColor = _graphics.getColor(); + Color fontColor = ta.getTextColor(); + if (fontColor == null) { + fontColor = _defaultColor; + } + _graphics.setColor(fontColor); + + final double scale = _graphics.getTransform().getScaleX(); + final String str = text.getText(); + + AffineTransform before = _graphics.getTransform(); + _graphics.setTransform(new AffineTransform()); + + double fs = ta.getFontSize(); + fs = fs == 0 ? 1 : fs * scale / DEFAULT_FONT_SIZE; + + Font font = createFont(ta, 0); + + AffineTransform fontTransform = new AffineTransform(); + fontTransform.scale(fs, fs); + fontTransform.rotate(-ta.getOrientationAngle() * Math.PI / 180); + font = font.deriveFont(fontTransform); + _graphics.setFont(font); + Rectangle2D bounds = _graphics.getFontMetrics().getStringBounds(str, _graphics); + + fontTransform.rotate(-ta.getOrientationAngle() * Math.PI / 180); + + final double yy = bounds.getHeight() + bounds.getY(); + + Point2D.Double pos = new Point2D.Double(text.getPosition().getX(), text.getPosition().getY()); + before.transform(pos, pos); + + double x = 0; + double y = 0; + if (ta.getOrientationAngle() == 0) { + x = -0.5 * ta.getHorizontalAnchor().getFactor() * bounds.getWidth(); + y = 0.5 * ta.getVerticalAnchor().getFactor() * bounds.getHeight() - yy; + x = pos.x + x; + y = pos.y + y; + } else { + x = 0.5 * ta.getVerticalAnchor().getFactor() * bounds.getHeight(); + y = 0.5 * ta.getHorizontalAnchor().getFactor() * bounds.getWidth(); + // System.err.println("yy="+y+" dx="+x+" dy="+y); + // x = 0; + // y = 0; + x = pos.x + x; + y = pos.y + y; + } + +// if (ta.getOrientationAngle() == 0) { +//// System.err.println("x0=" + x); +//// System.err.println("y0=" + y); +// } else { +// System.err.println("bounds=" + bounds + " y=" + bounds.getY() + " h=" + bounds.getHeight() + " vert=" +// + ta.getVerticalAnchor().getFactor()+" horz="+ta.getHorizontalAnchor().getFactor()); +// System.err.println("x1=" + x); +// System.err.println("y1=" + y); +// } + + + _graphics.drawString(str, (float) x, (float) y); + // _graphics.fillRect((int)x, (int)y, 5, 5); + _graphics.setTransform(before); + _graphics.setColor(currentColor); + } + } + + /** + * Creates a font instance based on the specified text attributes and font + * size. + * + * @param attributes + * Text attributes (font name and style). + * @param size + * Font size in pixel. If 0 {@link #DEFAULT_FONT_SIZE} will be + * used. + * @return new font instance. + */ + static Font createFont(TextAttributes attributes, int size) { + String fontName = attributes.getFontName(); + if (fontName == null) { + fontName = DEFAULT_FONT_NAME; + } + + FontStyle fontStyle = attributes.getFontStyle(); + if (fontStyle == null) { + fontStyle = DEFAULT_FONT_STYLE; + } + int style = Font.PLAIN; + if (fontStyle == FontStyle.BOLD) { + style = Font.BOLD; + } else if (fontStyle == FontStyle.ITALIC) { + style = Font.ITALIC; + } else if (fontStyle == FontStyle.BOLD_ITALIC) { + style = Font.BOLD + Font.ITALIC; + } + + if (size == 0) { + size = DEFAULT_FONT_SIZE; + } + + return new Font(fontName, style, size); + } + +} diff --git a/src/jcckit/renderer/Transformation.java b/src/jcckit/renderer/Transformation.java new file mode 100644 index 00000000000..1277c2e7e63 --- /dev/null +++ b/src/jcckit/renderer/Transformation.java @@ -0,0 +1,107 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.renderer; + +import java.awt.Graphics2D; + +import jcckit.graphic.Anchor; +import jcckit.graphic.ClippingRectangle; +import jcckit.graphic.GraphPoint; + +/** + * Transformation between device-independent coordinates + * and standard Java coordinates. The aspect-ratio will + * be the same. The position in the canvas is determined by a + * {@link jcckit.graphic.Rectangle Rectangle} defining a (virtual) + * paper which is placed in the canvas according to an anchor point. + * Depending on the aspect ratio of the canvas the paper width or + * height occupies the canvas width or height. + * + * @author Franz-Josef Elmer + */ +public class Transformation { + private final double _scale, _x0, _y0; + + public String toString() { + return "_scale=" + _scale + " _x0=" + _x0 + " _y0=" + _y0; + } + + /** + * Creates an instance for the specified canvas size, paper size, + * and anchor points of the paper. + * @param width Width of the canvas. + * @param height Height of the canvas. + * @param paper Rectangle defining the paper in device-independent + * coordinates. + * @param horizontalAnchor Horizontal anchor of the paper in the canvas. + * @param verticalAnchor Vertical anchor of the paper in the canvas. + */ + public Transformation(int width, int height, ClippingRectangle paper, + Anchor horizontalAnchor, Anchor verticalAnchor) { + double pWidth = paper.getMaxX() - paper.getMinX(); + double pHeight = paper.getMaxY() - paper.getMinY(); + _scale = Math.min(width / pWidth, height / pHeight); + _x0 = 0.5 * horizontalAnchor.getFactor() * (width - _scale * pWidth) + - _scale * paper.getMinX(); + _y0 = 0.5 * verticalAnchor.getFactor() * (_scale * pHeight - height) + + height + _scale * + paper.getMinY(); + } + + /** Transforms the device-independent x coordinate into Java coordinates. */ + public int transformX(double x) { + return trim(_scale * x + _x0); + } + + /** Transforms the device-independent y coordinate into Java coordinates. */ + public int transformY(double y) { + return trim(_y0 - _scale * y); + } + + /** Transforms the device-independent width into Java width. */ + public int transformWidth(double width) { + return trim(_scale * width + 0.5); + } + + /** Transforms the device-independent height into Java height. */ + public int transformHeight(double height) { + return trim(_scale * height + 0.5); + } + + private static int trim(double number) + { + return number > Short.MAX_VALUE + ? Short.MAX_VALUE + : (number < Short.MIN_VALUE ? Short.MIN_VALUE : (int) number); + } + + /** + * Transforms a point in Java coordinates back into device-independent + * coordinates. + */ + public GraphPoint transformBack(int x, int y) { + return new GraphPoint((x - _x0) / _scale, (_y0 - y) / _scale); + } + +public void apply(Graphics2D g) { + g.translate(_x0, _y0); + g.scale(_scale, -_scale); + +} +} + diff --git a/src/jcckit/transformation/CartesianTransformation.java b/src/jcckit/transformation/CartesianTransformation.java new file mode 100644 index 00000000000..d2c30da4926 --- /dev/null +++ b/src/jcckit/transformation/CartesianTransformation.java @@ -0,0 +1,96 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.transformation; + +import jcckit.data.DataPoint; +import jcckit.graphic.GraphPoint; +import jcckit.util.Util; + +/** + * Two-dimensional Cartesian transformation. The two independent + * transformations for the x-axis and the y-axis can be logarithmic + * from data coordinates to device-independent coordinates in order to + * realize diagrams with logarithmic scales. + * + * @author Franz-Josef Elmer + */ +public class CartesianTransformation implements Transformation { + private final boolean _xLogScale; + private final double _xOffset; + private final double _xScale; + private final boolean _yLogScale; + private final double _yOffset; + private final double _yScale; + + /** + * Creates an instance from the specified reference points. + * Note, that the reference points must differ in x and y coordinates + * otherwise a transformation would not be possible. + * @param xLogScale true if logarithmic x axis. + * @param yLogScale true if logarithmic y axis. + * @param dataPoint1 First reference point in data coordinates. + * @param graphPoint1 First reference point in device-independent + * coordinates. + * @param dataPoint2 Second reference point in data coordinates. + * @param graphPoint2 Second reference point in device-independent + * coordinates. + * @throws IllegalArgumentException if transformation in at least + * one of both directions is not possible. + */ + public CartesianTransformation(boolean xLogScale, boolean yLogScale, + DataPoint dataPoint1, GraphPoint graphPoint1, + DataPoint dataPoint2, GraphPoint graphPoint2) { + _xLogScale = xLogScale; + double d1 = Util.log(dataPoint1.getX(), xLogScale); + double dd = Util.log(dataPoint2.getX(), xLogScale) - d1; + check(dd, "data", "x", d1); + _xScale = (graphPoint2.getX() - graphPoint1.getX()) / dd; + check(_xScale, "graphical", "x", graphPoint1.getX()); + _xOffset = graphPoint1.getX() - d1 * _xScale; + + _yLogScale = yLogScale; + d1 = Util.log(dataPoint1.getY(), yLogScale); + dd = Util.log(dataPoint2.getY(), yLogScale) - d1; + check(dd, "data", "y", d1); + _yScale = (graphPoint2.getY() - graphPoint1.getY()) / dd; + check(_yScale, "graphical", "y", graphPoint1.getY()); + _yOffset = graphPoint1.getY() - d1 * _yScale; + } + + private void check(double valueToCheck, String type, String axis, + double value) { + if (valueToCheck == 0) { + throw new IllegalArgumentException("The " + type + + " reference points in " + axis + " must be different; both are " + + value); + } + } + + public GraphPoint transformToGraph(DataPoint point) { + return new GraphPoint( + _xOffset + Util.log(point.getX(), _xLogScale) * _xScale, + _yOffset + Util.log(point.getY(), _yLogScale) * _yScale); + } + + public DataPoint transformToData(GraphPoint point) { + return new DataPoint( + Util.exp((point.getX() - _xOffset) / _xScale, _xLogScale), + Util.exp((point.getY() - _yOffset) / _yScale, _yLogScale)); + } +} diff --git a/src/jcckit/transformation/Transformation.java b/src/jcckit/transformation/Transformation.java new file mode 100644 index 00000000000..46b3d16a9b4 --- /dev/null +++ b/src/jcckit/transformation/Transformation.java @@ -0,0 +1,44 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.transformation; + +import jcckit.data.DataPoint; +import jcckit.graphic.GraphPoint; + +/** + * Interface for transformations between data coordinates + * and device-independent coordinates. + * + * @author Franz-Josef Elmer + */ +public interface Transformation { + /** + * Transforms a {@link DataPoint} into a {@link GraphPoint}. + * @param point A point in data coordinates. + * @return point tranformed into device-independent coordinates.. + */ + public GraphPoint transformToGraph(DataPoint point); + + /** + * Transforms a {@link GraphPoint} into a {@link DataPoint}. + * @param point A point in device-independent coordinates.. + * @return point tranformed into data coordinates. + */ + public DataPoint transformToData(GraphPoint point); +} diff --git a/src/jcckit/util/AppletBasedConfigData.java b/src/jcckit/util/AppletBasedConfigData.java new file mode 100644 index 00000000000..e46b7208d9d --- /dev/null +++ b/src/jcckit/util/AppletBasedConfigData.java @@ -0,0 +1,53 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +import java.applet.Applet; + +/** + * Implementation of {@link FlatConfigData} based on + * java.applet.Applet. + * + * @author Franz-Josef Elmer + */ +public class AppletBasedConfigData extends FlatConfigData { + private final Applet _applet; + + /** + * Creates an instance based on the specified applet. + * The path is undefined. + */ + public AppletBasedConfigData(Applet applet) { + this(applet, null); + } + + /** Creates an instance based on the specified properties and path. */ + private AppletBasedConfigData(Applet applet, String path) { + super(path); + _applet = applet; + } + + protected String getValue(String fullKey) { + return _applet.getParameter(fullKey); + } + + protected ConfigData createConfigData(String path) { + return new AppletBasedConfigData(_applet, path); + } +} diff --git a/src/jcckit/util/ConfigData.java b/src/jcckit/util/ConfigData.java new file mode 100644 index 00000000000..7a48bb39590 --- /dev/null +++ b/src/jcckit/util/ConfigData.java @@ -0,0 +1,55 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +/** + * Interface for hierarchically managed key-value pairs. The key is + * always a string which contains any kind of printable character except + * '/', '=', ':', and whitespace characters like ' ' and '\t'. + * The value is either a string or a ConfigData object. + *

+ * This interface will be used by {@link ConfigParameters} in accordance + * with the Strategy design pattern. + * + * @author Franz-Josef Elmer + */ +public interface ConfigData { + /** + * Returns the full key. + * @param key A (relative) key. null is not allowed. + * @return the full key including path. + */ + public String getFullKey(String key); + + /** + * Returns the value associated with this key. + * @param key The relative key. null is not allowed. + * @return the associated value. Will be null if no value exists + * for key. + */ + public String get(String key); + + /** + * Returns the ConfigData object associated with this key. + * @param key The relative key. null is not allowed. + * @return the associated value. Will never return null. + * Instead an empty ConfigData is returned. + */ + public ConfigData getNode(String key); +} diff --git a/src/jcckit/util/ConfigParameters.java b/src/jcckit/util/ConfigParameters.java new file mode 100644 index 00000000000..7d28374b362 --- /dev/null +++ b/src/jcckit/util/ConfigParameters.java @@ -0,0 +1,320 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +import java.awt.Color; +import java.util.StringTokenizer; + +import net.sourceforge.plantuml.ugraphic.color.ColorMapperIdentity; +import net.sourceforge.plantuml.ugraphic.color.HColorSet; + + +/** + * Read-only class for hierarchically organized key-value pairs. + * The key is always a string. The following value types are + * supported: + *

+ *

+ * In accordance with the Strategy design pattern the retrieval of + * a key-value pair is delegated to an instance of + * {@link ConfigData}. + * + * @author Franz-Josef Elmer + */ +public class ConfigParameters { + private final ConfigData _configData; + + /** Creates an instance from the specified ConfigData object. */ + public ConfigParameters(ConfigData configData) { + _configData = configData; + } + + /** + * Returns the full key. + * @return the path concatenated with key. + * @see ConfigData#getFullKey + */ + public String getFullKey(String key) { + return _configData.getFullKey(key); + } + + /** + * Returns the string value associated with the specified key. + * @param key The (relative) key. null is not allowed. + * @return the corresponding value. Will always be not null. + * @throws IllegalArgumentException if no value exists for key. + * The exception message is the full key. + */ + public String get(String key) { + String result = _configData.get(key); + if (result == null) { + throw new IllegalArgumentException(getFullKey(key)); + } + return result; + } + + /** + * Returns the string value associated with the specified key or + * defaultValue if undefined. + * @param key The (relative) key. null is not allowed. + * @param defaultValue The default value. Can be null. + * @return the corresponding value or defaultValue. + */ + public String get(String key, String defaultValue) { + String result = _configData.get(key); + if (result == null) { + result = defaultValue; + } + return result; + } + + /** + * Returns the boolean associated with the specified key. + * @param key The (relative) key. null is not allowed. + * @return true if the value is "true" otherwise false. + * @throws IllegalArgumentException if no value exists for key. + * The exception message is the full key. + * @throws NumberFormatException if the value is neither "true" nor "false". + */ + public boolean getBoolean(String key) { + return parseBoolean(get(key), key); + } + + /** + * Returns the boolean associated with the specified key. + * @param key The (relative) key. null is not allowed. + * @param defaultValue The default value. Can be null. + * @return true if the value is "true" otherwise false. + * @throws NumberFormatException if the value is neither "true" nor "false". + */ + public boolean getBoolean(String key, boolean defaultValue) { + String value = _configData.get(key); + return value == null ? defaultValue : parseBoolean(value, key); + } + + private boolean parseBoolean(String value, String key) { + if (value.equals("true")) { + return true; + } else if (value.equals("false")) { + return false; + } else { + throw createNumberFormatException("boolean", value, key); + } + } + + private NumberFormatException createNumberFormatException(String text, + String value, + String key) { + return new NumberFormatException("Not a " + text + ": " + getFullKey(key) + + " = " + value); + } + + /** + * Returns the integer associated with the specified key. + * The value can be either + *

+ * @param key The (relative) key. null is not allowed. + * @return the integer value. + * @throws IllegalArgumentException if no value exists for key. + * The exception message is the full key. + * @throws NumberFormatException if the value is not a number. + * The exception message contains the full key and the invalid value. + */ + public int getInt(String key) { + return parseInt(get(key), key); + } + + /** + * Returns the integer associated with the specified key or + * defaultValue if no key-value pair exists for the specified key. + * The value can be either + * + * @param key The (relative) key. null is not allowed. + * @param defaultValue The default value. Can be null. + * @return the integer value. + * @throws NumberFormatException if the value exists but is not a number. + * The exception message contains the full key and the invalid value. + */ + public int getInt(String key, int defaultValue) { + String value = _configData.get(key); + return value == null ? defaultValue : parseInt(value, key); + } + + private int parseInt(String value, String key) { + try { + return Integer.decode(value).intValue(); + } catch (NumberFormatException e) { + throw createNumberFormatException("number", value, key); + } + } + + /** + * Returns the double associated with the specified key. + * @param key The (relative) key. null is not allowed. + * @return the double value. + * @throws IllegalArgumentException if no value exists for key. + * The exception message is the full key. + * @throws NumberFormatException if the value is not a valid number. + * The exception message contains the full key and the invalid value. + */ + public double getDouble(String key) { + return parseDouble(get(key), key); + } + + /** + * Returns the double associated with the specified key or + * defaultValue if no key-value pair exists for the specified key. + * @param key The (relative) key. null is not allowed. + * @param defaultValue The default value. Can be null. + * @return the double value. + * @throws NumberFormatException if the value exists but is not a valid + * number. + * The exception message contains the full key and the invalid value. + */ + public double getDouble(String key, double defaultValue) { + String value = _configData.get(key); + return value == null ? defaultValue : parseDouble(value, key); + } + + private double parseDouble(String value, String key) { + try { + return new Double(value).doubleValue(); + } catch (NumberFormatException e) { + throw createNumberFormatException("number", value, key); + } + } + + /** + * Returns the array of doubles associated with the specified key. + * The numbers are separated by whitespaces. + * @param key The (relative) key. null is not allowed. + * @return the array of double values. + * @throws IllegalArgumentException if no value exists for key. + * The exception message is the full key. + * @throws NumberFormatException if the value exists but is not a + * sequence of number. The exception message contains + * the full key and the invalid value. + */ + public double[] getDoubleArray(String key) { + return parseDoubleArray(get(key), key); + } + + /** + * Returns the array of doubles associated with the specified key + * or defaultValue if no key-value pair exists for + * the specified key. The numbers are separated by whitespaces. + * @param key The (relative) key. null is not allowed. + * @param defaultValue The default value. Can be null. + * @return the array of double values. + * @throws NumberFormatException if the value exists but is not a + * sequence of number. The exception message contains + * the full key and the invalid value. + */ + public double[] getDoubleArray(String key, double[] defaultValue) { + String value = _configData.get(key); + return value == null ? defaultValue : parseDoubleArray(value, key); + } + + private double[] parseDoubleArray(String value, String key) { + try { + StringTokenizer tokenizer = new StringTokenizer(value); + double[] result = new double[tokenizer.countTokens()]; + for (int i = 0; i < result.length; i++) { + result[i] = new Double(tokenizer.nextToken()).doubleValue(); + } + return result; + } catch (NumberFormatException e) { + throw createNumberFormatException("sequence of numbers", value, key); + } + } + + /** + * Returns the color associated with the specified key. + * The color is coded as + * + * @param key The (relative) key. null is not allowed. + * @return the color. + * @throws NumberFormatException if the value exists but is not a number. + * The exception message contains the full key and the invalid value. + */ + public Color getColor(String key) { + return parseColor(get(key), key); + } + + /** + * Returns the color associated with the specified key or the specified + * default value if no key-value pair exists for the specified key. + * The color is coded as + * + * @param key The (relative) key. null is not allowed. + * @param defaultValue The default value. Can be null. + * @return the color or null if the value is an empty string. + * @throws NumberFormatException if the value exists but is not a number. + * The exception message contains the full key and the invalid value. + */ + public Color getColor(String key, Color defaultValue) { + String value = _configData.get(key); + return value == null ? defaultValue : parseColor(value, key); + } + + private Color parseColor(String value, String key) { + try { + return value.length() == 0 ? null : decodeInternal(value); + } catch (NumberFormatException e) { + throw createNumberFormatException("number", value, key); + } + } + +static private HColorSet colors = HColorSet.instance(); +private Color decodeInternal(String value) { + if (colors.getColorIfValid(value)!=null) { + return new ColorMapperIdentity().getMappedColor(colors.getColorIfValid(value)); + } + return Color.decode(value); +} + + /** + * Returns the child node associated with the specified key. + * This method returns in any case a non-null result. + * @param key The (relative) key. null is not allowed. + * @return the corresponding child node which may be empty. + */ + public ConfigParameters getNode(String key) { + return new ConfigParameters(_configData.getNode(key)); + } +} diff --git a/src/jcckit/util/ConfigParametersBasedConfigData.java b/src/jcckit/util/ConfigParametersBasedConfigData.java new file mode 100644 index 00000000000..77138a7ea74 --- /dev/null +++ b/src/jcckit/util/ConfigParametersBasedConfigData.java @@ -0,0 +1,74 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +/** + * An implementation of {@link ConfigData} based on two instances of + * {@link ConfigParameters}. The second one serves as a set of + * default parameters. It will be used if the first one has not the requested + * key-value pair. + * + * @author Franz-Josef Elmer + */ +public class ConfigParametersBasedConfigData implements ConfigData { + private ConfigParameters _config; + private ConfigParameters _defaultConfig; + + /** + * Creates an instance. + * @param config A set of key-value pairs. + * @param defaultConfig The default set of key-value pairs. + */ + public ConfigParametersBasedConfigData(ConfigParameters config, + ConfigParameters defaultConfig) { + _config = config; + _defaultConfig = defaultConfig; + } + + /** + * Returns the full key. + * @param key A (relative) key. null is not allowed. + * @return the full key including path. + */ + public String getFullKey(String key) { + return _config.getFullKey(key); + } + + /** + * Returns the value associated with this key. + * @param key The relative key. null is not allowed. + * @return the associated value. Will be null if no value exists + * for key. + */ + public String get(String key) { + String value = _config.get(key, null); + return value == null ? _defaultConfig.get(key, null) : value; + } + + /** + * Returns the ConfigData object associated with this key. + * @param key The relative key. null is not allowed. + * @return the associated value. Will never return null. + * Instead an empty ConfigData is returned. + */ + public ConfigData getNode(String key) { + return new ConfigParametersBasedConfigData(_config.getNode(key), + _defaultConfig.getNode(key)); + } +} diff --git a/src/jcckit/util/Factory.java b/src/jcckit/util/Factory.java new file mode 100644 index 00000000000..240f8befe1d --- /dev/null +++ b/src/jcckit/util/Factory.java @@ -0,0 +1,120 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +import java.lang.reflect.Constructor; + +/** + * General purpose factory method based on {@link ConfigParameters} + * and Java's Reflection API. + * + * @author Franz-Josef Elmer + */ +public class Factory { + /** The constant defining the key className. */ + public static final String CLASS_NAME_KEY = "className"; + + /** No public constructor necessary. */ + private Factory() {} + + /** + * Creates an instance of the specified class. + * @param className Fully-qualified name of a class with a default + * constructor. + * @return a new instance. + * @throws IllegalArgumentException if the instance could be created. + */ + public static Object create(String className) { + try { + return Class.forName(className).newInstance(); + } catch (Throwable t) { + throw new IllegalArgumentException("Could not create an instance of " + + className + " because of " + t); + } + } + + /** + * Creates an object based on the specified configuration + * parameters. The class of the object is determined by the + * parameter with the key {@link #CLASS_NAME_KEY}. + * The constructor with a single argument of the type + * ConfigParameter is invoked with the argument + * configParameters. If such a constructor + * does not exists the default constructor is invoked. If + * neither of these constructors exist a {@link FactoryException} + * is thrown. + * @param configParameters Configuration parameters. + * @return the newly created object. + * @throws IllegalArgumentException if key className is missing. + * @throws FactoryException wrapping any kind of exception or error occured. + */ + public static Object create(ConfigParameters configParameters) { + String className = configParameters.get(CLASS_NAME_KEY); + return createObject(configParameters, className); + } + + /** + * Creates an object based on the specified configuration + * parameters and default class name. If the + * parameter with the key {@link #CLASS_NAME_KEY} is missed in + * configParameters defaultClassName is used. + * Otherwise it works as {@link #create(jcckit.util.ConfigParameters)}. + * @param configParameters Configuration parameters. + * @param defaultClassName Default class name. + * @return the newly created object. + * @throws FactoryException wrapping any kind of exception or error occured. + */ + public static Object create(ConfigParameters configParameters, + String defaultClassName) { + String className = configParameters.get(CLASS_NAME_KEY, defaultClassName); + return createObject(configParameters, className); + } + + /** + * Creates an object based on the specified configuration + * parameters or returns the default object. This method behaves + * as {@link #create(jcckit.util.ConfigParameters)}, except that is does + * not throw an IllegalArgumentException if key className + * is missing. Instead defaultObject is returned. + */ + public static Object createOrGet(ConfigParameters configParameters, + Object defaultObject) { + String className = configParameters.get(CLASS_NAME_KEY, null); + return className == null ? defaultObject + : createObject(configParameters, className); + } + + private static Object createObject(ConfigParameters configParameters, + String className) { + try { + Class c = Class.forName(className); + Object result = null; + Constructor constructor = null; + try { + constructor = c.getConstructor(new Class[] {ConfigParameters.class}); + result = constructor.newInstance(new Object[] {configParameters}); + } catch (NoSuchMethodException e) { + result = c.newInstance(); + } + return result; + } catch (Throwable t) { + throw new FactoryException(configParameters, CLASS_NAME_KEY, t); + } + } +} diff --git a/src/jcckit/util/FactoryException.java b/src/jcckit/util/FactoryException.java new file mode 100644 index 00000000000..28d0f39e900 --- /dev/null +++ b/src/jcckit/util/FactoryException.java @@ -0,0 +1,79 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +import java.lang.reflect.InvocationTargetException; + +/** + * Exception thrown in the case of an error during creation of a new + * object by {@link Factory#create}. + * + * @author Franz-Josef Elmer + */ +public class FactoryException extends RuntimeException { + private final String _fullKey; + private final String _className; + private final Object _reason; + + /** + * Creates a new instance based on the specified configuration parameters + * and reason object. + *

+ * If reason is an instance of InvocationTargetException + * it will be replaced by the wrapped Throwable. + * @param configParameters Configuration parameters from which the + * className will be extracted (if it exists, otherwise + * null will be taken). + * @param reason The reason causing this exception. Most often an + * an exception. + */ + public FactoryException(ConfigParameters configParameters, String key, + Object reason) { + _fullKey = configParameters.getFullKey(key); + _className = configParameters.get(key, null); + if (reason instanceof InvocationTargetException) { + reason = ((InvocationTargetException) reason).getTargetException(); + } + _reason = reason; + } + + /** Returns the full class name key. */ + public String getFullKey() { + return _fullKey; + } + + /** Returns the fully qualified class name. */ + public String getClassName() { + return _className; + } + + /** Returns the reason object causing this exception. */ + public Object getReason() { + return _reason; + } + + /** + * Renders this instance as follows: jcckit.util.FactoryException: + * full key = class name: reason. + */ + public String toString() { + return getClass().getName() + ": " + _fullKey + " = " + _className + + ": " + _reason; + } +} diff --git a/src/jcckit/util/FlatConfigData.java b/src/jcckit/util/FlatConfigData.java new file mode 100644 index 00000000000..1384e5ca1e4 --- /dev/null +++ b/src/jcckit/util/FlatConfigData.java @@ -0,0 +1,187 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +/** + * An implementation of ConfigData based on a flat + * representation of the hierachically organized key-value pairs. + * Concrete subclasses must implement the methods + * {@link #getValue} and {@link #createConfigData} in accordance + * with the Template Method pattern and Factory Method pattern, + * respectively. + *

+ * In a flat representation of hierachically organized key-value + * pairs all key-value pairs are stored in a single Hashtable. + * Its key is the full key of the configuration data (i.e. the key + * including its path). + *

+ * Example (using the notation for a .properties file): + *

+ *  title = example
+ *  symbolAttributes/className = jcckit.graphic.BasicDrawingAttributes
+ *  symbolAttributes/fillColor = 0xcaffee
+ *  symbolAttributes/lineColor = 0xff0000
+ *  
+ * The following table shows the result of some method calls at a + * FlatConfigData instance prepared with + * this example: + *

+ *

+ * + * + * + * + *
Method callResult
get("title")example
getNode("symbolAttributes").get("fillColor") + * 0xcaffee
+ *
+ *

+ * In addition FlatConfigData implements inheritance + * of key-value pairs. + * Basically a node in the tree of key-value pairs + * may extend another node in the tree. + * The extended node inherit all key-value pairs from the extending + * one including the key-value pairs of all descendants. + * The value of a inherited key-value pair may be overridden. + * Also new key-value pairs may be placed in the inherited node or + * anywhere in the subtree. + * Note, that the extending node has to be a node which is not a + * descendant of the extended node (otherwise a circulary chain + * of references occurs). As a consequence not more than 20 inheritance + * levels are allowed. + *

+ * The implementation of this kind of inheritance in a flat hashtable + * is done by an additional key-value pair of the form + *

+ *    extending-node/ = extended-node/
+ *  
+ * Example: + *
+ *  A/a/priority = high
+ *  A/a/alpha/hello = universe
+ *  A/a/alpha/answer = 42
+ *  A/b/1/ = A/a/
+ *  A/b/1/alpha/hello = world
+ *  A/b/1/alpha/question = 6 * 7
+ *  
+ * The following table shows the result of various method calls + * applied at the node A/b/1/ of a FlatConfigData + * instance prepared with this example: + *

+ *

+ * + * + * + * + * + * + *
Method callResultComment
get("priority")highinherited
getNode("alpha").get("hello") + * worldoverridden
getNode("alpha").get("question") + * 6 * 7added
getNode("alpha").get("answer") + * 42inherited
+ *
+ * + * @author Franz-Josef Elmer + */ +public abstract class FlatConfigData implements ConfigData { + private final String _path; + + /** Creates a new instance for the specified path. */ + public FlatConfigData(String path) { + _path = path; + } + + /** + * Returns the full key. + * @param key A (relative) key. null is not allowed. + * @return the path concatenated with key or key + * if the path is undefined. + */ + public String getFullKey(String key) { + return _path == null ? key : _path + key; + } + + /** + * Returns the value associated with this key. + * @param key The relative key. null is not allowed. + * @return the associated value. Will be null if no value exists + * for key. + */ + public String get(String key) { + return get(_path, key, 0); + } + + /** + * Obtains a value in accordance with hierarchy (path) and + * inheritance (recursive calls of this routine). + */ + private String get(String path, String key, int numberOfLevels) { + String result = null; + if (numberOfLevels < 20) { + String fullKey = path == null ? key : path + key; + result = getValue(fullKey); + if (result == null) { + // posAfterDelim is the index in path just after '/' + int posAfterDelim = path == null ? -1 : path.length(); + String replacement; + while (posAfterDelim > 0) { + // look for a sub-tree + replacement = getValue(path.substring(0, posAfterDelim)); + if (replacement != null) { + // sub-tree found, add last part of the original path + result = get(replacement + path.substring(posAfterDelim), key, + numberOfLevels + 1); + // break whether result is null or not. + break; + } + // remove last element from the path + posAfterDelim = path.lastIndexOf('/', posAfterDelim - 2) + 1; + } + } + } + return result; + } + + /** + * Returns the ConfigData object associated with this key. + * @param key The relative key. + * @return the associated value. Will never return null. + * Instead an empty ConfigData is returned. + */ + public ConfigData getNode(String key) { + String path = (_path == null ? key : _path + key) + '/'; + return createConfigData(path); + } + + /** + * Returns the value for the specified full key from the flat + * representation of the hierarchically organized key-value pairs. + * @param fullKey The full key including path. null is not allowed. + * @return the value or null if not found. + */ + protected abstract String getValue(String fullKey); + + /** + * Returns the FlatConfigData object for the specified full path. + * In general path will be used in the constructor with + * path argument. + * @param path The full path. + * @return a new instance in any case. + */ + protected abstract ConfigData createConfigData(String path); +} diff --git a/src/jcckit/util/Format.java b/src/jcckit/util/Format.java new file mode 100644 index 00000000000..c4e04e2b4af --- /dev/null +++ b/src/jcckit/util/Format.java @@ -0,0 +1,208 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +import java.util.Vector; + +/** + * A helper class for formatting numbers according to + * a printf-like format string. Each instance of + * this class is initialized by a format string for a + * single number. + * + * @author Franz-Josef Elmer + */ +public class Format implements TicLabelFormat { + /** + * Creates a new instance based of specified key-value pair of the + * specified configuration parameters. + * @param config Config parameters. + * @param key The key of the key-value pair in config containing + * the format string. + * @return null if undefined key-value pair or format string + * is an empty string. + * @throws FactoryException if the format string is invalid. + */ + public static Format create(ConfigParameters config, String key) { + Format result = null; + String format = config.get(key, null); + if (format != null && format.length() > 0) { + try { + result = new Format(format); + } catch (Exception e) { + throw new FactoryException(config, key, e); + } + } + return result; + } + + private final FormatElement[] _formatElements; + private final Vector _staticParts; + + /** + * Creates an instance for the specified format string. + * The format string is an alternation of some static texts and + * format elements. + * A format element has to start with '%' and it must end with + * one of the following format descriptors: + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ddecimal integer
ooctal integer
xhex integer
ffloating point number with a fixed decimal point
e, Efloating point number in logarithmic format
g, Gfloating point number rendered either in fixed-decimal + * format of logarithmic format depending on the size of + * the mantissa.
+ * The characters between '%' and the decriptor are optional. + * They can be grouped into + * + * A plain '%' is coded as '%%'. + * @param formatString The format string. + * @exception IllegalArgumentException if invalid format string. + */ + public Format(String formatString) { + _staticParts = new Vector(); + Vector formatElements = new Vector(); + StringBuffer part = new StringBuffer(); + boolean insideFormatElement = false; + boolean atPercentSymbol = false; + for (int i = 0, n = formatString.length(); i < n; i++) { + char c = formatString.charAt(i); + if (insideFormatElement) { + part.append(c); + if (FormatElement.DESCRIPTORS.indexOf(c) >= 0) { + formatElements.addElement(new String(part)); + part.setLength(0); + insideFormatElement = false; + } + } else if (atPercentSymbol) { + atPercentSymbol = false; + if (c != '%') { + _staticParts.addElement(new String(part)); + part.setLength(0); + insideFormatElement = true; + } + part.append(c); + if (FormatElement.DESCRIPTORS.indexOf(c) >= 0) { + formatElements.addElement(new String(part)); + part.setLength(0); + insideFormatElement = false; + } + } else { + if (c == '%') { + atPercentSymbol = true; + } else { + part.append(c); + } + } + } + if (insideFormatElement) { + formatElements.addElement(new String(part)); + } else { + _staticParts.addElement(new String(part)); + } + + _formatElements = new FormatElement[formatElements.size()]; + for (int i = 0; i < _formatElements.length; i++) { + _formatElements[i] + = new FormatElement((String) formatElements.elementAt(i)); + } + } + + /** + * Format a number. + * If there are no format elements the numbers will be ignored. + * If there are more than one format elements the + * additional format elements will be ignored and only the static parts + * are taken. + * @param number Number to be formated. + * @return Formated number. + */ + public String form(long number) { + StringBuffer result = new StringBuffer(); + result.append(_staticParts.elementAt(0)); + if (_formatElements.length > 0) { + _formatElements[0].form(result, number); + } + return appendRest(result); + } + + /** + * Format a number. + * If there are no format elements the numbers will be ignored. + * If there are more than one format elements the + * additional format elements will be ignored and only the static parts + * are taken. + * @param number Number to be formated. + * @return Formated number. + */ + public String form(double number) { + StringBuffer result = new StringBuffer(); + result.append(_staticParts.elementAt(0)); + if (_formatElements.length > 0) { + _formatElements[0].form(result, number); + } + return appendRest(result); + } + + private String appendRest(StringBuffer buffer) { + for (int i = 1, n = _staticParts.size(); i < n; i++) { + buffer.append(_staticParts.elementAt(i)); + } + return new String(buffer); + } + + /** + * Format an array of double numbers. + * If there are less format elements than numbers the additional numbers + * will be ignored. If there are less numbers than format elements the + * additional format elements will be ignored and only the static parts + * are taken. + * @param numbers Numbers to be formated. + * @return Formated numbers. + */ + public String form(double[] numbers) { + StringBuffer result = new StringBuffer(); + for (int i = 0, n = _staticParts.size(); i < n; i++) { + result.append(_staticParts.elementAt(i)); + if (i < _formatElements.length && i < numbers.length) { + _formatElements[i].form(result, numbers[i]); + } + } + return new String(result); + } +} diff --git a/src/jcckit/util/FormatElement.java b/src/jcckit/util/FormatElement.java new file mode 100644 index 00000000000..84f629a9959 --- /dev/null +++ b/src/jcckit/util/FormatElement.java @@ -0,0 +1,242 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +/** + * + * + * @author Franz-Josef Elmer + */ +class FormatElement { + /** All descriptor characters. */ + static final String DESCRIPTORS = "doxfeEgG"; + private static final String INT_DESCRIPTORS = "dox"; + private static final int INT_DESCRIPTOR = 0; + private static final int FLOAT_DESCRIPTOR = 1; + /** + * Calculate the integer power of a floating point number. + * @param n Exponent. + * @param x Number. + * @return x^n. + */ + private static final double power(double x, int n) { + return n < 0 ? 1.0 / power2(x, -n) : power2(x, n); + } + + /** Calculate x^n recursively assuming n > 0. */ + private static final double power2(double x, int n) { + switch (n) { + case 0: return 1; + case 1: return x; + default: + double p = power2(x, n / 2); + return p * p * power2(x, n % 2); + } + } + + private final char _descriptor; + private final int _descriptorType; + private final double _tenToPrecision; + private boolean _decimalPoint; + private boolean _flushLeft; + private boolean _leadingZeros; + private boolean _alwaysSign; + private int _width; + private int _precision; + + /** Creates an instance for the specified format string. */ + FormatElement(String formatString) { + int len = formatString.length() - 1; + _descriptor = formatString.charAt(len); + if (DESCRIPTORS.indexOf(_descriptor) < 0) { + throw new IllegalArgumentException("Format element '" + formatString + + "' does not ends with one of the following characters: " + + DESCRIPTORS); + } + _descriptorType = INT_DESCRIPTORS.indexOf(_descriptor) >= 0 + ? INT_DESCRIPTOR : FLOAT_DESCRIPTOR; + if (formatString.length() > 1) { + switch (formatString.charAt(0)) { + case '-': + _flushLeft = true; + formatString = formatString.substring(1); + break; + case '0': + _leadingZeros = true; + formatString = formatString.substring(1); + break; + case '+': + _alwaysSign = true; + formatString = formatString.substring(1); + break; + } + len = formatString.length() - 1; + int index = formatString.indexOf('.'); + _decimalPoint = index >= 0; + int last = _decimalPoint ? index : len; + if (last > 0) { + _width = Integer.parseInt(formatString.substring(0, last)); + } + if (_decimalPoint) { + index++; + if (index < len) { + _precision = Integer.parseInt(formatString.substring(index, len)); + } + } + } + _tenToPrecision = power(10, _precision); + } + + /** + * Format a number in accordance of the format string + * given at the initialisation of this instance. + * @param buffer Buffer to which the formated output will be appended. + * @param number Number to be formated. + */ + public void form(StringBuffer buffer, long number) { + if (_descriptorType == FLOAT_DESCRIPTOR) { + form(buffer, (double) number); + } else { + // Format absolut value in the right base + buffer.append(form(number < 0, + Long.toString(Math.abs(number), + _descriptor == 'o' ? 8 + : (_descriptor == 'x' ? 16 : 10)), + "")); + } + } + + /** + * Format a number in accordance of the format string + * given at the initialisation of this instance. + * @param buffer Buffer to which the formated output will be appended. + * @param number Number to be formated. + */ + public void form(StringBuffer buffer, double number) { + if (_descriptorType == INT_DESCRIPTOR) { + form(buffer, (long) Math.floor(number + 0.5)); + } else if (_descriptor == 'f') { + buffer.append(formF(number)); + } else if (_descriptor == 'e' || _descriptor == 'E') { + buffer.append(formE(number)); + } else if (_descriptor == 'g' || _descriptor == 'G') { + String formF = formF(number); + String formE = formE(number); + buffer.append(formF.length() > formE.length() ? formE : formF); + } + } + + private String form(boolean negativeValue, String intPart, String fracPart) { + int len = intPart.length() + fracPart.length(); + + // Buffer holding the result + StringBuffer result = new StringBuffer(); + int count = 0; + + // add sign if necessary + if (_alwaysSign || negativeValue) { + result.append(negativeValue ? '-' : '+'); + count++; + } + + // add zeros if necessary + if (_leadingZeros) { + for (int i = count + len; i < _width; i++) { + result.append('0'); + count++; + } + } + + // add number + result.append(intPart).append(fracPart); + count += len; + + // add spaces if necessary + if (_flushLeft) { + for (; count < _width; count++) { + result.append(' '); + } + } else { + for (; count < _width; count++) { + result.insert(0, ' '); + } + } + + return new String(result); + } + + /** Format floating point number with exponent. */ + private String formE(double number) { + // format absolute mantisse + int exponent = 0; + String zeros = "00000000000000000000000".substring(0, _precision + 1); + if (number != 0) { + exponent = (int) Math.floor(Math.log(Math.abs(number)) / Math.log(10)); + double mantisse = Math.floor(Math.abs(number * power(10.0, + _precision - exponent)) + 0.5); + if (mantisse >= 10 * _tenToPrecision) { + exponent++; + mantisse = Math.floor(Math.abs(number * power(10.0, + _precision - exponent)) + 0.5); + } + zeros = Long.toString((long) mantisse); + } + + // make fractional part + StringBuffer fracPart = new StringBuffer(); + if (_decimalPoint) { + fracPart.append('.').append(zeros.substring(1)); + } + + // make exponent + fracPart.append(Character.isLowerCase(_descriptor) ? 'e': 'E') + .append(exponent < 0 ? '-' : '+'); + exponent = Math.abs(exponent); + for (int i = 0, n = fracPart.length(); i < 3; i++) { + fracPart.insert(n, Character.forDigit(exponent % 10, 10)); + exponent /= 10; + } + + return form(number < 0, zeros.substring(0, 1), new String(fracPart)); + } + + /** Format floating point number. */ + private String formF(double number) { + // Format absolut value + double multiplier = number < 0 ? - _tenToPrecision : _tenToPrecision; + String digits + = Long.toString((long) Math.floor(number * multiplier + 0.5)); + String intPart = digits; + StringBuffer fracPart = new StringBuffer(); + if (_decimalPoint) { + int len = digits.length() - _precision; + fracPart.append('.').append(digits.substring(Math.max(0, len))); + if (len > 0) { + intPart = digits.substring(0, len); + } else { + intPart = "0"; + for (; len < 0; len++) { + fracPart.insert(1, '0'); + } + } + } + + return form(number < 0, intPart, new String(fracPart)); + } +} diff --git a/src/jcckit/util/Point.java b/src/jcckit/util/Point.java new file mode 100644 index 00000000000..623c78fc157 --- /dev/null +++ b/src/jcckit/util/Point.java @@ -0,0 +1,65 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +/** + * Immutable class of a two-dimensional point with floating point + * coordinates. + * + * @author Franz-Josef Elmer + */ +public class Point { + private final double _x; + private final double _y; + + /** + * Creates an instance for the specified vector. The value of the + * first/second element of vector denotes the x/y value. + * If vector is null or not long enough 0 will be used + * as default values. + */ + public Point(double[] vector) { + double x = 0; + double y = 0; + if (vector != null && vector.length > 0) { + x = vector[0]; + if (vector.length > 1) { + y = vector[1]; + } + } + _x = x; + _y = y; + } + + /** Creates an instance for the specified coordinates. */ + public Point(double x, double y) { + _x = x; + _y = y; + } + + /** Returns the x-coordinate of the point. */ + public double getX() { + return _x; + } + + /** Returns the y-coordinate of the point. */ + public double getY() { + return _y; + } +} diff --git a/src/jcckit/util/PropertiesBasedConfigData.java b/src/jcckit/util/PropertiesBasedConfigData.java new file mode 100644 index 00000000000..1d5bcc43644 --- /dev/null +++ b/src/jcckit/util/PropertiesBasedConfigData.java @@ -0,0 +1,81 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; + +/** + * Implementation of {@link FlatConfigData} based on + * java.util.Properties. + * + * @author Franz-Josef Elmer + */ +public class PropertiesBasedConfigData extends FlatConfigData { + private final Properties _properties; + + /** + * Creates an instance from the specified .properties file. + * @param fileName File name of the .properties file relative + * to the working directory or absolute. + * @throws IOException if the .properties does not exist or could + * not be read. + */ + public PropertiesBasedConfigData(String fileName) throws IOException { + super(null); + _properties = new Properties(); + _properties.load(new FileInputStream(fileName)); + } + + /** + * Creates an instance based on the specified properties. + * The path is undefined. + */ + public PropertiesBasedConfigData(Properties properties) { + this(properties, null); + } + + /** Creates an instance based on the specified properties and path. */ + private PropertiesBasedConfigData(Properties properties, String path) { + super(path); + _properties = properties; + } + + /** + * Returns the value for the specified full key. The call will be delegated + * to the wrapped java.util.properties object. + * @param fullKey The full key including path. null is not allowed. + * @return the value or null if not found. + */ + protected String getValue(String fullKey) { + return _properties.getProperty(fullKey); + } + + /** + * Returns a new instance of PropertiesBasedConfigData + * for the specified full path. The wrapped java.util.Properties + * will be the same as of this instance. + * @param path The full path. + * @return a new instance. + */ + protected ConfigData createConfigData(String path) { + return new PropertiesBasedConfigData(_properties, path); + } +} diff --git a/src/jcckit/util/TicLabelFormat.java b/src/jcckit/util/TicLabelFormat.java new file mode 100644 index 00000000000..61d924c58e5 --- /dev/null +++ b/src/jcckit/util/TicLabelFormat.java @@ -0,0 +1,33 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +/** + * Format interface for tic labels. Maps a numerical tic value onto a string. + * + * @author Franz-Josef Elmer + */ +public interface TicLabelFormat +{ + /** + * Forms the specified tic value to a string. Note, the numerical + * ticValue may be mapped onto a non-numerical one. + */ + public String form(double ticValue); +} diff --git a/src/jcckit/util/Util.java b/src/jcckit/util/Util.java new file mode 100644 index 00000000000..5715d5a46d7 --- /dev/null +++ b/src/jcckit/util/Util.java @@ -0,0 +1,47 @@ +/* + * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details + * (http://www.gnu.org/copyleft/lesser.html). + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package jcckit.util; + +/** + * Collection of static utility methods. + * + * @author Franz-Josef Elmer + */ +public class Util { + /** Private constructor to prevent instanciation of this class. */ + private Util() {} + + /** + * Returns the natural logarithm of the specified number if + * logScale is true. + * @return x if logScale == false. + */ + public static double log(double x, boolean logScale) { + return logScale ? Math.log(x) : x; + } + + /** + * Returns the exponential function of the specified number if + * logScale is true. + * @return x if logScale == false. + */ + public static double exp(double x, boolean logScale) { + return logScale ? Math.exp(x) : x; + } +} diff --git a/src/net/sourceforge/plantuml/LineBreakStrategy.java b/src/net/sourceforge/plantuml/LineBreakStrategy.java index 23889146816..03ba93e1048 100644 --- a/src/net/sourceforge/plantuml/LineBreakStrategy.java +++ b/src/net/sourceforge/plantuml/LineBreakStrategy.java @@ -44,6 +44,11 @@ public class LineBreakStrategy { public LineBreakStrategy(String value) { this.value = value; } + + @Override + public String toString() { + return value; + } public boolean isAuto() { return "auto".equalsIgnoreCase(value); diff --git a/src/net/sourceforge/plantuml/PSystemBuilder.java b/src/net/sourceforge/plantuml/PSystemBuilder.java index 3fbbe0459b6..98daca76600 100644 --- a/src/net/sourceforge/plantuml/PSystemBuilder.java +++ b/src/net/sourceforge/plantuml/PSystemBuilder.java @@ -68,6 +68,7 @@ import net.sourceforge.plantuml.flowdiagram.FlowDiagramFactory; import net.sourceforge.plantuml.font.PSystemListFontsFactory; import net.sourceforge.plantuml.help.HelpFactory; +import net.sourceforge.plantuml.jcckit.PSystemJcckitFactory; import net.sourceforge.plantuml.math.PSystemLatexFactory; import net.sourceforge.plantuml.math.PSystemMathFactory; import net.sourceforge.plantuml.mindmap.MindMapDiagramFactory; @@ -79,8 +80,8 @@ import net.sourceforge.plantuml.salt.PSystemSaltFactory; import net.sourceforge.plantuml.sequencediagram.SequenceDiagramFactory; import net.sourceforge.plantuml.sprite.ListSpriteDiagramFactory; -import net.sourceforge.plantuml.sprite.StdlibDiagramFactory; import net.sourceforge.plantuml.sprite.PSystemListInternalSpritesFactory; +import net.sourceforge.plantuml.sprite.StdlibDiagramFactory; import net.sourceforge.plantuml.statediagram.StateDiagramFactory; import net.sourceforge.plantuml.stats.StatsUtilsIncrement; import net.sourceforge.plantuml.sudoku.PSystemSudokuFactory; @@ -109,9 +110,10 @@ final public Diagram createPSystem(ISkinSimple skinParam, final List emptyList()); - return PSystemErrorUtils.buildV2(umlSource, err, Collections. emptyList(), strings2); + s.getLocation()); + // return PSystemErrorUtils.buildV1(umlSource, err, Collections. + // emptyList()); + return PSystemErrorUtils.buildV2(umlSource, err, Collections.emptyList(), strings2); } } @@ -173,8 +175,8 @@ private static List getAllFactories(ISkinSimple skinParam) { factories.add(new PSystemDitaaFactory(DiagramType.DITAA)); factories.add(new PSystemDitaaFactory(DiagramType.UML)); if (License.getCurrent() == License.GPL || License.getCurrent() == License.GPLV2) { - // factories.add(new PSystemJcckitFactory(DiagramType.JCCKIT)); - // factories.add(new PSystemJcckitFactory(DiagramType.UML)); + factories.add(new PSystemJcckitFactory(DiagramType.JCCKIT)); + factories.add(new PSystemJcckitFactory(DiagramType.UML)); // factories.add(new PSystemLogoFactory()); factories.add(new PSystemSudokuFactory()); } diff --git a/src/net/sourceforge/plantuml/Run.java b/src/net/sourceforge/plantuml/Run.java index 4964007ec05..6bc6d496047 100644 --- a/src/net/sourceforge/plantuml/Run.java +++ b/src/net/sourceforge/plantuml/Run.java @@ -62,7 +62,6 @@ import net.sourceforge.plantuml.command.UmlDiagramFactory; import net.sourceforge.plantuml.descdiagram.DescriptionDiagramFactory; import net.sourceforge.plantuml.ftp.FtpServer; -import net.sourceforge.plantuml.objectdiagram.ObjectDiagramFactory; import net.sourceforge.plantuml.png.MetadataTag; import net.sourceforge.plantuml.preproc.Stdlib; import net.sourceforge.plantuml.sequencediagram.SequenceDiagramFactory; @@ -342,7 +341,7 @@ private static void managePattern() { printPattern(new DescriptionDiagramFactory(null)); // printPattern(new ComponentDiagramFactory()); printPattern(new StateDiagramFactory(null)); - printPattern(new ObjectDiagramFactory(null)); + // printPattern(new ObjectDiagramFactory(null)); } private static void printPattern(UmlDiagramFactory factory) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java b/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java index ca46952756e..d8924cb9e4c 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java @@ -49,6 +49,8 @@ import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.activitydiagram3.ftile.BoxStyle; +import net.sourceforge.plantuml.activitydiagram3.ftile.ISwimlanesA; +import net.sourceforge.plantuml.activitydiagram3.ftile.SwimlanesAAA; import net.sourceforge.plantuml.activitydiagram3.ftile.SwimlanesC; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.core.DiagramDescription; @@ -64,7 +66,7 @@ import net.sourceforge.plantuml.ugraphic.ImageBuilder; import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.comp.CompressionMode; -import net.sourceforge.plantuml.ugraphic.comp.TextBlockCompressedOnXorY; +import net.sourceforge.plantuml.ugraphic.comp.CompressionXorYBuilder; public class ActivityDiagram3 extends UmlDiagram { @@ -74,7 +76,36 @@ enum SwimlaneStrategy { private SwimlaneStrategy swimlaneStrategy; - private final SwimlanesC swinlanes = new SwimlanesC(getSkinParam(), getPragma()); + private final ISwimlanesA swinlanes = new SwimlanesAAA(getSkinParam(), getPragma()); + // private final ISwimlanesA swinlanes = new SwimlanesC(getSkinParam(), + // getPragma()); + + private ImageData exportDiagramInternalAAA(OutputStream os, int index, FileFormatOption fileFormatOption) + throws IOException { + // BUG42 + // COMPRESSION + swinlanes.computeSize(fileFormatOption.getDefaultStringBounder()); + TextBlock result = swinlanes; + + result = CompressionXorYBuilder.build(CompressionMode.ON_X, result, fileFormatOption.getDefaultStringBounder()); + result = CompressionXorYBuilder.build(CompressionMode.ON_Y, result, fileFormatOption.getDefaultStringBounder()); + + result = new TextBlockRecentred(result); + final ISkinParam skinParam = getSkinParam(); + result = new AnnotatedWorker(this, skinParam, fileFormatOption.getDefaultStringBounder()).addAdd(result); + + final Dimension2D dim = result.getMinMax(fileFormatOption.getDefaultStringBounder()).getDimension(); + final double margin = 10; + final double dpiFactor = getDpiFactor(fileFormatOption, Dimension2DDouble.delta(dim, 2 * margin, 0)); + + final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam(), dpiFactor, + fileFormatOption.isWithMetadata() ? getMetadata() : null, getWarningOrError(), margin, margin, + getAnimation()); + imageBuilder.setUDrawable(result); + + return imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed(), os); + + } public ActivityDiagram3(ISkinSimple skinParam) { super(skinParam); @@ -123,7 +154,8 @@ public void addActivity(Display activity, BoxStyle style, Url url, Colors colors } public void addSpot(String spot, HColor color) { - final InstructionSpot ins = new InstructionSpot(spot, color, nextLinkRenderer(), swinlanes.getCurrentSwimlane()); + final InstructionSpot ins = new InstructionSpot(spot, color, nextLinkRenderer(), + swinlanes.getCurrentSwimlane()); current().add(ins); setNextLinkRendererInternal(LinkRendering.none()); manageSwimlaneStrategy(); @@ -201,17 +233,21 @@ public UmlDiagramType getUmlDiagramType() { @Override protected ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException { + if (swinlanes instanceof SwimlanesC == false || swinlanes instanceof SwimlanesAAA) { + return exportDiagramInternalAAA(os, index, fileFormatOption); + } // BUG42 // COMPRESSION + swinlanes.computeSize(fileFormatOption.getDefaultStringBounder()); TextBlock result = swinlanes; - // result = new TextBlockCompressedOnY(CompressionMode.ON_Y, result); - result = new TextBlockCompressedOnXorY(CompressionMode.ON_X, result); - result = new TextBlockCompressedOnXorY(CompressionMode.ON_Y, result); + + result = CompressionXorYBuilder.build(CompressionMode.ON_X, result, fileFormatOption.getDefaultStringBounder()); + result = CompressionXorYBuilder.build(CompressionMode.ON_Y, result, fileFormatOption.getDefaultStringBounder()); + result = new TextBlockRecentred(result); final ISkinParam skinParam = getSkinParam(); result = new AnnotatedWorker(this, skinParam, fileFormatOption.getDefaultStringBounder()).addAdd(result); - // final Dimension2D dim = TextBlockUtils.getMinMax(result, fileFormatOption.getDefaultStringBounder()) - // .getDimension(); + final Dimension2D dim = result.getMinMax(fileFormatOption.getDefaultStringBounder()).getDimension(); final double margin = 10; final double dpiFactor = getDpiFactor(fileFormatOption, Dimension2DDouble.delta(dim, 2 * margin, 0)); @@ -329,8 +365,8 @@ public CommandExecutionResult endSwitch() { public void startIf(Display test, Display whenThen, HColor color, Url url) { manageSwimlaneStrategy(); - final InstructionIf instructionIf = new InstructionIf(swinlanes.getCurrentSwimlane(), current(), test, - whenThen, nextLinkRenderer(), color, getSkinParam(), url); + final InstructionIf instructionIf = new InstructionIf(swinlanes.getCurrentSwimlane(), current(), test, whenThen, + nextLinkRenderer(), color, getSkinParam(), url); current().add(instructionIf); setNextLinkRendererInternal(LinkRendering.none()); setCurrent(instructionIf); @@ -396,12 +432,13 @@ public CommandExecutionResult repeatWhile(Display label, Display yes, Display ou } - public CommandExecutionResult backwardWhile(Display label) { + public CommandExecutionResult backwardWhile(Display label, BoxStyle boxStyle) { manageSwimlaneStrategy(); if (current() instanceof InstructionRepeat) { final InstructionRepeat instructionRepeat = (InstructionRepeat) current(); - // final LinkRendering back = new LinkRendering(linkColor).withDisplay(linkLabel); - instructionRepeat.setBackward(label, swinlanes.getCurrentSwimlane()); + // final LinkRendering back = new + // LinkRendering(linkColor).withDisplay(linkLabel); + instructionRepeat.setBackward(label, swinlanes.getCurrentSwimlane(), boxStyle); // setCurrent(instructionRepeat.getParent()); // this.setNextLinkRendererInternal(LinkRendering.none()); return CommandExecutionResult.ok(); @@ -435,8 +472,8 @@ final public CommandExecutionResult kill() { return CommandExecutionResult.ok(); } - public void startGroup(Display name, HColor backColor, HColor titleColor, HColor borderColor, - USymbol type, double roundCorner) { + public void startGroup(Display name, HColor backColor, HColor titleColor, HColor borderColor, USymbol type, + double roundCorner) { manageSwimlaneStrategy(); final InstructionGroup instructionGroup = new InstructionGroup(current(), name, backColor, titleColor, swinlanes.getCurrentSwimlane(), borderColor, nextLinkRenderer(), type, roundCorner); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/InstructionRepeat.java b/src/net/sourceforge/plantuml/activitydiagram3/InstructionRepeat.java index 5ff0153ae9c..63516a3ba88 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/InstructionRepeat.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/InstructionRepeat.java @@ -55,6 +55,7 @@ public class InstructionRepeat implements Instruction { private final LinkRendering nextLinkRenderer; private final Swimlane swimlane; private Swimlane swimlaneOut; + private BoxStyle boxStyle; // private final HtmlColor color; private boolean killed = false; private final BoxStyle boxStyleIn; @@ -93,9 +94,10 @@ private boolean isLastOfTheParent() { return false; } - public void setBackward(Display label, Swimlane swimlaneOut) { + public void setBackward(Display label, Swimlane swimlaneOut, BoxStyle boxStyle) { this.backward = label; this.swimlaneOut = swimlaneOut; + this.boxStyle = boxStyle; } public void add(Instruction ins) { @@ -104,7 +106,7 @@ public void add(Instruction ins) { public Ftile createFtile(FtileFactory factory) { final Ftile back = Display.isNull(backward) ? null - : factory.activity(backward, swimlane, BoxStyle.PLAIN, Colors.empty()); + : factory.activity(backward, swimlane, boxStyle, Colors.empty()); final Ftile decorateOut = factory.decorateOut(repeatList.createFtile(factory), endRepeatLinkRendering); final Ftile result = factory.repeat(boxStyleIn, swimlane, swimlaneOut, startLabel, decorateOut, test, yes, out, colors, backRepeatLinkRendering, back, isLastOfTheParent()); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandBackward3.java b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandBackward3.java index 42bb413265e..566c9bca98b 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandBackward3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandBackward3.java @@ -37,6 +37,7 @@ import net.sourceforge.plantuml.LineLocation; import net.sourceforge.plantuml.activitydiagram3.ActivityDiagram3; +import net.sourceforge.plantuml.activitydiagram3.ftile.BoxStyle; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.SingleLineCommand2; import net.sourceforge.plantuml.command.regex.IRegex; @@ -57,14 +58,22 @@ static IRegex getRegexConcat() { RegexLeaf.spaceZeroOrMore(), // new RegexLeaf(":"), // new RegexLeaf("LABEL", "(.*)"), // - new RegexLeaf(";"), // + new RegexLeaf("STYLE", CommandActivity3.ENDING_GROUP), // RegexLeaf.end()); } @Override protected CommandExecutionResult executeArg(ActivityDiagram3 diagram, LineLocation location, RegexResult arg) { + final BoxStyle boxStyle; + final String styleString = arg.get("STYLE", 0); + if (styleString == null) { + boxStyle = BoxStyle.PLAIN; + } else { + boxStyle = BoxStyle.fromChar(styleString.charAt(0)); + } + final Display label = Display.getWithNewlines(arg.get("LABEL", 0)); - return diagram.backwardWhile(label); + return diagram.backwardWhile(label, boxStyle); } } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/CenteredText.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/CenteredText.java new file mode 100644 index 00000000000..863a4253ace --- /dev/null +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/CenteredText.java @@ -0,0 +1,59 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.activitydiagram3.ftile; + +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.ugraphic.UShape; + +public class CenteredText implements UShape { + + private final TextBlock text; + private final double totalWidth; + + public CenteredText(TextBlock text, double totalWidth) { + this.text = text; + this.totalWidth = totalWidth; + } + + public TextBlock getText() { + return text; + } + + public double getTotalWidth() { + return totalWidth; + } + +} diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactoryDelegator.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactoryDelegator.java index 927b5e9ca12..2f20a3ae6eb 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactoryDelegator.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactoryDelegator.java @@ -118,7 +118,7 @@ protected final TextBlock getTextBlock(Display display) { } else { fontConfiguration = new FontConfiguration(skinParam(), FontParam.ARROW, null); } - return display.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam(), CreoleMode.SIMPLE_LINE); + return display.create7(fontConfiguration, HorizontalAlignment.LEFT, skinParam(), CreoleMode.SIMPLE_LINE); } protected Display getInLinkRenderingDisplay(Ftile tile) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/ISwimlanesA.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/ISwimlanesA.java new file mode 100644 index 00000000000..eb58f1e8247 --- /dev/null +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/ISwimlanesA.java @@ -0,0 +1,62 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.activitydiagram3.ftile; + +import net.sourceforge.plantuml.activitydiagram3.Instruction; +import net.sourceforge.plantuml.activitydiagram3.LinkRendering; +import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.style.Styleable; +import net.sourceforge.plantuml.ugraphic.color.HColor; + +public interface ISwimlanesA extends TextBlock, Styleable { + + public void computeSize(StringBounder stringBounder); + + public void swimlane(String name, HColor color, Display label); + + public void setCurrent(Instruction ins); + + public Instruction getCurrent(); + + public LinkRendering nextLinkRenderer(); + + public Swimlane getCurrentSwimlane(); + + public void setNextLinkRenderer(LinkRendering link); + +} diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/LaneDivider.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/LaneDivider.java new file mode 100644 index 00000000000..d8621011e2b --- /dev/null +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/LaneDivider.java @@ -0,0 +1,123 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.activitydiagram3.ftile; + +import java.awt.geom.Dimension2D; + +import net.sourceforge.plantuml.ColorParam; +import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.LineParam; +import net.sourceforge.plantuml.SkinParam; +import net.sourceforge.plantuml.graphic.AbstractTextBlock; +import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.skin.rose.Rose; +import net.sourceforge.plantuml.style.PName; +import net.sourceforge.plantuml.style.SName; +import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.StyleSignature; +import net.sourceforge.plantuml.ugraphic.UChangeColor; +import net.sourceforge.plantuml.ugraphic.UEmpty; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.ULine; +import net.sourceforge.plantuml.ugraphic.UShape; +import net.sourceforge.plantuml.ugraphic.UStroke; +import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.color.HColor; + +public class LaneDivider extends AbstractTextBlock { + + private final ISkinParam skinParam;; + + private final double x1; + private final double x2; + private final double height; + private Style style; + + public LaneDivider(ISkinParam skinParam, double x1, double x2, double height) { + this.skinParam = skinParam; + this.x1 = x1; + this.x2 = x2; + this.height = height; + } + + public StyleSignature getDefaultStyleDefinition() { + return StyleSignature.of(SName.root, SName.element, SName.classDiagram, SName.swimlane); + } + + private Style getStyle() { + if (style == null) { + this.style = getDefaultStyleDefinition().getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + return style; + } + + public Dimension2D calculateDimension(StringBounder stringBounder) { + return new Dimension2DDouble(x1 + x2, height); + } + + public void drawU(UGraphic ug) { +// final UShape back = new URectangle(x1 + x2, height).ignoreForCompressionOnY(); +// ug.apply(new UChangeColor(HColorUtils.BLUE)).draw(back); + final UShape back = new UEmpty(x1 + x2, 1); + ug.draw(back); + + HColor color = skinParam.getHtmlColor(ColorParam.swimlaneBorder, null, false); + if (color == null) { + color = ColorParam.swimlaneBorder.getDefaultValue(); + } + UStroke thickness = Rose.getStroke(skinParam, LineParam.swimlaneBorder, 2); + if (SkinParam.USE_STYLES()) { + color = getStyle().value(PName.LineColor).asColor(skinParam.getIHtmlColorSet()); + thickness = getStyle().getStroke(); + } + ug.apply(UTranslate.dx(x1)).apply(thickness).apply(new UChangeColor(color)).draw(ULine.vline(height)); + + } + + public double getWidth() { + return x1 + x2; + } + + public final double getX1() { + return x1; + } + + public final double getX2() { + return x2; + } + +} diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Snake.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Snake.java index bc60791792e..ff1420083c5 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Snake.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Snake.java @@ -54,7 +54,7 @@ import net.sourceforge.plantuml.ugraphic.UPolygon; import net.sourceforge.plantuml.ugraphic.UShape; import net.sourceforge.plantuml.ugraphic.UTranslate; -import net.sourceforge.plantuml.ugraphic.comp.CompressionTransform; +import net.sourceforge.plantuml.ugraphic.comp.PiecewiseAffineTransform; public class Snake implements UShape { @@ -72,7 +72,7 @@ public final void setIgnoreForCompression() { this.worm.setIgnoreForCompression(); } - public Snake transformX(CompressionTransform compressionTransform) { + public Snake transformX(PiecewiseAffineTransform compressionTransform) { final Snake result = new Snake(startDecoration, horizontalAlignment, color, endDecoration); result.textBlock = this.textBlock; result.mergeable = this.mergeable; diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Swimlane.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Swimlane.java index ab0e6297c6d..09de94ec7d7 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Swimlane.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Swimlane.java @@ -79,8 +79,11 @@ public final UTranslate getTranslate() { return translate; } - public final void setTranslateAndWidth(UTranslate translate, double actualWidth) { + public final void setTranslate(UTranslate translate) { this.translate = translate; + } + + public final void setWidth(double actualWidth) { this.actualWidth = actualWidth; } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesA.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesA.java index 71036230364..b3d243073bc 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesA.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesA.java @@ -77,10 +77,12 @@ import net.sourceforge.plantuml.ugraphic.UShape; import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.color.HColor; +import net.sourceforge.plantuml.ugraphic.comp.CompressionMode; +import net.sourceforge.plantuml.ugraphic.comp.SlotFinder; import net.sourceforge.plantuml.ugraphic.comp.SlotSet; import net.sourceforge.plantuml.utils.MathUtils; -public class SwimlanesA extends AbstractTextBlock implements TextBlock, Styleable { +public class SwimlanesA extends AbstractTextBlock implements ISwimlanesA, TextBlock, Styleable { protected final ISkinParam skinParam;; private final Pragma pragma; @@ -179,28 +181,33 @@ public UGraphic apply(UChange change) { } - static protected final double separationMargin = 10; + protected double separationMargin() { + return 10; + } - private TextBlock full; + // private TextBlock full; - public void drawU(UGraphic ug) { - if (full == null) { - final FtileFactory factory = getFtileFactory(ug.getStringBounder()); - full = root.createFtile(factory); - if (swimlanes.size() <= 1) { - // BUG42 - full = new TextBlockInterceptorUDrawable(full); - } + public final void computeSize(StringBounder stringBounder) { + final SlotFinder ug = new SlotFinder(CompressionMode.ON_Y, stringBounder); + if (swimlanes.size() > 1) { + TextBlock full = root.createFtile(getFtileFactory(stringBounder)); + computeSizeInternal(ug, full); } + } + + public final void drawU(UGraphic ug) { + TextBlock full = root.createFtile(getFtileFactory(ug.getStringBounder())); + ug = new UGraphicForSnake(ug); - if (swimlanes.size() <= 1) { + if (swimlanes.size() > 1) { + drawWhenSwimlanes(ug, full); + } else { + // BUG42 + full = new TextBlockInterceptorUDrawable(full); full.drawU(ug); ug.flushUg(); - return; } - - drawWhenSwimlanes(ug, full); } static private void printDebug(UGraphic ug, SlotSet slot, HColor col, TextBlock full) { @@ -213,30 +220,32 @@ protected void drawWhenSwimlanes(final UGraphic ug, TextBlock full) { final StringBounder stringBounder = ug.getStringBounder(); final Dimension2D dimensionFull = full.calculateDimension(stringBounder); - computeSize(ug, full); - final UTranslate titleHeightTranslate = getTitleHeightTranslate(stringBounder); - double x2 = 0; for (Swimlane swimlane : swimlanes) { final HColor back = swimlane.getColors(skinParam).getColor(ColorType.BACK); if (back != null) { - final UGraphic background = ug.apply(new UChangeBackColor(back)).apply(new UChangeColor(back)) - .apply(UTranslate.dx(x2)); - final URectangle rectangle = new URectangle(swimlane.getActualWidth(), dimensionFull.getHeight() - + titleHeightTranslate.getDy()).ignoreForCompression(); - background.draw(rectangle); + UGraphic background = ug.apply(new UChangeBackColor(back)).apply(new UChangeColor(back)); + background = background.apply(UTranslate.dx(x2)); + drawBackColor(background, swimlane, dimensionFull); } - full.drawU(new UGraphicInterceptorOneSwimlane(ug, swimlane).apply(swimlane.getTranslate()).apply( - titleHeightTranslate)); + full.drawU(new UGraphicInterceptorOneSwimlane(ug, swimlane).apply(swimlane.getTranslate()) + .apply(getTitleHeightTranslate(stringBounder))); x2 += swimlane.getActualWidth(); } - final Cross cross = new Cross(ug.apply(titleHeightTranslate)); + final Cross cross = new Cross(ug.apply(getTitleHeightTranslate(stringBounder))); full.drawU(cross); cross.flushUg(); } + protected void drawBackColor(UGraphic ug, Swimlane swimlane, Dimension2D dimensionFull) { + final StringBounder stringBounder = ug.getStringBounder(); + final double height = dimensionFull.getHeight() + getTitleHeightTranslate(stringBounder).getDy(); + final URectangle rectangle = new URectangle(swimlane.getActualWidth(), height).ignoreForCompressionOnX().ignoreForCompressionOnY(); + ug.draw(rectangle); + } + protected UTranslate getTitleHeightTranslate(final StringBounder stringBounder) { return new UTranslate(); } @@ -245,8 +254,8 @@ private void computeDrawingWidths(UGraphic ug, TextBlock full) { final StringBounder stringBounder = ug.getStringBounder(); for (Swimlane swimlane : swimlanes) { final LimitFinder limitFinder = new LimitFinder(stringBounder, false); - final UGraphicInterceptorOneSwimlane interceptor = new UGraphicInterceptorOneSwimlane(new UGraphicForSnake( - limitFinder), swimlane); + final UGraphicInterceptorOneSwimlane interceptor = new UGraphicInterceptorOneSwimlane( + new UGraphicForSnake(limitFinder), swimlane); full.drawU(interceptor); interceptor.flushUg(); final MinMax minMax = limitFinder.getMinMax(); @@ -254,7 +263,7 @@ private void computeDrawingWidths(UGraphic ug, TextBlock full) { } } - private void computeSize(UGraphic ug, TextBlock full) { + private void computeSizeInternal(UGraphic ug, TextBlock full) { computeDrawingWidths(ug, full); double x1 = 0; @@ -269,9 +278,10 @@ private void computeSize(UGraphic ug, TextBlock full) { for (Swimlane swimlane : swimlanes) { final double swimlaneActualWidth = swimlaneActualWidth(ug.getStringBounder(), swimlaneWidth, swimlane); - final UTranslate translate = UTranslate.dx(x1 - swimlane.getMinMax().getMinX() + separationMargin - + (swimlaneActualWidth - rawDrawingWidth(swimlane)) / 2.0); - swimlane.setTranslateAndWidth(translate, swimlaneActualWidth); + final UTranslate translate = UTranslate.dx(x1 - swimlane.getMinMax().getMinX() + separationMargin() + + (swimlaneActualWidth - rawDrawingWidth(swimlane)) / 2.0); + swimlane.setTranslate(translate); + swimlane.setWidth(swimlaneActualWidth); x1 += swimlaneActualWidth; } @@ -282,7 +292,7 @@ protected double swimlaneActualWidth(StringBounder stringBounder, double swimlan } private double rawDrawingWidth(Swimlane swimlane) { - return swimlane.getMinMax().getWidth() + 2 * separationMargin; + return swimlane.getMinMax().getWidth() + 2 * separationMargin(); } public Dimension2D calculateDimension(StringBounder stringBounder) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesAAA.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesAAA.java new file mode 100644 index 00000000000..53e61634649 --- /dev/null +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesAAA.java @@ -0,0 +1,436 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.activitydiagram3.ftile; + +import java.awt.geom.Dimension2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.sourceforge.plantuml.ColorParam; +import net.sourceforge.plantuml.FontParam; +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.LineBreakStrategy; +import net.sourceforge.plantuml.Pragma; +import net.sourceforge.plantuml.SkinParam; +import net.sourceforge.plantuml.activitydiagram3.Instruction; +import net.sourceforge.plantuml.activitydiagram3.InstructionList; +import net.sourceforge.plantuml.activitydiagram3.LinkRendering; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorAddNote; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorAddUrl; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorAssembly; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorCreateGroup; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorCreateParallel; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorIf; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorRepeat; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorSwitch; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorWhile; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.UGraphicInterceptorOneSwimlane; +import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.VCompactFactory; +import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.graphic.AbstractTextBlock; +import net.sourceforge.plantuml.graphic.FontConfiguration; +import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.graphic.TextBlockUtils; +import net.sourceforge.plantuml.graphic.UGraphicDelegator; +import net.sourceforge.plantuml.graphic.color.ColorType; +import net.sourceforge.plantuml.style.PName; +import net.sourceforge.plantuml.style.SName; +import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.StyleSignature; +import net.sourceforge.plantuml.style.Styleable; +import net.sourceforge.plantuml.svek.UGraphicForSnake; +import net.sourceforge.plantuml.ugraphic.LimitFinder; +import net.sourceforge.plantuml.ugraphic.MinMax; +import net.sourceforge.plantuml.ugraphic.UChange; +import net.sourceforge.plantuml.ugraphic.UChangeBackColor; +import net.sourceforge.plantuml.ugraphic.UChangeColor; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.URectangle; +import net.sourceforge.plantuml.ugraphic.UShape; +import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.color.HColor; +import net.sourceforge.plantuml.ugraphic.comp.CompressionMode; +import net.sourceforge.plantuml.ugraphic.comp.SlotFinder; +import net.sourceforge.plantuml.utils.MathUtils; + +public class SwimlanesAAA extends AbstractTextBlock implements ISwimlanesA, TextBlock, Styleable { + + private final ISkinParam skinParam;; + private final Pragma pragma; + + private final List swimlanesRaw = new ArrayList(); + private final List swimlanesSpecial = new ArrayList(); + private final List dividers = new ArrayList(); + private Swimlane currentSwimlane = null; + + private final Instruction root = new InstructionList(); + private Instruction currentInstruction = root; + + private LinkRendering nextLinkRenderer = LinkRendering.none(); + private Style style; + + private List swimlanes() { + return Collections.unmodifiableList(swimlanesRaw); + } + + private List swimlanesSpecial() { + if (swimlanesSpecial.size() == 0) { + swimlanesSpecial.addAll(swimlanesRaw); + final Swimlane last = new Swimlane(""); + last.setMinMax(MinMax.getEmpty(true)); + swimlanesSpecial.add(last); + } + return Collections.unmodifiableList(swimlanesSpecial); + } + + public StyleSignature getDefaultStyleDefinition() { + return StyleSignature.of(SName.root, SName.element, SName.classDiagram, SName.swimlane); + } + + public SwimlanesAAA(ISkinParam skinParam, Pragma pragma) { + this.skinParam = skinParam; + this.pragma = pragma; + } + + protected Style getStyle() { + if (style == null) { + this.style = getDefaultStyleDefinition().getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + return style; + } + + private FtileFactory getFtileFactory(StringBounder stringBounder) { + FtileFactory factory = new VCompactFactory(skinParam, stringBounder); + factory = new FtileFactoryDelegatorAddUrl(factory); + factory = new FtileFactoryDelegatorAssembly(factory); + factory = new FtileFactoryDelegatorIf(factory, pragma); + factory = new FtileFactoryDelegatorSwitch(factory); + factory = new FtileFactoryDelegatorWhile(factory); + factory = new FtileFactoryDelegatorRepeat(factory); + factory = new FtileFactoryDelegatorCreateParallel(factory); + // factory = new FtileFactoryDelegatorCreateParallelAddingMargin(new + // FtileFactoryDelegatorCreateParallel1(factory)); + factory = new FtileFactoryDelegatorAddNote(factory); + factory = new FtileFactoryDelegatorCreateGroup(factory); + return factory; + } + + public void swimlane(String name, HColor color, Display label) { + currentSwimlane = getOrCreate(name); + if (color != null) { + currentSwimlane.setSpecificColorTOBEREMOVED(ColorType.BACK, color); + } + if (Display.isNull(label) == false) { + currentSwimlane.setDisplay(label); + } + } + + private Swimlane getOrCreate(String name) { + for (Swimlane s : swimlanes()) { + if (s.getName().equals(name)) { + return s; + } + } + final Swimlane result = new Swimlane(name); + swimlanesRaw.add(result); + return result; + } + + class Cross extends UGraphicDelegator { + + private Cross(UGraphic ug) { + super(ug); + } + + @Override + public void draw(UShape shape) { + if (shape instanceof Ftile) { + final Ftile tile = (Ftile) shape; + tile.drawU(this); + } else if (shape instanceof Connection) { + final Connection connection = (Connection) shape; + final Ftile tile1 = connection.getFtile1(); + final Ftile tile2 = connection.getFtile2(); + + if (tile1 == null || tile2 == null) { + return; + } + if (tile1.getSwimlaneOut() != tile2.getSwimlaneIn()) { + final ConnectionCross connectionCross = new ConnectionCross(connection); + connectionCross.drawU(getUg()); + } + } + } + + public UGraphic apply(UChange change) { + return new Cross(getUg().apply(change)); + } + + } + + public final void computeSize(StringBounder stringBounder) { + final SlotFinder ug = new SlotFinder(CompressionMode.ON_Y, stringBounder); + if (swimlanes().size() > 1) { + TextBlock full = root.createFtile(getFtileFactory(stringBounder)); + computeSizeInternal(ug, full); + } + + } + + public final void drawU(UGraphic ug) { + TextBlock full = root.createFtile(getFtileFactory(ug.getStringBounder())); + + ug = new UGraphicForSnake(ug); + if (swimlanes().size() > 1) { + drawWhenSwimlanes(ug, full); + } else { + // BUG42 + full = new TextBlockInterceptorUDrawable(full); + full.drawU(ug); + ug.flushUg(); + } + } + + private TextBlock getTitle(Swimlane swimlane) { + final HorizontalAlignment horizontalAlignment = HorizontalAlignment.LEFT; + FontConfiguration fontConfiguration = new FontConfiguration(skinParam, FontParam.SWIMLANE_TITLE, null); + if (SkinParam.USE_STYLES()) { + fontConfiguration = getStyle().getFontConfiguration(skinParam.getIHtmlColorSet()); + } + LineBreakStrategy wrap = getWrap(); + if (wrap.isAuto()) { + wrap = new LineBreakStrategy("" + ((int) swimlane.getActualWidth())); + } + + return swimlane.getDisplay().create9(fontConfiguration, horizontalAlignment, skinParam, wrap); + } + + private LineBreakStrategy getWrap() { + LineBreakStrategy wrap = skinParam.swimlaneWrapTitleWidth(); + if (wrap == LineBreakStrategy.NONE) { + wrap = skinParam.wrapWidth(); + } + return wrap; + } + + private UTranslate getTitleHeightTranslate(final StringBounder stringBounder) { + double titlesHeight = getTitlesHeight(stringBounder); + return UTranslate.dy(titlesHeight > 0 ? titlesHeight + 5 : 0); + } + + private double getTitlesHeight(StringBounder stringBounder) { + double titlesHeight = 0; + for (Swimlane swimlane : swimlanes()) { + final TextBlock swTitle = getTitle(swimlane); + titlesHeight = Math.max(titlesHeight, swTitle.calculateDimension(stringBounder).getHeight()); + } + return titlesHeight; + } + + private void drawWhenSwimlanes(UGraphic ug, TextBlock full) { + final StringBounder stringBounder = ug.getStringBounder(); + final UTranslate titleHeightTranslate = getTitleHeightTranslate(stringBounder); + + drawTitlesBackground(ug); + + final Dimension2D dimensionFull = full.calculateDimension(stringBounder); + int i = 0; + assert dividers.size() == swimlanes().size() + 1; + for (Swimlane swimlane : swimlanesSpecial()) { + final LaneDivider divider1 = dividers.get(i); + + final double xpos = swimlane.getTranslate().getDx() + swimlane.getMinMax().getMinX(); + final HColor back = swimlane.getColors(skinParam).getColor(ColorType.BACK); + if (back != null) { + final LaneDivider divider2 = dividers.get(i + 1); + final UGraphic background = ug.apply(new UChangeBackColor(back)).apply(new UChangeColor(back)) + .apply(UTranslate.dx(xpos - divider1.getX2())); + final double width = swimlane.getActualWidth() + divider1.getX2() + divider2.getX1(); + final double height = dimensionFull.getHeight() + titleHeightTranslate.getDy(); + background.draw(new URectangle(width, height).ignoreForCompressionOnX().ignoreForCompressionOnY()); + } + + full.drawU(new UGraphicInterceptorOneSwimlane(ug, swimlane).apply(swimlane.getTranslate()) + .apply(getTitleHeightTranslate(stringBounder))); + + final double dividerWith = divider1.calculateDimension(stringBounder).getWidth(); + divider1.drawU(ug.apply(UTranslate.dx(xpos - dividerWith))); + i++; + } + + final Cross cross = new Cross(ug.apply(getTitleHeightTranslate(stringBounder))); + full.drawU(cross); + cross.flushUg(); + + drawTitles(ug); + + } + + private void drawTitlesBackground(UGraphic ug) { + HColor color = skinParam.getHtmlColor(ColorParam.swimlaneTitleBackground, null, false); + if (SkinParam.USE_STYLES()) { + color = getStyle().value(PName.BackGroundColor).asColor(skinParam.getIHtmlColorSet()); + } + if (color != null) { + final double titleHeight = getTitlesHeight(ug.getStringBounder()); + double fullWidth = swimlanesSpecial().get(swimlanesSpecial().size() - 1).getTranslate().getDx() - 2 * 5 - 1; + final URectangle back = new URectangle(fullWidth, titleHeight).ignoreForCompressionOnX() + .ignoreForCompressionOnY(); + ug.apply(UTranslate.dx(5)).apply(new UChangeBackColor(color)).apply(new UChangeColor(color)).draw(back); + } + } + + private void drawTitles(UGraphic ug) { + for (Swimlane swimlane : swimlanes()) { + final TextBlock swTitle = getTitle(swimlane); + final double x2 = swimlane.getTranslate().getDx() + swimlane.getMinMax().getMinX(); + final CenteredText centeredText = new CenteredText(swTitle, getWidthWithoutTitle(swimlane)); + ug.apply(UTranslate.dx(x2)).draw(centeredText); + } + } + + private void computeDrawingWidths(UGraphic ug, TextBlock full) { + final StringBounder stringBounder = ug.getStringBounder(); + for (Swimlane swimlane : swimlanes()) { + final LimitFinder limitFinder = new LimitFinder(stringBounder, false); + final UGraphicInterceptorOneSwimlane interceptor = new UGraphicInterceptorOneSwimlane( + new UGraphicForSnake(limitFinder), swimlane); + full.drawU(interceptor); + interceptor.flushUg(); + final MinMax minMax = limitFinder.getMinMax(); + swimlane.setMinMax(minMax); + } + } + + private void computeSizeInternal(UGraphic ug, TextBlock full) { + computeDrawingWidths(ug, full); + + double min = skinParam.swimlaneWidth(); + + if (min == ISkinParam.SWIMLANE_WIDTH_SAME) { + for (Swimlane swimlane : swimlanes()) { + min = Math.max(min, getWidthWithoutTitle(swimlane)); + } + } + final StringBounder stringBounder = ug.getStringBounder(); + + for (int i = 0; i < swimlanesSpecial().size(); i++) { + final Swimlane swimlane = swimlanesSpecial().get(i); + final double swimlaneActualWidth = MathUtils.max(min, getWidthWithoutTitle(swimlane)); + swimlane.setWidth(swimlaneActualWidth); + } + + final UTranslate titleHeightTranslate = getTitleHeightTranslate(stringBounder); + final Dimension2D dimensionFull = full.calculateDimension(stringBounder); + + dividers.clear(); + double xpos = 0; + for (int i = 0; i < swimlanesSpecial().size(); i++) { + final Swimlane swimlane = swimlanesSpecial().get(i); + double x1 = getHalfMissingSpace(stringBounder, i, min); + double x2 = getHalfMissingSpace(stringBounder, i + 1, min); + final LaneDivider laneDivider = new LaneDivider(skinParam, x1, x2, + dimensionFull.getHeight() + titleHeightTranslate.getDy()); + dividers.add(laneDivider); + + final double xx = xpos + laneDivider.getWidth() - swimlane.getMinMax().getMinX() + + (swimlane.getActualWidth() - getWidthWithoutTitle(swimlane)) / 2.0; + swimlane.setTranslate(UTranslate.dx(xx)); + + xpos += swimlane.getActualWidth() + laneDivider.getWidth(); + } + assert dividers.size() == swimlanes().size() + 1; + } + + public double getHalfMissingSpace(StringBounder stringBounder, int i, double min) { + if (i == 0 || i > swimlanesSpecial().size()) { + return 5; + } + final Swimlane swimlane = swimlanesSpecial().get(i - 1); + final double swimlaneActualWidth = Math.max(min, getWidthWithoutTitle(swimlane)); + final double titleWidth = getTitle(swimlane).calculateDimension(stringBounder).getWidth(); + if (titleWidth <= swimlaneActualWidth) { + return 5; + } + assert titleWidth > swimlaneActualWidth; + return Math.max(5, 5 + (titleWidth - swimlaneActualWidth) / 2); + } + + private double getWidthWithoutTitle(Swimlane swimlane) { + return swimlane.getMinMax().getWidth(); + } + + public Dimension2D calculateDimension(StringBounder stringBounder) { + return getMinMax(stringBounder).getDimension(); + } + + public Instruction getCurrent() { + return currentInstruction; + } + + public void setCurrent(Instruction current) { + this.currentInstruction = current; + } + + public LinkRendering nextLinkRenderer() { + return nextLinkRenderer; + } + + public void setNextLinkRenderer(LinkRendering link) { + if (link == null) { + throw new IllegalArgumentException(); + } + this.nextLinkRenderer = link; + } + + public Swimlane getCurrentSwimlane() { + return currentSwimlane; + } + + private MinMax cachedMinMax; + + @Override + public MinMax getMinMax(StringBounder stringBounder) { + if (cachedMinMax == null) { + cachedMinMax = TextBlockUtils.getMinMax(this, stringBounder); + } + return cachedMinMax; + } + +} diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesB.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesB.java index d973307b308..6802fcb8612 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesB.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesB.java @@ -73,7 +73,7 @@ protected void drawWhenSwimlanes(UGraphic ug, TextBlock full) { } if (color != null) { final double titleHeight = getTitlesHeight(stringBounder); - final URectangle back = new URectangle(getTitlesWidth(stringBounder), titleHeight).ignoreForCompression(); + final URectangle back = new URectangle(getTitlesWidth(stringBounder), titleHeight).ignoreForCompressionOnX().ignoreForCompressionOnY(); ug.apply(new UChangeBackColor(color)).apply(new UChangeColor(color)).draw(back); } for (Swimlane swimlane : swimlanes) { @@ -105,7 +105,7 @@ private TextBlock getTitle(Swimlane swimlane) { wrap = new LineBreakStrategy("" + ((int) swimlane.getActualWidth())); } - return swimlane.getDisplay().create(fontConfiguration, horizontalAlignment, skinParam, wrap); + return swimlane.getDisplay().create9(fontConfiguration, horizontalAlignment, skinParam, wrap); } private LineBreakStrategy getWrap() { @@ -124,7 +124,7 @@ protected double swimlaneActualWidth(StringBounder stringBounder, double swimlan } final double titleWidth = getTitle(swimlane).calculateDimension(stringBounder).getWidth(); - return MathUtils.max(m1, titleWidth + 2 * separationMargin); + return MathUtils.max(m1, titleWidth + 2 * separationMargin()); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesC.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesC.java index 679519bad8d..97c98f2e6fd 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesC.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesC.java @@ -91,5 +91,4 @@ private void drawSeparation(UGraphic ug, double height) { } ug.apply(thickness).apply(new UChangeColor(color)).draw(ULine.vline(height)); } - } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Worm.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Worm.java index 76a6a6fbdef..30a39f2d527 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Worm.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Worm.java @@ -104,7 +104,7 @@ public void drawInternalOneColor(UPolygon startDecoration, UGraphic ug, HtmlColo ug = ug.apply(new UStroke(1.5)); final Point2D start = points.get(0); if (ignoreForCompression) { - startDecoration.setIgnoreForCompression(CompressionMode.ON_X); + startDecoration.setCompressionMode(CompressionMode.ON_X); } ug.apply(new UTranslate(start)).apply(new UStroke()).draw(startDecoration); } @@ -112,7 +112,7 @@ public void drawInternalOneColor(UPolygon startDecoration, UGraphic ug, HtmlColo ug = ug.apply(new UStroke(1.5)); final Point2D end = points.get(points.size() - 1); if (ignoreForCompression) { - endDecoration.setIgnoreForCompression(CompressionMode.ON_X); + endDecoration.setCompressionMode(CompressionMode.ON_X); } ug.apply(new UTranslate(end)).apply(new UStroke()).draw(endDecoration); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/AbstractParallelFtilesBuilder.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/AbstractParallelFtilesBuilder.java index d2aa032a8c9..cf787e45eda 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/AbstractParallelFtilesBuilder.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/AbstractParallelFtilesBuilder.java @@ -119,7 +119,7 @@ protected final TextBlock getTextBlock(Display display) { } else { fontConfiguration = new FontConfiguration(skinParam(), FontParam.ARROW, null); } - return display.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam(), CreoleMode.SIMPLE_LINE); + return display.create7(fontConfiguration, HorizontalAlignment.LEFT, skinParam(), CreoleMode.SIMPLE_LINE); } protected TextBlock getTextBlock(LinkRendering linkRendering) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileGroup.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileGroup.java index d21e36fa8af..01cc8ae7f78 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileGroup.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileGroup.java @@ -173,8 +173,8 @@ public double suppWidth(StringBounder stringBounder) { final FtileGeometry orig = getInnerDimension(stringBounder); final Dimension2D dimTitle = name.calculateDimension(stringBounder); final Dimension2D dimHeaderNote = headerNote.calculateDimension(stringBounder); - final double suppWidth = MathUtils - .max(orig.getWidth(), dimTitle.getWidth() + 20, dimHeaderNote.getWidth() + 20) - orig.getWidth(); + final double suppWidth = MathUtils.max(orig.getWidth(), dimTitle.getWidth() + 20, dimHeaderNote.getWidth() + 20) + - orig.getWidth(); return suppWidth; } @@ -207,11 +207,11 @@ protected FtileGeometry calculateDimensionFtile(StringBounder stringBounder) { + headerNoteHeight(stringBounder); final double titleAndHeaderNoteHeight = diffHeightTitle(stringBounder) + headerNoteHeight(stringBounder); if (orig.hasPointOut()) { - return new FtileGeometry(width, height, orig.getLeft() + suppWidth / 2, orig.getInY() - + titleAndHeaderNoteHeight, orig.getOutY() + titleAndHeaderNoteHeight); + return new FtileGeometry(width, height, orig.getLeft() + suppWidth / 2, + orig.getInY() + titleAndHeaderNoteHeight, orig.getOutY() + titleAndHeaderNoteHeight); } - return new FtileGeometry(width, height, orig.getLeft() + suppWidth / 2, orig.getInY() - + titleAndHeaderNoteHeight); + return new FtileGeometry(width, height, orig.getLeft() + suppWidth / 2, + orig.getInY() + titleAndHeaderNoteHeight); } private double headerNoteHeight(StringBounder stringBounder) { @@ -222,12 +222,14 @@ public void drawU(UGraphic ug) { final StringBounder stringBounder = ug.getStringBounder(); final Dimension2D dimTotal = calculateDimension(stringBounder); - // final double roundCorner = type.getSkinParameter().getRoundCorner(skinParam(), null); + // final double roundCorner = + // type.getSkinParameter().getRoundCorner(skinParam(), null); final SymbolContext symbolContext = new SymbolContext(backColor, borderColor).withShadow(shadowing) .withStroke(stroke).withCorner(roundCorner, 0); - type.asBig(name, inner.skinParam().getHorizontalAlignment(AlignmentParam.packageTitleAlignment, null, false), - TextBlockUtils.empty(0, 0), dimTotal.getWidth(), dimTotal.getHeight(), symbolContext, + final HorizontalAlignment align = inner.skinParam().getHorizontalAlignment(AlignmentParam.packageTitleAlignment, + null, false); + type.asBig(name, align, TextBlockUtils.empty(0, 0), dimTotal.getWidth(), dimTotal.getHeight(), symbolContext, skinParam().getStereotypeAlignment()).drawU(ug); final Dimension2D dimHeaderNote = headerNote.calculateDimension(stringBounder); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileRepeat.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileRepeat.java index dbc07e7224c..45ca924c929 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileRepeat.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileRepeat.java @@ -154,12 +154,12 @@ public static Ftile create(LinkRendering backRepeatLinkRendering, Swimlane swiml final List conns = new ArrayList(); final Display in1 = repeat.getInLinkRendering().getDisplay(); - final TextBlock tbin1 = in1 == null ? null : in1.create(fcArrow, HorizontalAlignment.LEFT, spriteContainer, + final TextBlock tbin1 = in1 == null ? null : in1.create7(fcArrow, HorizontalAlignment.LEFT, spriteContainer, CreoleMode.SIMPLE_LINE); conns.add(result.new ConnectionIn(repeat.getInLinkRendering().getRainbow(arrowColor), tbin1)); final Display backLink1 = backRepeatLinkRendering.getDisplay(); - final TextBlock tbbackLink1 = backLink1 == null ? null : backLink1.create(fcArrow, HorizontalAlignment.LEFT, + final TextBlock tbbackLink1 = backLink1 == null ? null : backLink1.create7(fcArrow, HorizontalAlignment.LEFT, spriteContainer, CreoleMode.SIMPLE_LINE); if (repeat.getSwimlaneIn() == swimlaneOut) { if (backward == null) { @@ -176,7 +176,7 @@ public static Ftile create(LinkRendering backRepeatLinkRendering, Swimlane swiml } final Display out1 = repeat.getOutLinkRendering().getDisplay(); - final TextBlock tbout1 = out1 == null ? null : out1.create(fcArrow, HorizontalAlignment.LEFT, spriteContainer, + final TextBlock tbout1 = out1 == null ? null : out1.create7(fcArrow, HorizontalAlignment.LEFT, spriteContainer, CreoleMode.SIMPLE_LINE); final Rainbow tmpColor = endRepeatLinkColor.withDefault(arrowColor); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderSplit.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderSplit.java index d56e794b031..cbf0530b190 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderSplit.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderSplit.java @@ -52,7 +52,6 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.FtileKilled; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileUtils; import net.sourceforge.plantuml.activitydiagram3.ftile.Snake; -import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileThinSplit; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.Rainbow; diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java index 01d80f3bc0f..a244eab08e9 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java @@ -267,7 +267,7 @@ private Ftile getDiamond1(boolean eastWest, TextBlock tb1, TextBlock tb2) { } private TextBlock getLabelPositive(Branch branch) { - return branch.getLabelPositive().create(fontArrow, HorizontalAlignment.LEFT, ftileFactory.skinParam(), + return branch.getLabelPositive().create7(fontArrow, HorizontalAlignment.LEFT, ftileFactory.skinParam(), CreoleMode.SIMPLE_LINE); } @@ -279,10 +279,10 @@ private Ftile getDiamond2(Branch branch1, Branch branch2, boolean useNorth) { // else use default ConditionEndStyle.DIAMOND if (hasTwoBranches()) { final Display out1 = branch1.getFtile().getOutLinkRendering().getDisplay(); - final TextBlock tbout1 = out1 == null ? null : out1.create(fontArrow, HorizontalAlignment.LEFT, + final TextBlock tbout1 = out1 == null ? null : out1.create7(fontArrow, HorizontalAlignment.LEFT, ftileFactory.skinParam(), CreoleMode.SIMPLE_LINE); final Display out2 = branch2.getFtile().getOutLinkRendering().getDisplay(); - final TextBlock tbout2 = out2 == null ? null : out2.create(fontArrow, HorizontalAlignment.LEFT, + final TextBlock tbout2 = out2 == null ? null : out2.create7(fontArrow, HorizontalAlignment.LEFT, ftileFactory.skinParam(), CreoleMode.SIMPLE_LINE); FtileDiamond tmp = new FtileDiamond(tile1.skinParam(), backColor, borderColor, swimlane); tmp = useNorth ? tmp.withNorth(tbout1) : tmp.withWest(tbout1); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/FtileSwitchWithDiamonds.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/FtileSwitchWithDiamonds.java index c12357381c6..23241fde000 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/FtileSwitchWithDiamonds.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/FtileSwitchWithDiamonds.java @@ -194,7 +194,7 @@ protected UTranslate getTranslateDiamond2(StringBounder stringBounder) { protected TextBlock getLabelPositive(Branch branch) { final FontConfiguration fcArrow = new FontConfiguration(skinParam(), FontParam.ARROW, null); - return branch.getLabelPositive().create(fcArrow, HorizontalAlignment.LEFT, skinParam(), CreoleMode.SIMPLE_LINE); + return branch.getLabelPositive().create7(fcArrow, HorizontalAlignment.LEFT, skinParam(), CreoleMode.SIMPLE_LINE); } } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/FtileSwitchWithOneLink.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/FtileSwitchWithOneLink.java index eaec448b374..32d521e0864 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/FtileSwitchWithOneLink.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/FtileSwitchWithOneLink.java @@ -39,7 +39,6 @@ import java.util.ArrayList; import java.util.List; -import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.activitydiagram3.Branch; import net.sourceforge.plantuml.activitydiagram3.ftile.AbstractConnection; import net.sourceforge.plantuml.activitydiagram3.ftile.Arrows; @@ -49,12 +48,8 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.FtileUtils; import net.sourceforge.plantuml.activitydiagram3.ftile.Snake; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; -import net.sourceforge.plantuml.creole.CreoleMode; -import net.sourceforge.plantuml.graphic.FontConfiguration; -import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.Rainbow; import net.sourceforge.plantuml.graphic.StringBounder; -import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.ugraphic.UGraphic; public class FtileSwitchWithOneLink extends FtileSwitchWithDiamonds { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBlackBlock.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBlackBlock.java index f925a61b795..fcbdbd49754 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBlackBlock.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBlackBlock.java @@ -91,7 +91,7 @@ protected FtileGeometry calculateDimensionFtile(StringBounder stringBounder) { } public void drawU(UGraphic ug) { - final URectangle rect = new URectangle(width, height).rounded(5).ignoreForCompression(); + final URectangle rect = new URectangle(width, height).rounded(5).ignoreForCompressionOnX(); if (skinParam().shadowing(null)) { rect.setDeltaShadow(3); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java index 3993ff28150..120c557b690 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java @@ -67,7 +67,6 @@ import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.UDrawable; -import net.sourceforge.plantuml.graphic.color.ColorType; import net.sourceforge.plantuml.graphic.color.Colors; import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.SName; diff --git a/src/net/sourceforge/plantuml/classdiagram/ClassDiagramFactory.java b/src/net/sourceforge/plantuml/classdiagram/ClassDiagramFactory.java index 0682933317a..dad321503a8 100644 --- a/src/net/sourceforge/plantuml/classdiagram/ClassDiagramFactory.java +++ b/src/net/sourceforge/plantuml/classdiagram/ClassDiagramFactory.java @@ -79,6 +79,7 @@ import net.sourceforge.plantuml.descdiagram.command.CommandPackageWithUSymbol; import net.sourceforge.plantuml.objectdiagram.command.CommandCreateEntityObject; import net.sourceforge.plantuml.objectdiagram.command.CommandCreateEntityObjectMultilines; +import net.sourceforge.plantuml.objectdiagram.command.CommandCreateMap; public class ClassDiagramFactory extends UmlDiagramFactory { @@ -110,6 +111,7 @@ protected List createCommands() { cmds.add(new CommandRemoveRestore()); cmds.add(new CommandCreateClassMultilines()); cmds.add(new CommandCreateEntityObjectMultilines()); + cmds.add(new CommandCreateMap()); cmds.add(new CommandCreateClass()); cmds.add(new CommandCreateEntityObject()); diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandAddMethod.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandAddMethod.java index 663c6c7c008..fe53e6fcf49 100644 --- a/src/net/sourceforge/plantuml/classdiagram/command/CommandAddMethod.java +++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandAddMethod.java @@ -84,7 +84,7 @@ protected CommandExecutionResult executeArg(ClassDiagram diagram, LineLocation l if (field.length() > 0 && VisibilityModifier.isVisibilityCharacter(field)) { diagram.setVisibilityModifierPresent(true); } - entity.getBodier().addFieldOrMethod(field, entity); + entity.getBodier().addFieldOrMethod(field); return CommandExecutionResult.ok(); } } diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java index 04285202f3d..16432539cf6 100644 --- a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java +++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java @@ -109,8 +109,8 @@ private static IRegex getRegexConcat() { new RegexLeaf("DISPLAY2", CommandCreateClass.DISPLAY_WITH_GENERIC)), // new RegexLeaf("CODE3", "(" + CommandCreateClass.CODE + ")"), // new RegexLeaf("CODE4", "[%g]([^%g]+)[%g]")), // - new RegexOptional(new RegexConcat(RegexLeaf.spaceZeroOrMore(), new RegexLeaf("GENERIC", "\\<(" - + GenericRegexProducer.PATTERN + ")\\>"))), // + new RegexOptional(new RegexConcat(RegexLeaf.spaceZeroOrMore(), + new RegexLeaf("GENERIC", "\\<(" + GenericRegexProducer.PATTERN + ")\\>"))), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("STEREO", "(\\<\\<.+\\>\\>)?"), // RegexLeaf.spaceZeroOrMore(), // @@ -120,17 +120,17 @@ private static IRegex getRegexConcat() { RegexLeaf.spaceZeroOrMore(), // color().getRegex(), // RegexLeaf.spaceZeroOrMore(), // - new RegexOptional(new RegexConcat(new RegexLeaf("##"), new RegexLeaf("LINECOLOR", - "(?:\\[(dotted|dashed|bold)\\])?(\\w+)?"))), // - new RegexOptional(new RegexConcat(RegexLeaf.spaceOneOrMore(), new RegexLeaf("EXTENDS", - "(extends)[%s]+(" + CommandCreateClassMultilines.CODES + ")"))), // - new RegexOptional(new RegexConcat(RegexLeaf.spaceOneOrMore(), new RegexLeaf("IMPLEMENTS", - "(implements)[%s]+(" + CommandCreateClassMultilines.CODES + ")"))), // + new RegexOptional(new RegexConcat(new RegexLeaf("##"), + new RegexLeaf("LINECOLOR", "(?:\\[(dotted|dashed|bold)\\])?(\\w+)?"))), // + new RegexOptional(new RegexConcat(RegexLeaf.spaceOneOrMore(), + new RegexLeaf("EXTENDS", "(extends)[%s]+(" + CommandCreateClassMultilines.CODES + ")"))), // + new RegexOptional(new RegexConcat(RegexLeaf.spaceOneOrMore(), + new RegexLeaf("IMPLEMENTS", "(implements)[%s]+(" + CommandCreateClassMultilines.CODES + ")"))), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("\\{"), // RegexLeaf.spaceZeroOrMore(), // RegexLeaf.end() // - ); + ); } @Override @@ -152,9 +152,10 @@ protected CommandExecutionResult executeNow(ClassDiagram diagram, BlocLines line } if (lines.size() > 1) { lines = lines.subExtract(1, 1); - final Url url = null; + // final Url url = null; // if (lines.size() > 0) { - // final UrlBuilder urlBuilder = new UrlBuilder(diagram.getSkinParam().getValue("topurl"), ModeUrl.STRICT); + // final UrlBuilder urlBuilder = new + // UrlBuilder(diagram.getSkinParam().getValue("topurl"), ModeUrl.STRICT); // url = urlBuilder.getUrl(lines.getFirst499().toString()); // } else { // url = null; @@ -166,15 +167,11 @@ protected CommandExecutionResult executeNow(ClassDiagram diagram, BlocLines line if (s.getString().length() > 0 && VisibilityModifier.isVisibilityCharacter(s.getString())) { diagram.setVisibilityModifierPresent(true); } - if (s instanceof StringLocated) { - entity.getBodier().addFieldOrMethod(((StringLocated) s).getString(), entity); - } else { - entity.getBodier().addFieldOrMethod(s.toString(), entity); - } - } - if (url != null) { - entity.addUrl(url); + entity.getBodier().addFieldOrMethod(s.getString()); } +// if (url != null) { +// entity.addUrl(url); +// } } manageExtends("EXTENDS", diagram, line0, entity); @@ -216,8 +213,8 @@ public static void manageExtends(String keyword, ClassDiagram diagram, RegexResu typeLink = typeLink.goDashed(); } final Link link = new Link(cl2, entity, typeLink, Display.NULL, 2, null, null, - diagram.getLabeldistance(), diagram.getLabelangle(), diagram.getSkinParam() - .getCurrentStyleBuilder()); + diagram.getLabeldistance(), diagram.getLabelangle(), + diagram.getSkinParam().getCurrentStyleBuilder()); diagram.addLink(link); } } @@ -266,9 +263,9 @@ private IEntity executeArg0(ClassDiagram diagram, RegexResult arg) { } result.setVisibilityModifier(visibilityModifier); if (stereotype != null) { - result.setStereotype(new Stereotype(stereotype, diagram.getSkinParam().getCircledCharacterRadius(), diagram - .getSkinParam().getFont(null, false, FontParam.CIRCLED_CHARACTER), diagram.getSkinParam() - .getIHtmlColorSet())); + result.setStereotype(new Stereotype(stereotype, diagram.getSkinParam().getCircledCharacterRadius(), + diagram.getSkinParam().getFont(null, false, FontParam.CIRCLED_CHARACTER), + diagram.getSkinParam().getIHtmlColorSet())); } final String urlString = arg.get("URL", 0); @@ -290,9 +287,11 @@ private IEntity executeArg0(ClassDiagram diagram, RegexResult arg) { result.setColors(colors); // result.setSpecificColorTOBEREMOVED(ColorType.BACK, - // diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("COLOR", 0))); + // diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("COLOR", + // 0))); // result.setSpecificColorTOBEREMOVED(ColorType.LINE, - // diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("LINECOLOR", 1))); + // diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("LINECOLOR", + // 1))); // result.applyStroke(arg.get("LINECOLOR", 0)); if (generic != null) { diff --git a/src/net/sourceforge/plantuml/creole/SheetBlock1.java b/src/net/sourceforge/plantuml/creole/SheetBlock1.java index 0ee09d46868..73b079cbdb0 100644 --- a/src/net/sourceforge/plantuml/creole/SheetBlock1.java +++ b/src/net/sourceforge/plantuml/creole/SheetBlock1.java @@ -59,7 +59,7 @@ public class SheetBlock1 extends AbstractTextBlock implements TextBlock, Atom, S public List splitInTwo(StringBounder stringBounder, double width) { throw new UnsupportedOperationException(getClass().toString()); } - + private final Sheet sheet; private List stripes; private Map heights; @@ -77,7 +77,7 @@ public SheetBlock1(Sheet sheet, LineBreakStrategy maxWidth, double padding) { throw new IllegalArgumentException(); } } - + @Override public String toString() { return sheet.toString(); diff --git a/src/net/sourceforge/plantuml/creole/atom/AtomText.java b/src/net/sourceforge/plantuml/creole/atom/AtomText.java index 872c95ada40..e1119ae5326 100644 --- a/src/net/sourceforge/plantuml/creole/atom/AtomText.java +++ b/src/net/sourceforge/plantuml/creole/atom/AtomText.java @@ -92,11 +92,6 @@ public static Atom create(String text, FontConfiguration fontConfiguration) { return new AtomText(text, fontConfiguration, null, ZERO, ZERO); } -// public static AtomText createHeading(String text, FontConfiguration fontConfiguration, int order) { -// fontConfiguration = FOO(fontConfiguration, order); -// return new AtomText(text, fontConfiguration, null, ZERO, ZERO); -// } - public static Atom createUrl(Url url, FontConfiguration fontConfiguration, ISkinSimple skinSimple) { fontConfiguration = fontConfiguration.hyperlink(); final Display display = Display.getWithNewlines(url.getLabel()); diff --git a/src/net/sourceforge/plantuml/cucadiagram/Bodier.java b/src/net/sourceforge/plantuml/cucadiagram/Bodier.java index c2e88142999..c91716f9303 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/Bodier.java +++ b/src/net/sourceforge/plantuml/cucadiagram/Bodier.java @@ -35,206 +35,28 @@ */ package net.sourceforge.plantuml.cucadiagram; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Set; import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.ISkinParam; -import net.sourceforge.plantuml.StringUtils; -import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.TextBlock; -import net.sourceforge.plantuml.graphic.TextBlockLineBefore; -import net.sourceforge.plantuml.graphic.TextBlockUtils; -import net.sourceforge.plantuml.skin.VisibilityModifier; -public class Bodier { +public interface Bodier { - private final List rawBody = new ArrayList(); - private final Set hides; - private LeafType type; - private List methodsToDisplay; - private List fieldsToDisplay; - private final boolean manageModifier; - private ILeaf leaf; + public void setLeaf(ILeaf leaf); - public void muteClassToObject() { - methodsToDisplay = null; - fieldsToDisplay = null; - type = LeafType.OBJECT; - } + public List getFieldsToDisplay(); - public Bodier(LeafType type, Set hides) { - this.hides = hides; - this.type = type; - this.manageModifier = type == null ? false : type.manageModifier(); - } + public List getMethodsToDisplay(); - public void setLeaf(ILeaf leaf) { - if (leaf == null) { - throw new IllegalArgumentException(); - } - this.leaf = leaf; + public void addFieldOrMethod(String s); - } + public TextBlock getBody(FontParam fontParam, ISkinParam skinParam, boolean showMethods, boolean showFields, + Stereotype stereotype); - public void addFieldOrMethod(String s, IEntity leaf) { - if (leaf == null) { - throw new IllegalArgumentException(); - } - // Empty cache - methodsToDisplay = null; - fieldsToDisplay = null; - rawBody.add(s); - if (leaf instanceof ILeaf) { - if (this.leaf != null && this.leaf != leaf) { - throw new IllegalArgumentException(); - } - this.leaf = (ILeaf) leaf; - } - } + public List getRawBody(); - private boolean isBodyEnhanced() { - for (String s : rawBody) { - if (BodyEnhanced.isBlockSeparator(s)) { - return true; - } - } - return false; - } - - private boolean isMethod(String s) { - if (type == LeafType.ANNOTATION || type == LeafType.ABSTRACT_CLASS || type == LeafType.CLASS - || type == LeafType.INTERFACE || type == LeafType.ENUM) { - return Member.isMethod(s); - } - return false; - } - - public List getMethodsToDisplay() { - if (methodsToDisplay == null) { - methodsToDisplay = new ArrayList(); - for (int i = 0; i < rawBody.size(); i++) { - final String s = rawBody.get(i); - if (isMethod(i, rawBody) == false) { - continue; - } - if (s.length() == 0 && methodsToDisplay.size() == 0) { - continue; - } - final Member m = new Member(s, true, manageModifier); - if (hides == null || hides.contains(m.getVisibilityModifier()) == false) { - methodsToDisplay.add(m); - } - } - removeFinalEmptyMembers(methodsToDisplay); - } - return Collections.unmodifiableList(methodsToDisplay); - } - - private boolean isMethod(int i, List rawBody) { - if (i > 0 && i < rawBody.size() - 1 && rawBody.get(i).length() == 0 && isMethod(rawBody.get(i - 1)) - && isMethod(rawBody.get(i + 1))) { - return true; - } - return isMethod(rawBody.get(i)); - } - - public List getFieldsToDisplay() { - if (fieldsToDisplay == null) { - fieldsToDisplay = new ArrayList(); - for (String s : rawBody) { - if (isMethod(s) == true) { - continue; - } - if (s.length() == 0 && fieldsToDisplay.size() == 0) { - continue; - } - final Member m = new Member(s, false, manageModifier); - if (hides == null || hides.contains(m.getVisibilityModifier()) == false) { - fieldsToDisplay.add(m); - } - } - removeFinalEmptyMembers(fieldsToDisplay); - } - return Collections.unmodifiableList(fieldsToDisplay); - } - - private void removeFinalEmptyMembers(List result) { - while (result.size() > 0 && StringUtils.trin(result.get(result.size() - 1).getDisplay(false)).length() == 0) { - result.remove(result.size() - 1); - } - } - - public boolean hasUrl() { - for (Member m : getFieldsToDisplay()) { - if (m.hasUrl()) { - return true; - } - } - for (Member m : getMethodsToDisplay()) { - if (m.hasUrl()) { - return true; - } - } - return false; - } - - private List rawBodyWithoutHidden() { - if (hides == null || hides.size() == 0) { - return rawBody; - } - final List result = new ArrayList(); - for (String s : rawBody) { - final Member m = new Member(s, isMethod(s), manageModifier); - if (hides.contains(m.getVisibilityModifier()) == false) { - result.add(s); - } - - } - return result; - } - - public TextBlock getBody(final FontParam fontParam, final ISkinParam skinParam, final boolean showMethods, - final boolean showFields, Stereotype stereotype) { - if (type.isLikeClass() && isBodyEnhanced()) { - if (showMethods || showFields) { - return new BodyEnhanced(rawBodyWithoutHidden(), fontParam, skinParam, manageModifier, stereotype, leaf); - } - return null; - } - if (leaf == null) { - throw new IllegalStateException(); - } - final MethodsOrFieldsArea fields = new MethodsOrFieldsArea(getFieldsToDisplay(), fontParam, skinParam, - stereotype, leaf); - if (type == LeafType.OBJECT) { - if (showFields == false) { - return new TextBlockLineBefore(TextBlockUtils.empty(0, 0)); - } - return fields.asBlockMemberImpl(); - } - if (type.isLikeClass() == false) { - throw new UnsupportedOperationException(); - } - final MethodsOrFieldsArea methods = new MethodsOrFieldsArea(getMethodsToDisplay(), fontParam, skinParam, - stereotype, leaf); - if (showFields && showMethods == false) { - return fields.asBlockMemberImpl(); - } else if (showMethods && showFields == false) { - return methods.asBlockMemberImpl(); - } else if (showFields == false && showMethods == false) { - return TextBlockUtils.empty(0, 0); - } - - final TextBlock bb1 = fields.asBlockMemberImpl(); - final TextBlock bb2 = methods.asBlockMemberImpl(); - return TextBlockUtils.mergeTB(bb1, bb2, HorizontalAlignment.LEFT); - } - - public List getRawBody() { - return Collections.unmodifiableList(rawBody); - } + public void muteClassToObject(); + public boolean hasUrl(); } diff --git a/src/net/sourceforge/plantuml/cucadiagram/BodierImpl.java b/src/net/sourceforge/plantuml/cucadiagram/BodierImpl.java new file mode 100644 index 00000000000..fec9b01cec9 --- /dev/null +++ b/src/net/sourceforge/plantuml/cucadiagram/BodierImpl.java @@ -0,0 +1,243 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.cucadiagram; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import net.sourceforge.plantuml.FontParam; +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.StringUtils; +import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.graphic.TextBlockLineBefore; +import net.sourceforge.plantuml.graphic.TextBlockUtils; +import net.sourceforge.plantuml.skin.VisibilityModifier; + +public class BodierImpl implements Bodier { + + private final List rawBody = new ArrayList(); + private final Set hides; + private LeafType type; + private List methodsToDisplay; + private List fieldsToDisplay; + private final boolean manageModifier; + private ILeaf leaf; + + public void muteClassToObject() { + methodsToDisplay = null; + fieldsToDisplay = null; + type = LeafType.OBJECT; + } + + public BodierImpl(LeafType type, Set hides) { + if (type == LeafType.MAP) { + throw new IllegalArgumentException(); + } + this.hides = hides; + this.type = type; + this.manageModifier = type == null ? false : type.manageModifier(); + } + + public void setLeaf(ILeaf leaf) { + if (leaf == null) { + throw new IllegalArgumentException(); + } + this.leaf = leaf; + + } + + public void addFieldOrMethod(String s) { +// if (leaf == null) { +// throw new IllegalArgumentException(); +// } + // Empty cache + methodsToDisplay = null; + fieldsToDisplay = null; + rawBody.add(s); +// if (leaf instanceof ILeaf) { +// if (this.leaf != null && this.leaf != leaf) { +// throw new IllegalArgumentException(); +// } +// this.leaf = (ILeaf) leaf; +// } + } + + private boolean isBodyEnhanced() { + for (String s : rawBody) { + if (BodyEnhanced.isBlockSeparator(s)) { + return true; + } + } + return false; + } + + private boolean isMethod(String s) { + if (type == LeafType.ANNOTATION || type == LeafType.ABSTRACT_CLASS || type == LeafType.CLASS + || type == LeafType.INTERFACE || type == LeafType.ENUM) { + return Member.isMethod(s); + } + return false; + } + + public List getMethodsToDisplay() { + if (methodsToDisplay == null) { + methodsToDisplay = new ArrayList(); + for (int i = 0; i < rawBody.size(); i++) { + final String s = rawBody.get(i); + if (isMethod(i, rawBody) == false) { + continue; + } + if (s.length() == 0 && methodsToDisplay.size() == 0) { + continue; + } + final Member m = new Member(s, true, manageModifier); + if (hides == null || hides.contains(m.getVisibilityModifier()) == false) { + methodsToDisplay.add(m); + } + } + removeFinalEmptyMembers(methodsToDisplay); + } + return Collections.unmodifiableList(methodsToDisplay); + } + + private boolean isMethod(int i, List rawBody) { + if (i > 0 && i < rawBody.size() - 1 && rawBody.get(i).length() == 0 && isMethod(rawBody.get(i - 1)) + && isMethod(rawBody.get(i + 1))) { + return true; + } + return isMethod(rawBody.get(i)); + } + + public List getFieldsToDisplay() { + if (fieldsToDisplay == null) { + fieldsToDisplay = new ArrayList(); + for (String s : rawBody) { + if (isMethod(s) == true) { + continue; + } + if (s.length() == 0 && fieldsToDisplay.size() == 0) { + continue; + } + final Member m = new Member(s, false, manageModifier); + if (hides == null || hides.contains(m.getVisibilityModifier()) == false) { + fieldsToDisplay.add(m); + } + } + removeFinalEmptyMembers(fieldsToDisplay); + } + return Collections.unmodifiableList(fieldsToDisplay); + } + + private void removeFinalEmptyMembers(List result) { + while (result.size() > 0 && StringUtils.trin(result.get(result.size() - 1).getDisplay(false)).length() == 0) { + result.remove(result.size() - 1); + } + } + + public boolean hasUrl() { + for (Member m : getFieldsToDisplay()) { + if (m.hasUrl()) { + return true; + } + } + for (Member m : getMethodsToDisplay()) { + if (m.hasUrl()) { + return true; + } + } + return false; + } + + private List rawBodyWithoutHidden() { + if (hides == null || hides.size() == 0) { + return rawBody; + } + final List result = new ArrayList(); + for (String s : rawBody) { + final Member m = new Member(s, isMethod(s), manageModifier); + if (hides.contains(m.getVisibilityModifier()) == false) { + result.add(s); + } + + } + return result; + } + + public TextBlock getBody(final FontParam fontParam, final ISkinParam skinParam, final boolean showMethods, + final boolean showFields, Stereotype stereotype) { + if (type.isLikeClass() && isBodyEnhanced()) { + if (showMethods || showFields) { + return new BodyEnhanced(rawBodyWithoutHidden(), fontParam, skinParam, manageModifier, stereotype, leaf); + } + return null; + } + if (leaf == null) { + throw new IllegalStateException(); + } + final MethodsOrFieldsArea fields = new MethodsOrFieldsArea(getFieldsToDisplay(), fontParam, skinParam, + stereotype, leaf); + if (type == LeafType.OBJECT) { + if (showFields == false) { + return new TextBlockLineBefore(TextBlockUtils.empty(0, 0)); + } + return fields.asBlockMemberImpl(); + } + if (type.isLikeClass() == false) { + throw new UnsupportedOperationException(); + } + final MethodsOrFieldsArea methods = new MethodsOrFieldsArea(getMethodsToDisplay(), fontParam, skinParam, + stereotype, leaf); + if (showFields && showMethods == false) { + return fields.asBlockMemberImpl(); + } else if (showMethods && showFields == false) { + return methods.asBlockMemberImpl(); + } else if (showFields == false && showMethods == false) { + return TextBlockUtils.empty(0, 0); + } + + final TextBlock bb1 = fields.asBlockMemberImpl(); + final TextBlock bb2 = methods.asBlockMemberImpl(); + return TextBlockUtils.mergeTB(bb1, bb2, HorizontalAlignment.LEFT); + } + + public List getRawBody() { + return Collections.unmodifiableList(rawBody); + } + +} diff --git a/src/net/sourceforge/plantuml/cucadiagram/BodierMap.java b/src/net/sourceforge/plantuml/cucadiagram/BodierMap.java new file mode 100644 index 00000000000..af4d5139ae5 --- /dev/null +++ b/src/net/sourceforge/plantuml/cucadiagram/BodierMap.java @@ -0,0 +1,112 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.cucadiagram; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import net.sourceforge.plantuml.FontParam; +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.graphic.TextBlock; + +public class BodierMap implements Bodier { + + private final List rawBody = new ArrayList(); + private final Map map = new LinkedHashMap(); + private ILeaf leaf; + + public void muteClassToObject() { + throw new UnsupportedOperationException(); + } + + public BodierMap() { + } + + public void setLeaf(ILeaf leaf) { + if (leaf == null) { + throw new IllegalArgumentException(); + } + this.leaf = leaf; + + } + + public static String getLinkedEntry(String s) { + final Pattern p = Pattern.compile("(\\*-+\\>)"); + final Matcher m = p.matcher(s); + if (m.find()) { + return m.group(1); + } + return null; + } + + public void addFieldOrMethod(String s) { + if (s.contains("=>")) { + final int x = s.indexOf("=>"); + map.put(s.substring(0, x).trim(), s.substring(x + 2).trim()); + } else if (getLinkedEntry(s) != null) { + final String link = getLinkedEntry(s); + final int x = s.indexOf(link); + map.put(s.substring(0, x).trim(), "\0"); + } + } + + public List getMethodsToDisplay() { + throw new UnsupportedOperationException(); + } + + public List getFieldsToDisplay() { + throw new UnsupportedOperationException(); + } + + public boolean hasUrl() { + return false; + } + + public TextBlock getBody(FontParam fontParam, ISkinParam skinParam, final boolean showMethods, + final boolean showFields, Stereotype stereotype) { + return new TextBlockMap(fontParam, skinParam, map); + } + + public List getRawBody() { + return Collections.unmodifiableList(rawBody); + } + +} diff --git a/src/net/sourceforge/plantuml/cucadiagram/BodyEnhanced.java b/src/net/sourceforge/plantuml/cucadiagram/BodyEnhanced.java index a1fef7abd75..0326421872e 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/BodyEnhanced.java +++ b/src/net/sourceforge/plantuml/cucadiagram/BodyEnhanced.java @@ -166,7 +166,7 @@ private TextBlock getArea(StringBounder stringBounder) { } members = new ArrayList(); final List allTree = buildAllTree(s, it); - final TextBlock bloc = Display.create(allTree).create(fontParam.getFontConfiguration(skinParam), + final TextBlock bloc = Display.create(allTree).create7(fontParam.getFontConfiguration(skinParam), align, skinParam, CreoleMode.FULL); blocks.add(bloc); } else { diff --git a/src/net/sourceforge/plantuml/cucadiagram/BodyEnhanced2.java b/src/net/sourceforge/plantuml/cucadiagram/BodyEnhanced2.java index e13d4e21bb9..4199147c432 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/BodyEnhanced2.java +++ b/src/net/sourceforge/plantuml/cucadiagram/BodyEnhanced2.java @@ -124,7 +124,7 @@ private TextBlock getArea(StringBounder stringBounder) { } private TextBlock getTextBlock(Display members2, StringBounder stringBounder) { - final TextBlock result = members2.create(titleConfig, align, spriteContainer, lineBreakStrategy); + final TextBlock result = members2.create9(titleConfig, align, spriteContainer, lineBreakStrategy); return result; } diff --git a/src/net/sourceforge/plantuml/cucadiagram/Display.java b/src/net/sourceforge/plantuml/cucadiagram/Display.java index ef1fa872a13..0e235f473d5 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/Display.java +++ b/src/net/sourceforge/plantuml/cucadiagram/Display.java @@ -446,33 +446,33 @@ public static boolean isNull(Display display) { public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, ISkinSimple spriteContainer) { - return create(fontConfiguration, horizontalAlignment, spriteContainer, CreoleMode.FULL); + return create7(fontConfiguration, horizontalAlignment, spriteContainer, CreoleMode.FULL); } public TextBlock createWithNiceCreoleMode(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, ISkinSimple spriteContainer) { - return create(fontConfiguration, horizontalAlignment, spriteContainer, defaultCreoleMode); + return create7(fontConfiguration, horizontalAlignment, spriteContainer, defaultCreoleMode); } - public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, + public TextBlock create7(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, ISkinSimple spriteContainer, CreoleMode creoleMode) { - return create(fontConfiguration, horizontalAlignment, spriteContainer, LineBreakStrategy.NONE, creoleMode, null, - null); + return create0(fontConfiguration, horizontalAlignment, spriteContainer, LineBreakStrategy.NONE, creoleMode, + null, null); } - public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, + public TextBlock create8(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, ISkinSimple spriteContainer, CreoleMode modeSimpleLine, LineBreakStrategy maxMessageSize) { - return create(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize, modeSimpleLine, null, + return create0(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize, modeSimpleLine, null, null); } - public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, + public TextBlock create9(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, ISkinSimple spriteContainer, LineBreakStrategy maxMessageSize) { - return create(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize, defaultCreoleMode, null, + return create0(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize, defaultCreoleMode, null, null); } - public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, + public TextBlock create0(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, ISkinSimple spriteContainer, LineBreakStrategy maxMessageSize, CreoleMode creoleMode, UFont fontForStereotype, HColor htmlColorForStereotype) { if (maxMessageSize == null) { @@ -528,8 +528,8 @@ private TextBlock getCreole(FontConfiguration fontConfiguration, HorizontalAlign FontConfiguration stereotypeConfiguration) { final Sheet sheet = new CreoleParser(fontConfiguration, horizontalAlignment, spriteContainer, creoleMode, stereotypeConfiguration).createSheet(this); - final SheetBlock1 sheetBlock1 = new SheetBlock1(sheet, maxMessageSize, - spriteContainer == null ? 0 : spriteContainer.getPadding()); + final double padding = spriteContainer == null ? 0 : spriteContainer.getPadding(); + final SheetBlock1 sheetBlock1 = new SheetBlock1(sheet, maxMessageSize, padding); return new SheetBlock2(sheetBlock1, sheetBlock1, new UStroke(1.5)); } diff --git a/src/net/sourceforge/plantuml/cucadiagram/GroupRoot.java b/src/net/sourceforge/plantuml/cucadiagram/GroupRoot.java index b76d83e9180..92fee6cd14e 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/GroupRoot.java +++ b/src/net/sourceforge/plantuml/cucadiagram/GroupRoot.java @@ -282,4 +282,8 @@ public DisplayPositionned getLegend() { public Ident getIdent() { return Ident.empty(); } + + public boolean isAloneAndUnlinked() { + throw new UnsupportedOperationException(); + } } diff --git a/src/net/sourceforge/plantuml/cucadiagram/HideOrShow2.java b/src/net/sourceforge/plantuml/cucadiagram/HideOrShow2.java index 066412306b4..f18d1097cfd 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/HideOrShow2.java +++ b/src/net/sourceforge/plantuml/cucadiagram/HideOrShow2.java @@ -40,6 +40,11 @@ public class HideOrShow2 { private final String what; private final boolean show; + @Override + public String toString() { + return what + " (" + show + ")"; + } + private boolean isApplyable(ILeaf leaf) { if (what.startsWith("$")) { return isApplyableTag(leaf, what.substring(1)); @@ -47,11 +52,21 @@ private boolean isApplyable(ILeaf leaf) { if (what.startsWith("<<") && what.endsWith(">>")) { return isApplyableStereotype(leaf, what.substring(2, what.length() - 2).trim()); } + if (what.equalsIgnoreCase("@unlinked")) { + return isApplyableUnlinked(leaf); + } final String fullName = leaf.getCodeGetName(); // System.err.println("fullName=" + fullName); return match(fullName, what); } + private boolean isApplyableUnlinked(ILeaf leaf) { + if (leaf.isAloneAndUnlinked()) { + return true; + } + return false; + } + private boolean isApplyableStereotype(ILeaf leaf, String pattern) { final Stereotype stereotype = leaf.getStereotype(); if (stereotype == null) { diff --git a/src/net/sourceforge/plantuml/cucadiagram/IEntity.java b/src/net/sourceforge/plantuml/cucadiagram/IEntity.java index 253dc29c800..19c9d82c0e9 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/IEntity.java +++ b/src/net/sourceforge/plantuml/cucadiagram/IEntity.java @@ -94,5 +94,8 @@ public interface IEntity extends SpecificBackcolorable, Hideable, Removeable, Li public void addStereotag(Stereotag tag); public Set stereotags(); + + public boolean isAloneAndUnlinked(); + } diff --git a/src/net/sourceforge/plantuml/cucadiagram/LeafType.java b/src/net/sourceforge/plantuml/cucadiagram/LeafType.java index 53a149c01e4..f37e10ff444 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/LeafType.java +++ b/src/net/sourceforge/plantuml/cucadiagram/LeafType.java @@ -41,7 +41,7 @@ public enum LeafType { EMPTY_PACKAGE, - ABSTRACT_CLASS, CLASS, INTERFACE, ANNOTATION, LOLLIPOP_FULL, LOLLIPOP_HALF, NOTE, TIPS, OBJECT, ASSOCIATION, ENUM, CIRCLE, + ABSTRACT_CLASS, CLASS, INTERFACE, ANNOTATION, LOLLIPOP_FULL, LOLLIPOP_HALF, NOTE, TIPS, OBJECT, MAP, ASSOCIATION, ENUM, CIRCLE, USECASE, diff --git a/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java b/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java index 0503a7b31ec..3a1a219785c 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java +++ b/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java @@ -166,7 +166,7 @@ private TextBlock createTextBlock(Member m) { if (m.isStatic()) { config = config.underline(); } - TextBlock bloc = Display.getWithNewlines(s).create(config, align, skinParam, CreoleMode.SIMPLE_LINE, + TextBlock bloc = Display.getWithNewlines(s).create8(config, align, skinParam, CreoleMode.SIMPLE_LINE, skinParam.wrapWidth()); bloc = TextBlockUtils.fullInnerPosition(bloc, m.getDisplay(false)); return new TextBlockTracer(m, bloc); diff --git a/src/net/sourceforge/plantuml/cucadiagram/TextBlockMap.java b/src/net/sourceforge/plantuml/cucadiagram/TextBlockMap.java new file mode 100644 index 00000000000..4e0fea1f0dc --- /dev/null +++ b/src/net/sourceforge/plantuml/cucadiagram/TextBlockMap.java @@ -0,0 +1,210 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.cucadiagram; + +import java.awt.geom.Dimension2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.FontParam; +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.graphic.AbstractTextBlock; +import net.sourceforge.plantuml.graphic.FontConfiguration; +import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.graphic.TextBlockUtils; +import net.sourceforge.plantuml.svek.Ports; +import net.sourceforge.plantuml.svek.WithPorts; +import net.sourceforge.plantuml.ugraphic.UChangeBackColor; +import net.sourceforge.plantuml.ugraphic.UChangeColor; +import net.sourceforge.plantuml.ugraphic.UEllipse; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.ULine; +import net.sourceforge.plantuml.ugraphic.UShape; +import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.color.HColor; + +public class TextBlockMap extends AbstractTextBlock implements WithPorts { + + private final FontParam fontParam; + private final ISkinParam skinParam; + private final Map blocksMap = new LinkedHashMap(); + private final List keys = new ArrayList(); + private double totalWidth; + + public TextBlockMap(FontParam fontParam, ISkinParam skinParam, Map map) { + this.fontParam = fontParam; + this.skinParam = skinParam; + for (Map.Entry ent : map.entrySet()) { + final String key = ent.getKey(); + this.keys.add(key); + final String value = ent.getValue(); + final TextBlock block1 = getTextBlock(key); + final TextBlock block2 = getTextBlock(value); + this.blocksMap.put(block1, block2); + } + } + + public Ports getPorts(StringBounder stringBounder) { + final Ports ports = new Ports(); + int i = 0; + double y = 0; + for (Map.Entry ent : blocksMap.entrySet()) { + final TextBlock key = ent.getKey(); + final TextBlock value = ent.getValue(); + final double height = getHeightOfRow(stringBounder, key, value); + ports.add(keys.get(i), y, height); + y += height; + i++; + } + return ports; + } + + public Dimension2D calculateDimension(StringBounder stringBounder) { + return new Dimension2DDouble(getWidthColA(stringBounder) + getWidthColB(stringBounder), + getTotalHeight(stringBounder)); + } + + private double getWidthColA(StringBounder stringBounder) { + return getMaxWidth(stringBounder, blocksMap.keySet()); + } + + private double getWidthColB(StringBounder stringBounder) { + return getMaxWidth(stringBounder, blocksMap.values()); + } + + private double getMaxWidth(StringBounder stringBounder, Collection blocks) { + double width = 0; + for (TextBlock block : blocks) { + width = Math.max(width, block.calculateDimension(stringBounder).getWidth()); + } + return width; + } + + public void drawU(final UGraphic ug) { + final StringBounder stringBounder = ug.getStringBounder(); + final Dimension2D fullDim = calculateDimension(stringBounder); + final double trueWidth = Math.max(fullDim.getWidth(), totalWidth); + final double widthColA = getWidthColA(stringBounder); + final double widthColB = getWidthColB(stringBounder); + double y = 0; + for (Map.Entry ent : blocksMap.entrySet()) { + final TextBlock key = ent.getKey(); + final TextBlock value = ent.getValue(); + final UGraphic ugline = ug.apply(UTranslate.dy(y)); + ugline.draw(ULine.hline(trueWidth)); + final double heightOfRow = getHeightOfRow(stringBounder, key, value); + if (value instanceof Point) { +// final Dimension2D dimPoint = value.calculateDimension(stringBounder); +// final double xp = widthColA + (widthColB - dimPoint.getWidth()) / 2; +// final double yp = (heightOfRow - dimPoint.getHeight()) / 2; +// value.drawU(ugline.apply(new UTranslate(xp, yp))); + final double posColA = (trueWidth - key.calculateDimension(stringBounder).getWidth()) / 2; + key.drawU(ugline.apply(UTranslate.dx(posColA))); + } else { + final double posColA = (widthColA - key.calculateDimension(stringBounder).getWidth()) / 2; + key.drawU(ugline.apply(UTranslate.dx(posColA))); + value.drawU(ugline.apply(UTranslate.dx(widthColA))); + ugline.apply(UTranslate.dx(widthColA)).draw(ULine.vline(heightOfRow)); + } + y += heightOfRow; + } + // ug.apply(UTranslate.dx(widthColA)).draw(ULine.vline(fullDim.getHeight())); + } + + private double getTotalHeight(StringBounder stringBounder) { + double height = 0; + for (Map.Entry ent : blocksMap.entrySet()) { + final TextBlock key = ent.getKey(); + final TextBlock value = ent.getValue(); + height += getHeightOfRow(stringBounder, key, value); + } + return height; + } + + private double getHeightOfRow(StringBounder stringBounder, TextBlock key, TextBlock value) { + return Math.max(key.calculateDimension(stringBounder).getHeight(), + value.calculateDimension(stringBounder).getHeight()); + } + + private TextBlock getTextBlock(String key) { + if (key.equals("\0")) { + return new Point(getFontConfiguration().getColor()); + } + final Display display = Display.getWithNewlines(key); + TextBlock result = display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam); + result = TextBlockUtils.withMargin(result, 5, 2); + return result; + } + + static class Point extends AbstractTextBlock { + + private final HColor color; + + public Point(HColor color) { + this.color = color; + } + + public Dimension2D calculateDimension(StringBounder stringBounder) { + return new Dimension2DDouble(getDiameter(), getDiameter()); + } + + public void drawU(UGraphic ug) { + final UShape point = new UEllipse(getDiameter(), getDiameter()); + ug = ug.apply(new UChangeColor(color)).apply(new UChangeBackColor(color)); + ug.draw(point); + } + + private double getDiameter() { + return 7; + } + + } + + private FontConfiguration getFontConfiguration() { + return new FontConfiguration(skinParam, fontParam, null); + } + + public void setTotalWidth(double totalWidth) { + this.totalWidth = totalWidth; + } + +} diff --git a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java index 6f5a99c2580..86312179968 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java +++ b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java @@ -46,6 +46,7 @@ import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.Log; +import net.sourceforge.plantuml.OptionFlags; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.vizjs.GraphvizJs; import net.sourceforge.plantuml.vizjs.VizJsEngine; @@ -139,6 +140,14 @@ public static int getenvImageLimit() { return 4096; } + public static boolean getJavascriptUnsecure() { + final String env = getenv("PLANTUML_JAVASCRIPT_UNSECURE"); + if ("true".equalsIgnoreCase(env)) { + return true; + } + return OptionFlags.ALLOW_INCLUDE; + } + public static String getenvDefaultConfigFilename() { return getenv("PLANTUML_DEFAULT_CONFIG_FILENAME"); } diff --git a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityFactory.java b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityFactory.java index cf879417946..0e86ea8396c 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityFactory.java +++ b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityFactory.java @@ -50,6 +50,8 @@ import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.creole.CreoleMode; import net.sourceforge.plantuml.cucadiagram.Bodier; +import net.sourceforge.plantuml.cucadiagram.BodierImpl; +import net.sourceforge.plantuml.cucadiagram.BodierMap; import net.sourceforge.plantuml.cucadiagram.Code; import net.sourceforge.plantuml.cucadiagram.CucaDiagram; import net.sourceforge.plantuml.cucadiagram.Display; @@ -82,7 +84,7 @@ public final class EntityFactory { private final IGroup rootGroup = new GroupRoot(this); private final SuperGroup rootSuperGroup = new SuperGroup(rootGroup); - + private final List hides2; private final List removed; /* private */ final public CucaDiagram namespaceSeparator; @@ -216,7 +218,7 @@ public ILeaf createLeaf(Ident ident, Code code, Display display, LeafType entity if (entityType == null) { throw new IllegalArgumentException(); } - final Bodier bodier = new Bodier(entityType, hides); + final Bodier bodier = entityType == LeafType.MAP ? new BodierMap() : new BodierImpl(entityType, hides); final EntityImpl result = new EntityImpl(ident, code, this, bodier, parentContainer, entityType, namespaceSeparator, rawLayout); bodier.setLeaf(result); @@ -229,7 +231,7 @@ public IGroup createGroup(Ident ident, Code code, Display display, Code namespac if (groupType == null) { throw new IllegalArgumentException(); } - final Bodier bodier = new Bodier(null, hides); + final Bodier bodier = new BodierImpl(null, hides); final EntityImpl result = new EntityImpl(ident, code, this, bodier, parentContainer, groupType, namespace, namespaceSeparator, rawLayout); if (Display.isNull(display) == false) { @@ -511,5 +513,4 @@ public IGroup getParentContainer(Ident ident, IGroup parentContainer) { return parentContainer; } - } diff --git a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java index fb8dd611e54..0381f6085e4 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java +++ b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java @@ -661,6 +661,18 @@ private boolean isRemovedInternal() { return entityFactory.isRemoved(this); } + public boolean isAloneAndUnlinked() { + if (isGroup()) { + return false; + } + for (Link link : entityFactory.getLinks()) { + if (link.contains(this) && link.getType().isInvisible() == false) { + return false; + } + } + return true; + } + private int layer; public int getHectorLayer() { diff --git a/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementFull.java b/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementFull.java index 94608d321cd..f9a80895a13 100644 --- a/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementFull.java +++ b/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementFull.java @@ -43,6 +43,7 @@ import net.sourceforge.plantuml.UrlBuilder; import net.sourceforge.plantuml.UrlBuilder.ModeUrl; import net.sourceforge.plantuml.classdiagram.AbstractEntityDiagram; +import net.sourceforge.plantuml.classdiagram.command.CommandCreateClassMultilines; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.SingleLineCommand2; import net.sourceforge.plantuml.command.regex.IRegex; @@ -57,6 +58,7 @@ import net.sourceforge.plantuml.cucadiagram.ILeaf; import net.sourceforge.plantuml.cucadiagram.Ident; import net.sourceforge.plantuml.cucadiagram.LeafType; +import net.sourceforge.plantuml.cucadiagram.Stereotag; import net.sourceforge.plantuml.cucadiagram.Stereotype; import net.sourceforge.plantuml.descdiagram.DescriptionDiagram; import net.sourceforge.plantuml.graphic.USymbol; @@ -120,6 +122,8 @@ private static IRegex getRegexConcat() { new RegexLeaf("STEREOTYPE", "(\\<\\<.+\\>\\>)") // )), // RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("TAGS", Stereotag.pattern() + "?"), // + RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), // RegexLeaf.spaceZeroOrMore(), // color().getRegex(), RegexLeaf.end()); @@ -215,6 +219,7 @@ protected CommandExecutionResult executeArg(DescriptionDiagram diagram, LineLoca .getSkinParam().getFont(null, false, FontParam.CIRCLED_CHARACTER), diagram.getSkinParam() .getIHtmlColorSet())); } + CommandCreateClassMultilines.addTags(entity, arg.get("TAGS", 0)); final String urlString = arg.get("URL", 0); if (urlString != null) { diff --git a/src/net/sourceforge/plantuml/donors/PSystemDonors.java b/src/net/sourceforge/plantuml/donors/PSystemDonors.java index 2846dbfe9e7..19906ebe3c1 100644 --- a/src/net/sourceforge/plantuml/donors/PSystemDonors.java +++ b/src/net/sourceforge/plantuml/donors/PSystemDonors.java @@ -71,24 +71,25 @@ public class PSystemDonors extends AbstractPSystem { private static final int COLS = 6; private static final int FREE_LINES = 6; - public static final String DONORS = "6taA0AmEU9ELAujmujswMQFg3ojH8OBbUK9n65Z4qzs0-0FSEptkDz9VH5UwzqqpeYr_pV7pZA4O27ey" - + "VrqDs_nl3nxxgV8W-Ev2KDA92uXiAx7-a7f_TK3C5DrlcT3URXqNwk24ckSZ-BYouVtDS9vl6X-zz0nO" - + "GjLFqNtj_qrTPLrULOLPkblL-UWAbR5LkrbpkljHu8ues7Seq23Kc4vTN8T3LOUvTgAlJemGOEAT4tpR" - + "jPWLenuY9LKtjY0b1YDqjqdhb-GN6RN_g1VGfhrSKo9dGddC4ecksqg7znrqFolvvOW7Nx19O06L7E4J" - + "5Brjn934UT3GEPlHsCAHBKy2C6IWZNtuHr4SAPwIcMreaIIaG4dAjt40CYfrQn6pvSs0yfxHObYJXCxt" - + "Xt3VE4och3feU0Wi4Yof3Qefo9lG4pxLLrqoEET3KSLVVflairaCD2XR0kJDZBw5HvD4-Py-aFdyRbBR" - + "FAMnrNNC_puSYg8fiuRVz3PgEO9xVrb8mU920SeHwAK-KKb-Vyg-iH23S6sb5z8njrr9emYNR4YhM9UV" - + "Oearwz-wnCQcnRBSMBIF_nTyKpBG4YkHPEXjMlbaxNoXf6bglB_arT3vRc9Dtapl6Ar7wPpc_tV3Iise" - + "X85ETp7AT4EWs8o6QgXPc0XC2zqS2XCW3w3sDBdbJwilyMkV8FEc4ed8RRZqWB_-JAvouS9KhEds9cO0" - + "auUKUf8aBOXGrY7eIQ1K8sKH-XacBTEMZedxf0qUfysCWH_LCSL9-6aXS7N3l9etMxkspp5RS8FlPJvr" - + "7zAuYkTqS-zv5wdv6mpeBIte4QanejZtial2LGCbihXB7XhYkuSTN3nqtu8pMRI16MsEGsP2vLeoQkaj" - + "HXcQTBubapNjrLPK6X1U7EFWZenEy7WZUQGMbqZYPZ2325i0qlhY4xiauSw4gbjkTZRN5gODNxq8BS7l" - + "Kfd0KeKNdYxiwEv-SKPZ5DadvhqoUsayfXGV2wYIKmLLQQFqcLBaQMiP6JBMe6Uz3R3BgMuB-3O_rR1E" - + "ABojejCM6tIRGeQhX6yqYYTg5UqQkDYaC82lUNaAdZRMGSPtUbb7722RIq885Lfp-0UdfR7w22rblKN_" - + "jstRoyhvy-zrP0MdddZcLGNG8qZpVpzble15h-jx6_fMvLCUs06pnP0UR2rM7b1w9v3KO1-biugwDCs8" - + "htX7kKLjqSgF3vN_wNIFM4m7tx3yefeYdxx4QRQzD9nAqdtV5ukJ73R-AQhCokIgrAg94Tt4Te_YF8sT" - + "Podkkde54lIEImNkdhhUJjDyIf_p1QM7uOeXFn-H8PlghWMra9RZjC0sSTRtPhOXcUf_IGy-2RLrdDN3" - + "qC7sRt8NQFRjJMxS40K6HVo1WNtsc9CJ5CSR0kt6r1rfkPYoSz4ztIuMhB7Vz8_8ieG_B6kLYJ3NowrO" + "B0lnh6sq0m00"; + public static final String DONORS = "6yOA0AmEU9ELAujmujswMQFg3ojH8OBbUK9n65Z4qzs0-0FSEptkDz9VH5UwzqqpeYr_pV7p3A4OY7ey" + + "VrqDs_nl3nw_gV8W-DyBGKadBY2ohSIweUlD3WZJeVilasvFjuwB0W9KP3adE_G0tjyCv_ccyT5Bpu0b" + + "LFqKtTV-xt8YSVTG2BCqMu7Jfn7gnbPqZkNou-hIK-rEggXkLUMOJkKSmrMXKLuzyBM51faKxfhWsw75" + + "h1Zz42cPkh056QNHGq-Rj7v9tkYe_KUzWJOTqpLbv4meZrwYqVbOwSYsWUuN9By2oU0BCGqie98ZUe5Y" + + "juqQaYGF5hhcO3IsuSYM9o44yj21V_X7fJYIF2KpXs55aX829HdV9W18gzIZ1MUhcm7LUxB5Y2QfkjWV" + + "Xll7ONhAgOE6Hy0YnP8oG3K5UHDw8IVxh5iwPryLC_pbjqdkpHAWuR9bGDpCw5jyD4cC_zbJiu3VDMgB" + + "frIski_-Fqw78cdAhE4FhOroZX3U3mjXB6ujG3e2FTSd9icVJzat5k8GgQtqHhlExLV2AC8b7p9KhCjF" + + "iUGrvnzTScCpubaE5kCJ_8NOb0oqr9LACFI1LdsYTRx0QPeQdvUy6je_0wwfTxjtdDfBsPmL_tV3oioe" + + "141dkkW5tGWOcD6q6Xui80BJGjU6mWJ82jHsark-Mxqahds2uCsa9Agm4T8B_lfpESk5Yv3nfZkQc05C" + + "xrBAHPAsO8HcROAUHfLIj2n2lysaPjgqCNMVrC7ZhC4O-34TLxaOVbe8dCEmNYsQdStQvvX3S8llPJvr" + + "7yguYkzi2-y5Dwdv9WDsImjQHAgEgcnRsIt3MGE3MRmb3ms9tSDEBXwwVy6PBDh4Z3R78REXSZaPfVGH" + + "9pLDchyLoDhsQcUb1gIN82IucT4D7czD7gd59PAa6SmWnYQ0hBxun2v5k94mqIqlEvlh4A6rMBq8BUHt" + + "AKrWgQABI3TsTlS0dZ4zYkp3UI_CiJJMBknZ0RLaDq59EZ1wJs5vsfmWGyOQz6oq1dQwrB50BlrR3PiE" + + "XRTDTDQumSGKqbqb-c3H8j6eY6lenIU50tpDorFg6MCTT7odbmt60RA4902gC9iZlmGjZPUrQ1dhBVf_" + + "R5aEA-VFlzUHHKwzuvbt5K3FGKRy1odh4xgOTGDlmxnbDim13fZ9H4zskFBGqhk1f0NxIPrLr9LfHdB5" + + "1yijQOjQVdoe-jzEz-5YDlX651UbiBpxbA3PScW4bMBx_YyM9pam_YcgpCdagjIfYH4JOdj7SOfZnrvA" + + "kAvPWGQz4pA1jwUkjzCqTsbplg2CORW6vAT7fCacUsX1BKsRouN0Td7Mz-Qs9fdiVqcBVehMpdbM3yCd" + + "sx-fNQ3Xsvz2kw4K62uIDnpmqMDERf3CDnJQZQixod8nRUUY-uPT8jZ0VpC_8Wi9honhbOaov-7MSl5b" + + "8P6r7CZ1Mye-qnkiB_2gCW8oVM6E2G40"; /* * Special thanks to our sponsors and donors: diff --git a/src/net/sourceforge/plantuml/error/PSystemError.java b/src/net/sourceforge/plantuml/error/PSystemError.java index f08659d2298..526ce84122d 100644 --- a/src/net/sourceforge/plantuml/error/PSystemError.java +++ b/src/net/sourceforge/plantuml/error/PSystemError.java @@ -218,17 +218,17 @@ final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatO } else { udrawable = result; } - udrawable = addMessageCoronavirus(udrawable); -// final int min = (int) (System.currentTimeMillis() / 60000L) % 60; -// if (min == 1 || min == 8 || min == 13 || min == 55) { -// udrawable = addMessagePatreon(udrawable); -// } else if (min == 15) { -// udrawable = addMessageLiberapay(udrawable); -// } else if (min == 30 || min == 39 || min == 48) { -// udrawable = addMessageDedication(udrawable); -// } else if (getSource().containsIgnoreCase("arecibo")) { -// udrawable = addMessageArecibo(udrawable); -// } + final int min = (int) (System.currentTimeMillis() / 60000L) % 60; + // udrawable = addMessageAdopt(udrawable); + if (min == 1 || min == 8 || min == 13 || min == 55) { + udrawable = addMessagePatreon(udrawable); + } else if (min == 15) { + udrawable = addMessageLiberapay(udrawable); + } else if (min == 30 || min == 39 || min == 48) { + udrawable = addMessageDedication(udrawable); + } else if (getSource().containsIgnoreCase("arecibo")) { + udrawable = addMessageArecibo(udrawable); + } imageBuilder.setUDrawable(udrawable); final ImageData imageData = imageBuilder.writeImageTOBEMOVED(fileFormat, seed(), os); ((ImageDataAbstract) imageData).setStatus(FileImageData.ERROR); @@ -282,13 +282,6 @@ private TextBlock addMessagePatreon(final TextBlock source) throws IOException { return result; } - private TextBlock addMessageCoronavirus(final TextBlock source) throws IOException { - final TextBlock message = getMessageCoronavirus(); - TextBlock result = TextBlockUtils.mergeTB(message, source, HorizontalAlignment.LEFT); - result = TextBlockUtils.mergeTB(result, message, HorizontalAlignment.LEFT); - return result; - } - private TextBlock addMessageDedication(final TextBlock source) throws IOException { if (LicenseInfo.retrieveNamedOrDistributorQuickIsValid()) { return source; @@ -353,42 +346,6 @@ private TextBlockBackcolored getMessageAdopt() { } - private TextBlockBackcolored getMessageCoronavirus() { - - final FlashCodeUtils utils = FlashCodeFactory.getFlashCodeUtils(); - final HColorSimple backColor = (HColorSimple) HColorSet.instance().getColorIfValid("#fff"); - - final BufferedImage qrcode = smaller(utils.exportFlashcode( - "https://medium.com/@tomaspueyo/coronavirus-act-today-or-people-will-die-f4d3d9cd99ca", Color.BLACK, - backColor.getColor999())); - final Display disp = Display.create("Coronavirus: Why You Must Act Now", " ", - "Please use the flashcode or go to", "https://plantuml/coronavirus", " ", - "If you live in UK, Europe, North & South America, Iran, Japan, Korea...", - " please apply social distancing right now!", " ", "The coronavirus is coming to you.", - "It’s coming at an exponential speed: gradually, and then suddenly.", - "It’s a matter of days. Maybe a week or two.", - "When it does, your healthcare system will be overwhelmed.", - "Your fellow citizens will be treated in the hallways.", - "Exhausted healthcare workers will break down. Some will die.", - "They will have to decide which patient gets the oxygen and which one dies.", - "The only way to prevent this is social distancing today. Not tomorrow. Today.", - "That means keeping as many people home as possible, starting now.", " "); - - final UFont font = UFont.sansSerif(14); - final FontConfiguration fc = new FontConfiguration(font, HColorUtils.BLACK, HColorUtils.BLACK, false); - final TextBlock text = TextBlockUtils - .withMargin(disp.create(fc, HorizontalAlignment.LEFT, new SpriteContainerEmpty()), 10, 0); - final TextBlock result; - if (qrcode == null) { - result = text; - } else { - final UImage qr = new UImage(qrcode).scaleNearestNeighbor(3); - result = TextBlockUtils.mergeLR(text, TextBlockUtils.fromUImage(qr), VerticalAlignment.CENTER); - } - return TextBlockUtils.addBackcolor(result, backColor); - - } - private TextBlockBackcolored getMessagePatreon() { final UImage message = new UImage(PSystemVersion.getTime01()); final Color back = new Color(message.getImage().getRGB(0, 0)); diff --git a/src/net/sourceforge/plantuml/graphic/GraphicStrings.java b/src/net/sourceforge/plantuml/graphic/GraphicStrings.java index fd8946f9fa8..82fbec933d1 100644 --- a/src/net/sourceforge/plantuml/graphic/GraphicStrings.java +++ b/src/net/sourceforge/plantuml/graphic/GraphicStrings.java @@ -145,7 +145,7 @@ private TextBlock getTextBlock() { return new TextBlockRaw(strings, fontConfiguration); } else { - return display.create(fontConfiguration, HorizontalAlignment.LEFT, new SpriteContainerEmpty(), mode); + return display.create7(fontConfiguration, HorizontalAlignment.LEFT, new SpriteContainerEmpty(), mode); } } diff --git a/src/net/sourceforge/plantuml/graphic/QuoteUtils.java b/src/net/sourceforge/plantuml/graphic/QuoteUtils.java index 7188b733d74..5828535974e 100644 --- a/src/net/sourceforge/plantuml/graphic/QuoteUtils.java +++ b/src/net/sourceforge/plantuml/graphic/QuoteUtils.java @@ -248,7 +248,15 @@ public class QuoteUtils { "Guvf vf gur jnl", "Cngvrapr lbh zhfg unir zl lbhat cnqnjna", "V gubhtug lbh jrer ba zl fvqr", "Qba'g cnavp. Abar bs lbh cnavp. Nofbyhgryl ab ernfba gb cnavp.", "Gung jnf hacyrnfnag. V'z fbeel lbh unq gb frr gung.", "Gur neg bs fvzcyvpvgl vf n chmmyr bs pbzcyrkvgl.", - "Xrrc pnyz naq fgnl ng ubzr"); + "Xrrc pnyz naq fgnl ng ubzr", + "Gur terngrfg fubegpbzvat bs gur uhzna enpr vf bhe vanovyvgl gb haqrefgnaq gur rkcbaragvny shapgvba", + "Vs gur Znegvnaf vainqrq rnegu, bhe svefg erfcbafr jbhyq or gb ybjre vagrerfg engrf.", + "Rnfl gvzrf qba'g sbetr punenpgre. Vg'f gur gbhtu gvzrf gung sbetr punenpgre", + "Fbzrgvzrf va beqre gb qb gur evtug guvat, lbh unir gb qb gur jebat guvat.", + "Gur fgeratgu bs WninFpevcg vf gung lbh pna qb nalguvat. Gur jrnxarff vf gung lbh jvyy.", + "Vg'f tbvat gb qvfnccrne. Bar qnl vg'f yvxr n zvenpyr, vg jvyy qvfnccrne. Cebonoyl ol Rnfgre, BX?", + "V'ir sryg vg jnf n oht ybat orsber vg jnf pnyyrq n oht", + "Yrg'f frr guvf nf n pbyyngreny qnzntr sebz fbzr ureq vzzhavgl pybja'f gurbel."); private QuoteUtils() { } diff --git a/src/net/sourceforge/plantuml/graphic/SpecialText.java b/src/net/sourceforge/plantuml/graphic/SpecialText.java new file mode 100644 index 00000000000..eb59bd65d18 --- /dev/null +++ b/src/net/sourceforge/plantuml/graphic/SpecialText.java @@ -0,0 +1,67 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.graphic; + +import java.awt.geom.Dimension2D; + +import net.sourceforge.plantuml.ugraphic.UEmpty; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.UShapeIgnorableForCompression; +import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.comp.CompressionMode; + +public class SpecialText implements UShapeIgnorableForCompression { + + private final TextBlock title; + + public SpecialText(TextBlock title) { + this.title = title; + } + + public boolean isIgnoreForCompressionOn(CompressionMode mode) { + return true; + } + + public void drawWhenCompressed(UGraphic ug, CompressionMode mode) { + final Dimension2D dim = title.calculateDimension(ug.getStringBounder()); + ug.apply(UTranslate.dx(dim.getWidth())).draw(new UEmpty(1, 1)); + } + + public final TextBlock getTitle() { + return title; + } + +} \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockTitle.java b/src/net/sourceforge/plantuml/graphic/TextBlockTitle.java index 6926d9a2e2e..d141d646437 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockTitle.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockTitle.java @@ -58,7 +58,7 @@ public class TextBlockTitle implements TextBlock { throw new IllegalArgumentException(); } final LineBreakStrategy lineBreak = LineBreakStrategy.NONE; - textBlock = stringsToDisplay.create(font, HorizontalAlignment.CENTER, spriteContainer, lineBreak, + textBlock = stringsToDisplay.create0(font, HorizontalAlignment.CENTER, spriteContainer, lineBreak, CreoleMode.FULL, null, null); } diff --git a/src/net/sourceforge/plantuml/graphic/USymbolFrame.java b/src/net/sourceforge/plantuml/graphic/USymbolFrame.java index 5577c1ebf9b..d4fa5c5cb32 100644 --- a/src/net/sourceforge/plantuml/graphic/USymbolFrame.java +++ b/src/net/sourceforge/plantuml/graphic/USymbolFrame.java @@ -38,6 +38,7 @@ import java.awt.geom.Dimension2D; import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.ugraphic.Shadowable; import net.sourceforge.plantuml.ugraphic.UChangeBackColor; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphicStencil; @@ -55,7 +56,8 @@ public SkinParameter getSkinParameter() { private void drawFrame(UGraphic ug, double width, double height, Dimension2D dimTitle, boolean shadowing, double roundCorner) { - final URectangle shape = new URectangle(width, height).rounded(roundCorner).ignoreForCompression(); + final Shadowable shape = new URectangle(width, height).rounded(roundCorner).ignoreForCompressionOnX() + .ignoreForCompressionOnY(); if (shadowing) { shape.setDeltaShadow(3.0); } @@ -74,6 +76,7 @@ private void drawFrame(UGraphic ug, double width, double height, Dimension2D dim final double textHeight = getYpos(dimTitle); final UPath polygon = new UPath(); + polygon.setIgnoreForCompressionOnX(); polygon.moveTo(textWidth, 1); polygon.lineTo(textWidth, textHeight - cornersize); @@ -104,8 +107,8 @@ public void drawU(UGraphic ug) { final Dimension2D dim = calculateDimension(ug.getStringBounder()); ug = UGraphicStencil.create(ug, getRectangleStencil(dim), new UStroke()); ug = symbolContext.apply(ug); - drawFrame(ug, dim.getWidth(), dim.getHeight(), new Dimension2DDouble(0, 0), - symbolContext.isShadowing(), symbolContext.getRoundCorner()); + drawFrame(ug, dim.getWidth(), dim.getHeight(), new Dimension2DDouble(0, 0), symbolContext.isShadowing(), + symbolContext.getRoundCorner()); final Margin margin = getMargin(); final TextBlock tb = TextBlockUtils.mergeTB(stereotype, label, HorizontalAlignment.CENTER); tb.drawU(ug.apply(new UTranslate(margin.getX1(), margin.getY1()))); @@ -121,7 +124,8 @@ public Dimension2D calculateDimension(StringBounder stringBounder) { @Override public TextBlock asBig(final TextBlock title, HorizontalAlignment labelAlignment, final TextBlock stereotype, - final double width, final double height, final SymbolContext symbolContext, final HorizontalAlignment stereoAlignment) { + final double width, final double height, final SymbolContext symbolContext, + final HorizontalAlignment stereoAlignment) { return new AbstractTextBlock() { public void drawU(UGraphic ug) { @@ -129,9 +133,17 @@ public void drawU(UGraphic ug) { final Dimension2D dim = calculateDimension(stringBounder); ug = symbolContext.apply(ug); final Dimension2D dimTitle = title.calculateDimension(stringBounder); - drawFrame(ug, dim.getWidth(), dim.getHeight(), dimTitle, symbolContext.isShadowing(), + final double widthFull = dim.getWidth(); + drawFrame(ug, widthFull, dim.getHeight(), dimTitle, symbolContext.isShadowing(), symbolContext.getRoundCorner()); - title.drawU(ug.apply(new UTranslate(3, 1))); + final double widthTitle = title.calculateDimension(stringBounder).getWidth(); + + // Temporary hack... + if (widthFull - widthTitle < 25) { + title.drawU(ug.apply(new UTranslate(3, 1))); + } else { + ug.apply(new UTranslate(3, 1)).draw(new SpecialText(title)); + } final Dimension2D dimStereo = stereotype.calculateDimension(stringBounder); final double posStereo = (width - dimStereo.getWidth()) / 2; @@ -145,6 +157,29 @@ public Dimension2D calculateDimension(StringBounder stringBounder) { }; } +// static class Interceptor extends UGraphicDelegator { +// +// public Interceptor(UGraphic ug) { +// super(ug); +// } +// +// @Override +// public void draw(UShape shape) { +// if (shape instanceof SpecialText) { +// final SpecialText specialText = (SpecialText) shape; +// specialText.title.drawU(getUg()); +// // System.err.println("getug=" + getUg()); +// return; +// } +// super.draw(shape); +// } +// +// public UGraphic apply(UChange change) { +// return new Interceptor(getUg().apply(change)); +// } +// +// } + @Override public boolean manageHorizontalLine() { return true; diff --git a/src/net/sourceforge/plantuml/jcckit/PSystemJcckit.java b/src/net/sourceforge/plantuml/jcckit/PSystemJcckit.java new file mode 100644 index 00000000000..e2872adbf68 --- /dev/null +++ b/src/net/sourceforge/plantuml/jcckit/PSystemJcckit.java @@ -0,0 +1,88 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.jcckit; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Properties; + +import javax.imageio.ImageIO; + +import jcckit.GraphicsPlotCanvas; +import jcckit.data.DataPlot; +import jcckit.util.ConfigParameters; +import jcckit.util.PropertiesBasedConfigData; +import net.sourceforge.plantuml.AbstractPSystem; +import net.sourceforge.plantuml.FileFormatOption; +import net.sourceforge.plantuml.api.ImageDataSimple; +import net.sourceforge.plantuml.core.DiagramDescription; +import net.sourceforge.plantuml.core.ImageData; + +public class PSystemJcckit extends AbstractPSystem { + + private final PropertiesBasedConfigData prop; + private final int width; + private final int height; + + public PSystemJcckit(Properties p, int width, int height) { + this.width = width; + this.height = height; + prop = new PropertiesBasedConfigData(p); + } + + @Override + final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) + throws IOException { + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + + // Sets up a Graphics2DPlotCanvas + ConfigParameters config = new ConfigParameters(prop); + GraphicsPlotCanvas plotCanvas = new GraphicsPlotCanvas(config, image); + plotCanvas.connect(DataPlot.create(config)); + plotCanvas.paint(); + + // Writes the off-screen image into a PNG file + ImageIO.write(image, "png", os); + + return new ImageDataSimple(width, height); + } + + public DiagramDescription getDescription() { + return new DiagramDescription("(JCCKit)"); + } + +} diff --git a/src/net/sourceforge/plantuml/jcckit/PSystemJcckitFactory.java b/src/net/sourceforge/plantuml/jcckit/PSystemJcckitFactory.java new file mode 100644 index 00000000000..8adae19798d --- /dev/null +++ b/src/net/sourceforge/plantuml/jcckit/PSystemJcckitFactory.java @@ -0,0 +1,120 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.jcckit; + +import java.io.IOException; +import java.io.StringReader; +import java.util.Properties; + +import net.sourceforge.plantuml.BackSlash; +import net.sourceforge.plantuml.Log; +import net.sourceforge.plantuml.StringUtils; +import net.sourceforge.plantuml.command.PSystemBasicFactory; +import net.sourceforge.plantuml.command.regex.Matcher2; +import net.sourceforge.plantuml.command.regex.MyPattern; +import net.sourceforge.plantuml.command.regex.Pattern2; +import net.sourceforge.plantuml.core.DiagramType; + +public class PSystemJcckitFactory extends PSystemBasicFactory { + + private StringBuilder data; + private int width; + private int height; + + public PSystemJcckitFactory(DiagramType diagramType) { + super(diagramType); + } + + public PSystemJcckit init(String startLine) { + this.data = null; + this.width = 640; + this.height = 400; + if (getDiagramType() == DiagramType.UML) { + return null; + } else if (getDiagramType() == DiagramType.JCCKIT) { + extractDimension(startLine); + data = new StringBuilder(); + return createSystem(); + } else { + throw new IllegalStateException(getDiagramType().name()); + } + + } + + private void extractDimension(String startLine) { + final Pattern2 p = MyPattern.cmpile("\\((\\d+),(\\d+)\\)"); + final Matcher2 m = p.matcher(startLine); + final boolean ok = m.find(); + if (ok) { + width = Integer.parseInt(m.group(1)); + height = Integer.parseInt(m.group(2)); + } + } + + String getDimension() { + return "" + width + "-" + height; + } + + private PSystemJcckit createSystem() { + final Properties p = new Properties(); + try { + p.load(new StringReader(data.toString())); + // For Java 1.5 + // p.load(new ByteArrayInputStream(data.toString().getBytes("ISO-8859-1"))); + } catch (IOException e) { + Log.error("Error " + e); + e.printStackTrace(); + return null; + } + return new PSystemJcckit(p, width, height); + } + + @Override + public PSystemJcckit executeLine(PSystemJcckit system, String line) { + if (system == null && line.startsWith("jcckit")) { + data = new StringBuilder(); + extractDimension(line); + return createSystem(); + } + if (data == null) { + return null; + } + data.append(StringUtils.trin(line)); + data.append(BackSlash.NEWLINE); + return createSystem(); + } + +} diff --git a/src/net/sourceforge/plantuml/objectdiagram/ObjectDiagramFactory.java b/src/net/sourceforge/plantuml/objectdiagram/ObjectDiagramFactory.java deleted file mode 100644 index e0ccf25a6e7..00000000000 --- a/src/net/sourceforge/plantuml/objectdiagram/ObjectDiagramFactory.java +++ /dev/null @@ -1,115 +0,0 @@ -/* ======================================================================== - * PlantUML : a free UML diagram generator - * ======================================================================== - * - * (C) Copyright 2009-2020, Arnaud Roques - * - * Project Info: http://plantuml.com - * - * If you like this project or if you find it useful, you can support us at: - * - * http://plantuml.com/patreon (only 1$ per month!) - * http://plantuml.com/paypal - * - * This file is part of PlantUML. - * - * PlantUML 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. - * - * PlantUML 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 this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * - * Original Author: Arnaud Roques - * - * - */ -package net.sourceforge.plantuml.objectdiagram; - -import java.util.ArrayList; -import java.util.List; - -import net.sourceforge.plantuml.ISkinSimple; -import net.sourceforge.plantuml.UmlDiagramType; -import net.sourceforge.plantuml.classdiagram.command.CommandLinkClass; -import net.sourceforge.plantuml.classdiagram.command.CommandUrl; -import net.sourceforge.plantuml.command.Command; -import net.sourceforge.plantuml.command.CommandEndPackage; -import net.sourceforge.plantuml.command.CommandFootboxIgnored; -import net.sourceforge.plantuml.command.CommandPackage; -import net.sourceforge.plantuml.command.CommandPage; -import net.sourceforge.plantuml.command.CommandRankDir; -import net.sourceforge.plantuml.command.UmlDiagramFactory; -import net.sourceforge.plantuml.command.note.CommandFactoryNote; -import net.sourceforge.plantuml.command.note.CommandFactoryNoteOnEntity; -import net.sourceforge.plantuml.command.note.CommandFactoryNoteOnLink; -import net.sourceforge.plantuml.command.regex.RegexLeaf; -import net.sourceforge.plantuml.objectdiagram.command.CommandAddData; -import net.sourceforge.plantuml.objectdiagram.command.CommandCreateEntityObject; -import net.sourceforge.plantuml.objectdiagram.command.CommandCreateEntityObjectMultilines; - -public class ObjectDiagramFactory extends UmlDiagramFactory { - - private final ISkinSimple skinParam; - - public ObjectDiagramFactory(ISkinSimple skinParam) { - this.skinParam = skinParam; - } - - @Override - protected List createCommands() { - - final List cmds = new ArrayList(); - cmds.add(new CommandFootboxIgnored()); - - addCommonCommands1(cmds); - cmds.add(new CommandRankDir()); - cmds.add(new CommandPage()); - cmds.add(new CommandAddData()); - cmds.add(new CommandLinkClass(UmlDiagramType.OBJECT)); - // - cmds.add(new CommandCreateEntityObject()); - final CommandFactoryNote factoryNoteCommand = new CommandFactoryNote(); - - cmds.add(factoryNoteCommand.createSingleLine()); - cmds.add(new CommandPackage()); - cmds.add(new CommandEndPackage()); - // addCommand(new CommandNamespace()); - // addCommand(new CommandEndNamespace()); - // addCommand(new CommandStereotype()); - // - // addCommand(new CommandImport()); - final CommandFactoryNoteOnEntity factoryNoteOnEntityCommand = new CommandFactoryNoteOnEntity("object", - new RegexLeaf("ENTITY", "([\\p{L}0-9_.]+|[%g][^%g]+[%g])")); - cmds.add(factoryNoteOnEntityCommand.createSingleLine()); - - cmds.add(new CommandUrl()); - - cmds.add(factoryNoteCommand.createMultiLine(false)); - cmds.add(factoryNoteOnEntityCommand.createMultiLine(true)); - cmds.add(factoryNoteOnEntityCommand.createMultiLine(false)); - cmds.add(new CommandCreateEntityObjectMultilines()); - - final CommandFactoryNoteOnLink factoryNoteOnLinkCommand = new CommandFactoryNoteOnLink(); - cmds.add(factoryNoteOnLinkCommand.createSingleLine()); - cmds.add(factoryNoteOnLinkCommand.createMultiLine(false)); - - // addCommand(new CommandNoopClass()); - return cmds; - - } - - @Override - public ObjectDiagram createEmptyDiagram() { - return new ObjectDiagram(skinParam); - } -} diff --git a/src/net/sourceforge/plantuml/objectdiagram/command/CommandAddData.java b/src/net/sourceforge/plantuml/objectdiagram/command/CommandAddData.java index b9f3f8d28ee..05eafc91a79 100644 --- a/src/net/sourceforge/plantuml/objectdiagram/command/CommandAddData.java +++ b/src/net/sourceforge/plantuml/objectdiagram/command/CommandAddData.java @@ -73,7 +73,7 @@ protected CommandExecutionResult executeArg(AbstractClassOrObjectDiagram diagram if (field.length() > 0 && VisibilityModifier.isVisibilityCharacter(field)) { diagram.setVisibilityModifierPresent(true); } - entity.getBodier().addFieldOrMethod(field, entity); + entity.getBodier().addFieldOrMethod(field); return CommandExecutionResult.ok(); } } diff --git a/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateEntityObjectMultilines.java b/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateEntityObjectMultilines.java index 98d0f9625e6..3295b3a826c 100644 --- a/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateEntityObjectMultilines.java +++ b/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateEntityObjectMultilines.java @@ -99,7 +99,7 @@ protected CommandExecutionResult executeNow(AbstractClassOrObjectDiagram diagram if (VisibilityModifier.isVisibilityCharacter(s.getString())) { diagram.setVisibilityModifierPresent(true); } - entity.getBodier().addFieldOrMethod(s.getString(), entity); + entity.getBodier().addFieldOrMethod(s.getString()); } return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateMap.java b/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateMap.java new file mode 100644 index 00000000000..e298b61b93c --- /dev/null +++ b/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateMap.java @@ -0,0 +1,144 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.objectdiagram.command; + +import net.sourceforge.plantuml.FontParam; +import net.sourceforge.plantuml.StringLocated; +import net.sourceforge.plantuml.UrlBuilder; +import net.sourceforge.plantuml.command.BlocLines; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.command.CommandMultilines2; +import net.sourceforge.plantuml.command.MultilinesStrategy; +import net.sourceforge.plantuml.command.regex.IRegex; +import net.sourceforge.plantuml.command.regex.RegexConcat; +import net.sourceforge.plantuml.command.regex.RegexLeaf; +import net.sourceforge.plantuml.command.regex.RegexResult; +import net.sourceforge.plantuml.cucadiagram.BodierMap; +import net.sourceforge.plantuml.cucadiagram.Code; +import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.cucadiagram.IEntity; +import net.sourceforge.plantuml.cucadiagram.ILeaf; +import net.sourceforge.plantuml.cucadiagram.Ident; +import net.sourceforge.plantuml.cucadiagram.LeafType; +import net.sourceforge.plantuml.cucadiagram.Link; +import net.sourceforge.plantuml.cucadiagram.LinkDecor; +import net.sourceforge.plantuml.cucadiagram.LinkType; +import net.sourceforge.plantuml.cucadiagram.Stereotype; +import net.sourceforge.plantuml.graphic.color.ColorParser; +import net.sourceforge.plantuml.graphic.color.ColorType; +import net.sourceforge.plantuml.objectdiagram.AbstractClassOrObjectDiagram; +import net.sourceforge.plantuml.style.StyleBuilder; + +public class CommandCreateMap extends CommandMultilines2 { + + public CommandCreateMap() { + super(getRegexConcat(), MultilinesStrategy.REMOVE_STARTING_QUOTE); + } + + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateMap.class.getName(), RegexLeaf.start(), // + new RegexLeaf("TYPE", "map"), // + RegexLeaf.spaceOneOrMore(), // + new RegexLeaf("NAME", "(?:[%g]([^%g]+)[%g][%s]+as[%s]+)?([\\p{L}0-9_.]+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREO", "(\\<\\<.+\\>\\>)?"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), // + RegexLeaf.spaceZeroOrMore(), // + ColorParser.exp1(), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("\\{"), // + RegexLeaf.end()); + } + + @Override + public String getPatternEnd() { + return "(?i)^[%s]*\\}[%s]*$"; + } + + @Override + protected CommandExecutionResult executeNow(AbstractClassOrObjectDiagram diagram, BlocLines lines) { + lines = lines.trim(true); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final IEntity entity1 = executeArg0(diagram, line0); + if (entity1 == null) { + return CommandExecutionResult.error("No such entity"); + } + lines = lines.subExtract(1, 1); + for (StringLocated sl : lines) { + final String line = sl.getString(); + assert line.length() > 0; + entity1.getBodier().addFieldOrMethod(line); + if (BodierMap.getLinkedEntry(line) != null) { + final String linkStr = BodierMap.getLinkedEntry(line); + final int x = line.indexOf(linkStr); + final String key = line.substring(0, x).trim(); + final String dest = line.substring(x + linkStr.length()).trim(); + final Ident ident2 = diagram.buildLeafIdentSpecial(dest); + final ILeaf entity2 = diagram.getEntityFactory().getLeafStrict(ident2); + final LinkType linkType = new LinkType(LinkDecor.ARROW, LinkDecor.NONE); + final int length = linkStr.length() - 2; + final Link link = new Link(entity1, entity2, linkType, Display.NULL, length, + diagram.getSkinParam().getCurrentStyleBuilder()); + link.setPortMembers(key, null); + diagram.addLink(link); + } + } + return CommandExecutionResult.ok(); + } + + private IEntity executeArg0(AbstractClassOrObjectDiagram diagram, RegexResult line0) { + final String name = line0.get("NAME", 1); + final Ident ident = diagram.buildLeafIdent(name); + final Code code = diagram.V1972() ? ident : diagram.buildCode(name); + final String display = line0.get("NAME", 0); + final String stereotype = line0.get("STEREO", 0); + final boolean leafExist = diagram.V1972() ? diagram.leafExistSmart(ident) : diagram.leafExist(code); + if (leafExist) { + return diagram.getOrCreateLeaf(diagram.buildLeafIdent(name), code, LeafType.MAP, null); + } + final IEntity entity = diagram.createLeaf(ident, code, Display.getWithNewlines(display), LeafType.MAP, null); + if (stereotype != null) { + entity.setStereotype(new Stereotype(stereotype, diagram.getSkinParam().getCircledCharacterRadius(), + diagram.getSkinParam().getFont(null, false, FontParam.CIRCLED_CHARACTER), + diagram.getSkinParam().getIHtmlColorSet())); + } + entity.setSpecificColorTOBEREMOVED(ColorType.BACK, + diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(line0.get("COLOR", 0))); + return entity; + } + +} diff --git a/src/net/sourceforge/plantuml/project/GanttDiagram.java b/src/net/sourceforge/plantuml/project/GanttDiagram.java index adc235108ba..840f8d56859 100644 --- a/src/net/sourceforge/plantuml/project/GanttDiagram.java +++ b/src/net/sourceforge/plantuml/project/GanttDiagram.java @@ -181,7 +181,7 @@ public void setPrintScale(PrintScale printScale) { } private boolean isHidden(Task task) { - if (printStart == null) { + if (printStart == null || task instanceof TaskSeparator) { return false; } if (task.getEnd().compareTo(min) < 0) { diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/AbstractTile.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/AbstractTile.java index ac13d357017..72f1e4b5821 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/AbstractTile.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/AbstractTile.java @@ -51,15 +51,15 @@ final public double getZ(StringBounder stringBounder) { return result; } - public Tile matchAnchorV1(String anchor) { + public boolean matchAnchorV1(String anchor) { final Event event = this.getEvent(); if (event instanceof AbstractMessage) { final AbstractMessage msg = (AbstractMessage) event; if (anchor.equals(msg.getAnchor())) { - return this; + return true; } } - return null; + return false; } diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/GroupingTile.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/GroupingTile.java index 6b7be4fb96b..a1d74c4c86f 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/GroupingTile.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/GroupingTile.java @@ -87,17 +87,6 @@ public double getYPoint(StringBounder stringBounder) { return 0; } - @Override - public Tile matchAnchorV1(String anchor) { - for (Tile tile : tiles) { - final Tile result = tile.matchAnchorV1(anchor); - if (result != null) { - return result; - } - } - return super.matchAnchorV1(anchor); - } - public GroupingTile(Iterator it, GroupingStart start, TileArguments tileArgumentsBachColorChanged, TileArguments tileArgumentsOriginal) { final StringBounder stringBounder = tileArgumentsOriginal.getStringBounder(); @@ -236,14 +225,16 @@ public void callbackY(double y) { } public static double fillPositionelTiles(StringBounder stringBounder, double y, List tiles, - final List positionedTiles) { + final List local, List full) { for (Tile tile : mergeParallel(tiles)) { - positionedTiles.add(new YPositionedTile(tile, y)); + final YPositionedTile ytile = new YPositionedTile(tile, y); + local.add(ytile); + full.add(ytile); if (tile instanceof GroupingTile) { final GroupingTile groupingTile = (GroupingTile) tile; final double headerHeight = groupingTile.getHeaderHeight(stringBounder); - fillPositionelTiles(stringBounder, y + headerHeight, groupingTile.tiles, - new ArrayList()); + final ArrayList local2 = new ArrayList(); + fillPositionelTiles(stringBounder, y + headerHeight, groupingTile.tiles, local2, full); } y += tile.getPreferredHeight(stringBounder); } diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/PlayingSpace.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/PlayingSpace.java index 9215b0c2be9..8986a1bc78c 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/PlayingSpace.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/PlayingSpace.java @@ -110,16 +110,17 @@ public void drawForeground(UGraphic ug) { private double drawUInternal(UGraphic ug, boolean trace) { final StringBounder stringBounder = ug.getStringBounder(); - final List positionedTiles = new ArrayList(); - final double y = GroupingTile.fillPositionelTiles(stringBounder, startingY, tiles, positionedTiles); - for (YPositionedTile tile : positionedTiles) { + final List local = new ArrayList(); + final List full = new ArrayList(); + final double y = GroupingTile.fillPositionelTiles(stringBounder, startingY, tiles, local, full); + for (YPositionedTile tile : local) { tile.drawInArea(ug); } for (LinkAnchor linkAnchor : linkAnchors) { - final YPositionedTile tile1 = getFromAnchor(positionedTiles, linkAnchor.getAnchor1()); - final YPositionedTile tile2 = getFromAnchor(positionedTiles, linkAnchor.getAnchor2()); - if (tile1 != null && tile2 != null) { - linkAnchor.drawAnchor(ug, tile1, tile2, skinParam); + final YPositionedTile ytile1 = getFromAnchor(full, linkAnchor.getAnchor1()); + final YPositionedTile ytile2 = getFromAnchor(full, linkAnchor.getAnchor2()); + if (ytile1 != null && ytile2 != null) { + linkAnchor.drawAnchor(ug, ytile1, ytile2, skinParam); } } // System.err.println("MainTile::drawUInternal finalY=" + y); @@ -127,9 +128,10 @@ private double drawUInternal(UGraphic ug, boolean trace) { } private YPositionedTile getFromAnchor(List positionedTiles, String anchor) { - for (YPositionedTile tile : positionedTiles) { - if (tile.matchAnchorV2(anchor)) { - return tile; + for (YPositionedTile ytile : positionedTiles) { + final boolean matchAnchorV2 = ytile.matchAnchorV2(anchor); + if (matchAnchorV2) { + return ytile; } } return null; diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/Tile.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/Tile.java index 5d354ca4b1b..447d71c4905 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/Tile.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/Tile.java @@ -57,7 +57,7 @@ public interface Tile extends UDrawable, UShape { public double getZ(StringBounder stringBounder); - public Tile matchAnchorV1(String anchor); + public boolean matchAnchorV1(String anchor); } diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/TileParallel.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/TileParallel.java index f0852eb4b80..1f52d07bf39 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/TileParallel.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/TileParallel.java @@ -165,14 +165,13 @@ public Event getEvent() { return null; } - public Tile matchAnchorV1(String anchor) { + public boolean matchAnchorV1(String anchor) { for (Tile tile : tiles) { - final Tile result = tile.matchAnchorV1(anchor); - if (result != null) { - return result; + if (tile.matchAnchorV1(anchor)) { + return true; } } - return null; + return false; } } diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/YPositionedTile.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/YPositionedTile.java index f8d6bec9719..391939abbf4 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/YPositionedTile.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/YPositionedTile.java @@ -67,8 +67,8 @@ public void drawInArea(UGraphic ug) { } public boolean matchAnchorV2(String anchor) { - final Tile result = tile.matchAnchorV1(anchor); - return result != null; + final boolean result = tile.matchAnchorV1(anchor); + return result; } public final double getY(StringBounder stringBounder) { diff --git a/src/net/sourceforge/plantuml/skin/AbstractTextualComponent.java b/src/net/sourceforge/plantuml/skin/AbstractTextualComponent.java index c43d4987371..d0883b5b4c4 100644 --- a/src/net/sourceforge/plantuml/skin/AbstractTextualComponent.java +++ b/src/net/sourceforge/plantuml/skin/AbstractTextualComponent.java @@ -114,7 +114,7 @@ public AbstractTextualComponent(Style style, Style stereo, LineBreakStrategy max textBlock = new BodyEnhanced2(this.display, FontParam.NOTE, spriteContainer, horizontalAlignment, fc, maxMessageSize); } else { - textBlock = this.display.create(fc, horizontalAlignment, spriteContainer, maxMessageSize, CreoleMode.FULL, + textBlock = this.display.create0(fc, horizontalAlignment, spriteContainer, maxMessageSize, CreoleMode.FULL, fontForStereotype, htmlColorForStereotype); } } diff --git a/src/net/sourceforge/plantuml/skin/rose/ComponentRoseActiveLine.java b/src/net/sourceforge/plantuml/skin/rose/ComponentRoseActiveLine.java index 39d77018ced..98ef41c3e0c 100644 --- a/src/net/sourceforge/plantuml/skin/rose/ComponentRoseActiveLine.java +++ b/src/net/sourceforge/plantuml/skin/rose/ComponentRoseActiveLine.java @@ -73,6 +73,10 @@ protected void drawInternalU(UGraphic ug, Area area) { final StringBounder stringBounder = ug.getStringBounder(); final int x = (int) (dimensionToUse.getWidth() - getPreferredWidth(stringBounder)) / 2; + if (dimensionToUse.getHeight() == 0) { + return; + } + final URectangle rect = new URectangle(getPreferredWidth(stringBounder), dimensionToUse.getHeight()); if (symbolContext.isShadowing()) { rect.setDeltaShadow(1); diff --git a/src/net/sourceforge/plantuml/statediagram/command/CommandAddField.java b/src/net/sourceforge/plantuml/statediagram/command/CommandAddField.java index 435880721d1..6e5a5045956 100644 --- a/src/net/sourceforge/plantuml/statediagram/command/CommandAddField.java +++ b/src/net/sourceforge/plantuml/statediagram/command/CommandAddField.java @@ -81,7 +81,7 @@ protected CommandExecutionResult executeArg(StateDiagram diagram, LineLocation l final Code code = diagram.V1972() ? ident : diagram.buildCode(codeString); final IEntity entity = diagram.getOrCreateLeaf(ident, code, null, null); - entity.getBodier().addFieldOrMethod(field, entity); + entity.getBodier().addFieldOrMethod(field); return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/statediagram/command/CommandCreateState.java b/src/net/sourceforge/plantuml/statediagram/command/CommandCreateState.java index 29f9da5cc1a..5e60796d50a 100644 --- a/src/net/sourceforge/plantuml/statediagram/command/CommandCreateState.java +++ b/src/net/sourceforge/plantuml/statediagram/command/CommandCreateState.java @@ -150,7 +150,7 @@ protected CommandExecutionResult executeArg(StateDiagram diagram, LineLocation l final String addFields = arg.get("ADDFIELD", 0); if (addFields != null) { - ent.getBodier().addFieldOrMethod(addFields, ent); + ent.getBodier().addFieldOrMethod(addFields); } return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java index 608fe88bf35..3d84063703d 100644 --- a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java +++ b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java @@ -84,7 +84,6 @@ import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersion; import net.sourceforge.plantuml.cucadiagram.dot.Neighborhood; import net.sourceforge.plantuml.cucadiagram.entity.EntityFactory; -import net.sourceforge.plantuml.cucadiagram.entity.EntityImpl; import net.sourceforge.plantuml.descdiagram.EntityImageDesignedDomain; import net.sourceforge.plantuml.descdiagram.EntityImageDomain; import net.sourceforge.plantuml.descdiagram.EntityImageMachine; @@ -100,7 +99,6 @@ import net.sourceforge.plantuml.graphic.TextBlockWidth; import net.sourceforge.plantuml.graphic.USymbol; import net.sourceforge.plantuml.graphic.USymbolInterface; -import net.sourceforge.plantuml.graphic.color.ColorType; import net.sourceforge.plantuml.style.SName; import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.style.StyleSignature; @@ -118,6 +116,7 @@ import net.sourceforge.plantuml.svek.image.EntityImageLollipopInterface; import net.sourceforge.plantuml.svek.image.EntityImageLollipopInterfaceEye1; import net.sourceforge.plantuml.svek.image.EntityImageLollipopInterfaceEye2; +import net.sourceforge.plantuml.svek.image.EntityImageMap; import net.sourceforge.plantuml.svek.image.EntityImageNote; import net.sourceforge.plantuml.svek.image.EntityImageObject; import net.sourceforge.plantuml.svek.image.EntityImagePseudoState; @@ -212,6 +211,9 @@ public static IEntityImage createEntityImageBlock(ILeaf leaf, ISkinParam skinPar if (leaf.getLeafType() == LeafType.OBJECT) { return new EntityImageObject(leaf, skinParam, portionShower); } + if (leaf.getLeafType() == LeafType.MAP) { + return new EntityImageMap(leaf, skinParam, portionShower); + } if (leaf.getLeafType() == LeafType.SYNCHRO_BAR || leaf.getLeafType() == LeafType.STATE_FORK_JOIN) { return new EntityImageSynchroBar(leaf, skinParam); } diff --git a/src/net/sourceforge/plantuml/svek/Line.java b/src/net/sourceforge/plantuml/svek/Line.java index 949e753408c..0490d37224a 100644 --- a/src/net/sourceforge/plantuml/svek/Line.java +++ b/src/net/sourceforge/plantuml/svek/Line.java @@ -342,7 +342,7 @@ public Line(Link link, ColorSequence colorSequence, ISkinParam skinParam, String private TextBlock getLineLabel(Link link, ISkinParam skinParam, FontConfiguration labelFont) { final double marginLabel = startUid.equalsId(endUid) ? 6 : 1; final HorizontalAlignment alignment = getMessageTextAlignment(link.getUmlDiagramType(), skinParam); - TextBlock label = link.getLabel().create(labelFont, alignment, skinParam, skinParam.maxMessageSize()); + TextBlock label = link.getLabel().create9(labelFont, alignment, skinParam, skinParam.maxMessageSize()); final VisibilityModifier visibilityModifier = link.getVisibilityModifier(); if (visibilityModifier != null) { final Rose rose = new Rose(); diff --git a/src/net/sourceforge/plantuml/svek/UGraphicForSnake.java b/src/net/sourceforge/plantuml/svek/UGraphicForSnake.java index b3cea8c14f6..b79634e2720 100644 --- a/src/net/sourceforge/plantuml/svek/UGraphicForSnake.java +++ b/src/net/sourceforge/plantuml/svek/UGraphicForSnake.java @@ -53,7 +53,7 @@ public class UGraphicForSnake extends UGraphicDelegator { @Override public String toString() { - return super.toString() + " " + getUg(); + return "UGraphicForSnake " + getUg(); } public UTranslate getTranslation() { diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageMap.java b/src/net/sourceforge/plantuml/svek/image/EntityImageMap.java new file mode 100644 index 00000000000..0def72bef78 --- /dev/null +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageMap.java @@ -0,0 +1,222 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.svek.image; + +import java.awt.geom.Dimension2D; + +import net.sourceforge.plantuml.ColorParam; +import net.sourceforge.plantuml.CornerParam; +import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.FontParam; +import net.sourceforge.plantuml.Guillemet; +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.LineConfigurable; +import net.sourceforge.plantuml.LineParam; +import net.sourceforge.plantuml.SkinParamUtils; +import net.sourceforge.plantuml.Url; +import net.sourceforge.plantuml.creole.Stencil; +import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.cucadiagram.EntityPortion; +import net.sourceforge.plantuml.cucadiagram.ILeaf; +import net.sourceforge.plantuml.cucadiagram.LeafType; +import net.sourceforge.plantuml.cucadiagram.PortionShower; +import net.sourceforge.plantuml.cucadiagram.Stereotype; +import net.sourceforge.plantuml.cucadiagram.TextBlockMap; +import net.sourceforge.plantuml.graphic.FontConfiguration; +import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.graphic.TextBlockEmpty; +import net.sourceforge.plantuml.graphic.TextBlockLineBefore; +import net.sourceforge.plantuml.graphic.TextBlockUtils; +import net.sourceforge.plantuml.graphic.color.ColorType; +import net.sourceforge.plantuml.svek.AbstractEntityImage; +import net.sourceforge.plantuml.svek.Ports; +import net.sourceforge.plantuml.svek.ShapeType; +import net.sourceforge.plantuml.svek.WithPorts; +import net.sourceforge.plantuml.ugraphic.PlacementStrategyY1Y2; +import net.sourceforge.plantuml.ugraphic.Shadowable; +import net.sourceforge.plantuml.ugraphic.UChangeBackColor; +import net.sourceforge.plantuml.ugraphic.UChangeColor; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.UGraphicStencil; +import net.sourceforge.plantuml.ugraphic.ULayoutGroup; +import net.sourceforge.plantuml.ugraphic.URectangle; +import net.sourceforge.plantuml.ugraphic.UStroke; +import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.color.HColor; + +public class EntityImageMap extends AbstractEntityImage implements Stencil, WithPorts { + + final private TextBlock name; + final private TextBlock stereo; + final private TextBlock entries; + final private Url url; + final private double roundCorner; + + final private LineConfigurable lineConfig; + + public EntityImageMap(ILeaf entity, ISkinParam skinParam, PortionShower portionShower) { + super(entity, skinParam); + this.lineConfig = entity; + final Stereotype stereotype = entity.getStereotype(); + this.roundCorner = skinParam.getRoundCorner(CornerParam.DEFAULT, null); + this.name = TextBlockUtils.withMargin( + entity.getDisplay().create(new FontConfiguration(getSkinParam(), FontParam.OBJECT, stereotype), + HorizontalAlignment.CENTER, skinParam), + 2, 2); + if (stereotype == null || stereotype.getLabel(Guillemet.DOUBLE_COMPARATOR) == null + || portionShower.showPortion(EntityPortion.STEREOTYPE, entity) == false) { + this.stereo = null; + } else { + this.stereo = Display.create(stereotype.getLabels(skinParam.guillemet())).create( + new FontConfiguration(getSkinParam(), FontParam.OBJECT_STEREOTYPE, stereotype), + HorizontalAlignment.CENTER, skinParam); + } + + this.entries = entity.getBodier().getBody(FontParam.OBJECT_ATTRIBUTE, skinParam, false, false, + entity.getStereotype()); + this.url = entity.getUrl99(); + + } + + public Ports getPorts(StringBounder stringBounder) { + final Dimension2D dimTitle = getTitleDimension(stringBounder); + return ((WithPorts) entries).getPorts(stringBounder).translateY(dimTitle.getHeight()); + } + + private int marginEmptyFieldsOrMethod = 13; + + public Dimension2D calculateDimension(StringBounder stringBounder) { + final Dimension2D dimTitle = getTitleDimension(stringBounder); + final Dimension2D dimFields = entries.calculateDimension(stringBounder); + double width = Math.max(dimFields.getWidth(), dimTitle.getWidth() + 2 * xMarginCircle); + if (width < getSkinParam().minClassWidth()) { + width = getSkinParam().minClassWidth(); + } + + final double height = getMethodOrFieldHeight(dimFields) + dimTitle.getHeight(); + return new Dimension2DDouble(width, height); + } + + final public void drawU(UGraphic ug) { + final StringBounder stringBounder = ug.getStringBounder(); + final Dimension2D dimTotal = calculateDimension(stringBounder); + final Dimension2D dimTitle = getTitleDimension(stringBounder); + + final double widthTotal = dimTotal.getWidth(); + final double heightTotal = dimTotal.getHeight(); + final Shadowable rect = new URectangle(widthTotal, heightTotal).rounded(roundCorner); + if (getSkinParam().shadowing(getEntity().getStereotype())) { + rect.setDeltaShadow(4); + } + + ug = ug.apply(new UChangeColor(SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.objectBorder))); + HColor backcolor = getEntity().getColors(getSkinParam()).getColor(ColorType.BACK); + if (backcolor == null) { + backcolor = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.objectBackground); + } + ug = ug.apply(new UChangeBackColor(backcolor)); + if (url != null) { + ug.startUrl(url); + } + + final UStroke stroke = getStroke(); + ug.apply(stroke).draw(rect); + + final ULayoutGroup header = new ULayoutGroup(new PlacementStrategyY1Y2(ug.getStringBounder())); + if (stereo != null) { + header.add(stereo); + } + header.add(name); + header.drawU(ug, dimTotal.getWidth(), dimTitle.getHeight()); + + final UGraphic ug2 = UGraphicStencil.create(ug, this, stroke); + ((TextBlockMap) entries).setTotalWidth(dimTotal.getWidth()); + entries.drawU(ug2.apply(UTranslate.dy(dimTitle.getHeight()))); + + if (url != null) { + ug.closeAction(); + } + } + + private UStroke getStroke() { + UStroke stroke = lineConfig.getColors(getSkinParam()).getSpecificLineStroke(); + if (stroke == null) { + stroke = getSkinParam().getThickness(LineParam.objectBorder, getStereo()); + } + if (stroke == null) { + stroke = new UStroke(1.5); + } + return stroke; + } + + private double getMethodOrFieldHeight(final Dimension2D dim) { + final double fieldsHeight = dim.getHeight(); + if (fieldsHeight == 0 && this.getEntity().getLeafType() != LeafType.MAP) { + return marginEmptyFieldsOrMethod; + } + return fieldsHeight; + } + + private int xMarginCircle = 5; + + private Dimension2D getTitleDimension(StringBounder stringBounder) { + return getNameAndSteretypeDimension(stringBounder); + } + + private Dimension2D getNameAndSteretypeDimension(StringBounder stringBounder) { + final Dimension2D nameDim = name.calculateDimension(stringBounder); + final Dimension2D stereoDim = stereo == null ? new Dimension2DDouble(0, 0) + : stereo.calculateDimension(stringBounder); + final Dimension2D nameAndStereo = new Dimension2DDouble(Math.max(nameDim.getWidth(), stereoDim.getWidth()), + nameDim.getHeight() + stereoDim.getHeight()); + return nameAndStereo; + } + + public ShapeType getShapeType() { + return ShapeType.RECTANGLE_HTML_FOR_PORTS; + } + + public double getStartingX(StringBounder stringBounder, double y) { + return 0; + } + + public double getEndingX(StringBounder stringBounder, double y) { + return calculateDimension(stringBounder).getWidth(); + } + +} diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageState.java b/src/net/sourceforge/plantuml/svek/image/EntityImageState.java index 502e609bec8..77390d4f9f7 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageState.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageState.java @@ -91,7 +91,7 @@ public EntityImageState(IEntity entity, ISkinParam skinParam) { final Stereotype stereotype = entity.getStereotype(); this.withSymbol = stereotype != null && stereotype.isWithOOSymbol(); - this.desc = entity.getDisplay().create(new FontConfiguration(getSkinParam(), FontParam.STATE, stereotype), + this.desc = entity.getDisplay().create8(new FontConfiguration(getSkinParam(), FontParam.STATE, stereotype), HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, skinParam.wrapWidth()); Display list = Display.empty(); @@ -101,7 +101,7 @@ public EntityImageState(IEntity entity, ISkinParam skinParam) { this.url = entity.getUrl99(); - this.fields = list.create(new FontConfiguration(getSkinParam(), FontParam.STATE_ATTRIBUTE, stereotype), + this.fields = list.create8(new FontConfiguration(getSkinParam(), FontParam.STATE_ATTRIBUTE, stereotype), HorizontalAlignment.LEFT, skinParam, CreoleMode.FULL, skinParam.wrapWidth()); } diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageStateEmptyDescription.java b/src/net/sourceforge/plantuml/svek/image/EntityImageStateEmptyDescription.java index 6fd453b82e1..77e37c0f203 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageStateEmptyDescription.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageStateEmptyDescription.java @@ -76,7 +76,7 @@ public EntityImageStateEmptyDescription(IEntity entity, ISkinParam skinParam) { super(entity, skinParam); final Stereotype stereotype = entity.getStereotype(); - this.desc = entity.getDisplay().create(new FontConfiguration(getSkinParam(), FontParam.STATE, stereotype), + this.desc = entity.getDisplay().create8(new FontConfiguration(getSkinParam(), FontParam.STATE, stereotype), HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, skinParam.wrapWidth()); Display list = Display.empty(); diff --git a/src/net/sourceforge/plantuml/svg/SvgGraphics.java b/src/net/sourceforge/plantuml/svg/SvgGraphics.java index 04fe14999b3..dcd36a725f7 100644 --- a/src/net/sourceforge/plantuml/svg/SvgGraphics.java +++ b/src/net/sourceforge/plantuml/svg/SvgGraphics.java @@ -63,6 +63,7 @@ import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.SvgString; import net.sourceforge.plantuml.code.Base64Coder; +import net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils; import net.sourceforge.plantuml.tikz.TikzGraphics; import net.sourceforge.plantuml.ugraphic.UPath; import net.sourceforge.plantuml.ugraphic.USegment; @@ -326,7 +327,8 @@ public void openLink(String url, String title, String target) { if (url == null) { throw new IllegalArgumentException(); } - if (OptionFlags.ALLOW_INCLUDE == false && url.toLowerCase().startsWith("javascript")) { + // javascript: security issue + if (GraphvizUtils.getJavascriptUnsecure() == false && url.toLowerCase().startsWith("javascript")) { return; } diff --git a/src/net/sourceforge/plantuml/ugraphic/AbstractUGraphic.java b/src/net/sourceforge/plantuml/ugraphic/AbstractUGraphic.java index 044598cae4e..e130983e10a 100644 --- a/src/net/sourceforge/plantuml/ugraphic/AbstractUGraphic.java +++ b/src/net/sourceforge/plantuml/ugraphic/AbstractUGraphic.java @@ -38,6 +38,7 @@ import java.util.HashMap; import java.util.Map; +import net.sourceforge.plantuml.graphic.SpecialText; import net.sourceforge.plantuml.ugraphic.color.ColorMapper; public abstract class AbstractUGraphic extends AbstractCommonUGraphic { @@ -70,6 +71,10 @@ final protected void registerDriver(Class cl, UDriver drive } public final void draw(UShape shape) { + if (shape instanceof SpecialText) { + ((SpecialText) shape).getTitle().drawU(this); + return; + } if (shape instanceof UEmpty) { return; } diff --git a/src/net/sourceforge/plantuml/ugraphic/LimitFinder.java b/src/net/sourceforge/plantuml/ugraphic/LimitFinder.java index 7762a7efa84..bd1c55c3985 100644 --- a/src/net/sourceforge/plantuml/ugraphic/LimitFinder.java +++ b/src/net/sourceforge/plantuml/ugraphic/LimitFinder.java @@ -38,6 +38,8 @@ import java.awt.geom.Dimension2D; import net.sourceforge.plantuml.Url; +import net.sourceforge.plantuml.activitydiagram3.ftile.CenteredText; +import net.sourceforge.plantuml.graphic.SpecialText; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.posimo.DotPath; @@ -49,7 +51,7 @@ public class LimitFinder implements UGraphic { public boolean matchesProperty(String propertyName) { return false; } - + public double dpiFactor() { return 1; } @@ -141,6 +143,10 @@ public void draw(UShape shape) { tb.drawU(this); } else if (shape instanceof UCenteredCharacter) { // To be done + } else if (shape instanceof CenteredText) { + // Ignored + } else if (shape instanceof SpecialText) { + // Ignored } else if (shape instanceof UPixel) { addPoint(x, y); } else { diff --git a/src/net/sourceforge/plantuml/ugraphic/UPath.java b/src/net/sourceforge/plantuml/ugraphic/UPath.java index baf112ced6a..79a8d5ad227 100644 --- a/src/net/sourceforge/plantuml/ugraphic/UPath.java +++ b/src/net/sourceforge/plantuml/ugraphic/UPath.java @@ -40,13 +40,17 @@ import java.util.Iterator; import java.util.List; -public class UPath extends AbstractShadowable implements Iterable { +import net.sourceforge.plantuml.ugraphic.comp.CompressionMode; + +public class UPath extends AbstractShadowable implements Iterable, UShapeIgnorableForCompression { private final String comment; private final List segments = new ArrayList(); private MinMax minmax = MinMax.getEmpty(false); private boolean isOpenIconic; + private boolean ignoreForCompressionOnX; + private boolean ignoreForCompressionOnY; public UPath(String comment) { this.comment = comment; @@ -179,6 +183,27 @@ public final String getComment() { return comment; } + public void setIgnoreForCompressionOnX() { + this.ignoreForCompressionOnX = true; + } + + public void setIgnoreForCompressionOnY() { + this.ignoreForCompressionOnY = true; + } + + public void drawWhenCompressed(UGraphic ug, CompressionMode mode) { + } + + public boolean isIgnoreForCompressionOn(CompressionMode mode) { + if (mode == CompressionMode.ON_X) { + return ignoreForCompressionOnX; + } + if (mode == CompressionMode.ON_Y) { + return ignoreForCompressionOnY; + } + throw new IllegalArgumentException(); + } + // public boolean isEmpty() { // return segments.size() == 0; // } diff --git a/src/net/sourceforge/plantuml/ugraphic/UPolygon.java b/src/net/sourceforge/plantuml/ugraphic/UPolygon.java index 15cbd734d69..268ec1a9ffe 100644 --- a/src/net/sourceforge/plantuml/ugraphic/UPolygon.java +++ b/src/net/sourceforge/plantuml/ugraphic/UPolygon.java @@ -159,14 +159,14 @@ public double[] getPointArray(double x, double y) { return points; } - private CompressionMode ignoreForCompression; + private CompressionMode compressionMode; - public final CompressionMode isIgnoreForCompression() { - return ignoreForCompression; + public final CompressionMode getCompressionMode() { + return compressionMode; } - public final void setIgnoreForCompression(CompressionMode ignoreForCompression) { - this.ignoreForCompression = ignoreForCompression; + public final void setCompressionMode(CompressionMode compressionMode) { + this.compressionMode = compressionMode; } diff --git a/src/net/sourceforge/plantuml/ugraphic/URectangle.java b/src/net/sourceforge/plantuml/ugraphic/URectangle.java index d16cd23c9ef..aaab07f1b40 100644 --- a/src/net/sourceforge/plantuml/ugraphic/URectangle.java +++ b/src/net/sourceforge/plantuml/ugraphic/URectangle.java @@ -36,39 +36,42 @@ import java.awt.geom.Dimension2D; -public class URectangle extends AbstractShadowable implements Scalable, UShapeSized { +import net.sourceforge.plantuml.ugraphic.comp.CompressionMode; + +public class URectangle extends AbstractShadowable implements Scalable, UShapeSized, UShapeIgnorableForCompression { private final double width; private final double height; private final double rx; private final double ry; private final String comment; - private boolean ignoreForCompression; + private final boolean ignoreForCompressionOnX; + private final boolean ignoreForCompressionOnY; public URectangle withHeight(double newHeight) { - final URectangle result = new URectangle(width, newHeight, rx, ry, comment, ignoreForCompression); - result.ignoreForCompression = this.ignoreForCompression; + final URectangle result = new URectangle(width, newHeight, rx, ry, comment, ignoreForCompressionOnX, + ignoreForCompressionOnY); result.setDeltaShadow(this.getDeltaShadow()); return result; } public URectangle withWidth(double newWidth) { - final URectangle result = new URectangle(newWidth, height, rx, ry, comment, ignoreForCompression); - result.ignoreForCompression = this.ignoreForCompression; + final URectangle result = new URectangle(newWidth, height, rx, ry, comment, ignoreForCompressionOnX, + ignoreForCompressionOnY); result.setDeltaShadow(this.getDeltaShadow()); return result; } public URectangle withComment(String comment) { - return new URectangle(width, height, rx, ry, comment, ignoreForCompression); + return new URectangle(width, height, rx, ry, comment, ignoreForCompressionOnX, ignoreForCompressionOnY); } public URectangle rounded(double round) { - return new URectangle(width, height, round, round, comment, ignoreForCompression); + return new URectangle(width, height, round, round, comment, ignoreForCompressionOnX, ignoreForCompressionOnY); } public Shadowable diagonalCorner(double diagonalCorner) { - if (ignoreForCompression) { + if (ignoreForCompressionOnX || ignoreForCompressionOnY) { throw new IllegalStateException(); } if (diagonalCorner == 0) { @@ -87,8 +90,12 @@ public Shadowable diagonalCorner(double diagonalCorner) { return result; } - public final URectangle ignoreForCompression() { - return new URectangle(width, height, rx, ry, comment, true); + public final URectangle ignoreForCompressionOnX() { + return new URectangle(width, height, rx, ry, comment, true, ignoreForCompressionOnY); + } + + public final URectangle ignoreForCompressionOnY() { + return new URectangle(width, height, rx, ry, comment, ignoreForCompressionOnX, true); } public UShape getScaled(double scale) { @@ -96,13 +103,13 @@ public UShape getScaled(double scale) { return this; } final AbstractShadowable result = new URectangle(width * scale, height * scale, rx * scale, ry * scale, comment, - ignoreForCompression); + ignoreForCompressionOnX, ignoreForCompressionOnY); result.setDeltaShadow(this.getDeltaShadow()); return result; } public URectangle(double width, double height) { - this(width, height, 0, 0, null, false); + this(width, height, 0, 0, null, false, false); } public URectangle(Dimension2D dim) { @@ -110,14 +117,15 @@ public URectangle(Dimension2D dim) { } private URectangle(double width, double height, double rx, double ry, String comment, - boolean ignoreForCompression) { + boolean ignoreForCompressionOnX, boolean ignoreForCompressionOnY) { if (height == 0) { throw new IllegalArgumentException("height=" + height); } if (width == 0) { throw new IllegalArgumentException("width=" + width); } - this.ignoreForCompression = ignoreForCompression; + this.ignoreForCompressionOnX = ignoreForCompressionOnX; + this.ignoreForCompressionOnY = ignoreForCompressionOnY; this.comment = comment; this.width = width; this.height = height; @@ -158,8 +166,30 @@ public final String getComment() { return comment; } - public final boolean isIgnoreForCompression() { - return ignoreForCompression; + public void drawWhenCompressed(UGraphic ug, CompressionMode mode) { + if (mode == CompressionMode.ON_X) { + ug.draw(new UEmpty(2, getHeight())); + ug.apply(UTranslate.dx(getWidth() - 2)).draw(new UEmpty(2, getHeight())); +// drawEmpty(x, y, new UEmpty(2, shape.getHeight())); +// drawEmpty(x + shape.getWidth() - 2, y, new UEmpty(2, shape.getHeight())); + } + if (mode == CompressionMode.ON_Y) { + ug.draw(new UEmpty(getWidth(), 2)); + ug.apply(UTranslate.dy(getHeight() - 2)).draw(new UEmpty(getWidth(), 2)); +// drawEmpty(x, y, new UEmpty(shape.getWidth(), 2)); +// drawEmpty(x, y + shape.getHeight() - 2, new UEmpty(shape.getWidth(), 2)); + } + + } + + public boolean isIgnoreForCompressionOn(CompressionMode mode) { + if (mode == CompressionMode.ON_X) { + return ignoreForCompressionOnX; + } + if (mode == CompressionMode.ON_Y) { + return ignoreForCompressionOnY; + } + throw new IllegalArgumentException(); } } diff --git a/src/net/sourceforge/plantuml/ugraphic/UShapeIgnorableForCompression.java b/src/net/sourceforge/plantuml/ugraphic/UShapeIgnorableForCompression.java new file mode 100644 index 00000000000..11c9084b4c5 --- /dev/null +++ b/src/net/sourceforge/plantuml/ugraphic/UShapeIgnorableForCompression.java @@ -0,0 +1,46 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.ugraphic; + +import net.sourceforge.plantuml.ugraphic.comp.CompressionMode; + +public interface UShapeIgnorableForCompression extends UShape { + + public boolean isIgnoreForCompressionOn(CompressionMode mode); + + public void drawWhenCompressed(UGraphic ug, CompressionMode mode); + +} diff --git a/src/net/sourceforge/plantuml/ugraphic/comp/CompressionTransform.java b/src/net/sourceforge/plantuml/ugraphic/comp/CompressionTransform.java index add8d6cf44e..7f5383e47ff 100644 --- a/src/net/sourceforge/plantuml/ugraphic/comp/CompressionTransform.java +++ b/src/net/sourceforge/plantuml/ugraphic/comp/CompressionTransform.java @@ -37,7 +37,7 @@ import java.util.List; -public class CompressionTransform { +public class CompressionTransform implements PiecewiseAffineTransform { private final List all; diff --git a/src/net/sourceforge/plantuml/ugraphic/comp/CompressionXorYBuilder.java b/src/net/sourceforge/plantuml/ugraphic/comp/CompressionXorYBuilder.java new file mode 100644 index 00000000000..cdaf039b321 --- /dev/null +++ b/src/net/sourceforge/plantuml/ugraphic/comp/CompressionXorYBuilder.java @@ -0,0 +1,56 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.ugraphic.comp; + +import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.TextBlock; + +public class CompressionXorYBuilder { + + public static TextBlock build(CompressionMode mode, TextBlock textBlock, StringBounder stringBounder) { + final PiecewiseAffineTransform affine = getPiecewiseAffineTransform(mode, textBlock, stringBounder); + return PiecewiseAffineOnXorYBuilder.build(mode, textBlock, affine); + } + + private static PiecewiseAffineTransform getPiecewiseAffineTransform(CompressionMode mode, TextBlock textBlock, + StringBounder stringBounder) { + final SlotFinder slotFinder = new SlotFinder(mode, stringBounder); + textBlock.drawU(slotFinder); + final SlotSet ysSlotSet = slotFinder.getSlotSet().reverse().smaller(5.0); + return new CompressionTransform(ysSlotSet); + } + +} \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/ugraphic/comp/Expand.java b/src/net/sourceforge/plantuml/ugraphic/comp/Expand.java new file mode 100644 index 00000000000..1a02241c5a9 --- /dev/null +++ b/src/net/sourceforge/plantuml/ugraphic/comp/Expand.java @@ -0,0 +1,80 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.ugraphic.comp; + +public class Expand implements Comparable { + + private final double position; + private final double extend; + private final ExpandType type; + + public Expand(ExpandType type, double position, double extend) { + if (extend <= 0) { + throw new IllegalArgumentException(); + } + this.type = type; + this.position = position; + this.extend = extend; + } + + @Override + public String toString() { + return "(" + position + "==>+" + extend + " " + type + ")"; + } + + public int compareTo(Expand other) { + if (this.position < other.position) { + return -1; + } + if (this.position > other.position) { + return 1; + } + return 0; + } + + public final double getPosition() { + return position; + } + + public final double getExtend() { + return extend; + } + + public final ExpandType getType() { + return type; + } + +} diff --git a/src/net/sourceforge/plantuml/ugraphic/comp/ExpandTransform.java b/src/net/sourceforge/plantuml/ugraphic/comp/ExpandTransform.java new file mode 100644 index 00000000000..892e19ed3b2 --- /dev/null +++ b/src/net/sourceforge/plantuml/ugraphic/comp/ExpandTransform.java @@ -0,0 +1,71 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.ugraphic.comp; + +import java.util.Set; +import java.util.TreeSet; + +public class ExpandTransform implements PiecewiseAffineTransform { + + private final Set all = new TreeSet(); + + @Override + public String toString() { + return all.toString(); + } + + public void addExpandIncludingLimit(double position, double extend) { + this.all.add(new Expand(ExpandType.INCLUDING_LIMIT, position, extend)); + } + + public void addExpandExcludingLimit(double position, double extend) { + this.all.add(new Expand(ExpandType.EXCLUDING_LIMIT, position, extend)); + } + + public double transform(final double init) { + double result = init; + for (Expand expand : all) { + if (ExpandType.INCLUDING_LIMIT == expand.getType() && init >= expand.getPosition()) { + result += expand.getExtend(); + } + if (ExpandType.EXCLUDING_LIMIT == expand.getType() && init > expand.getPosition()) { + result += expand.getExtend(); + } + } + return result; + } + +} diff --git a/src/net/sourceforge/plantuml/ugraphic/comp/ExpandType.java b/src/net/sourceforge/plantuml/ugraphic/comp/ExpandType.java new file mode 100644 index 00000000000..1d5d67abbad --- /dev/null +++ b/src/net/sourceforge/plantuml/ugraphic/comp/ExpandType.java @@ -0,0 +1,42 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.ugraphic.comp; + +public enum ExpandType { + + INCLUDING_LIMIT, EXCLUDING_LIMIT + +} diff --git a/src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineComposition.java b/src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineComposition.java new file mode 100644 index 00000000000..e86b288207c --- /dev/null +++ b/src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineComposition.java @@ -0,0 +1,52 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.ugraphic.comp; + +public class PiecewiseAffineComposition implements PiecewiseAffineTransform { + + private final PiecewiseAffineComposition first; + private final PiecewiseAffineComposition second; + + public PiecewiseAffineComposition(PiecewiseAffineComposition first, PiecewiseAffineComposition second) { + this.first = first; + this.second = second; + } + + public double transform(double v) { + return second.transform(first.transform(v)); + } + +} diff --git a/src/net/sourceforge/plantuml/ugraphic/comp/TextBlockCompressedOnXorY.java b/src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineOnXorYBuilder.java similarity index 62% rename from src/net/sourceforge/plantuml/ugraphic/comp/TextBlockCompressedOnXorY.java rename to src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineOnXorYBuilder.java index ba680ee4413..2697a2fb6ec 100644 --- a/src/net/sourceforge/plantuml/ugraphic/comp/TextBlockCompressedOnXorY.java +++ b/src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineOnXorYBuilder.java @@ -42,23 +42,31 @@ import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlockUtils; +import net.sourceforge.plantuml.svek.TextBlockBackcolored; import net.sourceforge.plantuml.ugraphic.MinMax; import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.color.HColor; -public class TextBlockCompressedOnXorY extends AbstractTextBlock implements TextBlock { +public class PiecewiseAffineOnXorYBuilder extends AbstractTextBlock implements TextBlock, TextBlockBackcolored { private final TextBlock textBlock; private final CompressionMode mode; + private final PiecewiseAffineTransform piecewiseAffineTransform; - public TextBlockCompressedOnXorY(CompressionMode mode, TextBlock textBlock) { + public static TextBlock build(CompressionMode mode, TextBlock textBlock, + PiecewiseAffineTransform piecewiseAffineTransform) { + return new PiecewiseAffineOnXorYBuilder(mode, textBlock, piecewiseAffineTransform); + } + + private PiecewiseAffineOnXorYBuilder(CompressionMode mode, TextBlock textBlock, + PiecewiseAffineTransform piecewiseAffineTransform) { this.textBlock = textBlock; this.mode = mode; + this.piecewiseAffineTransform = piecewiseAffineTransform; } public void drawU(final UGraphic ug) { - final StringBounder stringBounder = ug.getStringBounder(); - final CompressionTransform compressionTransform = getCompressionTransform(stringBounder); - textBlock.drawU(new UGraphicCompressOnXorY(mode, ug, compressionTransform)); + textBlock.drawU(new UGraphicCompressOnXorY(mode, ug, piecewiseAffineTransform)); } private MinMax cachedMinMax; @@ -71,30 +79,17 @@ public MinMax getMinMax(StringBounder stringBounder) { return cachedMinMax; } - private CompressionTransform cachedCompressionTransform; - - private CompressionTransform getCompressionTransform(final StringBounder stringBounder) { - if (cachedCompressionTransform == null) { - cachedCompressionTransform = getCompressionTransformSlow(stringBounder); - } - return cachedCompressionTransform; - } - - private CompressionTransform getCompressionTransformSlow(final StringBounder stringBounder) { - final SlotFinder slotFinder = new SlotFinder(mode, stringBounder); - textBlock.drawU(slotFinder); - final SlotSet ysSlotSet = slotFinder.getSlotSet().reverse().smaller(5.0); - final CompressionTransform compressionTransform = new CompressionTransform(ysSlotSet); - return compressionTransform; - } - public Dimension2D calculateDimension(StringBounder stringBounder) { - final CompressionTransform compressionTransform = getCompressionTransform(stringBounder); final Dimension2D dim = textBlock.calculateDimension(stringBounder); if (mode == CompressionMode.ON_X) { - return new Dimension2DDouble(compressionTransform.transform(dim.getWidth()), dim.getHeight()); + return new Dimension2DDouble(piecewiseAffineTransform.transform(dim.getWidth()), dim.getHeight()); } else { - return new Dimension2DDouble(dim.getWidth(), compressionTransform.transform(dim.getHeight())); + return new Dimension2DDouble(dim.getWidth(), piecewiseAffineTransform.transform(dim.getHeight())); } } + + public HColor getBackcolor() { + return null; + } + } \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineTransform.java b/src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineTransform.java new file mode 100644 index 00000000000..65ab0065937 --- /dev/null +++ b/src/net/sourceforge/plantuml/ugraphic/comp/PiecewiseAffineTransform.java @@ -0,0 +1,41 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML 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. + * + * PlantUML 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.ugraphic.comp; + +public interface PiecewiseAffineTransform { + + public double transform(double v); +} diff --git a/src/net/sourceforge/plantuml/ugraphic/comp/SlotFinder.java b/src/net/sourceforge/plantuml/ugraphic/comp/SlotFinder.java index f2352a8fb5c..5d3cf5c79a2 100644 --- a/src/net/sourceforge/plantuml/ugraphic/comp/SlotFinder.java +++ b/src/net/sourceforge/plantuml/ugraphic/comp/SlotFinder.java @@ -50,6 +50,7 @@ import net.sourceforge.plantuml.ugraphic.UPolygon; import net.sourceforge.plantuml.ugraphic.URectangle; import net.sourceforge.plantuml.ugraphic.UShape; +import net.sourceforge.plantuml.ugraphic.UShapeIgnorableForCompression; import net.sourceforge.plantuml.ugraphic.UStroke; import net.sourceforge.plantuml.ugraphic.UText; import net.sourceforge.plantuml.ugraphic.UTranslate; @@ -108,32 +109,30 @@ public UParam getParam() { return new UParamNull(); } - public void draw(UShape shape) { + public void draw(UShape sh) { final double x = translate.getDx(); final double y = translate.getDy(); - if (shape instanceof URectangle) { - final URectangle rect = (URectangle) shape; - if (mode == CompressionMode.ON_X && rect.isIgnoreForCompression()) { - drawRectangle(x, y, new URectangle(2, rect.getHeight())); - drawRectangle(x + rect.getWidth() - 2, y, new URectangle(2, rect.getHeight())); + if (sh instanceof UShapeIgnorableForCompression) { + final UShapeIgnorableForCompression shape = (UShapeIgnorableForCompression) sh; + if (shape.isIgnoreForCompressionOn(mode)) { + shape.drawWhenCompressed(this, mode); return; } - if (mode == CompressionMode.ON_Y && rect.isIgnoreForCompression()) { - drawRectangle(x, y, new URectangle(rect.getWidth(), 2)); - drawRectangle(x, y + rect.getHeight() - 2, new URectangle(rect.getWidth(), 2)); - return; - } - drawRectangle(x, y, (URectangle) shape); - } else if (shape instanceof UPath) { - drawPath(x, y, (UPath) shape); - } else if (shape instanceof UPolygon) { - drawPolygon(x, y, (UPolygon) shape); - } else if (shape instanceof UEllipse) { - drawEllipse(x, y, (UEllipse) shape); - } else if (shape instanceof UText) { - drawText(x, y, (UText) shape); - } else if (shape instanceof UEmpty) { - drawEmpty(x, y, (UEmpty) shape); + + } + if (sh instanceof URectangle) { + drawRectangle(x, y, (URectangle) sh); + } else if (sh instanceof UPath) { + drawPath(x, y, (UPath) sh); + } else if (sh instanceof UPolygon) { + drawPolygon(x, y, (UPolygon) sh); + } else if (sh instanceof UEllipse) { + drawEllipse(x, y, (UEllipse) sh); + } else if (sh instanceof UText) { + final UText text = (UText) sh; + drawText(x, y, text); + } else if (sh instanceof UEmpty) { + drawEmpty(x, y, (UEmpty) sh); } } @@ -173,7 +172,7 @@ private void drawEllipse(double x, double y, UEllipse shape) { } private void drawPolygon(double x, double y, UPolygon shape) { - if (mode == shape.isIgnoreForCompression()) { + if (mode == shape.getCompressionMode()) { return; } if (mode == CompressionMode.ON_X) { diff --git a/src/net/sourceforge/plantuml/ugraphic/comp/UGraphicCompressOnXorY.java b/src/net/sourceforge/plantuml/ugraphic/comp/UGraphicCompressOnXorY.java index ea01395ebca..94dc6654be0 100644 --- a/src/net/sourceforge/plantuml/ugraphic/comp/UGraphicCompressOnXorY.java +++ b/src/net/sourceforge/plantuml/ugraphic/comp/UGraphicCompressOnXorY.java @@ -35,6 +35,8 @@ */ package net.sourceforge.plantuml.ugraphic.comp; +import net.sourceforge.plantuml.activitydiagram3.ftile.CenteredText; +import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.UGraphicDelegator; import net.sourceforge.plantuml.ugraphic.UChange; import net.sourceforge.plantuml.ugraphic.UChangeBackColor; @@ -50,7 +52,8 @@ public class UGraphicCompressOnXorY extends UGraphicDelegator { public UGraphic apply(UChange change) { if (change instanceof UTranslate) { - return new UGraphicCompressOnXorY(mode, getUg(), compressionTransform, translate.compose((UTranslate) change)); + return new UGraphicCompressOnXorY(mode, getUg(), compressionTransform, + translate.compose((UTranslate) change)); } else if (change instanceof UStroke || change instanceof UChangeBackColor || change instanceof UChangeColor) { return new UGraphicCompressOnXorY(mode, getUg().apply(change), compressionTransform, translate); } @@ -58,14 +61,19 @@ public UGraphic apply(UChange change) { } private final CompressionMode mode; - private final CompressionTransform compressionTransform; + private final PiecewiseAffineTransform compressionTransform; private final UTranslate translate; - public UGraphicCompressOnXorY(CompressionMode mode, UGraphic ug, CompressionTransform compressionTransform) { + @Override + public String toString() { + return "UGraphicCompressOnXorY " + mode; + } + + public UGraphicCompressOnXorY(CompressionMode mode, UGraphic ug, PiecewiseAffineTransform compressionTransform) { this(mode, ug, compressionTransform, new UTranslate()); } - private UGraphicCompressOnXorY(CompressionMode mode, UGraphic ug, CompressionTransform compressionTransform, + private UGraphicCompressOnXorY(CompressionMode mode, UGraphic ug, PiecewiseAffineTransform compressionTransform, UTranslate translate) { super(ug); this.mode = mode; @@ -78,24 +86,41 @@ public void draw(UShape shape) { final double y = translate.getDy(); if (shape instanceof URectangle) { final URectangle rect = (URectangle) shape; - if (rect.isIgnoreForCompression()) { - if (mode == CompressionMode.ON_X) { - final double x2 = ct(x + rect.getWidth()); - shape = rect.withWidth(x2 - ct(x)); - } else { - final double y2 = ct(y + rect.getHeight()); - shape = rect.withHeight(y2 - ct(y)); - } + if (mode == CompressionMode.ON_X) { + final double x2 = ct(x + rect.getWidth()); + shape = rect.withWidth(x2 - ct(x)); + } else { + final double y2 = ct(y + rect.getHeight()); + shape = rect.withHeight(y2 - ct(y)); } } - if (shape instanceof ULine) { - drawLine(x, y, (ULine) shape); - } else { + if (shape instanceof CenteredText) { + final CenteredText centeredText = (CenteredText) shape; + final TextBlock text = centeredText.getText(); + final double totalWidth = centeredText.getTotalWidth(); + final double realSpaceWidth; if (mode == CompressionMode.ON_X) { - getUg().apply(new UTranslate(ct(x), y)).draw(shape); + realSpaceWidth = ct(x + totalWidth) - ct(x); } else { - getUg().apply(new UTranslate(x, ct(y))).draw(shape); + realSpaceWidth = totalWidth; } + final double textWidth = text.calculateDimension(getStringBounder()).getWidth(); + final double pos = (realSpaceWidth - textWidth) / 2; + text.drawU(getUg().apply(getTranslate(x, y)).apply(UTranslate.dx(pos))); + return; + } + if (shape instanceof ULine) { + drawLine(x, y, (ULine) shape); + } else { + getUg().apply(getTranslate(x, y)).draw(shape); + } + } + + private UTranslate getTranslate(final double x, final double y) { + if (mode == CompressionMode.ON_X) { + return new UTranslate(ct(x), y); + } else { + return new UTranslate(x, ct(y)); } } diff --git a/src/net/sourceforge/plantuml/version/Version.java b/src/net/sourceforge/plantuml/version/Version.java index 10a8b319e53..cab610f7fe8 100644 --- a/src/net/sourceforge/plantuml/version/Version.java +++ b/src/net/sourceforge/plantuml/version/Version.java @@ -43,7 +43,7 @@ public class Version { private static final int MAJOR_SEPARATOR = 1000000; public static int version() { - return 1202004; + return 1202006; } public static int versionPatched() { @@ -92,7 +92,7 @@ public static String turningId() { } public static long compileTime() { - return 1584613009502L; + return 1586090312827L; } public static String compileTimeString() { diff --git a/stdlib/logos-abx.repx b/stdlib/logos-abx.repx index 1daaef51291ab2a961c2116af02bef6d58d8072e..58a01eb95e4f6ee62a1036abc7a17aca6a0354bf 100644 GIT binary patch delta 10994 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 delta 10931 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 VKdExN_z09$&v&`l6s-fZ{{_cqYB&G@ diff --git a/stdlib/logos-dex.repx b/stdlib/logos-dex.repx index 02e926f9ebd12a5eda64ce824a8bf6e2f39b4419..b419225b6ce5c3b9c6e1c518dba7a33131a823c8 100644 GIT binary patch literal 273188 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%0Aaqj}PId8Z%3nCbbY6NCHcP-WzjyTb2;pmdC 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
    G$2(qR{{TmO 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 `SOLh&^^@0pbn;*)X8enQ$Dd6EbUQ@H_lHhrn-L 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�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 w5&1LK;or!3?Wz+fCk=@^B%yY2O;?nl&M<-U%Q^

    Khf;hpc$w&Jh?G*N<^gYk@ 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 S(B@_vx}vOMYADL@_16H0B8M#i literal 273114 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