NAME
yEd::Document - pure perl API to easily create yEd-loadable Documents from scratch (using XML::LibXML)
VERSION
Version 1.01
DEPENDENCIES
INTENTION
This package is intended to offer a way to create yEd Documents from scratch without having to deal with XML at all.
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 (see sections "BUGS" and/or "SUPPORT")).
Object features are supported as described at
and its subclasses.
The Document itself supports basic templating (section "TEMPLATING"), layers (section "LAYERS") and id management (section "OBJECT IDENTIFIERS").
You can also use relative coords for positioning your entities and use this feature for basic grouping (section "RELATIVE OBJECTS").
All entities are property based and can also be selected by properties (see yEd::PropertyBasedObject).
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 different ways to create a Node with Label (all have the same effect on the Document):
# the manual approach
my $n = yEd::Node::ShapeNode->new('myid1');
$n->x(50);
$n->y(150);
my $l = yEd::Label::NodeLabel->new('hello world');
$n->addLabel($l);
$doc->addNode($n);
# a slightly more user friendly approach
# provide the propertys with constructor and don't deal with IDs
my $n = yEd::Node::ShapeNode->new($doc->getFreeId(), 'x' => 50, 'y' => 150);
# directly add the label
my $l = $n->addNewLabel('hello world');
$doc->addNode($n);
# or do it all in two lines
my $n = $doc->addNewNode('ShapeNode', 'x' => 50, 'y' => 150);
my $l = $n->addNewLabel('hello world');
# or in one if you don't need the node ref (label ref is returned)
my $l = $doc->addNewNode('ShapeNode', 'x' => 50, 'y' => 150)->addNewLabel('hello world');
# or use templating if you need many copies of the same node
my $l = $doc->addNewNodeTemplate('mytemplate', 'ShapeNode', 'x' => 50, 'y' => 150)->addNewLabel('hello world');
my $n = $doc->addTemplateNode('mytemplate');
# you can use $n to modify the copy (e.g. coords), you can also provide new properties with the call to addTemplateNode()
# creating edges can be done in nearly the same ways
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 (each with a 'Template' in its name).
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.
Have a look at the 'Example of using templating' in the section "SYNOPSIS".
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 $n->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) (as is true for the target
anchor). This is somehow inconsistent as the Node's coords don't describe its center (you can obtain a Node's center by using its absCenter()
function). 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.
Have a look at the 'Example of using relative entities and layers' in the section "SYNOPSIS".
Tip: 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
).
Have a look at the 'Example of using relative entities and layers' in the section "SYNOPSIS".
SUBROUTINES/METHODS
new
Creates a new instance of yEd::Document and initializes it.
EXAMPLE
my $doc = yEd::Document->new();
resetDocument
Resets (empties) and reinitializes this Document.
Previously registered templates will be kept.
EXAMPLE
$doc->resetDocument();
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 .
EXAMPLE
my $xml = $doc->buildDocument();
my $xml = $doc->buildDocument('/path/to/mydoc');
getFreeId
Returns the next still free id
, 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).
EXAMPLE
my $myid = $doc->getFreeId();
getFrontLayer
Returns the highest layer
that is set for any Node of this Document.
EXAMPLE
my $front = $doc->getFrontLayer();
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 (property1 => value, property2 => value2, ...
).
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.
EXAMPLE
my $tmplLabel = $doc->addNewLabelTemplate('mytemplate', 'NodeLabel', 'hello world', 'alignment' => 'left');
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 (property1 => value, property2 => value2, ...
).
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.
EXAMPLE
my $tmplLabel = $doc->addLabelTemplate('mytemplate', $srcLabel, 'text' => 'foo');
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 (property1 => value, property2 => value2, ...
).
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 add it somewhere yourself.
EXAMPLE
my $label = $doc->getTemplateLabel('mytemplate', 'text' => 'bar');
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 (property1 => value, property2 => value2, ...
).
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.
EXAMPLE
my $tmplNode = $doc->addNewNodeTemplate('mytemplate', 'ShapeNode', 'width' => 300, 'height' => 200);
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 (property1 => value, property2 => value2, ...
).
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.
EXAMPLE
my $tmplNode = $doc->addNodeTemplate('mytemplate', $srcNode, 'width' => 300, 'height' => 200);
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 (property1 => value, property2 => value2, ...
).
EXAMPLE
my $node = $doc->getTemplateNode('mytemplate', 'x' => 50, 'y' => 200);
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 (property1 => value, property2 => value2, ...
).
EXAMPLE
my $node = $doc->addTemplateNode('mytemplate', 'x' => 50, 'y' => 200);
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 (property1 => value, property2 => value2, ...
).
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.
EXAMPLE
my $tmplEdge = $doc->addNewEdgeTemplate('mytemplate', 'ArcEdge', 'tArrow' => 'standard');
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 (property1 => value, property2 => value2, ...
).
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.
EXAMPLE
my $tmplEdge = $doc->addEdgeTemplate('mytemplate', $srcEdge, 'tArrow' => 'standard');
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 (property1 => value, property2 => value2, ...
).
EXAMPLE
my $edge = $doc->getTemplateEdge('mytemplate', $srcNode, $trgNode, 'tArrow' => 'standard');
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 (property1 => value, property2 => value2, ...
).
EXAMPLE
my $edge = $doc->addTemplateEdge('mytemplate', $srcNode, $trgNode, 'tArrow' => 'standard');
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 (property1 => value, property2 => value2, ...
).
EXAMPLE
my $node = $doc->addNewNode('ShapeNode', 'x' => 60, 'y' => 450);
addNode
Takes a yEd::Node as parameter and adds it to the Document.
EXAMPLE
$doc->addNode($node);
getNodes
Returns an array of all Nodes of this Document.
EXAMPLE
my @nodes = $doc->getNodes();
getNodesByProperties
Takes arguments of the form property1 => value, property2 => value2, ...
.
Returns a list of all Nodes that matches the given filter.
EXAMPLE
my @nodes = $doc->getNodesByProperties('width' => 300);
hasNodeId
Takes a Node's id
as parameter and returns true if it is present in this Document.
EXAMPLE
if ($doc->hasNodeId('myid1')) { ...
getNodeById
Takes an id
as parameter and returns the Node with this id
, if present in this Document.
EXAMPLE
my $node = $doc->getNodeById('myid1');
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
# in the "Example of using relative entities and layers" (see SYNOPSIS)
# only the cirlce will remain if you call
$d->removeNode($grouproot);
# only $grouproot and $e will be removed if you call
$d->removeNode($grouproot, 1);
# $n will then be 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 (property1 => value, property2 => value2, ...
).
EXAMPLE
my $edge = $doc->addNewEdge('ArcEdge', $srcNode, $trgNode, 'tArrow' => 'standard');
addEdge
Takes a yEd::Edge as parameter and adds it to the Document.
EXAMPLE
$doc->addEdge($edge);
getEdges
Returns an array of all Edges of this Document.
EXAMPLE
my @edges = $doc->getEdges();
getEdgesByProperties
Takes arguments of the form property1 => value, property2 => value2, ...
.
Returns a list of all Edges that matches the given filter.
EXAMPLE
my @edges = $doc->getEdgesByProperties('tArrow' => 'standard');
hasEdgeId
Takes an Edge's id
as parameter and returns true if it is present in this Document.
EXAMPLE
if ($doc->hasEdgeId('myid1')) { ...
getEdgeById
Takes an id
as parameter and returns the Edge with this id
, if present in this Document.
EXAMPLE
my $edge = $doc->getEdgeById('myid1');
removeEdge
Takes a yEd::Edge as parameter and tries to remove it from this document.
EXAMPLE
$doc->removeEdge($edge);
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.