You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-users@xmlgraphics.apache.org by Lukasz Matuszczak <l....@atrem.pl> on 2005/01/13 16:18:56 UTC
Mix SVG with Swing - Swing GraphicsNode?
I'm using the batik toolkit to create dynamic and interactive diagrams in my
Swing application. The diagrams should mix typical SVG content with swing
components, like a JButton, ChartPanel (from JFreeChart project). I assume
that my diagram consists of a SVG background (presented by JSVGCanvas or
potentially one of its superclasses) and components, which locations and
sizes are specified relative to coordinate system of the background. By the
way, due to performance reasons, some of my components are simply
transparent JSVGCanvases. For example when I want to change quickly some
small part of my SVG document (for example to rotate fast a small arrow
symbol in a big complicated document), using single JSVGCanvas turned out to
be totally ineffective. Instead I'm cutting out DOM fragment and creating
separate SVG document out of it. It is a little tricky solution because i
have to set <svg> tag viewbox attribute properly for the additional SVG
Document, when i want my JSVGCanvas component to have a different location
and size than my background JSVGCanvas.
I have already created my own tags such as <oc:component id="btn1"
type="JButton" x="100" y="170" width="200" height="20"><oc:param
name="caption" value="My Button"></oc:component>
I can see different approaches to implement SVG and Swing mix.
1. Using JLayeredPane with custom layout manager. It is my current approach,
with which i'm not satisfied. In layout container we can set components'
bounds in layoutContainer method, based on viewboxtransform of background
canvas. The layered pane revalidate method is called in
gvtRenderingCompleted or updateCompleted when the viewbox transform has
changed. Off course it's a simplification, because components' bounds should
be calculated according to their parent tags coordinate system.
The shortcoming of this solution is that we can't put JLayeredPane in
JSVGScrollPane, so we have to implement all zoom and scrolling stuff on our
own.
2. Using JSVGCanvas as container (add method) - it is similar to first
solution, but it's potentially easier to use JSVGScrollPane.
3. Using batik extension mechanism. It would be the best solution because
all positioning, zooming, scrolling, painting, printing and so on, would be
supported directly by batik. Also i could partially cover swing components
by SVG shapes.
Thierry Kormann in
http://koala.ilog.fr/batik/mlists/batik-users/archives/msg01001.html
suggests that it is possible, but i got stuck in event dispatching and
repainting.
I have made bridges and dom extensions and MyComponentNode extending
AbstractGraphicsNode.
For example i call JButton's paint from MyComponentNode's primitivePaint(..)
method to paint button at specific place:
public void primitivePaint(Graphics2D g2d) {
...
Graphics gForComponent = g2d.create();
gForComponent.translate(button.getX(), button.getY());
button.paint(gForComponent);
...
}
At MyComponentNodeBridge' createGraphicsNode method I register listener on
graphics nodes mouse events. The code is:
UserAgent ua = ctx.getUserAgent();
if (ua != null) {
EventDispatcher dispatcher = ua.getEventDispatcher();
if (dispatcher != null) {
dispatcher.addGraphicsNodeMouseListener(node.getMouseListener());
}
I wanted to implement all methods of my mouseListener similar to:
button.dispatchEvent(new MouseEvent(button,
evt.getID(),
evt.getWhen(),
evt.getModifiers(),
x,
y,
evt.getClickCount(),
false));
Well, it nearly works but the problem is that the JButton doesn't belong to
Swing hierarchy so it won't repaint itself (for example to show that it's
pressed down).
Has anyone succeeded in making graphics node in GVT Tree based on Swing
Component, making it interactive when showed in JSVGCanvas?
I would also be grateful for any thoughts about advantages and disadvantages
of above approaches (espacially in the context of memory and processor
usage).
Thanks in advance.
Lukasz Matuszczak
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-users-help@xml.apache.org
Re: Mix SVG with Swing - Swing GraphicsNode?
Posted by Thomas DeWeese <Th...@Kodak.com>.
Hi Lukasz,
>>> 3. Using batik extension mechanism. It would be the best solution
>>> because
>>> all positioning, zooming, scrolling, painting, printing and so on, would
>>> be supported directly by batik. Also i could partially cover swing
>>> components by SVG shapes.
>
> [...]
>
>>> Well, it nearly works but the problem is that the JButton doesn't belong
>>> to Swing hierarchy so it won't repaint itself (for example to show that
>>> it's pressed down).
>>
> Thomas DeWeese wrote:
>> Unfortunately I don't know the internals of Swing well enough to
>> really help here, but I'll try and give some suggestions. I suspect
>> that when a component wants to 'update' it's self it calls one of the
>> repaint methods. I suspect that these repaint requests get forwarded
>> to the parent of the component. These then bubble up to the window
>> which triggers the actual update. If this is correct then you should
>> be able to provide a 'parent' for the button that will be notified
>> when the child wants to be repainted. The parent can then invalidate
>> the components region in the GVT tree (all this must happen in the
>> UpdateManager thread of course). Then the JSVGCanvas will request
>> that the region in question be repainted.
Lukasz Matuszczak wrote:
> I have two questions here:
> 1. How can I invalidate some regions in the GVT Tree? I know this must be a
> silly question, but I got lost a little bit in the Batik API :)
I could see how you might miss it. Changes in the GVT Tree are
signaled by triggering a 'GraphicsNodeChangeEvent'. These events
always come in pairs a 'started' and 'completed' event. In general
the entire visible bounds of the node that fires the event are
considered to be invalid.
> 2. Do you think it is possible to provide a 'parent' in such way, that my
> swing extensions to batik will work not only in my application but also for
> example in squiggle browser?
I would think so.
> I'm afraid that solutions which assume an
> access to UpdateManager thread are not perfectly clean and universal. As
> far as I understand it, while I write batik extensions I have access only to
> BridgeContext (i get it as parameter of createGraphicsNode method), and to
> UserAgent through the BridgeContext.getUserAgent() method.
Well the BridgeContext gives you access to almost everything,
including the UpdateManager (which has the UpdateManager thread).
The only word of caution I have is that 'caching' a reference to
the BridgeContext is a bad idea for static documents (which I
understand is not your area of interest). Ideally you would
check if the BridgeContext is configured for dynamic and only
cache a reference in that case (otherwise you just paint your
currently working 'static' version).
>> One comment on this, is that the reason putting little animations
>> out of the main document and into a transparent JSVGCanvas helps is
>> because the 'background' can then be repainted from the offscreen
>> image rather than having to walk the entire GVT tree [...]
>
> Well, thank you for this clarification. It puts in question the "batik
> extension" solution. If I understand it correctly, the only way to get a
> performance boost is to make JSVGCanvas (and thus GVT tree) "unaware" of my
> transparent JSVGCanvas components, so I am forced to use JLayeredPane
> (solution 1.) or JSVGCanvas as swing container (solution 2.)
Well, you could consider doing a bit of both (although it would be
a bit more work). So extension elements could trigger the creation
of Swing Components. The painting context for the swing components
would come from the GVT tree (when the GraphicsNode was painted).
This would be tricky!
>> Depending on the structure of the document what you really
>> want/need is the 'static' CSS hint from SVG 1.2. If this were
>> properly implemented in Batik it would allow subtree's to repaint
>> themselves from offscreen images rather than re-rendering the
>> subtree from scratch each time. I've done one or two sample
>> implementations and was not satisfied with the results but I'm
>> still looking into it.
>
> That would solve a lot of problems, so I wish you good luck
> :).
Yes, it really would solve a lot of problems and in general
is likely a _very_ important optimization for a vector graphics
language like SVG.
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-users-help@xml.apache.org
Re: Mix SVG with Swing - Swing GraphicsNode?
Posted by Lukasz Matuszczak <l....@atrem.pl>.
----- Original Message -----
From: "Thomas DeWeese" <Th...@Kodak.com>
To: "Batik Users" <ba...@xml.apache.org>
Sent: Tuesday, January 18, 2005 1:54 PM
Subject: Re: Mix SVG with Swing - Swing GraphicsNode?
Thank you very much for Your answers, Thomas. I am new to the batik project
and i'm really impressed with such a good response from the authors. Great job!
Unfortunately I wasn't able to read your suggestions and comment on them
earlier.
>
>> I can see different approaches to implement SVG and Swing mix.
>>
[..]
>> 3. Using batik extension mechanism. It would be the best solution because
>> all positioning, zooming, scrolling, painting, printing and so on, would
>> be supported directly by batik. Also i could partially cover swing
>> components by SVG shapes.
[...]
>
>> Well, it nearly works but the problem is that the JButton doesn't belong
>> to Swing hierarchy so it won't repaint itself (for example to show that
>> it's pressed down).
>
> Unfortunately I don't know the internals of Swing well enough to
> really help here, but I'll try and give some suggestions. I suspect
> that when a component wants to 'update' it's self it calls one of the
> repaint methods. I suspect that these repaint requests get forwarded
> to the parent of the component. These then bubble up to the window
> which triggers the actual update. If this is correct then you should
> be able to provide a 'parent' for the button that will be notified
> when the child wants to be repainted. The parent can then invalidate
> the components region in the GVT tree (all this must happen in the
> UpdateManager thread of course). Then the JSVGCanvas will request that the
> region in question be repainted.
I have two questions here:
1. How can I invalidate some regions in the GVT Tree? I know this must be a
silly question, but I got lost a little bit in the Batik API :)
2. Do you think it is possible to provide a 'parent' in such way, that my
swing extensions to batik will work not only in my application but also for
example in squiggle browser? I'm afraid that solutions which assume an
access to UpdateManager thread are not perfectly clean and universal. As far
as I understand it, while I write batik extensions I have access only to
BridgeContext (i get it as parameter of createGraphicsNode method), and to
UserAgent through the BridgeContext.getUserAgent() method. Therefore I can't
see the way to invalidate the components region in the GVT tree from that level.
[...]
> One comment on this, is that the reason putting little animations
> out of the main document and into a transparent JSVGCanvas helps is
> because the 'background' can then be repainted from the offscreen
> image rather than having to walk the entire GVT tree looking for nodes
> or subtree's that intersect the animated region. So if you then
> move these canvas's back into the GVT tree you will have your old
> performance problem back because you will once again have to walk
> the whole GVT tree drawing everything under the animated region.
Well, thank you for this clarification. It puts in question the "batik
extension" solution. If I understand it correctly, the only way to get a
performance boost is to make JSVGCanvas (and thus GVT tree) "unaware" of my
transparent JSVGCanvas components, so I am forced to use JLayeredPane
(solution 1.) or JSVGCanvas as swing container (solution 2.)
> Depending on the structure of the document what you really
> want/need is the 'static' CSS hint from SVG 1.2. If this were
> properly implemented in Batik it would allow subtree's to repaint
> themselves from offscreen images rather than re-rendering the
> subtree from scratch each time. I've done one or two sample
> implementations and was not satisfied with the results but I'm
> still looking into it.
That would solve a lot of problems, so I wish you good luck
:).
Best regards
Lukasz Matuszczak
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-users-help@xml.apache.org
Re: Mix SVG with Swing - Swing GraphicsNode?
Posted by Thomas DeWeese <Th...@Kodak.com>.
Hi Lukasz,
Lukasz Matuszczak wrote:
> I can see different approaches to implement SVG and Swing mix.
>
> 1. Using JLayeredPane with custom layout manager.
> 2. Using JSVGCanvas as container (add method) - it is similar to first
> solution, but it's potentially easier to use JSVGScrollPane.
> 3. Using batik extension mechanism. It would be the best solution
> because all positioning, zooming, scrolling, painting, printing and so
> on, would be supported directly by batik. Also i could partially cover
> swing components by SVG shapes.
> Thierry Kormann in
> http://koala.ilog.fr/batik/mlists/batik-users/archives/msg01001.html
> suggests that it is possible, but i got stuck in event dispatching and
> repainting.
> Well, it nearly works but the problem is that the JButton doesn't belong
> to Swing hierarchy so it won't repaint itself (for example to show that
> it's pressed down).
Unfortunately I don't know the internals of Swing well enough to
really help here, but I'll try and give some suggestions. I suspect
that when a component wants to 'update' it's self it calls one of the
repaint methods. I suspect that these repaint requests get forwarded
to the parent of the component. These then bubble up to the window
which triggers the actual update. If this is correct then you should
be able to provide a 'parent' for the button that will be notified
when the child wants to be repainted. The parent can then invalidate
the components region in the GVT tree (all this must happen in the
UpdateManager thread of course). Then the JSVGCanvas will request
that the region in question be repainted.
> Has anyone succeeded in making graphics node in GVT Tree based on Swing
> Component, making it interactive when showed in JSVGCanvas?
>
> I would also be grateful for any thoughts about advantages and
> disadvantages of above approaches (espacially in the context of memory
> and processor usage).
One comment on this, is that the reason putting little animations
out of the main document and into a transparent JSVGCanvas helps is
because the 'background' can then be repainted from the offscreen
image rather than having to walk the entire GVT tree looking for nodes
or subtree's that intersect the animated region. So if you then
move these canvas's back into the GVT tree you will have your old
performance problem back because you will once again have to walk
the whole GVT tree drawing everything under the animated region.
Depending on the structure of the document what you really
want/need is the 'static' CSS hint from SVG 1.2. If this were
properly implemented in Batik it would allow subtree's to repaint
themselves from offscreen images rather than re-rendering the
subtree from scratch each time. I've done one or two sample
implementations and was not satisfied with the results but I'm
still looking into it.
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-users-help@xml.apache.org