<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Andrew Pietsch&#039;s Weblog</title>
	<atom:link href="http://pietschy.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://pietschy.com/blog</link>
	<description>Things and stuff</description>
	<lastBuildDate>Sun, 01 Aug 2010 07:43:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Pectin 0.8 Released</title>
		<link>http://pietschy.com/blog/2010/08/pectin-0-8-released/</link>
		<comments>http://pietschy.com/blog/2010/08/pectin-0-8-released/#comments</comments>
		<pubDate>Sun, 01 Aug 2010 07:26:58 +0000</pubDate>
		<dc:creator>pietschy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[GWT]]></category>

		<guid isPermaLink="false">http://pietschy.com/blog/?p=234</guid>
		<description><![CDATA[I&#8217;ve just released Pectin 0.8 with lots of new features.  Some of the more significant&#160;are: More generalised binding support, i.e. you no longer need to use forms if you don&#8217;t need&#160;plugins. Beans binding now supports basic nested property&#160;paths. Command improvements &#8230; <a href="http://pietschy.com/blog/2010/08/pectin-0-8-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just released <a href="http://code.google.com/p/gwt-pectin/">Pectin 0.8</a> with lots of new features.  Some of the more significant&nbsp;are:</p>
<ul>
<li>More generalised binding support, i.e. you no longer need to use forms if you don&#8217;t need&nbsp;plugins.</li>
<li>Beans binding now supports basic nested property&nbsp;paths.</li>
<li>Command improvements including new exception&nbsp;handlers.</li>
<li>..and lots of other&nbsp;improvements.</li>
</ul>
<p>Check out the <a href="http://code.google.com/p/gwt-pectin/wiki/ReleaseNotes">release notes for more&nbsp;information</a>.</p>
<p>You can get pectin <a href="http://code.google.com/p/gwt-pectin/downloads/list">from the download&nbsp;page</a>.</p>
<p>Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://pietschy.com/blog/2010/08/pectin-0-8-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using &lt;? extends T&gt; and &lt;? super T&gt; for reduce style functions that operate on collections</title>
		<link>http://pietschy.com/blog/2010/02/using-extends-t-and-super-t-for-reduce-style-functions-that-operate-on-collections/</link>
		<comments>http://pietschy.com/blog/2010/02/using-extends-t-and-super-t-for-reduce-style-functions-that-operate-on-collections/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 01:15:51 +0000</pubDate>
		<dc:creator>pietschy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[GWT]]></category>

		<guid isPermaLink="false">http://pietschy.com/blog/?p=226</guid>
		<description><![CDATA[One of the cases I&#8217;ve had to deal with in gwt-pectin is creating Reduce style functions that operate on a collection of values.  The basic idea is to define interface of the&#160;form. public interface Reduce&#60;R,T&#62; { R reduce(List&#60;T&#62; source); } &#8230; <a href="http://pietschy.com/blog/2010/02/using-extends-t-and-super-t-for-reduce-style-functions-that-operate-on-collections/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the cases I&#8217;ve had to deal with in <a href="http://code.google.com/p/gwt-pectin/">gwt-pectin</a> is creating Reduce style functions that operate on a collection of values.  The basic idea is to define interface of the&nbsp;form.</p>
<pre>public interface Reduce&lt;R,T&gt; {
   R reduce(List&lt;T&gt; source);
}</pre>
<p>I use this on my ReducingValueModel&lt;R,T&gt; to automatically compute fields such as a sum&#8217;s of numbers, or a string representation of a list and so forth.  So on my ReducingValueModel I have a method to configure the reducing function to use as&nbsp;follows.</p>
<pre>public class ReducingValueModel&lt;R,T&gt; {
<span style="color: #999999;">   // our function</span>
   private Reduce&lt;R,T&gt; function;
<span style="color: #999999;">   // and it's setter</span>
   public void setFunction(Reduce&lt;R,T&gt; function) {
      this.function = function;
      recompute();
   }
   <span style="color: #999999;">// and every thing else that makes it go
   ...
</span>}</pre>
<p>This works fine when define a new function for each different combination of R and T.  The trouble appears when you want to create a generic Reduce function that you can use on any ReductingValueModel.   Something like a generic &#8220;list to string&#8221; style function for&nbsp;example:</p>
<pre>public class ListToStringFunction&lt;String, Object&gt; {
<span style="color: #c0c0c0;">   // we can convert any list of objects to a string</span>
   public String reduce(List&lt;Object&gt; values) {
     <span style="color: #c0c0c0;">// concate our list values and return the result.</span>
     return ...;
   }
}</pre>
<p>So now lets try and use&nbsp;it.</p>
<pre>ReducingValueModel&lt;String, Integer&gt; reducingModel = ...;
<span style="color: #999999;">// This won't compile...</span>
reductingModel.setFunction(new ListToStringFunction());
</pre>
<p>But this won&#8217;t compile because ListToStringFunction is a Reduce&lt;String, Object&gt; and not Reduce&lt;String, Integer&gt;.  So we bung in the standard &lt;? super T&gt; clause on the ReducingValueModel so it can accept a function that works on any super&nbsp;type.</p>
<pre>public class ReducingValueModel&lt;R,T&gt; {
<pre>  private <strong>Reduce&lt;R, ? super T&gt;</strong> function;
<span style="color: #c0c0c0;">  <span style="color: #999999;">// now lets use &lt;? super S&gt; so we can use functions that
  // operate on any super source type.</span></span>
  public void setFunction(<strong>Reduce&lt;R,? super T&gt;</strong> function) {
    this.function = function;
    recompute();
  }
}</pre>
</pre>
<p>And while it looks like this should work, it doesn&#8217;t.  The problem is that were I&#8217;m using the Reduce function it&#8217;s now defined as a Reduce&lt;R, ? super T&gt; (making it a Reduce&lt;T,Object&gt; for all intents and purposes) so it can&#8217;t accept any old List&lt;T&gt; as an&nbsp;argument.</p>
<pre>public class ReducingValueModel&lt;R,T&gt; {

  private <strong>Reduce&lt;R, ? super T&gt;</strong> function;

  protected void recompute()  {
    ArrayList&lt;T&gt; values = ...;  // prepare the values..
    <span style="color: #999999;">// now this won't compile because our the function we
    // passed in only works on List&lt;? super T&gt; and not List&lt;T&gt;</span>
    <strong>R computedValue = function.compute(values);</strong>
    fireValueChangeEvent(computedValue);
  }
}</pre>
<p>Fortunately the fix is simple.  We need to update our Reduce&lt;R,T&gt; interface to accept any values that extend T. &nbsp;I.e.</p>
<pre>public interface Reduce&lt;R,T&gt; {
<span style="color: #999999;">  <span style="color: #999999;"> // this allows our Reduce&lt;R, ? super T&gt; to operate
   // on any list</span></span><span style="color: #999999;"> that extends T</span>
   T reduce(<strong>List&lt;? extends T&gt;</strong> source);
}</pre>
<p>Now our ReducingValueModel&lt;R,T&gt; can accept functions that work on any super type of T and our Reduce&lt;R,T&gt; can accept any list whose values that extend&nbsp;T.</p>
<p>So the two things to do&nbsp;are:</p>
<ol>
<li>Make sure your functions can operate on source collections of type &lt;? extends T&gt;. i.e.
<pre>public interface Reduce&lt;R,T&gt; {
   R reduce(<strong>List&lt;? extends T&gt;</strong> source)
}</pre>
</li>
<li>Allow users to configure functions use &lt;? super S&gt; for the source values.  i.e.
<pre>public void setFunction(<strong>Reduce&lt;R, ? super T&gt;</strong> function) {...}</pre>
</li>
</ol>
<p>All&nbsp;good.</p>
]]></content:encoded>
			<wfw:commentRss>http://pietschy.com/blog/2010/02/using-extends-t-and-super-t-for-reduce-style-functions-that-operate-on-collections/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Specifying units for an SVG path</title>
		<link>http://pietschy.com/blog/2009/11/specifying-units-for-an-svg-path/</link>
		<comments>http://pietschy.com/blog/2009/11/specifying-units-for-an-svg-path/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 23:40:41 +0000</pubDate>
		<dc:creator>pietschy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pietschy.com/blog/?p=214</guid>
		<description><![CDATA[Specifying units for an SVG path isn&#8217;t obvious at first glance.  The trick is to wrap the path in a nested svg element with it&#8217;s size specified the units you&#160;require. In this example, the units of the path are relative &#8230; <a href="http://pietschy.com/blog/2009/11/specifying-units-for-an-svg-path/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Specifying units for an SVG path isn&#8217;t obvious at first glance.  The trick is to wrap the path in a nested svg element with it&#8217;s size specified the units you&nbsp;require.</p>
<p>In this example, the units of the path are relative the the viewBox (0 0 <strong>10 10</strong>) and the actual size will be determined by the width and height of the svg element (width=10mm,&nbsp;height=10mm).</p>
<pre>&lt;svg x="0" y="0" <strong>width="10mm" height="10mm"</strong> <strong>viewBox="0 0 10 10"</strong>&gt;
 <span style="color: #808080;">&lt;!-- these are all in viewBox units --&gt;</span>
 &lt;path d="M 5 9  L 1 5 L 3.5 5 L 3.5 1.5 L 6.5 1.5 L 6.5 5 L 9 5 z"
       style="fill: #FFF; stroke: black; stroke-width: 0.5"&gt;
 &lt;/path&gt;
&lt;/svg&gt;</pre>
<p>You can of course change the ratio of the viewBox and width/height as you please and things will scale&nbsp;accordingly.</p>
]]></content:encoded>
			<wfw:commentRss>http://pietschy.com/blog/2009/11/specifying-units-for-an-svg-path/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Well said&#8230;</title>
		<link>http://pietschy.com/blog/2009/11/well-said/</link>
		<comments>http://pietschy.com/blog/2009/11/well-said/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 23:21:03 +0000</pubDate>
		<dc:creator>pietschy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pietschy.com/blog/?p=209</guid>
		<description><![CDATA[An well written and enjoyable read if you&#8217;ve ever been a developer of open source.  If you&#8217;ve a user of open source libraries then it&#8217;s something you should&#160;read. Dear User of My Open Source&#160;Project A&#160;quote: Now, all of this may &#8230; <a href="http://pietschy.com/blog/2009/11/well-said/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>An well written and enjoyable read if you&#8217;ve ever been a developer of open source.  If you&#8217;ve a user of open source libraries then it&#8217;s something you <em>should</em>&nbsp;read.</p>
<p><a rel="bookmark" href="http://enfranchisedmind.com/blog/posts/fyi-my-open-source-users/">Dear User of My Open Source&nbsp;Project</a></p>
<p>A&nbsp;quote:</p>
<blockquote><p>Now, all of this may seem a bit harsh, but let’s analyze the relationship a bit closer. For me to do work for you, there’s got to be some kind of social bond; some kind of give-and-take; a bi-directional relationship wherein both parties have given and received. At the point when you’ve come at me with your comment, our relationship consists of one point of interaction: I’ve put work into a project and released it, and you’ve taken the project. See the lopsidedness? You’re not doing me a favor by taking the project: I have no social bond with you because you decide to take my free toilet. If you want me to do some work, a kind of <em>quid pro quo</em> is required up-front: some sign that you’re in the relationship, and the relationship will be give-and-take. I don’t keep careful books on how much I’ve given or taken from people, but in your case, I don’t have to: I’ve given something, you’ve given nothing, and now you’re demanding more. That’s not the kind of relationship I care to be a part&nbsp;of.</p></blockquote>
<p>And a nice quote from the&nbsp;comments:</p>
<blockquote><p>I’m more than willing to share because I don’t do open source for fame or ego or whatever: I’ve long since known that I don’t have the skills or the cult-follower-inspiring charisma or the Satanic pact or whatever it is that moves people from “open source developer” to “software developer micro-celebrity”. I do open source because it solves a problem for me, and I think it might help solve a problem for someone else. Or because it’s interesting, and I think someone else might find the stuff interesting,&nbsp;too.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://pietschy.com/blog/2009/11/well-said/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GWT binding library for building forms released</title>
		<link>http://pietschy.com/blog/2009/08/gwt-binding-library-for-building-forms-released/</link>
		<comments>http://pietschy.com/blog/2009/08/gwt-binding-library-for-building-forms-released/#comments</comments>
		<pubDate>Mon, 10 Aug 2009 05:06:43 +0000</pubDate>
		<dc:creator>pietschy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pietschy.com/blog/?p=205</guid>
		<description><![CDATA[Pectin is a prototype library for building forms in GWT.  It uses a guice style builder API to simplify model creation and widget bindings.  You can check it out at&#160;http://code.google.com/p/gwt-pectin/.]]></description>
			<content:encoded><![CDATA[<p>Pectin is a prototype library for building forms in GWT.  It uses a guice style builder API to simplify model creation and widget bindings.  You can check it out at&nbsp;<a href="http://code.google.com/p/gwt-pectin/">http://code.google.com/p/gwt-pectin/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://pietschy.com/blog/2009/08/gwt-binding-library-for-building-forms-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GWT binding library for building forms</title>
		<link>http://pietschy.com/blog/2009/07/gwt-binding-library-for-building-forms/</link>
		<comments>http://pietschy.com/blog/2009/07/gwt-binding-library-for-building-forms/#comments</comments>
		<pubDate>Tue, 14 Jul 2009 06:23:57 +0000</pubDate>
		<dc:creator>pietschy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pietschy.org/blog/?p=196</guid>
		<description><![CDATA[Lately I&#8217;ve been pondering and playing with a presentation model style a binding API for GWT.  It&#8217;s been fun, and I&#8217;ve got an initial prototype going.  It uses a guice style builder API that makes wiring things up much nicer.  &#8230; <a href="http://pietschy.com/blog/2009/07/gwt-binding-library-for-building-forms/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Lately I&#8217;ve been pondering and playing with a presentation model style a binding API for GWT.  It&#8217;s been fun, and I&#8217;ve got an initial prototype going.  It uses a guice style builder API that makes wiring things up much nicer.  You can read the overview/ideas document&nbsp;at:</p>
<p><a href="http://docs.google.com/View?id=dm73tfj_55dqrkpwgx">http://docs.google.com/View?id=dm73tfj_55dqrkpwgx</a></p>
<p>Update: A prototype of the library is now on google code -&nbsp;<a href="http://code.google.com/p/gwt-pectin/">http://code.google.com/p/gwt-pectin/</a></p>
<p>Cheers<br />&nbsp;Andrew</p>
]]></content:encoded>
			<wfw:commentRss>http://pietschy.com/blog/2009/07/gwt-binding-library-for-building-forms/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mac Fidelity on Menus using GUI Commands</title>
		<link>http://pietschy.com/blog/2009/01/mac-fidelity-on-menus-using-gui-commands/</link>
		<comments>http://pietschy.com/blog/2009/01/mac-fidelity-on-menus-using-gui-commands/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 04:59:33 +0000</pubDate>
		<dc:creator>pietschy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pietschy.org/blog/?p=148</guid>
		<description><![CDATA[One of the things to Java/Swing developers face when trying to migrate a application to the Mac is handling the differences in how the Mac displays menus. This can particularly be the case if you&#8217;re a microISV and can&#8217;t justify &#8230; <a href="http://pietschy.com/blog/2009/01/mac-fidelity-on-menus-using-gui-commands/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the things to Java/Swing developers face when trying to migrate a application to the Mac is handling the differences in how the Mac displays menus.  This can particularly be the case if you&#8217;re a microISV and can&#8217;t justify the time and effort so support a platform you may rarely use.  Still, the number of Mac users are growing and it would be nice to include them if you&nbsp;can.</p>
<p>So if you&#8217;re going to deploy to the Mac there are four main things that need to be&nbsp;addressed.</p>
<ol>
<li>Mac menu items don&#8217;t contain&nbsp;icons</li>
<li>Mac menu items don&#8217;t have&nbsp;mnemonics.</li>
<li>The default menu accelerator is the Command key (KeyEvent.VK_META) and not&nbsp;Control.</li>
<li>Mac menus often have a different structure.  For example, &#8220;Quit&#8221; is never in the &#8220;File&#8221; menu, it&#8217;s on the Mac provided application menu along with your &#8220;Preferences&#8221; (think &#8220;Tools/Options&#8221; on&nbsp;Windows).</li>
</ol>
<p>These differences can be a huge pain to implement and you definitely want to avoid putting a whole stack of <code>if (Env.isMacOS())</code> statements in your code.  Of the four points above, <a href="http://pietschy.com/products/gui-commands/index.html">GUI Commands</a> handles the first three automatically, the fourth is handled using Mac specific configuration files that provide just the Mac specific&nbsp;differences.</p>
<h4>Fixing Icons, Mnemonics and the Default&nbsp;Accelerator</h4>
<p><a href="http://pietschy.com/products/gui-commands/index.html">GUI Commands</a> automatically provides the correct rendering on the Mac without any developer intervention.  The following images show how the &#8220;Edit&#8221; menu from <a href="http://pietschy.com/products/mr-schedule/index.html">Mr Schedule</a> appears on both windows and the Mac with the exact same&nbsp;configuration.</p>
<table border="0" align="center">
<tbody>
<tr>
<td><a href="http://pietschy.org/blog/wp-content/uploads/2009/01/windows-menu.png"><img class="aligncenter size-medium wp-image-150" title="windows-menu" src="http://pietschy.org/blog/wp-content/uploads/2009/01/windows-menu-161x300.png" alt="windows-menu" width="161" height="300" /></a></td>
<td><a href="http://pietschy.org/blog/wp-content/uploads/2009/01/mac-menu.png"><img class="aligncenter size-medium wp-image-149" title="Menu on a Mac" src="http://pietschy.org/blog/wp-content/uploads/2009/01/mac-menu-164x300.png" alt="Menu on a Mac" width="164" height="300" /></a></td>
</tr>
</tbody>
</table>
<p>GUI commands stores the details of any particular menu item in standard resource bundles and uses a relatively simple key syntax to define each value.  The following is a shows the configuration for the &#8220;Cut&#8221; menu item.  They basic syntax is <code>&lt;command-id&gt;@&lt;dotted-property-name&gt;=...</code>.  The &#8220;face&#8221; prefix is used for all visual properties such as the text or icon&nbsp;etc.</p>
<pre>editor-cut@face.text=Cu_t@default X
editor-cut@face.icon=classpath:images/cut.gif
editor-cut@face.description=Cuts the current selection to the clipboard (${accelerator})</pre>
<p>GUI commands then automatically removes the mnemonic and icon and uses the correct accelerator &#8220;<code>⌘X</code>&#8221; when running in a Mac environment.  The use of ${accelerator} in the description is also important since GUI Commands will inject the correct value for the platform, thus you&#8217;ll get &#8220;Ctrl-X&#8221; on Windows, and &#8220;⌘X&#8221; on the&nbsp;Mac.</p>
<h4>Changing Menus and Other&nbsp;Things</h4>
<p>So far, we haven&#8217;t had to provide any Mac specific configuration.  But to remove the &#8220;Quit&#8221; item from the file menu we&#8217;ll have take a different approach.  In this case we need to provide alternate configuration when running on Macs.  Importantly, by using GUI Commands you only need to supply the data that changes, i.e. you won&#8217;t have any replicated configuration (the <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY&nbsp;principle</a>).</p>
<p>In this example we&#8217;ll create a file menu that works correctly for both Windows and the Mac.  First off we&#8217;ll create the default configuration file, in it we&#8217;ll define the &#8220;File&#8221; menu and an &#8220;Open&#8221; and &#8220;Quit&#8221; command.  Menus are defined using the prefix <code>group!</code> and we&#8217;ll create our settings in a file called&nbsp;Commands.properties.</p>
<pre># The file menu
group!file-menu@face.text=_File
group!file-menu@members=open-command, separator, quit-command

# The commands
open-command@face.text=_Open@default O
quit-command@face.text=E_xit@alt F4</pre>
<p>Now we create MacCommandVariants.properties and put anything that is different for the Mac platform.  In our case the file menu has different members and the quit command has different text and a different&nbsp;accelerator.</p>
<pre># The Mac file menu (we only need to include the properties that change).
group!file-menu@members=open-command

# The quit-command has different text and accelerator on the Mac.
quit-command@face.text=Quit@default Q</pre>
<p>Now in our code we can do the&nbsp;following.</p>
<pre>// load all the commands as normal.
GuiCommands.load("Commands");
if (Env.isMacOS())
{
   // Load the Mac specific differences.  It's important to
   // do this after loading the main file so it can override
   // existing settings.
   GuiCommands.load("MacCommandVariants");
}</pre>
<h4>Using Locale&nbsp;Variants</h4>
<p>Because GUI Commands configuration files are standard ResouceBundles, you can also use Locale Variants to acheive this same behaviour.  In this case you&#8217;d configure you locale variant to something like &#8220;MAC&#8221; and rename your Mac settings to something like Commands_en_AU_MAC.properties.  Because of the way the Locale class works, this can be an issue of you want to use the default bundle or don&#8217;t want to specify country codes.  So unless you&#8217;re fully localising your app, the previous method is simpler and easier to&nbsp;understand.</p>
<h3>Putting Things in the Application&nbsp;Menu</h3>
<p>While GUI Commands doesn&#8217;t support this directly, the following shows how to add our Quit command to the applicaiton menu using&nbsp;<a href="http://homepage.mac.com/sroy/mrjadapter/">MRJAdapter</a>.</p>
<pre>QuitCommand quitCommand = ...;
MRJAdapter.addQuitApplicationListener(quitCommand.getActionAdapter());</pre>
<p>And that&#8217;s about it.  When running on the Mac, our menus will behave as expected, and our &#8220;Quit&#8221; will appear in all the right&nbsp;places.</p>
<p>You can read more about <a href="http://pietschy.com/products/gui-commands/index.html">GUI Commands on the website</a>.  Personal licenses <a href="http://pietschy.com/products/gui-commands/purchase.html">cost $15 dollars&nbsp;US</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://pietschy.com/blog/2009/01/mac-fidelity-on-menus-using-gui-commands/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mac Fidelity and the JOptionPane</title>
		<link>http://pietschy.com/blog/2009/01/mac-fidelity-joptionpane/</link>
		<comments>http://pietschy.com/blog/2009/01/mac-fidelity-joptionpane/#comments</comments>
		<pubDate>Sat, 03 Jan 2009 03:32:59 +0000</pubDate>
		<dc:creator>pietschy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pietschy.webfactional.com/blog/?p=4</guid>
		<description><![CDATA[The slogan of write once run anywhere definitely has it&#8217;s limits. In slowing migrating Mr Schedule toward the Apple Human Interface Guidelines the JOptionPane is one of those limits. There are a couple of Mac specific requirements that it just &#8230; <a href="http://pietschy.com/blog/2009/01/mac-fidelity-joptionpane/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The slogan of write once run anywhere definitely has it&#8217;s limits.  In <em>slowing</em> migrating <a href="http://pietschy.com/products/mr-schedule/index.html">Mr Schedule</a> toward the <a href="http://developer.apple.com/documentation/userexperience/Conceptual/AppleHIGuidelines/XHIGWindows/chapter_18_section_7.html#//apple_ref/doc/uid/20000961-BACJGAAI">Apple Human Interface Guidelines</a> the  JOptionPane is one of those limits.  There are a couple of Mac specific requirements that it just doesn&#8217;t support.  Amongst other things they&nbsp;include:</p>
<ol>
<li>The Mac supports document model dialogs that are displayed as a&nbsp;<a href="http://www.randelshofer.ch/quaqua/guide/jsheet.html">sheet</a>.</li>
<li>The Mac supports the notion of a &#8220;destructive option&#8221;, things like &#8220;Discard Changes&#8221;.  These options are displayed physically distant from non other options like &#8220;Save&#8221; or &#8220;Cancel&#8221;.  This is a perfect application of the proximity principle in <a href="http://www.amazon.com/Non-Designers-Design-Book-Typographic-Principles/dp/1566091594">visual design</a>.
<li>Mac dialogs don&#8217;t have a&nbsp;title.</li>
<li>Mac dialogs should display only the application&#8217;s icon and not the regular question or exclamation&nbsp;icons.</li>
</ol>
<p>The following example shows a document model dialog with a destructive&nbsp;option.</p>
<div id="attachment_100" class="wp-caption aligncenter" style="width: 310px"><a href="http://pietschy.com/blog/wp-content/uploads/2009/01/mac-dialog-example.png"><img src="http://pietschy.com/blog/wp-content/uploads/2009/01/mac-dialog-example-300x105.png" alt="Mac Dialog Example" title="Mac Dialog Example" width="300" height="105" class="size-medium wp-image-100" /></a><p class="wp-caption-text">Mac Dialog&nbsp;Example</p></div>
<p>Now the excellent <a href="http://www.randelshofer.ch/quaqua/index.html">Quaqua library</a> already does much of the work for us including providing a sheet style dialog implementation, but there are a few things that are still missing for easy use in a production&nbsp;environment.  </p>
<ol>
<li>Quaqua does&#8217;t provide a unified API for all platforms, it&#8217;s still up to the developer to write Mac specific&nbsp;code</li>
<li>The document model sheet implementation isn&#8217;t a blocking call.  This adds to the level of Mac specific code you need to write as well as adding an additional threading&nbsp;concern.</li>
</ol>
<p>Now to overcome this we need some kind of framework that delivers&nbsp;following:</p>
<ol>
<li>An encapsulation of all the data required to show a message to the user including the default and destructive&nbsp;options.</li>
<li>A standard mechanism to display the message to the user with well defined semantics for the developer (i.e. does this call block or&nbsp;not?)</li>
<li>A platform specific implementation the does the &#8220;right thing&#8221; for the&nbsp;platform.</li>
<li>A factory that automatically gives us the correct implementation based on the current&nbsp;platform</li>
</ol>
<p><strong>Creating Your Message</strong><br />
Most of this isn&#8217;t too hard, and pays off enormously once you use it in a second application.  In my code I&#8217;ve created a Message object that holds the message title, the main and information messages along with the options available (including if they&#8217;re the default or destructive&nbsp;option).</p>
<pre>
Message myMessage = new Message("This is the title");
myMessage.setMainMessage("Do you want to save the changes to
                          this message before closing?");
myMessage.setInfoMessage("If you don't save, your changes will
                          be lost");
// now add the options..
myMessage.addDefaultOption(Option.SAVE);
myMessage.addOption(Option.CANEL);
myMessage.addDestructiveOption(Option.DISCARD_CHANGES);
</pre>
<p>This creates everything we need to know about the message.  I&#8217;ve also created Option object instead of the JOptionPane integer approach since objects are nice and play better when using resource&nbsp;bundles. </p>
<p><strong>Displaying the Message</strong><br />
Now we need a mechanism for displaying the message.  To do this I&#8217;ve created a MessagePane class that acts as both an abstract base class and provides static factory methods for accessing the correct implementation for the platform.  You could of course separate these roles, but I chose not to.  The concrete instances of MessagePane are created by a service provider interface called MessagePaneProvider.  In my world this is <a href="http://pietschy.com/blog/2008/05/playing-with-google-guice-look-and-feel/">configured using Google Guice</a>, but you could just as easily do something like <code>MessagePane.setMessagePaneProvider(...)</code> if you&#8217;re not doing the injection&nbsp;thing.</p>
<p>Once our MessagePaneProvider has been configured we can now simply&nbsp;go:</p>
<pre>
// get a document message pane instance
MessagePane pane = MessagePane.getDocumentInstance(myFrame);

// now call to show to display it.  This call will block on
//  all platforms
Result result = pane.show(myMessage);

// now check the result
if (result.userChose(Option.SAVE))
{
   // save our document...
}
else if (result.userChose(Option.CANCEL))
{
   // cancel...
}
</pre>
<p>For the Mac this will use a MessagePane instance that displays a <a href="http://www.randelshofer.ch/quaqua/guide/jsheet.html">JSheet</a> and uses some <a href="http://foxtrot.sourceforge.net/">Foxtrot</a> magic to make it a blocking&nbsp;call.</p>
<p>The above example also highlights the shows of a Result object instead of JOptionPanes integer approach.  I find result.userChose(Option.SAVE) much more readable for a start, but more importantly result.userChose(&#8230;) throws an exception if passed an option that was never included in the&nbsp;message.  </p>
<p><strong>JSheet and Foxtrot Magic</strong><br />
 The only really tricky aspect of the design was getting the JSheet call to block.  The approach I&#8217;ve used uses <a href="http://foxtrot.sourceforge.net/">Foxtrot</a> to block the &#8220;show&#8221; method until until the JSheet callback has been&nbsp;invoked. </p>
<pre>
public Result
show(Message message)
{
   // we use a JOptionPane to do the work.  This method creates
   // and configures the JOptionPane appropriately for the platform.
   JOptionPane pane = createOptionPane(message);

   // Quaqua's JSheet is non blocking so we create a blocking
   // queque that foxtrot can block on until the selected option
   // is placed in queue by the JSheet callback.
   final ArrayBlockingQueue<Option> queue = new ArrayBlockingQueue<Option>(1);

   // now show the sheet.. this method won't block.
   JSheet.showSheet(pane, parent, new SheetListener()
   {
      public void
      optionSelected(SheetEvent evt)
      {
         // bung the result in the queue for the
         // foxtrot worker retrieve.
         queue.add((Option) evt.getValue());
      }
   });

   // Now use foxtrot to block on the queue waiting
   // for the sheet to return the result.
   Option selectedValue = (Option) Worker.post(new Job()
   {
      public Object run()
      {
         try
         {
            return queue.take();
         }
         catch (InterruptedException e)
         {
            throw new RuntimeException("Unexpected InterruptedException", e);
         }
      }
   });

   // and finally return the result
   return new Result(message, selectedValue, pane.getInputValue());
}
</pre>
<p><strong>Summary</strong><br />
So just a little bit of thought and effort you can create an API that is consistent and simple for the developer and pushes as many of the platform specific details as possible into the framework&nbsp;implementation.</p>
]]></content:encoded>
			<wfw:commentRss>http://pietschy.com/blog/2009/01/mac-fidelity-joptionpane/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mr Schedule 1.0.97 Released</title>
		<link>http://pietschy.com/blog/2008/10/mr-schedule-1097-released/</link>
		<comments>http://pietschy.com/blog/2008/10/mr-schedule-1097-released/#comments</comments>
		<pubDate>Mon, 27 Oct 2008 22:06:02 +0000</pubDate>
		<dc:creator>pietschy</dc:creator>
				<category><![CDATA[Mr Schedule]]></category>
		<category><![CDATA[Mr Schedule Announce]]></category>

		<guid isPermaLink="false">http://pietschy.webfactional.com/blog/?p=27</guid>
		<description><![CDATA[This release adds keyboard shortcuts for switching between the outline and notes editors along with a few bug fixes. Please read the release notes for more&#160;details. You can get the new version from the download&#160;page. Cheers&#160;Andrew]]></description>
			<content:encoded><![CDATA[<p>This release adds keyboard shortcuts for switching between the outline and notes editors along with a few bug fixes.  Please read the <a href="http://pietschy.com/downloads/mr-schedule/ReleaseNotes.html">release notes</a> for more&nbsp;details.</p>
<p>You can get the new version from the <a href="http://pietschy.com/products/mr-schedule/download.html">download&nbsp;page</a>.</p>
<p>Cheers<br />&nbsp;Andrew</p>
]]></content:encoded>
			<wfw:commentRss>http://pietschy.com/blog/2008/10/mr-schedule-1097-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simplifying</title>
		<link>http://pietschy.com/blog/2008/10/simplifying/</link>
		<comments>http://pietschy.com/blog/2008/10/simplifying/#comments</comments>
		<pubDate>Sun, 19 Oct 2008 00:03:57 +0000</pubDate>
		<dc:creator>pietschy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[UIs and Swing]]></category>

		<guid isPermaLink="false">http://pietschy.webfactional.com/blog/?p=26</guid>
		<description><![CDATA[I always find it healthy to come back and use code you wrote a while ago. There&#8217;s nothing like a bit of space to help see things in a new light. Often too you can be so focused on solving &#8230; <a href="http://pietschy.com/blog/2008/10/simplifying/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I always find it healthy to come back and use code you wrote a while ago.  There&#8217;s nothing like a bit of space to help see things in a new light.  Often too you can be so focused on solving one problem that you don&#8217;t get a chance to step back and see the bigger&nbsp;picture.</p>
<p>And so it was when using my binding framework the other day.  Don&#8217;t get me wrong, I really like it.  But the first pass gave me flexibililty I needed, but not the simplicity I needed for day to day regular use.  Who really wants to create presentation models using the&nbsp;following?</p>
<pre>// somewhere at startup
Pectin.registerMixin(ComponentMixin.instance());

// then when you need a presentation model
PresentationModel&lt;ComponentValueModel&gt; pm =
      new PresentationModel&lt;ComponentValueModel&gt;();

// and use the "firstName" value model..
pm.get("firstName").setEnabled(false);</pre>
<p>What&#8217;s a ComponentValueModel anyway and why do I need one?  As it turns out I almost always want one (since it gives my value models the common enabled, visible, and editable properties) so why do I have to specify it every time?  Then there&#8217;s validation, you almost always need that&nbsp;too.</p>
<p>So, short story long, I&#8217;ve layered the API.  The original classes have been moved to a lower level (i.e. GenericPresentationModel) and I&#8217;ve created new implementations that extend them and that come pre-configured with the default interfaces.   I&#8217;ve also installed the associated Mixins automatically so for everyday use it&#8217;s now&nbsp;just:</p>
<pre lang="java">// This is much better
PresentationModel pm = new PresentationModel();
pm.get("firstName").setEnabled(false);</pre>
<p>Much&nbsp;nicer.</p>
]]></content:encoded>
			<wfw:commentRss>http://pietschy.com/blog/2008/10/simplifying/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
