All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.plantuml.sequencediagram.graphic.SequenceDiagramFileMakerPuma Maven / Gradle / Ivy

Go to download

PlantUML is a component that allows to quickly write : * sequence diagram, * use case diagram, * class diagram, * activity diagram, * component diagram, * state diagram * object diagram

There is a newer version: 8059
Show newest version
/* ========================================================================
 * PlantUML : a free UML diagram generator
 * ========================================================================
 *
 * (C) Copyright 2009-2013, Arnaud Roques
 *
 * Project Info:  http://plantuml.sourceforge.net
 * 
 * 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.
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
 * in the United States and other countries.]
 *
 * Original Author:  Arnaud Roques
 * 
 * Revision $Revision: 9591 $
 *
 */
package net.sourceforge.plantuml.sequencediagram.graphic;

import java.awt.Color;
import java.awt.geom.AffineTransform;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import net.sourceforge.plantuml.CMapData;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.FileFormat;
import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.activitydiagram3.ftile.EntityImageLegend;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.eps.EpsStrategy;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.HtmlColorGradient;
import net.sourceforge.plantuml.graphic.HtmlColorSimple;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.StringBounderUtils;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.png.PngTitler;
import net.sourceforge.plantuml.sequencediagram.Event;
import net.sourceforge.plantuml.sequencediagram.LifeEvent;
import net.sourceforge.plantuml.sequencediagram.LifeEventType;
import net.sourceforge.plantuml.sequencediagram.Message;
import net.sourceforge.plantuml.sequencediagram.Newpage;
import net.sourceforge.plantuml.sequencediagram.Participant;
import net.sourceforge.plantuml.sequencediagram.SequenceDiagram;
import net.sourceforge.plantuml.skin.Area;
import net.sourceforge.plantuml.skin.Component;
import net.sourceforge.plantuml.skin.ComponentType;
import net.sourceforge.plantuml.skin.SimpleContext2D;
import net.sourceforge.plantuml.skin.Skin;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.eps.UGraphicEps;
import net.sourceforge.plantuml.ugraphic.g2d.UGraphicG2d;
import net.sourceforge.plantuml.ugraphic.html5.UGraphicHtml5;
import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg;
import net.sourceforge.plantuml.ugraphic.visio.UGraphicVdx;

public class SequenceDiagramFileMakerPuma implements FileMaker {

	private static final StringBounder dummyStringBounder;

	static {
		final BufferedImage imDummy = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
		dummyStringBounder = StringBounderUtils.asStringBounder(imDummy.createGraphics());
	}

	private final SequenceDiagram diagram;
	private final DrawableSet drawableSet;
	private final Dimension2D fullDimension;
	private final List pages;
	private final FileFormatOption fileFormatOption;
	private final List flashcodes;

	private int offsetX;
	private int offsetY;

	public SequenceDiagramFileMakerPuma(SequenceDiagram sequenceDiagram, Skin skin, FileFormatOption fileFormatOption,
			List flashcodes) {
		// HtmlColor.setForceMonochrome(sequenceDiagram.getSkinParam().isMonochrome());
		this.flashcodes = flashcodes;
		this.diagram = sequenceDiagram;
		this.fileFormatOption = fileFormatOption;
		final DrawableSetInitializer initializer = new DrawableSetInitializer(skin, sequenceDiagram.getSkinParam(),
				sequenceDiagram.isShowFootbox(), sequenceDiagram.getAutonewpage());

		for (Participant p : sequenceDiagram.participants().values()) {
			initializer.addParticipant(p, sequenceDiagram.getEnglober(p));
		}

		for (Event ev : sequenceDiagram.events()) {
			initializer.addEvent(ev);
			if (ev instanceof Message) {
				// TODO mieux faire
				final Message m = (Message) ev;
				for (LifeEvent lifeEvent : m.getLiveEvents()) {
					if (lifeEvent.getType() == LifeEventType.DESTROY
					/*
					 * || lifeEvent.getType() == LifeEventType.CREATE
					 */) {
						initializer.addEvent(lifeEvent);
					}
				}
			}
		}
		drawableSet = initializer.createDrawableSet(dummyStringBounder);
		final List newpages = new ArrayList();
		for (Event ev : drawableSet.getAllEvents()) {
			if (ev instanceof Newpage) {
				newpages.add((Newpage) ev);
			}
		}
		fullDimension = drawableSet.getDimension();
		final Map positions = new LinkedHashMap();
		for (Newpage n : newpages) {
			positions.put(n, initializer.getYposition(dummyStringBounder, n));
		}
		pages = create(drawableSet, positions, sequenceDiagram.isShowFootbox(), sequenceDiagram.getTitle()).getPages();
	}

	public int getNbPages() {
		return pages.size();
	}

	private PageSplitter create(DrawableSet drawableSet, Map positions, boolean showFootbox,
			Display title) {

		final double headerHeight = drawableSet.getHeadHeight(dummyStringBounder);
		final double tailHeight = drawableSet.getTailHeight(dummyStringBounder, showFootbox);
		final double signatureHeight = 0;
		final double newpageHeight = drawableSet.getSkin()
				.createComponent(ComponentType.NEWPAGE, null, drawableSet.getSkinParam(), Display.asList(""))
				.getPreferredHeight(dummyStringBounder);

		return new PageSplitter(fullDimension.getHeight(), headerHeight, positions, tailHeight, signatureHeight,
				newpageHeight, title);
	}

	public Dimension2D createOne(OutputStream os, int index) throws IOException {
		final UGraphic createImage = createImage((int) fullDimension.getWidth(), pages.get(index), index);
		createImage.writeImage(os, diagram.getMetadata(), diagram.getDpi(fileFormatOption));
		return new Dimension2DDouble(fullDimension.getWidth(), fullDimension.getHeight());
	}

	private double getImageWidth(SequenceDiagramArea area, boolean rotate, double dpiFactor, double legendWidth) {
		final int minsize = diagram.getMinwidth();
		final double w = Math.max(getImageWidthWithoutMinsize(area, rotate, dpiFactor), legendWidth);
		if (minsize == Integer.MAX_VALUE) {
			return w;
		}
		if (w >= minsize) {
			return w;
		}
		return minsize;
	}

	private double getScale(double width, double height) {
		if (diagram.getScale() == null) {
			return 1;
		}
		return diagram.getScale().getScale(width, height);
	}

	private double getImageWidthWithoutMinsize(SequenceDiagramArea area, boolean rotate, double dpiFactor) {
		final double w;
		if (rotate) {
			w = area.getHeight() * getScale(area.getWidth(), area.getHeight()) * dpiFactor;
		} else {
			w = area.getWidth() * getScale(area.getWidth(), area.getHeight()) * dpiFactor;
		}
		return w;
	}

	private double getImageHeight(SequenceDiagramArea area, final Page page, boolean rotate, double dpiFactor) {
		if (rotate) {
			return area.getWidth() * getScale(area.getWidth(), area.getHeight()) * dpiFactor;
		}
		return area.getHeight() * getScale(area.getWidth(), area.getHeight()) * dpiFactor;
	}

	private UGraphic createImage(final int diagramWidth, final Page page, final int indice) {
		double delta = 0;
		if (indice > 0) {
			delta = page.getNewpage1() - page.getHeaderHeight();
		}
		if (delta < 0) {
			delta = 0;
		}

		final SequenceDiagramArea area = new SequenceDiagramArea(diagramWidth, page.getHeight());

		Component compTitle = null;

		if (page.getTitle() != null) {
			compTitle = drawableSet.getSkin().createComponent(ComponentType.TITLE, null, drawableSet.getSkinParam(),
					page.getTitle());
			area.setTitleArea(compTitle.getPreferredWidth(dummyStringBounder),
					compTitle.getPreferredHeight(dummyStringBounder));
		}
		addFooter2(area);
		addHeader2(area);

		offsetX = (int) Math.round(area.getSequenceAreaX());
		offsetY = (int) Math.round(area.getSequenceAreaY());

		Color backColor = null;
		if (diagram.getSkinParam().getBackgroundColor() instanceof HtmlColorSimple) {
			backColor = diagram.getSkinParam().getColorMapper()
					.getMappedColor(diagram.getSkinParam().getBackgroundColor());
		}
		final FileFormat fileFormat = fileFormatOption.getFileFormat();
		final double dpiFactor = diagram.getDpiFactor(fileFormatOption);

		final Display legend = diagram.getLegend();
		final TextBlock legendBlock;
		if (legend == null) {
			legendBlock = TextBlockUtils.empty(0, 0);
		} else {
			legendBlock = EntityImageLegend.create(legend, diagram.getSkinParam());
		}
		final Dimension2D dimLegend = TextBlockUtils.getDimension(legendBlock);

		UGraphic ug;
		if (fileFormat == FileFormat.PNG) {
			double imageHeight = getImageHeight(area, page, diagram.isRotation(), 1);
			if (imageHeight == 0) {
				imageHeight = 1;
			}
			double flashCodeHeight = 0;
			if (flashcodes != null) {
				flashCodeHeight = flashcodes.get(0).getHeight();
			}

			final Dimension2D dim;
			final double imageWidthWithDpi = getImageWidth(area, diagram.isRotation(), 1, dimLegend.getWidth());
			if (diagram.isRotation()) {
				dim = new Dimension2DDouble(imageHeight + dimLegend.getHeight(), imageWidthWithDpi + flashCodeHeight);
			} else {
				dim = new Dimension2DDouble(imageWidthWithDpi, imageHeight + flashCodeHeight + dimLegend.getHeight());
			}

			ug = fileFormatOption.createUGraphic(diagram.getSkinParam().getColorMapper(), dpiFactor, dim, diagram
					.getSkinParam().getBackgroundColor(), diagram.isRotation());

			if (flashcodes != null) {
				((UGraphicG2d) ug).getGraphics2D().drawImage(flashcodes.get(0), null, 0, (int) imageHeight);
			}
			final AffineTransform scale = ((UGraphicG2d) ug).getGraphics2D().getTransform();
			scale.scale(getScale(area.getWidth(), area.getHeight()), getScale(area.getWidth(), area.getHeight()));
			((UGraphicG2d) ug).getGraphics2D().setTransform(scale);
		} else if (fileFormat == FileFormat.SVG) {
			if (diagram.getSkinParam().getBackgroundColor() instanceof HtmlColorGradient) {
				ug = new UGraphicSvg(diagram.getSkinParam().getColorMapper(), (HtmlColorGradient) diagram
						.getSkinParam().getBackgroundColor(), false);
			} else if (backColor == null || backColor.equals(Color.WHITE)) {
				ug = new UGraphicSvg(diagram.getSkinParam().getColorMapper(), false);
			} else {
				ug = new UGraphicSvg(diagram.getSkinParam().getColorMapper(), StringUtils.getAsHtml(backColor), false);
			}
		} else if (fileFormat == FileFormat.EPS) {
			ug = new UGraphicEps(diagram.getSkinParam().getColorMapper(), EpsStrategy.getDefault2());
		} else if (fileFormat == FileFormat.EPS_TEXT) {
			ug = new UGraphicEps(diagram.getSkinParam().getColorMapper(), EpsStrategy.WITH_MACRO_AND_TEXT);
		} else if (fileFormat == FileFormat.HTML5) {
			ug = new UGraphicHtml5(diagram.getSkinParam().getColorMapper());
		} else if (fileFormat == FileFormat.VDX) {
			ug = new UGraphicVdx(diagram.getSkinParam().getColorMapper());
		} else {
			throw new UnsupportedOperationException();
		}

		if (compTitle != null) {
			final StringBounder stringBounder = ug.getStringBounder();
			final double h = compTitle.getPreferredHeight(stringBounder);
			final double w = compTitle.getPreferredWidth(stringBounder);
			compTitle.drawU(ug.apply(new UTranslate(area.getTitleX(), area.getTitleY())), new Area(
					new Dimension2DDouble(w, h)), new SimpleContext2D(false));
		}

		addHeader3(area, ug);
		addFooter3(area, ug);

		final double delta1 = Math.max(0, dimLegend.getWidth() - area.getWidth());
		// bugnewway X*58
		drawableSet.drawU(ug.apply(new UTranslate(area.getSequenceAreaX() + delta1 / 2, area.getSequenceAreaY())),
				delta, diagramWidth, page, diagram.isShowFootbox());

		if (legend != null) {
			final double delta2;
			if (diagram.getLegendAlignment() == HorizontalAlignment.LEFT) {
				delta2 = 0;
			} else if (diagram.getLegendAlignment() == HorizontalAlignment.RIGHT) {
				delta2 = Math.max(0, area.getWidth() - dimLegend.getWidth());
			} else {
				delta2 = Math.max(0, area.getWidth() - dimLegend.getWidth()) / 2;
			}
			legendBlock.drawU(ug.apply(new UTranslate(delta2, area.getHeight())));
		}

		return ug;
	}

	private void addFooter2(SequenceDiagramArea area) {
		final HtmlColor titleColor = diagram.getSkinParam().getFontHtmlColor(FontParam.FOOTER, null);
		final String fontFamily = diagram.getSkinParam().getFont(FontParam.FOOTER, null).getFamily(null);
		final int fontSize = diagram.getSkinParam().getFont(FontParam.FOOTER, null).getSize();
		final PngTitler pngTitler = new PngTitler(titleColor, diagram.getFooter(), fontSize, fontFamily,
				diagram.getFooterAlignment());
		final Dimension2D dim = pngTitler.getTextDimension(dummyStringBounder);
		if (dim != null) {
			area.setFooterArea(dim.getWidth(), dim.getHeight(), 3);
		}
	}

	private void addHeader2(SequenceDiagramArea area) {
		final HtmlColor titleColor = diagram.getSkinParam().getFontHtmlColor(FontParam.HEADER, null);
		final String fontFamily = diagram.getSkinParam().getFont(FontParam.HEADER, null).getFamily(null);
		final int fontSize = diagram.getSkinParam().getFont(FontParam.HEADER, null).getSize();
		final PngTitler pngTitler = new PngTitler(titleColor, diagram.getHeader(), fontSize, fontFamily,
				diagram.getHeaderAlignment());
		final Dimension2D dim = pngTitler.getTextDimension(dummyStringBounder);
		if (dim != null) {
			area.setHeaderArea(dim.getWidth(), dim.getHeight(), 3);
		}
	}

	private void addFooter3(SequenceDiagramArea area, UGraphic ug) {
		final HtmlColor titleColor = diagram.getSkinParam().getFontHtmlColor(FontParam.FOOTER, null);
		final String fontFamily = diagram.getSkinParam().getFont(FontParam.FOOTER, null).getFamily(null);
		final int fontSize = diagram.getSkinParam().getFont(FontParam.FOOTER, null).getSize();
		final PngTitler pngTitler = new PngTitler(titleColor, diagram.getFooter(), fontSize, fontFamily,
				diagram.getFooterAlignment());
		final TextBlock text = pngTitler.getTextBlock();
		if (text == null) {
			return;
		}
		text.drawU(ug.apply(new UTranslate(area.getFooterX(diagram.getFooterAlignment()), area.getFooterY())));
	}

	private void addHeader3(SequenceDiagramArea area, UGraphic ug) {
		final HtmlColor titleColor = diagram.getSkinParam().getFontHtmlColor(FontParam.HEADER, null);
		final String fontFamily = diagram.getSkinParam().getFont(FontParam.HEADER, null).getFamily(null);
		final int fontSize = diagram.getSkinParam().getFont(FontParam.HEADER, null).getSize();
		final PngTitler pngTitler = new PngTitler(titleColor, diagram.getHeader(), fontSize, fontFamily,
				diagram.getHeaderAlignment());
		final TextBlock text = pngTitler.getTextBlock();
		if (text == null) {
			return;
		}
		text.drawU(ug.apply(new UTranslate(area.getHeaderX(diagram.getHeaderAlignment()), area.getHeaderY())));
	}

	public static StringBounder getDummystringbounder() {
		return dummyStringBounder;
	}

	public void appendCmap(CMapData cmap) {
		drawableSet.appendCmap(cmap, offsetX, offsetY, dummyStringBounder, diagram);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy