NAME
yEd::Document - pure perl API to easily create yEd-loadable Documents from scratch (using XML::LibXML)
VERSION
Version 1.00
DEPENDENCIES
INTENTION
This package is intended to offer a way to create yEd Documents from scratch using perl.
It is ment to help automating the task of creating graphical overviews of platforms, workflows, dependencies, ...
Since it doesn't support all the features of a yEd created Document you can only create Documents, loading Documents into the package is not supported, yet.
SUPPORTED FEATURES
This package and all available features have been developed and tested for yEd version 3.13.
If you find it doesn't work on another version or a specific platform, please let me know.
Object features are supported as described at
and its subclasses.
The Document itself supports basic templating, layers and id management.
You can also use relative coords for positioning your entities and use this feature for basic grouping.
All entities are property based and can also be selected by properties.
SYNOPSIS
This package provides a pure object oriented implementation, so only use functions and properties of yEd::Document and the other types in the context of a blessed instance.
Minimal example (creating an empty, yEd loadable Document):
use yEd::Document;
# create the document
$d = yEd::Document->new();
# build the document
$xmlstring = $d->buildDocument();
# or
$d->buildDocument('/mypath/mydocument');
Example of using relative entities and layers (ready to run):
use strict;
use yEd::Document;
my $d = yEd::Document->new();
# play around with these values and note that the edge will always keep its right angles :)
my $sx = -15; # -0.5 * default width
my $sy = 15; # 0.5 * default height -> lower left corner of source
my $tx = 15; # 0.5 * default width
my $ty = 15; # 0.5 * default height -> lower right corner of target
my $distance = 250;
# place the absolute "root" node
my $grouproot = $d->addNewNode('ShapeNode', 'x' => 1000, 'y' => 1000);
# place another node $distance units to its right (or left if negative)
my $n = $d->addNewNode('ShapeNode', 'x' => $distance, 'y' => 0, 'relative' => $grouproot);
# place an edge on both which will go 50 units down, then $distance units (modified by anchor offsets) right/left (and then up again to connect to its target)
my $e = $d->addNewEdge('PolyLineEdge', $grouproot, $n, 'relativeWaypoints' => 1, 'sx' => $sx, 'sy' => $sy, 'tx' => $tx, 'ty' => $ty);
$e->waypoints([0,50],[$distance - $sx + $tx,0]);
# place a circle on top of $grouproot to make the "group movement" visible in yEd
my $c = $d->addNewNode('ShapeNode','shape' => 'ellipse', 'layer' => 1, 'x' => 1000, 'y' => 1000);
$d->addNewEdge('PolyLineEdge', $n, $c, 'tArrow' => 'standard', 'sArrow' => 'standard');
# you can now move the whole "group" by modifying $grouproot's x and y values (uncomment it and watch the difference in yEd)
#$grouproot->setProperties('x' => 778.88, 'y' => 900);
$d->buildDocument('test');
Example of using templating (ready to run):
use strict;
use yEd::Document;
my $d = yEd::Document->new();
# preparing the templates
$d->addNewLabelTemplate('headline', 'NodeLabel', 'The house of Santa Claus', 'positionModell' => 'sandwich-n', 'fontSize' => 20);
$d->addNewNodeTemplate('housenode', 'ShapeNode', 'shape' => 'ellipse', 'fillColor' => '#0000ff');
my $wall = $d->addNewEdgeTemplate('wall', 'GenericEdge', 'lineWidth' => 5, 'fillColor' => '#0000ff', 'tArrow' => 'standard');
$wall->addNewLabel('This', 'positionModell' => 'three_center-scentr', 'textColor' => '#005500', 'backgroundColor' => '#cccccc');
$d->addEdgeTemplate('roof', $wall, 'fillColor' => '#ff0000');
# adding the nodes
my $n = $d->addTemplateNode('housenode', 'y' => 300);
my $n1 = $d->addTemplateNode('housenode');
my $n2 = $d->addTemplateNode('housenode', 'x' => 300);
my $n3 = $d->addTemplateNode('housenode', 'x' => 300, 'y' => 300);
# adding a node that wasn't defined as a template
my $n4 = $d->addNewNode('ShapeNode', 'x' => 150, 'y' => -150, 'shape' => 'triangle', 'fillColor' => '#ff0000');
$n4->addLabel($d->getTemplateLabel('headline'));
# adding the edges
$d->addTemplateEdge('wall',$n,$n1);
($d->addTemplateEdge('wall',$n1,$n2)->labels())[0]->text('is');
($d->addTemplateEdge('wall',$n2,$n)->labels())[0]->text('the');
($d->addTemplateEdge('wall',$n,$n3)->labels())[0]->text('house');
($d->addTemplateEdge('wall',$n3,$n2)->labels())[0]->text('of');
($d->addTemplateEdge('roof',$n2,$n4)->labels())[0]->text('San-');
($d->addTemplateEdge('roof',$n4,$n1)->labels())[0]->text('ta');
($d->addTemplateEdge('wall',$n1,$n3)->labels())[0]->text('Claus');
$d->buildDocument('santa_claus');
OBJECT IDENTIFIERS
All Nodes and Edges of a Document must have an unique ID.
If you only use the yEd::Document's addNew... functions and templating features you won't have to care for IDs.
But if you need to externally create Nodes or Edges from its classes you will have to provide the ID yourself.
In this case it is up to you to ensure unique values unless you obtain the IDs via yEd::Document's getFreeId function.
This automatically created IDs will always be positive integer values, but if you provide your own IDs you can use almost anything.
If you load and save a Document in yEd all IDs will be converted to yEd's syntax ('n0','n1',...,'e0','e1',...).
TEMPLATING
If you have to add many copies of the same modification of a Node, Edge or Label have a look at yEd::Document's template functions.
These offer the ability to save an object's configuration and return and/or add copies of it.
For Nodes and Edges added Labels will be copied along with the template.
For Nodes that are relative to other Nodes you may want to call 'relative(0)' or 'relative($newTarget)' on the copy (or provide it with the properties parameter).
For Edges all waypoints are copied along with the template, this may not be what you want unless the Edge's 'relativeWaypoints' property is set, consider calling 'clearWaypoints()' on the copy.
RELATIVE OBJECTS
A Node or Edge-waypoint by default will be absolute, this is its x and y values are directly applied to the drawing pane.
However you can change a Node to be relative to a given other Node by using the Node's 'relative' property. In this case x and y are values that are added to the other Node's absolute position to determine the Node's position. The other Node however may be relative to yet another Node, too. Just make sure you don't create dependency loops. ;)
If you manually cut the relation of two Nodes by setting 'relative(0)' on the dependend Node, the provided x and y value will not be changed but only interpreted as being absolute further on. If you want to cut the relation without changing the Node's current absolute position call '$n->x($n->absX)' and '$n->y($n->absY)' BEFORE the call to 'relative(0)'.
Note that the x and y coords of a Node refer to its upper left corner or rather the upper left corner of the Node's surrounding rectangle (e.g. for ellipse ShapeNodes). Consider this if you do any Node positioning math in your scripts.
Edges do have such a property, too, it is called 'relativeWaypoints' but is a boolean value in contrast to Node's property. If set to a true value any waypoints added to this Edge will be positioned relative to the previous waypoint. The first waypoint's position will be calculated relative to the Edge's anchor point on its source Node (sx,sy).
If you change from 'relativeWaypoints(1)' to 'relativeWaypoints(0)' there will be no conversion of the waypoint coords by default (same behavior as for Nodes).
Note that the source Node anchor point (sx,sy) is relative to the Node's center (sx = sy = 0). This is somehow inconsistent as the Node's coords don't describe its center. Consider this if you do any positioning math in your scripts. However for relative waypoints you will likely have the desired bahavior by default, since first waypoint is relative to the anchor point which's absolute position is automatically computed for you by this package.
Hint: If you create "groups" with the reative feature always build your group on top of a root node that spans the whole area of the group. If you need the Nodes to not be surrounded by a background root Node simply make it invisible (no fill color, no border). This way you can always ask your root Node for the width and height of the whole "group" if you need these values for calculation. :)
Note that this way of "grouping" has no effect in yEd, it does only exist within the code.
LAYERS
yEd Documents / Nodes do only support "virtual" layering which is saved to the graphml file by giving the Nodes a special order (first Node defined is drawn first).
This concept has been adopted by this package. The layer is described as a property of each Node, named 'layer' (Edges do not support layering, they will always be drawn on top the Nodes). Its default value is 0 which is the bottom layer. You can define the layer of a Node as any positive integer value, where a higher value is "more in front".
Within a single layer the drawing order of Nodes is undefined, if they overlap or need a special order because of other reasons use different layers.
Like with any other property you may obtain a list of all Nodes on a specified layer by using 'getNodesByProperties' (e.g. getNodesByProperties(layer => 3)).
SUBROUTINES/METHODS
new
Creates a new instance of yEd::Document and initializes it.
resetDocument
Resets (empties) and reinitializes this Document.
Previously registered templates will be kept.
buildDocument
Builds the Document and returns it as a string.
If a filename is provided (without the ending) it will additionally be written into filename.graphml .
getFreeId
Returns the next still free ID number, that can be used for creating new Nodes or Edges.
This is only required if you externally create new Nodes/Edges and you could also use own values as IDs (you will then have to ensure that all IDs are unique).
getFrontLayer
Returns the highest layer number that is set for any Node of this Document.
addNewLabelTemplate
Creates a template for Labels.
Must have parameters are: templatename (a string for accessing the template) , labeltype (Node- or EdgeLabel) , labeltext (the text for the Label)
Further parameters to set properties are optional (property => value, ...).
The template Label is returned as a reference, if you modify this reference all further copies of the template will be affected ! Copies created earlier will not be affected since they are as said copies.
addLabelTemplate
Creates a template for Labels.
Must have parameters are: templatename (a string for accessing the template) , label (a reference to a Label object)
Further parameters to set properties are optional (property => value, ...).
The source Label will not be changed, a copy of the Label will be used as template. If you want to modify the template after adding it use the returned reference to the copy.
getTemplateLabel
Creates a copy of a previously created Label template and returns it.
Must have parameters are: templatename (a string for accessing the template)
Further parameters to set properties are optional (property => value, ...).
In contrast to Nodes and Edges Label templates can not be added directly because the need to be added to a Node or Edge. So use this function to obtain a copy and do with it what ever you want.
addNewNodeTemplate
Creates a template for Nodes.
Must have parameters are: templatename (a string for accessing the template) , nodetype (Shape- or GenericNode)
Further parameters to set properties are optional (property => value, ...).
The template Node is returned as a reference, if you modify this reference all further copies of the template will be affected ! Copies created earlier will not be affected since they are as said copies.
addNodeTemplate
Creates a template for Nodes.
Must have parameters are: templatename (a string for accessing the template) , node (a reference to a Node object)
Further parameters to set properties are optional (property => value, ...).
The source Node will not be changed, a copy of the Node will be used as template. If you want to modify the template after adding it use the returned reference to the copy.
getTemplateNode
Creates a copy of a previously created Node template and returns it.
Must have parameters are: templatename (a string for accessing the template)
Further parameters to set properties are optional (property => value, ...).
addTemplateNode
Creates a copy of a previously created Node template, adds it to the Document and returns it.
Must have parameters are: templatename (a string for accessing the template)
Further parameters to set properties are optional (property => value, ...).
addNewEdgeTemplate
Creates a template for Edges.
Must have parameters are: templatename (a string for accessing the template) , edgetype (one of the supported Edge class names)
Further parameters to set properties are optional (property => value, ...).
The template Edge is returned as a reference, if you modify this reference all further copies of the template will be affected ! Copies created earlier will not be affected since they are as said copies.
addEdgeTemplate
Creates a template for Edges.
Must have parameters are: templatename (a string for accessing the template) , edge (a reference to an Edge object)
Further parameters to set properties are optional (property => value, ...).
The source Edge will not be changed, a copy of the Edge will be used as template. If you want to modify the template after adding it use the returned reference to the copy.
getTemplateEdge
Creates a copy of a previously created Edge template and returns it.
Must have parameters are: templatename (a string for accessing the template), source, target (the new source and target yEd::Node refs for the new Edge)
Further parameters to set properties are optional (property => value, ...).
addTemplateEdge
Creates a copy of a previously created Edge template, adds it to the Document and returns it.
Must have parameters are: templatename (a string for accessing the template), source, target (the new source and target yEd::Node refs for the new Edge)
Further parameters to set properties are optional (property => value, ...).
addNewNode
Creates a new Node, adds it and returns a reference to it.
Must have parameters are: nodetype (Shape- or GenericNode)
Further parameters to set properties are optional (property => value, ...).
addNode
Takes a yEd::Node as parameter and adds it to the Document.
getNodes
Returns an array of all Nodes of this Document.
getNodesByProperties
Takes arguments of the form 'property1 => value, property2 => value2, ...'.
Returns a list of all Nodes that matches the given filter.
hasNodeId
Takes a Node's id as parameter and returns true if it is present in this Document.
getNodeById
Takes an id as parameter and returns the Node with this id, if present in this Document.
removeNode
Takes a yEd::Node as parameter and tries to remove it from this document.
All connected Edges will be removed, too.
If there are Nodes relative to the given Node, they will also be removed (and their Edges and Nodes relative to these Nodes and so on, until all dependencies are resolved) unless the second (keepRelative) parameter is true. In this case the absolute x and y values are calculated and the relationship is cut, making the orphaned Nodes absolute.
Example: if you call removeNode($grouproot) in the "example of using relative entities and layers" (see SYNOPSIS), only the circle will remain. If you call removeNode($grouproot, 1) instead, only $grouproot and $e will be removed, making $n absolute at its last position.
addNewEdge
Creates a new Edge, adds it and returns a reference to it.
Must have parameters are: edgetype (one of the supported Edge class names), source, target (the source and target yEd::Node refs for the new Edge)
Further parameters to set properties are optional (property => value, ...).
addEdge
Takes a yEd::Edge as parameter and adds it to the Document.
getEdges
Returns an array of all Edges of this Document.
getEdgesByProperties
Takes arguments of the form 'property1 => value, property2 => value2, ...'.
Returns a list of all Edges that matches the given filter.
hasEdgeId
Takes an Edge's id as parameter and returns true if it is present in this Document.
getEdgeById
Takes an id as parameter and returns the Edge with this id, if present in this Document.
removeEdge
Takes a yEd::Edge as parameter and tries to remove it from this document.
AUTHOR
Heiko Finzel, <heikofinzel at googlemail.com>
BUGS
Please report any bugs or feature requests to bug-yed-document at rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=yEd-Document. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc yEd::Document
Also see perldoc of the other classes of this package.
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
AnnoCPAN: Annotated CPAN documentation
CPAN Ratings
Search CPAN
LICENSE AND COPYRIGHT
Copyright 2014 Heiko Finzel.
This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:
http://www.perlfoundation.org/artistic_license_2_0
Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.
If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.
This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.
This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.
Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.