6.4.1 release

Former-commit-id: 5f8102fae0
This commit is contained in:
David Benson 2017-03-24 11:59:37 +00:00
parent d9fca61424
commit 3c75dc69a8
42 changed files with 2640 additions and 320 deletions

View file

@ -1,3 +1,20 @@
24-MAR-2017: 6.4.1
- Initial .vsdx theming support
21-MAR-2017: 6.4.0
- Fixes scaling on .vsdx import
- Adds Google Cloud Platform cards
18-MAR-2017: 6.3.8
- Changes display on marker pull-down for no marker in use
17-MAR-2017: 6.3.7
- Adds locale information to drive user
16-MAR-2017: 6.3.6
- Fixes selection of deleted parents after delete actions

View file

@ -1 +1 @@
6.3.6
6.4.1

View file

@ -96,6 +96,7 @@
<file name="Sidebar-ER.js" />
<file name="Sidebar-Floorplan.js" />
<file name="Sidebar-Flowchart.js" />
<file name="Sidebar-GCP.js" />
<file name="Sidebar-Gmdl.js" />
<file name="Sidebar-Ios.js" />
<file name="Sidebar-Ios7.js" />

View file

@ -1,6 +1,6 @@
/**
* Copyright (c) 2006-2016, JGraph Ltd
* Copyright (c) 2006-2016, Gaudenz Alder
* Copyright (c) 2006-2017, JGraph Ltd
* Copyright (c) 2006-2017, Gaudenz Alder
*/
package com.mxgraph.io;
@ -27,6 +27,11 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.google.appengine.api.images.Image;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.Transform;
import com.google.appengine.api.images.ImagesService.OutputEncoding;
import com.mxgraph.io.vsdx.Shape;
import com.mxgraph.io.vsdx.ShapePageId;
import com.mxgraph.io.vsdx.VsdxShape;
@ -39,13 +44,14 @@ import com.mxgraph.io.vsdx.mxVsdxModel;
import com.mxgraph.io.vsdx.mxVsdxPage;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.model.mxGraphModel;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.online.Utils;
import com.mxgraph.online.mxBase64;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.util.mxXmlUtils;
import com.mxgraph.view.mxCellState;
import com.mxgraph.view.mxConnectionConstraint;
import com.mxgraph.view.mxGraph;
import com.mxgraph.view.mxGraphHeadless;
@ -101,12 +107,12 @@ public class mxVsdxCodec
{
if (cellParent != null)
{
mxCellState state = graph.getView().getState(cellParent);
mxGeometry geo = graph.getModel().getGeometry(cellParent);
if (state != null)
if (geo != null)
{
point.setX(point.getX() + state.getX());
point.setY(point.getY() + state.getY());
point.setX(point.getX() + geo.getX());
point.setY(point.getY() + geo.getY());
}
}
@ -151,7 +157,36 @@ public class mxVsdxCodec
}
else if (filename.toLowerCase().startsWith(mxVsdxCodec.vsdxPlaceholder + "/media"))
{
mediaData.put(filename, StringUtils.newStringUtf8(Base64.encodeBase64(out.toByteArray(), false)));
String base64Str;
//Bmp images are huge and doesn't show up in the browser, so, it is better to compress it as jpeg
if (filename.toLowerCase().endsWith(".bmp"))
{
try
{
ImagesService imagesService = ImagesServiceFactory.getImagesService();
Image image = ImagesServiceFactory.makeImage(out.toByteArray());
//dummy transform
Transform transform = ImagesServiceFactory.makeCrop(0.0, 0.0, 1.0, 1.0);
//Use PNG format as it is lossless similar to bmp but compressed
Image newImage = imagesService.applyTransform(transform, image, OutputEncoding.PNG);
base64Str = StringUtils.newStringUtf8(Base64.encodeBase64(newImage.getImageData(), false));
}
catch (Exception e)
{
//conversion failed, nothing we can do!
base64Str = StringUtils.newStringUtf8(Base64.encodeBase64(out.toByteArray(), false));
}
}
else
{
base64Str = StringUtils.newStringUtf8(Base64.encodeBase64(out.toByteArray(), false));
}
mediaData.put(filename, base64Str);
}
}
}
@ -207,6 +242,42 @@ public class mxVsdxCodec
importPage(backPage, graph, graph.getDefaultParent());
}
//scale page
double scale = page.getPageScale() / page.getDrawingScale();
if (scale != 1)
{
mxGraphModel model = (mxGraphModel)graph.getModel();
for (Object c : model.getCells().values())
{
mxGeometry geo = model.getGeometry(c);
if (geo != null)
{
scaleRect(geo, scale);
scaleRect(geo.getAlternateBounds(), scale);
if (model.isEdge(c))
{
//scale edge waypoints, offset, ...
scalePoint(geo.getSourcePoint(), scale);
scalePoint(geo.getTargetPoint(), scale);
scalePoint(geo.getOffset(), scale);
List<mxPoint> points = geo.getPoints();
if (points != null)
{
for (mxPoint p : points)
{
scalePoint(p, scale);
}
}
}
}
}
}
graph.getModel().endUpdate();
mxCodec codec = new mxCodec();
@ -229,6 +300,44 @@ public class mxVsdxCodec
return xmlBuilder.toString();
}
/**
* Scale a point in place
*
* @param p point to scale in place
* @param scale scale
* @return scaled point
*/
private mxPoint scalePoint(mxPoint p, double scale)
{
if (p != null)
{
p.setX(p.getX() * scale);
p.setY(p.getY() * scale);
}
return p;
}
/**
* Scale a rectangle in place
*
* @param rect rectangle to scale in place
* @param scale scale
* @return scaled rectangle
*/
private mxRectangle scaleRect(mxRectangle rect, double scale)
{
if (rect != null)
{
rect.setX(rect.getX() * scale);
rect.setY(rect.getY() * scale);
rect.setHeight(rect.getHeight() * scale);
rect.setWidth(rect.getWidth() * scale);
}
return rect;
}
/**
*
* @param rootDoc
@ -701,15 +810,17 @@ public class mxVsdxCodec
}
else
{
mxCell srcTopParent = findTopParent(source, (mxCell) graph.getDefaultParent());
mxPoint dimensionFrom = fromShape.getDimensions();
//Get From shape origin and begin/end of edge in absolutes values.
double height = pageHeight;
if ((source.getParent() != null)
&& (source.getParent().getGeometry() != null))
if ((srcTopParent != null)
&& (srcTopParent.getGeometry() != null))
{
height = source.getParent().getGeometry().getHeight();
height = srcTopParent.getGeometry().getHeight();
}
mxPoint originFrom = fromShape.getOriginPoint(height, false);
@ -717,7 +828,7 @@ public class mxVsdxCodec
if (sourceToPart != mxVsdxConstants.CONNECT_TO_PART_WHOLE_SHAPE)
{
mxPoint absOriginFrom = calculateAbsolutePoint(source.getParent(), graph, originFrom);
mxPoint absOriginFrom = calculateAbsolutePoint(srcTopParent, graph, originFrom);
fromConstraint = new mxPoint(
(beginXY.getX() - absOriginFrom.getX())
/ dimensionFrom.getX(),
@ -748,16 +859,16 @@ public class mxVsdxCodec
else
{
target = vertexMap.get(new ShapePageId(pageId, toSheet));
mxCell trgTopParent = findTopParent(target, (mxCell) graph.getDefaultParent());
mxPoint dimentionTo = toShape.getDimensions();
//Get To shape origin.
double height = pageHeight;
if ((target.getParent() != null)
&& (target.getParent().getGeometry() != null))
if ((trgTopParent != null)
&& (trgTopParent.getGeometry() != null))
{
height = target.getParent().getGeometry().getHeight();
height = trgTopParent.getGeometry().getHeight();
}
mxPoint originTo = toShape.getOriginPoint(height, false);
@ -765,7 +876,7 @@ public class mxVsdxCodec
if (targetToPart != mxVsdxConstants.CONNECT_TO_PART_WHOLE_SHAPE)
{
mxPoint absOriginTo = calculateAbsolutePoint( target.getParent(), graph, originTo);
mxPoint absOriginTo = calculateAbsolutePoint( trgTopParent, graph, originTo);
toConstraint = new mxPoint(
(endXY.getX() - absOriginTo.getX())
/ dimentionTo.getX(),
@ -808,6 +919,24 @@ public class mxVsdxCodec
return edgeId;
}
/**
* Find the top parent in a group
*
* @param cell
* @return the top most parent (which has the defaultParent as its parent)
*/
private mxCell findTopParent(mxCell cell, mxCell defaultParent)
{
mxCell parent = (mxCell) cell.getParent();
while (parent.getParent() != null && parent.getParent() != defaultParent)
{
parent = (mxCell) parent.getParent();
}
return parent;
}
/**
* Adds a new edge not connected to any vertex to the graph.
* @param graph Graph where the parsed graph is included.

View file

@ -70,6 +70,10 @@ public class Shape extends Style
protected Map<String, String> imageData;
protected mxVsdxTheme theme;
protected int themeVariant = 0;
public mxPathDebug debug = null;
public Shape(Element shape, mxVsdxModel model)
@ -79,6 +83,21 @@ public class Shape extends Style
this.height = getScreenNumericalValue(this.cellElements.get(mxVsdxConstants.HEIGHT), 0);
}
public void setThemeAndVariant(mxVsdxTheme theme, int themeVariant)
{
this.theme = theme;
this.themeVariant = themeVariant;
}
public mxVsdxTheme getTheme()
{
if (theme != null)
{
theme.setVariant(themeVariant);
}
return theme;
}
/**
* Caches the specified element
* @param elem the element to cache
@ -164,6 +183,13 @@ public class Shape extends Style
{
this.imageData = new HashMap<String, String>();
this.imageData.put("iData", model.getMedia(mxVsdxCodec.vsdxPlaceholder + "/media/" + target));
//since we convert BMP files to PNG, we set the compression to PNG
if (target.toLowerCase().endsWith(".bmp"))
{
compression = "png";
}
this.imageData.put("iType", compression);
}
}
@ -1385,10 +1411,17 @@ public class Shape extends Style
String style = getTextStyle(index);
if (!style.equals(""))
{
if (style.toLowerCase().equals("themed"))
{
// TODO theme support
}
else
{
int value = Integer.parseInt(style);
isBold = ((value & 1) == 1);
}
}
return isBold;
}
@ -1408,10 +1441,17 @@ public class Shape extends Style
String style = getTextStyle(index);
if (!style.equals(""))
{
if (style.toLowerCase().equals("themed"))
{
// TODO theme support
}
else
{
int value = Integer.parseInt(style);
isItalic = ((value & 2) == 2);
}
}
return isItalic;
}
@ -1431,10 +1471,17 @@ public class Shape extends Style
String style = getTextStyle(index);
if (!style.equals(""))
{
if (style.toLowerCase().equals("themed"))
{
// TODO theme support
}
else
{
int value = Integer.parseInt(style);
isUnderline = ((value & 4) == 4);
}
}
return isUnderline;
}
@ -1454,10 +1501,17 @@ public class Shape extends Style
String style = getTextStyle(index);
if (!style.equals(""))
{
if (style.toLowerCase().equals("themed"))
{
// TODO theme support
}
else
{
int value = Integer.parseInt(style);
isSmallCaps = ((value & 8) == 8);
}
}
return isSmallCaps;
}

View file

@ -12,6 +12,7 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.mxgraph.io.vsdx.theme.Color;
import com.mxgraph.util.mxConstants;
/**
@ -38,7 +39,7 @@ public class Style
*/
protected Map<String, Style> styleParents = new HashMap<String, Style>();
protected Style theme;
protected Style style;
private final static Logger LOGGER = Logger.getLogger(Style.class.getName());
@ -56,6 +57,8 @@ public class Style
styleTypes.put(mxVsdxConstants.FILL_PATTERN , mxVsdxConstants.FILL_STYLE);
styleTypes.put(mxVsdxConstants.SHDW_PATTERN, mxVsdxConstants.FILL_STYLE);
styleTypes.put(mxVsdxConstants.FILL_STYLE, mxVsdxConstants.FILL_STYLE);
styleTypes.put("QuickStyleFillColor", mxVsdxConstants.FILL_STYLE);
styleTypes.put("QuickStyleFillMatrix", mxVsdxConstants.FILL_STYLE);
styleTypes.put(mxVsdxConstants.BEGIN_ARROW, mxVsdxConstants.LINE_STYLE);
styleTypes.put(mxVsdxConstants.END_ARROW, mxVsdxConstants.LINE_STYLE);
@ -97,6 +100,11 @@ public class Style
stylesheetRefs(model);
}
public mxVsdxTheme getTheme()
{
return null;
}
public void styleDebug(String debug)
{
if (vsdxStyleDebug)
@ -111,8 +119,8 @@ public class Style
styleParents.put(mxVsdxConstants.LINE_STYLE, model.getStylesheet(shape.getAttribute(mxVsdxConstants.LINE_STYLE)));
styleParents.put(mxVsdxConstants.TEXT_STYLE, model.getStylesheet(shape.getAttribute(mxVsdxConstants.TEXT_STYLE)));
Style theme = model.getStylesheet("0");
this.theme = theme;
Style style = model.getStylesheet("0");
this.style = style;
}
/**
@ -378,10 +386,10 @@ public class Style
{
inherit = true;
}
else if (form.equals("THEMEVAL()") && value.equals("Themed") && theme != null)
else if (form.equals("THEMEVAL()") && value.equals("Themed") && style != null)
{
// Use "no style" style
Element themeElem = theme.getCellElement(cellKey, index, sectKey);
Element themeElem = style.getCellElement(cellKey, index, sectKey);
if (themeElem != null)
{
@ -435,10 +443,14 @@ public class Style
{
inherit = true;
}
else if (form.equals("THEMEVAL()") && value.equals("Themed") && theme != null)
else if (form.equals("THEMEVAL()") && value.equals("Themed") && style != null)
{
//Handle theme here
//FIXME this is a very hacky way to test themes until fully integrating themes
if ("FillForegnd".equals(key)) return elem;
// Use "no style" style
Element themeElem = theme.getCellElement(key);
Element themeElem = style.getCellElement(key);
if (themeElem != null)
{
@ -501,6 +513,24 @@ public class Style
protected String getFillColor()
{
String fillForeColor = this.getColor(this.getCellElement(mxVsdxConstants.FILL_FOREGND));
if ("Themed".equals(fillForeColor))
{
mxVsdxTheme theme = getTheme();
if (theme != null)
{
int styleFillClr = Integer.parseInt(this.getValue(this.getCellElement("QuickStyleFillColor"), "1"));
int styleFillMtx = Integer.parseInt(this.getValue(this.getCellElement("QuickStyleFillMatrix"), "0"));
Color color = theme.getFillColor(styleFillClr, styleFillMtx);
fillForeColor = color.toHexStr();
}
else
{
fillForeColor = "";
}
}
String fillPattern = this.getValue(this.getCellElement(mxVsdxConstants.FILL_PATTERN), "0");
if (fillPattern != null && fillPattern.equals("0"))
@ -517,7 +547,7 @@ public class Style
{
String color = this.getValue(elem, "");
if (!color.startsWith("#"))
if (!"Themed".equals(color) && !color.startsWith("#"))
{
color = pm.getColor(color);
}

View file

@ -4,25 +4,17 @@
*/
package com.mxgraph.io.vsdx;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.online.Utils;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxResources;
import com.mxgraph.view.mxGraph;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.logging.Logger;
import java.util.zip.Deflater;
@ -35,6 +27,14 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.online.Utils;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxResources;
import com.mxgraph.view.mxGraph;
/**
* This class is a wrapper for one Shape Element.<br/>
* This class is responsible for retrieve all the properties of the shape and add it
@ -198,6 +198,11 @@ public class VsdxShape extends Shape
this.rotation = this.rotation % 360.0;
this.vertex = vertex;
mxVsdxTheme theme = model.getThemes().get(page.getCellIntValue("ThemeIndex", 33));
int variant = page.getCellIntValue("VariationColorIndex", 0);
setThemeAndVariant(theme, variant);
}
/**
@ -1314,6 +1319,7 @@ public class VsdxShape extends Shape
result.put("aspect", "fixed");
String iType = this.imageData.get("iType");
String iData = this.imageData.get("iData");
result.put("image", "data:image/" + iType + "," + iData);
return result;
}

View file

@ -56,6 +56,11 @@ public class mxVsdxModel {
*/
protected Map<String, Style> stylesheets = new HashMap<String, Style>();
/**
* Map themes indexed by their index
*/
protected Map<Integer, mxVsdxTheme> themes = new HashMap<>();
mxPropertiesManager pm;
public mxVsdxModel(Document doc, Map<String, Document> docData, Map<String, String> mediaData)
@ -79,10 +84,62 @@ public class mxVsdxModel {
this.pm = new mxPropertiesManager();
this.pm.initialise(rootElement, this);
initStylesheets();
initThemes();
initMasters();
initPages();
}
/**
* Initialize theme objects from the XML files
*/
private void initThemes()
{
// Lazy build up the master structure
if (this.xmlDocs != null)
{
boolean more = true;
int index = 1;
while (more)
{
String path = mxVsdxCodec.vsdxPlaceholder + "/theme/theme"+ index +".xml";
Document themeDoc = this.xmlDocs.get(path);
if (themeDoc != null)
{
Node child = themeDoc.getFirstChild();
while (child != null)
{
if (child instanceof Element && ((Element)child).getTagName().equals("a:theme"))
{
mxVsdxTheme theme = new mxVsdxTheme((Element) child);
if (theme.getThemeIndex() > -1)
{
themes.put(theme.getThemeIndex(), theme);
}
else
{
//theme index cannot be determined unless the theme is parsed
theme.processTheme();
themes.put(theme.getThemeIndex(), theme);
}
break;
}
child = child.getNextSibling();
}
index++;
}
else
{
more = false;
}
}
}
}
/**
* Load the map with the stylesheets elements in the document.<br/>
* The masters are wrapped for instances of mxStyleSheet.
@ -237,6 +294,11 @@ public class mxVsdxModel {
return this.pages;
}
public Map<Integer, mxVsdxTheme> getThemes()
{
return this.themes;
}
protected Element getRelationship(String rid, String path)
{
Document relsDoc = this.xmlDocs.get(path);

View file

@ -60,8 +60,6 @@ public class mxVsdxPage {
this.Id = Integer.valueOf(pageElem.getAttribute(mxVsdxConstants.ID));
this.pageName = pageElem.getAttribute(mxVsdxConstants.NAME);
parseNodes(pageElem, model, "pages");
ArrayList<Element> pageSheets = mxVsdxUtils.getDirectChildNamedElements(pageElem, "PageSheet");
if (pageSheets.size() > 0)
@ -75,6 +73,8 @@ public class mxVsdxPage {
this.cellElements.put(n, cellElem);
}
}
parseNodes(pageElem, model, "pages");
}
/**
@ -325,6 +325,47 @@ public class mxVsdxPage {
return 1;
}
/**
* Returns the page scale attribute of this page
* @return the PageScale
*/
public double getPageScale()
{
Element scale = this.cellElements.get("PageScale");
if (scale != null)
{
return Double.valueOf(scale.getAttribute("V")) * mxVsdxUtils.conversionFactor;
}
return 1;
}
public String getCellValue(String cellName)
{
Element cell = this.cellElements.get(cellName);
if (cell != null)
{
return cell.getAttribute("V");
}
return null;
}
public int getCellIntValue(String cellName, int defVal)
{
String val = getCellValue(cellName);
if (val != null)
{
return Integer.parseInt(val);
}
return defVal;
}
/**
* Returns the ID of the page
* @return the ID of the page

View file

@ -0,0 +1,453 @@
package com.mxgraph.io.vsdx;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.mxgraph.io.vsdx.theme.Color;
import com.mxgraph.io.vsdx.theme.FillStyle;
import com.mxgraph.io.vsdx.theme.FillStyleFactory;
import com.mxgraph.io.vsdx.theme.OoxmlColor;
import com.mxgraph.io.vsdx.theme.OoxmlColorFactory;
//Holds office 2013 theme data which applies to all office file formats
public class mxVsdxTheme
{
//Theme names to ID mapping
private static Map<String, Integer> themesIds = new HashMap<>();
//Theme index can be found deep inside the theme file, so this is faster for standard 2013 format
static
{
themesIds.put("Office", 33);
themesIds.put("Linear", 34);
themesIds.put("Zephyr", 35);
themesIds.put("Integral", 36);
themesIds.put("Simple", 37);
themesIds.put("Whisp", 38);
themesIds.put("Daybreak", 39);
themesIds.put("Parallel", 40);
themesIds.put("Sequence", 41);
themesIds.put("Slice", 42);
themesIds.put("Ion", 43);
themesIds.put("Retrospect", 44);
themesIds.put("Organic", 45);
themesIds.put("Bubble", 46);
themesIds.put("Clouds", 47);
themesIds.put("Gemstone", 48);
themesIds.put("Lines", 49);
themesIds.put("Facet", 50);
themesIds.put("Prominence", 51);
themesIds.put("Smoke", 52);
themesIds.put("Radiance", 53);
themesIds.put("Shade", 54);
themesIds.put("Pencil", 55);
themesIds.put("Pen", 56);
themesIds.put("Marker", 57);
themesIds.put("Whiteboard", 58);
}
//color id to color name
private static Map<Integer, String> colorIds = new HashMap<>();
//https://msdn.microsoft.com/en-us/library/hh661351%28v=office.12%29.aspx
//There are non standard values of 200 -> 206 also which are handled the same as 100 -> 106
static
{
colorIds.put(0, "dk1");
colorIds.put(1, "lt1");
colorIds.put(2, "accent1");
colorIds.put(3, "accent2");
colorIds.put(4, "accent3");
colorIds.put(5, "accent4");
colorIds.put(6, "accent5");
colorIds.put(7, "accent6");
}
private Element theme;
private int themeIndex = -1;
private int themeVariant = 0;
//colors handling
private Map<String, OoxmlColor> baseColors = new HashMap<>();
//Dynamic background color (index 8)
private OoxmlColor bkgndColor;
//Variant colors
private OoxmlColor[][] variantsColors = new OoxmlColor[4][7];
private boolean[] isMonotoneVariant = new boolean[4];
private Color defaultClr = new Color(255, 255, 255);
//fill style
private ArrayList<FillStyle> fillStyles = new ArrayList<>(6);
private int[] variantEmbellishment = new int[4];
private int[][] variantFillIdx = new int[4][4];
private int[][] variantLineIdx = new int[4][4];
private int[][] variantEffectIdx = new int[4][4];
private int[][] variantFontIdx = new int[4][4];
private boolean isProcessed = false;
public mxVsdxTheme(Element theme)
{
this.theme = theme;
Integer themeId = themesIds.get(theme.getAttribute("name"));
if (themeId != null)
{
themeIndex = themeId;
}
}
public int getThemeIndex()
{
return themeIndex;
}
public void setVariant(int variant)
{
themeVariant = variant;
}
public void processTheme()
{
if (isProcessed) return;
try
{
Node child = theme.getFirstChild();
while (child != null)
{
if (child instanceof Element && ((Element)child).getNodeName().equals("a:themeElements"))
{
Node child2 = child.getFirstChild();
while (child2 != null)
{
if (child2 instanceof Element)
{
Element elem = (Element)child2;
String nodeName = elem.getNodeName();
if (nodeName.equals("a:clrScheme"))
{
//Process the color scheme
processColors(elem);
}
else if (nodeName.equals("a:fontScheme"))
{
//Process the font scheme
processFonts(elem);
}
else if (nodeName.equals("a:fmtScheme"))
{
//Process the format scheme
processFormats(elem);
}
else if (nodeName.equals("a:extLst"))
{
//Process the extra list
processExtras(elem);
}
}
child2 = child2.getNextSibling();
}
}
child = child.getNextSibling();
}
}
catch (Exception e)
{
//cannot parse the theme format, probably it has non-standard format
e.printStackTrace();
}
isProcessed = true;
}
private void processExtras(Element element)
{
ArrayList<Element> exts = mxVsdxUtils.getDirectChildElements(element);
for (Element ext : exts)
{
Element vt = mxVsdxUtils.getDirectFirstChildElement(ext);
switch (vt.getNodeName())
{
case "vt:fmtConnectorScheme":
//TODO implement connector format scheme
break;
case "vt:lineStyles":
//TODO implement line styles
break;
case "vt:fontStylesGroup":
//TODO implement font styles
break;
case "vt:variationStyleSchemeLst":
ArrayList<Element> varStyleSchemes = mxVsdxUtils.getDirectChildElements(vt);
int i=0;
for (Element varStyleScheme : varStyleSchemes)
{
variantEmbellishment[i] = mxVsdxUtils.getIntAttr(varStyleScheme, "embellishment");
ArrayList<Element> varStyles = mxVsdxUtils.getDirectChildElements(varStyleScheme);
int j = 0;
for (Element varStyle : varStyles)
{
variantFillIdx[i][j] = mxVsdxUtils.getIntAttr(varStyle, "fillIdx");
variantLineIdx[i][j] = mxVsdxUtils.getIntAttr(varStyle, "lineIdx");
variantEffectIdx[i][j] = mxVsdxUtils.getIntAttr(varStyle, "effectIdx");
variantFontIdx[i][j] = mxVsdxUtils.getIntAttr(varStyle, "fontIdx");
j++;
}
i++;
}
break;
}
}
}
private void processFormats(Element element)
{
ArrayList<Element> styles = mxVsdxUtils.getDirectChildElements(element);
for (Element style : styles)
{
if (style.getNodeName().equals("a:fillStyleLst"))
{
ArrayList<Element> fillStyleElems = mxVsdxUtils.getDirectChildElements(style);
for (Element fillStyle : fillStyleElems)
{
fillStyles.add(FillStyleFactory.getFillStyle(fillStyle));
}
}
}
}
private void processFonts(Element element) {
// TODO Auto-generated method stub
}
private void processColors(Element element)
{
Node child = element.getFirstChild();
while (child != null)
{
if (child instanceof Element)
{
Element elem = (Element)child;
String nodeName = elem.getNodeName();
ArrayList<Element> children = mxVsdxUtils.getDirectChildElements(elem);
if (nodeName.equals("a:extLst"))
{
if (children.size() == 3) //the format has three a:ext nodes
{
if (themeIndex < 0)
{
extractThemeIndex(children.get(0));
}
addBkgndColor(children.get(1));
addVariantColors(children.get(2));
}
}
else
{
String clrName = nodeName.substring(2);
if (children.size() > 0)
{
addBasicColor(clrName, children.get(0));
}
}
}
child = child.getNextSibling();
}
}
private void addVariantColors(Element element)
{
Element parent = mxVsdxUtils.getDirectFirstChildElement(element);
if (parent != null)
{
ArrayList<Element> variants = mxVsdxUtils.getDirectChildElements(parent);
int i = 0;
for (Element variant : variants)
{
addVariantColorsSet(i++, variant);
}
}
}
private void addVariantColorsSet(int index, Element variant)
{
ArrayList<Element> colors = mxVsdxUtils.getDirectChildElements(variant);
isMonotoneVariant[index] = variant.hasAttribute("monotone");
for (Element color : colors)
{
String name = color.getNodeName();
switch (name)
{
case "vt:varColor1":
variantsColors[index][0] = OoxmlColorFactory.getOoxmlColor(
mxVsdxUtils.getDirectFirstChildElement(color));
break;
case "vt:varColor2":
variantsColors[index][1] = OoxmlColorFactory.getOoxmlColor(
mxVsdxUtils.getDirectFirstChildElement(color));
break;
case "vt:varColor3":
variantsColors[index][2] = OoxmlColorFactory.getOoxmlColor(
mxVsdxUtils.getDirectFirstChildElement(color));
break;
case "vt:varColor4":
variantsColors[index][3] = OoxmlColorFactory.getOoxmlColor(
mxVsdxUtils.getDirectFirstChildElement(color));
break;
case "vt:varColor5":
variantsColors[index][4] = OoxmlColorFactory.getOoxmlColor(
mxVsdxUtils.getDirectFirstChildElement(color));
break;
case "vt:varColor6":
variantsColors[index][5] = OoxmlColorFactory.getOoxmlColor(
mxVsdxUtils.getDirectFirstChildElement(color));
break;
case "vt:varColor7":
variantsColors[index][6] = OoxmlColorFactory.getOoxmlColor(
mxVsdxUtils.getDirectFirstChildElement(color));
break;
}
}
}
private void addBkgndColor(Element element)
{
Element elem = mxVsdxUtils.getDirectFirstChildElement(element);
if (elem != null)
{
bkgndColor = OoxmlColorFactory.getOoxmlColor(mxVsdxUtils.getDirectFirstChildElement(elem));
}
}
private void extractThemeIndex(Element element)
{
Element elem = mxVsdxUtils.getDirectFirstChildElement(element);
if (elem != null)
{
themeIndex = Integer.parseInt(elem.getAttribute("schemeEnum"));
}
}
private void addBasicColor(String clrName, Element element)
{
baseColors.put(clrName, OoxmlColorFactory.getOoxmlColor(element));
}
public Color getSchemeColor(String val)
{
processTheme();
OoxmlColor color = baseColors.get(val);
return color != null? color.getColor(this) : defaultClr;
}
// QuickStyleFillColor
public Color getStyleColor(int styleColor)
{
processTheme();
if (styleColor < 8)
{
OoxmlColor color = baseColors.get(colorIds.get(styleColor));
if (color != null)
{
return color.getColor(this);
}
}
else if (styleColor == 8)
{
if (bkgndColor != null)
{
return bkgndColor.getColor(this);
}
}
else
{
OoxmlColor color = null;
int clrIndex = 0;
if (styleColor >= 200) //200-206
{
clrIndex = styleColor - 200;
}
else if (styleColor >= 100) //100-106
{
clrIndex = styleColor - 100;
}
if (clrIndex >= 0 && clrIndex <= 6) //0 - 6
{
color = variantsColors[themeVariant][clrIndex];
}
if (color != null)
{
return color.getColor(this);
}
}
return defaultClr;
}
//Get fill color based on QuickStyleFillColor & QuickStyleFillMatrix
public Color getFillColor(int quickStyleFillColor, int quickStyleFillMatrix)
{
processTheme();
int fillColorStyle = quickStyleFillColor;
FillStyle fillStyle = null;
switch (quickStyleFillMatrix)
{
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
fillStyle = fillStyles.get(quickStyleFillMatrix - 1);
break;
case 100:
case 101:
case 102:
case 103:
if (isMonotoneVariant[themeVariant]) fillColorStyle = 100;
int index = quickStyleFillMatrix - 100;
//get style index of variants
fillStyle = fillStyles.get(variantFillIdx[themeVariant][index] - 1);
break;
}
if (fillStyle != null)
{
return fillStyle.applyStyle(fillColorStyle, this);
}
else
{
return getStyleColor(fillColorStyle);
}
}
}

View file

@ -50,6 +50,79 @@ public class mxVsdxUtils
return result;
}
/**
* Returns a collection of direct child Elements
* @param parent the parent whose direct children will be processed
* @return a collection of all child Elements
*/
public static ArrayList<Element> getDirectChildElements(Element parent)
{
ArrayList<Element> result = new ArrayList<Element>();
for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling())
{
if (child instanceof Element)
{
result.add((Element)child);
}
}
return result;
}
/**
* Returns the first direct child Element
* @param parent the parent whose direct first child will be processed
* @return the first child Element
*/
public static Element getDirectFirstChildElement(Element parent)
{
for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling())
{
if (child instanceof Element)
{
return (Element)child;
}
}
return null;
}
/**
* Return the value of an integer attribute or the default value
* @param elem Element
* @param attName Attribute name
* @param defVal default value
* @return the parsed attribute value or the default value
*/
public static int getIntAttr(Element elem, String attName, int defVal)
{
try
{
String val = elem.getAttribute(attName);
if (val != null)
{
return Integer.parseInt(val);
}
}
catch (NumberFormatException e)
{
//nothing, just return the default value
}
return defVal;
}
/**
* Return the value of an integer attribute or zero
* @param elem Element
* @param attName Attribute name
* @return the parsed attribute value or zero
*/
public static int getIntAttr(Element elem, String attName)
{
return getIntAttr(elem, attName, 0);
}
/**
* Returns the string that represents the content of a given style map.
* @param styleMap Map with the styles values

View file

@ -0,0 +1,92 @@
package com.mxgraph.io.vsdx.theme;
public class Color {
//Special none color
public static final Color NONE = new Color(-1, -1, -1);
private int red, green, blue;
private Color gradientClr;
public Color(int red, int green, int blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
public int getRed() {
return red;
}
public void setRed(int red) {
this.red = red;
}
public int getGreen() {
return green;
}
public void setGreen(int green) {
this.green = green;
}
public int getBlue() {
return blue;
}
public void setBlue(int blue) {
this.blue = blue;
}
public HSLColor toHsl()
{
double r = this.getRed()/255.0, g = this.getGreen()/255.0, b = this.getBlue()/255.0;
double max = Math.max(r, Math.max(g, b));
double min = Math.min(r, Math.min(g, b));
double l = (max + min) / 2.0;
double h, s;
if(max == min)
{
h = s = 0; // achromatic
}
else
{
double d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
if (max == r)
{
h = (g - b) / d + (g < b ? 6 : 0);
}
else if (max == g)
{
h = (b - r) / d + 2;
}
else
{
h = (r - g) / d + 4;
}
h /= 6;
}
return new HSLColor(h, s, l);
}
public static Color decodeColorHex(String hex)
{
int color = Integer.parseInt(hex, 16);
return new Color((color >> 16) & 0xff , (color >> 8) & 0xff, color & 0xff);
}
public String toHexStr() {
int clr = (red << 16) | (green << 8) | blue;
return "#" + Integer.toHexString(clr);
}
public Color getGradientClr() {
return gradientClr;
}
public void setGradientClr(Color gradientClr) {
this.gradientClr = gradientClr;
}
}

View file

@ -0,0 +1,7 @@
package com.mxgraph.io.vsdx.theme;
import com.mxgraph.io.vsdx.mxVsdxTheme;
public interface FillStyle {
public Color applyStyle(int styleValue, mxVsdxTheme theme);
}

View file

@ -0,0 +1,36 @@
package com.mxgraph.io.vsdx.theme;
import org.w3c.dom.Element;
import com.mxgraph.io.vsdx.mxVsdxUtils;
public class FillStyleFactory
{
public static FillStyle getFillStyle(Element fillStyle)
{
FillStyle fillObj = null;
switch (fillStyle.getNodeName())
{
case "a:solidFill":
fillObj = new SolidFillStyle(OoxmlColorFactory.getOoxmlColor(
mxVsdxUtils.getDirectFirstChildElement(fillStyle)));
break;
case "a:noFill":
fillObj = new NoFillStyle();
break;
case "a:gradFill":
fillObj = new GradFill(fillStyle);
break;
case "a:blipFill":
//TODO implement Picture Fill if it can be approximated in mxGraph
break;
case "a:pattFill":
//TODO implement Pattern Fill if it can be approximated in mxGraph
break;
case "a:grpFill":
//TODO implement Group Fill if it can be approximated in mxGraph
break;
}
return fillObj;
}
}

View file

@ -0,0 +1,46 @@
package com.mxgraph.io.vsdx.theme;
import java.util.ArrayList;
import org.w3c.dom.Element;
import com.mxgraph.io.vsdx.mxVsdxTheme;
import com.mxgraph.io.vsdx.mxVsdxUtils;
//mxGraph doesn't support such a complex gradient fill style. So, we will approximate the gradient by the first two colors only
public class GradFill implements FillStyle
{
private OoxmlColor color1 = null, color2 = null;
public GradFill(Element elem)
{
ArrayList<Element> gsLst = mxVsdxUtils.getDirectChildNamedElements(elem, "a:gsLst");
if (gsLst.size() > 0)
{
ArrayList<Element> gs = mxVsdxUtils.getDirectChildElements(gsLst.get(0));
if (gs.size() >= 2)
{
color1 = OoxmlColorFactory.getOoxmlColor(
mxVsdxUtils.getDirectFirstChildElement(gs.get(0)));
color2 = OoxmlColorFactory.getOoxmlColor(
mxVsdxUtils.getDirectFirstChildElement(gs.get(1)));
}
}
if (color1 == null)
{
color1 = color2 = new SrgbClr("FFFFFF");
}
}
@Override
public Color applyStyle(int styleValue, mxVsdxTheme theme)
{
Color color = color1.getColor(styleValue, theme);
color.setGradientClr(color2.getColor(styleValue, theme));
return color;
}
}

View file

@ -0,0 +1,120 @@
package com.mxgraph.io.vsdx.theme;
public class HSLColor
{
private double hue, sat, lum;
public HSLColor(double hue, double sat, double lum)
{
this.hue = hue;
this.sat = sat;
this.lum = lum;
}
public double getHue() {
return hue;
}
public void setHue(double hue) {
this.hue = hue;
}
public double getSat() {
return sat;
}
public void setSat(double sat) {
this.sat = sat;
}
public double getLum() {
return lum;
}
public void setLum(double lum) {
this.lum = lum;
}
private double hue2rgb(double p, double q, double t)
{
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6.0) return p + (q - p) * 6 * t;
if (t < 0.5) return q;
if (t < 2/3.0) return p + (q - p) * (2/3.0 - t) * 6;
return p;
}
public Color toRgb()
{
double r, g, b;
double h = this.hue;
double s = this.sat;
double l = this.lum;
if(s == 0)
{
r = g = b = l; // achromatic
}
else
{
double q = l < 0.5 ? l * (1 + s) : l + s - l * s;
double p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3.0);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3.0);
}
return new Color((int) (r * 255), (int) (g * 255), (int) (b * 255));
}
// Force a number between 0 and 1
private double clamp01(double val)
{
return Math.min(1, Math.max(0, val));
}
//lighten or tint
public HSLColor tint (int amount)
{
// HSLColor hsl = color.toHsl();
this.lum *= (1 + (amount / 100.0));
this.lum = clamp01(this.lum);
return this;
}
//darken or shade
public HSLColor shade(int amount)
{
this.lum *= amount / 100.0;
this.lum = clamp01(this.lum);
return this;
}
public HSLColor satMod(int amount)
{
this.sat *= amount / 100.0;
this.sat = clamp01(this.sat);
return this;
}
public HSLColor lumMod(int amount)
{
this.lum *= amount / 100.0;
this.lum = clamp01(this.lum);
return this;
}
}

View file

@ -0,0 +1,12 @@
package com.mxgraph.io.vsdx.theme;
public class HslClr extends OoxmlColor {
private double hue, sat, lum;
public HslClr(int hue, int sat, int lum) {
this.hue = hue / 360.0;
this.sat = sat / 100.0;
this.lum = lum / 100.0;
color = new HSLColor(hue, sat, lum).toRgb();
}
}

View file

@ -0,0 +1,15 @@
package com.mxgraph.io.vsdx.theme;
import com.mxgraph.io.vsdx.mxVsdxTheme;
public class NoFillStyle implements FillStyle
{
@Override
public Color applyStyle(int styleValue, mxVsdxTheme theme)
{
return Color.NONE;
}
}

View file

@ -0,0 +1,253 @@
package com.mxgraph.io.vsdx.theme;
import com.mxgraph.io.vsdx.mxVsdxTheme;
abstract public class OoxmlColor
{
// a:tint Tint
private int tint = 0;
// a:shade Shade
private int shade = 0;
// a:comp Complement
private int comp = 0;
// a:inv Inverse
private int inv = 0;
// a:gray Gray
private int gray = 0;
// a:alpha Alpha
private int alpha = 0;
// a:alphaOff Alpha Offset
private int alphaOff = 0;
// a:alphaMod Alpha Modulation
private int alphaMod = 0;
// a:hue Hue
private int hue = 0;
// a:hueOff Hue Offset
private int hueOff = 0;
// a:hueMod Hue Modulate
private int hueMod = 0;
// a:sat Saturation
private int sat = 0;
// a:satOff Saturation Offset
private int satOff = 0;
// a:satMod Saturation Modulation
private int satMod = 0;
// a:lum Luminance
private int lum = 0;
// a:lumOff Luminance Offset
private int lumOff = 0;
// a:lumMod Luminance Modulation
private int lumMod = 0;
// a:red Red
private int red = 0;
// a:redOff Red Offset
private int redOff = 0;
// a:redMod Red Modulation
private int redMod = 0;
// a:green Green
private int green = 0;
// a:greenOff Green Offset
private int greenOff = 0;
// a:greenMod Green Modification
private int greenMod = 0;
// a:blue Blue
private int blue = 0;
// a:blueOff Blue Offset
private int blueOff = 0;
// a:blueMod Blue Modification
private int blueMod = 0;
// a:gamma Gamma
private int gamma = 0;
// a:invGamma Inverse Gamma
private int invGamma = 0;
protected Color color;
protected boolean isDynamic = false;
protected boolean isInitialized = false;
protected boolean hasEffects = false;
protected void calcColor(int styleColor, mxVsdxTheme theme)
{
if (hasEffects)
{
//TODO complete the list of effects
//currently we support tint, shade, satMod, lumMod
HSLColor hslColor = color.toHsl();
if (tint != 0)
{
hslColor.tint(tint);
}
if (shade != 0)
{
hslColor.shade(shade);
}
if (satMod != 0)
{
hslColor.satMod(satMod);
}
if (lumMod != 0)
{
hslColor.lumMod(lumMod);
}
color = hslColor.toRgb();
}
}
public Color getColor(int styleColor, mxVsdxTheme theme)
{
if (isDynamic || !isInitialized)
{
calcColor(styleColor, theme);
isInitialized = true;
}
return color;
}
public Color getColor(mxVsdxTheme theme)
{
return getColor(-1, theme);
}
public void setTint(int tint) {
this.tint = tint;
hasEffects = true;
}
public void setShade(int shade) {
this.shade = shade;
hasEffects = true;
}
public void setComp(int comp) {
this.comp = comp;
hasEffects = true;
}
public void setInv(int inv) {
this.inv = inv;
hasEffects = true;
}
public void setGray(int gray) {
this.gray = gray;
hasEffects = true;
}
public void setAlpha(int alpha) {
this.alpha = alpha;
hasEffects = true;
}
public void setAlphaOff(int alphaOff) {
this.alphaOff = alphaOff;
hasEffects = true;
}
public void setAlphaMod(int alphaMod) {
this.alphaMod = alphaMod;
hasEffects = true;
}
public void setHue(int hue) {
this.hue = hue;
hasEffects = true;
}
public void setHueOff(int hueOff) {
this.hueOff = hueOff;
hasEffects = true;
}
public void setHueMod(int hueMod) {
this.hueMod = hueMod;
hasEffects = true;
}
public void setSat(int sat) {
this.sat = sat;
hasEffects = true;
}
public void setSatOff(int satOff) {
this.satOff = satOff;
hasEffects = true;
}
public void setSatMod(int satMod) {
this.satMod = satMod;
hasEffects = true;
}
public void setLum(int lum) {
this.lum = lum;
hasEffects = true;
}
public void setLumOff(int lumOff) {
this.lumOff = lumOff;
hasEffects = true;
}
public void setLumMod(int lumMod) {
this.lumMod = lumMod;
hasEffects = true;
}
public void setRed(int red) {
this.red = red;
hasEffects = true;
}
public void setRedOff(int redOff) {
this.redOff = redOff;
hasEffects = true;
}
public void setRedMod(int redMod) {
this.redMod = redMod;
hasEffects = true;
}
public void setGreen(int green) {
this.green = green;
hasEffects = true;
}
public void setGreenOff(int greenOff) {
this.greenOff = greenOff;
hasEffects = true;
}
public void setGreenMod(int greenMod) {
this.greenMod = greenMod;
hasEffects = true;
}
public void setBlue(int blue) {
this.blue = blue;
hasEffects = true;
}
public void setBlueOff(int blueOff) {
this.blueOff = blueOff;
hasEffects = true;
}
public void setBlueMod(int blueMod) {
this.blueMod = blueMod;
hasEffects = true;
}
public void setGamma(int gamma) {
this.gamma = gamma;
hasEffects = true;
}
public void setInvGamma(int invGamma) {
this.invGamma = invGamma;
hasEffects = true;
}
}

View file

@ -0,0 +1,98 @@
package com.mxgraph.io.vsdx.theme;
import java.util.ArrayList;
import org.w3c.dom.Element;
import com.mxgraph.io.vsdx.mxVsdxUtils;
public class OoxmlColorFactory {
//TODO Refactor the code such that each class parse itself
public static OoxmlColor getOoxmlColor(Element element)
{
OoxmlColor color = null;
String nodeName = element.getNodeName();
switch (nodeName)
{
case "a:scrgbClr":
color = new ScrgbClr(
Integer.parseInt(element.getAttribute("r")),
Integer.parseInt(element.getAttribute("g")),
Integer.parseInt(element.getAttribute("b")));
break;
case "a:srgbClr":
color = new SrgbClr(element.getAttribute("val"));
break;
case "a:hslClr":
color = new HslClr(
Integer.parseInt(element.getAttribute("hue")),
Integer.parseInt(element.getAttribute("sat")),
Integer.parseInt(element.getAttribute("lum")));
break;
case "a:sysClr":
color = new SysClr(
element.getAttribute("val"),
element.getAttribute("lastClr")
);
break;
case "a:schemeClr":
color = new SchemeClr(element.getAttribute("val"));
break;
case "a:prstClr":
color = new SrgbClr(element.getAttribute("val"));
break;
}
ArrayList<Element> effects = mxVsdxUtils.getDirectChildElements(element);
for (Element effect : effects)
{
int effVal = Integer.parseInt(effect.getAttribute("val")) / 1000; //these values are multiplied by 10,000 so we divide by 1,000 to keep the percentage only
String effName = effect.getNodeName();
switch(effName)
{
case "a:tint":
color.setTint(effVal);
break;
case "a:shade":
color.setShade(effVal);
break;
case "a:satMod":
color.setSatMod(effVal);
break;
case "a:lumMod":
color.setLumMod(effVal);
break;
//TODO complete the list when supported
// a:comp Complement
// a:inv Inverse
// a:gray Gray
// a:alpha Alpha
// a:alphaOff Alpha Offset
// a:alphaMod Alpha Modulation
// a:hue Hue
// a:hueOff Hue Offset
// a:hueMod Hue Modulate
// a:sat Saturation
// a:satOff Saturation Offset
// a:lum Luminance
// a:lumOff Luminance Offset
// a:red Red
// a:redOff Red Offset
// a:redMod Red Modulation
// a:green Green
// a:greenOff Green Offset
// a:greenMod Green Modification
// a:blue Blue
// a:blueOff Blue Offset
// a:blueMod Blue Modification
// a:gamma Gamma
// a:invGamma Inverse Gamma
}
}
return color;
}
}

View file

@ -0,0 +1,155 @@
package com.mxgraph.io.vsdx.theme;
public class PrstClr extends OoxmlColor {
private String val;
public PrstClr(String val) {
this.val = val;
//TODO Implement this if it is used
color = new Color(255, 255, 255);
// aliceBlue Alice Blue Preset Color
// antiqueWhite Antique White Preset Color
// aqua Aqua Preset Color
// aquamarine Aquamarine Preset Color
// azure Azure Preset Color
// beige Beige Preset Color
// bisque Bisque Preset Color
// black Black Preset Color
// blanchedAlmond Blanched Almond Preset Color
// blue Blue Preset Color
// blueViolet Blue Violet Preset Color
// brown Brown Preset Color
// burlyWood Burly Wood Preset Color
// cadetBlue Cadet Blue Preset Color
// chartreuse Chartreuse Preset Color
// chocolate Chocolate Preset Color
// coral Coral Preset Color
// cornflowerBlue Cornflower Blue Preset Color
// cornsilk Cornsilk Preset Color
// crimson Crimson Preset Color
// cyan Cyan Preset Color
// dkBlue Dark Blue Preset Color
// dkCyan Dark Cyan Preset Color
// dkGoldenrod Dark Goldenrod Preset Color
// dkGray Dark Gray Preset Color
// dkGreen Dark Green Preset Color
// dkKhaki Dark Khaki Preset Color
// dkMagenta Dark Magenta Preset Color
// dkOliveGreen Dark Olive Green Preset Color
// dkOrange Dark Orange Preset Color
// dkOrchid Dark Orchid Preset Color
// dkRed Dark Red Preset Color
// dkSalmon Dark Salmon Preset Color
// dkSeaGreen Dark Sea Green Preset Color
// dkSlateBlue Dark Slate Blue Preset Color
// dkSlateGray Dark Slate Gray Preset Color
// dkTurquoise Dark Turquoise Preset Color
// dkViolet Dark Violet Preset Color
// deepPink Deep Pink Preset Color
// deepSkyBlue Deep Sky Blue Preset Color
// dimGray Dim Gray Preset Color
// dodgerBlue Dodger Blue Preset Color
// firebrick Firebrick Preset Color
// floralWhite Floral White Preset Color
// forestGreen Forest Green Preset Color
// fuchsia Fuchsia Preset Color
// gainsboro Gainsboro Preset Color
// ghostWhite Ghost White Preset Color
// gold Gold Preset Color
// goldenrod Goldenrod Preset Color
// gray Gray Preset Color
// green Green Preset Color
// greenYellow Green Yellow Preset Color
// honeydew Honeydew Preset Color
// hotPink Hot Pink Preset Color
// indianRed Indian Red Preset Color
// indigo Indigo Preset Color
// ivory Ivory Preset Color
// khaki Khaki Preset Color
// lavender Lavender Preset Color
// lavenderBlush Lavender Blush Preset Color
// lawnGreen Lawn Green Preset Color
// lemonChiffon Lemon Chiffon Preset Color
// ltBlue Light Blue Preset Color
// ltCoral Light Coral Preset Color
// ltCyan Light Cyan Preset Color
// ltGoldenrodYellow Light Goldenrod Yellow Preset Color
// ltGray Light Gray Preset Color
// ltGreen Light Green Preset Color
// ltPink Light Pink Preset Color
// ltSalmon Light Salmon Preset Color
// ltSeaGreen Light Sea Green Preset Color
// ltSkyBlue Light Sky Blue Preset Color
// ltSlateGray Light Slate Gray Preset Color
// ltSteelBlue Light Steel Blue Preset Color
// ltYellow Light Yellow Preset Color
// lime Lime Preset Color
// limeGreen Lime Green Preset Color
// linen Linen Preset Color
// magenta Magenta Preset Color
// maroon Maroon Preset Color
// medAquamarine Medium Aquamarine Preset Color
// medBlue Medium Blue Preset Color
// medOrchid Medium Orchid Preset Color
// medPurple Medium Purple Preset Color
// medSeaGreen Medium Sea Green Preset Color
// medSlateBlue Medium Slate Blue Preset Color
// medSpringGreen Medium Spring Green Preset Color
// medTurquoise Medium Turquoise Preset Color
// medVioletRed Medium Violet Red Preset Color
// midnightBlue Midnight Blue Preset Color
// mintCream Mint Cream Preset Color
// mistyRose Misty Rose Preset Color
// moccasin Moccasin Preset Color
// navajoWhite Navajo White Preset Color
// navy Navy Preset Color
// oldLace Old Lace Preset Color
// olive Olive Preset Color
// oliveDrab Olive Drab Preset Color
// orange Orange Preset Color
// orangeRed Orange Red Preset Color
// orchid Orchid Preset Color
// paleGoldenrod Pale Goldenrod Preset Color
// paleGreen Pale Green Preset Color
// paleTurquoise Pale Turquoise Preset Color
// paleVioletRed Pale Violet Red Preset Color
// papayaWhip Papaya Whip Preset Color
// peachPuff Peach Puff Preset Color
// peru Peru Preset Color
// pink Pink Preset Color
// plum Plum Preset Color
// powderBlue Powder Blue Preset Color
// purple Purple Preset Color
// red Red Preset Color
// rosyBrown Rosy Brown Preset Color
// royalBlue Royal Blue Preset Color
// saddleBrown Saddle Brown Preset Color
// salmon Salmon Preset Color
// sandyBrown Sandy Brown Preset Color
// seaGreen Sea Green Preset Color
// seaShell Sea Shell Preset Color
// sienna Sienna Preset Color
// silver Silver Preset Color
// skyBlue Sky Blue Preset Color
// slateBlue Slate Blue Preset Color
// slateGray Slate Gray Preset Color
// snow Snow Preset Color
// springGreen Spring Green Preset Color
// steelBlue Steel Blue Preset Color
// tan Tan Preset Color
// teal Teal Preset Color
// thistle Thistle Preset Color
// tomato Tomato Preset Color
// turquoise Turquoise Preset Color
// violet Violet Preset Color
// wheat Wheat Preset Color
// white White Preset Color
// whiteSmoke White Smoke Preset Color
// yellow Yellow Preset Color
// yellowGreen Yellow Green Preset Color
}
}

View file

@ -0,0 +1,45 @@
package com.mxgraph.io.vsdx.theme;
import com.mxgraph.io.vsdx.mxVsdxTheme;
public class SchemeClr extends OoxmlColor
{
private String val;
// bg1 Background Color 1
// tx1 Text Color 1
// bg2 Background Color 2
// tx2 Text Color 2
// accent1 Accent Color 1
// accent2 Accent Color 2
// accent3 Accent Color 3
// accent4 Accent Color 4
// accent5 Accent Color 5
// accent6 Accent Color 6
// hlink Hyperlink Color
// folHlink Followed Hyperlink Color
// phClr Style Color
// dk1 Dark Color 1
// lt1 Light Color 1
// dk2 Dark Color 2
// lt2 Light Color 2
public SchemeClr(String val)
{
isDynamic = true;
this.val = val;
}
protected void calcColor(int styleColor, mxVsdxTheme theme)
{
if (!"phClr".equals(val))
{
color = theme.getSchemeColor(val);
isDynamic = false;
} else {
color = theme.getStyleColor(styleColor);
}
super.calcColor(styleColor, theme);
}
}

View file

@ -0,0 +1,14 @@
package com.mxgraph.io.vsdx.theme;
public class ScrgbClr extends OoxmlColor{
private int r,g,b;
public ScrgbClr(int r, int g, int b) {
this.r = r;
this.g = g;
this.b = b;
color = new Color(r, g, b);
}
}

View file

@ -0,0 +1,20 @@
package com.mxgraph.io.vsdx.theme;
import com.mxgraph.io.vsdx.mxVsdxTheme;
public class SolidFillStyle implements FillStyle
{
private OoxmlColor color;
public SolidFillStyle(OoxmlColor color)
{
this.color = color;
}
@Override
public Color applyStyle(int styleValue, mxVsdxTheme theme)
{
return color.getColor(styleValue, theme);
}
}

View file

@ -0,0 +1,10 @@
package com.mxgraph.io.vsdx.theme;
public class SrgbClr extends OoxmlColor {
private String hexVal;
public SrgbClr(String hexVal) {
this.hexVal = hexVal;
color = Color.decodeColorHex(hexVal);
}
}

View file

@ -0,0 +1,57 @@
package com.mxgraph.io.vsdx.theme;
public class SysClr extends OoxmlColor
{
private String val, lastClr;
public SysClr(String val, String lastClr)
{
this.val = val;
this.lastClr = lastClr;
//System color depends on the system. So, if lastClr is not given, guess best common system color
String hexVal = lastClr;
if (hexVal == null)
{
switch(val)
{
case "windowText": hexVal = "000000"; break;
case "window": hexVal = "FFFFFF"; break;
//TODO complete the cases! but this is rarely used
// scrollBar Scroll Bar System Color
// background Background System Color
// activeCaption Active Caption System Color
// inactiveCaption Inactive Caption System Color
// menu Menu System Color
// windowFrame Window Frame System Color
// menuText Menu Text System Color
// captionText Caption Text System Color
// activeBorder Active Border System Color
// inactiveBorder Inactive Border System Color
// appWorkspace Application Workspace System Color
// highlight Highlight System Color
// highlightText Highlight Text System Color
// btnFace Button Face System Color
// btnShadow Button Shadow System Color
// grayText Gray Text System Color
// btnText Button Text System Color
// inactiveCaptionText Inactive Caption Text System Color
// btnHighlight Button Highlight System Color
// 3dDkShadow 3D Dark System Color
// 3dLight 3D Light System Color
// infoText Info Text System Color
// infoBk Info Back System Color
// hotLight Hot Light System Color
// gradientActiveCaption Gradient Active Caption System Color
// gradientInactiveCaption Gradient Inactive Caption System Color
// menuHighlight Menu Highlight System Color
// menuBar Menu Bar System Color
default:
hexVal = "FFFFFF";
}
}
color = Color.decodeColorHex(hexVal);
}
}

View file

@ -1,7 +1,7 @@
CACHE MANIFEST
# THIS FILE WAS GENERATED. DO NOT MODIFY!
# 03/16/2017 05:01 PM
# 03/24/2017 11:20 AM
app.html
index.html?offline=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 27 KiB

303
war/js/app.min.js vendored

File diff suppressed because one or more lines are too long

197
war/js/atlas.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
/**
* Copyright (c) 2006-2016, JGraph Ltd
* Copyright (c) 2006-2016, Gaudenz Alder
* Copyright (c) 2006-2017, JGraph Ltd
* Copyright (c) 2006-2017, Gaudenz Alder
*/
/**
* Constructs a new point for the optional x and y coordinates. If no
@ -1161,12 +1161,13 @@ App.prototype.checkLicense = function()
if (at >= 0)
{
domain = email.substring(at + 1);
email = this.crc32(email.substring(0, at)) + '@' + domain;
//email = this.crc32(email.substring(0, at)) + '@' + domain;
}
// Timestamp is workaround for cached response in certain environments
mxUtils.post('/license', 'domain=' + encodeURIComponent(domain) + '&email=' +
encodeURIComponent(email) + '&ts=' + new Date().getTime(),
mxUtils.post('/license', 'domain=' + encodeURIComponent(domain) + '&email=' + encodeURIComponent(email) +
'&ds=' + encodeURIComponent(driveUser.displayName) + '&lc=' + encodeURIComponent(driveUser.locale) +
'&ts=' + new Date().getTime(),
mxUtils.bind(this, function(req)
{
var registered = false;

View file

@ -45,6 +45,7 @@ mxscript(drawDevUrl + 'js/diagramly/sidebar/Sidebar-Electrical.js');
mxscript(drawDevUrl + 'js/diagramly/sidebar/Sidebar-ER.js');
mxscript(drawDevUrl + 'js/diagramly/sidebar/Sidebar-Floorplan.js');
mxscript(drawDevUrl + 'js/diagramly/sidebar/Sidebar-Flowchart.js');
mxscript(drawDevUrl + 'js/diagramly/sidebar/Sidebar-GCP.js');
mxscript(drawDevUrl + 'js/diagramly/sidebar/Sidebar-Gmdl.js');
mxscript(drawDevUrl + 'js/diagramly/sidebar/Sidebar-Ios.js');
mxscript(drawDevUrl + 'js/diagramly/sidebar/Sidebar-Ios7.js');

View file

@ -2,33 +2,20 @@
* Copyright (c) 2006-2017, JGraph Ltd
* Copyright (c) 2006-2017, Gaudenz Alder
*/
DrawioUser = function(id, email, displayName, pictureUrl)
DrawioUser = function(id, email, displayName, pictureUrl, locale)
{
/**
* Holds the x-coordinate of the point.
* @type number
* @default 0
*/
// Unique ID of the user for the current storage system
this.id = id;
/**
* Holds the x-coordinate of the point.
* @type number
* @default 0
*/
// Email address of the user
this.email = email;
/**
* Holds the x-coordinate of the point.
* @type number
* @default 0
*/
// Display name of the user
this.displayName = displayName;
/**
* Holds the x-coordinate of the point.
* @type number
* @default 0
*/
// URL to an image of the user
this.pictureUrl = pictureUrl;
// country code locale of the user
this.locale = locale;
};

View file

@ -535,7 +535,7 @@ DriveClient.prototype.updateUser = function(success, error, remember)
this.executeRequest(gapi.client.drive.about.get(), mxUtils.bind(this, function(resp)
{
this.setUser(new DrawioUser(info.id, resp.user.emailAddress, resp.user.displayName,
(resp.user.picture != null) ? resp.user.picture.url : null));
(resp.user.picture != null) ? resp.user.picture.url : null, info.locale));
this.setUserId(info.id, remember);
if (success != null)

View file

@ -0,0 +1,218 @@
(function()
{
// Adds GCP (Google Cloud Platform) shapes
Sidebar.prototype.addGoogleCloudPlatformCardsPalette = function()
{
var sb = this;
var n = 'dashed=0;html=1;' + mxConstants.STYLE_SHAPE + '=mxgraph.gcp.compute.';
var n1 = 'dashed=0;html=1;strokeColor=#dddddd;fillcolor=#ffffff;gradientColor=none;shadow=1;strokeWidth=1;';
var gn = 'mxgraph.gcp.product_cards';
var dt = 'gcp google cloud platform card';
var s = 0.3; //scale
var fns =
[
this.addEntry(dt + 'product', function()
{
var bg = new mxCell('', new mxGeometry(0, 0, 170, 55), n1);
bg.vertex = true;
var icon = new mxCell('', new mxGeometry(0, 0, s * 129, s * 115), n + 'compute_engine;fillColor=#4387FD;gradientColor=#4683EA;strokeColor=none;');
icon.vertex = true;
icon.geometry.relative = true;
icon.geometry.offset = new mxPoint(10, 10);
bg.insert(icon);
var text1 = new mxCell('Compute Engine', new mxGeometry(0, 0.5, 110, 20), 'text;fontSize=13;fontColor=#808080;align=left;verticalAlign=middle;');
text1.vertex = true;
text1.geometry.relative = true;
text1.geometry.offset = new mxPoint(60, -12);
bg.insert(text1);
return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'Product Card');
}),
this.addEntry(dt + 'product', function()
{
var bg = new mxCell('', new mxGeometry(0, 0, 190, 55), n1);
bg.vertex = true;
var icon = new mxCell('', new mxGeometry(0, 0, s * 129, s * 115), n + 'compute_engine;fillColor=#4387FD;gradientColor=#4683EA;strokeColor=none;');
icon.vertex = true;
icon.geometry.relative = true;
icon.geometry.offset = new mxPoint(10, 10);
bg.insert(icon);
var text1 = new mxCell('Analytics Backend', new mxGeometry(0, 0.5, 130, 20), 'text;fontSize=13;fontColor=#444444;align=left;verticalAlign=middle;');
text1.vertex = true;
text1.geometry.relative = true;
text1.geometry.offset = new mxPoint(60, -20);
bg.insert(text1);
var text2 = new mxCell('Compute Engine', new mxGeometry(0, 0.5, 130, 20), 'text;fontSize=13;fontColor=#808080;align=left;verticalAlign=middle;');
text2.vertex = true;
text2.geometry.relative = true;
text2.geometry.offset = new mxPoint(60, 0);
bg.insert(text2);
return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'Product Card');
}),
this.addEntry(dt + 'product', function()
{
var bg1 = new mxCell('', new mxGeometry(0, 0, 190, 55), n1);
bg1.vertex = true;
var icon = new mxCell('', new mxGeometry(0, 0, s * 129, s * 115), n + 'compute_engine;fillColor=#4387FD;gradientColor=#4683EA;strokeColor=none;');
icon.vertex = true;
icon.geometry.relative = true;
icon.geometry.offset = new mxPoint(10, 10);
bg1.insert(icon);
var text1 = new mxCell('Analytics Backend', new mxGeometry(0, 0.5, 130, 20), 'text;fontSize=13;fontColor=#444444;align=left;verticalAlign=middle;');
text1.vertex = true;
text1.geometry.relative = true;
text1.geometry.offset = new mxPoint(60, -20);
bg1.insert(text1);
var text2 = new mxCell('Compute Engine', new mxGeometry(0, 0.5, 130, 20), 'text;fontSize=13;fontColor=#808080;align=left;verticalAlign=middle;');
text2.vertex = true;
text2.geometry.relative = true;
text2.geometry.offset = new mxPoint(60, 0);
bg1.insert(text2);
var bg2 = new mxCell('', new mxGeometry(0, 55, 190, 55), n1);
bg2.vertex = true;
var icon = new mxCell('', new mxGeometry(0, 0, s * 129, s * 115), n + 'compute_engine;fillColor=#4387FD;gradientColor=#4683EA;strokeColor=none;');
icon.vertex = true;
icon.geometry.relative = true;
icon.geometry.offset = new mxPoint(10, 10);
bg2.insert(icon);
var text1 = new mxCell('Analytics Backend', new mxGeometry(0, 0.5, 130, 20), 'text;fontSize=13;fontColor=#444444;align=left;verticalAlign=middle;');
text1.vertex = true;
text1.geometry.relative = true;
text1.geometry.offset = new mxPoint(60, -20);
bg2.insert(text1);
var text2 = new mxCell('Compute Engine', new mxGeometry(0, 0.5, 130, 20), 'text;fontSize=13;fontColor=#808080;align=left;verticalAlign=middle;');
text2.vertex = true;
text2.geometry.relative = true;
text2.geometry.offset = new mxPoint(60, 0);
bg2.insert(text2);
return sb.createVertexTemplateFromCells([bg1, bg2], bg1.geometry.width, bg1.geometry.height * 2, 'Product Card');
}),
this.addEntry(dt + 'expanded product', function()
{
var bg = new mxCell('', new mxGeometry(0, 0, 190, 80), n1);
bg.vertex = true;
var icon = new mxCell('', new mxGeometry(0, 0, s * 129, s * 115), n + 'compute_engine;fillColor=#4387FD;gradientColor=#4683EA;strokeColor=none;');
icon.vertex = true;
icon.geometry.relative = true;
icon.geometry.offset = new mxPoint(10, 10);
bg.insert(icon);
var text1 = new mxCell('Batch Processing', new mxGeometry(0, 0, 130, 20), 'text;fontSize=13;fontColor=#444444;align=left;verticalAlign=middle;');
text1.vertex = true;
text1.geometry.relative = true;
text1.geometry.offset = new mxPoint(60, 8);
bg.insert(text1);
var text2 = new mxCell('Compute Engine', new mxGeometry(0, 0, 130, 20), 'text;fontSize=13;fontColor=#808080;align=left;verticalAlign=middle;');
text2.vertex = true;
text2.geometry.relative = true;
text2.geometry.offset = new mxPoint(60, 28);
bg.insert(text2);
var part = new mxCell('', new mxGeometry(0, 0, 130, 10), 'shape=line;strokeColor=#dddddd;');
part.vertex = true;
part.geometry.relative = true;
part.geometry.offset = new mxPoint(60, 48);
bg.insert(part);
var text3 = new mxCell('Multiple Instances', new mxGeometry(0, 0, 130, 20), 'text;fontSize=12;fontColor=#444444;align=left;verticalAlign=middle;');
text3.vertex = true;
text3.geometry.relative = true;
text3.geometry.offset = new mxPoint(60, 58);
bg.insert(text3);
return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'Expanded Product Card');
}),
this.addEntry(dt + 'expanded product', function()
{
var bg = new mxCell('', new mxGeometry(0, 0, 150, 100), n1);
bg.vertex = true;
var icon1 = new mxCell('', new mxGeometry(0, 0, s * 65, s * 58), n + 'compute_engine;fillColor=#757575;gradientColor=none;strokeColor=none;');
icon1.vertex = true;
icon1.geometry.relative = true;
icon1.geometry.offset = new mxPoint(10, 10);
bg.insert(icon1);
var text1 = new mxCell('Compute Engine', new mxGeometry(0, 0, 110, 20), 'text;fontSize=13;fontColor=#444444;align=left;verticalAlign=middle;');
text1.vertex = true;
text1.geometry.relative = true;
text1.geometry.offset = new mxPoint(40, 8);
bg.insert(text1);
var part = new mxCell('', new mxGeometry(0, 0, 110, 10), 'shape=line;strokeColor=#dddddd;');
part.vertex = true;
part.geometry.relative = true;
part.geometry.offset = new mxPoint(40, 28);
bg.insert(part);
var text2 = new mxCell('10GB PD', new mxGeometry(0, 0, 110, 20), 'text;fontSize=12;fontColor=#888888;align=left;verticalAlign=middle;');
text2.vertex = true;
text2.geometry.relative = true;
text2.geometry.offset = new mxPoint(40, 38);
bg.insert(text2);
var icon2 = new mxCell('', new mxGeometry(0, 0, 17, 17), 'dashed=0;html=1;shape=mxgraph.gcp.product_cards.standard_machine;fillColor=#757575;gradientColor=none;strokeColor=none;');
icon2.vertex = true;
icon2.geometry.relative = true;
icon2.geometry.offset = new mxPoint(30, 60);
bg.insert(icon2);
var icon3 = new mxCell('', new mxGeometry(0, 0, 17, 17), 'dashed=0;html=1;shape=mxgraph.gcp.product_cards.disk;fillColor=#757575;gradientColor=none;strokeColor=none;');
icon3.vertex = true;
icon3.geometry.relative = true;
icon3.geometry.offset = new mxPoint(70, 60);
bg.insert(icon3);
var icon4 = new mxCell('', new mxGeometry(0, 0, 17, 17), 'dashed=0;html=1;shape=mxgraph.gcp.product_cards.close;fillColor=#757575;gradientColor=none;strokeColor=none;');
icon4.vertex = true;
icon4.geometry.relative = true;
icon4.geometry.offset = new mxPoint(110, 60);
bg.insert(icon4);
var icon5 = new mxCell('4', new mxGeometry(0, 0, 14, 14), 'dashed=0;html=1;ellipse;fillColor=#3979F1;gradientColor=none;strokeColor=none;fontColor=#FFFFFF;fontSize=10;verticalAlign=middle;spacing=0;spacingBottom=1;');
icon5.vertex = true;
icon5.geometry.relative = true;
icon5.geometry.offset = new mxPoint(22, 68);
bg.insert(icon5);
var icon6 = new mxCell('2', new mxGeometry(0, 0, 14, 14), 'dashed=0;html=1;ellipse;fillColor=#3979F1;gradientColor=none;strokeColor=none;fontColor=#FFFFFF;fontSize=10;verticalAlign=middle;spacing=0;spacingBottom=1;');
icon6.vertex = true;
icon6.geometry.relative = true;
icon6.geometry.offset = new mxPoint(42, 68);
bg.insert(icon6);
var icon7 = new mxCell('1', new mxGeometry(0, 0, 14, 14), 'dashed=0;html=1;ellipse;fillColor=#3979F1;gradientColor=none;strokeColor=none;fontColor=#FFFFFF;fontSize=10;verticalAlign=middle;spacing=0;spacingBottom=1;');
icon7.vertex = true;
icon7.geometry.relative = true;
icon7.geometry.offset = new mxPoint(82, 68);
bg.insert(icon7);
return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'Expanded Product Card');
}),
this.addEntry(dt + 'service', function()
{
var bg = new mxCell('', new mxGeometry(0, 0, 110, 50), n1);
bg.vertex = true;
var icon = new mxCell('', new mxGeometry(0, 0, s * 129, s * 115), n + 'compute_engine;fillColor=#757575;gradientColor=none;strokeColor=none;');
icon.vertex = true;
icon.geometry.relative = true;
icon.geometry.offset = new mxPoint(10, 8);
bg.insert(icon);
var text1 = new mxCell('Local\nCompute', new mxGeometry(0, 0, 60, 50), 'text;fontSize=13;fontColor=#808080;align=left;verticalAlign=middle;');
text1.vertex = true;
text1.geometry.relative = true;
text1.geometry.offset = new mxPoint(50, 0);
bg.insert(text1);
return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'Service Card');
})
];
this.addPalette('gcpCards', 'GCP / Cards', false, mxUtils.bind(this, function(content)
{
for (var i = 0; i < fns.length; i++)
{
content.appendChild(fns[i](content));
}
}));
};
})();

View file

@ -30,7 +30,7 @@
/**
*
*/
Sidebar.prototype.gcp = ['Big Data', 'Compute', 'Developer Tools', 'Extras', 'Identity and Security', 'Machine Learning', 'Management Tools', 'Networking', 'Storage Databases'];
Sidebar.prototype.gcp = ['Cards', 'Big Data', 'Compute', 'Developer Tools', 'Extras', 'Identity and Security', 'Machine Learning', 'Management Tools', 'Networking', 'Storage Databases'];
/**
*
*/
@ -728,11 +728,18 @@
}
for (var i = 0; i < gcp.length; i++)
{
if (gcp[i].toLowerCase() === 'cards')
{
this.addGoogleCloudPlatformCardsPalette();
}
else
{
this.addStencilPalette('gcp' + gcp[i], 'GCP / ' + gcp[i],
dir + '/gcp/' + gcp[i].toLowerCase().replace(/ /g, '_') + '.xml',
';html=1;fillColor=#4387FD;gradientColor=#4683EA;strokeColor=none;verticalLabelPosition=bottom;verticalAlign=top;align=center;');
}
}
for (var i = 0; i < rack.length; i++)
{

View file

@ -184,7 +184,7 @@ f)+"\n"+t+"}":"{"+x.join(",")+"}";f=t;return l}}"function"!==typeof Date.prototy
e=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,f,g,h={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},k;"function"!==typeof JSON.stringify&&(JSON.stringify=function(a,b,d){var e;g=f="";if("number"===typeof d)for(e=0;e<d;e+=1)g+=" ";else"string"===typeof d&&(g=d);if((k=b)&&"function"!==typeof b&&("object"!==typeof b||"number"!==typeof b.length))throw Error("JSON.stringify");return c("",{"":a})});
"function"!==typeof JSON.parse&&(JSON.parse=function(a,b){function c(a,d){var e,f,g=a[d];if(g&&"object"===typeof g)for(e in g)Object.prototype.hasOwnProperty.call(g,e)&&(f=c(g,e),void 0!==f?g[e]=f:delete g[e]);return b.call(a,d,g)}var e;a=""+a;d.lastIndex=0;d.test(a)&&(a=a.replace(d,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return e=eval("("+a+")"),"function"===typeof b?c({"":e},""):e;throw new SyntaxError("JSON.parse");})})();var mxBasePath="https://www.draw.io/mxgraph/",mxLoadStylesheets=mxLoadResources=!1,mxLanguage="en";window.urlParams=window.urlParams||{};window.MAX_REQUEST_SIZE=window.MAX_REQUEST_SIZE||10485760;window.MAX_AREA=window.MAX_AREA||225E6;window.EXPORT_URL=window.EXPORT_URL||"/export";window.SAVE_URL=window.SAVE_URL||"/save";window.OPEN_URL=window.OPEN_URL||"/open";window.RESOURCES_PATH=window.RESOURCES_PATH||"resources";window.RESOURCE_BASE=window.RESOURCE_BASE||window.RESOURCES_PATH+"/grapheditor";window.STENCIL_PATH=window.STENCIL_PATH||"stencils";window.IMAGE_PATH=window.IMAGE_PATH||"images";
window.STYLE_PATH=window.STYLE_PATH||"styles";window.CSS_PATH=window.CSS_PATH||"styles";window.OPEN_FORM=window.OPEN_FORM||"open.html";window.mxBasePath=window.mxBasePath||"../../../src";window.mxLanguage=window.mxLanguage||urlParams.lang;window.mxLanguages=window.mxLanguages||["de"];var mxClient={VERSION:"6.3.6",IS_IE:0<=navigator.userAgent.indexOf("MSIE"),IS_IE6:0<=navigator.userAgent.indexOf("MSIE 6"),IS_IE11:!!navigator.userAgent.match(/Trident\/7\./),IS_EDGE:!!navigator.userAgent.match(/Edge\//),IS_QUIRKS:0<=navigator.userAgent.indexOf("MSIE")&&(null==document.documentMode||5==document.documentMode),IS_EM:"spellcheck"in document.createElement("textarea")&&8==document.documentMode,VML_PREFIX:"v",OFFICE_PREFIX:"o",IS_NS:0<=navigator.userAgent.indexOf("Mozilla/")&&0>navigator.userAgent.indexOf("MSIE")&&
window.STYLE_PATH=window.STYLE_PATH||"styles";window.CSS_PATH=window.CSS_PATH||"styles";window.OPEN_FORM=window.OPEN_FORM||"open.html";window.mxBasePath=window.mxBasePath||"../../../src";window.mxLanguage=window.mxLanguage||urlParams.lang;window.mxLanguages=window.mxLanguages||["de"];var mxClient={VERSION:"6.4.1",IS_IE:0<=navigator.userAgent.indexOf("MSIE"),IS_IE6:0<=navigator.userAgent.indexOf("MSIE 6"),IS_IE11:!!navigator.userAgent.match(/Trident\/7\./),IS_EDGE:!!navigator.userAgent.match(/Edge\//),IS_QUIRKS:0<=navigator.userAgent.indexOf("MSIE")&&(null==document.documentMode||5==document.documentMode),IS_EM:"spellcheck"in document.createElement("textarea")&&8==document.documentMode,VML_PREFIX:"v",OFFICE_PREFIX:"o",IS_NS:0<=navigator.userAgent.indexOf("Mozilla/")&&0>navigator.userAgent.indexOf("MSIE")&&
0>navigator.userAgent.indexOf("Edge/"),IS_OP:0<=navigator.userAgent.indexOf("Opera/")||0<=navigator.userAgent.indexOf("OPR/"),IS_OT:0<=navigator.userAgent.indexOf("Presto/")&&0>navigator.userAgent.indexOf("Presto/2.4.")&&0>navigator.userAgent.indexOf("Presto/2.3.")&&0>navigator.userAgent.indexOf("Presto/2.2.")&&0>navigator.userAgent.indexOf("Presto/2.1.")&&0>navigator.userAgent.indexOf("Presto/2.0.")&&0>navigator.userAgent.indexOf("Presto/1."),IS_SF:0<=navigator.userAgent.indexOf("AppleWebKit/")&&
0>navigator.userAgent.indexOf("Chrome/")&&0>navigator.userAgent.indexOf("Edge/"),IS_IOS:navigator.userAgent.match(/(iPad|iPhone|iPod)/g)?!0:!1,IS_GC:0<=navigator.userAgent.indexOf("Chrome/")&&0>navigator.userAgent.indexOf("Edge/"),IS_CHROMEAPP:null!=window.chrome&&null!=chrome.app&&null!=chrome.app.runtime,IS_FF:0<=navigator.userAgent.indexOf("Firefox/"),IS_MT:0<=navigator.userAgent.indexOf("Firefox/")&&0>navigator.userAgent.indexOf("Firefox/1.")&&0>navigator.userAgent.indexOf("Firefox/2.")||0<=navigator.userAgent.indexOf("Iceweasel/")&&
0>navigator.userAgent.indexOf("Iceweasel/1.")&&0>navigator.userAgent.indexOf("Iceweasel/2.")||0<=navigator.userAgent.indexOf("SeaMonkey/")&&0>navigator.userAgent.indexOf("SeaMonkey/1.")||0<=navigator.userAgent.indexOf("Iceape/")&&0>navigator.userAgent.indexOf("Iceape/1."),IS_SVG:0<=navigator.userAgent.indexOf("Firefox/")||0<=navigator.userAgent.indexOf("Iceweasel/")||0<=navigator.userAgent.indexOf("Seamonkey/")||0<=navigator.userAgent.indexOf("Iceape/")||0<=navigator.userAgent.indexOf("Galeon/")||

View file

@ -3730,7 +3730,9 @@ StyleFormatPanel.prototype.addStroke = function(container)
{
if (ss.style.shape == 'connector' || ss.style.shape == 'flexArrow')
{
this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.NONE, 0], 'geIcon geSprite geSprite-noarrow', null, false).setAttribute('title', mxResources.get('none'));
var item = this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.NONE, 0], 'geIcon', null, false);
item.setAttribute('title', mxResources.get('none'));
item.firstChild.firstChild.innerHTML = '<font style="font-size:10px;">' + mxUtils.htmlEntities(mxResources.get('none')) + '</font>';
if (ss.style.shape == 'connector')
{
@ -3776,7 +3778,9 @@ StyleFormatPanel.prototype.addStroke = function(container)
{
if (ss.style.shape == 'connector' || ss.style.shape == 'flexArrow')
{
this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.NONE, 0], 'geIcon geSprite geSprite-noarrow', null, false).setAttribute('title', mxResources.get('none'));
var item = this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.NONE, 0], 'geIcon', null, false);
item.setAttribute('title', mxResources.get('none'));
item.firstChild.firstChild.innerHTML = '<font style="font-size:10px;">' + mxUtils.htmlEntities(mxResources.get('none')) + '</font>';
if (ss.style.shape == 'connector')
{
@ -4077,6 +4081,16 @@ StyleFormatPanel.prototype.addStroke = function(container)
markerDiv.className = ui.getCssClassForMarker(prefix, ss.style.shape, marker, fill);
if (markerDiv.className == 'geSprite geSprite-noarrow')
{
markerDiv.innerHTML = mxUtils.htmlEntities(mxResources.get('none'));
markerDiv.style.backgroundImage = 'none';
markerDiv.style.verticalAlign = 'top';
markerDiv.style.marginTop = '5px';
markerDiv.style.fontSize = '10px';
markerDiv.nextSibling.style.marginTop = '0px';
}
return markerDiv;
};

View file

@ -184,7 +184,7 @@ f)+"\n"+t+"}":"{"+x.join(",")+"}";f=t;return l}}"function"!==typeof Date.prototy
e=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,f,g,h={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},k;"function"!==typeof JSON.stringify&&(JSON.stringify=function(a,b,d){var e;g=f="";if("number"===typeof d)for(e=0;e<d;e+=1)g+=" ";else"string"===typeof d&&(g=d);if((k=b)&&"function"!==typeof b&&("object"!==typeof b||"number"!==typeof b.length))throw Error("JSON.stringify");return c("",{"":a})});
"function"!==typeof JSON.parse&&(JSON.parse=function(a,b){function c(a,d){var e,f,g=a[d];if(g&&"object"===typeof g)for(e in g)Object.prototype.hasOwnProperty.call(g,e)&&(f=c(g,e),void 0!==f?g[e]=f:delete g[e]);return b.call(a,d,g)}var e;a=""+a;d.lastIndex=0;d.test(a)&&(a=a.replace(d,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return e=eval("("+a+")"),"function"===typeof b?c({"":e},""):e;throw new SyntaxError("JSON.parse");})})();var mxBasePath="https://www.draw.io/mxgraph/",mxLoadStylesheets=mxLoadResources=!1,mxLanguage="en";window.urlParams=window.urlParams||{};window.MAX_REQUEST_SIZE=window.MAX_REQUEST_SIZE||10485760;window.MAX_AREA=window.MAX_AREA||225E6;window.EXPORT_URL=window.EXPORT_URL||"/export";window.SAVE_URL=window.SAVE_URL||"/save";window.OPEN_URL=window.OPEN_URL||"/open";window.RESOURCES_PATH=window.RESOURCES_PATH||"resources";window.RESOURCE_BASE=window.RESOURCE_BASE||window.RESOURCES_PATH+"/grapheditor";window.STENCIL_PATH=window.STENCIL_PATH||"stencils";window.IMAGE_PATH=window.IMAGE_PATH||"images";
window.STYLE_PATH=window.STYLE_PATH||"styles";window.CSS_PATH=window.CSS_PATH||"styles";window.OPEN_FORM=window.OPEN_FORM||"open.html";window.mxBasePath=window.mxBasePath||"../../../src";window.mxLanguage=window.mxLanguage||urlParams.lang;window.mxLanguages=window.mxLanguages||["de"];var mxClient={VERSION:"6.3.6",IS_IE:0<=navigator.userAgent.indexOf("MSIE"),IS_IE6:0<=navigator.userAgent.indexOf("MSIE 6"),IS_IE11:!!navigator.userAgent.match(/Trident\/7\./),IS_EDGE:!!navigator.userAgent.match(/Edge\//),IS_QUIRKS:0<=navigator.userAgent.indexOf("MSIE")&&(null==document.documentMode||5==document.documentMode),IS_EM:"spellcheck"in document.createElement("textarea")&&8==document.documentMode,VML_PREFIX:"v",OFFICE_PREFIX:"o",IS_NS:0<=navigator.userAgent.indexOf("Mozilla/")&&0>navigator.userAgent.indexOf("MSIE")&&
window.STYLE_PATH=window.STYLE_PATH||"styles";window.CSS_PATH=window.CSS_PATH||"styles";window.OPEN_FORM=window.OPEN_FORM||"open.html";window.mxBasePath=window.mxBasePath||"../../../src";window.mxLanguage=window.mxLanguage||urlParams.lang;window.mxLanguages=window.mxLanguages||["de"];var mxClient={VERSION:"6.4.1",IS_IE:0<=navigator.userAgent.indexOf("MSIE"),IS_IE6:0<=navigator.userAgent.indexOf("MSIE 6"),IS_IE11:!!navigator.userAgent.match(/Trident\/7\./),IS_EDGE:!!navigator.userAgent.match(/Edge\//),IS_QUIRKS:0<=navigator.userAgent.indexOf("MSIE")&&(null==document.documentMode||5==document.documentMode),IS_EM:"spellcheck"in document.createElement("textarea")&&8==document.documentMode,VML_PREFIX:"v",OFFICE_PREFIX:"o",IS_NS:0<=navigator.userAgent.indexOf("Mozilla/")&&0>navigator.userAgent.indexOf("MSIE")&&
0>navigator.userAgent.indexOf("Edge/"),IS_OP:0<=navigator.userAgent.indexOf("Opera/")||0<=navigator.userAgent.indexOf("OPR/"),IS_OT:0<=navigator.userAgent.indexOf("Presto/")&&0>navigator.userAgent.indexOf("Presto/2.4.")&&0>navigator.userAgent.indexOf("Presto/2.3.")&&0>navigator.userAgent.indexOf("Presto/2.2.")&&0>navigator.userAgent.indexOf("Presto/2.1.")&&0>navigator.userAgent.indexOf("Presto/2.0.")&&0>navigator.userAgent.indexOf("Presto/1."),IS_SF:0<=navigator.userAgent.indexOf("AppleWebKit/")&&
0>navigator.userAgent.indexOf("Chrome/")&&0>navigator.userAgent.indexOf("Edge/"),IS_IOS:navigator.userAgent.match(/(iPad|iPhone|iPod)/g)?!0:!1,IS_GC:0<=navigator.userAgent.indexOf("Chrome/")&&0>navigator.userAgent.indexOf("Edge/"),IS_CHROMEAPP:null!=window.chrome&&null!=chrome.app&&null!=chrome.app.runtime,IS_FF:0<=navigator.userAgent.indexOf("Firefox/"),IS_MT:0<=navigator.userAgent.indexOf("Firefox/")&&0>navigator.userAgent.indexOf("Firefox/1.")&&0>navigator.userAgent.indexOf("Firefox/2.")||0<=navigator.userAgent.indexOf("Iceweasel/")&&
0>navigator.userAgent.indexOf("Iceweasel/1.")&&0>navigator.userAgent.indexOf("Iceweasel/2.")||0<=navigator.userAgent.indexOf("SeaMonkey/")&&0>navigator.userAgent.indexOf("SeaMonkey/1.")||0<=navigator.userAgent.indexOf("Iceape/")&&0>navigator.userAgent.indexOf("Iceape/1."),IS_SVG:0<=navigator.userAgent.indexOf("Firefox/")||0<=navigator.userAgent.indexOf("Iceweasel/")||0<=navigator.userAgent.indexOf("Seamonkey/")||0<=navigator.userAgent.indexOf("Iceape/")||0<=navigator.userAgent.indexOf("Galeon/")||

View file

@ -423,7 +423,7 @@ noFiles=Keine Dateien
noFileSelected=Keine Datei ausgewählt
noLibraries=Keine Bibliotheken gefunden
noMoreResults=Keine Weiteren Resultate
none=Keine
none=Ohne
noOtherViewers=Keine weiteren Betrachter
noPlugins=Keine Plugins
noPreview=Keine Vorschau

View file

@ -168509,6 +168509,112 @@
</foreground>
</shape>
</shapes>
<shapes name="mxgraph.gcp.product_cards">
<shape aspect="variable" h="122.19" name="Close" strokewidth="inherit" w="121.43">
<connections/>
<foreground>
<path>
<move x="74.62" y="122.19"/>
<line x="74.62" y="109.96"/>
<line x="100.43" y="109.96"/>
<line x="32.44" y="41.96"/>
<line x="41.36" y="32.88"/>
<line x="109.06" y="101.18"/>
<line x="109.06" y="75.88"/>
<line x="121.43" y="75.88"/>
<line x="121.43" y="122.19"/>
<close/>
<move x="60.26" y="122.19"/>
<line x="11.61" y="122.19"/>
<curve x1="6.31" x2="0" x3="0" y1="122.19" y2="117.2" y3="111.44"/>
<line x="0" y="12.8"/>
<curve x1="0" x2="4.61" x3="13.39" y1="7.15" y2="0" y3="0"/>
<line x="109.29" y="0"/>
<curve x1="114.53" x2="121.43" x3="121.43" y1="0" y2="5.14" y3="11.46"/>
<line x="121.43" y="60.11"/>
<line x="109.06" y="60.11"/>
<line x="109.06" y="13.4"/>
<line x="12.05" y="13.4"/>
<line x="12.05" y="109.96"/>
<line x="60.26" y="109.96"/>
<close/>
</path>
<fillstroke/>
</foreground>
</shape>
<shape aspect="variable" h="98.49" name="Disk" strokewidth="inherit" w="121.9">
<connections/>
<foreground>
<path>
<move x="11.64" y="18.28"/>
<line x="24.19" y="18.28"/>
<line x="24.19" y="6.02"/>
<line x="11.64" y="6.02"/>
<close/>
<move x="0.0" y="24.01"/>
<line x="0.0" y="0.0"/>
<line x="121.9" y="0.0"/>
<line x="121.9" y="24.01"/>
<close/>
<move x="11.64" y="55.6"/>
<line x="24.19" y="55.6"/>
<line x="24.19" y="42.71"/>
<line x="11.64" y="42.71"/>
<close/>
<move x="0.0" y="61.18"/>
<line x="0.0" y="37.59"/>
<line x="121.9" y="37.59"/>
<line x="121.9" y="61.18"/>
<close/>
<move x="11.64" y="93.04"/>
<line x="24.19" y="93.04"/>
<line x="24.19" y="79.44"/>
<line x="11.64" y="79.44"/>
<close/>
<move x="0.0" y="98.49"/>
<line x="0.0" y="73.77"/>
<line x="121.9" y="73.77"/>
<line x="121.9" y="98.49"/>
<close/>
</path>
<fillstroke/>
</foreground>
</shape>
<shape aspect="variable" h="123.25" name="Standard Machine" strokewidth="inherit" w="122.48">
<connections/>
<foreground>
<path>
<move x="87.91" y="96.71"/>
<line x="102.86" y="96.71"/>
<line x="102.86" y="26.7"/>
<line x="74.15" y="26.7"/>
<line x="74.15" y="41.73"/>
<line x="87.91" y="41.73"/>
<close/>
<move x="19.32" y="96.71"/>
<line x="34.79" y="96.71"/>
<line x="34.79" y="41.73"/>
<line x="46.4" y="41.73"/>
<line x="46.4" y="96.71"/>
<line x="61.72" y="96.71"/>
<line x="61.72" y="42.48"/>
<curve x1="61.72" x2="56.68" x3="49.22" y1="33.67" y2="26.7" y3="26.7"/>
<line x="19.32" y="26.7"/>
<close/>
<move x="11.92" y="123.25"/>
<curve x1="5.49" x2="0.0" x3="0.0" y1="123.25" y2="116.63" y3="109.42"/>
<line x="0.0" y="11.66"/>
<curve x1="0.0" x2="7.14" x3="13.14" y1="6.98" y2="0.0" y3="0.0"/>
<line x="109.64" y="0.0"/>
<curve x1="115.46" x2="122.48" x3="122.48" y1="0.0" y2="5.16" y3="13.92"/>
<line x="122.48" y="111.66"/>
<curve x1="122.48" x2="116.9" x3="110.6" y1="117.33" y2="123.25" y3="123.25"/>
<close/>
</path>
<fillstroke/>
</foreground>
</shape>
</shapes>
<shapes name="mxgraph.gcp.storage_databases">
<shape aspect="variable" h="115.01" name="Cloud Bigtable" strokewidth="inherit" w="129.03">
<connections/>

View file

@ -0,0 +1,106 @@
<shapes name="mxgraph.gcp.product_cards">
<shape aspect="variable" h="122.19" name="Close" strokewidth="inherit" w="121.43">
<connections/>
<foreground>
<path>
<move x="74.62" y="122.19"/>
<line x="74.62" y="109.96"/>
<line x="100.43" y="109.96"/>
<line x="32.44" y="41.96"/>
<line x="41.36" y="32.88"/>
<line x="109.06" y="101.18"/>
<line x="109.06" y="75.88"/>
<line x="121.43" y="75.88"/>
<line x="121.43" y="122.19"/>
<close/>
<move x="60.26" y="122.19"/>
<line x="11.61" y="122.19"/>
<curve x1="6.31" x2="0" x3="0" y1="122.19" y2="117.2" y3="111.44"/>
<line x="0" y="12.8"/>
<curve x1="0" x2="4.61" x3="13.39" y1="7.15" y2="0" y3="0"/>
<line x="109.29" y="0"/>
<curve x1="114.53" x2="121.43" x3="121.43" y1="0" y2="5.14" y3="11.46"/>
<line x="121.43" y="60.11"/>
<line x="109.06" y="60.11"/>
<line x="109.06" y="13.4"/>
<line x="12.05" y="13.4"/>
<line x="12.05" y="109.96"/>
<line x="60.26" y="109.96"/>
<close/>
</path>
<fillstroke/>
</foreground>
</shape>
<shape aspect="variable" h="98.49" name="Disk" strokewidth="inherit" w="121.9">
<connections/>
<foreground>
<path>
<move x="11.64" y="18.28"/>
<line x="24.19" y="18.28"/>
<line x="24.19" y="6.02"/>
<line x="11.64" y="6.02"/>
<close/>
<move x="0.0" y="24.01"/>
<line x="0.0" y="0.0"/>
<line x="121.9" y="0.0"/>
<line x="121.9" y="24.01"/>
<close/>
<move x="11.64" y="55.6"/>
<line x="24.19" y="55.6"/>
<line x="24.19" y="42.71"/>
<line x="11.64" y="42.71"/>
<close/>
<move x="0.0" y="61.18"/>
<line x="0.0" y="37.59"/>
<line x="121.9" y="37.59"/>
<line x="121.9" y="61.18"/>
<close/>
<move x="11.64" y="93.04"/>
<line x="24.19" y="93.04"/>
<line x="24.19" y="79.44"/>
<line x="11.64" y="79.44"/>
<close/>
<move x="0.0" y="98.49"/>
<line x="0.0" y="73.77"/>
<line x="121.9" y="73.77"/>
<line x="121.9" y="98.49"/>
<close/>
</path>
<fillstroke/>
</foreground>
</shape>
<shape aspect="variable" h="123.25" name="Standard Machine" strokewidth="inherit" w="122.48">
<connections/>
<foreground>
<path>
<move x="87.91" y="96.71"/>
<line x="102.86" y="96.71"/>
<line x="102.86" y="26.7"/>
<line x="74.15" y="26.7"/>
<line x="74.15" y="41.73"/>
<line x="87.91" y="41.73"/>
<close/>
<move x="19.32" y="96.71"/>
<line x="34.79" y="96.71"/>
<line x="34.79" y="41.73"/>
<line x="46.4" y="41.73"/>
<line x="46.4" y="96.71"/>
<line x="61.72" y="96.71"/>
<line x="61.72" y="42.48"/>
<curve x1="61.72" x2="56.68" x3="49.22" y1="33.67" y2="26.7" y3="26.7"/>
<line x="19.32" y="26.7"/>
<close/>
<move x="11.92" y="123.25"/>
<curve x1="5.49" x2="0.0" x3="0.0" y1="123.25" y2="116.63" y3="109.42"/>
<line x="0.0" y="11.66"/>
<curve x1="0.0" x2="7.14" x3="13.14" y1="6.98" y2="0.0" y3="0.0"/>
<line x="109.64" y="0.0"/>
<curve x1="115.46" x2="122.48" x3="122.48" y1="0.0" y2="5.16" y3="13.92"/>
<line x="122.48" y="111.66"/>
<curve x1="122.48" x2="116.9" x3="110.6" y1="117.33" y2="123.25" y3="123.25"/>
<close/>
</path>
<fillstroke/>
</foreground>
</shape>
</shapes>