mirror of
https://github.com/octoleo/plantuml.git
synced 2024-12-22 10:59:01 +00:00
Merge pull request #475 from ioplker/master
Add interactive functionality for Usecase diagrams exported to SVG
This commit is contained in:
commit
74ff89f4ba
@ -86,6 +86,10 @@ public abstract class UGraphicDelegator implements UGraphic {
|
|||||||
ug.startGroup(groupId);
|
ug.startGroup(groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void startGroupWithClass(String groupClasses) {
|
||||||
|
ug.startGroupWithClass(groupClasses);
|
||||||
|
}
|
||||||
|
|
||||||
public void closeGroup() {
|
public void closeGroup() {
|
||||||
ug.closeGroup();
|
ug.closeGroup();
|
||||||
}
|
}
|
||||||
|
@ -624,6 +624,7 @@ public class Line implements Moveable, Hideable, GuideLine {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ug.draw(link.commentForSvg());
|
ug.draw(link.commentForSvg());
|
||||||
|
ug.startGroupWithClass("link " + link.getEntity1().getCode() + " " + link.getEntity2().getCode() + " selected");
|
||||||
double x = 0;
|
double x = 0;
|
||||||
double y = 0;
|
double y = 0;
|
||||||
final Url url = link.getUrl();
|
final Url url = link.getUrl();
|
||||||
@ -750,6 +751,8 @@ public class Line implements Moveable, Hideable, GuideLine {
|
|||||||
link.getLinkConstraint().setPosition(link, minPt);
|
link.getLinkConstraint().setPosition(link, minPt);
|
||||||
link.getLinkConstraint().drawMe(ug, skinParam);
|
link.getLinkConstraint().drawMe(ug, skinParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ug.closeGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Point2D> getSquare(double x, double y) {
|
private List<Point2D> getSquare(double x, double y) {
|
||||||
|
@ -294,6 +294,8 @@ public class EntityImageDescription extends AbstractEntityImage {
|
|||||||
|
|
||||||
final public void drawU(UGraphic ug) {
|
final public void drawU(UGraphic ug) {
|
||||||
ug.draw(new UComment("entity " + getEntity().getCodeGetName()));
|
ug.draw(new UComment("entity " + getEntity().getCodeGetName()));
|
||||||
|
ug.startGroupWithClass("elem " + getEntity().getCode() + " selected");
|
||||||
|
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
ug.startUrl(url);
|
ug.startUrl(url);
|
||||||
}
|
}
|
||||||
@ -320,6 +322,8 @@ public class EntityImageDescription extends AbstractEntityImage {
|
|||||||
if (url != null) {
|
if (url != null) {
|
||||||
ug.closeUrl();
|
ug.closeUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ug.closeGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawHexagon(UGraphic ug) {
|
private void drawHexagon(UGraphic ug) {
|
||||||
|
@ -201,6 +201,9 @@ public class EntityImageNote extends AbstractEntityImage implements Stencil {
|
|||||||
|
|
||||||
final public void drawU(UGraphic ug) {
|
final public void drawU(UGraphic ug) {
|
||||||
final Url url = getEntity().getUrl99();
|
final Url url = getEntity().getUrl99();
|
||||||
|
|
||||||
|
ug.startGroupWithClass("elem " + getEntity().getCode() + " selected");
|
||||||
|
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
ug.startUrl(url);
|
ug.startUrl(url);
|
||||||
}
|
}
|
||||||
@ -236,6 +239,8 @@ public class EntityImageNote extends AbstractEntityImage implements Stencil {
|
|||||||
if (url != null) {
|
if (url != null) {
|
||||||
ug.closeUrl();
|
ug.closeUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ug.closeGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getRoundCorner() {
|
private double getRoundCorner() {
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
* (C) Copyright 2009-2020, Arnaud Roques
|
* (C) Copyright 2009-2020, Arnaud Roques
|
||||||
*
|
*
|
||||||
* Project Info: http://plantuml.com
|
* Project Info: http://plantuml.com
|
||||||
*
|
*
|
||||||
* If you like this project or if you find it useful, you can support us at:
|
* 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/patreon (only 1$ per month!)
|
||||||
* http://plantuml.com/paypal
|
* http://plantuml.com/paypal
|
||||||
*
|
*
|
||||||
* This file is part of PlantUML.
|
* This file is part of PlantUML.
|
||||||
*
|
*
|
||||||
* PlantUML is free software; you can redistribute it and/or modify it
|
* PlantUML is free software; you can redistribute it and/or modify it
|
||||||
@ -30,7 +30,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Original Author: Arnaud Roques
|
* Original Author: Arnaud Roques
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package net.sourceforge.plantuml.svek.image;
|
package net.sourceforge.plantuml.svek.image;
|
||||||
@ -143,7 +143,10 @@ public class EntityImageUseCase extends AbstractEntityImage {
|
|||||||
ug = ug.apply(backcolor.bg());
|
ug = ug.apply(backcolor.bg());
|
||||||
final UGraphic ug2 = new MyUGraphicEllipse(ug, 0, 0, ellipse.getUEllipse());
|
final UGraphic ug2 = new MyUGraphicEllipse(ug, 0, 0, ellipse.getUEllipse());
|
||||||
|
|
||||||
|
ug2.startGroupWithClass("elem " + getEntity().getCode() + " selected");
|
||||||
ellipse.drawU(ug2);
|
ellipse.drawU(ug2);
|
||||||
|
ug2.closeGroup();
|
||||||
|
|
||||||
if (getEntity().getLeafType() == LeafType.USECASE_BUSINESS) {
|
if (getEntity().getLeafType() == LeafType.USECASE_BUSINESS) {
|
||||||
specialBusiness(ug, ellipse.getUEllipse());
|
specialBusiness(ug, ellipse.getUEllipse());
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
* (C) Copyright 2009-2020, Arnaud Roques
|
* (C) Copyright 2009-2020, Arnaud Roques
|
||||||
*
|
*
|
||||||
* Project Info: http://plantuml.com
|
* Project Info: http://plantuml.com
|
||||||
*
|
*
|
||||||
* If you like this project or if you find it useful, you can support us at:
|
* 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/patreon (only 1$ per month!)
|
||||||
* http://plantuml.com/paypal
|
* http://plantuml.com/paypal
|
||||||
*
|
*
|
||||||
* This file is part of PlantUML.
|
* This file is part of PlantUML.
|
||||||
*
|
*
|
||||||
* PlantUML is free software; you can redistribute it and/or modify it
|
* PlantUML is free software; you can redistribute it and/or modify it
|
||||||
@ -30,7 +30,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Original Author: Arnaud Roques
|
* Original Author: Arnaud Roques
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package net.sourceforge.plantuml.svg;
|
package net.sourceforge.plantuml.svg;
|
||||||
@ -158,12 +158,145 @@ public class SvgGraphics {
|
|||||||
if (hover != null) {
|
if (hover != null) {
|
||||||
defs.appendChild(getPathHover(hover));
|
defs.appendChild(getPathHover(hover));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add styles and script for interactive SVG
|
||||||
|
defs.appendChild(getStylesForInteractiveMode());
|
||||||
|
defs.appendChild(getScriptForInteractiveMode());
|
||||||
} catch (ParserConfigurationException e) {
|
} catch (ParserConfigurationException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Element getStylesForInteractiveMode() {
|
||||||
|
final Element style = simpleElement("style");
|
||||||
|
final CDATASection cdata = document.createCDATASection(
|
||||||
|
".elem {cursor: pointer;} " + "\n" +
|
||||||
|
".elem, .link {opacity: 0.3;}" + "\n" +
|
||||||
|
".elem.selected, .link.selected {opacity: 1;}"
|
||||||
|
);
|
||||||
|
style.setAttribute("type", "text/css");
|
||||||
|
style.appendChild(cdata);
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Element getScriptForInteractiveMode() {
|
||||||
|
final Element script = document.createElement("script");
|
||||||
|
script.setTextContent(
|
||||||
|
"function addItemToMapOfLists(mapOfLists, name, item) {" + "\n" +
|
||||||
|
" // mapOfLists = {" + "\n" +
|
||||||
|
" // 'key1': [item1, item2, ...]," + "\n" +
|
||||||
|
" // 'key2': [item3, item4, ...]," + "\n" +
|
||||||
|
" // }" + "\n" +
|
||||||
|
" if (mapOfLists[name].length > 0) {" + "\n" +
|
||||||
|
" if (!mapOfLists[name].includes(item)) {" + "\n" +
|
||||||
|
" mapOfLists[name].push(item);" + "\n" +
|
||||||
|
" }" + "\n" +
|
||||||
|
" } else {" + "\n" +
|
||||||
|
" mapOfLists[name] = [item];" + "\n" +
|
||||||
|
" }" + "\n" +
|
||||||
|
"}" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
"function main() {" + "\n" +
|
||||||
|
" let elems = Array.from(document.getElementsByClassName('elem'));" + "\n" +
|
||||||
|
" let links = Array.from(document.getElementsByClassName('link'));" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" let elemsMap = {};" + "\n" +
|
||||||
|
" let linkedElems = {};" + "\n" +
|
||||||
|
" let linkedLinks = {};" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" elems.forEach(elem => {" + "\n" +
|
||||||
|
" let name = elem.classList[1];" + "\n" +
|
||||||
|
" elemsMap[name] = elem;" + "\n" +
|
||||||
|
" linkedElems[name] = [];" + "\n" +
|
||||||
|
" linkedLinks[name] = [];" + "\n" +
|
||||||
|
" });" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" links.forEach(link => {" + "\n" +
|
||||||
|
" if (elemsMap[name1]) {" + "\n" +
|
||||||
|
" if (elemsMap[name2]) {" + "\n" +
|
||||||
|
" let name1 = link.classList[1];" + "\n" +
|
||||||
|
" let name2 = link.classList[2];" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" let elem1 = elemsMap[name1];" + "\n" +
|
||||||
|
" let elem2 = elemsMap[name2];" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" addItemToMapOfLists(linkedElems, name1, elem2);" + "\n" +
|
||||||
|
" addItemToMapOfLists(linkedElems, name2, elem1);" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" addItemToMapOfLists(linkedLinks, name1, link);" + "\n" +
|
||||||
|
" addItemToMapOfLists(linkedLinks, name2, link);" + "\n" +
|
||||||
|
" }" + "\n" +
|
||||||
|
" }" + "\n" +
|
||||||
|
" });" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" let selectedElems = [];" + "\n" +
|
||||||
|
" let selectedLinks = [];" + "\n" +
|
||||||
|
" let selectedElemName = null;" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" function clearSelected() {" + "\n" +
|
||||||
|
" selectedElems.forEach(item => {" + "\n" +
|
||||||
|
" item.classList.remove('selected');" + "\n" +
|
||||||
|
" });" + "\n" +
|
||||||
|
" selectedElems = [];" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" selectedLinks.forEach(item => {" + "\n" +
|
||||||
|
" item.classList.remove('selected');" + "\n" +
|
||||||
|
" });" + "\n" +
|
||||||
|
" selectedLinks = [];" + "\n" +
|
||||||
|
" }" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" function selectAll() {" + "\n" +
|
||||||
|
" selectedElemName = null;" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" selectedElems = Array.from(elems);" + "\n" +
|
||||||
|
" selectedElems.forEach(item => {" + "\n" +
|
||||||
|
" item.classList.add('selected');" + "\n" +
|
||||||
|
" });" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" selectedLinks = Array.from(links);" + "\n" +
|
||||||
|
" selectedLinks.forEach(item => {" + "\n" +
|
||||||
|
" item.classList.add('selected');" + "\n" +
|
||||||
|
" });" + "\n" +
|
||||||
|
" }" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" function selectElem(elemName) {" + "\n" +
|
||||||
|
" if (elemName === selectedElemName) {" + "\n" +
|
||||||
|
" selectAll();" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" } else {" + "\n" +
|
||||||
|
" clearSelected();" + "\n" +
|
||||||
|
" selectedElemName = elemName;" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" elemsMap[elemName].classList.add('selected');" + "\n" +
|
||||||
|
" selectedElems.push(elemsMap[elemName]);" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" linkedElems[elemName].forEach(linkedElem => {" + "\n" +
|
||||||
|
" selectedElems.push(linkedElem);" + "\n" +
|
||||||
|
" linkedElem.classList.add('selected');" + "\n" +
|
||||||
|
" });" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" linkedLinks[elemName].forEach(linkedLink => {" + "\n" +
|
||||||
|
" selectedLinks.push(linkedLink);" + "\n" +
|
||||||
|
" linkedLink.classList.add('selected');" + "\n" +
|
||||||
|
" });" + "\n" +
|
||||||
|
" }" + "\n" +
|
||||||
|
" }" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" Object.keys(elemsMap).forEach(name => {" + "\n" +
|
||||||
|
" elemsMap[name].onclick = () => { selectElem(name); };" + "\n" +
|
||||||
|
" });" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
" selectAll();" + "\n" +
|
||||||
|
"}" + "\n" +
|
||||||
|
"" + "\n" +
|
||||||
|
"document.addEventListener('DOMContentLoaded', (event) => {" + "\n" +
|
||||||
|
" main();" + "\n" +
|
||||||
|
"});"
|
||||||
|
);
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
private Element getPathHover(String hover) {
|
private Element getPathHover(String hover) {
|
||||||
final Element style = simpleElement("style");
|
final Element style = simpleElement("style");
|
||||||
final CDATASection cdata = document.createCDATASection("path:hover { stroke: " + hover + " !important;}");
|
final CDATASection cdata = document.createCDATASection("path:hover { stroke: " + hover + " !important;}");
|
||||||
@ -932,6 +1065,11 @@ public class SvgGraphics {
|
|||||||
pendingAction.get(0).setAttribute("id", groupId);
|
pendingAction.get(0).setAttribute("id", groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void startGroupWithClass(String groupClasses) {
|
||||||
|
pendingAction.add(0, (Element) document.createElement("g"));
|
||||||
|
pendingAction.get(0).setAttribute("class", groupClasses);
|
||||||
|
}
|
||||||
|
|
||||||
public void closeGroup() {
|
public void closeGroup() {
|
||||||
closeLink();
|
closeLink();
|
||||||
}
|
}
|
||||||
|
@ -173,6 +173,9 @@ public abstract class AbstractCommonUGraphic implements UGraphic {
|
|||||||
public void startGroup(String groupId) {
|
public void startGroup(String groupId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void startGroupWithClass(String groupClasses) {
|
||||||
|
}
|
||||||
|
|
||||||
public void closeGroup() {
|
public void closeGroup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,8 @@ public interface UGraphic {
|
|||||||
|
|
||||||
public void startGroup(String id);
|
public void startGroup(String id);
|
||||||
|
|
||||||
|
public void startGroupWithClass(String groupClasses);
|
||||||
|
|
||||||
public void closeGroup();
|
public void closeGroup();
|
||||||
|
|
||||||
public void flushUg();
|
public void flushUg();
|
||||||
|
@ -45,6 +45,9 @@ public abstract class UGraphicNo {
|
|||||||
final public void startGroup(String groupId) {
|
final public void startGroup(String groupId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final public void startGroupWithClass(String groupClasses) {
|
||||||
|
}
|
||||||
|
|
||||||
final public void closeUrl() {
|
final public void closeUrl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,11 @@ public class UGraphicSvg extends AbstractUGraphic<SvgGraphics> implements ClipCo
|
|||||||
@Override
|
@Override
|
||||||
public void startGroup(String groupId) {
|
public void startGroup(String groupId) {
|
||||||
getGraphicObject().startGroup(groupId);
|
getGraphicObject().startGroup(groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startGroupWithClass(String groupClasses) {
|
||||||
|
getGraphicObject().startGroupWithClass(groupClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user