Hi, there! :-)
TL;DR: Here is a SAR file that cleans up the code of all widget classes such as lists and buttons in your image and adds support for UI theming as well as a bunch of UI themes (choose Themes via "Extras > Themes & Colors"): squeak_trunk_uitheme_v12.sar http://forum.world.st/file/n4908439/squeak_trunk_uitheme_v12.sar
Here is a preview: http://i.giphy.com/l46CcX46yRE9H6yQ0.gif
*Try it out. Report bugs. Report performance issues!!* We will commit the changes to trunk this Saturday.
Btw: The SAR installer is compatible with Eliot's current working image. ;o) And there are numerous open windows and projects in that image...^^
========================================== 0. The Long History of Squeak & UI Theming ==========================================
... http://forum.world.st/Dark-theme-td4869082.html http://forum.world.st/Themes-for-Squeak-5-1-td4882848.html http://forum.world.st/Skylark-Theme-and-Squeak-3-9-td54720.html http://forum.world.st/Non-SmallLand-colour-theme-lying-around-td4697438.html... ...
======================== 1. User Interface Themes ========================
Chris, Karl, and I designed a very lightweight abstraction to support UI themes in Squeak. You can find the whole implementation in the class UserInterfaceTheme and a bunch of tests in UserInterfaceThemeTests.
An object that wants to support theming SHOULD (!) implement three methods:
MyFancyClass class >> #themeProperties MyFancyClass >> #applyUserInterfaceTheme MyFancyClass >> #canApplyUserInterfaceTheme
It also MUST (!) access the current UI theme when setting visual state. And here comes the nice part:
... self color: (self userInterfaceTheme color ifNil: [Color white]). ...
Remember, usually you would write something like this:
... self color: Color white. ...
How can this work? It works by using #doesNotUnderstand: and trigger a dynamic lookup in a dictionary inside the current theme:
Object >> #userInterfaceTheme ^ UserInterfaceTheme current pushScope: self; yourself
UserInterfaceTheme >> #doesNotUnderstand: aMessage ... ^ [self get: scope top class -> aMessage selector] ensure: [scope pop]
Isn't this slow? No, not at all. If you have any doubts, try benching it on your machine:
UserInterfaceThemeTestObject benchLookup.
On my machine, this is even fast enough to support theme lookups in frequently called messages such as Morph >> #drawOn:. However, applications are advised to cache. That's why we have the explicit #applyUserInterfaceTheme callbacks as described above.
Note that amazing effects can be achieved by adjusting #color, #borderColor, #borderWidth, #fillStyle, and fonts. :-) The existing themes do exactly that.
To get a feeling of the impact of having themes in Squeak, try browsing senders and implementors of #applyUserInterfaceTheme, #themeProperties, #userInterfaceTheme, and maybe #canApplyUserInterfaceTheme. I think we can still reduce the number of sends to #userInterfaceTheme a little more.
================================== 2. Code clean-up in widget classes ==================================
We made Shout look up the current theme to build its internal cache of text attributes to quickly style code as you type it.
We removed window color specifications and replaced them by simply implementing Model >> #defaultWindowColor. There is also still the #uniformWindowColor if you do not like colorful windows. This makes it also much easier for new applications to have their own window color.
We unified the implementation of MenuMorph and DockingBarMorph and fixed several bugs there.
Dialogs! *phew* ... *arrrrgss* ... Dialogs. :-) We managed to introduce a general DialogWindow class. FillInTheBlankMorph and UserDialogBoxMorph are now mere subclasses with a custom interface. There is also support for ToolBuilder, see ListChooser for an example. *yay*
Buttons feel more like buttons now. It's a good thing, right?
For lists and trees and text boxes, we greatly reduced the amount of code that just accessed global state. LazyListMorph, NewParagraph, TextMorph, IndentingListItemMorph, ... they all now get configured by their "hosts", which are PluggableListMorph, PluggableTextMorph, and SimpleHierarchicalListMorph. Having this, we improved the modular structure of our whole Squeak widget library. That modular structure made applying themes much easier. :-)
======================== 3. Theme all the widgets ========================
There is a nice existing pattern with the message #setDefaultParameters, which is usually called from #initialize. Go, see for yourself. Browse implementors of #setDefaultParameters. We used that pattern and cleaned up many implementations of that message in the image.
Note that rounded corners, gradients, colorful windows, and shadows are still preferences outside of UI themes. You can toggle them in any UI theme.
Note that the background color/image is also not subject to be themed. Just drop your favorite picture or pattern in the image. It's really easy.
Now, take a look at the class SqueakTheme. There, you will find source code for creating the default Squeak theme to be shared via SqueakSource and reset during the release building process. :-)
Besides get/set/clear -- which might be expected from the theme structure because it is basically a dictionary with some properties -- There, you will notice a "merge" or "link" or "derive". When creating themes programmatically, you can: - derive properties from other properties - link themes to extend property look-up - merge one theme into another theme
How does property look-up work? Well, see UserInterfaceTheme >> #get: 1. Look up the key, which is usually "Class -> symbol". 2. Try the superclass chain. 3. Try the same lookup in the linked theme if any.
Theoretically, you could actually implement messages in subclasses of UserInterfaceTheme and bypass that DNU-triggered lookup. We do not do this right now.
As you can see, Squeak/Smalltalk offers a great deal of flexibility. It is remains subject to discussion of how to employ the language and its semantics. Think of the current implementation of user interface themes as one way that represents a trade-off between a concise programming interface (i.e. ... self userInterfaceTheme color ifNil ...), a fair amount of comprehensive patterns (i.e. #setDefaultParameters, #applyUserInterfaceTheme, ...), and some other existing constraints (i.e. old code, Monticello/Squeaksource, existing tools such as senders/implementors, ...).
Happy Squeaking!
Marcel, Chris, Karl
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
Hi.
First, a warning for other using this sar - it applies updates before loading. So, if you are on trunk, you will be updated to the latest trunk. Mostly that should be ok.
Second, if you have a LOT of open windows, the image will appear to seize up briefly at one point during load. It isn't frozen - it is just applying the theme to all open windows. (I have 47 open windows - takes a bit of time).
Changing themes (with my 47 open windows) takes about 9 seconds.
Changing themes works - mostly. It appears to just change the thematic elements that are visible at the time of theme changing. What is mean is, if you have a window minimized, then the contents of that window will not change to the new theme, but will stay with the old theme (at least, the colors do). This may not be an issue for folks with a reasonably small number of windows open, of course.
As a side effect, it is possible to mix themes this way.
I'll run with it today, and report any issues, although I doubt I'll see many more.
-cbc
On Thu, Jul 28, 2016 at 6:14 AM, marcel.taeumel Marcel.Taeumel@hpi.de wrote:
Hi, there! :-)
TL;DR: Here is a SAR file that cleans up the code of all widget classes such as lists and buttons in your image and adds support for UI theming as well as a bunch of UI themes (choose Themes via "Extras > Themes & Colors"): squeak_trunk_uitheme_v12.sar http://forum.world.st/file/n4908439/squeak_trunk_uitheme_v12.sar
Here is a preview: http://i.giphy.com/l46CcX46yRE9H6yQ0.gif
*Try it out. Report bugs. Report performance issues!!* We will commit the changes to trunk this Saturday.
Btw: The SAR installer is compatible with Eliot's current working image. ;o) And there are numerous open windows and projects in that image...^^
========================================== 0. The Long History of Squeak & UI Theming ==========================================
... http://forum.world.st/Dark-theme-td4869082.html http://forum.world.st/Themes-for-Squeak-5-1-td4882848.html http://forum.world.st/Skylark-Theme-and-Squeak-3-9-td54720.html
http://forum.world.st/Non-SmallLand-colour-theme-lying-around-td4697438.html... ...
========================
- User Interface Themes
========================
Chris, Karl, and I designed a very lightweight abstraction to support UI themes in Squeak. You can find the whole implementation in the class UserInterfaceTheme and a bunch of tests in UserInterfaceThemeTests.
An object that wants to support theming SHOULD (!) implement three methods:
MyFancyClass class >> #themeProperties MyFancyClass >> #applyUserInterfaceTheme MyFancyClass >> #canApplyUserInterfaceTheme
It also MUST (!) access the current UI theme when setting visual state. And here comes the nice part:
... self color: (self userInterfaceTheme color ifNil: [Color white]). ...
Remember, usually you would write something like this:
... self color: Color white. ...
How can this work? It works by using #doesNotUnderstand: and trigger a dynamic lookup in a dictionary inside the current theme:
Object >> #userInterfaceTheme ^ UserInterfaceTheme current pushScope: self; yourself
UserInterfaceTheme >> #doesNotUnderstand: aMessage ... ^ [self get: scope top class -> aMessage selector] ensure: [scope pop]
Isn't this slow? No, not at all. If you have any doubts, try benching it on your machine:
UserInterfaceThemeTestObject benchLookup.
On my machine, this is even fast enough to support theme lookups in frequently called messages such as Morph >> #drawOn:. However, applications are advised to cache. That's why we have the explicit #applyUserInterfaceTheme callbacks as described above.
Note that amazing effects can be achieved by adjusting #color, #borderColor, #borderWidth, #fillStyle, and fonts. :-) The existing themes do exactly that.
To get a feeling of the impact of having themes in Squeak, try browsing senders and implementors of #applyUserInterfaceTheme, #themeProperties, #userInterfaceTheme, and maybe #canApplyUserInterfaceTheme. I think we can still reduce the number of sends to #userInterfaceTheme a little more.
================================== 2. Code clean-up in widget classes ==================================
We made Shout look up the current theme to build its internal cache of text attributes to quickly style code as you type it.
We removed window color specifications and replaced them by simply implementing Model >> #defaultWindowColor. There is also still the #uniformWindowColor if you do not like colorful windows. This makes it also much easier for new applications to have their own window color.
We unified the implementation of MenuMorph and DockingBarMorph and fixed several bugs there.
Dialogs! *phew* ... *arrrrgss* ... Dialogs. :-) We managed to introduce a general DialogWindow class. FillInTheBlankMorph and UserDialogBoxMorph are now mere subclasses with a custom interface. There is also support for ToolBuilder, see ListChooser for an example. *yay*
Buttons feel more like buttons now. It's a good thing, right?
For lists and trees and text boxes, we greatly reduced the amount of code that just accessed global state. LazyListMorph, NewParagraph, TextMorph, IndentingListItemMorph, ... they all now get configured by their "hosts", which are PluggableListMorph, PluggableTextMorph, and SimpleHierarchicalListMorph. Having this, we improved the modular structure of our whole Squeak widget library. That modular structure made applying themes much easier. :-)
======================== 3. Theme all the widgets ========================
There is a nice existing pattern with the message #setDefaultParameters, which is usually called from #initialize. Go, see for yourself. Browse implementors of #setDefaultParameters. We used that pattern and cleaned up many implementations of that message in the image.
Note that rounded corners, gradients, colorful windows, and shadows are still preferences outside of UI themes. You can toggle them in any UI theme.
Note that the background color/image is also not subject to be themed. Just drop your favorite picture or pattern in the image. It's really easy.
Now, take a look at the class SqueakTheme. There, you will find source code for creating the default Squeak theme to be shared via SqueakSource and reset during the release building process. :-)
Besides get/set/clear -- which might be expected from the theme structure because it is basically a dictionary with some properties -- There, you will notice a "merge" or "link" or "derive". When creating themes programmatically, you can:
- derive properties from other properties
- link themes to extend property look-up
- merge one theme into another theme
How does property look-up work? Well, see UserInterfaceTheme >> #get:
- Look up the key, which is usually "Class -> symbol".
- Try the superclass chain.
- Try the same lookup in the linked theme if any.
Theoretically, you could actually implement messages in subclasses of UserInterfaceTheme and bypass that DNU-triggered lookup. We do not do this right now.
As you can see, Squeak/Smalltalk offers a great deal of flexibility. It is remains subject to discussion of how to employ the language and its semantics. Think of the current implementation of user interface themes as one way that represents a trade-off between a concise programming interface (i.e. ... self userInterfaceTheme color ifNil ...), a fair amount of comprehensive patterns (i.e. #setDefaultParameters, #applyUserInterfaceTheme, ...), and some other existing constraints (i.e. old code, Monticello/Squeaksource, existing tools such as senders/implementors, ...).
Happy Squeaking!
Marcel, Chris, Karl
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
cbc wrote
Hi.
First, a warning for other using this sar - it applies updates before loading. So, if you are on trunk, you will be updated to the latest trunk. Mostly that should be ok.
Second, if you have a LOT of open windows, the image will appear to seize up briefly at one point during load. It isn't frozen - it is just applying the theme to all open windows. (I have 47 open windows - takes a bit of time).
Changing themes (with my 47 open windows) takes about 9 seconds.
Changing themes works - mostly. It appears to just change the thematic elements that are visible at the time of theme changing. What is mean is, if you have a window minimized, then the contents of that window will not change to the new theme, but will stay with the old theme (at least, the colors do). This may not be an issue for folks with a reasonably small number of windows open, of course.
As a side effect, it is possible to mix themes this way.
I'll run with it today, and report any issues, although I doubt I'll see many more.
-cbc
On Thu, Jul 28, 2016 at 6:14 AM, marcel.taeumel <
Marcel.Taeumel@
> wrote:
Hi, there! :-)
TL;DR: Here is a SAR file that cleans up the code of all widget classes such as lists and buttons in your image and adds support for UI theming as well as a bunch of UI themes (choose Themes via "Extras > Themes & Colors"): squeak_trunk_uitheme_v12.sar <http://forum.world.st/file/n4908439/squeak_trunk_uitheme_v12.sar%3E;
Here is a preview: http://i.giphy.com/l46CcX46yRE9H6yQ0.gif
*Try it out. Report bugs. Report performance issues!!* We will commit the changes to trunk this Saturday.
Btw: The SAR installer is compatible with Eliot's current working image. ;o) And there are numerous open windows and projects in that image...^^
========================================== 0. The Long History of Squeak & UI Theming ==========================================
... http://forum.world.st/Dark-theme-td4869082.html http://forum.world.st/Themes-for-Squeak-5-1-td4882848.html http://forum.world.st/Skylark-Theme-and-Squeak-3-9-td54720.html
http://forum.world.st/Non-SmallLand-colour-theme-lying-around-td4697438.html... ...
========================
- User Interface Themes
========================
Chris, Karl, and I designed a very lightweight abstraction to support UI themes in Squeak. You can find the whole implementation in the class UserInterfaceTheme and a bunch of tests in UserInterfaceThemeTests.
An object that wants to support theming SHOULD (!) implement three methods:
MyFancyClass class >> #themeProperties MyFancyClass >> #applyUserInterfaceTheme MyFancyClass >> #canApplyUserInterfaceTheme
It also MUST (!) access the current UI theme when setting visual state. And here comes the nice part:
... self color: (self userInterfaceTheme color ifNil: [Color white]). ...
Remember, usually you would write something like this:
... self color: Color white. ...
How can this work? It works by using #doesNotUnderstand: and trigger a dynamic lookup in a dictionary inside the current theme:
Object >> #userInterfaceTheme ^ UserInterfaceTheme current pushScope: self; yourself
UserInterfaceTheme >> #doesNotUnderstand: aMessage ... ^ [self get: scope top class -> aMessage selector] ensure: [scope pop]
Isn't this slow? No, not at all. If you have any doubts, try benching it on your machine:
UserInterfaceThemeTestObject benchLookup.
On my machine, this is even fast enough to support theme lookups in frequently called messages such as Morph >> #drawOn:. However, applications are advised to cache. That's why we have the explicit #applyUserInterfaceTheme callbacks as described above.
Note that amazing effects can be achieved by adjusting #color, #borderColor, #borderWidth, #fillStyle, and fonts. :-) The existing themes do exactly that.
To get a feeling of the impact of having themes in Squeak, try browsing senders and implementors of #applyUserInterfaceTheme, #themeProperties, #userInterfaceTheme, and maybe #canApplyUserInterfaceTheme. I think we can still reduce the number of sends to #userInterfaceTheme a little more.
================================== 2. Code clean-up in widget classes ==================================
We made Shout look up the current theme to build its internal cache of text attributes to quickly style code as you type it.
We removed window color specifications and replaced them by simply implementing Model >> #defaultWindowColor. There is also still the #uniformWindowColor if you do not like colorful windows. This makes it also much easier for new applications to have their own window color.
We unified the implementation of MenuMorph and DockingBarMorph and fixed several bugs there.
Dialogs! *phew* ... *arrrrgss* ... Dialogs. :-) We managed to introduce a general DialogWindow class. FillInTheBlankMorph and UserDialogBoxMorph are now mere subclasses with a custom interface. There is also support for ToolBuilder, see ListChooser for an example. *yay*
Buttons feel more like buttons now. It's a good thing, right?
For lists and trees and text boxes, we greatly reduced the amount of code that just accessed global state. LazyListMorph, NewParagraph, TextMorph, IndentingListItemMorph, ... they all now get configured by their "hosts", which are PluggableListMorph, PluggableTextMorph, and SimpleHierarchicalListMorph. Having this, we improved the modular structure of our whole Squeak widget library. That modular structure made applying themes much easier. :-)
======================== 3. Theme all the widgets ========================
There is a nice existing pattern with the message #setDefaultParameters, which is usually called from #initialize. Go, see for yourself. Browse implementors of #setDefaultParameters. We used that pattern and cleaned up many implementations of that message in the image.
Note that rounded corners, gradients, colorful windows, and shadows are still preferences outside of UI themes. You can toggle them in any UI theme.
Note that the background color/image is also not subject to be themed. Just drop your favorite picture or pattern in the image. It's really easy.
Now, take a look at the class SqueakTheme. There, you will find source code for creating the default Squeak theme to be shared via SqueakSource and reset during the release building process. :-)
Besides get/set/clear -- which might be expected from the theme structure because it is basically a dictionary with some properties -- There, you will notice a "merge" or "link" or "derive". When creating themes programmatically, you can:
- derive properties from other properties
- link themes to extend property look-up
- merge one theme into another theme
How does property look-up work? Well, see UserInterfaceTheme >> #get:
- Look up the key, which is usually "Class -> symbol".
- Try the superclass chain.
- Try the same lookup in the linked theme if any.
Theoretically, you could actually implement messages in subclasses of UserInterfaceTheme and bypass that DNU-triggered lookup. We do not do this right now.
As you can see, Squeak/Smalltalk offers a great deal of flexibility. It is remains subject to discussion of how to employ the language and its semantics. Think of the current implementation of user interface themes as one way that represents a trade-off between a concise programming interface (i.e. ... self userInterfaceTheme color ifNil ...), a fair amount of comprehensive patterns (i.e. #setDefaultParameters, #applyUserInterfaceTheme, ...), and some other existing constraints (i.e. old code, Monticello/Squeaksource, existing tools such as senders/implementors, ...).
Happy Squeaking!
Marcel, Chris, Karl
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
Thanks for this elaborate report. :-)
"Changing themes works - mostly. It appears to just change the thematic elements that are visible at the time of theme changing. What is mean is, if you have a window minimized, then the contents of that window will not change to the new theme, but will stay with the old theme (at least, the colors do). This may not be an issue for folks with a reasonably small number of windows open, of course."
There is a filter in Morph >> #canApplyUserInterfaceTheme, which checks "self isInWorld". For collapsed window contents (text boxes etc.), that returns false.
One could experiment with removing that check for a while. We think that we might not want to change prototypical content or left-overs... Hmm... I think we can fix this for Pluggable* widgets very easy by checking #containingWindow.
Thanks!
Best, Marcel
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
marcel.taeumel wrote
cbc wrote
Hi.
First, a warning for other using this sar - it applies updates before loading. So, if you are on trunk, you will be updated to the latest trunk. Mostly that should be ok.
Second, if you have a LOT of open windows, the image will appear to seize up briefly at one point during load. It isn't frozen - it is just applying the theme to all open windows. (I have 47 open windows - takes a bit of time).
Changing themes (with my 47 open windows) takes about 9 seconds.
Changing themes works - mostly. It appears to just change the thematic elements that are visible at the time of theme changing. What is mean is, if you have a window minimized, then the contents of that window will not change to the new theme, but will stay with the old theme (at least, the colors do). This may not be an issue for folks with a reasonably small number of windows open, of course.
As a side effect, it is possible to mix themes this way.
I'll run with it today, and report any issues, although I doubt I'll see many more.
-cbc
On Thu, Jul 28, 2016 at 6:14 AM, marcel.taeumel <
Marcel.Taeumel@
> wrote:
Hi, there! :-)
TL;DR: Here is a SAR file that cleans up the code of all widget classes such as lists and buttons in your image and adds support for UI theming as well as a bunch of UI themes (choose Themes via "Extras > Themes & Colors"): squeak_trunk_uitheme_v12.sar <http://forum.world.st/file/n4908439/squeak_trunk_uitheme_v12.sar%3E;
Here is a preview: http://i.giphy.com/l46CcX46yRE9H6yQ0.gif
*Try it out. Report bugs. Report performance issues!!* We will commit the changes to trunk this Saturday.
Btw: The SAR installer is compatible with Eliot's current working image. ;o) And there are numerous open windows and projects in that image...^^
========================================== 0. The Long History of Squeak & UI Theming ==========================================
... http://forum.world.st/Dark-theme-td4869082.html http://forum.world.st/Themes-for-Squeak-5-1-td4882848.html http://forum.world.st/Skylark-Theme-and-Squeak-3-9-td54720.html
http://forum.world.st/Non-SmallLand-colour-theme-lying-around-td4697438.html... ...
========================
- User Interface Themes
========================
Chris, Karl, and I designed a very lightweight abstraction to support UI themes in Squeak. You can find the whole implementation in the class UserInterfaceTheme and a bunch of tests in UserInterfaceThemeTests.
An object that wants to support theming SHOULD (!) implement three methods:
MyFancyClass class >> #themeProperties MyFancyClass >> #applyUserInterfaceTheme MyFancyClass >> #canApplyUserInterfaceTheme
It also MUST (!) access the current UI theme when setting visual state. And here comes the nice part:
... self color: (self userInterfaceTheme color ifNil: [Color white]). ...
Remember, usually you would write something like this:
... self color: Color white. ...
How can this work? It works by using #doesNotUnderstand: and trigger a dynamic lookup in a dictionary inside the current theme:
Object >> #userInterfaceTheme ^ UserInterfaceTheme current pushScope: self; yourself
UserInterfaceTheme >> #doesNotUnderstand: aMessage ... ^ [self get: scope top class -> aMessage selector] ensure: [scope pop]
Isn't this slow? No, not at all. If you have any doubts, try benching it on your machine:
UserInterfaceThemeTestObject benchLookup.
On my machine, this is even fast enough to support theme lookups in frequently called messages such as Morph >> #drawOn:. However, applications are advised to cache. That's why we have the explicit #applyUserInterfaceTheme callbacks as described above.
Note that amazing effects can be achieved by adjusting #color, #borderColor, #borderWidth, #fillStyle, and fonts. :-) The existing themes do exactly that.
To get a feeling of the impact of having themes in Squeak, try browsing senders and implementors of #applyUserInterfaceTheme, #themeProperties, #userInterfaceTheme, and maybe #canApplyUserInterfaceTheme. I think we can still reduce the number of sends to #userInterfaceTheme a little more.
================================== 2. Code clean-up in widget classes ==================================
We made Shout look up the current theme to build its internal cache of text attributes to quickly style code as you type it.
We removed window color specifications and replaced them by simply implementing Model >> #defaultWindowColor. There is also still the #uniformWindowColor if you do not like colorful windows. This makes it also much easier for new applications to have their own window color.
We unified the implementation of MenuMorph and DockingBarMorph and fixed several bugs there.
Dialogs! *phew* ... *arrrrgss* ... Dialogs. :-) We managed to introduce a general DialogWindow class. FillInTheBlankMorph and UserDialogBoxMorph are now mere subclasses with a custom interface. There is also support for ToolBuilder, see ListChooser for an example. *yay*
Buttons feel more like buttons now. It's a good thing, right?
For lists and trees and text boxes, we greatly reduced the amount of code that just accessed global state. LazyListMorph, NewParagraph, TextMorph, IndentingListItemMorph, ... they all now get configured by their "hosts", which are PluggableListMorph, PluggableTextMorph, and SimpleHierarchicalListMorph. Having this, we improved the modular structure of our whole Squeak widget library. That modular structure made applying themes much easier. :-)
======================== 3. Theme all the widgets ========================
There is a nice existing pattern with the message #setDefaultParameters, which is usually called from #initialize. Go, see for yourself. Browse implementors of #setDefaultParameters. We used that pattern and cleaned up many implementations of that message in the image.
Note that rounded corners, gradients, colorful windows, and shadows are still preferences outside of UI themes. You can toggle them in any UI theme.
Note that the background color/image is also not subject to be themed. Just drop your favorite picture or pattern in the image. It's really easy.
Now, take a look at the class SqueakTheme. There, you will find source code for creating the default Squeak theme to be shared via SqueakSource and reset during the release building process. :-)
Besides get/set/clear -- which might be expected from the theme structure because it is basically a dictionary with some properties -- There, you will notice a "merge" or "link" or "derive". When creating themes programmatically, you can:
- derive properties from other properties
- link themes to extend property look-up
- merge one theme into another theme
How does property look-up work? Well, see UserInterfaceTheme >> #get:
- Look up the key, which is usually "Class -> symbol".
- Try the superclass chain.
- Try the same lookup in the linked theme if any.
Theoretically, you could actually implement messages in subclasses of UserInterfaceTheme and bypass that DNU-triggered lookup. We do not do this right now.
As you can see, Squeak/Smalltalk offers a great deal of flexibility. It is remains subject to discussion of how to employ the language and its semantics. Think of the current implementation of user interface themes as one way that represents a trade-off between a concise programming interface (i.e. ... self userInterfaceTheme color ifNil ...), a fair amount of comprehensive patterns (i.e. #setDefaultParameters, #applyUserInterfaceTheme, ...), and some other existing constraints (i.e. old code, Monticello/Squeaksource, existing tools such as senders/implementors, ...).
Happy Squeaking!
Marcel, Chris, Karl
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
Thanks for this elaborate report. :-)
"Changing themes works - mostly. It appears to just change the thematic elements that are visible at the time of theme changing. What is mean is, if you have a window minimized, then the contents of that window will not change to the new theme, but will stay with the old theme (at least, the colors do). This may not be an issue for folks with a reasonably small number of windows open, of course."
There is a filter in Morph >> #canApplyUserInterfaceTheme, which checks "self isInWorld". For collapsed window contents (text boxes etc.), that returns false.
One could experiment with removing that check for a while. We think that we might not want to change prototypical content or left-overs... Hmm... I think we can fix this for Pluggable* widgets very easy by checking #containingWindow.
Thanks!
Best, Marcel
Anyway, you can always re-apply a theme.
Best, Marcel
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
On Thu, Jul 28, 2016 at 7:49 AM, marcel.taeumel Marcel.Taeumel@hpi.de wrote: <snip>
Thanks for this elaborate report. :-)
You're welcome. I'm in the UI most every day, for several hours. Looks matter to me.
I notice that the selection lists have changed somewhat - either in this package or in the trunk recently (not sure which). I think I like the new selections - but will take some time to get used to them.
"Changing themes works - mostly. It appears to just change the thematic elements that are visible at the time of theme changing. What is mean is, if you have a window minimized, then the contents of that window will not change to the new theme, but will stay with the old theme (at least, the colors do). This may not be an issue for folks with a reasonably small number of windows open, of course."
There is a filter in Morph >> #canApplyUserInterfaceTheme, which checks "self isInWorld". For collapsed window contents (text boxes etc.), that returns false.
One could experiment with removing that check for a while.
I'm thinking I'll need to do this. Some of the older themes plus highlighting in the newest produce startling results - old dark theme in new dark theme = blinding white selections.
We think that we
might not want to change prototypical content or left-overs... Hmm... I think we can fix this for Pluggable* widgets very easy by checking #containingWindow.
Thanks!
Best, Marcel
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
Oh, and I should mention that I do like this. The theme selection is nice/reasonable to use and was easy to understand.
and the look - I really like that. -cbc
On Thu, Jul 28, 2016 at 10:08 AM, Chris Cunningham cunningham.cb@gmail.com wrote:
On Thu, Jul 28, 2016 at 7:49 AM, marcel.taeumel Marcel.Taeumel@hpi.de wrote:
<snip>
Thanks for this elaborate report. :-)
You're welcome. I'm in the UI most every day, for several hours. Looks matter to me.
I notice that the selection lists have changed somewhat - either in this package or in the trunk recently (not sure which). I think I like the new selections - but will take some time to get used to them.
"Changing themes works - mostly. It appears to just change the thematic elements that are visible at the time of theme changing. What is mean is, if you have a window minimized, then the contents of that window will not change to the new theme, but will stay with the old theme (at least, the colors do). This may not be an issue for folks with a reasonably small number of windows open, of course."
There is a filter in Morph >> #canApplyUserInterfaceTheme, which checks "self isInWorld". For collapsed window contents (text boxes etc.), that returns false.
One could experiment with removing that check for a while.
I'm thinking I'll need to do this. Some of the older themes plus highlighting in the newest produce startling results - old dark theme in new dark theme = blinding white selections.
We think that we
might not want to change prototypical content or left-overs... Hmm... I think we can fix this for Pluggable* widgets very easy by checking #containingWindow.
Thanks!
Best, Marcel
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
I noticed that white/ light colored on dark background letters now look a little bolder than before. Black on white does not look so bold.
Best, Karl
On Thu, Jul 28, 2016 at 7:27 PM, Chris Cunningham cunningham.cb@gmail.com wrote:
Oh, and I should mention that I do like this. The theme selection is nice/reasonable to use and was easy to understand.
and the look - I really like that. -cbc
On Thu, Jul 28, 2016 at 10:08 AM, Chris Cunningham < cunningham.cb@gmail.com> wrote:
On Thu, Jul 28, 2016 at 7:49 AM, marcel.taeumel Marcel.Taeumel@hpi.de wrote:
<snip>
Thanks for this elaborate report. :-)
You're welcome. I'm in the UI most every day, for several hours. Looks matter to me.
I notice that the selection lists have changed somewhat - either in this package or in the trunk recently (not sure which). I think I like the new selections - but will take some time to get used to them.
"Changing themes works - mostly. It appears to just change the thematic elements that are visible at the time of theme changing. What is mean is, if you have a window minimized, then the contents of that window will not change to the new theme, but will stay with the old theme (at least, the colors do). This may not be an issue for folks with a reasonably small number of windows open, of course."
There is a filter in Morph >> #canApplyUserInterfaceTheme, which checks "self isInWorld". For collapsed window contents (text boxes etc.), that returns false.
One could experiment with removing that check for a while.
I'm thinking I'll need to do this. Some of the older themes plus highlighting in the newest produce startling results - old dark theme in new dark theme = blinding white selections.
We think that we
might not want to change prototypical content or left-overs... Hmm... I think we can fix this for Pluggable* widgets very easy by checking #containingWindow.
Thanks!
Best, Marcel
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
Chris Muller-3 wrote
One could experiment with removing that check for a while.
Instead of removing it, couldn't we just override it in SystemWindow?
Wouldn't work because it does not affect instances of SystemWindow but its submorphs. Anyway, I found a solution.
Best, Marcel
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
marcel.taeumel wrote
Chris Muller-3 wrote
One could experiment with removing that check for a while.
Instead of removing it, couldn't we just override it in SystemWindow?
Wouldn't work because it does not affect instances of SystemWindow but its submorphs. Anyway, I found a solution.
Best, Marcel
Hi, there.
It's all in the Trunk now. It should work. :-) I do only have some troubles with the VM when applying all the updates to Eliot's working image. I suspect a bug in the VM. If you also experience VM crashes, open Monticello and the trunk/update map manually. Now load one mcm after the other (starting with mt.372.mcm).
If you get debuggers, please report. There might still be some fine-tuning left in the .mcm's package load order.
Best, Marcel
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
I'm still using the Spur 3692 VM, and was able to update my trunk image with no problems.
On Sun, Jul 31, 2016 at 4:55 AM, marcel.taeumel Marcel.Taeumel@hpi.de wrote:
marcel.taeumel wrote
Chris Muller-3 wrote
One could experiment with removing that check for a while.
Instead of removing it, couldn't we just override it in SystemWindow?
Wouldn't work because it does not affect instances of SystemWindow but its submorphs. Anyway, I found a solution.
Best, Marcel
Hi, there.
It's all in the Trunk now. It should work. :-) I do only have some troubles with the VM when applying all the updates to Eliot's working image. I suspect a bug in the VM. If you also experience VM crashes, open Monticello and the trunk/update map manually. Now load one mcm after the other (starting with mt.372.mcm).
If you get debuggers, please report. There might still be some fine-tuning left in the .mcm's package load order.
Best, Marcel
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
Yay, Marcel!
Best, Karl
On Thu, Jul 28, 2016 at 3:14 PM, marcel.taeumel Marcel.Taeumel@hpi.de wrote:
Hi, there! :-)
TL;DR: Here is a SAR file that cleans up the code of all widget classes such as lists and buttons in your image and adds support for UI theming as well as a bunch of UI themes (choose Themes via "Extras > Themes & Colors"): squeak_trunk_uitheme_v12.sar http://forum.world.st/file/n4908439/squeak_trunk_uitheme_v12.sar
Here is a preview: http://i.giphy.com/l46CcX46yRE9H6yQ0.gif
*Try it out. Report bugs. Report performance issues!!* We will commit the changes to trunk this Saturday.
Btw: The SAR installer is compatible with Eliot's current working image. ;o) And there are numerous open windows and projects in that image...^^
========================================== 0. The Long History of Squeak & UI Theming ==========================================
... http://forum.world.st/Dark-theme-td4869082.html http://forum.world.st/Themes-for-Squeak-5-1-td4882848.html http://forum.world.st/Skylark-Theme-and-Squeak-3-9-td54720.html
http://forum.world.st/Non-SmallLand-colour-theme-lying-around-td4697438.html... ...
========================
- User Interface Themes
========================
Chris, Karl, and I designed a very lightweight abstraction to support UI themes in Squeak. You can find the whole implementation in the class UserInterfaceTheme and a bunch of tests in UserInterfaceThemeTests.
An object that wants to support theming SHOULD (!) implement three methods:
MyFancyClass class >> #themeProperties MyFancyClass >> #applyUserInterfaceTheme MyFancyClass >> #canApplyUserInterfaceTheme
It also MUST (!) access the current UI theme when setting visual state. And here comes the nice part:
... self color: (self userInterfaceTheme color ifNil: [Color white]). ...
Remember, usually you would write something like this:
... self color: Color white. ...
How can this work? It works by using #doesNotUnderstand: and trigger a dynamic lookup in a dictionary inside the current theme:
Object >> #userInterfaceTheme ^ UserInterfaceTheme current pushScope: self; yourself
UserInterfaceTheme >> #doesNotUnderstand: aMessage ... ^ [self get: scope top class -> aMessage selector] ensure: [scope pop]
Isn't this slow? No, not at all. If you have any doubts, try benching it on your machine:
UserInterfaceThemeTestObject benchLookup.
On my machine, this is even fast enough to support theme lookups in frequently called messages such as Morph >> #drawOn:. However, applications are advised to cache. That's why we have the explicit #applyUserInterfaceTheme callbacks as described above.
Note that amazing effects can be achieved by adjusting #color, #borderColor, #borderWidth, #fillStyle, and fonts. :-) The existing themes do exactly that.
To get a feeling of the impact of having themes in Squeak, try browsing senders and implementors of #applyUserInterfaceTheme, #themeProperties, #userInterfaceTheme, and maybe #canApplyUserInterfaceTheme. I think we can still reduce the number of sends to #userInterfaceTheme a little more.
================================== 2. Code clean-up in widget classes ==================================
We made Shout look up the current theme to build its internal cache of text attributes to quickly style code as you type it.
We removed window color specifications and replaced them by simply implementing Model >> #defaultWindowColor. There is also still the #uniformWindowColor if you do not like colorful windows. This makes it also much easier for new applications to have their own window color.
We unified the implementation of MenuMorph and DockingBarMorph and fixed several bugs there.
Dialogs! *phew* ... *arrrrgss* ... Dialogs. :-) We managed to introduce a general DialogWindow class. FillInTheBlankMorph and UserDialogBoxMorph are now mere subclasses with a custom interface. There is also support for ToolBuilder, see ListChooser for an example. *yay*
Buttons feel more like buttons now. It's a good thing, right?
For lists and trees and text boxes, we greatly reduced the amount of code that just accessed global state. LazyListMorph, NewParagraph, TextMorph, IndentingListItemMorph, ... they all now get configured by their "hosts", which are PluggableListMorph, PluggableTextMorph, and SimpleHierarchicalListMorph. Having this, we improved the modular structure of our whole Squeak widget library. That modular structure made applying themes much easier. :-)
======================== 3. Theme all the widgets ========================
There is a nice existing pattern with the message #setDefaultParameters, which is usually called from #initialize. Go, see for yourself. Browse implementors of #setDefaultParameters. We used that pattern and cleaned up many implementations of that message in the image.
Note that rounded corners, gradients, colorful windows, and shadows are still preferences outside of UI themes. You can toggle them in any UI theme.
Note that the background color/image is also not subject to be themed. Just drop your favorite picture or pattern in the image. It's really easy.
Now, take a look at the class SqueakTheme. There, you will find source code for creating the default Squeak theme to be shared via SqueakSource and reset during the release building process. :-)
Besides get/set/clear -- which might be expected from the theme structure because it is basically a dictionary with some properties -- There, you will notice a "merge" or "link" or "derive". When creating themes programmatically, you can:
- derive properties from other properties
- link themes to extend property look-up
- merge one theme into another theme
How does property look-up work? Well, see UserInterfaceTheme >> #get:
- Look up the key, which is usually "Class -> symbol".
- Try the superclass chain.
- Try the same lookup in the linked theme if any.
Theoretically, you could actually implement messages in subclasses of UserInterfaceTheme and bypass that DNU-triggered lookup. We do not do this right now.
As you can see, Squeak/Smalltalk offers a great deal of flexibility. It is remains subject to discussion of how to employ the language and its semantics. Think of the current implementation of user interface themes as one way that represents a trade-off between a concise programming interface (i.e. ... self userInterfaceTheme color ifNil ...), a fair amount of comprehensive patterns (i.e. #setDefaultParameters, #applyUserInterfaceTheme, ...), and some other existing constraints (i.e. old code, Monticello/Squeaksource, existing tools such as senders/implementors, ...).
Happy Squeaking!
Marcel, Chris, Karl
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
Thank you, Marcel, for slogging through this detailed work and bringing it to the level of excellence expected of a first class IDE. Your initiative to get this pushed across the finish-line means the Squeak release will be looking gorgeous at ESUG!
I finally had a moment to read your whole note. :) Yes, we spent a lot of time thinking about this themeing implementation, those trade-offs you mentioned are exactly what we were aiming for and I think the balance we ended up with is fantastic. Its light, flexible, easy to understand, nad supports a variety of integration cases which you said actually brought some uniformity to some legacy areas of the system. Oh, and its not slow.
What more could we possibly want from a theming implementation? Just two things: 1) A window which presents all the themeProperties and ability to change them and, 2) Ability to save/load as objects. :)
Best, Chris
On Thu, Jul 28, 2016 at 8:14 AM, marcel.taeumel Marcel.Taeumel@hpi.de wrote:
Hi, there! :-)
TL;DR: Here is a SAR file that cleans up the code of all widget classes such as lists and buttons in your image and adds support for UI theming as well as a bunch of UI themes (choose Themes via "Extras > Themes & Colors"): squeak_trunk_uitheme_v12.sar http://forum.world.st/file/n4908439/squeak_trunk_uitheme_v12.sar
Here is a preview: http://i.giphy.com/l46CcX46yRE9H6yQ0.gif
*Try it out. Report bugs. Report performance issues!!* We will commit the changes to trunk this Saturday.
Btw: The SAR installer is compatible with Eliot's current working image. ;o) And there are numerous open windows and projects in that image...^^
========================================== 0. The Long History of Squeak & UI Theming ==========================================
... http://forum.world.st/Dark-theme-td4869082.html http://forum.world.st/Themes-for-Squeak-5-1-td4882848.html http://forum.world.st/Skylark-Theme-and-Squeak-3-9-td54720.html http://forum.world.st/Non-SmallLand-colour-theme-lying-around-td4697438.html... ...
========================
- User Interface Themes
========================
Chris, Karl, and I designed a very lightweight abstraction to support UI themes in Squeak. You can find the whole implementation in the class UserInterfaceTheme and a bunch of tests in UserInterfaceThemeTests.
An object that wants to support theming SHOULD (!) implement three methods:
MyFancyClass class >> #themeProperties MyFancyClass >> #applyUserInterfaceTheme MyFancyClass >> #canApplyUserInterfaceTheme
It also MUST (!) access the current UI theme when setting visual state. And here comes the nice part:
... self color: (self userInterfaceTheme color ifNil: [Color white]). ...
Remember, usually you would write something like this:
... self color: Color white. ...
How can this work? It works by using #doesNotUnderstand: and trigger a dynamic lookup in a dictionary inside the current theme:
Object >> #userInterfaceTheme ^ UserInterfaceTheme current pushScope: self; yourself
UserInterfaceTheme >> #doesNotUnderstand: aMessage ... ^ [self get: scope top class -> aMessage selector] ensure: [scope pop]
Isn't this slow? No, not at all. If you have any doubts, try benching it on your machine:
UserInterfaceThemeTestObject benchLookup.
On my machine, this is even fast enough to support theme lookups in frequently called messages such as Morph >> #drawOn:. However, applications are advised to cache. That's why we have the explicit #applyUserInterfaceTheme callbacks as described above.
Note that amazing effects can be achieved by adjusting #color, #borderColor, #borderWidth, #fillStyle, and fonts. :-) The existing themes do exactly that.
To get a feeling of the impact of having themes in Squeak, try browsing senders and implementors of #applyUserInterfaceTheme, #themeProperties, #userInterfaceTheme, and maybe #canApplyUserInterfaceTheme. I think we can still reduce the number of sends to #userInterfaceTheme a little more.
================================== 2. Code clean-up in widget classes ==================================
We made Shout look up the current theme to build its internal cache of text attributes to quickly style code as you type it.
We removed window color specifications and replaced them by simply implementing Model >> #defaultWindowColor. There is also still the #uniformWindowColor if you do not like colorful windows. This makes it also much easier for new applications to have their own window color.
We unified the implementation of MenuMorph and DockingBarMorph and fixed several bugs there.
Dialogs! *phew* ... *arrrrgss* ... Dialogs. :-) We managed to introduce a general DialogWindow class. FillInTheBlankMorph and UserDialogBoxMorph are now mere subclasses with a custom interface. There is also support for ToolBuilder, see ListChooser for an example. *yay*
Buttons feel more like buttons now. It's a good thing, right?
For lists and trees and text boxes, we greatly reduced the amount of code that just accessed global state. LazyListMorph, NewParagraph, TextMorph, IndentingListItemMorph, ... they all now get configured by their "hosts", which are PluggableListMorph, PluggableTextMorph, and SimpleHierarchicalListMorph. Having this, we improved the modular structure of our whole Squeak widget library. That modular structure made applying themes much easier. :-)
======================== 3. Theme all the widgets ========================
There is a nice existing pattern with the message #setDefaultParameters, which is usually called from #initialize. Go, see for yourself. Browse implementors of #setDefaultParameters. We used that pattern and cleaned up many implementations of that message in the image.
Note that rounded corners, gradients, colorful windows, and shadows are still preferences outside of UI themes. You can toggle them in any UI theme.
Note that the background color/image is also not subject to be themed. Just drop your favorite picture or pattern in the image. It's really easy.
Now, take a look at the class SqueakTheme. There, you will find source code for creating the default Squeak theme to be shared via SqueakSource and reset during the release building process. :-)
Besides get/set/clear -- which might be expected from the theme structure because it is basically a dictionary with some properties -- There, you will notice a "merge" or "link" or "derive". When creating themes programmatically, you can:
- derive properties from other properties
- link themes to extend property look-up
- merge one theme into another theme
How does property look-up work? Well, see UserInterfaceTheme >> #get:
- Look up the key, which is usually "Class -> symbol".
- Try the superclass chain.
- Try the same lookup in the linked theme if any.
Theoretically, you could actually implement messages in subclasses of UserInterfaceTheme and bypass that DNU-triggered lookup. We do not do this right now.
As you can see, Squeak/Smalltalk offers a great deal of flexibility. It is remains subject to discussion of how to employ the language and its semantics. Think of the current implementation of user interface themes as one way that represents a trade-off between a concise programming interface (i.e. ... self userInterfaceTheme color ifNil ...), a fair amount of comprehensive patterns (i.e. #setDefaultParameters, #applyUserInterfaceTheme, ...), and some other existing constraints (i.e. old code, Monticello/Squeaksource, existing tools such as senders/implementors, ...).
Happy Squeaking!
Marcel, Chris, Karl
-- View this message in context: http://forum.world.st/ANN-Widget-Refactorings-UI-Themes-for-Squeak-tp4908439... Sent from the Squeak - Dev mailing list archive at Nabble.com.
squeak-dev@lists.squeakfoundation.org