copyright 2001 ro it systems gmbh ro it systems gmbh building an svg gui with perl ronan oger ro it...
TRANSCRIPT
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]