Re: How should one implement a custom window color for a custom window?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
19 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

timrowledge
A couple of months back Eliot asked about this and I have a few minutes to spend to maybe fix it.

I notice that Model>windowColorToUse sends #customWindowColor, which is not implemented. Which would seemingly lead us to expect a debugger but I see some very… interesting code in UserInterfaceTheme where a dNU: is caught and Very Odd Things are done. Ten out of ten for creative and intriguing code, minus several million for completely obscured intent.

At the least it would be nice to have an implementation *somewhere* that explains what is being done, why, and maybe even how we can move to a simpler scheme.

Related things I noticed -
EToys-Squeakland adds Object, StringHolder & TranscriptStream class > windowColorSpecification which seem to be in need of removal.
PreferencesPanel class>windowColorSpecification is seemingly in need of the chop
WindowColorRegistry, the only sender of windowColorSpecification, is in the deprecated categories, though yes, i nthe 5.1 deprecation pile so maybe is has to stay for now.

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Strange OpCodes: WK: Write to Keyboard



Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

marcel.taeumel
Hi Tim,

I am sorry that the core mechanism of the User Interface Themes confuses you. :) The idea of application-specific UI properties, such as window colors, kind of overlaps/interferes with the idea of general widget theming.

If you want to work around the UI theming to provide a window color for your tool, just implement #windowColorToUse. If not, just implement #defaultWindowColor like all other tools in the system do. Try the implementors tool to verify. :-)

It is not that difficult. You already found Model >> #windowColorToUse. Now you can use the Squeak's implementors tool to browse implementors of all the symbols you can find in that method: #( useColorfulWindows customWindowColor defaultWindowColor uniformWindowColor). I suppose that that journey ends after a few minutes when you discover:


Best,
Marcel

Am 16.09.2017 02:00:18 schrieb tim Rowledge <[hidden email]>:

A couple of months back Eliot asked about this and I have a few minutes to spend to maybe fix it.

I notice that Model>windowColorToUse sends #customWindowColor, which is not implemented. Which would seemingly lead us to expect a debugger but I see some very… interesting code in UserInterfaceTheme where a dNU: is caught and Very Odd Things are done. Ten out of ten for creative and intriguing code, minus several million for completely obscured intent.

At the least it would be nice to have an implementation *somewhere* that explains what is being done, why, and maybe even how we can move to a simpler scheme.

Related things I noticed -
EToys-Squeakland adds Object, StringHolder & TranscriptStream class > windowColorSpecification which seem to be in need of removal.
PreferencesPanel class>windowColorSpecification is seemingly in need of the chop
WindowColorRegistry, the only sender of windowColorSpecification, is in the deprecated categories, though yes, i nthe 5.1 deprecation pile so maybe is has to stay for now.

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Strange OpCodes: WK: Write to Keyboard





Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

Hannes Hirzel
In reply to this post by timrowledge
Tim

On 9/16/17, tim Rowledge <[hidden email]> wrote:
> A couple of months back Eliot asked about this and I have a few minutes to
> spend to maybe fix it.

> I notice that Model>windowColorToUse sends #customWindowColor, which is not
> implemented.

There was also an issue earlier this year with the tool 'Extras' menu
, then 'Graphical imports' not following the user interface  theme. A
partial solution was implemented. I'll dig out the details and answer
in the approriate thread.

--Hannes

> Which would seemingly lead us to expect a debugger but I see
> some very… interesting code in UserInterfaceTheme where a dNU: is caught and
> Very Odd Things are done. Ten out of ten for creative and intriguing code,
> minus several million for completely obscured intent.
>
> At the least it would be nice to have an implementation *somewhere* that
> explains what is being done, why, and maybe even how we can move to a
> simpler scheme.
>
> Related things I noticed -
> EToys-Squeakland adds Object, StringHolder & TranscriptStream class >
> windowColorSpecification which seem to be in need of removal.
> PreferencesPanel class>windowColorSpecification is seemingly in need of the
> chop
> WindowColorRegistry, the only sender of windowColorSpecification, is in the
> deprecated categories, though yes, i nthe 5.1 deprecation pile so maybe is
> has to stay for now.
>
> tim
> --
> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
> Strange OpCodes: WK: Write to Keyboard
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

Hannes Hirzel
In reply to this post by marcel.taeumel
Hello Marcel

Thank you for the clarifications about the user interface themes
(UserInterfaceTheme [1]). May we consider this as a start of a
documentation ?

Or is there more from your side?

:-)

Regards

--Hannes

[1] UserInterfaceTheme
http://wiki.squeak.org/squeak/6508

On 9/16/17, Marcel Taeumel <[hidden email]> wrote:

> Hi Tim,
>
> I am sorry that the core mechanism of the User Interface Themes confuses
> you. :) The idea of application-specific UI properties, such as window
> colors, kind of overlaps/interferes with the idea of general widget
> theming.
>
> If you want to work around the UI theming to provide a window color for your
> tool, just implement #windowColorToUse. If not, just implement
> #defaultWindowColor like all other tools in the system do. Try the
> implementors tool to verify. :-)
>
> It is not that difficult. You already found Model >> #windowColorToUse. Now
> you can use the Squeak's implementors tool to browse implementors of all the
> symbols you can find in that method: #( useColorfulWindows customWindowColor
> defaultWindowColor uniformWindowColor). I suppose that that journey ends
> after a few minutes when you discover:
>
>
> Best,
> Marcel
> Am 16.09.2017 02:00:18 schrieb tim Rowledge <[hidden email]>:
> A couple of months back Eliot asked about this and I have a few minutes to
> spend to maybe fix it.
>
> I notice that Model>windowColorToUse sends #customWindowColor, which is not
> implemented. Which would seemingly lead us to expect a debugger but I see
> some very… interesting code in UserInterfaceTheme where a dNU: is caught and
> Very Odd Things are done. Ten out of ten for creative and intriguing code,
> minus several million for completely obscured intent.
>
> At the least it would be nice to have an implementation *somewhere* that
> explains what is being done, why, and maybe even how we can move to a
> simpler scheme.
>
> Related things I noticed -
> EToys-Squeakland adds Object, StringHolder & TranscriptStream class >
> windowColorSpecification which seem to be in need of removal.
> PreferencesPanel class>windowColorSpecification is seemingly in need of the
> chop
> WindowColorRegistry, the only sender of windowColorSpecification, is in the
> deprecated categories, though yes, i nthe 5.1 deprecation pile so maybe is
> has to stay for now.
>
> tim
> --
> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
> Strange OpCodes: WK: Write to Keyboard
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

marcel.taeumel
Hi Hannes,

I wasn't aware of these wiki pages. :) Looks good. Yet, I would rather add more application code examples:

   label color: (self userInterfaceTheme unfocusedLabelColor ifNil: [Color darkGray]).

   (self userInterfaceTheme unfocusedWindowColorModifier ifNil: [ [:color | color darker] ]) value: self paneColorToUse.

   text addAttribute: (TextFontReference toFont: (self userInterfaceTheme font ifNil: [TextStyle defaultFont])).

   (self userInterfaceTheme selectionModifier ifNil: [ [:c | c muchLighter] ]) value: (aButton valueOfProperty: #normalColor).

The code itself is a good documentation, too:
- Look at the tests in UserInterfaceThemeTest.
- Browse senders of #userInterfaceTheme.
- Browse implementors of #setDefaultParameters in conjunction with implementors of #applyUserInterfaceTheme.
- Browse implementors/senders of #themeProperties --- which is part of the update logic during theme switches BUT ALSO a  tool interface for UI-Theme-Design-Tools yet to be implemented. :-D



Programming tools are paramount for understanding code, objects, behavior, .... Especially in a live environment such as Squeak. ;-)

Best,
Marcel 

Am 16.09.2017 13:49:56 schrieb H. Hirzel <[hidden email]>:

Hello Marcel

Thank you for the clarifications about the user interface themes
(UserInterfaceTheme [1]). May we consider this as a start of a
documentation ?

Or is there more from your side?

:-)

Regards

--Hannes

[1] UserInterfaceTheme
http://wiki.squeak.org/squeak/6508

On 9/16/17, Marcel Taeumel wrote:

> Hi Tim,
>
> I am sorry that the core mechanism of the User Interface Themes confuses
> you. :) The idea of application-specific UI properties, such as window
> colors, kind of overlaps/interferes with the idea of general widget
> theming.
>
> If you want to work around the UI theming to provide a window color for your
> tool, just implement #windowColorToUse. If not, just implement
> #defaultWindowColor like all other tools in the system do. Try the
> implementors tool to verify. :-)
>
> It is not that difficult. You already found Model >> #windowColorToUse. Now
> you can use the Squeak's implementors tool to browse implementors of all the
> symbols you can find in that method: #( useColorfulWindows customWindowColor
> defaultWindowColor uniformWindowColor). I suppose that that journey ends
> after a few minutes when you discover:
>
>
> Best,
> Marcel
> Am 16.09.2017 02:00:18 schrieb tim Rowledge :
> A couple of months back Eliot asked about this and I have a few minutes to
> spend to maybe fix it.
>
> I notice that Model>windowColorToUse sends #customWindowColor, which is not
> implemented. Which would seemingly lead us to expect a debugger but I see
> some very… interesting code in UserInterfaceTheme where a dNU: is caught and
> Very Odd Things are done. Ten out of ten for creative and intriguing code,
> minus several million for completely obscured intent.
>
> At the least it would be nice to have an implementation *somewhere* that
> explains what is being done, why, and maybe even how we can move to a
> simpler scheme.
>
> Related things I noticed -
> EToys-Squeakland adds Object, StringHolder & TranscriptStream class >
> windowColorSpecification which seem to be in need of removal.
> PreferencesPanel class>windowColorSpecification is seemingly in need of the
> chop
> WindowColorRegistry, the only sender of windowColorSpecification, is in the
> deprecated categories, though yes, i nthe 5.1 deprecation pile so maybe is
> has to stay for now.
>
> tim
> --
> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
> Strange OpCodes: WK: Write to Keyboard
>
>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

timrowledge
In reply to this post by marcel.taeumel

> On 16-09-2017, at 2:40 AM, Marcel Taeumel <[hidden email]> wrote:
>
> Hi Tim,
>
> I am sorry that the core mechanism of the User Interface Themes confuses you. :)

Ah, it’s just the price of getting old and senile. You young whipper-snappers just don’t understand. Now git orff moi lawn!

> The idea of application-specific UI properties, such as window colors, kind of overlaps/interferes with the idea of general widget theming.

I don’t have any problem with your theming as such; it’s a jolly good thing. It’s the non-implemented #customWindowColor message and the sneaky (not necessarily bad, but hard to find, follow and document) usurpation of dNU: that bothers me a bit. Instead of trapping a fairly crucial system error doohickey and performing unnatural acts upon its person why wouldn’t you just implement #customWindowColor in UserInterfaceTheme ?


tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Strange OpCodes: OKP: On your Knees and Pray!



Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

marcel.taeumel
Well, the class UserInterfaceTheme is independent from Morphic. It belongs to the system. Kind of a more fancy version of Preferences with a slight tendency towards visuals only instead of "interaction stuff".

Best,
Marcel

Am 16.09.2017 20:05:23 schrieb tim Rowledge <[hidden email]>:


> On 16-09-2017, at 2:40 AM, Marcel Taeumel wrote:
>
> Hi Tim,
>
> I am sorry that the core mechanism of the User Interface Themes confuses you. :)

Ah, it’s just the price of getting old and senile. You young whipper-snappers just don’t understand. Now git orff moi lawn!

> The idea of application-specific UI properties, such as window colors, kind of overlaps/interferes with the idea of general widget theming.

I don’t have any problem with your theming as such; it’s a jolly good thing. It’s the non-implemented #customWindowColor message and the sneaky (not necessarily bad, but hard to find, follow and document) usurpation of dNU: that bothers me a bit. Instead of trapping a fairly crucial system error doohickey and performing unnatural acts upon its person why wouldn’t you just implement #customWindowColor in UserInterfaceTheme ?


tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Strange OpCodes: OKP: On your Knees and Pray!





Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

Stéphane Rollandin
In reply to this post by marcel.taeumel
Nice informative post, thanks Marcel.

I think I see something fragile in the implementation though: each
#userInterfaceTheme send must absolutely be followed by another
selector, else the relevant stacked object (in the scope inst. var. of
the theme) will not be popped at the proper moment.

In other words, a line of code as simple as

        Morph new userInterfaceTheme explore

may break things in potentially ugly ways; for one thing, even if
further scope push/pop work properly, the Morph instanciated by the
above code will never be GCed...

Does that make sense?


Stef

Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

Chris Muller-3
That's true.  One goal of the design was to provide access to a
first-class Theme object, without needing to either write, nor see,
that extra level of indirection in the code.

   myMorph userInterfaceTheme color

vs.

   (myMorph userInterfaceTheme propertyNamed: #color)

The latter becomes a wordy and repetitious (not to mention, the extra
parenthesis), a lot to ask clients to sprinkle throughout their code.

I don't see the example "never being GC'd" as being related to the
UserInterfaceTheme implementation.  I may be missing your question but
-- if an explorer is opened [substitute with any case of:  user still
needs the object], the object would not be GC'd, regardless from which
code it was opened.

 - Chris

On Sun, Sep 17, 2017 at 7:02 AM, Stéphane Rollandin
<[hidden email]> wrote:

> Nice informative post, thanks Marcel.
>
> I think I see something fragile in the implementation though: each
> #userInterfaceTheme send must absolutely be followed by another selector,
> else the relevant stacked object (in the scope inst. var. of the theme) will
> not be popped at the proper moment.
>
> In other words, a line of code as simple as
>
>         Morph new userInterfaceTheme explore
>
> may break things in potentially ugly ways; for one thing, even if further
> scope push/pop work properly, the Morph instanciated by the above code will
> never be GCed...
>
> Does that make sense?
>
>
> Stef
>

Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

marcel.taeumel
In reply to this post by Stéphane Rollandin
Hi Stef,

such fragility should usually be discovered quickly by the progarmmer that tries something like this. So, this is not considered an issue for bigger projects. Since Squeak is an interactive environment, the feedback loop is very short in this regard.

As for your GC concerns: Can you construct a more elaborate example? If your environment experiences a severe memory issue, you should just try to clean-up the system like in the release process:

UserInterfaceTheme cleanUp: true.

or

Smalltalk cleanUp: true.

Since the "cope" instVar is local to a specific instance of UserInterfaceTheme, programmers can easily fix any issues there. One could also add a test case for that to improve usability. :)

Best,
Marcel

Am 17.09.2017 14:04:21 schrieb Stéphane Rollandin <[hidden email]>:

Nice informative post, thanks Marcel.

I think I see something fragile in the implementation though: each
#userInterfaceTheme send must absolutely be followed by another
selector, else the relevant stacked object (in the scope inst. var. of
the theme) will not be popped at the proper moment.

In other words, a line of code as simple as

Morph new userInterfaceTheme explore

may break things in potentially ugly ways; for one thing, even if
further scope push/pop work properly, the Morph instanciated by the
above code will never be GCed...

Does that make sense?


Stef



Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

Stéphane Rollandin
> As for your GC concerns: Can you construct a more elaborate example? If
> your environment experiences a severe memory issue, you should just try
> to clean-up the system like in the release process:

I have no problem in my images, it's just by perusing the code that I
saw that #userInterfaceTheme requires a specific handling.

What worries me is not the normal usage of #userInterfaceTheme, which
works fine, it is how technically easy it is to mess things up, although
I do not see that happening too often or at all actually. But if it
happens sometime, somewhere, it will be a silent bug difficult to diagnose.

BTW I see that the #cleanUp: method will indeed reset all stacks in
hard-coded subclasses of UserInterfaceTheme, but it will not do so for
possibly existing other subclasses. So if I create my own
MuOInterfaceTheme for example, I will also need to monkey-patch
#cleanUp:.. Maybe we should iterate long #allSubclasses?

Stef

Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

marcel.taeumel
Well, "Smalltalk cleanUp:except:" does exactly that, it iterates over all classes. :-) The call "UserInterfaceTheme cleanUp: true" was just an ad-hoc, oversimplified example for programmers to try out.

I just added a new test for the themes. If the integrity of a theme is broken, one can just browse all senders of #userInterfaceTheme and debug. I claim that it is quite simple to diagnose. :)

Best,
Marcel

Am 18.09.2017 11:12:52 schrieb Stéphane Rollandin <[hidden email]>:

> As for your GC concerns: Can you construct a more elaborate example? If
> your environment experiences a severe memory issue, you should just try
> to clean-up the system like in the release process:

I have no problem in my images, it's just by perusing the code that I
saw that #userInterfaceTheme requires a specific handling.

What worries me is not the normal usage of #userInterfaceTheme, which
works fine, it is how technically easy it is to mess things up, although
I do not see that happening too often or at all actually. But if it
happens sometime, somewhere, it will be a silent bug difficult to diagnose.

BTW I see that the #cleanUp: method will indeed reset all stacks in
hard-coded subclasses of UserInterfaceTheme, but it will not do so for
possibly existing other subclasses. So if I create my own
MuOInterfaceTheme for example, I will also need to monkey-patch
#cleanUp:.. Maybe we should iterate long #allSubclasses?

Stef



Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

Stéphane Rollandin
In reply to this post by Chris Muller-3
> I don't see the example "never being GC'd" as being related to the
> UserInterfaceTheme implementation.  I may be missing your question but

Oh, easy to check: just do

      100 timesRepeat: [Morph new userInterfaceTheme yourself].

then

      UserInterfaceTheme current explore

... you will see all 100 instances of Morph in the stack.


Stef

Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

Stéphane Rollandin
In reply to this post by marcel.taeumel
> UserInterfaceTheme cleanUp: true.
>
> or
>
> Smalltalk cleanUp: true.


Hmm I did:

100 timesRepeat: [Morph new userInterfaceTheme yourself].
UserInterfaceTheme cleanUp: true.
Smalltalk cleanUp: true.
UserInterfaceTheme current explore

... the scope stack was still populated.


Stef

Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

marcel.taeumel
Thank you for this bug report. :)

The current clean-up strategy is to dismiss existing instances of UserInterfaceTheme. In your example, the current theme was not touched and is still active. That is, your environment as an active theme that is not in the list "UserInterfaceTheme allThemes". The release building process usually picks a new theme after the clean-up, which your example did not.

Anyway, I will fix the test to also consider the currently active theme. ;-)

Best,
Marcel

Am 18.09.2017 11:23:18 schrieb Stéphane Rollandin <[hidden email]>:

> UserInterfaceTheme cleanUp: true.
>
> or
>
> Smalltalk cleanUp: true.


Hmm I did:

100 timesRepeat: [Morph new userInterfaceTheme yourself].
UserInterfaceTheme cleanUp: true.
Smalltalk cleanUp: true.
UserInterfaceTheme current explore

... the scope stack was still populated.


Stef



Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

Stéphane Rollandin
In reply to this post by marcel.taeumel
> I just added a new test for the themes. If the integrity of a theme is
> broken, one can just browse all senders of #userInterfaceTheme and
> debug. I claim that it is quite simple to diagnose. :)

I am not too concerned by having the integrity of a theme broken. What I
see more likely is objects accumulating silently in the stack until this
becomes a problem.

Stef

Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

marcel.taeumel
Uh-oh. I broke this list conversation by accident. I did not notice. This is what happened:

Me: It is only a single global state/entry point. If tests can point you to this problem, then it should be easy to clean up resp. fix.

Stef: Ok I see what you mean but I think we talk past each other. In my opinion, we should not expect the developer to be super good at catching things like this, we should instead make it difficult for anyone (that is, not-so-good programmers) that simply uses the API to break something. The API should be foolproof.

Me: I basically agree. Yet, there is no such thing as "fool-proof" API in a dynamic system such as Squeak/Smalltalk. We can only provide tools that help discover mistakes and inconsistencies. ;-) It remains a trade-off. As Chris mentioned before, we have the priority of code readability. DNU + tools still looks like a good trade-off to me.

---

Well, I am aware that my system knowledge makes it difficult to anticipate some user challenges. Nevertheless, I want to emphasize the fact that the system is full of trade-offs and that the programming language alone cannot solve all issues. Tools matter. 

Considering memory leaks, they can happen. We need tools to detect them. Maybe domain-specific ones, maybe generic ones.

Considering Squeak's image concept in general: I think we really need more ideas on how to manage object state in the long term. A sole focus on code (artifacts) and bootstrapping techniques seems wrong to me. :)

Btw: Tobias just mentioned that the combination of Object >> #userInterfaceTheme and UserInterfaceTheme >> #doesNotUnderstand: kind of implements higher-order messaging (HOM). :D

Best,
Marcel

Am 18.09.2017 11:33:13 schrieb Stéphane Rollandin <[hidden email]>:

> I just added a new test for the themes. If the integrity of a theme is
> broken, one can just browse all senders of #userInterfaceTheme and
> debug. I claim that it is quite simple to diagnose. :)

I am not too concerned by having the integrity of a theme broken. What I
see more likely is objects accumulating silently in the stack until this
becomes a problem.

Stef



Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

timrowledge
If performance is an issue (as appears to be the case from the comment in #getViaSuperclasses:) I’d anticipate that it might be worth explicitly implementing frequently used messages such as borderColor, customWindowColor etc along the lines of
borderColor
  ^[self get: scope top class->#borderColor] ensure:[scope pop]
… in order to avoid the time cost of the whole dNU: dance.


tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Strange OpCodes: RCR: Rewind Card Reader



Reply | Threaded
Open this post in threaded view
|

Re: How should one implement a custom window color for a custom window?

Chris Muller-3
When I first encountered the DNU implementation, I also thought it
would be a performance issue, but then I ran some benchmarks and found
it actually isn't.

On Mon, Sep 18, 2017 at 6:50 PM, tim Rowledge <[hidden email]> wrote:

> If performance is an issue (as appears to be the case from the comment in #getViaSuperclasses:) I’d anticipate that it might be worth explicitly implementing frequently used messages such as borderColor, customWindowColor etc along the lines of
> borderColor
>   ^[self get: scope top class->#borderColor] ensure:[scope pop]
> … in order to avoid the time cost of the whole dNU: dance.
>
>
> tim
> --
> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
> Strange OpCodes: RCR: Rewind Card Reader
>
>
>