[squeak-dev] [ANN] Widget Refactorings & UI Themes for Squeak
asqueaker at gmail.com
Fri Jul 29 19:12:46 UTC 2016
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. :)
On Thu, Jul 28, 2016 at 8:14 AM, marcel.taeumel <Marcel.Taeumel at 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"):
> Here is a preview:
> *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
> 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;
> 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
> 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.
More information about the Squeak-dev