[squeak-dev] [ANN] Widget Refactorings & UI Themes for Squeak

marcel.taeumel Marcel.Taeumel at hpi.de
Thu Jul 28 13:14:31 UTC 2016


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.


More information about the Squeak-dev mailing list