<?xml version='1.0' encoding='UTF-8' ?>
<rss version="2.0" 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>Making Smalltalk Easier</title>
		<link>http://www.cincomsmalltalk.com/userblogs/vbykov/blogView</link>
		<description>Smalltalk Tools</description>
		<webMaster>smalltalkbigot@gmail.com</webMaster>
		<lastBuildDate>Fri, 21 Sep 2007 13:12:05 EDT</lastBuildDate>
		<image>
			<url>/images/cst_small.jpg</url>
			<title>Making Smalltalk Easier</title>
			<link>http://www.cincomsmalltalk.com/blog/blogView</link>
			<height>50</height>
			<width>81</width>
		</image>
		<admin:generatorAgent rdf:resource="/CincomSmalltalkWiki/Silt"></admin:generatorAgent>
		<admin:errorReportsTo rdf:resource="mailto:smalltalkbigot@gmail.com"></admin:errorReportsTo>
		<dc:language>en-us</dc:language>
		<dc:creator>Vassili Bykov</dc:creator>
		<dc:rights>Copyright 2007 Vassili Bykov</dc:rights>
		<dc:date>2007-09-21T13:12:05-04:00</dc:date>
		<icbm:latitude>36.953946</icbm:latitude>
		<icbm:longitude>-122.039920</icbm:longitude>
		<item>
			<title>Farewell</title>
			<link>http://www.cincomsmalltalk.com/userblogs/vbykov/blogView?showComments=true&amp;printTitle=Farewell&amp;entry=3351975688</link>
			<category>general</category>
			<pubDate>Thu, 22 Mar 2007 00:21:28 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>Two months ago I left Cincom, and this is the last post on this blog. The work on VisualWorks tools was an interesting period which taught me much. I worked with great people on a cool product, and I am happy to have had that chance. As is also often the case with interesting periods in life, I also feel happy about the change that followed. And with that change, <a href="http://blog.3plus4.org">I am starting a new blog</a> as a more appropriate place for writing about things not necessarily related to Cincom Smalltalk. </p><p>&nbsp;Farewell.<br /></p>
</div>]]></description>
			<guid isPermaLink="false">3351975688</guid>
			<includedComments:comment-collection></includedComments:comment-collection>
		</item>
		<item>
			<title>Browser History</title>
			<link>http://www.cincomsmalltalk.com/userblogs/vbykov/blogView?showComments=true&amp;printTitle=Browser_History&amp;entry=3347559859</link>
			<category>VisualWorks</category>
			<pubDate>Mon, 29 Jan 2007 21:44:19 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>Here is another experimental package from the recent past:</p>



<p>VB-Sketch-Browser History</p>



<p>It adds a History menu to the browser, containing the most recently visited classes and packages.</p>



<p>I know of at least one other recent attempt (RBrowserHistory in the public repository) to add history to the browser, in the form of forward/backward buttons for sequential navigation. My Browser History use of a menu instead of the buttons is not at all a statement against the sequential approach. Rather, my focus was on playing with defining the concept of a <em>location</em>--something one really needs to implement any kind of history mechanism--not with the particular method of navigation. Fitting a menu into the RB simply does not require the level of voodoo that fitting navigation buttons does, this is why it was the natural first choice. Here is what the whole location business is about.</p>



<p>The classic Smalltalk browser defines a deeply hierarchical information space with semi-random access. The concept of a location in that space can be defined in a number of ways. Unlike in a hypertext web of pages a web browser deals with, it is not at all clear when exactly you leave one "place" and arrive at another in a Smalltalk browser. At least it is not clear if you want the history mechanism to be <em>useful</em>.</p>



<p>Useful is the key here. The obvious approach is to remember each and every selection state in the navigator and consider those the locations, and their sequence the history. As the user clicks the Back button, we just walk back through all of the remembered states. Logical enough, but consider this very common navigation scenario. I am about to write or change a method, but before I do that, I want to refresh my memory of another class's API. So I go to that class, perhaps select a likely protocol to narrow down the list of methods, look at a couple of methods that look promising, maybe select a few other protocols and look at a few other methods to make sure I understand what's going on. Now I want to get back to where I was <em>before</em> the exploration started. The "remember everything" approach will make sure I go back though <em>every</em> browser state I visited, including rather uninteresting states such as when only a protocol and no methods are selected.</p>



<p>In order to properly support this scenario, we need to recognize that some browser states are less important than others. And some states are so much alike that they should be considered the same. Here is how Browser History understands locations. (This definition is indeed geared towards random access--I imagine sequential access might require adjustments).</p>



<p>The core idea is combining two levels of granularity in defining a location. One is the package/class level, which defines what is considered a distinct location. The history keeps track of visits to classes and packages. Changes between different protocols and methods within the same class are not considered location changes. However, these visits are not ignored. When the history remembers a visit to a class, it always remembers the last <em>exact</em> location within that class. So, even though the granularity of what is seen as distinct locations are package and class level, the level of detail remembered about that location is the exact selection in that package and/or class.</p>



<p>In other words, you can choose to go back to a particular class or a particular package. Going back to a class takes you to the last method you were looking at in that class. Going back to a particular package takes you to the last class and method, if any, visited in that package.</p>



<p>This sketch, just as DontModeMeIn, ignores views/buffers and related things such as RB_Tabs. This is for two related reasons. One, I don't care to support something I don't use in experimental tools I make. Two, if I haven't made is sufficiently clear in the previous post, I have a strong suspicion that buffers/views come as a solution to the problem of edit modality and absence of browser history in traditional browsers. In fact, discussing these two sketches with <a href="http://www.cincomsmalltalk.com/userblogs/bobw/blogView">Bob Westergaard</a>, I was referring to them as the buffer killing experiment.</p>



<p>And one advice: the detailed class icons <a href="http://www.cincomsmalltalk.com/userblogs/travis/blogView?showComments=true&printTitle=Vassilis_Icons&entry=3347154628">published by Travis</a> (which I also published a few days before as VB-Icon Update-nov06) go very well with the History menu, often making it easier to scan.</p>


</div>]]></description>
			<guid isPermaLink="false">3347559859</guid>
			<includedComments:comment-collection></includedComments:comment-collection>
		</item>
		<item>
			<title>Don't Mode Me In</title>
			<link>http://www.cincomsmalltalk.com/userblogs/vbykov/blogView?showComments=true&amp;printTitle=Dont_Mode_Me_In&amp;entry=3347470901</link>
			<category>Interfaces</category>
			<pubDate>Sun, 28 Jan 2007 21:01:41 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>This post is about an experimental piece I wrote some time ago, which for a number of reasons hasn't made it into VW proper--the main being the depth of changes it makes to the basic logic of the RB, and how unreceptive RB in general is to such changes. However, it is stable enough to be useful as an unsupported add-on. It is published to the public repository as</p>



<p>VB-Sketch-DontModeMeIn</p>



<p>"Don't mode me in" was a slogan reportedly coined by Larry Tesler in the early days of UIs, which also were the early days of Smalltalk. The switch from an application-centric culture where an editor was one application, a compiler another, and a debugger yet another again, all used one at a time--to a window-based environment where all of these were just windows all available at once must have been quite a change.</p>



<p>So much of a change that perhaps the modes the individual tools of the environment were imposing on the user did not seem as such a big deal. The mode I mean is the editing mode of the traditional Smalltalk browser. And by the traditional Smalltalk browser I mean not only the browser of Smalltalk-76 and -80, but also every hot browser that came into existence since then. Once you start editing a method, you have to either accept or cancel before switching elsewhere. Makes sense, doesn't it--after all, this is how it's coded in any UI tutorial. What was the name of that method in the class just above this one? Sorry, can't let you go there--must accept first!</p>



<p>Short of keeping two browser windows side-by-side--one for work, the other for looking things up, which really only works on nice and wide Mac screens--obviously this is why one needs multiple browser views, fondly dubbed "buffers" by some with either a very good memory or too much exposure to software antiques.</p>



<p>Obvious solutions often distract attention away from the best ones, while those best solutions can be hidden in plain view for years. The best solution here is simple: <em>Just Make it Work</em>. There is no good reason why I shouldn't be able to postpone an edit, navigate elsewhere in the same browser, and then come back to finish what I was doing.</p>



<p>VB-Sketch-DontModeMeIn is an attempt to fix that within the constraints of the existing RB and the UI framework.</p>



<p>Load it. Close any open browsers. Open a new one. Look at a method source. Start changing it. Without accepting, click on another method. Or another class. Or search for a class. The button with a red circle and white dots at the bottom of the browser is the link back to the postponed edit left behind. The same works for class comments or any other tools. For example, while writing a class comment you can have a peek at class methods to remember what that instance creation method was called.</p>



<p>The interesting part is that this change might not seem as such a big deal after all. I read somewhere that if you put a piece of glass across a fish tank like a wall, the fish get so much used to it that it takes a long time before they start going into the other half of the tank after the glass is removed. In some ways, we are still not that far away from the fish.</p>


</div>]]></description>
			<guid isPermaLink="false">3347470901</guid>
			<includedComments:comment-collection>
				<includedComments:comment>
					<includedComments:guid>/blogView?showComments=true&amp;printTitle=Dont_Mode_Me_In&amp;entry=3347470901</includedComments:guid>
					<includedComments:puid>/blogView?showComments=true&amp;printTitle=Dont_Mode_Me_In&amp;entry=3347470901</includedComments:puid>
					<includedComments:author>Bob Westergaard</includedComments:author>
					<includedComments:pubDate>2007-01-29T10:24:10-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;I&amp;#39;ve been using this extension internally for quite some time now and I must admit I love it. 
&lt;/p&gt;&lt;/div&gt;</includedComments:content>
					<includedComments:title>It is great!</includedComments:title>
				</includedComments:comment>
				<includedComments:comment>
					<includedComments:guid>/blogView?showComments=true&amp;printTitle=Dont_Mode_Me_In&amp;entry=3347470901</includedComments:guid>
					<includedComments:puid>/blogView?showComments=true&amp;printTitle=Dont_Mode_Me_In&amp;entry=3347470901</includedComments:puid>
					<includedComments:author>chipd</includedComments:author>
					<includedComments:pubDate>2007-01-29T16:16:31-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;It looks great, but needs to work with RB_Tabs&lt;br /&gt;
&lt;/p&gt;&lt;/div&gt;</includedComments:content>
					<includedComments:title></includedComments:title>
				</includedComments:comment>
			</includedComments:comment-collection>
		</item>
		<item>
			<title>Tools-State Machine and Assistants</title>
			<link>http://www.cincomsmalltalk.com/userblogs/vbykov/blogView?showComments=true&amp;printTitle=Tools-State_Machine_and_Assistants&amp;entry=3346524723</link>
			<category>VisualWorks</category>
			<pubDate>Wed, 17 Jan 2007 22:12:03 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>And here is another package, or a group of packages this time, just published to the public repository:</p>



<ul>

<li>Tools-State Machine</li>

<li>Tools-State Machine-Tests</li>

<li>Tools-State Machine-Pollock Example</li>

</ul>



<p>A state machine is a useful abstraction in specifying user interface interactions. So useful in fact, that it's handy to make the abstraction concrete. The main package, Tools-State Machine, contains an implementation of a state machine integrated with Announcements. Tools-State Machine-Pollock Example contains an example of an Assistant, a Pollock pane helper providing pluggable functionality, implemented using a state machine.</p>



<p>In the current VisualWorks system, tooltips ("fly-by help") implementation is based on a state machine. However, the state machine transitions implemented by FlyByHelpTracker are hard to track even for myself who wrote it. Each transition from each state is a method of its own, the state shared by these methods is stored in instance variables used throughout the class, and the logic of how the thing actually works is evenly spread over a maze of little methods, all different.</p>



<p>OverlayAssistant in the example package also implements a state machine, but thanks to the state machine framework, its implementation is much easier to comprehend.</p>



<p>First, a few words about Assistants. Assistants have become part of Pollock sometime ago. They are envisioned as pluggable components that can be attached to standard panes to add non-standard behavior to them. Once attached, an assistant listens to announcements broadcast by the pane and reacts to them by doing things with panes that panes themselves are not programmed to do.</p>



<p>A good example of both an Assistant and the use of a state machine is an implementation of list item overlays. By an item overlay I mean a tooltip-like little window that pops up when the mouse hovers on an item which is too long to fit in the list, showing the complete text of the item. (One could argue these are also tooltips, only displayed differently. Perhaps, but I like to think of tooltips as temporary labels, and of item overlays as "real" items temporarily "pulled out" of the confines of the list that contains them. So I call them different names).</p>



<p>Pollock list boxes announce ZoneEntered and ZoneExited as the mouse moves over the widget, crossing over from one item ("zone") to another. These are exactly what's needed to drive overlay display, and in fact were added to Pollock to support that. (Though they are not essential--we could listen to "raw" MouseMoved announcements and track item boundary crossovers ourselves). When the mouse enters an item that could benefit from an overlay, we want to display the overlay after a short delay. But if the mouse leaves the item before the delay expires, we lose interest in that particular item. After we open a popup, we want to close it after a while or when the mouse leaves the item. Scenarios made of cases like these are a perfect job for a state machine.</p>



<p>OverlayAssistantExample class in Tools-State Machine-Pollock Example is a reasonably complete implementation of overlays. See the class implementation and the class-side #example method for details and an example of attaching an assistant to a pane. Here we'll show only the two key methods: #setPane:, the initialization method of any Pollock PaneHelper, and the method that actually builds the state machine.</p>



<pre>

    setPane: aPane



	super setPane: aPane.

	self buildStateMachine.

	stateMachine

		subscribeTo: ZoneEntered from: pane;

		subscribeTo: ZoneExited from: pane;

		start



    buildStateMachine



	| coldState armedState reaperState indexToOpen |

	stateMachine := StateMachine new.

	coldState := stateMachine newState.

	armedState := stateMachine newState.

	reaperState := stateMachine newState.

	coldState

		on: ZoneEntered do:

			[:announcement |

			(self itemNeedsOverlayAt: announcement index) ifTrue:

				[indexToOpen := announcement index.

				armedState enter]].

	armedState

		on: ZoneExited do:

			[coldState enter];

		afterMilliseconds: 200 do:

			[self openItemOverlayAt: indexToOpen.

			reaperState enter].

	reaperState

		on: ZoneExited do:

			[self closeItemOverlay.

			coldState enter];

		afterMilliseconds: 5000 do:

			[self closeItemOverlay.

			coldState enter]

</pre>



<p>Note how the machine is made of three states. "Armed" is the state we enter when the mouse enters an item that needs an overlay. If we linger in that state for longer than 200 ms, the overlay opens and go into the "reaper" state. The reaper state is where we are when there is an open overlay. We leave the reaper state and remove the overlay either when the mouse leaves the item or after a five second delay.</p>



<p>Also note how state transition actions are able to share information such as "indexToOpen" by virtue of being blocks inside the same method.</p>



<p>As another example, we'll have a look at implementing "regular" tooltips for a toolbar. This assistant is not included in the published example, but it should be easy enough to reproduce for those who are interested.</p>



<p>The difference between this assistant and the overlay one is in the announcements ToolbarTooltipAssistant listens to. The announcements are PaneEntered and PaneExited, sent by the toolbar subpanes (the individual buttons) rather than the toolbar itself. The assistant itself subscribes to SubpaneAdded announcement from the toolbar (announced each time a new component is added to it). When the announcement is broadcast, the assistant instructs its state machine to subscribe to the PaneEntered and PaneExited events from the subpane. To be neat, the assistant also listens to SubpaneRemoved announcement and unsubscribes the state machine from the announcements sent by the removed subpane.</p>



<p>The actual state machine resembles the one of OverlayAssistant, though it's a little more complex.</p>



<pre>

    buildStateMachine

	| coldState armedState reaperState warmState paneEntered |

	stateMachine := StateMachine new.

	coldState := stateMachine newState.

	armedState := stateMachine newState.

	reaperState := stateMachine newState.

	warmState := stateMachine newState.

	coldState 

		on: PaneEntered do: 

			[:announcement |

			paneEntered := announcement pane.

			(self hasTooltip: paneEntered)

				ifTrue: [armedState enter]].

	armedState

		on: PaneExited do: 

			[coldState enter];

		afterMilliseconds: 500 do: 

			[self openTooltipFor: paneEntered.

			reaperState enter].

	reaperState

		on: PaneExited do: 

			[:announcement | 

			self closeTooltipFor: announcement pane.

			warmState enter];

		afterMilliseconds: 5000 do: 

			[self closeTooltipFor: paneEntered.

			coldState enter].

	warmState

		on: PaneEntered do: 

			[:announcement | 

			paneEntered := announcement pane.

			(self hasTooltip: paneEntered)

				ifTrue: 

					[self openTooltipFor: paneEntered.

					reaperState enter]];

		afterMilliseconds: 300 do:

			[coldState enter]

</pre>



<p>The addition is an extra state, warmState. It is required in toolbar assistant to support easy scanning of tooltips. Once a tooltip for an item is displayed, if the user moves the mouse cursor to a different item, the proper behavior is to display the tooltip for that item immediately rather than after the usual delay. This way, it's easy to "swipe" the toolbar with the mouse looking for a particular item, without having to wait half a second at each button for its tooltip to open. To support that, when the mouse leaves a pane with an open tooltip (PaneExited in reaperState), the machine switches to warmState rather than to coldState as in the overlay assistant. In warm state, entering a different pane displays the tooltip immediately. If the machine stays in warm state for 300 milliseconds and no other panes are entered, it "cools down" and reverts to the usual policy of waiting before opening the tooltip of a visited item.</p>



<p>Compare readability of the method above with the same state machine implemented as methods in the 'events' protocol in FlyByHelpTracker.</p>


</div>]]></description>
			<guid isPermaLink="false">3346524723</guid>
			<includedComments:comment-collection></includedComments:comment-collection>
		</item>
		<item>
			<title>Tools-Resource Library</title>
			<link>http://www.cincomsmalltalk.com/userblogs/vbykov/blogView?showComments=true&amp;printTitle=Tools-Resource_Library&amp;entry=3346448618</link>
			<category>VisualWorks</category>
			<pubDate>Wed, 17 Jan 2007 01:03:38 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>This is an explanation of what the package Tools-Resource Library just published to the open repository does, and how it does that.</p>



<p>VisualWorks applications, at least most of those I've been working on, use images prepared outside of the VisualWorks environment. Some of the older icons I made, including those in the Launcher and the RB were created using CoolImage--but nice as it is compared to the default Image Editor, it is no Photoshop killer. And arguably, replicating Photoshop or Gimp in Smalltalk is a waste of time better used otherwise. This means that bringing images (and perhaps some other resources) prepared in external applications into the image is a task worth supporting.</p>



<p>Currently, the class ImageReader can import external images, creating resource methods in one of the icon libraries. Unfortunately, this workflow is hard to manage, as the association of resource methods and their source files is not preserved. It's hard to keep track of what resource methods need updating after some of the source files change. The only workaround is maintaining a master import utility method that reimports all of the files "wholesale".</p>



<p>Additionally, the IconLibrary facility itself is showing its age. The mechanism that maps icon names to resource methods is rather complicated, mostly because of its unused ability to support multiple icon sizes and because of caching in the library.</p>



<p>Tools-Resource Library addresses all of these deficiencies. As an introduction, here is how one would use it in an application.</p>



<p>Begin by creating a subclass of ResourceLibrary. For the sake of the example, let's assume the class name is FooResources.</p>



<p>For each image you want to import in the library, write a class-side resource method marked with a pragma identifying the resource type and source file name. For example:</p>



<pre>

productIcon

    &lt;opaqueImage: 'product.gif'>

</pre>



<p>The method (for now) needs no code in the body other than the pragma. The selector and the protocol are entirely up to you. We are assuming that product.gif file is present in the current directory.</p>



<p>Now, in a workspace near you evaluate the expression "FooLibrary regenerate". Now look at the two methods again. If the files mentioned in the pragmas were indeed accessible, regenerating replaced the code of the methods with something like (omitting some non-essential comments):</p>



<pre>

productIcon

	&lt;opaqueImage: 'product.gif' >

	"Generated from: product.gif

	timestamped: March 31, 2006 22:10:50.000

	on: January 15, 2007 11:08:50.161"



	| figure shape |

	figure := CachedImage on: <i>...stuff...</i> .

	shape := CachedImage on: <i>...stuff...</i> .

	^OpaqueImage figure: figure shape: shape

</pre>



<p>This shows the first thing that is special about ResourceLibrary and its subclasses. They can maintain methods with data imported from external files, and update them as necessary. Each time the class is sent the #regenerate message, the timestamp of the imported file stored as a comment inside a resource method is checked to see if the method needs updating.</p>



<p>All that's necessary to get the imported image is evaluating the expression "FooLibrary productIcon", which will return an instance of OpaqueImage, just as the method code shows.</p>



<p>Now, what about efficiency? It seems that every time the method is executed a new OpaqueImage is created. This certainly is a waste of both cycles and storage since these images could be cached and shared, as IconLibrary already does. Let's look at the method closer. Inspecting it shows that its bytecode in fact looks as follows:</p>



<pre>

    short AnnotatedMethod numArgs=0 numTemps=0 frameSize=0



    literals: (an OpaqueImage )



    1 &lt;1C> push an OpaqueImage

    2 &lt;65> return

</pre>



<p>What we have here is essentially compile-time evaluation at the method level, performed by the special compiler assigned to resource libraries. The code in the method body was evaluated by the compiler and saved as a literal returned by the method. Or, to look at it in a different perspective, we do have caching, with each resource access method doubling as a cache entry.</p>



<p>Only resource methods (those marked with one of the predefined resource pragmas) on the class side of ResourceLibrary and its subclasses are compiled in this fashion. All other methods are compiled and work as usual. The can also be filed out or published to a Store repository.</p>



<p>The following resource types (pragma keywords) are supported:</p>



<p>opaqueImage: -- an image file is imported and stored as an OpaqueImage. Supported image formats are those supported by ImageReader. As of VW 7.5, .gif and .png are best bets. Note that OpaqueImage does not support alpha channels, so only .png files with full transparency/opacity can be meaningfully imported.</p>



<p>image: -- an image file is imported and stored as a CachedImage on an Image.</p>



<p>xmlDocument: -- an XML file is imported, parsed and stored as an XML Document.</p>



<p>binaryFileContents: -- the contents of an arbitrary file are imported and saved as a ByteArray.</p>



<p>A library class understands the following messages of notice: </p>



<p>#regenerate -- regenerate the source code and recompile all resource methods that are out of date. "Out of date" means either that there is no "timestamp" line in the method, which is interpreted as a method that has not yet been generated from its file, or the timestamp of the source file remembered in the method differs from the file on the disk. If the source file of a method is missing, the method is left untouched.</p>



<p>#regenerateAll -- regenerates all resource methods of the class, regardless of whether they are out of date or not.



<p>#pragmasWithMissingSourceFiles -- returns Pragma instances pointing to the methods whose original files are missing.</p>



<p>By default, files mentioned in resource pragmas are looked up in the current directory. ResourceLibrary defines a class instance variable rootDirectory, which can be set in each subclass to point to a different directory to look in.</p>


</div>]]></description>
			<guid isPermaLink="false">3346448618</guid>
			<includedComments:comment-collection></includedComments:comment-collection>
		</item>
		<item>
			<title>Bring Your Own SubscriptionRegistry</title>
			<link>http://www.cincomsmalltalk.com/userblogs/vbykov/blogView?showComments=true&amp;printTitle=Bring_Your_Own_SubscriptionRegistry&amp;entry=3335654616</link>
			<category>Announcements Framework</category>
			<pubDate>Thu, 14 Sep 2006 02:43:36 EDT</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p>After a long period of stability, there is a new version of Announcements in the public repository, preview-28.0. The change it contains is unusual in that it removes rather than adds functionality. It can therefore affect people who already use announcements.</p>



<p>Removed is the ability for an arbitrary object to remember subscriptions. There is a new class in System-Announcements, called Announcer (which previously was included as an example in the Systems-Announcements-Extras package). In order to be able to accept subscriptions, an object should either inherit from Announcer or implement in a sufficiently similar way the two or three methods that Announcer implements: #subscriptionRegistry:, #subscriptionRegistryOrNil and (typically) #postCopy.</p>



<p>In the original design, any object, including something as primitive as a SmallInteger, could accept subscription requests, remember the subscriptions, and later deliver announcements to the subscribers. This was possible because Object implemented subscription storage using one external global registry, following the tradition set by change/update (DependentsFields) and triggerEvent (EventTable). Only classes that wanted the lower cost of local subscription storage would care to store subscriptions in an instance variable instead of inheriting the global mechanism from Object.</p>



<p>The problem with that tradition are a number of subtle issues in the interaction between the external registry, #become:, and collection growth logic, as well as the risk of garbage accumulating in the global registry. A detailed review would easily make up a post of its own going some fifteen years of VW evolution back, but for now suffice it to say that the issues were bad enough that we decided to explore the alternative approach, more in the spirit of "worse is better". </p>



<p>The common case is that a relatively small number of specialized announcement sources, such as Pollock Panes, does indeed broadcast events. Such objects often replace the default storage management with local storage as a matter of optimization. In the new Announcements, this is no longer an optimization. Now it's strictly Bring Your Own SubscriptionRegistry. Any object that wants to accept subscriptions must make its own arrangements to hold onto its subscription registry.</p>



<p>I've been careful to say that an object has to make these arrangements "to be able to accept subscriptions" rather than "to be able to broadcast announcements". Conceptually, the framework still considers all objects as capable of broadcasting announcements. It's just that not all objects will accept subscriptions. From the framework's point of view, any newly created object starts off with zero subscriptions. It doesn't matter whether the object is an instance of Point or Pane. It is OK to send #unsubscribe: to both of those, which will be a no-op since there are no subscriptions to remove. It is even OK to send #announce: to both, which again will be a no-op as there are no interested recipients. The only difference is that one can send a #when:... message to Pane to create a new subscription, while sending it to Point will cause an error.</p>


</div>]]></description>
			<guid isPermaLink="false">3335654616</guid>
			<includedComments:comment-collection></includedComments:comment-collection>
		</item>
		<item>
			<title>Unit Tests and Mouse Input</title>
			<link>http://www.cincomsmalltalk.com/userblogs/vbykov/blogView?showComments=true&amp;printTitle=Unit_Tests_and_Mouse_Input&amp;entry=3321440106</link>
			<category>VisualWorks</category>
			<pubDate>Sun, 02 Apr 2006 14:15:06 EDT</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">
<p><html><html><div xmlns="http://www.w3.org/1999/xhtml">

<p>Now that Michael and other nice people from Software with Style <a href="http://www.cincomsmalltalk.com/userblogs/mls/blogView?showComments=true&amp;entry=3321306493">finished Splash for me</a>, I can with clear conscience write about something else. Here is something cool I stole from Sames. (How's that for clear conscience?)</p>
<p>If you look at the PollockTestCase class in Pollock-Tests-Support package, you can find a protocol called &quot;mouse support&quot;. It contains a bunch of methods for simulating mouse input in the window being tested. Layout editor in Splash being a very mouse-centric thing, those sure looked invaluable.</p><p>That protocol would actually better be split in two. One for those methods that send primitive mouse events, such as red button press and red button release, to the window. The other for higher-level methods that simulate user-level input gestures, such as clicking at a particular point or dragging from one point to another.</p><p>So I &quot;borrowed&quot; mouse event methods such as #pressRedButtonAt: and #moveMouseTo:. PollockTestCase also includes methods to simulate input gestures, but I wrote my own versions with names that spoke better to me: #simulateClickAt: and #simulateDragFrom:by:. With this, I can smoke test the &quot;real&quot; response of the editor to mouse clicks, like:</p>
<pre>testClickWindowTitle
 	self assert: editor selection isEmpty.
 	self simulateClickAt: editor fakeWindow titleBarBox center.
 	self assert: editor selection isWindowSelected
</pre>
<p>This is a very short test that exercises an awful lot of stuff. Almost like &quot;3 +4 &quot; in Smalltalk. &quot;fakeWindow&quot; is the editor object that appears as a window inside the editor--those windows without title text in the screenshots in the last post. &quot;Box&quot;, or #titleBarBox in this case, is the term the various things in the layout editor use for the &quot;important&quot; rectangle that describes their position. For widgets, the box is Pollock's #frameBounds, but for some things it is different. For example, a fakeWindow's box is its inner area (what Windows calls the client area). For our needs, it is more important than the bounds of the window itself that depend on window decorations in the look we are faking.</p>
<p>Here is another example testing that dragging a widget works:</p>
<pre>testDragButton
	| button oldBox |
	self assert: editor selection isEmpty.
	button := editor widgetObjectForId: #button.
	oldBox := button box.
	self simulateDragFrom: button box center by: 50 @ 30.
	self assert: editor selection isSingleWidgetSelected.
	self assert: button box = (oldBox translatedBy: 50 @ 30)
</pre>
</div></html></html>
</p></div>]]></description>
			<guid isPermaLink="false">3321440106</guid>
			<includedComments:comment-collection></includedComments:comment-collection>
		</item>
		<item>
			<title>What Splash Will and Won't Be</title>
			<link>http://www.cincomsmalltalk.com/userblogs/vbykov/blogView?showComments=true&amp;printTitle=What_Splash_Will_and_Wont_Be&amp;entry=3320965482</link>
			<category>Splash</category>
			<pubDate>Tue, 28 Mar 2006 02:24:42 EST</pubDate>
			<description><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml">

<p>To meta-comment on some of the comments to the last post.</p>

<p>Like Pollock is nothing but a reasonable UI framework, Splash will be nothing but a reasonable UI builder. If you are hoping for the &quot;blue plane&quot; stuff with Splash somehow naturally blending with regular windows so that you can edit any window you work in and work in any window you edit--you will be disappointed. We don't serve this here at this restaurant.</p>

<p>Which is not such a bad thing, all you blue plane people out there. As an anonymous commenter observed, UI building is not rocket science. That certainly is true--whatever is meant by UI building, the building of UIs or the building of UI builder UIs. What is somewhat puzzling considering that is the abundance of crappy UIs, including UI builder UIs, out there. So what Splash is supposed to be is &quot;simply&quot; a UI builder that doesn't suck. Which is not little.</p>

<p>As a mental experiment, imagine that the current VisualWorks UI builder is beefed up so that it gets fully dynamic. You can switch any window to the edit mode and back, and any edit you make is propagated to other window that came from the same spec. Java weenies shrivel up and die at the mere sight of this powerful dynamism. This isn't that hard to do, really. Would it produce a better UI builder?</p>

<p>I am a very active UI builder user, and my answer is a resounding NO. Making the current builder more dynamic would address none of the issues that make working with it a pain. Here are some off the top of my list. Note that some items imply more than they say.</p>

<ol>
<li>The model of VW UI builder has nothing in common with the mental model of a typical user. Everyone comes to UI building with the concept of &quot;I'll put an input field and a button inside a window and do something simple to put a message in the field when the button is clicked&quot;. Nobody comes with concepts of &quot;I'll define an aspect for the input field, create the aspect method and then set the aspect when the button is clicked&quot;.</li>
<li>Widget properties all neatly packed into ten different notebook pages all with an Accept button to trip over when switching to a different one is not the most usable properties representation.</li>
<li>Typing numbers into fraction/offset input fields is not how people think about laying out the widgets.</li>
<li>No undo. There is just no excuse for that.</li>
<li>Separate windows for the UI under editing, its parameters, and the tools palette were sexy in 1990 when NeXT was the hottest thing around. In the 16 years since, the world has learned the cost of unnecessary window management. (Yes, OS X Interface Builder sucks too).</li>
<li>Interaction detail, which is where the devil is. There's just too much little interaction things UI Builder got wrong. You don't initiate a drag as soon as the user presses down on the mouse button. You wait until they've dragged some initial threshold--or they will end up moving their widgets by a pixel as they click them to select. In all modern UIs, rubberband selects any objects it overlaps, not just those it encloses completely.</li>
<li>And yes, things are too closed off on the runtime side in VW. Given a window, there is no easy way to even debug it, let alone get to its definition to change it. This needs fixing too, and full dynamism is not the only solution.</li>
</ol>

<p>So what Splash will be is simply something that won't have those issues, and others like them. And it will be really modular so that anyone can use any part of it for great fun and profit. Such as writing a whole new tool you can plug into Splash. Or writing a whole new Splash-like builder to edit live windows, instead of just blogging what a nice thing it would be.</p>

<p>Now for the show-and-tell. Because of sickness and boring work stuff, I only had a few good days to work on Splash since the last post. Here is a window with Splash layout editor inside.</p>

<img src="http://www.cincomsmalltalk.com/CincomSmalltalkWiki/DOWNLOAD/vb/blog/splash060327-1.jpg" style="margin-left:1em;"></img>

<p>What looks like a window without a title isn't a real window, as the selection frame around it suggests. This is to reinforce the point that Splash will not have a multiple-window setup where the UI you edit is a real window on the screen. Windows95-like widgets inside are there just because I'm using a Windows95 look. The editor takes after that, even though the fake window in the editor for now unconditionally paints itself as an OS X window.</p>

<img src="http://www.cincomsmalltalk.com/CincomSmalltalkWiki/DOWNLOAD/vb/blog/splash060327-2.jpg" style="margin-left:1em;"></img>

<p>This shot is the same window, resized and with widgets rearranged and resized, all using the editor. You can't see it in the screenshot, but dragging and rubberband selection work as they should, little details included, and with wrinkles such as holding down Shift to constrain drag to vertical and horizontal direction and to constrain resizing to preserve the original proportion.</p>

</div>]]></description>
			<guid isPermaLink="false">3320965482</guid>
			<includedComments:comment-collection>
				<includedComments:comment>
					<includedComments:guid>/blogView?showComments=true&amp;printTitle=What_Splash_Will_and_Wont_Be&amp;entry=3320965482</includedComments:guid>
					<includedComments:puid>/blogView?showComments=true&amp;printTitle=What_Splash_Will_and_Wont_Be&amp;entry=3320965482</includedComments:puid>
					<includedComments:author>Travis Griggs</includedComments:author>
					<includedComments:pubDate>2006-03-28T02:57:09-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;I've been gone too, so I apologize if I'm "out of phase" here. I desperately hope you don't take editing layouts by fractions away. I hate every other ui layout tool because it usually lacks them (ST/X is the only one that actually offered an improvement on the VW ones), and I hate the UI's they reproduce. Like windows that look like crap as soon as you resize them. Or slightly one pixel off alignment errors on close inspection.
&lt;/p&gt;&lt;/div&gt;</includedComments:content>
					<includedComments:title></includedComments:title>
				</includedComments:comment>
				<includedComments:comment>
					<includedComments:guid>/blogView?showComments=true&amp;printTitle=What_Splash_Will_and_Wont_Be&amp;entry=3320965482</includedComments:guid>
					<includedComments:puid>/blogView?showComments=true&amp;printTitle=What_Splash_Will_and_Wont_Be&amp;entry=3320965482</includedComments:puid>
					<includedComments:author></includedComments:author>
					<includedComments:pubDate>2006-03-28T07:29:46-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;Is Splash built with Pollock? If so, how do you manage to make it work at an acceptably performance? Regards.&lt;br /&gt;
&lt;/p&gt;&lt;/div&gt;</includedComments:content>
					<includedComments:title>MetaSplash</includedComments:title>
				</includedComments:comment>
				<includedComments:comment>
					<includedComments:guid>/blogView?showComments=true&amp;printTitle=What_Splash_Will_and_Wont_Be&amp;entry=3320965482</includedComments:guid>
					<includedComments:puid>/blogView?showComments=true&amp;printTitle=What_Splash_Will_and_Wont_Be&amp;entry=3320965482</includedComments:puid>
					<includedComments:author>Vassili</includedComments:author>
					<includedComments:pubDate>2006-03-28T17:13:27-05:00</includedComments:pubDate>
					<includedComments:content>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;FractionalFrames are an important part of Pollock, so of course we are not taking them out. In fact, I love fractional frames. They give the most bang for the buck, where the bang is specifying resize behavior and the buck is implementation complexity, of everything I've seen. What I meant is that eight input fields to type numbers into are not a good UI for specifying fractional layout. There are ways to do it easier for the common use cases. But, there most certainly will be fractional frames, and fields to type numbers into for those who are so inclined.&lt;/p&gt;

&lt;p&gt;Yes, Splash is built entirely in Pollock. Of course. How do I make it work with acceptable performance? I don't--apart from avoiding obviously wasteful actions on my end. So far I would describe the performance I see as "between somewhat sluggish and marginally acceptable". I work on a 1.33GHz PowerPC using X11 VM. Pollock has not been tuned for performance yet. At all. There are some well known bottlenecks that need to be optimized. There probably are some unknown bottlenecks as well. I know Sames will take care of it when the time comes. At this point, I don't worry about Pollock performance I see. And neither should anyone else.&lt;/p&gt;
&lt;/div&gt;</includedComments:content>
					<includedComments:title></includedComments:title>
				</includedComments:comment>
			</includedComments:comment-collection>
		</item>
	</channel>
</rss>
