lib-gwt-svg goals and design

Library goals

lib-gwt-svg tries to reach the following goals:

  • Provide a clean, GWT-friendly API
  • Hide the idiosyncrasies of vendor SVG implementations
  • Reuse existing GWT features wherever possible to eliminate code duplication and impedance mismatch
  • Stick to the W3C standard, unless it duplicates an existing GWT feature or the GWT feature is too incomplete

Compatibility with SVG, W3C standards and exitsing GWT APIs

The SVG 1.1 specification is built on top of several other specifications. The following table lists each specification, explains whether GWT already has an API addressing it, and whether lib-gwt-svg chooses to reuse it or not. The following subsections provide a more elaborate view of each table row.

W3C Standard Goal Pre-existing GWT APIs Reuse in lib-gwt-svg
DOM Level 2 Define the base model to access the documents displayed by a browser com.google.gwt.dom.client defines overlay classes for low-level DOM programming. com.google.gwt.user.client also has an Element overlay class. com.google.gwt.user.client.ui defines fundamental user-interface classes. Mostly.
DOM Level 2 views Provide support for multiple views on the same document No API Not supported currently
DOM Level 2 events Define the events occurring as one interacts with a browser document. GWT already has one low-level event model (com.google.gwt.user.client.DOM) and two high-level models: com.google.gwt.user.client (deprecated) and com.google.gwt.event.dom.client Mostly.
SMIL Provide support for animation and integration of multimedia content in DOM document GWT offers com.google.gwt.animation.client. No.
CSS Define the graphical styles used to render elements com.google.gwt.dom.client.Style provides Css style support. Mostly.
XLink Defines linking between documents GWT provides a com.google.gwt.user.client.ui.Hyperlink which provides integration with History. Not yet. Planned History integration

DOM Level 2

GWT has two hierarchies. The low-level class hierarchy in com.google.gwt.dom.client consists mostly in overlay types for HTML elements. The high-level class hierarchy in com.google.gwt.user.client.ui consists in higher level widgets classes which wrap types of the first hierarchy.

lib-gwt-svg uses a similar architecture. The types in org.vectomatic.dom.svg.impl forms the low-level implementation based on overlay types. You should never have to use these types directly. The types in org.vectomatic.dom.svg form the high level implementation which end-users manipulate.

End-users only need to care about DOM Level 2 in the following scenarios:

  • when they need to insert their DOM tree in the HTML tree: lib-gwt-svg automatically imports the node in the main document and OMElement.getElement() will return a GWT compatible class
  • when they need to manipulate the DOM structure: the wrapper types provide DOM-like methods to manipulate the DOM tree (appendChild, removeChild, insertBefore, …). Users should be careful when they use methods to navigate the DOM tree (getNextSibling, getElementById, …). These methods automatically build a wrapper type from the underlying overlay type. While convenient, these method build a new wrapper every time they are called. Thus end-users should either store the returned reference for later use, or do their navigation on the overlay types and convert to wrapper types when needed using OMNode.convert

DOM Level 2 events

The GWT event model is roughly structured like this: a low-level model registers handlers and channels events through a central dispatcher. The dispatcher sends events to a new and extensible event model. The new event level is capable of emulating the deprecated event model. lib-gwt-svg cannot reuse low-level model: it is indeed not extensible and SVG has several events which are specific (onzoom, onrepeat, onfocusin…). Thus this part is re-developed, and you should not try to use event-related methods of com.google.gwt.user.client.DOM. lib-gwt-svg channels events to a central disptacher. The dispatcher sends events to the GWT new event model. This provides compatibilty with existing GWT APIs (notably, mouse event handlers are the same). lib-gwt-svg extends the GWT event model with new classes corresponding to new event types. No effort is made towards compatibility with the deprecated GWT event model.

SMIL

GWT offers com.google.gwt.animation.client. It consists mostly in timer management and is orthogonal to SMIL. Indeed, SVG SMIL provides support for declarative animation, using animation elements derived from ElementTimeControl. lib-gwt-svg integrates SMIL by providing animation specific events integrated in the GWT event model. However currently only Opera seems to implement them. lib-gwt-svg does not preclude using com.google.gwt.animation.client to update an SVG scene at periodic intervals. Actually, this seems like the only approach to SVG animation today given the limitations of current SVG implementations, Opera excepted.

CSS

SVG low-level class hierarchy in com.google.gwt.dom.client provide support for manipulating both the ‘style’ and the ‘className’ CSS attributes. These mechanisms can be reused, but only up to a certain point. Bug 374216 is Firefox breaks the Style.getProperty() and Style.setProperty() on SVG elements. The SVG model itself makes the className an OMSVGAnimatedString instead of a mere String. lib-gwt-svg defines an OMSVGStyle overlay type derived from Style. It provides a pair of getSVGProperty() and setSVGProperty() to bypass Bug 374216. lib-gwt-svg also defines a IStylable interface, which provides methods equivalent to GWT for classname manipulation, but adapted to the constraints of an OMSVGAnimatedString.

GWT provides a com.google.gwt.user.client.ui.Hyperlink which provides integration with History. This class cannot be reused, but the same principles will be implemented in a future version to provide integration between OMSVGAlement and com.google.gwt.user.client.History.

Lib-gwt-svg relies on the browser native SVG engine and its javascript API. To invoke the API, all lib-gwt-svg methods invoke a JSNI method at the end of the call chain. Some of the native javascript APIs can raise exception. JNSI will catch these exceptions and report them as com.google.gwt.core.client.JavaScriptExceptions. com.google.gwt.core.client.JavaScriptExceptions are runtime exception, which means you do not have to catch them and declare them like checked exceptions. The W3C specifications distinguishes several kinds of exceptions (DOMExceptions, SVGExceptions), however from a GWT point of view they will all appear as JavaScriptException. It could have been possible to catch all the com.google.gwt.core.client.JavaScriptExceptions, wrapped them in a typed checked exception and rethrow that exception. However this would have been awkward to manipulate for the end user, would have degraded performance and would have brought little added value. Thus the choice has been made to keep the exception in the form of com.google.gwt.core.client.JavaScriptExceptions. It is very important information though for the end user to know when they invoke a method if it may throw an exception and in what circumstance. Thus, all the exceptions are documented and throws clauses have been used for added precision, though it does not change the fact that the thrown exceptions are not checked exceptions.

25 comments to lib-gwt-svg goals and design

  • David Sirland

    I have a question regarding events. I am trying to load an external .svg file, parsing it using the same code as the example with the tiger.
    But then I want to connect an event to a specific SVG node with a specific id, or atleast reach the clicked element in the handler for the event. As I currently stand, the mouse events are only supported on the OMSVGSVGElement class (addMouseDownHandler), and the resulting MouseDownEvent getSource() does only hand me the OMSVGSVGElement back, not the node&element clicked in the SVG.

    Is this at all possible to do? Or am I trying to do something futile here, appreciate the pointers!

  • admin

    David,

    I think I see where the problem comes from. Actually most SVG elements which have a graphical representation (such as all shapes) respond to mouse events. In lib-gwt-svg-samples you have an example with a circle responding to mousedown events.

    Maybe the problem comes from the fact that OMSVGParser.parse() returns a OMSVGSVGElement. Thus you need to:
    1. navigate back to the the document to which this OMSVGSVGElement belongs (this is the not very intuitive part)
    2. From there, you can call OMSVGDocument.getElementById(“yourElementId”)
    3. Then you can downcast the resulting node to the proper SVG type (say, OMSVGRectElement).
    4. Finally, you ought to be able to add your event handler on the downcast type

    I do something similar in the chess sample (look at http://www.vectomatic.org/mvn-sites/lib-gwt-svg-chess/xref/org/vectomatic/svg/chess/ChessBoard.html#120)

    One final word of caution. As mentioned in the above post, if you need repeated access to the same SVG element, you should keep a reference to it. Indeed, two calls to: mySvgDocument.getElementById(“foo”) will return two different wrapper instances (which will both point to the same SVG overlay type). While harmless most of the time, this could cause confusion / bugs and waste resources.

  • David Sirland

    Ah, I see. Thank you for your swift response :).

  • Popadom

    Hi,

    i’m trying to import lib-gwt-svg.jar to my gwt project but when I inherit to my xml application file hosted mode returns blank page and gwt doesn’t compile. what’s wrong?

    Thanks guys!

  • admin

    Not 100% sure what is wrong in your case. My guess is that it may be a classpath problem. Note that for everything to work correctly, lib-gwt-svg.jar must appear in your classpath before gwt-user.jar and gwt-dev.jar. This is because the UiBinder integration work I did requires one class of gwt-user.jar to be replaced with my “patched” version, so my class must be loaded first otherwise you get an error like:

    00:00:13.031 [ERROR] Unable to load module entry point class org.vectomatic.svg.samples.client.Main (see associated exception for details)
    java.lang.RuntimeException: Deferred binding failed for ‘org.vectomatic.svg.samples.client.widgets.WidgetsSample$WidgetsSampleBinder’ (did you forget to inherit a required module?) at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:43) at com.google.gwt.core.client.GWT.create(GWT.java:98) at org.vectomatic.svg.samples.client.widgets.WidgetsSample.(WidgetsSample.java:97) at org.vectomatic.svg.samples.client.Main.onModuleLoad(Main.java:95) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:369) at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:181) at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:510) at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:352) at java.lang.Thread.run(Thread.java:619) Caused by: com.google.gwt.core.ext.UnableToCompleteException: (see previous log entries) at com.google.gwt.dev.shell.ModuleSpace.rebind(ModuleSpace.java:541) at com.google.gwt.dev.shell.ModuleSpace.rebindAndCreate(ModuleSpace.java:414) at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:39) at com.google.gwt.core.client.GWT.create(GWT.java:98) at org.vectomatic.svg.samples.client.widgets.WidgetsSample.(WidgetsSample.java:97) at org.vectomatic.svg.samples.client.Main.onModuleLoad(Main.java:95) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:369) at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:181) at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:510) at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:352) at java.lang.Thread.run(Thread.java:619)

    Can you tell me more about the environment you are using and stack traces if you have any (I work with maven and Eclipse 3.4 and and do not use the GWT eclipse plugin) ?

  • Popadom

    I’m using Eclipse 3.5 with GWT Plugin..

    I just create a new Web Application Project which works great, but when I inherit the lib on the xml file ( ), the application does not load the module (Hosted Mode) showing this error:

    19:58:58.564 [ERROR] [app1] Failed to load module ‘app1’ from user agent ‘Safari DMP’ at localhost:59113
    java.lang.UnsupportedClassVersionError: Bad version number in .class file
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:676)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:317)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:280)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:375)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:242)
    at com.google.gwt.dev.javac.TypeOracleMediator.getAnnotationClass(TypeOracleMediator.java:482)
    at com.google.gwt.dev.javac.TypeOracleMediator.resolveAnnotation(TypeOracleMediator.java:563)
    at com.google.gwt.dev.javac.TypeOracleMediator.resolveAnnotations(TypeOracleMediator.java:583)
    at com.google.gwt.dev.javac.TypeOracleMediator.resolveClass(TypeOracleMediator.java:728)
    at com.google.gwt.dev.javac.TypeOracleMediator.addNewUnits(TypeOracleMediator.java:353)
    at com.google.gwt.dev.javac.CompilationState.assimilateUnits(CompilationState.java:135)
    at com.google.gwt.dev.javac.CompilationState.(CompilationState.java:79)
    at com.google.gwt.dev.javac.CompilationStateBuilder.doBuildFrom(CompilationStateBuilder.java:286)
    at com.google.gwt.dev.javac.CompilationStateBuilder.buildFrom(CompilationStateBuilder.java:182)
    at com.google.gwt.dev.cfg.ModuleDef.getCompilationState(ModuleDef.java:280)
    at com.google.gwt.dev.DevModeBase$UiBrowserWidgetHostImpl.createModuleSpaceHost(DevModeBase.java:99)
    at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:180)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:380)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:222)
    at java.lang.Thread.run(Thread.java:613)

    . And when I try to compile using Google-> GWT Compile shows GWT Compilation Failed.

    The only way to use the library is by creating maven project?

  • admin

    Thanks for the stack. Actually it seems to be a JDK version problem. lib-gwt-svg has been built with jdk version 1.6u16 on linux. Your stack mentions “safari”, so I suppose you must be working on macosx, probably with a JDK version older than mine. Hence the “java.lang.UnsupportedClassVersionError: Bad version number in .class file” error. I think lib-gwt-svg does not have any dependency on JDK 1.6, it could probably run with 1.5. Can you please give me your java version number and if this turns out to be the actual problem I will recompile with -target 1.5 and update the jar.
    By the way, you do not need to use maven to use lib-gwt-svg.jar. I will do a few experiments of my own with Eclipse 3.5 and the GWT plugin and keep you posted

  • Popadom

    I’m using default system library 1.5, i’ll try to use 1.6…

  • admin

    I have done some tests with Eclipse 3.5.2 / JDK1.6u16 / GWT plugin. It ought to work. I have written a getting started article to summarize the required steps for developers not using maven. Let me know how things work with 1.6 on your side.

  • Popadom

    yes,

    i just tried, it works on 1.6

    thanks!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  • Allen Wu

    Dear admin,

    I want to use ” element with libgwtsvg.jar, but why I get a null element as using the method ‘doc.createSVGAnimateMotionElement()’?

    When I parsed the inner code and found the return value of SVGAnimateMotionElement is ‘SVGElement’, not ‘SVGAnimateMotionElement’, which caused the conversion(last line) to return a null value.

    please refer to the following code:
    Element element = DOMHelper.createElementNS(
    (Document)ot.cast(),
    SVGConstants.SVG_NAMESPACE_URI,
    SVGConstants.SVG_ANIMATE_MOTION_TAG);
    SVGAnimateMotionElement svgAnimate =
    ((SVGAnimateMotionElement)element).cast();
    String type = DOMHelper.getType(svgAnimate); // type = ‘SVGElement’
    OMSVGAnimateMotionElement animateMotion = (OMSVGAnimateMotionElement)convert((SVGAnimateMotionElement)svgAnimate.cast());

    How can I resolve this problem? Please give me a advice. Thanks a lot in advance.

    Best regards,

    Allen Wu

  • admin

    Hi Allen,

    I think there are two problems here.

    1/ The first problem is that you are not using the right API. You are not supposed to use anything in the org.vectomatic.dom.svg.impl directly. These are implementation classes with no guarantee of API stability. The package javadoc mentions it, but this is not advertised prominently enough. I am in the process of writing a tutorial to make things clearer.

    Thus, the proper way to create a SVGAnimateMotionElement is:

    OMSVGDocument myDocument;

    OMSVGAnimationElement myAnimElement = myDocument.createSVGAnimateElement();

    Underneath the covers, this code does something which is very close to the code your posted.

    2/ The second problem is that the code will only work on browsers which support the animateMotion tag. Currently the results are not very good, since only two browsers support it:

    Opera 9.x +
    upcoming Firefox 3.7
    If you make the call on a browser which does not support it, the ‘myAnimElement’ will be null. I think this is what is happening.

    You can visit the http://localhost/vectomatic/lib-gwt-svg/resources page. It contains links to the officially supported SVG feature matrices for all vendors (except MS but this will come with IE9). In a nutshell: Opera is the most complete. Firefox is not far behind. Webkit-based browser have no support for filter effects and animation yet.

    Regards

    Lukas

  • Allen Wu

    Dear Lukas,

    Thanks very much for your quick response.

    I have ever tried to get OMSVGAnimateMotionElement with the 2 ways shown as below:

    Procedure 1:
    OMSVGDocument myDoc = OMSVGParser.currentDocument();
    OMSVGAnimateMotionElement myAnimate = myDoc.createSVGAnimateMotionElement();

    Procedure 2:
    OMSVGDocument myDoc = svg.getOwnerDocument().getElementById(“pathId”).getOwnedDocument();
    OMSVGAnimateMotionElement myAnimate = myDoc.createSVGAnimateMotionElement();

    But what I got were both of ‘null’ results, so I traced the inner code of createSVGAnimateMotionElement() in org.vectomatic.dom.svg.OMSVGDocument, and went through the test procedures as I mentioned at my last comment – The key point what I found was:
    the return value of (SVGAnimateMotionElement)DOMHelper.createElementNS((Document)ot.cast(), SVGConstants.SVG_NAMESPACE_URI, SVGConstants.SVG_ANIMATE_MOTION_TAG).cast() was ‘SVGElement’, not ‘SVGAnimateMotionElement’, so the return value of org.vectomatic.dom.svg.OMNode.Conversion.convert(node) was null.

    Look forward to your guidance.

    By the way,
    except Opera 9.x+ and upcoming Firefox3.7 as you mentioned, I found Google Chrome (4.1.249.1045) also supports animateMotion function.

    Best regards,

    Allen Wu

  • admin

    Allen,

    I have done some research on this topic and here is what I have found out. It really boils down to what browser you are using. SMIL animation at this point is really work in progress on all browsers, except for Opera (the code I gave you fails in FF37a4 but actually does work in Opera10.10).

    Your analysis is quite accurate, the fact that the instantiation fails on some browser comes from the fact that the browser either does not support the tag at all, or reports its javascript type incorrectly.
    Here are the results of my tests (on Linux). There are 4 tags in SMIL animation. The following table shows the javascript type returned by the browser when you create the tag from script, using Document.createElementNS:

    Tag name                 | animateMotion           | animateTransform           | animate           | animateColor
    Chrome 5.0.373.0 (44067) | SVGElement              | SVGAnimateTransformElement | SVGAnimateElement | SVGAnimateColorElement
    Firefox 3.7 alpha4       | Element                 | SVGAnimateTransformElement | SVGAnimateElement | Element
    Opera 10.10 (44067)      | SVGAnimateMotionElement | SVGAnimateTransformElement | SVGAnimateElement | SVGAnimateColorElement

    My advice to you is thus:

    1. If you really want to use SMIL animation at this point, use Opera, as it seems to be the only browser which does it correctly.

    2. To try to get the things to improve, you can report bugs to mozilla and webkit. For mozilla this is a bit early since they have never claimed to fully support SMIL animations at this point. I will file the bug though when they reach beta if things have not improved. I do not precisely know the status of SMIL in Chrome.

    3. If you need to develop something today, you can do your own animation by combining the lib-gwt-svg and com.google.gwt.animation.client.Animation and changing the parameters of your SVG scene by code. I know this approach works since I use it in http://www.vectomatic.org/games/lib-gwt-svg-edu to animate my transitions

    Regards
    Lukas

  • Allen Wu

    Dear Lukas,

    Thank you very much for your advice which resolves my problem.

    Best regards,

    Allen Wu

  • Marcos Rimoldi

    Hi Lukas,

    the type returned by the browser when you create the animateMotion from script, using Document.createElementNS, has changed in the last version published?

    I’m using 0.4.6 version and I’m getting the cast exception trying to instantiate a OMSVGAnimateMotionElement.

    thanks!

    Marcos.

  • admin

    Hi Marcos,
    In my entry from April 14, 2010 at 11:37 pm, I had come to the conclusion that only Opera implemented animateMotion correctly at that time (other browsers did not implement it and attempting to create such elements in these browsers would result in a ClassCastException). I think this is still the case. Can you confirm that your problem is with 0.4.6 + Opera (if so I will investigate), otherwise I think it comes from the browser not supporting it.

    Lukas

  • Marcos Rimoldi

    Hi Lukas,

    On Opera is working fine. The problem I have is on Chrome. I create a simple demo svg with the text editor and I can see animateMotion working on Chrome, but when I tried to add it using the lib, I got the exception.

    Marcos.

  • admin

    Maybe the animateMotion element exists but the corresponding javascript prototypes are not exposed in Chrome yet ? The code is the same in lib-gwt-svg for Chrome and Opera (there is no special Opera vs Chrome branch for this part of the library) so what works in Opera ought to work in Chrome if Chrome has a complete implementation. What version of Chrome are you using ? I will try to do some tests of my own tomorrow and report back my findings.

    Lukas

  • Marcos Rimoldi

    Yes, may be is the Chrome webkit. I’m using version 8.0.552.0 dev

    Marcos

  • admin

    I have done some testing and I can confirm what we were saying yersterday. The Chrome version of animateMotion is either buggy or incomplete at the moment. There is already an bug report for this at http://code.google.com/p/chromium/issues/detail?id=13585. I have added a comment of my own to it with more details. I did the testing with version 8.0.559.0 (63051) custom. You can star the bug, maybe it will increase the incentive for a quick fix.

  • liyuanchao

    hi,i want to use libgwtsvg.jar,when i create a gwt project(eclipse 3.6, plugin, gwt 2.4), copy the org package source to the project , i want to run it from libgwtsvg.gwt.xml use firefor, the web.xml file is null,the console give me the warning “[WARN] No startup URLs supplied and no plausible ones found — use -startupUrl”, my qq:397048009

  • liyuanchao

    thank you, i have slove the problem
    !

  • liyuanchao

    hello,i have try use the file libgwtsvg, i want to let my svg Graphical have its own menuļ¼Œcan you give me an example of how to use the menu,thank you very much!

  • admin

    hi liyuanchao2004,
    Could you please re-post your question to the official google-group ( https://groups.google.com/group/lib-gwt-svg ). I will be glad to answer it. I prefer answering questions on the newsgroup rather than here as the info provided through this canal have better visibility and can serve many people. Thanks
    Lukas

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>