Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 218104

Summary: Cleanup of DefaultGalleryItemRenderer
Product: z_Archived Reporter: Peter Centgraf <peter>
Component: NebulaAssignee: Nicolas Richeton <nicolas.richeton>
Status: CLOSED INVALID QA Contact:
Severity: normal    
Priority: P1 CC: olaf.klischat, remy.suen, rkandepu
Version: unspecifiedKeywords: plan
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
Gallery Renderer cleanup
none
mylyn/context/zip none

Description Peter Centgraf CLA 2008-02-06 18:21:30 EST
This patch is a general cleanup of the DefaultGalleryItemRenderer class, reordering the drawing operations to simplify the logic and adding more comments.  I've eliminated duplicate local fields when an SWT property could be used instead, and I avoid caching values for properties that that may change dynamically at runtime.  Finally, this version will redraw the Gallery automatically when a visual property is changed in the renderer.
Comment 1 Peter Centgraf CLA 2008-02-06 18:22:06 EST
Created attachment 89087 [details]
Gallery Renderer cleanup
Comment 2 Olaf Klischat CLA 2008-08-10 21:58:52 EDT
I get intermittent "SWTException: Invalid thread access" exceptions in the callstack below the Display#getSystemColor() call in the DefaultGalleryItemRenderer() constructor. Apparently, Display.getDefault() sometimes returns a display that doesn't belong to the calling thread. I don't fully understand it, but I'd say that all the Display.getDefault() calls should be replaced with org.eclipse.ui.PlatformUI.getWorkbench().getDisplay() calls. See also the Javadoc for IWorkbench#getDisplay(), which clearly states that you should use that method instead of Display.getDefault().
Comment 3 Remy Suen CLA 2008-08-10 23:04:34 EDT
(In reply to comment #2)
> I don't
> fully understand it, but I'd say that all the Display.getDefault() calls should
> be replaced with org.eclipse.ui.PlatformUI.getWorkbench().getDisplay() calls.
> See also the Javadoc for IWorkbench#getDisplay(), which clearly states that you
> should use that method instead of Display.getDefault().

I'm not sure how this is possible since the Nebula Gallery plug-in doesn't have any dependencies on the RCP components of Eclipse.
Comment 4 Remy Suen CLA 2008-08-12 11:06:13 EDT
I'd personally propose that the default constructor of the DefaultGalleryItemRenderer class be deprecated and replaced with one that takes a Display as an argument. This should prevent the race condition that Olaf is having.
Comment 5 Nicolas Richeton CLA 2008-08-17 08:43:46 EDT
Olaf : it seems that you are calling DefaultGalleryItemRenderer from a separate thread. Usualy, you should call it from the main thread or use Display.syncExec().

We should add some code to fail directly if called from a thread (like checkWidget() )

 
Comment 6 Olaf Klischat CLA 2008-08-19 12:41:40 EDT
(In reply to comment #5)
> Olaf : it seems that you are calling DefaultGalleryItemRenderer from a separate
> thread.

I'm not. Sorry if I didn't make this clear enough -- I basically do:

Gallery gallery = new Gallery(parent, SWT.V_SCROLL | SWT.VIRTUAL);
gallery.setItemRenderer(new DefaultGalleryItemRenderer());

in the createPartControl() method of a View in an RCP application -- this method is run in the GUI thread. The exception happens in the DefaultGalleryItemRenderer() constructor.
Comment 7 Nicolas Richeton CLA 2008-08-20 06:29:33 EDT
Olaf : Ok, but there should not be any problem with Display.getDefault() if this method is called by the UI thread. 
Which platform are you using (Win32, GTK )?
Are you opening this view from your code or by using an extension point ?

I suspect that the whole createPart code is running in a separate thread.


Comment 8 Olaf Klischat CLA 2008-08-20 09:49:22 EDT
(In reply to comment #7)
> Olaf : Ok, but there should not be any problem with Display.getDefault() if
> this method is called by the UI thread. 

OK, I checked some more -- there may be a race condition in my application. There is a Display.getDefault().syncExec(...) here in a method that's called regularly by a spring quartz trigger -- i.e. an internal spring thread. Sometimes it may happen that this is called before the RCP app's main class Application#run() method got a chance to PlatformUI.createDisplay()  -- and thus, that internal spring thread would become the GUI thread. I'll investigate this further. Sorry if I caused confusion here :P

That still raises interesting questions for me though -- is it technically feasible to have more than one Display in an RCP app, e.g. in multi-monitor configurations? And if so, shouldn't using Display.getDefault() be discouraged for widget writers (and replaced by parent.getDisplay(), or, if that's impossible, taking a Display as a constructor parameter)?
Comment 9 Peter Centgraf CLA 2008-08-21 15:46:39 EDT
Yes, it is possible to have multiple Displays in the same JVM.  Widget.getDisplay() should be used instead of Display.getCurrent() or Display.getDefault().
Comment 10 Remy Suen CLA 2009-04-16 12:47:51 EDT
Any updates on this to remove calling the static methods of Display? I think this bug is the cause of bug 184413.
Comment 11 Nicolas Richeton CLA 2009-04-16 13:13:27 EDT
Remy, 
Well, I may be wrong, but it should be safe to call this method from the UI thread. 

Since this is a breaking API change, I want to be sure that this bug is really caused by the Gallery widget. Note : my own application also uses perspective save/restore with this widget and I never got this issue on restore.

the change is really easy to do, so I would like that someone having this problem to try the proposed fix and ensure it really solves the problem. 

OR : attach a snippet/simple product that shows the issue so I can check by myself.
Comment 12 Remy Suen CLA 2009-04-16 13:26:18 EDT
Unfortunately, attachment 89087 [details] no longer applices cleanly to HEAD.

Nicolas, regarding API breakage, would you adding and deprecating constructors per my suggested comment 4?
Comment 13 Nicolas Richeton CLA 2009-04-16 14:52:38 EDT
Made the Display fix without changing API. Default colors are now defined in setGallery(), not in constructor, by using gallery.getDisplay(). Committed in CVS > 20090416

Back to Peter's patch, it seems to set a background color for every item which can lead to unnecessary drawing operations and redraw slowdown. I need to review it in details. Just to be sure : is this patch only code clean up or does this includes a fix for something required in another bug ?

Comment 14 Nicolas Richeton CLA 2009-04-16 14:52:45 EDT
Created attachment 132117 [details]
mylyn/context/zip
Comment 15 Peter Centgraf CLA 2009-04-21 00:49:35 EDT
The main problem that the patch was intended to fix is stale cached Color values.  SWT defines setBackground() and setForeground() methods on both the main Control and its Items, and new values should take effect immediately.  The value set on the Control acts as a default, in case no value is set on a particular Item.  The value set in the Display acts as a global default, in case no value is set in the Control, either.  

The code as it was originally written cached the Color values from the Gallery in the constructor and never checked for changes, so calling Gallery.setBackground() had no effect.  In my opinion, we should handle this like SWT does, and repeat the lookup on Item, Gallery, and Display for each Item to ensure that the colors are up to date when painting.
Comment 16 Nicolas Richeton CLA 2009-04-21 07:36:28 EDT
Ok, changing priority to P1 since this is a difference with SWT API. I'll take a look at it ASAP.
Comment 17 Nicolas Richeton CLA 2009-04-22 03:50:54 EDT
I've made the change to use Parent's color as in Tree. Item background is only drawn if different from gallery background color. 

Note : There is a bug on SWT carbon 3.4.1 (at least) causing item background to be always drawn : Control.getColor returns a new object every times, so gallery.getBackground() != gallery.getBackground()
Comment 18 Nicolas Richeton CLA 2009-04-24 08:22:23 EDT
Ok, this is not a bug. There is a probably a performance issue here, because every time we paint an item, we create a least 2 Color objects.  100 items visible + animations = 2500 Colors per second. 

Maybe Peter's patch is better after all :)
Comment 19 Boris Bokowski CLA 2009-04-27 22:30:00 EDT
*** Bug 184413 has been marked as a duplicate of this bug. ***
Comment 20 Wim Jongman CLA 2019-12-12 15:56:49 EST
This bug does not have a target milestone assigned and is automatically closed as part of the 2.3.0 release cleanup.

It could be that this bug is accidentally closed for which we apologize.

If this bug is still relevant, please re-open and set a target milestone.