diff --git a/src/net/sourceforge/plantuml/abel/Entity.java b/src/net/sourceforge/plantuml/abel/Entity.java index c94c0a141..927fa05dc 100644 --- a/src/net/sourceforge/plantuml/abel/Entity.java +++ b/src/net/sourceforge/plantuml/abel/Entity.java @@ -719,4 +719,32 @@ final public class Entity implements SpecificBackcolorable, Hideable, Removeable return true; } + public boolean canBePacked() { + if (isPacked()) + return false; + if (countChildren() != 1) + return false; + if (leafs().size() != 0) + return false; + for (Link link : entityFactory.getLinks()) + if (link.contains(this)) + return false; + + final Entity child = groups().iterator().next(); + if (child.countChildren() == 0) + return false; + + return true; + } + + private boolean packed; + + public final void setPacked(boolean packed) { + this.packed = true; + } + + public final boolean isPacked() { + return packed; + } + } diff --git a/src/net/sourceforge/plantuml/abel/Link.java b/src/net/sourceforge/plantuml/abel/Link.java index f3aab4670..9bbb1479c 100644 --- a/src/net/sourceforge/plantuml/abel/Link.java +++ b/src/net/sourceforge/plantuml/abel/Link.java @@ -334,23 +334,19 @@ public class Link extends WithLinkType implements Hideable, Removeable { } public boolean contains(Entity entity) { - if (isSame(getEntity1(), entity)) + if (getEntity1() == entity) return true; - if (isSame(getEntity2(), entity)) + if (getEntity2() == entity) return true; return false; } - static private boolean isSame(Entity a, Entity b) { - return a == b; - } - public Entity getOther(Entity entity) { - if (isSame(getEntity1(), entity)) + if (getEntity1() == entity) return getEntity2(); - if (isSame(getEntity2(), entity)) + if (getEntity2() == entity) return getEntity1(); throw new IllegalArgumentException(); diff --git a/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java b/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java index 51bf7637c..e96964e28 100644 --- a/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java +++ b/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java @@ -45,6 +45,7 @@ import net.sourceforge.plantuml.abel.Link; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.core.ImageData; import net.sourceforge.plantuml.core.UmlSource; +import net.sourceforge.plantuml.klimt.creole.Display; import net.sourceforge.plantuml.klimt.shape.TextBlock; import net.sourceforge.plantuml.objectdiagram.AbstractClassOrObjectDiagram; import net.sourceforge.plantuml.plasma.Quark; @@ -118,10 +119,37 @@ public class ClassDiagram extends AbstractClassOrObjectDiagram { link2.setLength(1); } + + if (getPragma().useIntermediatePackages() == false) + packSomePackage(); + this.applySingleStrategy(); return super.checkFinalError(); } + private void packSomePackage() { + String separator = getNamespaceSeparator(); + if (separator == null) + separator = "."; + + while (true) { + boolean changed = false; + for (Entity group : this.entityFactory.groups()) { + if (group.canBePacked()) { + final Entity child = group.groups().iterator().next(); + final String appended = group.getDisplay().get(0) + separator; + final Display newDisplay = child.getDisplay().appendFirstLine(appended); + child.setDisplay(newDisplay); + group.setPacked(true); + changed = true; + } + } + if (changed == false) + return; + } + + } + public CommandExecutionResult checkIfPackageHierarchyIfOk(Entity entity) { Quark current = entity.getQuark().getParent(); while (current.isRoot() == false) { diff --git a/src/net/sourceforge/plantuml/klimt/creole/Display.java b/src/net/sourceforge/plantuml/klimt/creole/Display.java index f03390384..6fc1425cc 100644 --- a/src/net/sourceforge/plantuml/klimt/creole/Display.java +++ b/src/net/sourceforge/plantuml/klimt/creole/Display.java @@ -416,6 +416,12 @@ public class Display implements Iterable { return result; } + public Display appendFirstLine(String appended) { + final Display result = new Display(this.showStereotype, this, this.defaultCreoleMode); + result.displayData.set(0, appended + result.displayData.get(0)); + return result; + } + public Display add(CharSequence s) { final Display result = new Display(this.showStereotype, this, this.defaultCreoleMode); result.displayData.add(s); diff --git a/src/net/sourceforge/plantuml/sdot/CucaDiagramFileMakerSmetana.java b/src/net/sourceforge/plantuml/sdot/CucaDiagramFileMakerSmetana.java index f010164e5..18dda025f 100644 --- a/src/net/sourceforge/plantuml/sdot/CucaDiagramFileMakerSmetana.java +++ b/src/net/sourceforge/plantuml/sdot/CucaDiagramFileMakerSmetana.java @@ -317,14 +317,18 @@ public class CucaDiagramFileMakerSmetana implements CucaDiagramFileMaker { if (g.getGroupType() == GroupType.CONCURRENT_STATE) return; - final ClusterHeader clusterHeader = new ClusterHeader((Entity) g, diagram.getSkinParam(), diagram, - stringBounder); - dotStringFactory.openCluster(g, clusterHeader); + if (g.isPacked() == false) { + final ClusterHeader clusterHeader = new ClusterHeader(g, diagram.getSkinParam(), diagram, stringBounder); + dotStringFactory.openCluster(g, clusterHeader); + } + this.printEntities(g.leafs()); printAllSubgroups(g); - dotStringFactory.closeCluster(); + if (g.isPacked() == false) { + dotStringFactory.closeCluster(); + } } private void printEntities(Collection entities) { @@ -361,8 +365,8 @@ public class CucaDiagramFileMakerSmetana implements CucaDiagramFileMaker { result = agnode(zz, cluster, new CString("z" + group.getUid()), true); agsafeset(zz, result, new CString("shape"), new CString("box"), new CString("")); - agsafeset(zz, result, new CString("width"), new CString("1"), new CString("")); - agsafeset(zz, result, new CString("height"), new CString("1"), new CString("")); + agsafeset(zz, result, new CString("width"), new CString("0.1"), new CString("")); + agsafeset(zz, result, new CString("height"), new CString("0.1"), new CString("")); coreNodes.put(group, result); return result; } @@ -373,7 +377,6 @@ public class CucaDiagramFileMakerSmetana implements CucaDiagramFileMaker { System.err.println("CANNOT FIND NODE"); return; } - System.err.println("exportEntity " + leaf); final ST_Agnode_s agnode = agnode(zz, cluster, new CString(node.getUid()), true); agsafeset(zz, agnode, new CString("shape"), new CString("box"), new CString("")); final XDimension2D dim = getDim(node); @@ -484,9 +487,14 @@ public class CucaDiagramFileMakerSmetana implements CucaDiagramFileMaker { } private void exportGroup(Globals zz, ST_Agraph_s graph, Entity group) { + if (group.isPacked()) { + this.exportEntities(zz, graph, group.leafs()); + this.exportGroups(zz, graph, group); + return; + } final Cluster cluster = getBibliotekon().getCluster(group); if (cluster == null) { - System.err.println("CucaDiagramFileMakerJDot::exportGroup issue"); + System.err.println("CucaDiagramFileMakerSmetana::exportGroup issue"); return; } JUtils.LOG2("cluster = " + cluster.getClusterId()); diff --git a/src/net/sourceforge/plantuml/skin/Pragma.java b/src/net/sourceforge/plantuml/skin/Pragma.java index 3066f1390..a16dbefeb 100644 --- a/src/net/sourceforge/plantuml/skin/Pragma.java +++ b/src/net/sourceforge/plantuml/skin/Pragma.java @@ -74,6 +74,10 @@ public class Pragma { return "true".equalsIgnoreCase(s) || "on".equalsIgnoreCase(s); } + private boolean isFalse(final String s) { + return "false".equalsIgnoreCase(s) || "off".equalsIgnoreCase(s); + } + public boolean useVerticalIf() { return isTrue(getValue("useverticalif")); } @@ -86,4 +90,8 @@ public class Pragma { return isTrue(getValue("kermor")); } + public boolean useIntermediatePackages() { + return !isFalse(getValue("useintermediatepackages")); + } + } diff --git a/src/net/sourceforge/plantuml/svek/ClusterDotString.java b/src/net/sourceforge/plantuml/svek/ClusterDotString.java index b673d1c7b..4a0f8dd76 100644 --- a/src/net/sourceforge/plantuml/svek/ClusterDotString.java +++ b/src/net/sourceforge/plantuml/svek/ClusterDotString.java @@ -66,6 +66,10 @@ public class ClusterDotString { this.skinParam = skinParam; } + private boolean isPacked() { + return cluster.getGroup().isPacked(); + } + void printInternal(StringBuilder sb, Collection lines, StringBounder stringBounder, DotMode dotMode, GraphvizVersion graphvizVersion, UmlDiagramType type) { if (cluster.diagram.getPragma().useKermor()) { @@ -73,6 +77,14 @@ public class ClusterDotString { graphvizVersion, type); return; } + final boolean packed = isPacked(); + + if (packed) { + cluster.printCluster1(sb, lines, stringBounder); + final SvekNode added = cluster.printCluster2(sb, lines, stringBounder, dotMode, graphvizVersion, type); + return; + + } final boolean thereALinkFromOrToGroup2 = isThereALinkFromOrToGroup(lines); boolean thereALinkFromOrToGroup1 = thereALinkFromOrToGroup2; final boolean useProtectionWhenThereALinkFromOrToGroup = graphvizVersion @@ -154,6 +166,8 @@ public class ClusterDotString { SvekUtils.println(sb); } SvekUtils.println(sb); + + // ----------- cluster.printCluster1(sb, lines, stringBounder); final SvekNode added = cluster.printCluster2(sb, lines, stringBounder, dotMode, graphvizVersion, type); @@ -167,6 +181,8 @@ public class ClusterDotString { } SvekUtils.println(sb); + // ----------- + sb.append("}"); if (protection1) sb.append("}"); diff --git a/src/net/sourceforge/plantuml/svek/DotStringFactory.java b/src/net/sourceforge/plantuml/svek/DotStringFactory.java index 239a61254..ba93eb3cb 100644 --- a/src/net/sourceforge/plantuml/svek/DotStringFactory.java +++ b/src/net/sourceforge/plantuml/svek/DotStringFactory.java @@ -415,6 +415,9 @@ public class DotStringFactory implements Moveable { } for (Cluster cluster : bibliotekon.allCluster()) { + if (cluster.getGroup().isPacked()) + continue; + int idx = getClusterIndex(svg, cluster.getColor()); final int starting = idx; final List points = svgResult.substring(starting).extractList(SvgResult.POINTS_EQUALS); diff --git a/src/net/sourceforge/plantuml/svek/SvekResult.java b/src/net/sourceforge/plantuml/svek/SvekResult.java index cc09e4bbd..8ef958c2b 100644 --- a/src/net/sourceforge/plantuml/svek/SvekResult.java +++ b/src/net/sourceforge/plantuml/svek/SvekResult.java @@ -72,7 +72,8 @@ public final class SvekResult extends AbstractTextBlock implements IEntityImage public void drawU(UGraphic ug) { for (Cluster cluster : dotStringFactory.getBibliotekon().allCluster()) - cluster.drawU(ug, dotData.getUmlDiagramType()); + if (cluster.getGroup().isPacked() == false) + cluster.drawU(ug, dotData.getUmlDiagramType()); final Style style2 = getDefaultStyleDefinition(null) .getMergedStyle(dotData.getSkinParam().getCurrentStyleBuilder());