<?xml version='1.0' encoding='UTF-8' ?>
<rss version="2.0" xml:base="http://www.cincomsmalltalk.com/userblogs/antony/" xmlns:admin="http://webns.net/mvcb/" xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:icbm="http://postneo.com/icbm" xmlns:includedComments="http://www.laudably.com/rss2-comments" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://search.yahoo.com/mrss/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/">
	<channel>
		<title>The creation of a new order of things</title>
		<link>http://www.cincomsmalltalk.com/userblogs/antony/blogView</link>
		<description>The creation of a new order of things</description>
		<webMaster>antony.blakey@linkuistics.com.au</webMaster>
		<lastBuildDate>Thu, 08 May 2008 21:25:31 EDT</lastBuildDate>
		<image>
			<url>/images/why-small.png</url>
			<title>The creation of a new order of things</title>
			<link>http://www.cincomsmalltalk.com/userblogs/antony/blogView</link>
			<height>50</height>
			<width>81</width>
		</image>
		<admin:generatorAgent rdf:resource="/CincomSmalltalkWiki/Silt"></admin:generatorAgent>
		<admin:errorReportsTo rdf:resource="mailto:antony.blakey@linkuistics.com.au"></admin:errorReportsTo>
		<dc:language>en-us</dc:language>
		<dc:creator>Antony Blakey</dc:creator>
		<dc:rights>Copyright 2007 Antony Blakey</dc:rights>
		<dc:date>2008-05-08T21:25:31-04:00</dc:date>
		<icbm:latitude>47.2017</icbm:latitude>
		<icbm:longitude>-88.4024</icbm:longitude>
		<item>
			<title>SymbolValue, in Ruby.</title>
			<link>http://www.cincomsmalltalk.com/userblogs/antony/blogView?showComments=true&amp;printTitle=SymbolValue,_in_Ruby.&amp;entry=3387734731</link>
			<category>general</category>
			<pubDate>Thu, 08 May 2008 21:25:31 EDT</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>Ruby has the <a href="http://feeds.feedburner.com/%7Er/jlainenet/%7E3/286084657/amp-lified">SymbolValue</a> 'controversy', just like Smalltalk.</p>
</div>]]></description>
			<guid isPermaLink="false">3387734731</guid>
			<pingback:server>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIPBServlet?guid=3387734731</pingback:server>
			<pingback:target>http://www.cincomsmalltalk.com/userblogs/antony/blogView?guid=3387734731</pingback:target>
			<includedComments:comment-collection></includedComments:comment-collection>
			<wfw:comment>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIServlet?guid=3387734731</wfw:comment>
		</item>
		<item>
			<title>Heroku</title>
			<link>http://www.cincomsmalltalk.com/userblogs/antony/blogView?showComments=true&amp;printTitle=Heroku&amp;entry=3387734280</link>
			<category>general</category>
			<pubDate>Thu, 08 May 2008 21:18:00 EDT</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>I saw <a href="http://heroku.com/">Heroku</a> mentioned this morning on <a href="http://feeds.feedburner.com/~r/Techcrunch/~3/286241641/">TechCrunch</a>. It <a href="http://heroku.com/features">integrates</a> everything from generation to deployment to the cloud, with code management. <a href='http://s3.amazonaws.com/heroku_screencasts/code_editor.mov'>Editing</a> looks OK.</p>



<p>Ruby and Rails are juggernauts, and there's a lot of attention, training, documentation, and VC money going into it. I hope Cincom are putting enough resource into WebVelocity, because on all of the non-technical issues (which is what actually matters), the 80/20 solution is a giant.</p>
</div>]]></description>
			<guid isPermaLink="false">3387734280</guid>
			<pingback:server>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIPBServlet?guid=3387734280</pingback:server>
			<pingback:target>http://www.cincomsmalltalk.com/userblogs/antony/blogView?guid=3387734280</pingback:target>
			<includedComments:comment-collection></includedComments:comment-collection>
			<wfw:comment>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIServlet?guid=3387734280</wfw:comment>
		</item>
		<item>
			<title>Clutter: Cairo+</title>
			<link>http://www.cincomsmalltalk.com/userblogs/antony/blogView?showComments=true&amp;printTitle=Clutter:_Cairo+&amp;entry=3386266934</link>
			<category>general</category>
			<pubDate>Mon, 21 Apr 2008 21:42:14 EDT</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>I spotted this in the WebKit mailing list: <a href="http://clutter-project.org/">Clutter</a>. From the home page ...



<blockquote style='padding: 1em 1em 1em 1em; background-color: rgb(128,128,128);'>



<p>Clutter is an open source software library for creating fast, visually

rich and animated graphical user interfaces.</p>



<p>Clutter uses <a href="http://opengl.org">OpenGL</a> (and optionally <a

href="http://www.khronos.org/opengles/">OpenGL ES</a> for use on

Mobile and embedded platforms) for rendering but with an API which hides

the underlying GL complexity from the developer.  The Clutter API is

intended to be easy to use, efficient and flexible.</p>



<p>Clutter currently features the following:



<ul>

 <li>Scene-graph of layered 2D interface elements manipulated in 3D space via position, grouping, transparency, scaling, clipping and rotation.</li>

 <li>Frame based animation engine providing path interpolation, transitions and other custom effects via Behaviours and Timelines.

 <li>Scriptable <a href="http://json.org">JSON</a> based layout and animation file support.

 <li>Advanced input event handling.</li>

 <li>Custom <a href="http://www.pango.org">Pango</a> renderer providing efficient internationalised UTF8 text rendering.</li>

 <li>Support for high end Open GL features such as Shaders and FBOs.</li>

 <li>Support for media playback with <a href="http://gstreamer.freedesktop.org">GStreamer</a>, <a

href="http://cairographics.org">Cairo</a> graphics rendering and <a

href="http://gtk.org">GTK+</a> embedding are available via optional add-on libraries.</li>

 <li>Object oriented design via <a

href="http://developer.gnome.org/doc/API/2.0/gobject/index.html">GObject</a> with a familiar <a href="http://gtk.org">GTK+</a> like API.</li>

 <li>Runs on Linux, Windows and OSX with backend window system support for GLX, EGL, SDL and Cocoa.</li>

 <li>Support for mobile devices with fixed point internals and portability across Open GL and OpenGL ES</li>

 <li>Developed in C, with language bindings for Perl, Python, C#, C++, Vala and Ruby.</li>

</ul>

</p>



<p>Clutter aims to be non specific -- it implements no particular style, but

rather provides a rich generic foundation that facilitates rapid and easy

creation of higher level tool kits tailored to specific needs.</p>



<p>Clutter is free software released under the <a

href="http://www.gnu.org/licenses/lgpl.html">GNU LGPL</a>. It is

supported by both a growing open source community and commercially by

<a href="http://o-hand.com">OpenedHand</a>.</p>



<p>Visit the <a href="/blog">clutter blog</a> for the latest Clutter

news, developments, screen shots, screen casts and more.</p>



</blockquote>



<p>There is an in-progress port of <a href="http://www.clutter-project.org/blog/?p=50">WebKit that uses Clutter as it's backend</a>.</p>



<p>This might be a richer outcome for VW than a pure Cairo binding.</p>
</p></div>]]></description>
			<guid isPermaLink="false">3386266934</guid>
			<pingback:server>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIPBServlet?guid=3386266934</pingback:server>
			<pingback:target>http://www.cincomsmalltalk.com/userblogs/antony/blogView?guid=3386266934</pingback:target>
			<includedComments:comment-collection></includedComments:comment-collection>
			<wfw:comment>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIServlet?guid=3386266934</wfw:comment>
		</item>
		<item>
			<title>GroupLayout in VW</title>
			<link>http://www.cincomsmalltalk.com/userblogs/antony/blogView?showComments=true&amp;printTitle=GroupLayout_in_VW&amp;entry=3384634059</link>
			<category>general</category>
			<pubDate>Thu, 03 Apr 2008 00:07:39 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>My work on the VW version of GroupLayout has reached a usable state (although it's not finished). The window in the following screenshot is layed out using this new system.</p>



<p><img src='files/AL.18.png'/></p>



<p>All of the spacing is symbolic, and deferred to the UILookPolicy. Components can be baseline/top/left/bottom/right aligned, and not just in a hierarchic table-like fashion. I've implemented most of the system described <a href="http://java.sun.com/docs/books/tutorial/uiswing/layout/group.html">here</a>, although currently the baseline/preferredSize/minimumSize/maximumSize methods don't cover all of the UI components (and really only in ASBAqua). That's just because I haven't got around to it yet, not because it's difficult.</p>



<p>The <code>linkSize</code> mechanism isn't implemented because I haven't yet figured out how to do it, and <code>replace</code> and <code>honoursVisibility</code> may not be relevant. I intend to implement a Cocoa-like visualInsets mechanism that preserves alignment in the face of shadows/focus indicators - visual alignment is often not the same as bounding box alignment. Finally, I'm going to look into allowing the min/preferred/max dimensions to control the window sizing, so that you don't have to specify those properties on the window.</p>



<p>The important thing about this layout mechanism is that it can adjust to different fonts, different widgets, and different platform policy regarding spacing, all while preserving alignments and relationships. It responds well to resizing, and interoperates with the existing layout mechanism. It will give good results across platforms and L&Fs Furthermore it contains no explicit positioning, apart from specifying some preferred dimensions for e.g. popup menus and lists, that have no natural size independent of their model.</p>



<p>The layout code is reasonably verbose, but not as verbose as explicitly dimensioning every component. The layout code can be partitioned if there are sections of the UI that have strict rectangular bounds without external alignment requirements e.g. the filter specification at the top of the example dialog. Furthermore it's amenable to more convenient construction mechanisms such as regular grids, whilst maintaining identical behaviour to a non-hierarchic canonical specification.</p>



<p>This is all published in the Public Store (undocumented as yet), as ASBRB, although note that it requires StoreGlorp (because that's where the dialog is from) and you must be using ASBAqua, and hence the OSX L&F, on OSX. It will pull in a number of other packages that I've published as bundles such as Linkuistics and LinkuisticsUI. You can test two different versions of that dialog in a workspace:</p>



<blockquote style='border: 1px dotted grey; padding: 0 1em 0 1em; background-color: rgb(230,230,230);'><pre>

ASBReplicationUIGroupLayout open

ASBReplicationUIMixedLayout open

</pre></blockquote >



<p>The MixedLayout version uses the traditional layout mechanism for some of the controls, and a simple TableLayout for a few items. That's 'Mixed' as in 'Mongrel' :)</p>



<p>GroupLayout was originally designed for use with the <a href="http://www.netbeans.org/kb/41/flash-matisse.html">Matisse UI Builder</a>, and so it has a natural representation and interface when used in a visual context. I've haven't done any UIPainter integration, and at this stage I don't intend to, purely because I have no commercial imperative to do so and I have some other projects that are more important to me. Having said that though ...</p>



<p>I know that this layout mechanism can be incoprorated into UIPainter, which could also be significantly improved in other areas. The VW UI has often been mentioned in the mailing list as a significant stain on the product. Presuming that I first did all of the cross-L&F work to complete GroupLayout e.g. baselines etc, I'm wondering if there are any Cincom clients who would be interested in funding the work required (I estimate 3 months), on a shared-cost basis, to update the UIPainter to incorporate this style of layout and make it best-of-breed, rather than, well, whatever it is now. Yes folks, that's an ad.</p>



<p>As a precaution, I need to say that regardless of the URL of my blog, I am in no way affiliated with Cincom.</p>




</div>]]></description>
			<guid isPermaLink="false">3384634059</guid>
			<pingback:server>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIPBServlet?guid=3384634059</pingback:server>
			<pingback:target>http://www.cincomsmalltalk.com/userblogs/antony/blogView?guid=3384634059</pingback:target>
			<includedComments:comment-collection>
				<includedComments:comment>
					<includedComments:guid>blogView?showComments=true&amp;printTitle=GroupLayout_in_VW&amp;entry=3384634059</includedComments:guid>
					<includedComments:puid>blogView?showComments=true&amp;printTitle=GroupLayout_in_VW&amp;entry=3384634059</includedComments:puid>
					<includedComments:author>
anonymous</includedComments:author>
					<includedComments:pubDate>2008-04-03T18:59:02-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;Comment by 
anonymous&lt;/p&gt;

&lt;p&gt;


&lt;p&gt;What about actually redesigning the window instead of just lining it up right?&lt;/p&gt;
&lt;/p&gt;
&lt;/div&gt;</includedComments:content>
					<includedComments:title>
Redesign</includedComments:title>
				</includedComments:comment>
				<includedComments:comment>
					<includedComments:guid>blogView?showComments=true&amp;printTitle=GroupLayout_in_VW&amp;entry=3384634059</includedComments:guid>
					<includedComments:puid>blogView?showComments=true&amp;printTitle=GroupLayout_in_VW&amp;entry=3384634059</includedComments:puid>
					<includedComments:author>Antony Blakey</includedComments:author>
					<includedComments:pubDate>2008-04-03T19:14:23-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;As I said in my previous post: I've haven't given much thought to how the functionality of this dialog could be improved - I'm only trying to fix the existing layout - but if this were an OSX application I'd use a predicate editor control.&lt;/p&gt;
&lt;p&gt;My version of this dialog won't be replacing the one one in the StoreGlorp package, so improving the dialog itself would be pointless. This is only a stalking horse to demonstrate improvements relative to the published version, and the specific improvements I'm demonstrating here are to do with the layout engine. This does include my Aqua L&amp;amp;F improvements but I've been blogging about those at some length so you can see exactly what's been improved.&lt;/p&gt;
&lt;/div&gt;</includedComments:content>
					<includedComments:title>Re: Redesign</includedComments:title>
				</includedComments:comment>
			</includedComments:comment-collection>
			<wfw:comment>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIServlet?guid=3384634059</wfw:comment>
		</item>
		<item>
			<title>Into the Heart of Darkness - adventures in the VW UI framework.</title>
			<link>http://www.cincomsmalltalk.com/userblogs/antony/blogView?showComments=true&amp;printTitle=Into_the_Heart_of_Darkness_-_adventures_in_the_VW_UI_framework.&amp;entry=3383197231</link>
			<category>general</category>
			<pubDate>Mon, 17 Mar 2008 09:00:31 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>This post is primarily about some ongoing work I'm doing to improve the VW UI framework, focussing in particular on improving the layout machinery and platform fidelity.</p>



<p>As part of my Aqua L&F improvements I implemented an improved resizing splitter control. The way splitters work in VW is quite ugly - and that ugliness comes from VWs layout machinery and specification. The problem I had to work around is that VW layout forces the user to encode the size of controls in the layout. Layout is one of two major blights in the UI framework, the other being font and text handling.</p>



<p>There are other issues with the VW interface code, such as a very limited drawing facilities, but unlike the layout mechanism I don't classify that as a problem of poor design - it's just old.</p>



<h3>A layout problem example</h3>



<p>Consider a window containing a single vertical split. Currently you have to place three components with the following layout, where the numbers shown are the x-axis left/right ratio/offsets</p>



<blockquote style='border: 1px dotted grey; padding: 0 1em 0 1em; background-color: rgb(230,230,230);'><pre>

 [ Left ]      [ Splitter ]      [ Right ]

 0   0.5-2  0.5-2      0.5+3  0.5+3      1

</pre></blockquote >



<p>Note how the width of the splitter is encoded in the layout. It so happens out that the Aqua splitter is 9 pixels in the minor axis, but VW UIs are all encoded with a smaller size. Regardless of the actual value, the important fact is that it's an L&F parameter, and shouldn't be part of the user-specified layout.</p>



<p>I hacked a fix for this in ASBAqua by doing a one-shot initial adjustment of the dependent view's offsets which allows the splitter to determine it's own dimensions. But it is a hack and it immediately made me wish that splitters worked by containment i.e. the splitter component should contain the views it splits, and manage their layout.</p>



<p>After doing some work to improve the Aqua L&F I was intending to get back to working on version control, but this looked like some low hanging fruit of general applicability, it was an excuse to learn something about the UI internals, and it could resolve some issue I hadn't been able to solve in ASBAqua.</p>



<p>I also wanted to do some experiments with the navigation UI of the Refactoring Browser, although this was before saw the reaction to James Robertson's thought-experiment post about the RB UI. It seems to me that many Smalltalkers believe that everyone would see the obvious advantage of Smalltalk, if not for their lack of imagination, and adherence to what they already know. Yet reading the responses to that post - what irony! Maybe things were different in the days when Smalltalk didn't have the weight of a tradition; maybe it's the rebellious teenager become conservative adult, their once original ideas crystalized as dogma. Eclipse is not a piece of crap. Neither is Java, nor Haskell (the epitome of static typing), nor Scheme, nor anything that isn't Smalltalk.</p>



<p>Anyway, it's been quite a detour but I've ended up overhauling all of the layout mechanism in a backwards compatible fashion, and providing a number of smaller, but very useful enhancements such as Controller/View merging, and a Seaside canvas model for manually generating UIs - although I've come to the conclusion that visual UI building is in fact preferable, as long as the tool is really good. It's all done a way that either is already, or can be made compatible with, an improved UIBuilder, which I also discuss.</p>



<h3>Containment based splitter</h3>



<p>The first thing I did was to subclass CompositePart to make a splitter container. Turned out to be trivial, which was a pleasant surprise.</p>



<p>In order to test this I subclassed the refactoring browser and overrode the window spec. I converted the spec literal array to code that creates the Spec objects. This doesn't stop the UIBuilder working, and adding a single override in UIPainter allows such specs to be opened in the painter. It would be an easy mod to have the specs serialized out of the painter as code rather than literal arrays, which IMO would be preferable because it would make the construction of the UI less opaque.</p>



<p>At this point it was still passive i.e. it didn't respond to the mouse. Here's the window spec:</p>



<blockquote style='border: 1px dotted grey; padding: 0 1em 0 1em; background-color: rgb(230,230,230);'><pre>

windowSpec

  &lt;resource: #canvas&gt;

  ^UI.FullSpec new

    window:

        (Linkuistics.UI.LUIWindowSpec new

            bounds: (0 @ 0 corner: 800 @ 600);

            min: 472 @ 312;

            menu: #menuBar;

            toolBar: #toolbarMenuHolder;

            useSavedDimensions);

    component:

        (Linkuistics.UI.LUISplitterSpec new

            initialFraction: 0.33;

            beHorizontal;

            add:

                (UI.SubCanvasSpec new

                    majorKey: #NavigatorTool;

                    minorKey: #windowSpec;

                    clientKey: #navigator;

                    name: #navigator);

            add:

                (UI.SubCanvasSpec new

                    majorKey: #CodeModelSubcanvas;

                    minorKey: #windowSpec;

                    clientKey: #codeTool))

</pre></blockquote>



<p>Note the lack of layout. The splitter does the layout for it's children, so they don't need any, and the default layout of my composite class is a LayoutFrame with (0.0+0,1.0+0) in both axis.</p>



<p>I subclassed the WindowSpec so that setting the menu also sets the flags that indicate a menu should be used. That could be a WindowSpec override, but I bet it would break someone, somewhere. Damn you, whitebox! :)</p>



<p>The UIPainter correctly shows the containment in this spec, but it really doesn't handle containment in any meaningful way. It's not that it couldn't be done, and probably without too much effort, but it currently presumes all views are peers except for one specific type of group.</p>



<h3>A merged Controller/View generic container</h3>



<p>To get the event handling working in the composite splitter, I copied code from Searchlight. Michael Lucas-Smith had developed a merged Controller/View using a state machine concept with state-based selectors e.g. if you are in 'pressed' state then the selector is "<code>pressedMouseMovedEvent: anEvent</code>", with a fallback to "<code>MouseMovedEvent: anEvent</code>", along with optional handlers for state transitions. It worked easily for my case and was very simple, but by this stage I was thinking about my composite in more ambitious terms. I couldn't see how to generalize and scale the FSM mechanism, particularly when dealing with components with many possibly coincident mouse regions, with a separate set of states for mouse-down tracking, each of which might involve different logic depending on where the mouse was originally pressed or what the keystate was (or is, during tracking).</p>



<p>This problem gave me a week of sleepless nights - literally. In the end I decided the solution required a model with less architectural commitment, so I developed a hybrid architecture. Each view has a (standard) tracker object that both handles mouse events and stores state relating to the tracking. The object is created every time the mouse enters the view and released when it exits (grabs don't exit until the mouse is released). In effect it acts as a transient controller, but it contains no user code and forwards filtered events to the view, using a "<code>mouseMoved:/mousePressed:/mouseDragged:/mouseReleased:</code>" protocol, with separate methods for different buttons ("<code>rightMousePressed:/centerMousePressed:</code>" et al). It handles drag offset increments, both from mouse press and last drag event, with limits that allow you to filter out drag events that would drag an object out of bounds whilst maintaining correct offset increments. It handles cursor tracking by sending cursorForPoint: to the view. I originally had a Cocoa NSView-like mechanism for declarative cursor regions but it was overkill for my particular use case, and in any case NSView uses it because it prefers not to deliver mouse motion events to the view. You can override the class of the tracker to extend it with additional mouse-only transient state and behaviour, although adding non-policy-pattern behaviour would conceptually de-merge the Controller from the View.  The reason it's transient is so I could be profligate with state without burdening the view. I anticipate adding functionality to the generic tracker for e.g. processing points for path construction, selection rollover, and handling transient key states to modify mouse behaviour e.g. shift/ctrl-down. Adding these things to the tracker simplifies the view whilst still allowing the Controller/View to be merged.</p>



<p>I don't know if this general architectural device is that useful for key handling - although focus provides a similar lifecycle boundary, there is less dynamic state involved. Even so, it might be worth it just for the sake of architectural uniformity.</p>



<p>After fixing a few bugs in the EventDispatcher that deal with exit/enter events, the splitter was fully functional.</p>



<h3>A Seaside canvas model of spec construction.</h3>



<p>I suspected I was going to be doing a lot more nesting as this work progressed, so I wrote a simple Seaside-like canvas model for building specs. The canvas model is very convenient for nested structures, primarily because of the "<code>with: [...]</code>" pattern. Using a block without an argument makes out-of-order construction less convenient, if not impossible, because the stack is transient and the top of the stack implicit, but that's an appropriate trade-off for Seaside because it allows the canvas to be streamed. That's not a requirement in this case because the result is a data structure, but I stuck with the niladic block because it looks better. The implementation is trivial, primarily because I use proxies around the specs rather than specific brush types. This is a necessary feature for non-intrusive arms-length interoperability with user-defined specs.</p>



<p>Here's what the refactoring browser window spec looks like now:</p>



<blockquote style='border: 1px dotted grey; padding: 0 1em 0 1em; background-color: rgb(230,230,230);'><pre>

windowSpec

  | canvas |

  canvas := Linkuistics.UI.LUICanvas new.

  self windowSpecOnCanvas: canvas.

  ^canvas fullSpec.

</pre></blockquote>



<blockquote style='border: 1px dotted grey; padding: 0 1em 0 1em; background-color: rgb(230,230,230);'><pre>

windowSpecOnCanvas: canvas

  canvas window

    bounds: (0 @ 0 corner: 800 @ 600);

    min: 472 @ 312;

    menu: #menuBar;

    toolBar: #toolbarMenuHolder;

    useSavedDimensions.

  canvas splitter initialFraction: 0.33; beHorizontal;

    with:

        [canvas subCanvas

          majorKey: #NavigatorTool;

          minorKey: #windowSpec;

          clientKey: #navigator;

          name: #navigator.

        canvas subCanvas

          majorKey: #CodeModelSubcanvas;

          minorKey: #windowSpec;

          clientKey: #codeTool]

</pre></blockquote>



<p>The improvement is more obvious when dealing with more complicated UIs.</p>



<p>A number of ideas occur looking at this. The canvas could do the building, rather than creating a separate spec tree. The UIPainter could capture the structure by using a different canvas class. By using a pattern such as "<code>canvas render: self using: #selector with: ...</code>" to partition the code, the UIPainter could also preserve the decomposition of the UI into separate methods when it regenerates.</p>



<h3>Enriching the dimensional model of parts</h3>



<p>The next step was to attack a more complicate example - the GlorpStoreReplication (GSR) window. Apart from the now-fixed splitter issues, the two issues I wanted to fix were a) the checkbox label baselines don't line up with the input field text baselines; and b) The "</code>&gt;&gt;</code>" button changes size as the window changes size, and I couldn't see a way to fix the dynamic behaviour of the button using the existing layout mechanism. Of course everything was explicitly positioned using layout objects. I could fix the alignment issue explicitly for a particular L&F, but not in a generic fashion e.g. one L&F would be right and the others not.</p>



<p>This is what the GPR window looks like without any modifications:</p>



<p><img src='files/AL.3.pre.png' /></p>



<p>The first problem I looked at was the issue of vertically aligning views on a baseline. Font metrics calculations in VW are very basic - just a line height and descent. Furthermore, the values the VM returns on OSX are wrong because it does some rounding in the primitive. I did some work to allow you to manually specify top/bottom leading, ascent and descent for a font which gives me a correct baseline for the 11pt Lucida Grande used in ASBAqua, but I subsequently realised (obviously) that for baseline alignment in single-font UIs it doesn't matter if it's wrong, because it's only used in a relative fashion. A good reason to want correct values however is so that you can line up text within controls, which you can't really do unless you know the ascent and descent and top leading. Top leading wouldn't be necessary if text was drawn relative to the ascent, but as should now be obvious, VW draws text relative to top leading + ascent, whereas the visual weight of the character lies between ascent + descent. The VM draws text according to it's naive and incorrect baseline, which therefore needs to be preserved, so I added parallel values for the four corrected parameters that can now be set as shown below (the example is from ASBAqua). Font metrics for character advance/widths are also wrong, at least on OSX, but fixing that is not in scope for this diversion.</p>



<blockquote style='border: 1px dotted grey; padding: 0 1em 0 1em; background-color: rgb(230,230,230);'><pre>

defaultSystemFontAttributes

  | characterAttributes textAttributes |

  characterAttributes := CharacterAttributes newWithDefaultAttributes.

  characterAttributes setDefaultQuery: 

    (FontDescription new name: 'Lucida*Grande*'; pixelSize: 11).

  textAttributes := Linkuistics.UI.LUITextAttributes new.

  textAttributes setCharacterAttributes: characterAttributes.

  textAttributes lineGrid: 16.

  textAttributes baseline: 10.

  textAttributes luiTopLeading: 3.

  textAttributes luiAscent: 9.

  textAttributes luiDescent: 2.

  "luiBottomLeading = lineGrid - luiTopLeading - luiAscent - luiDescent"

  ^textAttributes

</pre></blockquote>



<p>Once this was done, I simply added baseline methods to the relevant wrappers and parts. For top/bottom/left/right alignment purposes however, you also need another set of dimensions, which are the visual body alignment points. Typically these are inset somewhat from the part bounds because they represent the visually significant lines in the control, such as the top and bottom dark grey lines in OSX buttons. The part bounds extend beyond that because of shadows and focus indication, so you can't use the bounds for alignment purposes. Each type of control, and each visual variant within a control (OSX has many), can have a different amount of inset from the bounds, so it does have to be on each part. I haven't done this yet because I'm focusing on baseline alignment to start with. When I do, I'll add a visualInsets method to Wrappers and Parts, because the insets are typically constants wrt. a given L&F.</p>



<h3>A table based layout container</h3>



<p>At the top of the GPR window is a matrix of text fields and checkboxes. The obvious solution is a table layout, ala HTML. This was very easy, involving spec classes for tables, rows and cells, and a table part. The rows and cells are part of the table data structure rather than being represented as parts, but there's no isomorphism requirement on the spec and part trees, so that posed no problem. Although maybe I'm misunderstanding the role of SpecWrapper?. I implemented a non-configurable layout to start with - vertical baseline alignment with allocation being equal to the component preferred bounds in both axes. This immediately threw up a problem with input fields: the preferred bounds of an input field is the size of it's content. I solved this by adding a width attribute to the input field, which is a sort of poor-mans layout spec. My intention was that the width attribute could be a string containing some exemplar text that would be measured to generate a preferred width, which would allow the font metrics of the part to determine the actual width with the user supplying the exemplar at design time. However I've only implemented a numeric width so far.</p>



<p>When I got around to including popup menus in the table, a similar problem occurred, although in this case a popup menu doesn't really have a preferred bounds. It could consult it's model to determine the maximum width, but the model is dynamic, so either the menu would potentially change width as the model changes, or it would only reflect the initial model contents. And in any case, sometimes the model will be empty. An exemplar string width mechanism would have worked, but as a shortcut I decided to use the component's existing layout specification (if supplied) to determine the width while ignoring the layout's height calculation.</p>



<p>Allowing LayoutFrames to be only partially specified would be a good idea that would have obviated the need for a numeric width or special handling of the layout height. The width of a component could be fixed whilst allowing it to keep it's preferred height. The fact that you can't do this requires a nasty hack in ASBAqua to reset the height of input fields, which should be sized according to the font metrics but end up being a user-specified (incorrect) height because FrameLayout determines the height and width. I couldn't just modify FrameLayout because the change would likely break existing code, and I wanted to transparently 'fix' existing UIs.</p>



<p>The canvas mechanism really comes into it's own with this layout. Below is the method that specifies the spec of the filter properties. Note that there are no calls to add cells within rows. Because single component cells are quite common, the table puts each component added to a row outside of an open cell into a new cell.</p>



<blockquote style='border: 1px dotted grey; padding: 0 1em 0 1em; background-color: rgb(230,230,230);'><pre>

filterSpecOnCanvas: canvas

  (canvas table)

    layout: 4 @ 2;

    cellSpacing: 5 @ 2;

    with:

        [canvas tableRow

            with:

              [canvas checkBox

                model: #topLevelOnly;

                helpText: 'Should we retrieve only top level items, meaning things not contained by a bundle.';

                label: 'Top Level Only'.

              canvas checkBox

                model: #queryPundleName;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                label: 'Named'.

              canvas inputField

                model: #queryPundleNameText;

                width: 150;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                helpText: 'Find pundles whose name matches this.'.

              canvas checkBox

                model: #queryPublishDate;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                label: 'Published in the last (days)'.

              canvas inputField

                width: 150;

                model: #queryPublishDateText;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                helpText: 'Has this been published in the last N days.';

                type: #number;

                formatString: '0'].

          canvas tableRow

            with:

              [canvas checkBox

                model: #retrieveBundles;

                helpText: 'Should we retrieve bundles?';

                label: 'Bundles'.

              canvas checkBox

                model: #queryClassName;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                label: 'Defines Class'.

              canvas inputField

                width: 150;

                model: #queryClassNameText;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                helpText:

                    'Find pundles that define this class.' ,

                    ' Unlike method/shared queries, this is a short classname.'.

              canvas checkBox

                model: #queryPublisher;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                label: 'Published By'.

              canvas inputField

                width: 150;

                model: #queryPublisherText;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                helpText: 'Things that have a version published by someone matching this name.'].

          canvas tableRow

            with:

              [canvas checkBox

                model: #retrievePackages;

                helpText: 'Should we retrieve packages?';

                label: 'Packages'.

              canvas checkBox

                model: #queryMethodsInClass;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                label: 'Defines Methods In'.

              canvas inputField

                width: 150;

                model: #queryMethodsInClassText;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                helpText:

                    'Find pundles that define methods in the given class.' ,

                    ' For class methods, use "%Name class".' ,

                    ' This is the long class name, so "%.ClassName" is a good idea.'.

              canvas checkBox

                model: #queryMethodName;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                label: 'Defines Method'.

              canvas inputField

                width: 150;

                model: #queryMethodNameText;

                callbacksSpec: (UI.UIEventCallbackSubSpec new valueChangeSelector: #updateSourceItems);

                helpText: 'Find pundles that define a method (class or instance) matching this name.']]

</pre></blockquote>



<p>And this is what the window looks like with all the modifications described so far:</p>



<p><img src='files/AL.15.png'></p>



<p>Obviously there's more to do. For example: the window contents should have a platform-specific border indent, the spacing between controls should match platform specs, and the table of filter elements doesn't resize. If it did resize, then the text input fields should take up the extra space while ensuring that both columns remain the same width. Currently when the dialog expands the button between the two major sections expands as well. I can't currently think of any existing layout spec that would preserve the size of the button and the space on either side while still distributing the extra space between the left and right components. Here's an Interface Builder version of that dialog (with a layout error :).</p>



<p><img src='files/AL.16.png'></p>



<p> I've haven't given much thought to how the functionality of this dialog could be improved - I'm only trying to fix the existing layout - but if this were an OSX application I'd use a predicate editor control.</p>



<p><img src='files/AL.17.png'></p>



<h3>Different models of layout</h3>



<p>The next step was to add more parameters to the table layout, both for different alignments and to control column widths, both static and dynamic. But I've always found the limited specifications available with HTML tables to be annoying, so I wanted to do something better. My first thought was to make vertical and horizontal guides into first class layout entities, with controls aligned to guides rather then to each other. The attraction of this idea is that it has an obvious visual representation in the UIPainter, and to my mind at least would be easy to understand. Of course the guides themselves need to move to maintain spacing between components. I suspected that the constraints could be be solved using linear allocation on each axis independently, with some mechanism for nesting and allowing correlated dimensions for non-adjacent components.</p>



<p>This looked like a good point to do a literature search on using constraint solvers for UI layout. Coincidentally, a lot of work in this field was done by Alan Borning in Smalltalk, funded partially by OTI. I looked at a lot of papers, and the one that was most appealing (and most recent) was <a href="http://citeseer.ist.psu.edu/lutteroth06user.html">User Interface Layout with Ordinal and Linear Constraints</a>, which is followed up in <a href="https://www.se.auckland.ac.nz/research/trReports/details/?tid=UoA-SE-2007-6">this paper</a>. Conceptually it's similar to what I had imagined, although they've done the heavy lifting.</p>



<p>Another category of result that came up in searches was Java layout mechanisms, particularly <a href="http://www.jgoodies.com/articles/forms.pdf">FormLayout</a> from Karsten Lentzsch's JGoodies product (which I've used extensively) and <a href="http://java.sun.com/docs/books/tutorial/uiswing/layout/group.html">GroupLayout</a>, which is used by the <a href="http://www.netbeans.org/kb/41/flash-matisse.html">Matisse UI Builder</a>. I have no experience with GroupLayout because it was introduced after I had stopped doing Java UI work. I'd forgotten about FormLayout, but once reminded I realised that it was a much better option than replicating the HTML table model. FormLayout is supported by a number of Java UI builders, such as <a href="http://www.jformdesigner.com/">jFormDesigner</a>, and Instatiations WindowBuilder Pro.</p>



<p>In hindsight it's obvious that Java is the place to look for ideas about this stuff. Swing has exactly the same issues as VW because it's uses synthetic components, and UIs have to adapt to different L&Fs and different font metrics. I'm still amazed at how I didn't realise this given I've been working in Java since the mid 90s, and still do. Talk about not seeing your own nose!</p>



<p>For now I've decided to concentrate on the GroupLayout layout manager, on the basis of it's relative simplicity and the fact that I'm impressed with Matisse. It also seems conceptually related to both my idea about first class guides and the Lutteroth and Weber papers.</p>



<h3>Programmatic vs. Visual UI design</h3>



<p>The quality of the UI builder experience that can be supported by different layout systems is a critical factor in the choice of a layout system, hence the relevance of the UI Builder support for the Java layouts I mentioned above. In a couple of <a href="http://www.cincomsmalltalk.com/userblogs/antony/blogView?showComments=true&amp;printTitle=Improving_GUI_building_in_VW,_incrementally,_with_backwards_compatibility.&amp;entry=3379783821">blog</a> <a href="http://www.cincomsmalltalk.com/userblogs/antony/blogView?showComments=true&amp;printTitle=Improving_GUI_building_in_VW,_incrementally,_with_backwards_compatibility_(2)&amp;entry=3379867487">entries</a> recently, I said that I wasn't a fan of Graphical UI Building. I've reflected on that since, and realise that most of my antipathy comes from doing an enormous amount of Web work where I had to take HTML generated by Dreamweaver and similar tools, clean up the structure, and convert to CSS for use in dynamic page generation. When it comes to HTML, I far prefer the Seaside technique.</p>



<p>However, I have never programatically generated a GUI on NextStep or OSX. It wouldn't occur to me not to use Interface Builder. So I think the issue is more the quality of the tool, and how well it's integrated into the language/OS/environment. Thus my opinion about UI building in VW has completely changed. I think the appropriate course is to improve the UIPainter - which IMO is ugly both in it's own right and because of the existing layout system. Obviously all of these changes need to be compatible with the existing infrastructure, which I think is possible, especially considering that I've been using a mix of new and old layout mechanisms as I've been developing. Improving the UIPainter doesn't seem like too much work, especially if it could be forked.</p>



<p>And I've got an inkling that these layout techniques can be used to layout HTML as well, which opens up some interesting options for visual design of interfaces that are serialised as Seaside canvas code. IMO any system that doesn't allow people to use a visual designer is going to have a limited market. Having said that though, a small slice of an enormous pie can still be a lot of pie :)</p>



<h3>The end ...</h3>



<p>OK, that's quite a dump :) The reason I've posted this is because I'd really like some feedback, and I have to put it down for a bit to do some Java webwork for a client. Given this is my first trek into the guts of the UI I may be missing some critical problem. Am I out to lunch? Does anyone have an pointers to other useful work?</p>



<p>All of this is published in the Public Store. If you're on 7.6, and load ASBRB, you can start my GSR window like this:</p>



<blockquote style='border: 1px dotted grey; padding: 0 1em 0 1em; background-color: rgb(230,230,230);'><pre>

ASBReplicationUI open

</pre></blockquote>



<p>There's a bug in the event handling for checkboxes in tables - you have to double click to set/reset them.</p>



<p>One word of warning to ASBAqua users however - this is a work-in-progress, and the current version of ASBAqua may have regressions.</p>


</div>]]></description>
			<guid isPermaLink="false">3383197231</guid>
			<pingback:server>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIPBServlet?guid=3383197231</pingback:server>
			<pingback:target>http://www.cincomsmalltalk.com/userblogs/antony/blogView?guid=3383197231</pingback:target>
			<includedComments:comment-collection></includedComments:comment-collection>
			<wfw:comment>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIServlet?guid=3383197231</wfw:comment>
		</item>
		<item>
			<title>Using a wiki as data store</title>
			<link>http://www.cincomsmalltalk.com/userblogs/antony/blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</link>
			<category>general</category>
			<pubDate>Wed, 27 Feb 2008 00:16:32 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>After listening to the recent IM podcast where Randy Coulman was talking about <a href="http://www.fitnesse.org">FITnesse</a>, I downloaded the software and had a look. I'll probably use it, but that's not really what this post is about.</p>



<p>The underlying implementation concept of FITnesse, where tables in a wiki are used as data for input into another process, got me thinking. I do the accounts for two contracting companies that my business partner and I run. Originally we used Quickbooks, but double entry accounting drives me crazy, so we switched to e-Record, which is a cash-accounting package supplied by the Australia Tax Office. Even so, it's still a PITA because there's no way to add notes to entries, particularly for non-obvious intercompany transactions or director asset puchases, and the interface is abysmal. Also it doesn't track Workcover or ASIC, and there's nowhere for links to sites or records phone conversations with the ATO etc etc. Finally, it just isn't clear to me what should be going on in the calculations, and I really, really hate not having a clear understanding of stuff like that. Hate it with a passion.</p>



<p>I'd done a preliminary pass at storing the records in XML and constructing the reports using XSLT, but that only solved the problem of understanding, not the additional stuff like providing annotated records for our accountant, nor does it keep me clear on what I've done. It's a lot like coding in that sense of coming back to something you've done and not understanding it.</p>



<p>Anyway, it should be obvious where I'm going with this. I've put my accounting records into <a href="http://trac.edgewall.org">Trac</a>, simply because it's the wiki software I have installed for it's software development focus and svn/bzr integration. The records are represented as tables in pages - one or more records per table, multiple tables merged, table types by context or header row - which can be surrounded by prose descriptions, and links etc. I can organise stuff in different pages in whatever way makes it easier to understand. A simple bit of ST in VW to suck the pages and do any calculations required (or just validity checking), and Robert's your relative! I can even get VW to update pages, although that's a PITA in Trac because it has no API. Maybe <a href="http://www.atlassian.com/software/confluence/">Confluence</a> would be better. Or an ST wiki, although that's maybe tighter coupling than I'd like. Obviously the code for interacting with an external wiki could be packaged to make this kind of stuff reusable. I tried <a href="http://flyingmeat.com/voodoopad/">VoodooPad</a>, which I use for documentation, and although it will work for extraction, I'm not sure about the reverse. BTW, if you're on OSX I recommend both <a href="http://flyingmeat.com/acorn/">Acorn</a> and <a href="http://flyingmeat.com/flysketch/">FlySketch</a> from the same company.</p>



<p>With appropriate extensible editing support in the wiki software, these embedded tables could be made richer, with metadata that doesn't normally show, annotated with some graphical indicator to control the visibility of the data. This would make this idea even more powerful - a combination of wiki prose with easily embedded data controls.</p>



<p>And moments after the idea of accounting records came up, I thought about literate programming in an ST context. I'm going to try putting some markers in wiki text that allow ST code/hierarchies etc to be automatically inserted/updated. This means I can write tutorials and documentation that includes ST inline, without having to copy and paste. The update process can also mark those insertion points that have changed relative to the existing version so I can see what needs updating as the code changes. I know it sounds like a hack - I'm ignoring e.g. versioning of the documentation - but it feels like a simple idea that won't be too hard to try. Very 80/20.</p>
</div>]]></description>
			<guid isPermaLink="false">3381524192</guid>
			<pingback:server>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIPBServlet?guid=3381524192</pingback:server>
			<pingback:target>http://www.cincomsmalltalk.com/userblogs/antony/blogView?guid=3381524192</pingback:target>
			<includedComments:comment-collection>
				<includedComments:comment>
					<includedComments:guid>blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</includedComments:guid>
					<includedComments:puid>blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</includedComments:puid>
					<includedComments:author>Greg</includedComments:author>
					<includedComments:pubDate>2008-02-27T05:53:27-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;Email ID Validations in smalltalkhelp needed
&lt;/p&gt;&lt;/div&gt;</includedComments:content>
					<includedComments:title>please help</includedComments:title>
				</includedComments:comment>
				<includedComments:comment>
					<includedComments:guid>blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</includedComments:guid>
					<includedComments:puid>blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</includedComments:puid>
					<includedComments:author>Dave</includedComments:author>
					<includedComments:pubDate>2008-02-27T08:40:49-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;We've been using a wiki for some internal documentation.  A script introspects the database and for each table writes two pages on the wiki: a "generated" page and a "human editable page".  We add links and notes to the human editable page.  When the script is re-run (on schema change), the new generated page is diffed against the old generated page and the patch applied to the old human editable change.

So the wiki is sort of a versioned datastore, but it's more of a system for easy browsing and editing.

Instead of an API, we're using URL's and screen-scraping (Mechanize and BeautifulSoup) which could be better.
&lt;/p&gt;&lt;/div&gt;</includedComments:content>
					<includedComments:title>Used for documenting our database</includedComments:title>
				</includedComments:comment>
				<includedComments:comment>
					<includedComments:guid>blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</includedComments:guid>
					<includedComments:puid>blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</includedComments:puid>
					<includedComments:author>jay</includedComments:author>
					<includedComments:pubDate>2008-02-27T13:26:19-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;Why not try google docs?&lt;/p&gt;&lt;p&gt;There&amp;#39;s a nice API for their spreadsheets... I could see security being a concern but I&amp;#39;d guess it&amp;#39;s no bigger an exposure (you&amp;#39;re trusting google after all) then other existing instances of interoperability &amp;amp; data exchange.&amp;nbsp; &lt;/p&gt;
&lt;/div&gt;</includedComments:content>
					<includedComments:title>google docs?</includedComments:title>
				</includedComments:comment>
				<includedComments:comment>
					<includedComments:guid>blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</includedComments:guid>
					<includedComments:puid>blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</includedComments:puid>
					<includedComments:author>Antony Blakey</includedComments:author>
					<includedComments:pubDate>2008-02-27T16:41:07-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;Jay,

&lt;p&gt;I use google docs, but the spreadsheet isn't what I want for accounts because that still doesn't allow the kind of prose-form layout I'm looking for.&lt;/p&gt;

&lt;p&gt;And using their word processor doesn't allow for the hyperlinked wiki-type structure I want either.&lt;/p&gt;
&lt;/p&gt;&lt;/div&gt;</includedComments:content>
					<includedComments:title>Re: google docs</includedComments:title>
				</includedComments:comment>
				<includedComments:comment>
					<includedComments:guid>blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</includedComments:guid>
					<includedComments:puid>blogView?showComments=true&amp;printTitle=Using_a_wiki_as_data_store&amp;entry=3381524192</includedComments:puid>
					<includedComments:author>Bill Roberts</includedComments:author>
					<includedComments:pubDate>2008-03-05T12:36:24-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;Very interesting post.&amp;nbsp; My company, Swirrl, is working on a new wiki-for-data product along the lines of what you are describing.&amp;nbsp; It's useful to hear your thoughts on the importance of being able to combine the data with commentary, all on one wiki page, as that's something we've been thinking about recently. Similarly your points about APIs and integration with other systems.&lt;/p&gt;
&lt;p&gt;We're aiming to launch in summer 08 - if you are interested, we'll be posting progress reports on our blog:&amp;nbsp; http://blog.swirrl.com&lt;/p&gt;
&lt;/div&gt;</includedComments:content>
					<includedComments:title>wikis for data</includedComments:title>
				</includedComments:comment>
			</includedComments:comment-collection>
			<wfw:comment>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIServlet?guid=3381524192</wfw:comment>
		</item>
		<item>
			<title>ASBAqua look experiments split from Aqua enhancements</title>
			<link>http://www.cincomsmalltalk.com/userblogs/antony/blogView?showComments=true&amp;printTitle=ASBAqua_look_experiments_split_from_Aqua_enhancements&amp;entry=3380993091</link>
			<category>general</category>
			<pubDate>Wed, 20 Feb 2008 20:44:51 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>I've split the look experiments, which are primarily icons at this stage, out of ASBAqua package into ASBLook. Thus you can get the Aqua improvements on it's own.</p>



<p>As part of that process I've replace the bundle/package icons with ones more in keeping with the philosophy of the other icons, viz:</p>



<p><img src='http://www.cincomsmalltalk.com/userblogs/antony/files/AL.14.png' /></p>
</div>]]></description>
			<guid isPermaLink="false">3380993091</guid>
			<pingback:server>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIPBServlet?guid=3380993091</pingback:server>
			<pingback:target>http://www.cincomsmalltalk.com/userblogs/antony/blogView?guid=3380993091</pingback:target>
			<includedComments:comment-collection></includedComments:comment-collection>
			<wfw:comment>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIServlet?guid=3380993091</wfw:comment>
		</item>
		<item>
			<title>Improving the look of VW on OSX - a harmonized icon set</title>
			<link>http://www.cincomsmalltalk.com/userblogs/antony/blogView?showComments=true&amp;printTitle=Improving_the_look_of_VW_on_OSX_-_a_harmonized_icon_set&amp;entry=3380949119</link>
			<category>general</category>
			<pubDate>Wed, 20 Feb 2008 08:31:59 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>New version of ASBAqua, and this time a warning. This version contains a nearly compete set of aesthetically harmonized replacement icons for the RB, including class icons, and SUnitToo(ls). So if you hate the few icon changes I've made so far - yes, some people hate them :) - then stay away from this release, because it's a radical looking change. I'm going to split these changes off to a new package so you can just load the Aqua look enhancements without the general graphic mods that are currently included.</p>



<p>I've got a post in the works about the theory of these changes - and yes, there is a largely non-subjective rationale at work.</p>



<p>To whet your appetite, or turn your stomach completely inside out if you're not a fan, here's the obligatory screenshot:</p>



<p><img src='http://www.cincomsmalltalk.com/userblogs/antony/files/AL.13.png' /></p>
</div>]]></description>
			<guid isPermaLink="false">3380949119</guid>
			<pingback:server>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIPBServlet?guid=3380949119</pingback:server>
			<pingback:target>http://www.cincomsmalltalk.com/userblogs/antony/blogView?guid=3380949119</pingback:target>
			<includedComments:comment-collection>
				<includedComments:comment>
					<includedComments:guid>blogView?showComments=true&amp;printTitle=Improving_the_look_of_VW_on_OSX_-_a_harmonized_icon_set&amp;entry=3380949119</includedComments:guid>
					<includedComments:puid>blogView?showComments=true&amp;printTitle=Improving_the_look_of_VW_on_OSX_-_a_harmonized_icon_set&amp;entry=3380949119</includedComments:puid>
					<includedComments:author>Reinout Heeck</includedComments:author>
					<includedComments:pubDate>2008-02-20T20:03:49-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;A lot of the icon sets we see lately suffer from the fact that I need to &amp;#39;read&amp;#39; them.&lt;br /&gt;&lt;br /&gt;The debugger icons in the vw7.4 series for example registered in my brain as &amp;#39;triangle haze&amp;#39;, a whole new character set that I had to learn to read, and found I have to keep reading even after using them for quite a long time. The original icon set looked horrible but was much more functional: at a glance my brain new what they meant and my hand would move the mouse towards them without me spending conscious effort.&lt;br /&gt;&lt;br /&gt;Your screenshot nicely illustrates both good icons and bad icons in this respect: the package list shows icons that are in my &amp;#39;sweet&amp;#39; spot, they talk to me and in a calm voice, communicating the kind and state of entries in that list without conscious effort.&lt;br /&gt;&lt;br /&gt;The class list on the other hand crams graffiti into a space that is even narrower than the class names, they pretty much duplicate what I can already glean from the class names but require me to read twice. Note that I&amp;#39;m not talking about aesthetics here but about semiotics: icons that are aesthetically pleasing can at the same time be a pain to work with.&lt;br /&gt;&lt;br /&gt;So I strongly advice you to meditate on those childish looking buttons on the original PDP since they were so great to work with, aesthetics should be second to semiotics in professional tools.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As to the test methods I want to remark that showing three result states is more than we are interested in from a tool perspective, just differentiate &amp;#39;pass&amp;#39; from the other two states. And then again the semiotics: a red dot vs a green dot will do a much better job than the &amp;#39;paintings&amp;#39; you have up there now. The aesthetic endeavor should IMO focus on making such dots easy on the eye, not on creating a cartoon that tells a story that I don&amp;#39;t want to read a million times over the course of my day job.
&lt;/p&gt;&lt;/div&gt;</includedComments:content>
					<includedComments:title>Why icons that I have to read?</includedComments:title>
				</includedComments:comment>
				<includedComments:comment>
					<includedComments:guid>blogView?showComments=true&amp;printTitle=Improving_the_look_of_VW_on_OSX_-_a_harmonized_icon_set&amp;entry=3380949119</includedComments:guid>
					<includedComments:puid>blogView?showComments=true&amp;printTitle=Improving_the_look_of_VW_on_OSX_-_a_harmonized_icon_set&amp;entry=3380949119</includedComments:puid>
					<includedComments:author>Antony Blakey</includedComments:author>
					<includedComments:pubDate>2008-02-20T20:11:30-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;Reinout, I appreciate your feedback - it matches my intuition in spite of what you see.&lt;/p&gt;

&lt;p&gt;Some comments on the hieroglyphics...&lt;/p&gt;

&lt;p&gt;Most of those icons are for use in inspectors, where you don't have the class name to guide you as to the type of the value. You normally wouldn't see them while using the browser e.g. String/True/False etc.&lt;/p&gt;

&lt;p&gt;&lt;p&gt;Some of the icons e.g. SUnit are semantically overloaded and IMO there need to be more (unobtrusive) channels or annotative mechanisms to show combinations such as 'this is a test method' + 'pass/fail/notrun/error'. That's the same problem with the existing overloaded package/bundle icons that show type + is-it-db-connected + is-it-changed, all in the icon space.&lt;/p&gt;

&lt;p&gt;Also, you can't use interface items (such as a dot) that differ only in colour, especially red/green, because of colour blindness issues - 7% to 10% of males are red/green colour blind. That's why the success/failure forms of my SUnit icons also have a different meter-indicator position.&lt;/p&gt;

&lt;p&gt;Finally, the icons that show type for the purposes of subclass classification e.g. Exception/Model/ApplicationModel/Announcement are I think genuinely useful. I'm also going to try and add a line between the top navigation and the bottom tabbed area that shows a hyperlinked inheritance hierarchy for the currently selected class, so it's always visible, and also make it much easier to quickly turn on method visibility to include part of that tree.&lt;/p&gt;

&lt;p&gt;There are a number of other ideas I'm looking at for different views/ways of navigating the image, including a Whisker-like tool, and entire-class-at-once view, a hierarchic all-implementors-at-once method view, and an Eclipse-like fully expandable tree that goes from bundles down to methods/variables i.e. a unification of the hierarchy.&lt;/p&gt;

&lt;p&gt;IMO VW has stuck with the good-enough, which people have become used to and internalised as the-one-true-way, and largely stopped moving forward on this issue - StarBrowser aside.&lt;/p&gt;
&lt;/div&gt;</includedComments:content>
					<includedComments:title></includedComments:title>
				</includedComments:comment>
			</includedComments:comment-collection>
			<wfw:comment>http://www.cincomsmalltalk.com/userblogs/antony/servlet/CommentAPIServlet?guid=3380949119</wfw:comment>
		</item>
	</channel>
</rss>
