Bug 113160 - DCR ability to reinit a Color instance to reflect system changes
Summary: DCR ability to reinit a Color instance to reflect system changes
Status: CLOSED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Steve Northover CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks: 37456
  Show dependency tree
 
Reported: 2005-10-19 17:16 EDT by Randy Hudson CLA
Modified: 2019-09-04 03:00 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Randy Hudson CLA 2005-10-19 17:16:04 EDT
We have instances of system colors that are being referenced in tons of
paintable objects. Now that we get notification when a system color changes, it
would be nice to be able to update the instance of the Color that referred to
it. This way there is no need to notify tons of objects that are holding onto
the old Color to pick up the new "constant".

An alternative approach is to create a subclass of Color called SystemColor
which is automatically reinitialized whenever the system color changes. Or maybe
a more generic MutableColor subclass.

Of course, a color's changing after it has been set on a widget would have no
affect. This behavior has precedence in Images that are set on buttons or
toolitems (I can't remember which) on GTK. If you update the Image, the widget
is still displays an old copy of the Image.
Comment 1 Steve Northover CLA 2005-11-02 14:32:57 EST
I had considered this but eventually rejected the idea.

>We have instances of system colors that are being referenced in tons
>of paintable objects.

Why not query the color from display when needed?  In that case, there would 
be no need to listen for setting changes and your paintable objects will 
always be right.
Comment 2 Pratik Shah CLA 2005-11-02 18:02:17 EST
(In reply to comment #1)
> Why not query the color from display when needed?  In that case, there would 

That doesn't help for the same reason that invoking canvas.setForeground
(Display.getCurrent().getSystemColor(SWT.COLOR_INFO_FOREGROUND)) would not 
automatically update the foregournd Color later on.

What were your reasons for rejecting this idea, Steve?  Even if you can't 
reinit the Color, SystemColor could use the adapter pattern and act as a 
wrapper that points to the up-to-date Color.  We can't do this ourselves since 
Color is final.
Comment 3 Steve Northover CLA 2005-11-03 11:16:56 EST
Color objects (and other graphics objects for that matter) are not unique.  If 
you set a color into a control and then query it back, depending on the 
control and the platform, you might get then identical color back or an equal
() color.  This means that there can be copies of system colors.

>>That doesn't help for the same reason ...

If you never set a color, the default color is used and will change 
automatically when the theme changes.  I realize that you may have a framework 
in place that prevents you from knowing whether a color should be set or not.
Comment 4 Randy Hudson CLA 2005-11-03 16:32:02 EST
No one has said anything about asking to get the color back from a GC or 
Widget. If you return a different instance and even a different color, it 
doesn't affect our scenario.

Unfortunately, our system color constants are declared on an interface, so they 
are final and can't be updated even with the current notification. We would 
have to break API and make it a class.

Treating system colors specially might be safer than just reinitializing any 
color. on win32, it might look like this:

class GC {
...
public void setForeground(Color color){
   ...
   setPen(color.handle(), -1,-1,-1,-1,data.dashes);
}
...
}

class SystemColor extends Color {
...
int handle() {
  return OS.GetSysColor(sysID);
}
...
}

Of course I have no idea how slow that native method is so it might be a stupid 
idea/non-portable
Comment 5 Randy Hudson CLA 2005-11-03 16:44:20 EST
> Why not query the color from display when needed?  In that case, there would 
> be no need to listen for setting changes and your paintable objects will 
> always be right.

If you have a generic paintable object like a Polygon, etc., there is no easy 
way to set its background to be "query the display for the system's xxx color", 
right? I mean, its color can be red, or it could be widget_background, both are 
just stored in a field typed as Color. For us to do it your way we would have 
to wrapper SWT's color and create the SystemColor concept ourselves. Or we 
could create two fields to store either a color or system "int" identifier.
Comment 6 Steve Northover CLA 2005-11-03 17:27:31 EST
The code you gave won't work in general.  If you set a SystemColor in a widget 
and then query it back, on some platforms, you would get a Color and this 
would no longer be correct.

If you have a field in the polygon that represents the color, don't initialize 
it and always use an accessor.  Inside the accessor, if the color is null, get 
the system color.  If the color is not null, return it.  If someone sets the 
color, they are no longer using the system color.  I have no idea whether this 
would work for you but this is the approach that custom widget writers have 
been using for a while.  It's not great, but it works.
Comment 7 Randy Hudson CLA 2005-11-03 20:18:12 EST
So, a system color might work for us but not for widgets, which don't hold onto 
the java instance. I think the showstopper would be if the widget didn't track 
the system color.

I think the original request is the most reasonable one and it doesn't 
introduce anything too complicated like a mapping of system constants->(widget+ 
fg/bg).
Comment 8 Steve Northover CLA 2005-11-04 10:32:55 EST
Not sure what you mean.  The original request doesn't work.
Comment 9 Randy Hudson CLA 2005-11-04 11:24:45 EST
Why does the original request (the summary) not work? Colors would be exactly 
like Images. If you modify an Image by painting on it, you are only modifying 
that image. If you set the Image on a Button and get it back, it could be a 
different java object and a different resource. Painting on the image after 
setting it to a widget may have no effect. It's the same, no?
Comment 10 Steve Northover CLA 2005-11-04 12:25:24 EST
>If you modify an Image by painting on it, you are only modifying that image.

Depends on the platform and the control.  For example, custom control that 
don't take a copy of the image will be updated.  On Windows, even the native 
controls are different.  Trees and tables take a copy, menu items don't etc.

Hammering a single instance and hoping that no one has any copies seems wrong 
to me.  It's not what the operating systems do and it doesn't work in general 
(although it might work for GEF).

Sorry but I'm going to have to WONTFIX this bug report.
Comment 11 Randy Hudson CLA 2005-11-04 13:27:24 EST
> Hammering a single instance and hoping that no one has any copies seems wrong 
> to me.

OK, but HOW is it different than the Image scenario? It's exactly the same, 
except it's even more consistent whereas the Image scenario varies on each 
platform.
Comment 12 Steve Northover CLA 2005-11-04 13:35:05 EST
Nope.  Both are the same.  If you set a color into some native controls and 
then get it back, you might get back a copy that won't get hammered.
Comment 13 Randy Hudson CLA 2005-11-04 13:43:13 EST
A color is a cross-platform reference to some OS resource. Reinitializing is 
just changing that reference. SWT clients already know that widget.setColor() 
is just a cross-platform way of handing over the current resource, and not the 
java object itself. They must be aware of this for the other reasons you 
mentioned.

This is not GEF-specific. It helps anyone that works with SWT's colors without 
reaching in and grabbing the platform-specific data, which is everyone except 
for widgets. For example, JFace's ColorProvider and ColorDecorator classes. 
Also syntax highlighters, and even StyleRange used by StyledText control.
Comment 14 Randy Hudson CLA 2005-11-04 13:46:12 EST
(In reply to comment #12)
> Nope.  Both are the same.
That's what I said. It's the same. So let clients change a Color just like they 
can currently create a GC on an Image and change the Image. Or as you call it, 
hammering an _Image_ and hoping that no one has any copies.
Comment 15 Steve Northover CLA 2005-11-04 14:20:59 EST
This is the last time I'll try.

Colors are not unique.  There can be 1,000,000 instances of color, each one 
having the same operating system handle.  I don't have a refererence to every 
color that is creates so I can't find all the instances and hammer the handle.
Comment 16 Randy Hudson CLA 2005-11-04 15:25:59 EST
That is not what we are asking you to do and it wouldn't even be the correct 
behavior. Some manually-created colors might happen to have the same handle as 
a system color and it wouldn't make any sense to update them. The scenario is 
for the non-widget world that must hold on to specific instances of colors, 
regardless of whether they have the same handles or not.
Comment 17 Steve Northover CLA 2005-11-04 15:34:31 EST
I have no idea what you are talking about.  Please submit a patch.
Comment 18 Randy Hudson CLA 2005-11-05 11:09:13 EST
I'm not sure I understood your use of "hammer" the first time. I thought you 
were referring to the client making the change to the color. If you meant SWT 
updating the handle for a single color instance, this is all that we are asking 
for. It wouldn't make sense to update copies of the color.

Here's the patch to Color.java:

/**
 * Disposes the current color reference and reinitializes this
 * color using the given values. Equivalent to calling:
 * <pre>dispose();
 * new Color (device, r, g, b);</pre>
 */
public void disposeAndInit(Device device, int r, int g, int b) {
  dispose();
  init(device, r, g, b);
}

/**
 * Used to update a Color that was created using Display#getSystemColor.
 */
public void initSystemColor(Device device, int id) {
  // copy code from Display or refactor it.
}

The first method is exactly the same as calling dispose() on the Color, and 
then creating a new color. The effect on the other 1,000,000 "copies" is the 
same in either case.

The second method is exactly the same as just calling Display.getSystemColor
(int) and garbage collecting the old instance (since disposing isn't necessary).

The only difference in both cases is that the java object is reused.
Comment 19 Steve Northover CLA 2005-11-07 12:05:37 EST
>If you meant SWT updating the handle for a single color instance, this is
>all that we are asking for.

Ok, and I have already described how this does not work in general (while it 
may work for your use of system colors).  Updating a single instance is a 
lie.  Anyone who sets and then queries a color back will be burned.  The new 
instance won't be updated and they will have no idea why their code fails.

WONTFIXTHISEVER.
Comment 20 Randy Hudson CLA 2005-11-07 12:15:31 EST
> Ok, and I have already described how this does not work in general (while it 
> may work for your use of system colors).  Updating a single instance is a 
> lie.

But it's exactly what the proposed API would state, so how is it a lie?

> Anyone who sets and then queries a color back will be burned.  The new 
> instance won't be updated and they will have no idea why their code fails.

Using your exact same scenario, someone who sets and then queries a color back, 
and then disposes the *original* instance, will be "burned" because now they 
have a color with a bogus handle (on 8-bit displays). What is your solution to 
this scenario? There is no solution because it's incorrect usage and it's a 
pointless example.
Comment 21 Randy Hudson CLA 2005-11-07 12:24:48 EST
Actually, having copies of the Color isn't even necessary. There could be 
references to the handle in the native widgets. I could just set the color on a 
TreeItem and the dispose the color. SWT does not go in and repair the reference 
to the handle of the disposed color.

If I set a font on a control and then dispose the Font SWT doesn't go and 
repair references to that handle either.

Or, what if I have a copy of a Font and I dispose the original? Does SWT go in 
and hammer the copies to indicate that the copies are also disposed? No. Try 
the following:

Font font = new Font(display, "Papyrus", 18, SWT.BOLD);
shell.setFont(font);
Font another = shell.getFont();
font.dispose();
System.out.println(another.isDisposed());

Any copies of the Font are completely invalid, just like colors.
Comment 22 Billy Biggs CLA 2005-11-07 12:34:47 EST
I have been trying to follow this conversation but I find it quite confusing. 
Randy, can you please post a patch (like a real one, team > create patch) that
shows what you are proposing?  I find your notes from comment #18 too vague.
Comment 23 Randy Hudson CLA 2005-11-07 12:41:08 EST
(In reply to comment #22)
> I have been trying to follow this conversation but I find it quite confusing. 
> Randy, can you please post a patch (like a real one, team > create patch) that
> shows what you are proposing?  I find your notes from comment #18 too vague.

Any patch I would submit would not involve updating copies of colors. So the 
first step is to convince Steve that NOT updating copies is correct and 
consistent with the way dispose() works for both Fonts and Colors.
Comment 24 Steve Northover CLA 2005-11-07 13:15:11 EST
The other scenarios involving disposing fonts and colors are programming 
errors.  You should not dispose a resource that you did not allocate.
Comment 25 Randy Hudson CLA 2005-11-07 13:40:30 EST
(In reply to comment #24)
> The other scenarios involving disposing fonts and colors are programming 
> errors.  You should not dispose a resource that you did not allocate.

If you look at the code, I am disposing the resource that I created.
Comment 26 Steve Northover CLA 2005-11-07 13:49:12 EST
Your argument went something like "It's wrong for fonts that get disposed, so 
it's ok to get it partially right for system colors".
Comment 27 Randy Hudson CLA 2005-11-07 14:48:31 EST
The argument is a color is a useless java object once its been disposed. So let 
me reuse that object to do something else.
Comment 28 Steve Northover CLA 2005-11-07 15:00:25 EST
Eh?  Once an object is disposed, you can't use it (or reuse it) for anything.
Comment 29 Randy Hudson CLA 2005-11-07 15:25:35 EST
disposed != GCed
Comment 30 Steve Northover CLA 2005-11-07 18:52:00 EST
Once an SWT object with associated operating system resources is disposed, it 
cannot be used (reused) for anything.  The garbage collector doesn't enter 
into it.
Comment 31 Randy Hudson CLA 2005-11-08 13:36:34 EST
So this is the real issue. How important is it that such resource pointers 
be "immutable"? What does it guarantee?
Comment 32 Randy Hudson CLA 2006-01-24 11:17:14 EST
Steve, please reconsider this. We have system colors declared on an interface, which means there is no other way we can update them. Even if we deprecate the interface and create a class to replace it, it still wouldn't help us.
Comment 33 Lars Vogel CLA 2019-09-04 03:00:28 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it and remove the stalebug whiteboard tag. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--