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

Bug 302918

Summary: ToolItem setDisabledImage isn't used
Product: [Eclipse Project] Platform Reporter: Philipp Kursawe <phil.kursawe>
Component: SWTAssignee: Eric Williams <ericwill>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: eclipse.felipe, ericwill, gheorghe, loskutov, lshanmug, pwebster, remy.suen, Silenio_Quarti
Version: 3.6Keywords: triaged
Target Milestone: 4.14 RC1Flags: lshanmug: review+
Hardware: PC   
OS: Linux-GTK   
See Also: https://git.eclipse.org/r/149861
https://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=832213bb5bbc69bf725090388a341e391b16f27e
https://git.eclipse.org/r/149915
https://git.eclipse.org/c/www.eclipse.org/eclipse/news.git/commit/?id=514a9397f42ba9b0efc88f391d02880a6a6f23c9
https://bugs.eclipse.org/bugs/show_bug.cgi?id=551586
https://git.eclipse.org/r/152649
https://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=d55af1c18f895e76223f6eb1d61e49dc8196d582
https://git.eclipse.org/r/152962
https://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=076c8373de27a918ae94e3a6b29303af6ba615c6
https://bugs.eclipse.org/bugs/show_bug.cgi?id=563407
Whiteboard: RHT
Bug Depends on:    
Bug Blocks: 551318, 551319    
Attachments:
Description Flags
SWT Snippet reproducing the problem
none
nav images the snippet uses
none
Image of the created toolbar none

Description Philipp Kursawe CLA 2010-02-16 03:03:52 EST
I recently had a disabled handler for a command that also provided icon in the commandImages extension point. However, the disabled icon was not honored by the toolbar item, and instead Eclipse drew its own clumsy icon derived from the normal one. Setting the disabled icon directly on the toolbar contribution worked.
Comment 1 Paul Webster CLA 2010-02-19 12:54:17 EST
Hmmm, the CCI code should be asking for the disabled image using a iconStyle of IMAGE_STYLE_TOOLBAR.

if there's only one disabledImage registered for that command then it should have been returned early in getImageDescriptor(final String commandId, final int type, final String style).

I'll investigate.

PW
Comment 2 Paul Webster CLA 2011-01-06 09:37:21 EST
It's using the correct images ... SWT is not honouring them.

PW
Comment 3 Paul Webster CLA 2011-01-06 09:38:09 EST
Created attachment 186167 [details]
SWT Snippet reproducing the problem
Comment 4 Paul Webster CLA 2011-01-06 09:39:01 EST
Created attachment 186168 [details]
nav images the snippet uses
Comment 5 Paul Webster CLA 2011-01-06 09:41:40 EST
Created attachment 186169 [details]
Image of the created toolbar

The code looks like:

item1.setImage(nav);
item1.setDisabledImage(nav_dis);

item2.setImage(nav_dis);
item2.setDisabledImage(nav);

item3.setImage(nav);
item3.setDisabledImage(nav_dis);
item3.setEnabled(false);

item4.setImage(nav_dis);
item4.setDisabledImage(nav);
item4.setEnabled(false);

The images I expected were:
nav nav_dis nav_dis nav

PW
Comment 6 Paul Webster CLA 2011-01-06 09:42:56 EST
My tests were on 3.7  I20110104-0920

PW
Comment 7 Felipe Heidrich CLA 2011-01-07 16:53:11 EST
What platform are testing on ?

It worked for me on Windows 7 and XP.
The only code change I did was:
Image nav = new Image (display, "JavaCode/next_nav.gif");
Image nav_dis = new Image(display, "JavaCode/next_nav_dis.gif");
(removed ImageDescriptor)
Comment 8 Paul Webster CLA 2011-01-10 07:22:49 EST
(In reply to comment #7)
> What platform are testing on ?

When I ran my tests, it was on linux-gtk:

gtk2-2.18.9-4.el6.x86_64

PW
Comment 9 Felipe Heidrich CLA 2011-01-10 11:23:51 EST
Right, 

ToolItem#setDisabledImage () is not implemented in GTK.
Comment 10 Paul Webster CLA 2011-01-10 11:26:21 EST
Phil, could you run my SWT attachment in your system where you reported the problem?

Silenio, if there's already a bug for the SWT/Linux/setDisabledImage(*) problem, please just send this bug back to Platform/UI.

PW
Comment 11 Silenio Quarti CLA 2011-01-11 10:09:46 EST
I could not find another swt bug, so we are keeping this one.
Comment 12 Eric Williams CLA 2016-10-18 16:43:18 EDT
This issue is still reproducible.
Comment 14 Eric Williams CLA 2019-09-19 16:29:14 EDT
(In reply to Eclipse Genie from comment #13)
> Gerrit change https://git.eclipse.org/r/149861 was merged to [master].
> Commit:
> http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/
> ?id=832213bb5bbc69bf725090388a341e391b16f27e

In master now. I'll prepare a N&N entry tomorrow.
Comment 15 Eclipse Genie CLA 2019-09-20 11:17:27 EDT
New Gerrit change created: https://git.eclipse.org/r/149915
Comment 17 Eric Williams CLA 2019-09-20 11:23:59 EDT
(In reply to Eclipse Genie from comment #16)
> Gerrit change https://git.eclipse.org/r/149915 was merged to [master].
> Commit:
> http://git.eclipse.org/c/www.eclipse.org/eclipse/news.git/commit/
> ?id=514a9397f42ba9b0efc88f391d02880a6a6f23c9

N&N entry done.
Comment 18 Eric Williams CLA 2019-10-08 13:26:30 EDT
Verified in I20191008-0600.
Comment 19 Andrey Loskutov CLA 2019-11-14 04:58:32 EST
(In reply to Eclipse Genie from comment #13)
> Gerrit change https://git.eclipse.org/r/149861 was merged to [master].
> Commit:
> http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/
> ?id=832213bb5bbc69bf725090388a341e391b16f27e

This one (together with patch for bug 551586) causes regression described in bug 551586 comment 11.

I believe I have a patch.
Comment 20 Eclipse Genie CLA 2019-11-14 05:05:36 EST
New Gerrit change created: https://git.eclipse.org/r/152649
Comment 21 Lakshmi P Shanmugam CLA 2019-11-14 06:43:52 EST
@Eric,
I was looking at why the new ToolItem.test_setDisabledImage() test was failing on Mac. The test expects item.getImage() to return the disabled image when item is disabled which doesn't look right.
On Windows and Mac: 
item.getImage() returns the image set by item.setImage()
item.getDisabledImage() returns the image set by item.setDisabledImage(). The enabled state of the item doesn't affect the return value of item.setImage().

Essentially, when the item is disabled, the image on the widget needs be updated but Item.image should not be changed to the disabled image.
Comment 22 Andrey Loskutov CLA 2019-11-14 06:45:39 EST
(In reply to Lakshmi Shanmugam from comment #21)
> @Eric,
> I was looking at why the new ToolItem.test_setDisabledImage() test was
> failing on Mac. The test expects item.getImage() to return the disabled
> image when item is disabled which doesn't look right.
> On Windows and Mac: 
> item.getImage() returns the image set by item.setImage()
> item.getDisabledImage() returns the image set by item.setDisabledImage().
> The enabled state of the item doesn't affect the return value of
> item.setImage().
> 
> Essentially, when the item is disabled, the image on the widget needs be
> updated but Item.image should not be changed to the disabled image.

Lakshmi, could you please check my patch on Mac: https://git.eclipse.org/r/152649
Comment 23 Andrey Loskutov CLA 2019-11-14 07:03:07 EST
BTW, Console view shows also the problem: the drop-down button "Display selected console" is also "blank" if disabled (== only one console is shown).
Comment 24 Lakshmi P Shanmugam CLA 2019-11-14 07:08:47 EST
> Lakshmi, could you please check my patch on Mac:
> https://git.eclipse.org/r/152649

@Andrey, I checked the patch, it still fails on Mac. Item.getImage() is not expected to return the disabled image even if the item is disabled, so the test will not work.

> Essentially, when the item is disabled, the image on the widget needs be
> updated but Item.image should not be changed to the disabled image.
I think modifying the code based on this could fix the problem you mentioned in comment#19.
Comment 25 Andrey Loskutov CLA 2019-11-14 07:15:40 EST
(In reply to Lakshmi Shanmugam from comment #24)
> > Lakshmi, could you please check my patch on Mac:
> > https://git.eclipse.org/r/152649
> 
> @Andrey, I checked the patch, it still fails on Mac. Item.getImage() is not
> expected to return the disabled image even if the item is disabled, so the
> test will not work.

Thanks, so it is a different problem as mine.

> > Essentially, when the item is disabled, the image on the widget needs be
> > updated but Item.image should not be changed to the disabled image.

Not sure I can follow. This bug is initially about using "better" disabled images, if one is provided. So you say it is not OK? Is this a test-only issue? But org.eclipse.swt.tests.junit.Test_org_eclipse_swt_widgets_ToolItem.test_setDisabledImage() is already GTK only?

> I think modifying the code based on this could fix the problem you mentioned
> in comment#19.

https://git.eclipse.org/r/152649 fixes my problem already.
Comment 27 Lakshmi P Shanmugam CLA 2019-11-14 23:42:01 EST
(In reply to Andrey Loskutov from comment #25)
> > > Essentially, when the item is disabled, the image on the widget needs be
> > > updated but Item.image should not be changed to the disabled image.
> 
> Not sure I can follow. This bug is initially about using "better" disabled
> images, if one is provided. So you say it is not OK?

setDisabledImage() shouldn't call setImage() because it modifies Item.image to the disabled image. It should only update the image on ToolItem without modifying the Item.image field.

> Is this a test-only issue? But
> org.eclipse.swt.tests.junit.Test_org_eclipse_swt_widgets_ToolItem.
> test_setDisabledImage() is already GTK only?

The test is GTK only as it fails on Windows and Mac. The test incorrectly expects getImage() to return the disabled image when the item is disabled. getImage() always returns the image set by setImage().

> > I think modifying the code based on this could fix the problem you mentioned
> > in comment#19.
> 
> https://git.eclipse.org/r/152649 fixes my problem already.

I think modifying the code in setDisabledImage() to update the image without calling setImage() will fix the problem.
Comment 28 Andrey Loskutov CLA 2019-11-15 04:08:08 EST
(In reply to Lakshmi Shanmugam from comment #27)
> (In reply to Andrey Loskutov from comment #25)
> > > > Essentially, when the item is disabled, the image on the widget needs be
> > > > updated but Item.image should not be changed to the disabled image.
> > 
> > Not sure I can follow. This bug is initially about using "better" disabled
> > images, if one is provided. So you say it is not OK?
> 
> setDisabledImage() shouldn't call setImage() because it modifies Item.image
> to the disabled image. It should only update the image on ToolItem without
> modifying the Item.image field.

OK, thanks, now I see that we have there more then one "enabled" image :-)

@Eric, I haven't looked deeper (my problem from comment 19 is fixed via I20191114-1800), but it sounds that the original patch breaks some ToolItem vs Item semantics I do not understand fully yet. Could you please check this?
Comment 29 Eric Williams CLA 2019-11-15 09:33:51 EST
(In reply to Andrey Loskutov from comment #28)
> (In reply to Lakshmi Shanmugam from comment #27)
> > (In reply to Andrey Loskutov from comment #25)
> > > > > Essentially, when the item is disabled, the image on the widget needs be
> > > > > updated but Item.image should not be changed to the disabled image.
> > > 
> > > Not sure I can follow. This bug is initially about using "better" disabled
> > > images, if one is provided. So you say it is not OK?
> > 
> > setDisabledImage() shouldn't call setImage() because it modifies Item.image
> > to the disabled image. It should only update the image on ToolItem without
> > modifying the Item.image field.
> 
> OK, thanks, now I see that we have there more then one "enabled" image :-)
> 
> @Eric, I haven't looked deeper (my problem from comment 19 is fixed via
> I20191114-1800), but it sounds that the original patch breaks some ToolItem
> vs Item semantics I do not understand fully yet. Could you please check this?

I'll take a look today.
Comment 30 Eric Williams CLA 2019-11-15 09:56:04 EST
(In reply to Lakshmi Shanmugam from comment #27)
> setDisabledImage() shouldn't call setImage() because it modifies Item.image
> to the disabled image. It should only update the image on ToolItem without
> modifying the Item.image field.


Let's say this happens:

toolItem.setImage(a)
toolItem.setDisabledImage(b)
toolItem.setEnabled(false)

a client who then calls toolItem.getImage() should expect image "a"? Even if the receiver is displaying image "b"?
Comment 31 Lakshmi P Shanmugam CLA 2019-11-15 12:52:35 EST
(In reply to Eric Williams from comment #30)
> (In reply to Lakshmi Shanmugam from comment #27)
> > setDisabledImage() shouldn't call setImage() because it modifies Item.image
> > to the disabled image. It should only update the image on ToolItem without
> > modifying the Item.image field.
> 
> 
> Let's say this happens:
> 
> toolItem.setImage(a)
> toolItem.setDisabledImage(b)
> toolItem.setEnabled(false)
> 
> a client who then calls toolItem.getImage() should expect image "a"? Even if
> the receiver is displaying image "b"?

Yes. getImage() should just return the image set by setImage() not the image displayed by the receiver. On Windows and Mac too, it has been implemented this way.
Comment 32 Eric Williams CLA 2019-11-15 13:24:53 EST
(In reply to Lakshmi Shanmugam from comment #31)
> (In reply to Eric Williams from comment #30)
> > (In reply to Lakshmi Shanmugam from comment #27)
> > > setDisabledImage() shouldn't call setImage() because it modifies Item.image
> > > to the disabled image. It should only update the image on ToolItem without
> > > modifying the Item.image field.
> > 
> > 
> > Let's say this happens:
> > 
> > toolItem.setImage(a)
> > toolItem.setDisabledImage(b)
> > toolItem.setEnabled(false)
> > 
> > a client who then calls toolItem.getImage() should expect image "a"? Even if
> > the receiver is displaying image "b"?
> 
> Yes. getImage() should just return the image set by setImage() not the image
> displayed by the receiver. On Windows and Mac too, it has been implemented
> this way.

The Javadoc for Item.getImage() reads:

"Returns the receiver's image if it has one, or null if it does not."

This implies that the image returned by getImage() is the image that is displayed by the receiver, no? Are there other cases in SWT similar to this? It seems incorrect to me that a client should have to check the state of a widget before querying the image it is displaying.
Comment 33 Lakshmi P Shanmugam CLA 2019-11-18 05:33:37 EST
(In reply to Eric Williams from comment #32)
> 
> The Javadoc for Item.getImage() reads:
> 
> "Returns the receiver's image if it has one, or null if it does not."
> 
> This implies that the image returned by getImage() is the image that is
> displayed by the receiver, no?

I agree that it could imply that for most Widgets because in general there is only one image to be displayed, the one set by setImage(). 
But, in case of ToolItem, it can display either one of the 3 images: enabled, disabled and hot. To avoid confusion and to be able to access all the 3 images irrespective of widget state, we have 3 pairs of APIs get/setImage, get/setDisabledImage and get/setHotImage.
This javadoc is in Item class, if it helps we could override and improve the javadoc of ToolItem.getItem().

> Are there other cases in SWT similar to this?
AFAIK the only other Widget that has an API to disabled image is CTabItem, it's deprecated but is similar in implementation.

> It seems incorrect to me that a client should have to check the state of a
> widget before querying the image it is displaying.
It's just not enabled or disabled image, the displayed image could also be the hot image. :)

Item.getImage() is an existing API. From the Windows and Mac implementation, the getImage() API was designed to return the image set by setImage(). GTK's implementation should be consistent here. 

The bigger problem is that the current GTK implementation of setDisabledImage() breaks the Item.getImage() API.
For example: Some existing client code that uses ToolItem.getImage() and depends on the behaviour to return 'enabled' image irrespective of the state, will now get *either* the 'enabled' or 'disabled' image based on the enabled state.

If you think it's important for the tests or if there is a client request, we can create a new API to return the image being displayed.
Comment 34 Eric Williams CLA 2019-11-18 10:19:16 EST
(In reply to Lakshmi Shanmugam from comment #33)
> (In reply to Eric Williams from comment #32)
> > 
> > The Javadoc for Item.getImage() reads:
> > 
> > "Returns the receiver's image if it has one, or null if it does not."
> > 
> > This implies that the image returned by getImage() is the image that is
> > displayed by the receiver, no?
> 
> I agree that it could imply that for most Widgets because in general there
> is only one image to be displayed, the one set by setImage(). 
> But, in case of ToolItem, it can display either one of the 3 images:
> enabled, disabled and hot. To avoid confusion and to be able to access all
> the 3 images irrespective of widget state, we have 3 pairs of APIs
> get/setImage, get/setDisabledImage and get/setHotImage.
> This javadoc is in Item class, if it helps we could override and improve the
> javadoc of ToolItem.getItem().

Do you mean ToolItem.getImage()?


> > It seems incorrect to me that a client should have to check the state of a
> > widget before querying the image it is displaying.
> It's just not enabled or disabled image, the displayed image could also be
> the hot image. :)
> 
> Item.getImage() is an existing API. From the Windows and Mac implementation,
> the getImage() API was designed to return the image set by setImage(). GTK's
> implementation should be consistent here. 
> 
> The bigger problem is that the current GTK implementation of
> setDisabledImage() breaks the Item.getImage() API.
> For example: Some existing client code that uses ToolItem.getImage() and
> depends on the behaviour to return 'enabled' image irrespective of the
> state, will now get *either* the 'enabled' or 'disabled' image based on the
> enabled state.

IMO just because things have been done a certain way in the past doesn't mean it's the right way. If we are going to change GTK's ToolItem.setDisabledImage() behaviour back to what Mac/Windows do then the Javadocs should be modified -- it's far too ambiguous as it's written right now. A client shouldn't have to guess which image they are going to get when calling something generic like "getImage", especially when the Javadocs are equally ambiguous.

 
> If you think it's important for the tests or if there is a client request,
> we can create a new API to return the image being displayed.

As it's written right now, I would expect Item.getImage() to return this. Adding additional API seems redundant.
Comment 35 Lakshmi P Shanmugam CLA 2019-11-18 12:26:04 EST
(In reply to Eric Williams from comment #34)
> (In reply to Lakshmi Shanmugam from comment #33)
> > (In reply to Eric Williams from comment #32)
> > > 
> > > The Javadoc for Item.getImage() reads:
> > > 
> > > "Returns the receiver's image if it has one, or null if it does not."
> > > 
> > > This implies that the image returned by getImage() is the image that is
> > > displayed by the receiver, no?
> > 
> > I agree that it could imply that for most Widgets because in general there
> > is only one image to be displayed, the one set by setImage(). 
> > But, in case of ToolItem, it can display either one of the 3 images:
> > enabled, disabled and hot. To avoid confusion and to be able to access all
> > the 3 images irrespective of widget state, we have 3 pairs of APIs
> > get/setImage, get/setDisabledImage and get/setHotImage.
> > This javadoc is in Item class, if it helps we could override and improve the
> > javadoc of ToolItem.getItem().
> 
> Do you mean ToolItem.getImage()?
Sorry, yes.
> 
> 
> > > It seems incorrect to me that a client should have to check the state of a
> > > widget before querying the image it is displaying.
> > It's just not enabled or disabled image, the displayed image could also be
> > the hot image. :)
> > 
> > Item.getImage() is an existing API. From the Windows and Mac implementation,
> > the getImage() API was designed to return the image set by setImage(). GTK's
> > implementation should be consistent here. 
> > 
> > The bigger problem is that the current GTK implementation of
> > setDisabledImage() breaks the Item.getImage() API.
> > For example: Some existing client code that uses ToolItem.getImage() and
> > depends on the behaviour to return 'enabled' image irrespective of the
> > state, will now get *either* the 'enabled' or 'disabled' image based on the
> > enabled state.
> 
> IMO just because things have been done a certain way in the past doesn't
> mean it's the right way. 
Honestly, I can't see what is wrong with the API. However, I would not like to debate further if it's right or not.
What matters is that we can't change behaviour of existing API (ToolItem.getImage()) as it can break client code.

> If we are going to change GTK's
> ToolItem.setDisabledImage() behaviour back to what Mac/Windows do then the
> Javadocs should be modified -- it's far too ambiguous as it's written right
> now. A client shouldn't have to guess which image they are going to get when
> calling something generic like "getImage", especially when the Javadocs are
> equally ambiguous.
> 
Yes, I agree. I suggested the same in above comment.
Comment 36 Eric Williams CLA 2019-11-18 13:00:03 EST
Okay I'll prepare something for RC1.
Comment 37 Eclipse Genie CLA 2019-11-19 09:23:35 EST
New Gerrit change created: https://git.eclipse.org/r/152962
Comment 39 Andrey Loskutov CLA 2019-11-25 07:05:53 EST
(In reply to Eclipse Genie from comment #38)
> Gerrit change https://git.eclipse.org/r/152962 was merged to [master].
> Commit:
> http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/
> ?id=076c8373de27a918ae94e3a6b29303af6ba615c6

Shouldn't this have +1 approval from the project lead first?
Comment 40 Eric Williams CLA 2019-11-25 09:15:13 EST
(In reply to Andrey Loskutov from comment #39)
> (In reply to Eclipse Genie from comment #38)
> > Gerrit change https://git.eclipse.org/r/152962 was merged to [master].
> > Commit:
> > http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/
> > ?id=076c8373de27a918ae94e3a6b29303af6ba615c6
> 
> Shouldn't this have +1 approval from the project lead first?

Lakshmi is project co-lead for SWT, so no further approval needed IIRC.
Comment 41 Lakshmi P Shanmugam CLA 2019-11-25 12:16:18 EST
In reply to Eclipse Genie from comment #38)
> Gerrit change https://git.eclipse.org/r/152962 was merged to [master].
> Commit:
> http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=076c8373de27a918ae94e3a6b29303af6ba615c6
> 

Thanks Eric for the fix!
Comment 42 Eric Williams CLA 2019-11-26 11:50:57 EST
(In reply to Lakshmi Shanmugam from comment #41)
> Thanks Eric for the fix!

No problem! Verified in I20191126-0600.