Copyright 2001 RO IT Systems GmbH RO IT Systems GmbH www.roitsystems.com Building an SVG GUI with Perl Ronan Oger RO IT Systems GmbH Ronan @ roasp . com Ronan . oger @ roitsystems . com SVG Open 2003 SVG Open 2003
Mar 26, 2015
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Building an SVG GUIwith Perl
Ronan Oger
RO IT Systems [email protected]
SVG Open 2003
SVG Open 2003
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Perl
• Freely available for download• Cross-platform• Freely available for download• Cross-platform
– Tested on Sun, Windows, Mac OSX, Cygwin, Linux, FreeBSD
– Pure-perl: designed to avoid
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
SVG.pm
• Freely available for download under Perl Artistic License
• Installable many ways:– PPM– FreeBSD– Make– CPAN installation through Perl
• Pure-Perl: – Root access not required to implement– Cross-platform
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Installing SVG.pm
• CPAN:Perl –MCPAN –e `install SVG‘
• Perl Package Manager (win32):PPM
PPM>Install SVG
• Make:Gunzip svg-xx.xxx.tar.gz
Tar –xvf svg-xx-xxx.tar
Make
Make test
Make install
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
SVG.pm Features
• Free – Perl Artistic License• You get what you pay for...• You can ask for special features...
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
SVG.Pm Usage Examples
• Hello SVG World!• Draw a line• Navigating the DOM• Tessalate• YAPH
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Hello SVG World!
#!/usr/bin/perl -w
use strict;
use SVG;
print "Content-Type: image/svg+xml\n\n";
my $svg=new SVG();
$svg->rect(id=>'rect1',x=>'20px',y=>'55px',
width=>10,height=>10,fill=>'yellow');
my $text = $svg->text(x=>20, y=>55,
fill=>'red', stroke=>'black');
$text->cdata("Hello SVG world!");
#grab the fill element
my $fill = $svg->getElementByID('rect1')
->getAttribute('fill');
#modify the fill attribute of the text element
$text->setAttribute('fill',$fill);
print $svg->render(); #xmlify
http://www.roitsystems.com/conferences/yapc_eu/code/hello_world.txt
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Draw a Line
#!/usr/bin/perl -w
use strict;
use SVG;
print "Content-Type: image/svg+xml\n\n";
my $svg=new SVG(width=>60, height=>45);
my $group1=$svg->group(id=>"outer_group");
my $group2=$group1->group(id=>"inner_group");
$group2->line(x1=>20, y1=>30, x2=>50, y2=>35, stroke=>"blue");
print $svg->render();
http://www.roitsystems.com/conferences/yapc_eu2003/code/01b-GroupedLine.txt
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Navigate the DOM ...Part 1#!/usr/bin/perl –w
use strict;
use SVG;
print "Content-Type: image/svg+xml\n\n";
my $svg=new SVG(width=>60, height=>60);
my $group1=$svg->group(id=>"outer_group");
$group1->rect(x=>10, y=>10, width=>40, height=>40, fill=>"yellow");
my $group2=$group1->group(id=>"inner_group", stroke=>"blue");
$group2->line(x1=>10, y1=>30, x2=>50, y2=>40);
$group2->line(x1=>30, y1=>10, x2=>40, y2=>50);
$group2->line(x1=>10, y1=>40, x2=>40, y2=>10);
my $anchor = $group1->anchor(-href=>'http://example.net');
my $circle = $anchor->circle(cx=>30, cy=>30, r=>6, fill=>"red");
$circle->set(begin=>"mouseover", end=>"mouseout",
attributeName=>'fill', to=>'cyan');
print $svg->render(); #or xmlify or serialize
http://www.roitsystems.com/conferences/yapc_eu2003/code/01i-FirstNextIterator.txt
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Navigate the DOM ...Part 2
iterate($svg);
sub iterate {
my ($element,$depth)=@_;
$depth=0 unless defined $depth;
my $child=$element->getFirstChild();
return unless $child;
do {
print "\t"x$depth,
"Element $child is a ",
$child->getElementName(),
"\n";
iterate($child,$depth+1) if $child->hasChildren;
} while ($child = $child->getNextSibling);
}
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
#!/usr/bin/perl -w
use strict;
use SVG;
my $svg = SVG->new(width=>"100%", height=>"100%");
my $g = $svg->group(style=>{"fill-rule"=>"evenodd","stroke-linejoin"=>"round", "stroke-linecap"=>"round"});
my $d1 = $g->defs();
my $path = $svg->get_path(-type=>"path", x=>[0,90,60], y=>[0,60,90], -closed=>1);
my $d1g1p = $d1->group(id=>"Tess0p")->path(%$path);
my $d1g0 = $d1->group( id=>"Tess0", fill=>"rgb(255,255,0)",
stroke=>"none")->use(-href=>"#Tess0p");
Tessalate ...Part 1
http://www.roitsystems.com/conferences/yapc_eu2003/code/tessalate.txt
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Tessalate ...Part 2
my $d1g1 = $d1->group(id=>"Tess1", fill=>"none", stroke=>"rgb(0,0,0)", "stroke-width"=>"2.413")->use(-href=>"#Tess0p");
$path = $svg->get_path(-type=>"path", x=>[15,75,50], y=>[15,50,75], -closed=>1);
my $d1g2p = $d1->group( id=>"Tess2p")->path(%$path);
my $d1g2 = $d1->group(id=>"Tess2", fill=>"rgb(255,170,255)", stroke=>"none")->use(-href=>"#Tess2p");
my $d1g3 = $d1->group( id=>"Tess3", fill=>"none", stroke=>"rgb(0,0,0)", "stroke-width"=>"2.413")->use(-href=>"#Tess2p");
my $d2p2 = $g->defs()->pattern(id=>"TessPattern", patternUnits=>"userSpaceOnUse", x=>"0", y=>"0",
width=>"100", height=>"100", viewBox=>"0 0 100 100", overflow=>"visible");
$d2p2->group()->use(-href=>"#Tess0");
$d2p2->group()->use(-href=>"#Tess1");
$d2p2->group()->use(-href=>"#Tess2");
$d2p2->group()->use(-href=>"#Tess3");
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Tessalate ...Part 3
$svg->comment('Now let us define the polygon with the fill inside it refered to by url reference');
$svg->polygon(points=>"163.816,337.5 ".(140+rand(20)).",".(400+rand(60))." 234.868,344.079 334.868,428.289 291.447,299.342 480.921,284.868 326.974,".(160+rand(60))." 344.079,30.9211 232.237,167.763 123.026,29.6053 150.658,191.447 37.5,94.0789 ".(100+rand(10)).','.(200+rand(40))." 7.23684,288.816 84.8684,287.5 33.5526,333.553 111.184,320.395 82.2368,448.026",fill=>"url(#TessPattern)", stroke=>"black");
$svg->text(x=>100,y=>20)->cdata("Using A tessalated pattern to create a fill");
$svg->anchor(-href=>'http://roasp.com/tutorial/source/tessalate.txt')->text(x=>50,y=>400, fill=>'red' )->cdata("View Script Source");
print "Content-type: image/svg+xml\n\n";
print $svg->xmlify;
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
• Minimize client-side functional requirements
• Keep business logic on the server• Facilitate functional extension• Require planing and vision
Thin-client Applications
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
• Now: HTML-style form process model.– Render->modify->submit.– Familar with users.
• (Possibly) Later: XFORMS support in SVG.– Embedded form content within the XML
vocabulary.– Problem: Not in 1.2. Not finalized. No
processing model.– Too complex. Never worked with it...
Forms Processing in SVG
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
• HTML:– declarative form
processing– Must submit all values and
refresh page
• SVG 1.0-1-2:– No support for declarative
information processing– Reliant on scripting
HTML-Style Forms
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
HTML-style Architecture Concept
• Keep the widget a ‘black box‘• Wiget changes modify a text field• Maintain state at server• Use commit event to update state
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Examples
• Rotary control
• Sliding control
• Pull-down menu
http://www.roitsystems.com/conferences/yapc_eu2003/svg/knob.svg
http://www.roitsystems.com/conferences/yapc_eu2003/svg/slider.svg
http://www.roitsystems.com/conferences/yapc_eu2003/svg/pulldown.svg
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
How This Works...
• Commit button.• Do_process_form.• getURL (postURL).• Callback_method – rendering
commands.– Old: delete by id.– New: append to the workspace.– Message: server messages for the
user.
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Script Components
• Do_set_string: Assign the interface values
• Do_process_form: Submit the form• Show_callback: handle the result
from getURL
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
do_set_string()
// set a string
function do_set_string(Doc, id, string) {
Doc.getElementById(id).getFirstChild.setData(string);
}
• Provides a single method for assigning values to the form interface.
• Required due to a shortcoming in SMIL which does not support declarative animation on text elements.
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
do_process_form()
// submit the form for processing
function do_process_form(IDArray,ValueArray) {
var url = 'GISMax.cgi?edit=;act=processform;';
for (var i=0; i<IDArray.length; i++) {
url = url +
eval("'"+IDArray[i]+"'") + "=„ +
getFormFieldValue(evt,eval("'"+ValueArray[i]+"'"))+';';
}
getURL(url+';uid='+uid,show_callback);
setCommand(evt,'');
}
• Form handler for submit. • Required due to a shortcoming in SMIL which does not
support declarative animation on text elements.
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Show_callback() ...Start
function show_callback(test) {
//handle the raw return and parse the data
grp=parseXML('<g>'+test.content+'</g>',document);
if (grp.hasChildNodes) {
vp = document.getElementById('canvas');
//handle <old> nodes
engine = grp.getFirstChild();
xml = engine.getFirstChild();
//...continued next slide
• Form handler for submit. • Required due to a shortcoming in SMIL which does not
support declarative animation on text elements.
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Show_callback() ...Old
oldgroup = xml.getElementsByTagName('obj'); // I think this is now an array
var length = oldgroup.getLength();
i=0;
var oldId = "none";
while (i < length) {
thisElement=oldgroup.item(i);
oldId = thisElement.getAttribute("id");
myself = document.getElementById("g."+oldId);
if (myself) {
myself.parentNode.removeChild(myself);
myself = null;
}
i++;
do_set_string(document,'message',"Attached anchor "+oldId);
}
// ...continued
• Dispose of old elements by ID that the server declares as deletable
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Show_callback() ...msg
//message handler
//grab the message we recieved
message_body = xml.getElementsByTagName('message');
if (message_body) {
if (messageElement=message_body.item(0)) {
message = messageElement.getAttribute('value');
do_set_string(SVGDoc,'message',message);
}
}
• Message handler for feedback at the client side
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Show_callback() ...News
//handle new elements. Each element to be added is actually a group.
news = xml.getElementsByTagName('new');
length = news.getLength();
if (length == 0) {return}
var i=0;
while (i<length) {
xml = news.item(0);
newgroup = xml.getElementsByTagName('g');
var groups = newgroup.getLength();
//catch error (2): missing <g> tags in <new> tag
if (groups == 0) {return}
var j = 0;
while (j<length) {
vp.appendChild(newgroup.item(j));
j++;
}
}
} //for completeness. End of subroutine
• Insert new SVG snippet into workspace
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
XML snippet result
<engine id="engine">
<old id="oldgroups">
<OldID id="text_from_server" />
</old>
<NewGroup id="newgroup">
<g id="g.text_from_server">
<rect width="100" y="20" fill="green"
stroke="blue" x="10" height="60" />
<text y="24" fill="red" x="23">
Hey... you said: Dog</text>
</g>
</NewGroup>
<messages id="messages">
<message value="Hey, you said something" />
</messages>
</engine>
• Script function do_process_form causes a query to be called by getURL and to be parsed by parsXML
• Result of pulldown.svg server query
http://localhost/cgi-bin/svgopen2003/gui_workshop/processor.pl?gui_form_x_value=Dog
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Why this stuff is Good• Keep the client-side functionality simple
– Reduce implementation risk– Minimize cross-platform incompatibilities
• No large clientside codebase– Reduce user wait before getting started
• Obfuscates code base – some people like this– Client-side machine has minimal business logic– Applications can not be reverse-engineered by users
• Well suited for collaboration applications• All data stored on centralized servers
– Reduces workstation failure risk– Increases security– No user access to data unless explicitly enabled
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Down sides
• Must stay connected to the server – no standalone apps.– Not always on line.
• Bandwidth.– Mass-market sites not a good idea.– Better suited for intranet systems.– Distance to host affects user experience.
• Server load – Requires powerful hardware.– Server intensive.– Can be minimized by using caching.
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Down sides ...2
• Lag: Round-tripping data takes time– Not suitabable for very fast response systems– Need to allow for communication failures
• Incomplete Browser support– Requires SVG and JS– Limited to Adobe 3+, Corel batik.– ASV3 is broken on Mozilla 1.– Native SVG support in Mozilla still
experimental– JS/SVG has Issues on non-Windows platforms
Copyright 2001 RO IT Systems GmbHRO IT Systems GmbH www.roitsystems.com
Resources• Sites
– http//www.roasp.com/ Serverside SVG portal – by RO IT systems– http://www.w3.org/TR/SVG/ SVG recommendation – Comprehensive SVG
documentation with extensive examples– http://www.svgopen.org SVG Open conference home – Repository of papers
and presentations from past conferences dating back to SVG Open 2002– http://www.scale-a-vector.de/home-e.htm Petra Kukofka‘s SVG design page –
SVG cartoons and animations, discussions, SVG articles– http://www.schemasoft.org/ SPARK project: SVG Programmers'
Application Resource Kit. Sponsored by SchemaSoft.– http://www.pinkjuice.com/svg/ Prolific SVG page by Tobias rief in Berlin– http://www.svgfoundation.org SVG Foundation – http://www.protocol7.com/svg-wiki/ The SVG wiki – excellent site for cross-
reference– http://www.svg-cafe.com/ an SVG discussion forum sponsored by EvolGrafiX.– http://www.carto.net/ A rich cartography-specific SVG site with a number of
high quality academic papers and demos.
• Newsgroups– [email protected]