Hi Larry,

I was so happy that you proposed a 'minimal inversive' solution, but I
think it needs at least some tweaking.

Let's have a look at the relevant part of ZoomToSelectedItemsPlugIn.zoom():

1 -- panel.getRenderingManager().setInteractiveMode(false);
2 -- panel.getViewport().zoom(proposedEnvelope);
3 -- SwingUtilities.invokeLater(new Runnable() {
       public void run() {
          try {
            flash(geometries, panel);
          } catch (NoninvertibleTransformException e) {
        }
      }});
4 -- panel.getRenderingManager().setInteractiveMode(true);

After switching to non-interactive mode (1) all Renderer Runnables
produced by the RenderingManager are directly executed in the
event dispatch thread. This would be done in a render() method
of JUMP's RenderingMaanager. Unfortunately this will not happen!

If you call the Viewport.zoom method (2) the last thing inside this is
a repaint() against the LayerViewPanel. This repaint() lets the
Swing(!) RenderingManager of this component enqueue a Runnable
to the event display thread for later execution. Inside this
Runnable the render*() calls of *JUMPs will be executed. But for
the moment this is only scheduled.

After you've enqueued the flash Runnable (3) the internal event
dispatch queue will look like the following.

[a: Runnable from repaint -- render*()], [b: Runnable to flash]

This would be fine too because _iff_ the RenderingManager would
be in the non-interactive mode at the time of execution of a.
Then the Renderers would be executed directly via
GUIUtil.invokeOnEventThread(). So they would be executed before b.

But now the problem: Now you are doing 4, switching JUMP's
RenderingManager directly back to interactive mode.
The jobs a and b are not executed yet.
So when they got executed after the end of
ZoomToSelectedItemsPlugIn.zoom() the RenderingManager is back in
interactive mode and the Renderer Runnables
are not executed with GUIUtil.invokeOnEventThread().

To fix this I would place the 5 call inside the flash Runnable directly
before the flash() call too ensure that JUMPs rendering manager stays in
non-interactive mode as long as needed.

This observations are made under the assumption that
ZoomToSelectedItemsPlugIn.zoom() runs in the event dispatch thread.
If this is not the case the results are not predictable because the
threads  will work against each other and race conditions may occur.

But as always: I may be wrong with my analysis and so comments
and critics are welcome. :-)

I'm still a bit concerned that the hole expensive rendering is done
inside the event dispatch thread. I have to test if this may lead to
trouble elsewhere.

Stay tuned,
  Sascha

Sascha L. Teichmann schrieb:
> Hi Larry,
> 
> this definitely a step into the right direction. :-)
> 
> Using the event/display thread to serialize the
> renderers in the non-interactive mode is a good idea.
> Your code looks fine but I will think about the
> consequences (blocking GUI, etc.). Of course I
> will test it, too. ;-)
> 
> Regards, Sascha
> 
> Larry Becker schrieb:
>> The purpose of this thread is to document a problem with RenderManager
>> and to propose solutions.
>>
>> The good news:
>>
>> RenderManager is optimized for the most responsive interactive GUI
>> experience.  It uses multiple threads, image caching, and timed
>> refresh operations to ensure that the user's perception is that they
>> never have to wait.  IMO JUMP is unrivaled in this respect.
>>
>> The bad news:
>>
>> The original JUMP design did not including printing support.  Saving a
>> screen image was the only option.  Now we have many options supporting
>> printing, SVG, PDF, and image export.  This is great, but all of them
>> have to work around RenderManager issues to ensure proper results.
>> Sometimes a long user-specified delay while WMS or server layers
>> finish rendering is necessary.  This looks unprofessional and is
>> ultimately unreliable.
>> ----------------------------------------
>>
>> Here is the preferred solution as I see it (call it the "Interactive
>> Mode Switch" solution):
>>
>> Make a modification to the RenderManager class to include a new
>> property called interactiveMode with associated getters and setters.
>> The interactiveMode property defaults to true.  Printing code and
>> other routines that need batch oriented rendering will need to bracket
>> their rendering code with calls to setInteractiveMode(false) and
>> setInteractiveMode(true).  In between the calls, rendering operations
>> are guaranteed to be done on the same thread and block until they
>> complete.
>>
>> How this is accomplished:
>>
>> Again, making modifications only to RenderManager, make the following
>> changes:
>>
>> 1. In createRenderer() if interactiveMode is true, it should
>> setMaxFeatures for the Renderer to the maximum integer.  This will
>> disable image caching, causing renderers to paint directly to the
>> graphics context.
>>
>> 2. in render() if interactiveMode is true, it should run the Renderer
>> on the event thread instead of using the ThreadQueue.  Also it should
>> not start a repaint timer.
>>
>> These changes effectively eliminate any unsynchronized rendering from
>> RenderManager. See the attached copy of RenderManager for details.
>> -----------------------------------------------------
>>
>> For interactive plug-ins like ZoomToSelectedItems that also need to
>> control rendering order so that the flash operation is synchronized.
>> For ZoomToSelectedItems, in addition to bracketing rendering code with
>> sets, it is also necessary to use invokeLater() on the flash() method
>> so that it will be executed in order with the panel component update.
>>
>> I have tested this solution on both OpenJump and SkyJUMP and it seems
>> to solve the ZoomToSelectedItems flash issue (see attached file for
>> details).  I tested on my usual P4 2.4GHz and also on a 1.5GHz Athlon.
>> More testing is needed to determine how well it meets the needs of
>> printing plug-ins.
>>
>> This solution has the advantage that JUMP continues to behave exactly
>> as before until you set the interactiveMode to false.   No refactoring
>> of interactive rendering code is necessary.
>>
>> regards,
>> Larry Becker

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel

Reply via email to