What
SVG: Scalable Vector Graphics.
http://www.w3.org/Graphics/SVG
Currently a Candidate Recommendation. It defines an XML grammar
for rich 2D graphics which includes features such as transparency,
arbitrary geometry, filter effects (shadows, lighting effects,
etc...), scripting and animation.
There are several very good implementations of the spec. On
the (Java) server, we've used the CSIRO kit and experimented
with IBM's, but are moving very fast to Batik (http://xml.apache.org/batik/index.html).
On Windows clients, the Adobe control (http://www.adobe.com/SVG)
is superb.
Server Side Uses
SVG is a great way to construct dynamic images on a server.
We're using it to produce charts, graphs, powermaps, psychometric
results, imagemaps... anything where the graphic content is
variable but interaction with the graphic is limited.
Why use SVG here? Because it's XML. It's easy - and incredibly
flexible - to run a database query, or take some abritrary XML,
stream it through an XSLT transformation, apply a CSS stylesheet,
and end up with a JPG picture.
SVG and Groove
Synergies
The obvious synergy is that both SVG and Groove are founded
on XML. But there's way more than that.
XML
Both are completely centered around XML.
Everything is XML.
This means we can store an SVG model natively in a Groove database,
or construct SVG from other Groove data (with XSLT, for example),
and seamlessly move around the most complex data structures.
COM
Groove's component model is implemented upon COM; its user
interface components are COM components.
Adobe's SVG implementation is an ActiveX COM control. Which
means that talking between Groove and the Adobe viewer is very
straightforward and clean.
JavaScript
This is the primary development environment for both Groove
applications and SVG interactivity.
Development Speed
We could have used some Groove-supplied user interface components,
but this would have restricted our UI behavior. Or we could
have built UI components ourselves using C++ or VB, but this
would have meant a longer development cycle and specialist skill
sets. Using the SVG viewer inside Groove, our developers use
a single coherent set of skills: XML and JavaScript. Incremental
development and debugging becomes straightforward. Re-use is
encouraged by the tools - both SVG and Groove lend themselves
supremely well to modular project development.
UI Flexibility
The power of an SVG-driven application user interface is simply
in a different league from anything we could create any other
way.
Interactivity
The groove platform gives the *reason* for Internet standards-based
graphics to be interactive! And, SVG's UI dynamism - declarative
animations, smoothly scaling vector graphics, on-the-fly object
creation and DOM manipulation - is awesomely easy and powerful.
Distribution
The components which compose groove applications are distributed
(peer to peer, or from a center) according to dependency structures
defined using OSD (Open Software Description - yet another XML
vocabulary). This dependency structure means that our tools
can very simply specify that they require a certain ProgID,
or any set of other components - and also specify how these
dependent components can be found and installed. It's a very
seamless way to distribute plug-ins and other software components
exactly to the people who need them.
Implementation
Wrapping the Adobe SVG Control in a Groove Tool
The starting-point is to wrap Adobe's SVG control inside Groove's
"ActiveXWrapper" component, and put this inside a groove tool
layout.
The ActiveXWrapper
In your tool template, add a component to wrap the SVG control:
<g:Component Name="SVGControl">
<g:ComponentResource URL="http://components.groove.net/Groove/Components/Root.osd?Package=net.groove.Groove.ToolComponents.GrooveActiveXWrapperTool_DLL&Version=0&Factory=ActiveXWrapper"/>
<g:PropertyList Version="1">
<g:Property Name="ProgID" Value="Adobe.SVGCtl"/>
</g:PropertyList>
</g:Component>
Layout and Glue
Wrap everything inside a ComponentGroup, containing:
- a layout
- the ActiveX wrapper
- some glue code
thus:
<g:Component DisplayName="SVGComponent"
Name="SVGComponent">
<g:ComponentResource URL="http://components.groove.net/Groove/Components/Root.osd?Package=net.groove.Groove.ToolComponents.GrooveCommonComponents_DLL&Version=0&Factory=SubForm"/>
<g:ComponentGroup DefaultView="SVGView" Delegate="SVGGlue">
<g:Component Name="SVGView">
<g:ComponentResource URL="http://components.groove.net/Groove/Components/Root.osd?Package=net.groove.Groove.ToolComponents.GrooveCommonComponents_DLL&Version=0&Factory=ViewContainer"/>
<g:PropertyList Version="1"/>
<g:ComponentConnections>
<g:Connection ConnectionID="0" Name="SVGLayout"/>
</g:ComponentConnections>
</g:Component>
<g:Component Name="SVGLayout">
<g:ComponentResource URL="http://components.groove.net/Groove/Components/Root.osd?Package=net.groove.Groove.ToolComponents.GrooveCommonComponents_DLL&Version=0&Factory=HTMLTableLayout"/>
<g:PropertyList Version="1">
<g:Property Name="Layout">
<g:PropertyValue>
<TABLE CELLPADDING="0"><TR><TD>SVGControl</TD></TR></TABLE>
</g:PropertyValue>
</g:Property>
</g:PropertyList>
</g:Component>
<g:Component Name="SVGControl">
<g:ComponentResource URL="http://components.groove.net/Groove/Components/Root.osd?Package=net.groove.Groove.ToolComponents.GrooveActiveXWrapperTool_DLL&Version=0&Factory=ActiveXWrapper"/>
<g:PropertyList Version="1">
<g:Property Name="ProgID" Value="Adobe.SVGCtl"/>
</g:PropertyList>
</g:Component>
<g:Component Name="SVGGlue">
<g:ComponentResource URL="http://components.groove.net/Groove/Components/Root.osd?Package=net.groove.Groove.ToolComponents.GrooveCommonComponents_DLL&Version=0&Factory=ScriptHost"/>
<g:ComponentConnections>
<g:Connection ConnectionID="0" Name="SVGControl"/>
</g:ComponentConnections>
<SCRIPT>
<![CDATA[
// script here...
]]>
</SCRIPT>
</g:Component>
</g:ComponentGroup>
</g:Component>
Sending Events from Groove to SVG
In a word: don't.
The groove gluecode can get a handle on the SVG control's content,
and manipulate it. Do this.
You'll need to wait until the SVG control has loaded its content,
before you can get a handle on the DOM. That's described later.
For now:
var docSVG = null;
function initFirstTime() // called later...!v {
var s = SVGControl;
var c = s.Control;
var d = c.getSVGDocument();
docSVG = d;
}
/**
* External interfaces
* Callable from clients of this ComponentGroup
*/
function getSVGDocument()
{
return docSVG;
}
Sending Events to SVG from Groove
...tbd...
Delegation
Both the SVG file and the Groove tool will probably have some
JavaScript (or other scripting language) code which responds
to events and manipulates the "models" - the "view model" (SVG
DOM) and the "data model" (groove persistence and dynamics).
It's important to decide how to separate these two.
Here's our approach. It's not a "purist" model, but we think
it helps with development separation of roles, and makes debugging
quite a lot easier than simply exposing all the UI events in
their native form and asking in-groove script to handle those
events.
Beginning from the UI: users create commands by manipulating
the user interface in some way. Some UI gestures are significant
for the data model - they affect your application's data, and
you might want to use groove's dynamics to share those changes
with other users. Other gestures are only locally significant
- for example, selecting a menuitem, or hovering over a graphic
element to provide a tooltip.
So, build two layers:
- In SVG: handle all the user gestures. Locally-significant
gestures can manipulate the SVG DOM directly without talking
to groove at all. Gestures which might conceivably be interesting
to the groove context should be transformed into a set of "events"
which you can transmit into groove.
- In Groove: handle any events which the SVG control sends
you. Decide which of these alter the data model and which should
be shared and/or persisted. Dispatch those via groovey PropertyLists
or engines, and catch the OnXxxChange events which they generated,
at each client. When you get a change event (whether local or
remote), use that to write changes into the SVG DOM.
How Not To Delegate (1)
Don't pass every single SVG event into groove gluecode for
handling.
Well, you could, but it's not very efficient. More important,
it's quite hard to debug.
How Not To Delegate (2)
Don't try manipulating groove's APIs from JavaScript-inside-SVG.
It is possible (given some context, ie. the telespace and current
identity), but really not recommended.
Agora Professional Services, Ltd.