plantuml/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeo...

273 lines
10 KiB
Java

/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, 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.sequencediagram.teoz;
import java.awt.geom.Dimension2D;
import java.io.IOException;
import java.io.OutputStream;
import net.sourceforge.plantuml.AnnotatedWorker;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.activitydiagram3.ftile.EntityImageLegend;
import net.sourceforge.plantuml.core.ImageData;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.DisplaySection;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.graphic.VerticalAlignment;
import net.sourceforge.plantuml.png.PngTitler;
import net.sourceforge.plantuml.real.Real;
import net.sourceforge.plantuml.real.RealOrigin;
import net.sourceforge.plantuml.real.RealUtils;
import net.sourceforge.plantuml.sequencediagram.Participant;
import net.sourceforge.plantuml.sequencediagram.SequenceDiagram;
import net.sourceforge.plantuml.sequencediagram.graphic.FileMaker;
import net.sourceforge.plantuml.skin.SimpleContext2D;
import net.sourceforge.plantuml.skin.Skin;
import net.sourceforge.plantuml.ugraphic.ImageBuilder;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.utils.MathUtils;
public class SequenceDiagramFileMakerTeoz implements FileMaker {
private final SequenceDiagram diagram;
private final FileFormatOption fileFormatOption;
private final Skin skin;
private final AnnotatedWorker annotatedWorker;
public SequenceDiagramFileMakerTeoz(SequenceDiagram sequenceDiagram, Skin skin, FileFormatOption fileFormatOption) {
this.stringBounder = fileFormatOption.getDefaultStringBounder();
this.diagram = sequenceDiagram;
this.fileFormatOption = fileFormatOption;
this.skin = skin;
this.footer = getFooterOrHeader(FontParam.FOOTER);
this.header = getFooterOrHeader(FontParam.HEADER);
this.annotatedWorker = new AnnotatedWorker(sequenceDiagram, sequenceDiagram.getSkinParam());
this.main = new MainTileAdapter(createMainTile());
this.min1 = ((MainTileAdapter) main).getMinX(stringBounder);
this.title = getTitle();
this.legend = getLegend();
this.caption = annotatedWorker.getCaption();
this.heightEnglober1 = englobers.getOffsetForEnglobers(stringBounder);
this.heightEnglober2 = heightEnglober1 == 0 ? 0 : 10;
final double totalWidth = MathUtils.max(main.calculateDimension(stringBounder).getWidth(), title
.calculateDimension(stringBounder).getWidth(), footer.calculateDimension(stringBounder).getWidth(),
header.calculateDimension(stringBounder).getWidth(), legend.calculateDimension(stringBounder)
.getWidth());
final double totalHeight = main.calculateDimension(stringBounder).getHeight() + heightEnglober1
+ heightEnglober2 + title.calculateDimension(stringBounder).getHeight()
+ header.calculateDimension(stringBounder).getHeight()
+ legend.calculateDimension(stringBounder).getHeight()
+ footer.calculateDimension(stringBounder).getHeight();
this.dimTotal = new Dimension2DDouble(totalWidth, totalHeight);
}
private Englobers englobers;
private final StringBounder stringBounder;
private final TextBlock footer;
private final TextBlock header;
private final TextBlock main;
private final TextBlock title;
private final TextBlock legend;
private final TextBlock caption;
private final Dimension2D dimTotal;
private final Real min1;
private final LivingSpaces livingSpaces = new LivingSpaces();
private final double heightEnglober1;
private final double heightEnglober2;
private double oneOf(double a, double b) {
if (a == 1) {
return b;
}
return a;
}
public ImageData createOne(OutputStream os, int index, boolean isWithMetadata) throws IOException {
final UTranslate min1translate = new UTranslate(-min1.getCurrentValue(), 0);
final double dpiFactor = diagram.getDpiFactor(fileFormatOption, dimTotal);
final double scale = 1;
final String metadata = fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null;
final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam(), oneOf(scale, dpiFactor), metadata,
null, 3, 10, diagram.getAnimation());
imageBuilder.setUDrawable(new UDrawable() {
public void drawU(UGraphic ug) {
ug = ug.apply(min1translate);
englobers.drawEnglobers(goDownAndCenterForEnglobers(ug), main.calculateDimension(stringBounder)
.getHeight() + heightEnglober1 + heightEnglober2 / 2, new SimpleContext2D(true));
printAligned(ug, diagram.getFooterOrHeaderTeoz(FontParam.HEADER).getHorizontalAlignment(), header);
ug = goDown(ug, header);
printAligned(ug, HorizontalAlignment.CENTER, title);
ug = goDown(ug, title);
if (diagram.getLegend().getVerticalAlignment() == VerticalAlignment.TOP) {
printAligned(ug, diagram.getLegend().getHorizontalAlignment(), legend);
ug = goDown(ug, legend);
}
ug = ug.apply(new UTranslate(0, heightEnglober1));
printAligned(ug, HorizontalAlignment.CENTER, main);
ug = goDown(ug, main);
ug = ug.apply(new UTranslate(0, heightEnglober2));
printAligned(ug, HorizontalAlignment.CENTER, caption);
if (diagram.getLegend().getVerticalAlignment() == VerticalAlignment.BOTTOM) {
printAligned(ug, diagram.getLegend().getHorizontalAlignment(), legend);
ug = goDown(ug, legend);
}
printAligned(ug, diagram.getFooterOrHeaderTeoz(FontParam.FOOTER).getHorizontalAlignment(), footer);
}
});
return imageBuilder.writeImageTOBEMOVED(fileFormatOption, diagram.seed(), os);
}
private UGraphic goDownAndCenterForEnglobers(UGraphic ug) {
ug = goDown(ug, title);
ug = goDown(ug, header);
if (diagram.getLegend().getVerticalAlignment() == VerticalAlignment.TOP) {
ug = goDown(ug, legend);
}
final double dx = (dimTotal.getWidth() - main.calculateDimension(stringBounder).getWidth()) / 2;
return ug.apply(new UTranslate(dx, 0));
}
private UGraphic goDown(UGraphic ug, TextBlock size) {
return ug.apply(new UTranslate(0, size.calculateDimension(stringBounder).getHeight()));
}
public void printAligned(UGraphic ug, HorizontalAlignment align, final TextBlock layer) {
double dx = 0;
if (align == HorizontalAlignment.RIGHT) {
dx = dimTotal.getWidth() - layer.calculateDimension(stringBounder).getWidth();
} else if (align == HorizontalAlignment.CENTER) {
dx = (dimTotal.getWidth() - layer.calculateDimension(stringBounder).getWidth()) / 2;
}
layer.drawU(ug.apply(new UTranslate(dx, 0)));
}
private MainTile createMainTile() {
final RealOrigin origin = RealUtils.createOrigin();
Real currentPos = origin.addAtLeast(0);
for (Participant p : diagram.participants()) {
final LivingSpace livingSpace = new LivingSpace(p, diagram.getEnglober(p), skin, getSkinParam(),
currentPos, diagram.events());
livingSpaces.put(p, livingSpace);
currentPos = livingSpace.getPosD(stringBounder).addAtLeast(0);
}
final TileArguments tileArguments = new TileArguments(stringBounder, livingSpaces, skin,
diagram.getSkinParam(), origin);
this.englobers = new Englobers(tileArguments);
final MainTile mainTile = new MainTile(diagram, englobers, tileArguments);
this.livingSpaces.addConstraints(stringBounder);
mainTile.addConstraints(stringBounder);
this.englobers.addConstraints(stringBounder);
origin.compileNow();
tileArguments.setBordered(mainTile);
return mainTile;
}
public ISkinParam getSkinParam() {
return diagram.getSkinParam();
}
private TextBlock getTitle() {
if (diagram.getTitle().isNull()) {
return new ComponentAdapter(null);
}
final TextBlock compTitle = TextBlockUtils.title(new FontConfiguration(getSkinParam(),
FontParam.SEQUENCE_TITLE, null), diagram.getTitle().getDisplay(), getSkinParam());
return TextBlockUtils.withMargin(compTitle, 7, 7);
}
private TextBlock getLegend() {
final Display legend = diagram.getLegend().getDisplay();
if (Display.isNull(legend)) {
return TextBlockUtils.empty(0, 0);
}
return EntityImageLegend.create(legend, diagram.getSkinParam());
}
public TextBlock getFooterOrHeader(final FontParam param) {
if (diagram.getFooterOrHeaderTeoz(param).isNull()) {
return new TeozLayer(null, stringBounder, param);
}
final DisplaySection display = diagram.getFooterOrHeaderTeoz(param);
final HtmlColor hyperlinkColor = getSkinParam().getHyperlinkColor();
final HtmlColor titleColor = getSkinParam().getFontHtmlColor(null, param);
final String fontFamily = getSkinParam().getFont(null, false, param).getFamily(null);
final int fontSize = getSkinParam().getFont(null, false, param).getSize();
final PngTitler pngTitler = new PngTitler(titleColor, display, fontSize, fontFamily, hyperlinkColor,
getSkinParam().useUnderlineForHyperlink());
return new TeozLayer(pngTitler, stringBounder, param);
}
public int getNbPages() {
return 1;
}
}