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 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#a4697446 ... ======================== 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 |
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 <[hidden email]> wrote: Hi, there! :-) |
In reply to this post by marcel.taeumel
Yay, Marcel! Best, Karl On Thu, Jul 28, 2016 at 3:14 PM, marcel.taeumel <[hidden email]> wrote: Hi, there! :-) |
In reply to this post by cbc
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 |
In reply to this post by marcel.taeumel
On Thu, Jul 28, 2016 at 7:49 AM, marcel.taeumel <[hidden email]> wrote: <snip>
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.
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 |
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 <[hidden email]> wrote:
|
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 <[hidden email]> wrote:
|
In reply to this post by marcel.taeumel
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 <[hidden email]> 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#a4697446 > ... > > > ======================== > 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.html > Sent from the Squeak - Dev mailing list archive at Nabble.com. > |
In reply to this post by cbc
>> 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 |
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 <[hidden email]> 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-tp4908439p4908862.html > Sent from the Squeak - Dev mailing list archive at Nabble.com. > |
Free forum by Nabble | Edit this page |