<?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>KATI</title>
	<atom:link href="http://katidev.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://katidev.com/blog</link>
	<description></description>
	<lastBuildDate>Thu, 07 Oct 2010 12:52:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Gameboards and GUIs</title>
		<link>http://katidev.com/blog/2009/06/04/gameboards-and-guis/</link>
		<comments>http://katidev.com/blog/2009/06/04/gameboards-and-guis/#comments</comments>
		<pubDate>Thu, 04 Jun 2009 09:56:09 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Research]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=208</guid>
		<description><![CDATA[I wrote a post for the Sofa blog called Gameboards and GUIs. It&#8217;s inspired by something I read in the game design book, Rules of Play, by Katie Salen and Eric Zimmerman and I want to take a moment here to recommend the book to anyone who&#8217;s interested in interface and interaction design. It&#8217;s a [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote a post for the Sofa blog called<a href="http://www.madebysofa.com/blog/gameboards-and-guis/"> Gameboards and GUIs</a>.  It&#8217;s inspired by something I read in the game design book, <a href="http://www.amazon.com/Rules-Play-Game-Design-Fundamentals/dp/0262240459/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1243940889&amp;sr=8-1">Rules of Play</a>, by Katie Salen and Eric Zimmerman and I want to take a moment here to recommend the book to anyone who&#8217;s interested in interface and interaction design.  It&#8217;s a great book with unique insight into the challenge of engaging people in meaningful and enjoyable experiences.  Add it to <em>your</em> reading rainbow!</p>
<p>Read <a href="http://www.madebysofa.com/blog/gameboards-and-guis/">Gameboards and GUIs</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2009/06/04/gameboards-and-guis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>KTUIKit 0.9.1</title>
		<link>http://katidev.com/blog/2009/05/26/ktuikit-091/</link>
		<comments>http://katidev.com/blog/2009/05/26/ktuikit-091/#comments</comments>
		<pubDate>Tue, 26 May 2009 13:09:42 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=202</guid>
		<description><![CDATA[I want to thank all of the brave Mac devs out there who&#8217;ve taken the time to try out KTUIKit. The comments and bug reports are extremely helful and appreciated. Thank you. Things have been moving along with KTUIKit and I&#8217;m finally ready for a new Pre-alpha milestone release (0.9.1). You can download a copy [...]]]></description>
			<content:encoded><![CDATA[<p>I want to thank all of the brave Mac devs out there who&#8217;ve taken the time to try out KTUIKit.  The comments and bug reports are extremely helful and appreciated.  Thank you.</p>
<p>Things have been moving along with KTUIKit and I&#8217;m finally ready for a new Pre-alpha milestone release (0.9.1).  </p>
<p>You can download a copy of the release <a href="http://katidev.com/blog/wp-content/uploads/2009/05/ktuikit-091.zip" title="KTUIKit 0.9.1.zip">here</a>, or checkout the source from the  <a href="http://code.google.com/p/ktuikit/source/checkout">GoogleCode project</a>.</p>
<p>The .zip file contains:</p>
<li>A build of the framework</li>
<li>A build of the plugin</li>
<li>The KTUIKit Xcode project</li>
<li>An example application Xcode project that uses the framework and plugin</li>
<p>I&#8217;ve posted the release notes on the project&#8217;s <a href="http://code.google.com/p/ktuikit/">home page</a>.  There are major API changes in this update so I&#8217;ve made the previous revision of the project available for <a href="http://katidev.com/blog/wp-content/uploads/2009/05/ktuikit-source-0901.zip" title="KTUIKit_Source_0.9.0.zip">download</a> for those who went beyond &#8216;brave&#8217; into the realm of &#8216;crazy&#8217; and have used it in a project you actually care about <img src='http://katidev.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>I&#8217;ve also updated the <a href="http://katidev.com/blog/ktuikit/">KTUIKit page</a> here on the blog with new instructions on how to install the plugin and use the framework in a project.  The example project on the page has also been updated to use the latest version of the plugin and framework.  </p>
<p>A little bit of news:  I started working at <a href="http://www.madebysofa.com/">Sofa</a> a few months back and we&#8217;re using KTUIKit in a new product. I&#8217;m developing KTUIKit for Sofa in a separate branch of the subversion project and will slowly move those changes over to the trunk as the designs are finalized and the code stabilized.  There are two things that made it into this version of the trunk that some people might find interesting:  <strong>KTLayerController</strong>, a new controller for layers (like a view controller is to views) and <strong>KTTabViewController</strong>, whose only job is to switch between a list of view controllers.  Both are still *in the works*, but I&#8217;ve been using them and I think they have promise.  I have very loose descriptions of the classes and more in the release notes.</p>
<p>Again, thanks to everyone and I&#8217;ll see you at WWDC!</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2009/05/26/ktuikit-091/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>KTUIKit 0.9.0</title>
		<link>http://katidev.com/blog/2008/11/12/ktuikit-090/</link>
		<comments>http://katidev.com/blog/2008/11/12/ktuikit-090/#comments</comments>
		<pubDate>Wed, 12 Nov 2008 21:21:54 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[KTUIKit]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=171</guid>
		<description><![CDATA[I&#8217;m pleased to (finally!) introduce KTUIKit, an open source framework and Interface Builder plug-in project. The goal of the project is to address some of the issues that I&#8217;ve brought up in previous posts on this blog: Incorporating NSViewController into Cocoa&#8217;s controller system Replacing NSView&#8217;s Autoresizing mechanism for the layout of views and controls Styling [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m pleased to (finally!) introduce <a href="http://katidev.com/blog/ktuikit/">KTUIKit</a>, an open source framework and Interface Builder plug-in project.  The goal of the project is to address some of the issues that I&#8217;ve brought up in previous posts on this blog:</p>
<li>Incorporating NSViewController into Cocoa&#8217;s controller system</li>
<li>Replacing NSView&#8217;s Autoresizing mechanism for the layout of views and controls</li>
<li>Styling of views (not controls, i wish&#8230;)</li>
<p>KTUIKit currently includes the XS-Controllers, KTView, subclasses of many of the standard Cocoa controls, KTLayoutManager and KTStyleManager.  The Interface Builder plug-in provides a GUI for the layout manager and style manager.  </p>
<p><strong>This is still very much a work-in-progress. Don&#8217;t try to use it in your own project yet!</strong>  There are bugs &#8211; especially in the Interface Builder &#8216;Style&#8217; inspector, which is basically still unusable for anyone other than the person that programmed it&#8230;  Nevertheless, I thought I&#8217;d go ahead and put the project out there &#8211; incomplete, with bugs and all.  </p>
<p>If you want to check it out in action, you can download an <a href="http://katidev.com/blog/wp-content/uploads/2008/11/ktuikit-090-example.zip" title="KTUIKit_0.9.0_Example.zip">example project</a>.  The project shows how to use the layout and style managers in the view controller classes as well as in Interface Builder. If you want to open the nib files, you&#8217;ll have to do a little bit of work to get Interface Builder to load the plug-in:</p>
<li>Build the KTUIKit Xcode project that came with the example project</li>
<li>Copy the framework, which is located in a directory called &#8220;Uninstalled Products&#8221; in the Xcode project&#8217;s build directory, into your ~Library/Frameworks directory</li>
<li>Launch Interface Builder and go to its Preferences window</li>
<li>Go to the &#8220;Plug-ins&#8221; tab and hit the Add (+) button</li>
<li>Navigate IB to the copy of the framework in your ~Library/Frameworks directory</li>
<li>Hit &#8216;Open&#8217;</li>
<li>KATI will show up in your list of plug-ins and its library objects will show up in your library.</li>
<h3>The Example Project</h3>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/11/exampleapp.jpg" alt="ExampleApp.jpg" border="0" width="450" height="303" /></div>
<p>This example is very similar to the view controller example projects I&#8217;ve posted in the past.  It&#8217;s basically a window composed of several nib files, pieced together by several view controllers.  The difference is that it uses KTUIKit&#8217;s views and their layout and style managers.  </p>
<p>The main thing to notice is how durable the layout is.  Make the window as small as you can and as big as you can &#8211; drag the split view dividers all the way to zero and back.  Nothing breaks. Everything is where it should be.  There are also examples in the code of using the layout manager&#8217;s relative layout configurations &#8211; like &#8220;filling&#8221; and &#8220;floating&#8221;. There is no extra layout calculation code in the view controllers and KTView is never subclassed in the example project.</p>
<p>I&#8217;ve created a page dedicated to <a href="http://katidev.com/blog/ktuikit/">KTUIKit</a>.  It contains information about how to get it from Google Code and about using the framework in an Xcode project.  </p>
<p>If you have comments or feedback or if you&#8217;re interested in contributing to its development please feel free to email me. Here&#8217;s to a quick move to 1.0!</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/11/12/ktuikit-090/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Simple NSViewController Sample Projects</title>
		<link>http://katidev.com/blog/2008/07/24/simple-nsviewcontroller-sample-projects/</link>
		<comments>http://katidev.com/blog/2008/07/24/simple-nsviewcontroller-sample-projects/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 11:52:25 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Sample Code]]></category>
		<category><![CDATA[NSViewController]]></category>
		<category><![CDATA[SampleCode]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=152</guid>
		<description><![CDATA[Hello!! Thanks for all of the feedback on the XS-Controllers design that Jonathan and I posted. We&#8217;re going to be making some changes to the design based on feedback, bug reports and the experience we&#8217;ve had using it ourselves over the past few months. First, I want to take a few steps back and offer [...]]]></description>
			<content:encoded><![CDATA[<p>Hello!! </p>
<p>Thanks for all of the feedback on the <a href="http://katidev.com/blog/2008/04/17/nsviewcontroller-the-new-c-in-mvc-pt-2-of-3/">XS-Controllers</a> design that Jonathan and I posted.  We&#8217;re going to be making some changes to the design based on feedback, bug reports and the experience we&#8217;ve had using it ourselves over the past few months. </p>
<p>First, I want to take a few steps back and offer a couple of example projects that use <a href="http://developer.apple.com/documentation/Cocoa/Reference/NSViewController_Class/Introduction/Introduction.html">NSViewController</a> – straight out of the box &#8211; in a non-document based application.  I hope these will be more useful for people who are just starting out with view controllers.  The projects do the following:</p>
<li>Create a view controller with a nib file</li>
<li>Add several view controllers&#8217; views to the window&#8217;s view hierarchy</li>
<li>Switching between two view controllers and their views</li>
<li>Patch a single view controller into the Responder Chain</li>
<p>There&#8217;s also a good <a href="http://developer.apple.com/samplecode/ViewController/listing11.html">sample project</a> available on Apple&#8217;s site.  I recommend checking it out. </p>
<h3> Simple View Controller Xcode Projects</h3>
<h4>Simple View Controller &#8211; Adding Views to the View Hierarchy</h4>
<p><a href="http://katidev.com/blog/wp-content/uploads/2008/07/simpleviewcontrollerpart1.zip" title="SimpleViewControllerPart1.zip"><img src="http://katidev.com/blog/wp-content/uploads/2008/07/xcodeprojecticon.png" alt="XcodeProjectIcon.png" border="0" width="25" height="21" align="left" />Download SimpleViewControllerPart1.zip</a></p>
<p>A window controller creates two view controllers and<br />
adds their views to the window&#8217;s view hierarchy.  The window controller keeps references to the view controllers as instance variables.  They are not added to the responder chain.</p>
<h4>Simple View Controller 2 &#8211; Switching View Controllers</h4>
<p><a href="http://katidev.com/blog/wp-content/uploads/2008/07/simpleviewcontrollerpart2.zip" title="SimpleViewControllerPart2.zip"><img src="http://katidev.com/blog/wp-content/uploads/2008/07/xcodeprojecticon.png" alt="XcodeProjectIcon.png" border="0" width="25" height="21" align="left" />Download SimpleViewControllerPart2.zip</a></p>
<p>This project extends the previous project so that the <strong>DetailViewController</strong> manages the switching between two other view controllers and adding their views to its &#8220;contentView&#8221;.  This gives you tab-like behavior with the addition of view controller switching instead of just view switching. </p>
<p>The <strong>DetailViewController</strong> is patched into the responder chain when it is created, after its view is added to the window, so that it can handle the View menu actions for switching the views.</p>
<h4>Note on the Responder Chain:</h4>
<p>If you take a look at the sample code, you&#8217;ll notice that I added the DetailViewController to the responder chain after the window controller.  This follows Jonathan&#8217;s and my design for the <strong>XSViewControllers</strong>.  Many people have asked why we didn&#8217;t add the <strong>XSViewControllers</strong> into the responder chain after their associated views instead.  There a couple of reasons for this:</p>
<li>A view controller can&#8217;t control when its view is added and removed from the view hierarchy, so in a design like ours, there is no reliable way to patch the chain in this way without subclassing and extending NSView to be aware of its view controllers.  This is a more intrusive design, in my opinion.
<li>There is a significant <em>behavior</em> difference between the two approaches.  Action messages take a <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/chapter_2_section_6.html#//apple_ref/doc/uid/10000060i-CH3-SW9">specific route</a> through the responder chain.  In order for a view controller to be able to validate a menu item, its view or one of its subviews will need to be the first responder.  <strong>This means that you have to subclass the view, override &#8216;acceptsFirstResponder&#8217; to return &#8220;YES&#8221; – AND that your user has to click in the view before going to the menu in order for the menu items to be usable.</strong>
<p>Placing the view controllers in the same part of the chain as the other controller classes ensures that the action message can travel to them, regardless of which view is the first responder.  The controllers can then decide which items to validate based on their own internal logic.
</li>
<p>To see the difference in behavior of the two approaches, change the sample code from the SimpleViewController2 project in the file <strong>MainWindowController.m</strong>, in the <strong>windowDidLoad:</strong> method:</p>
<pre>
	// patch the detail view into the responder chain
	NSResponder * aNextResponder = [self nextResponder];
	[self setNextResponder:mDetailViewController];
	[mDetailViewController setNextResponder:aNextResponder];
</pre>
<p>to</p>
<pre>
	// patch the detail view into the responder chain
	NSResponder * aNextResponder = [aDetailView nextResponder];
	[aDetailView setNextResponder:mDetailViewController];
	[mDetailViewController setNextResponder:aNextResponder];
</pre>
<p>After you make that change, build and run the project.  Click within the detail view area to make it the window&#8217;s First Responder.  Go to the &#8216;View&#8217; menu and the items will be validated.  Now click into the table view area and then return to the &#8216;View&#8217; menu.  The menu items won&#8217;t be validated.  You will have to click in the detail view area again to validate the menu items.  This isn&#8217;t the desired behavior for these menu items.  </p>
<p>Anyway&#8230;</p>
<h3>NSViewController and IB</h3>
<p>NSViewController is designed to be used with a nib file.  As you can with NSWindowController, you will initialize a view controller with the name of its associated nib file.  </p>
<pre>
mTableViewController = [[TableViewController alloc] initWithNibName:@"TableView" bundle:nil];
</pre>
<p>The view controller will automatically load the nib when it is asked to return its view for the first time.  In order for all of this to go smoothly, there are two things to be sure to do in your nib file:</p>
<h4>1.  Set the File&#8217;s Owner&#8217;s &#8220;Class&#8221; to be the NSViewController subclass that will be managing its view</h4>
<ol>
<li>Drag the view controller&#8217;s header file into the IB project or use the &#8220;Read Class Files&#8230;&#8221; command in the File menu and select the header file. </li>
<li>Select the &#8220;File&#8217;s Owner&#8221; object and go to &#8220;Identity&#8221; tab in the inspector palette. Start typing the class name of the view controller.  It should autocomplete for you.</li>
</ol>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/07/picture-161.png" alt="Picture 16.png" border="0" width="301" height="381" /></div>
<h4>2.  Connect the File&#8217;s Owner&#8217;s (your view controller) &#8220;view&#8221; outlet to the nib&#8217;s top level view.</h4>
<ol>
<li>Ctrl-drag from &#8220;File&#8217;s Owner&#8221; to the view.</li>
<li>Select the &#8220;view&#8221; outlet when the small context menu pops up.</li>
</ol>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/07/connectingoutlet.jpg" alt="ConnectingOutlet.jpg" border="0" width="507" height="402" /></div>
<p>That&#8217;s it!</p>
<h3>Resources</h3>
<p><a href="http://developer.apple.com/documentation/Cocoa/Reference/NSViewController_Class/Introduction/Introduction.html">NSViewController Class Reference</a></p>
<p><a href="http://developer.apple.com/samplecode/ViewController/listing11.html">Apple&#8217;s View Controller Sample Code</a> (shows example of switching view controllers)</p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html#//apple_ref/occ/cl/NSResponder">NSResponder Class Reference</a></p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/chapter_2_section_6.html#//apple_ref/doc/uid/10000060i-CH3-SW9">The Responder Chain for Action Messages</a> (from the docs on the Event Architecture)</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/07/24/simple-nsviewcontroller-sample-projects/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>WWDC 2008!</title>
		<link>http://katidev.com/blog/2008/06/07/wwdc-2008/</link>
		<comments>http://katidev.com/blog/2008/06/07/wwdc-2008/#comments</comments>
		<pubDate>Sat, 07 Jun 2008 21:35:15 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=137</guid>
		<description><![CDATA[I thought I could get the next post out before WWDC, but it seems doubtful at this point. Sorry for the long pauses lately, I&#8217;ve had lots of work to do for my real job and it seems that it will be this way for the next month or so. Anyway, if anyone wants to [...]]]></description>
			<content:encoded><![CDATA[<p>I thought I could get the next post out before WWDC, but it seems doubtful at this point.  Sorry for the long pauses lately, I&#8217;ve had lots of work to do for my real job and it seems that it will be this way for the next month or so.</p>
<p>Anyway, if anyone wants to hang out in San Francisco next week, send me an email or a <a href="http://twitter.com/catshive">tweet</a> <img src='http://katidev.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>See you there!!!</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/06/07/wwdc-2008/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>NSViewController, the New C in MVC &#8211; Pt. 3 of 3</title>
		<link>http://katidev.com/blog/2008/05/26/nsviewcontroller-the-new-c-in-mvc-pt-3-of-3/</link>
		<comments>http://katidev.com/blog/2008/05/26/nsviewcontroller-the-new-c-in-mvc-pt-3-of-3/#comments</comments>
		<pubDate>Mon, 26 May 2008 19:31:20 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Layout]]></category>
		<category><![CDATA[Research]]></category>
		<category><![CDATA[NSView]]></category>
		<category><![CDATA[NSViewController]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=127</guid>
		<description><![CDATA[The last two installments in this series focused on the challenge of integrating NSViewController into the controller layer of the current Cocoa MVC application architecture. This is an important step to take, especially when developing a Cocoa application with a single window interface design. In a single window design, users will access most of the [...]]]></description>
			<content:encoded><![CDATA[<p>The last two installments in this series focused on the challenge of integrating <a href="http://developer.apple.com/documentation/Cocoa/Reference/NSViewController_Class/Introduction/Introduction.html">NSViewController</a> into the controller layer of the current Cocoa MVC application architecture.  This is an important step to take, especially when developing a Cocoa application with a single window interface design. In a single window design, users will access most of the application&#8217;s features through one window rather than opening and closing several smaller windows as they are needed.  Since this one window will never close during a session, the multiple view controllers in the window will fill the role previously held by multiple window controllers in creating a dynamic Cocoa application.</p>
<p>The application&#8217;s view controllers will perform tasks like loading/unloading the content of nib files and their controllers as needed and validating/invalidating menu items as features are added or removed from the window.  Plugging NSViewController into the existing controller architecture is a simple way to provide it with the support it needs to fulfill these standard duties for your application.</p>
<p>However important these window controller-type tasks are, keep in mind that they are not the principle duty of a view controller.  Unlike <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWindowController_Class/Reference/Reference.html">NSWindowController</a>, NSViewController has a close relationship to the view layer of the Cocoa MVC design.  Each view controller manages a view in a view hierarchy.  A system of view controllers, like the system <a href="http://jonathandann.wordpress.com/">Jonathan Dann</a> and I described in the previous installment, manages the entire view hierarchy of a window. One of the most mission-critical jobs of a system of view controllers is to build and maintain the structure and layout of a complex view hierarchy in a dynamic environment.</p>
<p><img src="http://katidev.com/blog/wp-content/uploads/2008/04/lightroom.jpg" border="0" alt="lightroom.jpg" width="450" height="311" /></p>
<p style="font-size:12px; line-height:12pt;"><strong>Above:</strong> <a href="http://www.adobe.com/products/photoshoplightroom/">Adobe Photoshop Lightroom</a> is an example of a feature rich application with a single window interface design.</p>
<h3>Quick Quiz: what is a view hierarchy?</h3>
<p>Quick answer from the <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaViewsGuide/WorkingWithAViewHierarchy/chapter_5_section_2.html#//apple_ref/doc/uid/TP40002978-CH4-SW13chapter_5_section_2.html#//apple_ref/doc/uid/TP40002978-CH4-SW13">docs</a> (emphasis is mine):</p>
<blockquote><p>In addition to being responsible for drawing and handling user events, a view instance can act as a container, enclosing other view instances. Those views are linked together creating a view hierarchy. Unlike a class hierarchy, which defines the lineage of a class, <strong>the view hierarchy defines the layout of views relative to other views.</strong></p></blockquote>
<h3>V + C, the dynamic layout duo</h3>
<p>There is a key difference between developing a Cocoa application that spreads its interface over several windows and one that uses a single window interface.  In a single window design, the <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaViewsGuide/WorkingWithAViewHierarchy/chapter_5_section_2.html#//apple_ref/doc/uid/TP40002978-CH4-SW13chapter_5_section_2.html#//apple_ref/doc/uid/TP40002978-CH4-SW13">view hierarchy</a> of the application&#8217;s main window is much more complex and, most importantly, <em>dynamic</em> than Cocoa windows normally are.  In fact, the view hierarchy is a prominent character in this type of development. Managing its structure and layout throughout the application&#8217;s runtime is a significant design problem that should be addressed in a systematic way by the software&#8217;s MVC architecture – in both the controller and view layers.</p>
<p>NSViewController addresses this issue by providing support for building and managing the structure of a view hierarchy through its &#8220;view&#8221; instance variable.  Once you organize your view controllers into a coherent system, you have a convenient mechanism for accessing and adjusting the hierarchy from its significant branches.  But the problem is only half solved since changes in the view hierarchy are reflected by changes in the layout, and unfortunately, the issue of layout in a dynamic view environment remains to be addressed by Cocoa.</p>
<p>Building and maintaining a complex layout, like the one pictured above, requires cooperation from both the views and the controllers of a window.  The controllers are the dictators of the layout.  They tell the views <em>contained in their domain of the hierarchy</em> where to go and how to behave.  Unless the circumstances are very special, it&#8217;s up to the view hierarchy itself to do the calculations necessary to maintain the integrity of that layout as the forces within it change over time.  If either member of the layout duo fails to perform their duty, the interface will simply break.</p>
<h3>The problem with V</h3>
<p>In Cocoa, <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSView_Class/Reference/NSView.html">NSView</a> fails to perform its duty in this kind of system because it isn&#8217;t equipped with the right tools.  NSView has something called an <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaViewsGuide/WorkingWithAViewHierarchy/chapter_5_section_6.html#//apple_ref/doc/uid/TP40002978-CH4-SW12">&#8220;autoresizing mask&#8221;</a>, which is meant to define the layout behavior of a view when its superview&#8217;s layout changes.  However, Autoresizing was never designed to function in a view hierarchy with a dynamic structure.  It is simply not the right tool for this job.  This is evidenced by one simple thing:  Autoresizing requires that a view is <em>already</em> laid out within its superview before you are supposed to set the desired resizing behavior.</p>
<p>This is well and good when you&#8217;re creating your entire layout in Interface Builder, where all the views are present and accounted for, but it&#8217;s simply not a practical limitation to make in a system of views and view controllers where elements of the layout will be added and removed during the application&#8217;s runtime.</p>
<p>It means that a view controller must have knowledge of it&#8217;s view&#8217;s superview and its frame before it can technically set a layout, but view controllers don&#8217;t necessarily have that information. For instance, when a view controller is initialized, it will create a view that will <em>eventually</em> be added to the view hierarchy.  At that moment, however, it doesn&#8217;t know anything about the view/controller hierarchy that it and its view are about to become a part of.  Technically, there&#8217;s no way for the controller to guarantee that the layout it dictates to its view (or more specifically, the view&#8217;s subviews) won&#8217;t be damaged by the layout of the view above it in the hierarchy.  Since NSViewController can&#8217;t always meet the requirements set forth by Autoresizing, the layout is exposed to the glitches and bugs that I&#8217;ve described in previous posts by default, and there&#8217;s nothing to be done about it except to take extra special care to explicitly size and position new views when adding them into the hierarchy and to set limits on how much the user is allowed to resize elements like split views and the window itself.  This is just extra grunt-work code that isn&#8217;t *really* necessary.  It&#8217;s a byproduct of the bugs in Autoresizing.</p>
<p>The bigger problem, one that does sometimes affect the design of the controllers, is that when a view controller makes a change to the existing view hierarchy, by either adding or removing views or manually adjusting the size or position of a view, it needs to take the view&#8217;s siblings into consideration.  The quote I pasted earlier, defining a view hierarchy, states that:</p>
<blockquote><p>the view hierarchy defines the layout of views relative to other views.</p></blockquote>
<p>What the docs really mean is that the layout of views is defined relative to their superviews.  The sibling views aren&#8217;t considered by the view hierarchy at all during autoresizing. So, any sibling that needs to move or resize as a result of the change needs to have its layout recalculated and its autoresizing mask re-set by the view controller that propagated the change – <em>even if the affected views aren&#8217;t in the controller&#8217;s domain of the view hierarchy</em>.  In this situation, the dynamic layout behavior of the view hierarchy becomes the responsibility of the view controller to maintain. This slippage of responsibility results in case-by-case workaround code that&#8217;s not only a pain in the ass to maintain, but that sometimes requires dependencies to views contained by other view controllers to be hard coded into the view controller.  All this does is make your view controllers less reusable by no fault of their own.  Again, none of this is necessary, it&#8217;s a byproduct of the limitations of Autoresizing.</p>
<h3>Absolute vs. Relative</h3>
<p>At the heart of the problem with Autoresizing, specifically in a dynamic system of views and view controllers, is the fact that there&#8217;s just nothing dynamic about it.  The mechanism is based on absolute positions and sizes, which makes it an inappropriate layout tool for this kind of interface development.  There are very few absolutes in a single window interface design.  Absolutes might include the height of a toolbar or the width of a control, but the state of the view hierarchy as a whole, at any given time during the app&#8217;s runtime, is variable.</p>
<p>A dynamic view hierarchy and its controller counterparts would be better served by a layout tool that can accommodate <strong>relative sizes and positions</strong>.  In a relative system, a view controller could just tell a newly created view to, for example, *fill* the width and height of its superview or *float* upwards in its superview – without having to specify any specific size or position (which might not be known anyway) – and the view hierarchy would work out the details once the view is in there.</p>
<p>Remember, view controllers have A LOT of responsibility in a Cocoa applicaiton.  They handle action events, load nib files, validate menu items, and sync up views to their data.  Why add managing the autoresizing behavior of the view hierarchy to their already long list of chores?</p>
<h3>Still more to come&#8230;</h3>
<p>So, yeah, I warned about the rant <img src='http://katidev.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />   Now I&#8217;ll try to offer a solution.</p>
<p>I&#8217;ve prepared an example project that illustrates how to use Jonathan&#8217;s and my controller subclasses, <strong>XSWindowController</strong> and <strong>XSViewController</strong> to build and manage a dynamic view hierarchy.  The project introduces an NSView subclass, <strong>KTView</strong>, into the mix.  Naturally, <strong>KTView</strong> uses an alternative to the Autoresizing mechanism that&#8217;s specifically designed to work within a changing view hierarchy.  It&#8217;s not a perfect solution (only Apple can do that), but it does get rid of the extra code from the view controllers that&#8217;s only there as a byproduct of Autoresizing.</p>
<p>The goal of the project is to bring together the concepts and opinions that have been covered in these three posts through examples of NSViewController in action.</p>
<p>I&#8217;ve decided that I don&#8217;t want to release <strong>KTView</strong> without an Interface Builder plugin, so I&#8217;ll publish the project with a tutorial as soon as that&#8217;s finished.</p>
<p>Until then, I found the original Smalltalk MVC Design paper, <a href="http://st-www.cs.uiuc.edu/users/smarch/st-docs/mvc.html">How to use Model-View-Controller</a>.  It&#8217;s interesting to read how Cocoa&#8217;s MVC design deviated from the original idea, especially when it comes to views and controllers.  Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/05/26/nsviewcontroller-the-new-c-in-mvc-pt-3-of-3/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Manual Input Sessions</title>
		<link>http://katidev.com/blog/2008/04/23/manual-input-sessions/</link>
		<comments>http://katidev.com/blog/2008/04/23/manual-input-sessions/#comments</comments>
		<pubDate>Wed, 23 Apr 2008 10:30:49 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Art]]></category>
		<category><![CDATA[Input]]></category>
		<category><![CDATA[Research]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=113</guid>
		<description><![CDATA[In Computer Administrative Debris, I briefly discussed the idea of &#8220;directness&#8221; in interaction design. I described a &#8220;direct&#8221; interaction model as one where the visual representation of the content and the interface to the content are the same. A direct interaction model also implies some sort of physical interaction with content. Today, we most frequently [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://katidev.com/blog/2008/02/15/computer-administrative-debris/">Computer Administrative Debris</a>, I briefly discussed the idea of &#8220;directness&#8221; in interaction design.  I described a &#8220;direct&#8221; interaction model as one where the visual representation of the content and the interface to the content are the same.  A direct interaction model also implies some sort of physical interaction with content.  Today, we most frequently use the mouse as an extension of our bodies to &#8220;point&#8221; at objects on the screen and to &#8220;drag&#8221; or &#8220;drop&#8221; them.  With gesture and touch-based technologies entering the mainstream, these interactions will become more and more concerned with the movement and/or form of the user&#8217;s actual body. </p>
<p>A beautiful and extreme example of directness in an interface design can be found in the the software developed by <a href="http://www.flong.com/">Golan Levin</a> and <a href="http://www.thesystemis.com/">Zachary Lieberman</a> for their 2004 audio/visual performances, <a href="http://www.tmema.org/mis/">Manual Input Sessions</a>.</p>
<blockquote><p>
The Manual Input Sessions is a series of audiovisual vignettes which probe the expressive possibilities of hand gestures and finger movements.
</p></blockquote>
<p>Using a custom hardware/software setup, they developed interfaces for creating and composing audio in real-time that incorporate physical objects and the body into the interaction models.  Users of this software literally mold the audio with their hands over time.  </p>
<p>Also, when you watch the videos, notice how each interface has environmental characteristics that aid the user in creating and composing the audio.  This is a clever way to add extra meaning to the input data.  It also infuses the interfaces with a sense of play and exploration, so they become much more instrument-like and less tool-like.</p>
<p><strong>[these videos need sound]</strong></p>
<p><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/IOwtu1B_DR4&#038;hl=en"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/IOwtu1B_DR4&#038;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object></p>
<p><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/57vdcjLd6Yw&#038;hl=en"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/57vdcjLd6Yw&#038;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object></p>
<p><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/iV-OoNTFS1E&#038;hl=en"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/iV-OoNTFS1E&#038;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/04/23/manual-input-sessions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NSViewController, the New C in MVC &#8211; Pt. 2 of 3</title>
		<link>http://katidev.com/blog/2008/04/17/nsviewcontroller-the-new-c-in-mvc-pt-2-of-3/</link>
		<comments>http://katidev.com/blog/2008/04/17/nsviewcontroller-the-new-c-in-mvc-pt-2-of-3/#comments</comments>
		<pubDate>Thu, 17 Apr 2008 13:14:17 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[NSViewController]]></category>
		<category><![CDATA[NSWindowController]]></category>
		<category><![CDATA[ResponderChain]]></category>
		<category><![CDATA[SampleCode]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=109</guid>
		<description><![CDATA[In the last post on NSViewController, I described the need for a view controller class that is part of a sound controller architecture, especially when developing an application with a single window interface. In this post, Jonathan Dann and I will share the design we came up with for integrating NSViewController into the existing Cocoa [...]]]></description>
			<content:encoded><![CDATA[<p>In the last post on <a href="http://developer.apple.com/documentation/Cocoa/Reference/NSViewController_Class/Introduction/Introduction.html">NSViewController</a>, I described the need for a view controller class that is part of a sound controller architecture, especially when developing an application with a single window interface. In this post, <a href="http://jonathandann.wordpress.com/">Jonathan Dann</a> and I will share the design we came up with for integrating NSViewController into the existing Cocoa MVC application architecture using <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWindowController_Class/Reference/Reference.html">NSWindowController</a> as the glue.  </p>
<p>Before, we do that&#8230;</p>
<h3>Meet Jonathan.</h3>
<p>I&#8217;m currently training with the National Health Service in the UK, working towards becoming a state-registered Medical Physicist. I was introduced to programming during my Bachelor&#8217;s degree where I did a short course in C. During my Master&#8217;s degree I learnt some FORTRAN and then had my first experience of object-oriented programming during that year.  Since then I&#8217;ve been learning as much as I could about Cocoa, design patterns, and the whole world of Mac programming. I&#8217;ve begun to write my first app, which will be available sometime around September, which really began life as a personal project when the tool I was using didn&#8217;t work right and didn&#8217;t fit properly within OS X.</p>
<p>As my code grew in size I soon realised that I needed a controller for some of my more complex view behaviour, NSSplitViews, NSTextViews, NSOutlineViews all need delegates to unlock their power and when all of this was in the same window controller I got the feeling it was doing work that it shouldn&#8217;t have to.  I started using NSViewController and came to the conclusion that it didn&#8217;t quite fit in my design, after considering how MVC should work I asked on cocoa-dev how other people use it. Sure enough, it sparked some conversation. I think that Apple has left the use of this class up to developers intentionally, maybe they will extend it in future releases, maybe having a structured controller system seems a little abstract for smaller programs, but I think it makes things easier to maintain in the long-run.</p>
<p>After using the class for a while I am of the mind that each view in an app could potentially have its own controller, although this would probably be overkill; the only structure that then makes sense is a tree, just like the view hierarchy.  I now use these classes extensively to inform the views, for example, how they should look: the view can then draw itself based on those options it gets from its overlord.</p>
<h3>The XS (extra special) Controllers</h3>
<p>Our solution includes to two classes:</p>
<ol>
<li><strong>XSWindowController</strong>, an NSWindowController subclass</li>
<li><strong>XSViewController</strong>, an NSViewController subclass</li>
</ol>
<p>You can find these classes in the example project (XCode 3.0).  Dowonload it <a href="http://katidev.com/blog/wp-content/uploads/2008/04/viewcontroller.zip">here</a>.</p>
<h3>The Goal of This Design</h3>
<p>The goal of our design is simple:  We want a way to manage a group of view controllers in a way that fits in nicely with the current Cocoa MVC architecture.  </p>
<p>When building a Cocoa app, the controller layer of the architecture can be described very loosely as: </p>
<ul>
<li>NSDocument contains a list of NSWindowControllers</li>
<li>Each window controller has an associated window</li>
</ul>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/04/cocoaarchitecture.jpg" alt="CocoaArchitecture.jpg" border="0" width="450" height="389" /></div>
<p>We want to extend this design so that:</p>
<ul>
<li>NSDocument contains a list of NSWindowControllers*</li>
<li>Each NSWindowController conains a list of NSViewControllers</li>
<li>Each NSViewController contains a list of subcontrollers</li>
<li>Each NSViewController has an associated view</li>
</ul>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/04/xsarch1.jpg" alt="XSArch.jpg" border="0" width="450" height="276" /></div>
<p>*Our changes happen beneath the document layer, so it is also a valid design for applications that aren&#8217;t document-based.</p>
<h3>XSViewController and XSWindowController</h3>
<p>In order to meet our goals, we enhanced Cocoa&#8217;s NSWindowController and NSViewController classes.</p>
<p>In <strong>XSViewController</strong>, we added a list of subcontrollers and the necessary methods to manage that list.  We also gave the view controllers a reference to the window controller.  </p>
<p>In <strong>XSWindowController</strong>, we added a list of view controllers.  The window controller is the &#8220;host&#8221; for the view controllers, so when the window controller is created and destroyed by the document, it does the same to the view controllers.  The window controller also does some extra work that is necessary for the view controllers to be integrated smoothly into the existing Cocoa controller architecture.  We&#8217;ll describe this work further down.</p>
<p>In this setup, you would use the following <strong>XSWindowController</strong> methods to add and remove view controllers,</p>
<pre>
- (void)addViewController:(XSViewController *)viewController;
- (void)removeViewController:(XSViewController *)viewController;
</pre>
<p>In <strong>XSViewController</strong>, you can nest controllers and manipulate the structure of the controller tree using several methods that will be familiar to those who have worked with mutable arrays,</p>
<pre>
- (void)addChild:(XSViewController *)child;
- (void)insertObject:(XSViewController *)child inChildrenAtIndex:(NSUInteger)index;
- (void)insertObjects:(NSArray *)children inChildrenAtIndexes:(NSIndexSet *)indexes;
- (void)insertObjects:(NSArray *)children inChildrenAtIndex:(NSUInteger)index;
- (void)removeChild:(XSViewController *)child;
- (void)removeObjectFromChildrenAtIndex:(NSUInteger)index;
</pre>
<p>As long as you use these methods to add and remove view controllers from the application, you will get all of the benefits of the design. </p>
<p><strong>Quick design note: </strong></p>
<p>We want to note here that we considered a design where the window controller contained one view controller that would be the root of a single view controller tree.  We chose to keep a list of view controllers in the window controller because it feels redundant to have to make a second controller that represents the entire window.</p>
<p>In a perfect world, the view controllers and window controllers would actually be the same class, so that the window controller would be the root of a single tree of controllers.  This isn&#8217;t possible, but we decided that we would design with that structure in mind anyway.</p>
<h3>Working with Cocoa</h3>
<p>So, after we had this system set up and running, making sure that memory management was handled properly, we had to handle some Cocoa-specific behaviors so that the view controllers were well integrated into the Cocoa application architecture.  This is the &#8220;glue-code&#8221; of this design.  There are two Cocoa-related issues that we had to consider.</p>
<h4> Cocoa Consideration 1: Taking care of the Responder Chain</h4>
<p>NSViewController is a subclass of NSResponder, but it needs to be added to the responder chain to receive action events from things like buttons and menu items.  We decided that our design should patch the responder chain so that it runs through the view controllers like this:</p>
<p><img src="http://katidev.com/blog/wp-content/uploads/2008/04/responderchainsmall.jpg" alt="ResponderChainSmall.jpg" border="0" width="450" height="295" /></p>
<p>We looked at two approaches to solving this problem.  The first approach would be to handle the responder chain in the NSViewController class, so that when a view controller was added or removed from the tree, its super controller would make sure the responder chain was patched together correctly.</p>
<p>The other approach is to have the window controller do the responder chain patching whenever a view controller is added or removed. </p>
<p>Both of these approaches have their advantages and disadvantages.  </p>
<p>The first approach would keep things logically clean and less glue-like.  The view controllers wouldn&#8217;t have to communicate back to the window controller when they add or remove their subcontrollers.  If this were the perfect design world, where the window and view controllers were in the same tree, this would be the obvious way to maintain the responder chain throughout a single hierarchy of controllers.  </p>
<p>The second approach is just more simple in this particular setup.  Since this isn&#8217;t the perfect design world, the code that adds the view controllers to the responder chain would have to be repeated in both classes anyway.  Letting one class handle the responder chain keeps this code centralized.</p>
<p>We decided to use the second approach.  We don&#8217;t feel that there is a perfect solution to this problem and that either approach works fine.</p>
<p>The method that patches the responder chain is in <strong>XSWindowController</strong>:</p>
<pre>- (void)patchResponderChain;</pre>
<p>The source code will show how simple it is to keep the responder chain looking like it does in the diagram.</p>
<h4>Consideration 2: Bindings and Observations</h4>
<p><a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/CocoaBindings.html">Bindings</a> and <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html">Key-Value Observing</a> are powerful Cocoa mechanisms that help us to keep our controllers and our data models separate.  Most view controllers and window controllers will have bindings or KVO set up in some way.  </p>
<p>In NSViewController, there is the idea of a &#8220;representedObject&#8221;.  According to the documentation of NSViewController:</p>
<blockquote><p>Declaring a generic representedObject property, to make it easy to establish bindings in the nib to an object that isn&#8217;t yet known at nib-loading time or readily available to the code that&#8217;s doing the nib loading.</p></blockquote>
<p>This is a handy feature of NSViewController, especially if you are setting up all of your bindings in Interface Builder, but in a more complex setup, the single &#8220;representedObject&#8221; may not be the best way to expose a view controller to the data in an application.  </p>
<p>There are situations where you might want to set up several KVOs and bindings in code and then remove them when you don&#8217;t need them anymore.  If you forgo the &#8220;representedObject&#8221; as a means to set up KVO with your application&#8217;s data, you might come across this message in your logs when you close the document:</p>
<p><strong>An instance (so-and-so) of class (so-and-so) is being deallocated while key value observers are still registered with it.  Break on _NSKVODeallocateLog to start debugging.<br />
</strong></p>
<p>We decided to go ahead and handle the possibility of these situations by adding a method to <strong>XSViewController</strong> called,</p>
<pre>- (void)removeObservations;</pre>
<p>This gives the view controllers a chance to remove observations or bindings that they set up in code before the data is released. The window controller has to manage the timing of this.  In <strong>XSWindowController</strong>, we do it right before the window closes, in an implementation of the window&#8217;s delegate method,</p>
<pre>- (void)windowWillClose:(NSNotification *)notification;</pre>
<p>The window controller tells its view controllers to &#8220;removeObservations&#8221; here and they pass the message on to their subcontrollers.  The window controller and document can then release data as they normally would in their implementations of &#8220;dealloc&#8221;.</p>
<p><strong>Quick notes on subclassing:</strong></p>
<p>If an <strong>XSViewController</strong> subclass implements the &#8220;removeObservations&#8221; method, it is responsible for calling super&#8217;s implementation so that the message will continue to be propagated down its branch of the tree.  </p>
<p>If an <strong>XSWindowController</strong> subclass needs to implement &#8220;windowWillClose&#8221;, it should be sure to call super&#8217;s implementation so that the view controllers will get the message to remove their observations.  The timing of this message is important, so if you are releasing some data here, be sure to call super first.  </p>
<p>Using &#8220;windowWillClose&#8221; for a feature like this may not be the best solution, but as far as we can tell, it seems like the most convenient place to perform this task.</p>
<h3>That&#8217;s It.</h3>
<p>With these few enhancements, we now have two new abstract super-classes for our controllers, <strong>XSWindowController</strong> and <strong>XSViewController</strong>.  When we subclass them to build our UIs, we get the controller architecture that we illustrated at the beginning of the post and the following features built in to our view controller:</p>
<ul>
<li>Automatic memory management!</li>
<li>Automatic inclusion in the responder chain!!!</li>
<li>A designated method for removing observations or bindings!</li>
<li>A relationship with the window controller and document!</li>
</ul>
<p>This design will become more and more useful as your single window interface becomes more complex, especially as your feature set changes over the life-time of your development.  With this architecture in place, you have more flexibility to try things out and change your design without worrying about breaking the responder chain (which is not that easy to debug) or causing memory leaks by accident as you&#8217;re working rapidly to test UI designs.  As long as you keep to MVC design principles, it is possible to create self-contained view controllers that can be plugged in to, and unplugged from, your UI with very little hassle. </p>
<h3>Next Time&#8230;</h3>
<p>First, thanks so much to Jonathan for working on this post with me.  It was great to have the chance to brainstorm with another developer, especially one whose applications are completely different from the ones I work on every day.  Working with him on this design helped to get me out of my usual mind-set and to isolate the issues that are truly common to any Cocoa application rather than unique to my own projects.  This has been an educational and super-productive experience for me – Thanks, Jonathan!</p>
<p>AND a another big thanks to Jonathan for setting up the Xcode 3.0 <a href="http://katidev.com/blog/wp-content/uploads/2008/04/viewcontroller.zip">example project and the source code</a>!  </p>
<p>In the next and last post about NSViewController, I&#8217;m going to discuss its relationship to NSView and the view hierarchy in more detail.  One of the many important jobs of a view controller is to help to build and manage the view hierarchy during runtime.  This is especially important when coding a single window interface that needs to give users access to many different features that can&#8217;t all be displayed in the window at one time.</p>
<p>Anyone who is sick of me writing about autoresizing should just skip the next installment ; ) ( or in Japanese, ^_- )</p>
<h3>Resources</h3>
<p>The <a href="http://katidev.com/blog/wp-content/uploads/2008/04/viewcontroller.zip">example project</a> contains <strong>XSWindowController</strong> and <strong>XSViewController</strong>, which contain all the nitty-gritty implementation details.  There is also an example app that shows how you could subclass these classes to build a UI based on the XS controllers. </p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/chapter_2_section_6.html">Cocoa Event-Handling Guide: The Responder Chain</a></p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Conceptual/Documents/Documents.html">Introduction to Document-Based Applications Overview</a></p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Reference/NSViewController_Class/Introduction/Introduction.html">NSViewController Class Reference</a></p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWindowController_Class/Reference/Reference.html">NSWindowController Class Reference</a></p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html">Introduction to Key-Value Observing Programming Guide</a></p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/CocoaBindings.html">Introduction to Cocoa Bindings Programming Topics</a></p>
<h3>UPDATE 04/23/08</h3>
<p>We updated the example project today.  The biggest change we made is in XSViewController.  We were previously setting the &#8220;representedObject&#8221; of child controllers to be that of its parent.  In the new version we don&#8217;t deal with &#8220;representedObject&#8221; in any way.  You can just use NSViewControllers methods to set them case-by-case.  </p>
<p><a href="http://katidev.com/blog/wp-content/uploads/2008/04/viewcontroller.zip">XCode Project</a></p>
<p><a href="http://katidev.com/blog/wp-content/uploads/2008/04/viewcontrollersource.zip" title="ViewControllerSource.zip">Just the Source Code</a></p>
<p><a href="http://katidev.com/blog/wp-content/uploads/2008/04/xscontrollers.zip" title="XSControllers.zip">Just XSViewController and XSWindowController</a></p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/04/17/nsviewcontroller-the-new-c-in-mvc-pt-2-of-3/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>NSViewController, the New C in MVC &#8211; Pt. 1 of 3</title>
		<link>http://katidev.com/blog/2008/04/09/nsviewcontroller-the-new-c-in-mvc-pt-1-of-3/</link>
		<comments>http://katidev.com/blog/2008/04/09/nsviewcontroller-the-new-c-in-mvc-pt-1-of-3/#comments</comments>
		<pubDate>Wed, 09 Apr 2008 10:11:05 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[NSViewController]]></category>
		<category><![CDATA[NSWindowController]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=99</guid>
		<description><![CDATA[Applications like iTunes and iPhoto have established a single window interface as the de-facto standard for modern Mac UI design. This design is great for end users, who no longer have to switch between several windows to be productive with their software. For developers, on the other hand, this design poses several challenges in terms [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/04/iphoto.jpg" alt="iPhoto.jpg" border="0" width="450" height="293" /></div>
<p>Applications like iTunes and iPhoto have established a single window interface as the de-facto standard for modern Mac UI design.  This design is great for end users, who no longer have to switch between several windows to be productive with their software.  For developers, on the other hand, this design poses several challenges in terms of interaction design and software architecture, especially in the view and controller layers of the MVC architecture prescribed by Cocoa.  This post is the first of three that will address this architectural design problem and, more specifically, examine the role of Cocoa&#8217;s new <a href="http://developer.apple.com/documentation/Cocoa/Reference/NSViewController_Class/Introduction/Introduction.html">NSViewController</a>  class in this design.</p>
<p>There are at least two major architectural issues that have to be addressed by the interface developer when coding this kind of interface. First, a single window interface requires a software architecture that can effectively handle dynamic changes in the view hierarchy during runtime.  I&#8217;ll address this issue in more detail in the third post on this topic.  </p>
<p>The second issue that needs to be addressed is that in a single window interface design, a great deal of burden naturally falls on <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWindowController_Class/Reference/Reference.htmlReference.html">NSWindowController</a>.  In this type of setup, the application&#8217;s main window controller is responsible for handling a majority of the user interface.  In other words, the interface code for an entire application, apart from a few dialog windows here and there, is expected to go into one single class.  This code quickly becomes unmanageable and unmaintainable as the feature set changes and grows.  It is natural to start to break this code up into logical groups of subcontrollers and to develop a system to manage and maintain these groups.</p>
<p>To accomplish this, many of us have already come up with our own &#8220;view controller&#8221; systems to extend our controller architecture.  Apple has also started to address this issue by adding NSViewController to the Cocoa SDK in Leopard.  </p>
<p>A standard view controller class is a great idea and welcome addition to Cocoa.  One particular feature, the built-in memory management of objects in nib files, makes NSViewController a very attractive alternative to using a custom view controller.  However, this class seems to have been left out of the controller layer of Cocoa&#8217;s MVC application architecture. Apart from being a subclass of NSResponder, there is no indication from the documentation or the class&#8217;s design that it is intended to be a part of the current controller architecture, but at the same time, it cannot be functional on its own.  So where does NSViewController fit into a Cocoa app and how can developers use this class effectively to build a solid controller architecture in their applications?</p>
<h3>NSViewController and the Cocoa MVC Architecture</h3>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/apparchitecture.jpg" alt="AppArchitecture.jpg" border="0" width="450" height="397" /></div>
<p>For larger projects, specifically projects with single window interfaces, the view controllers form a significant portion of the software architecture and it would make sense for there to be a standard way to approach view controllers as a general design problem. Unfortunately, the Cocoa documentation doesn&#8217;t give developers any hint as to what that approach should be.  There are some clues in NSViewController&#8217;s API about how you could patch a single view controller into a specific area of your current design, but nothing that suggests a holistic design strategy. </p>
<p>The conceptual documentation of Cocoa&#8217;s <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/Documents/Concepts/OverviewDocArchitecture.html#//apple_ref/doc/uid/20000023">&#8220;Document-Based Application Architecture&#8221;</a> hasn&#8217;t been updated yet to explain how the Cocoa engineers intend for us to incorporate NSViewController the current application architecture.  For example, the section that describes the &#8220;Key Objects&#8221; in the architecture makes no mention of NSViewController, and because of that, the paragraphs on &#8220;Typical Usage Patterns&#8221; still suggest that:</p>
<blockquote><p>If your document has only one window, but it is complex enough that you’d like to split up some of the logic in the controller layer, you can subclass NSWindowController as well as NSDocument. In this case, any outlets and actions and any other behavior that is specific to the management of the user interface goes into the NSWindowController subclass.</p></blockquote>
<p>Clearly a single NSWindowController subclass isn&#8217;t going to manage the whole user interface for an application like iPhoto.  This would be a perfect place to discuss the role of NSViewController.</p>
<p>I&#8217;ve given a lot of thought to the possibility that maybe it is better for Apple to leave this particular design decision to the developers.  As I mentioned, the view controllers in an application can grow into a significant portion of the architecture and it is annoying when Cocoa&#8217;s designs clash with your own.  However, if this is the case, what is the point of adding a view controller to Cocoa?  Those of us that have our own view controller system design already have our own view controller class that works in that design.  What is the incentive to use NSViewController instead of our own class if it doesn&#8217;t present a solution to the larger problem?</p>
<p>I&#8217;ve found from my own experience and from talking to other developers, that the design of a view controller system is the kind of design that tends to solve itself naturally within the current Cocoa MVC architecture.  There isn&#8217;t much room for imagination when it comes to its most basic structure.  If you ask developers how they organize their controllers, you&#8217;ll almost always get some variation of the same basic design:  view controllers own and manage a list of subcontrollers and the window controller owns and manages the view controllers.  It isn&#8217;t much different from the window and the view hierarchy.  The window has a content view and the content view has a list of subviews which contain a lists of subviews, etc.  </p>
<p>In fact, this particular relationship – the window and its views to the window controller and its view controllers – is very tight.  The view controllers and the window controller build and manage the view hierarchy.  The window controller has to add the view controllers&#8217; views to the window&#8217;s content view.  On top of that, the window controller needs to provide a way for the view controllers to enter the responder chain and, if there is a document, it should also give them access to that.  It seems logical that the relationship between NSWindowController and NSViewController should exist by default. The view controllers are, after all, an extension of the window controller. </p>
<p>When programming a large, single window interface, the first enhancements a developer is likely to make to NSViewController, before they can effectively use it in their application, is to add a list of subcontrollers and implement the methods to manage the list.  The next thing would be to establish some kind of  relationship between this structure of view controllers and NSWindowController.  These enhancements are enough to make NSViewController a key player in the current Cocoa controller archtitecture. </p>
<h3>Taking the Plunge</h3>
<p>The modifications to NSViewController that I mentioned above are simple enough for developers to make on their own.  But there are certain caveats that come up in the implementation details that are directly related to Cocoa.  These &#8220;gotchas&#8221; are not obvious until you start to test the design, but they also have to be dealt with before NSViewController can work effectively within the current controller architecture. </p>
<p>This is how I met <a href="http://jonathandann.wordpress.com/">Jonathan Dann</a> on the Cocoa-dev list.  Jonathan&#8217;s post was titled, <a href="http://www.cocoabuilder.com/archive/message/cocoa/2008/3/19/201743">&#8220;Correct use of NSViewController&#8221;</a>.  The title caught my attention because I had just finished my view controller design the week before.  I was not too surprised to see that his question had to do with implementing the exact design I&#8217;ve described in this post.  A few others chimed in with their solutions and it was very clear to me that this design is very obvious and that the issues in it were not unique to my implementation.  </p>
<p>Jonathan and I continued our discussion off-list and decided that we would write about the experience we had with NSViewController.  In the next post, he and I will describe the issues we came across when we tried to incorporate NSViewController into the Cocoa architecture and also provide our subclasses of NSViewController and NSWindowController as an example of how it might be accomplished.  </p>
<h4>To be continued&#8230;</h4>
<h3>Resources</h3>
<p><a href="http://developer.apple.com/documentation/Cocoa/Conceptual/Documents/Documents.html">Introduction to Document-Based Applications Overview</a></p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Reference/NSViewController_Class/Introduction/Introduction.html">NSViewController Class Reference</a></p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWindowController_Class/Reference/Reference.html">NSWindowController Class Reference</a></p>
<p>NSViewController documentation bug report &#8211; rdar://problem/5794739</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/04/09/nsviewcontroller-the-new-c-in-mvc-pt-1-of-3/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Sparkle And Spin</title>
		<link>http://katidev.com/blog/2008/03/25/sparkle-and-spin/</link>
		<comments>http://katidev.com/blog/2008/03/25/sparkle-and-spin/#comments</comments>
		<pubDate>Tue, 25 Mar 2008 13:01:13 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Graphic Design]]></category>
		<category><![CDATA[HIstory]]></category>
		<category><![CDATA[Research]]></category>
		<category><![CDATA[PaulRand]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=94</guid>
		<description><![CDATA[I found this 1993 video of Steve Jobs being interviewed about Paul Rand over on Paul Robinson&#8216;s site. It means so much to me when I see/read/hear someone that I admire admiring someone else that I admire. Towards the end of the interview, Jobs is asked what his favorite Paul Rand work is. His answer [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/paul-rand.jpg" border="0" alt="paul_rand.jpg" width="299" height="400" /></div>
<p>I found this 1993 video of Steve Jobs being interviewed about <a href="http://en.wikipedia.org/wiki/Paul_Rand">Paul Rand</a> over on <a href="http://kupuk.com/2008/03/18/jobs-on-paul-rand/">Paul Robinson</a>&#8216;s site. It means so much to me when I see/read/hear someone that I admire admiring someone else that I admire.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="wmode" value="transparent" /><param name="src" value="http://www.youtube.com/v/xb8idEf-Iak&amp;hl=en" /><embed type="application/x-shockwave-flash" width="425" height="355" src="http://www.youtube.com/v/xb8idEf-Iak&amp;hl=en" wmode="transparent"></embed></object></p>
<p>Towards the end of the interview, Jobs is asked what his favorite Paul Rand work is.  His answer is also my favorite – an offshoot of his famous IBM logo.  It combines the wit and playfulness of his children&#8217;s illustrations with the discipline and craftsmanship of his corporate logos.  Rand&#8217;s personality shines in this image:</p>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/eye-bee-m.jpg" border="0" alt="eye-bee-m.jpg" width="435" height="163" /></div>
<p>Here are some of the children&#8217;s illustrations that I lifted from this <a href="p://www.logoblog.org/wordpress/tribute-to-a-legend-paul-rand/">post</a>.  &#8220;Sparkle and Spin&#8221; is the title of one of the children&#8217;s books he created with his wife, Ann.</p>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/paul-rand-design-work-2.jpg" border="0" alt="paul-rand-design-work-2.jpg" width="440" height="625" /></div>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/paul-rand-design-work-1.jpg" border="0" alt="paul-rand-design-work-1.jpg" width="440" height="435" /></div>
<p>And some of the corporate logos we all know too well&#8230;</p>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/paulrandlogos.jpg" border="0" alt="PaulRandLogos.jpg" width="450" height="953" /></div>
<p>There&#8217;s an <a href="http://www.designobserver.com/archives/030468.html">article</a> on Design Observer with a funny story about how the Enron logo got its green after Paul Rand&#8217;s death in 1997.  The middle prong of the E was originally yellow.  The article describes all the fanfare and celebration that surrounded the unveiling of Enron&#8217;s new corporate identity but&#8230;</p>
<blockquote><p>Within hours, the world would laugh it off the stage. Houston faxed the logo to Enron&#8217;s offices in Europe. But in transmission the middle, yellow prong disappeared, leaving the new design meant to celebrate Enron&#8217;s triumphant ascension looking more like an electric plug. Worse, to the Italians it resembled an obscene hand gesture, one that meant about the same thing as shooting a middle finger at an American. The European executives roared with laughter: now they had a new way to win Italian customers.</p>
<p>Back in Houston, dismay grew: the yellow prong also vanished when run through the copying machine. Somehow, Enron had spent millions of dollars on a new business logo without bothering to check if it worked in business. Soon the hallway signs went down, the new cards and letterheads were shredded. With no fanfare, another logo was introduced, replacing the yellow prong with a green one.</p>
<p>The symbol meant to carry Enron into the next millennium hadn&#8217;t lasted a week.</p></blockquote>
<p>I would love to hear Rand&#8217;s comments on this teeny graphic design mishap.</p>
<p>One last treat.  The design company, <a href="http://imaginaryforces.com/company">Imaginary Forces</a>, did a great job animating Paul Rand&#8217;s work.  The animations are inter-cut with clips of Paul Rand speaking about design.  They&#8217;ve really captured his spirit with these animations.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="wmode" value="transparent" /><param name="src" value="http://www.youtube.com/v/uK-lr_QeI_g&amp;hl=en" /><embed type="application/x-shockwave-flash" width="425" height="355" src="http://www.youtube.com/v/uK-lr_QeI_g&amp;hl=en" wmode="transparent"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/03/25/sparkle-and-spin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NSView and Autresizing.  Yes, Again.</title>
		<link>http://katidev.com/blog/2008/03/20/nsview-and-autresizing-yes-again/</link>
		<comments>http://katidev.com/blog/2008/03/20/nsview-and-autresizing-yes-again/#comments</comments>
		<pubDate>Thu, 20 Mar 2008 12:51:20 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Layout]]></category>
		<category><![CDATA[NSView]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=86</guid>
		<description><![CDATA[The first post I made on this blog had to do with NSView&#8217;s autoresizing behavior being unreliable. As a Cocoa UI developer, this is a real problem that I just have to deal with. But, that&#8217;s not the worst thing about autoresizing in NSView. The worst thing about autoresizing in NSView is that setting an [...]]]></description>
			<content:encoded><![CDATA[<p>The first post I made on this blog had to do with NSView&#8217;s autoresizing behavior being unreliable.  As a Cocoa UI developer, this is a real problem that I just have to deal with.  But, that&#8217;s not the worst thing about autoresizing in NSView.  The worst thing about autoresizing in NSView is that setting an autoresizing mask requires that your view controller or window controller explicitly set the size and position of the view within its superview before it can set the autoresizing mask.  And whenever the view hierarchy changes, lets say that you need your layout to accommodate a new sibling view at some level of the hierarchy, you have to recalculate everyone&#8217;s frame and reset everyone&#8217;s mask at that level. Icky, dirty code.</p>
<p>I can see that Cocoa&#8217;s getting more sophisticated with how it approaches layout.  We can use &#8220;layout managers&#8221; with CALayers that have this great <a href="http://developer.apple.com/documentation/GraphicsImaging/Reference/CAConstraintLayoutManager_class/Introduction/Introduction.html">&#8220;constraints&#8221; system</a>.  From the docs:</p>
<blockquote><p>Constraint-based layout allows you to describe the position and size of a layer by specifying <strong>relationships</strong> between a layer and its sibling layers or its superlayer</p></blockquote>
<p>Relationships.  That makes more sense.  I want my views to have relationships to each other and I want the views or some layout manager to have the responsibility of maintaining those relationships when the view hierarchy changes, not the controller classes. That&#8217;s not what view controllers and window controllers are for.</p>
<p>So I wonder why all this great layout development for layers and not views?  Since layers aren&#8217;t in the responder chain, they&#8217;re not a viable view substitute and I can&#8217;t imagine that CALayer will ever become an NSResponder because of its relationship to another framework that we can&#8217;t talk about.  Maybe NSView is on its way out?  There are slight hints that some changes are underway, but even if that&#8217;s the case, I can&#8217;t imagine that it&#8217;ll happen any time soon.  NSView does a lot.  So, how about an NSViewLayoutManager class in the mean time?  Or new options for autoresizing masks? Yay! We Love View!</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="wmode" value="transparent" /><param name="src" value="http://www.youtube.com/v/X0AcrL6vHE8&amp;hl=en" /><embed type="application/x-shockwave-flash" width="425" height="355" src="http://www.youtube.com/v/X0AcrL6vHE8&amp;hl=en" wmode="transparent"></embed></object></p>
<p>I filed a bug report requesting a layout manager class for NSView:  Bug ID# 5809928.</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/03/20/nsview-and-autresizing-yes-again/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>The Next Device</title>
		<link>http://katidev.com/blog/2008/03/14/the-next-device/</link>
		<comments>http://katidev.com/blog/2008/03/14/the-next-device/#comments</comments>
		<pubDate>Fri, 14 Mar 2008 17:36:48 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Devices]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=79</guid>
		<description><![CDATA[The iPhone and its SDK inspire our imaginations. But maybe the thing in our imaginations is not this device, but the next device. There seems to be a general mood of frustration among developers stemming from the restrictions Apple is placing on third-party iPhone applications. As John Gruber points out today in his post, One [...]]]></description>
			<content:encoded><![CDATA[<p>The iPhone and its SDK inspire our imaginations.  But maybe the thing in our imaginations is not this device, but the next device.  There seems to be a general mood of frustration among developers stemming from the restrictions Apple is placing on third-party iPhone applications.  As John Gruber points out today in his post, <a href="http://daringfireball.net/2008/03/one_app_at_a_time">One App at a Time</a>, the restrictions aren&#8217;t unreasonable considering the hardware.  So maybe the angst and frustration we feel is coming from the fact that we have the tools in our hands and we finally have a real sense for this new platform and the possibilities are so clear to us but we have the wrong device.   Maybe the thing that we&#8217;re all hungry for is not the iPhone, but something else.  Something that&#8217;s a little less of a phone and not quite a laptop.  When you read though the CocoaTouch documentation, do your imaginings end with a phone? </p>
<p>It&#8217;s important for us to be patient with Apple and with ourselves right now.  This is something totally new and we need to take small steps to make the transition a smooth one.  As developers, we have to completely re-conceptualize our idea of how an application should behave and how to engage users without a keyboard or mouse.  We&#8217;ve been using the same model for software design since windowed GUIs were first introduced in the 80&#8242;s.  We don&#8217;t know any different and we shouldn&#8217;t underestimate the challenges we&#8217;ll inevitably encounter.  I can&#8217;t blame Apple for being so protective of their new platform.  We have a lot to learn and so do they.  Small steps, patience, a little bit of trust and compromise from both sides is going to be key to their and our success in this new endeavor.  </p>
<p>But it&#8217;s hard to be patient when we&#8217;re all feeling so passionate.  I look at this beautiful device and I read the documentation of its SDK and it makes me feel restless.  I know that this is much more than a phone.  But for now, all it is is a phone.  It&#8217;s the iPhone.  It&#8217;s not the next device.  That will come next and there will be another after that.  In the mean time, we have plenty to explore and have fun with.  If you think about it, they&#8217;re giving us a lot.  We&#8217;ll find out their next move soon enough. </p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/03/14/the-next-device/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Welcome, Designers</title>
		<link>http://katidev.com/blog/2008/03/10/welcome-designers/</link>
		<comments>http://katidev.com/blog/2008/03/10/welcome-designers/#comments</comments>
		<pubDate>Mon, 10 Mar 2008 18:51:34 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Layout]]></category>
		<category><![CDATA[Style]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[NSCell]]></category>
		<category><![CDATA[NSView]]></category>
		<category><![CDATA[sytle]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=74</guid>
		<description><![CDATA[My head has been reeling all weekend after watching the iPhone SDK presentation. The excitement I felt the first time I saw an iPhone has returned full-force after it was crushed by Steve Jobs during last year&#8217;s WWDC keynote address. I still think he owes all of us an apology for trying to pass off [...]]]></description>
			<content:encoded><![CDATA[<p>My head has been reeling all weekend after watching the iPhone SDK presentation.  The excitement I felt the first time I saw an iPhone has returned full-force after it was crushed by Steve Jobs during last year&#8217;s WWDC keynote address.  I still think he owes all of us an apology for trying to pass off Ajax techniques as an SDK like we&#8217;re stupid.  Anyway, I&#8217;m super happy and optimistic about all the new technology we get to play with and like many others, I can&#8217;t help but think about the future. There&#8217;s one thing in particular that I can&#8217;t get off my mind.</p>
<p>There are going to be lots of new Cocoa developers and many of them will come from the field of design, not software development.  Some will have never programmed before in their life.  This happened with HTML and CSS when the web became popular.  It&#8217;s going to happen in the world of iPhone development and Mac desktop application development will naturally follow.  </p>
<p>This influx of new developers means that the usability of the Cocoa&#8217;s APIs are going to be put to the test like never before.  Bugs like NSView&#8217;s autoresizing <a href="http://katidev.com/blog/?p=5">not working as advertised</a> or the fact that the methods to <a href="http://katidev.com/blog/?p=36">customize</a> the drag and drop highlights of an NSTableView are private and not legally accessible to developers are not going to sit well with this new generation of Mac devs, who will demand control over every aspect of their visual design. </p>
<p>It should be possible for the Cocoa engineers to give developers complete control over the visual properties and interactive behaviors of their classes.  I don&#8217;t mean in that convoluted creating a custom cell way, it should be <em>easy</em> — HTML and CSS easy (in fact, why don&#8217;t we use style sheets?). If there are points where this is technically impossible, it&#8217;s a design flaw of the framework and should be fixed. If it means writing a new NSTableView, so be it.</p>
<h3>Sorry, you&#8217;re screwed</h3>
<p>I keep thinking of an <a href="http://www.w3.org/Style/LieBos2e/history/">article</a> I read about the history of CSS and this part in particular: </p>
<blockquote><p>Meanwhile, writers of Web pages were complaining that they didn&#8217;t have enough influence over how their pages looked. One of the first questions from an author new to the Web was how to change fonts and colors of elements. HTML at that time did not provide this functionality &#8211; and rightfully so. This excerpt from a message sent to the www-talk mailing list early in 1994, gives a sense of the tensions between authors and implementors:</p>
<blockquote><p>In fact, it has been a constant source of delight for me over the past year to get to continually tell hordes (literally) of people who want to &#8212; strap yourselves in, here it comes &#8212; control what their documents look like in ways that would be trivial in TeX, Microsoft Word, and every other common text processing environment: &#8220;Sorry, you&#8217;re screwed.&#8221;</p></blockquote>
<p>The author of the message was Marc Andreessen, one of the programmers behind NCSA Mosaic. He later became a co-founder of Netscape and by then his views &#8211; if they ever were his views &#8211; on formatting had changed. </p></blockquote>
<p>I doubt that any Cocoa engineer has such a flippant attitude towards designers.  After all, this is OS X — the best looking operating system on the market.  I just hope that they will take these types of issues into more serious consideration when mapping out their priorities.   Sure, advertising &#8220;New Table Views!&#8221; in Cocoa isn&#8217;t as sexy a feature as Core Animation, but it&#8217;ll make everyone&#8217;s life easier in the long run.    Imagine this question popping up on the Cocoa-dev list:  &#8220;How do I customize the background color of a column in an NSTableView&#8221;.  Now think of the answer&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/03/10/welcome-designers/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>The Knowledge Navigator</title>
		<link>http://katidev.com/blog/2008/03/10/the-knowledge-navigator/</link>
		<comments>http://katidev.com/blog/2008/03/10/the-knowledge-navigator/#comments</comments>
		<pubDate>Mon, 10 Mar 2008 13:38:21 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Devices]]></category>
		<category><![CDATA[HIstory]]></category>
		<category><![CDATA[Research]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[knowledgenavigator]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=73</guid>
		<description><![CDATA[Features from this 1987 video that have been realized: Touch interface (iPhone) Voice commands (Speakable items) Animated views (Core Animation) Video conferencing (iChat) Looking at documents in a video conference (iChat Theater) Someone needs to implement the bow-tied digital butler.]]></description>
			<content:encoded><![CDATA[<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="wmode" value="transparent" /><param name="src" value="http://www.youtube.com/v/HGYFEI6uLy0" /><embed type="application/x-shockwave-flash" width="425" height="355" src="http://www.youtube.com/v/HGYFEI6uLy0" wmode="transparent"></embed></object></p>
<p>Features from this 1987 video that have been realized:</p>
<ul>
<li><strong>Touch interface</strong> (iPhone)</li>
<li><strong>Voice commands</strong> (Speakable items)</li>
<li><strong>Animated views</strong> (Core Animation)</li>
<li><strong>Video conferencing</strong> (iChat)</li>
<li><strong>Looking at documents in a video conference</strong> (iChat Theater)</li>
</ul>
<p>Someone needs to implement the bow-tied digital butler.</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/03/10/the-knowledge-navigator/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Creating a Custom Control with NSView</title>
		<link>http://katidev.com/blog/2008/03/07/how-to-create-a-custom-control-with-nsview/</link>
		<comments>http://katidev.com/blog/2008/03/07/how-to-create-a-custom-control-with-nsview/#comments</comments>
		<pubDate>Fri, 07 Mar 2008 01:09:04 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Research]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Widgets]]></category>
		<category><![CDATA[CIFilter]]></category>
		<category><![CDATA[CITwirlDistortion]]></category>
		<category><![CDATA[NSCell]]></category>
		<category><![CDATA[NSControl]]></category>
		<category><![CDATA[NSEvent]]></category>
		<category><![CDATA[NSOpenGLView]]></category>
		<category><![CDATA[NSResponder]]></category>
		<category><![CDATA[NSView]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=67</guid>
		<description><![CDATA[This tutorial is about implementing a custom control class. The goal is not to explain how to subclass NSControl or NSCell, but how to think more generally about controls, what they are and how to implement one with an NSView subclass. As with the last tutorial, it will be most useful if you download the [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/asimocontrol.jpg" alt="AsimoControl.jpg" border="0" width="450" height="362" /></div>
<p>This tutorial is about implementing a custom control class.  The goal is not to explain how to subclass NSControl or NSCell, but how to think more generally about controls, what they are and how to implement one with an NSView subclass.  As with the last tutorial, it will be most useful if you download the  <a href="http://katidev.com/blog/wp-content/uploads/2008/03/coreimagecontrol.zip" title="CoreImageControl.zip">example project</a> and follow along in the source code.  The comments will provide the implementation details. It&#8217;s also fun to give Asimo a pompadour. </p>
<p>The tutorial is based on a similar presentation that I gave at a New York City CocoaHeads meeting a few months ago.</p>
<h3>What is a Control?</h3>
<p>A control is an interface element that allows users to manipulate data in an application.  It&#8217;s main responsibilities are to draw itself, handle events, and communicate its values to other parts of the application.  </p>
<p>Cocoa&#8217;s AppKit framework comes with several controls out of the box:
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/picture-432.png" alt="Picture 43.png" border="0" width="319" height="188" /></div>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/picture-451.png" alt="Picture 45.png" border="0" width="319" height="178" /></div>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/picture-461.png" alt="Picture 46.png" border="0" width="319" height="188" /></div>
<p>All of the controls pictured above are decedents of Cocoa&#8217;s control class, <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSControl_Class/Reference/Reference.html">NSControl</a>.  As the documentation states, NSControl works closely with <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSCell_Class/Reference/NSCell.html">NSCell</a> to provide the basic features of a user interface object.  In most cases, you can use an AppKit control with no extra code.</p>
<h3>Why Make a Custom Control?</h3>
<p>With all of AppKit&#8217;s ready-made controls, why would you need to implement your own?  Here are two situations where the Cocoa control classes are not a good choice for your interface:</p>
<h4>1. None of the AppKit controls support the interaction model you want to implement</h4>
<p>Take Photoshop&#8217;s curves interface as an example.  This interface requires that the user is able to add control points to a bezier curve.  They must then be able to select the control points and drag them around to adjust the values of the curve.  If they click on the pencil button, the interface must switch to a mode that lets them draw the curve directly into the view.</p>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/pscurves1.jpg" alt="PSCurves.jpg" border="0" width="401" height="410" /></div>
<p>You&#8217;re not going to find an out of the box control that supports this interface in AppKit and NSControl may not be an appropriate place to start your custom implementation.  If you look at its API, it is clear that NSControl was designed to create the AppKit controls.  They all have fairly straightforward drawing, event handling and target/action needs.  Point-and-click.  If you were to use NSControl as a starting point for this interface, you would need to create a few custom cell classes that you would manage in your control&#8217;s custom cell.  At this point, you&#8217;re asking for a headache.  This interface is not what NSControl was designed for.  You&#8217;re going to spend more time fighting with the framework than implementing your ideas.</p>
<h4>2. You are drawing with OpenGL instead of Quartz</h4>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/picture-532.tiff" alt="Picture 53(2).tiff" border="0" width="450" height="360" /></div>
<p>All of the controls in the iTunes Cover Flow interface are drawn with OpenGL textures.  That includes the buttons, scrollbar and slider.  These are absolutely not NSControls, which can only draw in a Quartz graphics context.  If you want users to interact with your NSOpenGL view, you&#8217;re going to have to start from scratch with your controls.  Don&#8217;t let this scare you away from using OpenGL views for your interface.  They&#8217;re fast fast fast and if your app is displaying lots and lots of images, especially in a full screen situation with animation, they&#8217;re the way to go.  </p>
<p>Leopard&#8217;s LayerKit (Core Animation Layers) technology advertises mixed Quartz and OpenGL drawing, but I just have a hard time getting behind that idea.  More on this thought another time. </p>
<h3>Using NSView</h3>
<p>The subject of creating controls for an OpenGL view is a little out of the scope of this tutorial.  Again, I will come back to the issue of OpenGL views in the not-too-distant future.  </p>
<p>Working with NSView will let us touch on the very basics of what we need to make a control.  For really specialized, one-off interfaces that you can add to your window&#8217;s view hierarchy with no fuss, it makes a lot of sense to start here.  </p>
<p>As I mentioned before, there are three parts to a control.  Let&#8217;s make a to-do list for our class design.  Our view must be able to handle:</p>
<ol>
<li>Drawing</li>
<li>Event Handling</li>
<li>Communication with other parts of your app</li>
</ol>
<p>We&#8217;ll handle number one with NSView and number two with its superclass, NSResponder. For number three, we&#8217;ll use Cocoa bindings.</p>
<h3>What Are we Controlling?</h3>
<p>Before we subclass anything, we need to figure out what our control will control.  The example project contains a control for adjusting the values of a twirl distortion CoreImage filter.  To start the design, I looked at the documentation for <a href="http://developer.apple.com/documentation/periimeter/Reference/CoreImageFilterReference/Reference/reference.html%23//apple_ref/doc/filter/ci/CITwirlDistortionreference.html%23//apple_ref/doc/filter/ci/CITwirlDistortion">CITwirlDistortion</a>.  It lists the three attributes of the filter:  center postition, radius and angle.  I decided to create a circular design for controling all three attributes at once.  This seemed to be a nicer interface than providing three sliders.  Of course this design has some usability issues that will be obvious once you play around with it a bit, but it&#8217;s fun to experiment. </p>
<p>KDTwirlDistortionControl has this design:  </p>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/conroldiagram.jpg" alt="conrolDiagram.jpg" border="0" width="400" height="400" /></div>
<p>It&#8217;s basically a circle.  Users can drag on the main gray part of the circle to adjust its radius &#8211; this will change the radius attribute of the filter.  Dragging on the blue center point will change the position of the circle and the center position attribute of the filter.  Finally, dragging the small black circle around its perimeter will adjust the angle attribute of the filter. </p>
<p>We have an interface design.  Time for code.</p>
<h3>Defining the NSView subclass</h3>
<p>Our NSView subclass, KDTwirlDistortionControl, needs to keep track of three rectangles (pictured in the diagram) that it will use for drawing and hit detection.  These rectangles will also be used to calculate the adjustment values of the filter.  It declares the following ivars for the rectangles in the header file:</p>
<pre>
// drawing and hit detection
NSRect	mPositionControlRect;
NSRect	mAngleControlRect;
NSRect	mRadiusControlRect;
</pre>
<p>The control also contains 4 float values that can be bound to.  It does this by declaring the following ivars and their getters and setters:</p>
<pre>
// the values we bind to
float	mPositionX;	// a value between 0 and 1
float	mPositionY;	// a value between 0 and 1
float	mRadius;	// a value between 0 and 1
float	mAngle;		// a value between 0 and 6 radians
</pre>
<p>The getters and setters will always return normalized values for these ivars, which are calculated based on the positions and sizes of the rectangles in the view&#8217;s coordinate system.  Look in the code for more details about this part of the implementation.  </p>
<p>With the getters and setters in place, our control can communicate changes to these values to other classes with no more code.  We can check number three off of our to-do list.  Thanks Cocoa.</p>
<p>The last thing our control needs to manage is its state.  There are four possible states in our design:</p>
<ol>
<li>the control is inactive</li>
<li>the position rectangle is active</li>
<li>the radius rectangle is active</li>
<li>the angle rectangle is active</li>
</ol>
<p>We&#8217;ll use this information when we draw to give the user feedback about what they are adjusting.  We&#8217;ll also use it in our mouse drag handler so that we know which rectangle the user is adjusting.  To define the states of the control, create an enum type like this:</p>
<pre>
typedef enum
{
	kKDTwirlDistortionControlState_Inactive = 0,
	kKDTwirlDistortionControlState_AngleControlActive,
	kKDTwirlDistortionControlState_RadiusControlActive,
	kKDTwirlDistortionControlState_PositionControlActive

}KDTwirlDistortionControlState;
</pre>
<p>The view subclass declares an ivar that it will use to keep track of its current state:</p>
<pre>
// state
KDTwirlDistortionControlState		mControlState;
</pre>
<p>This is all the data we need for our control.  Now we will use NSView&#8217;s drawing and NSResponder&#8217;s event handler methods to implement the control.</p>
<h3>Drawing</h3>
<p>All we need to do to draw in an NSView subclass is to override the following NSView method:</p>
<pre>
- (void)drawRect:(NSRect)theRect;
</pre>
<p>To keep things organized, KDTwirlDistortionControl uses separate drawing methods for each part of the control.  It also creates a separate method to lay out the rectangles in the view.  It declares them as private methods in a category in the .m file:</p>
<pre>
@interface KDTwirlDistortionControl (Private)
- (void)drawPositionControlInContext:(CGContextRef)theContext;
- (void)drawAngleControlInContext:(CGContextRef)theContext;
- (void)drawRadiusControlInContext:(CGContextRef)theContext;
- (void)layoutControls;
@end
</pre>
<p>KDTwirlDistortionControl&#8217;s drawRect method looks like this:</p>
<pre>
- (void)drawRect:(NSRect)theRect
{
 CGContextRef aCGContextRef = [[NSGraphicsContext currentContext] graphicsPort];

 // draw the background
 CGContextSetRGBFillColor(aCGContextRef, 0.8, 0.8, 0.8, 1.0);
 CGRect aCGBackgroundRect = *((CGRect*)&#038;theRect);
 CGContextFillRect(aCGContextRef, aCGBackgroundRect);

 // layout the controls
 [self layoutControls];

 // draw the radius control rect
 [self drawRadiusControlInContext:aCGContextRef];

 // draw the position control rect
 [self drawPositionControlInContext:aCGContextRef];

 // draw the angle control rect
 [self drawAngleControlInContext:aCGContextRef];
}
</pre>
<p>If you look at the draw methods, you&#8217;ll notice that before they draw, they check the control state ivar to determine what color they will use to draw.  This gives the user feedback about the state of the control.  You might also notice that the control uses <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/index.html">Quartz2D</a> drawing commands.  Your control could just as well use Cocoa&#8217;s <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSBezierPath_Class/index.html">NSBezierPath</a> class to draw itself.  It&#8217;s good to be familiar with both drawing APIs.  There might be cases where you will notice the performance difference, so it&#8217;s nice to be able to fall back on Quartz for drawing straight into the view instead of using another object.  </p>
<p>We can check number 1 off of our to-do list.  The drawing is finished.  One more.</p>
<h3>Event Handling</h3>
<p>NSView is a subclass of <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html">NSResponder</a>.  The mechanism of the view hierarchy ensures that any view you add to it will be placed in the application&#8217;s &#8220;Responder Chain&#8221;.  The window will use the view hierarchy to deliver mouse events to the view that the user clicked on.  Keyboard events will be delivered through the responder chain.  It&#8217;s up to the view to implement the NSResponder event handlers that it is interested in.  </p>
<p>Most mouse events will be sent automatically to the appropriate view, but there is one step that a view must take to receive keyboard events. The keyboard events go to the &#8220;firstResponder&#8221; first and then travel through the responder chain.  If your view is to receive keyboard events it must accept first responder status.  To do this, the view needs to override the NSResponder method:</p>
<pre>
- (BOOL)acceptsFirstResponder
</pre>
<p>to return YES.  By default it returns NO.</p>
<p>Here&#8217;s a list of the most common mouse event handlers that a custom view can impelment:</p>
<pre>
- (void)mouseDown:(NSEvent*)theEvent;
- (void)mouseDragged:(NSEvent*)theEvent;
- (void)mouseUp:(NSEvent*)theEvent;
- (void)mouseMoved:(NSEvent*)theEvent;
- (void)mouseEntered:(NSEvent*)theEvent;
- (void)mouseExited:(NSEvent*)theEvent;
</pre>
<p>And common keyboard event handlers:</p>
<pre>
- (void)keyDown:(NSEvent*)theEvent;
- (void)keyUp:(NSEvent*)theEvent;
</pre>
<h4>NSEvent</h4>
<p>All of the event methods are going to pass us an <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/Reference/Reference.html">NSEvent</a> object that describes the event.  If it&#8217;s a mouse event, we can ask the event for the location of the mouse point using the NSEvent method:</p>
<pre>
- (NSPoint)locationInWindow;
</pre>
<p>This is going to give us the location of the mouse event in the window (duh).  We need to convert this point to a coordinate in our view&#8217;s internal coordinate system.  We&#8217;ll use NSView&#8217;s method</p>
<pre>
- (NSPoint)convertPoint:(NSPoint)thePoint fromView:(NSView*)theView;
</pre>
<p>If the event is a keyboard event, we can ask the NSEvent object for a string of characters associated with the event with the following methods:</p>
<pre>
- (NSString *)charactersIgnoringModifiers;
- (NSString *)characters;
</pre>
<p>Another useful bit of information we can get from NSEvent is whether or not a modifier key is associated with the event. Use the method</p>
<pre>
- (unsigned int)modifierFlags
</pre>
<p>to get the current modifier flags, which you can find documented in the list of NSEvent&#8217;s <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/Reference/Reference.html">constants</a>.  Check this against the modifier flag you are looking for.  This bit of code is checking for the command key:</p>
<pre>
if(([theEvent modifierFlags] &#038; NSCommandKeyMask) != 0)
{
 // do something special
}
</pre>
<p>Check the NSEvent documentation for more information on getting neat things like tablet data.  </p>
<p>Ok, Let&#8217;s get back to our control.</p>
<h4>Mouse Down</h4>
<p>When our view receives a mouse down, we want to check to see if the mouse point is inside any of the rectangles.  There&#8217;s a handy function we can use to check a point struct against a rectangle struct:</p>
<pre>
BOOL NSPointInRect(NSPoint thePoint, NSRect theRect);
</pre>
<p>KDTwirlDistortionControl&#8217;s mouse down method checks all of the rects against the mouse point.  If it determines that a click has occured inside any of its rects, it sets the control state to indicate which rectangle has been hit, tells itself to redraw and returns.  Here&#8217;s an excerpt:</p>
<pre>
// down on the position control rect
if(NSPointInRect(aMousePoint,mPositionControlRect))
{
 mControlState = kKDTwirlDistortionControlState_PositionControlActive;
 [self setNeedsDisplay:YES];
 return;
}
</pre>
<p>If none of the rectangles have been hit, the view centers the position rectangle around the mouse point.  This lets user click the background to set the position &#8211; hint: this feature comes in handy if you happen to drag it to an unusable position, like I said there are problems in this design ; )  </p>
<h4>Mouse Dragged</h4>
<p>This might be the most important method our class implements.  The mouse drag is going to change the values of our active rectangle.  It&#8217;s also going to call the setter methods of our control&#8217;s float values, which will automatically trigger notification of a value change to any class that is bound to the control.</p>
<p>The first thing the mouse dragged handler does is check the control state to determine which rectangle the user is adjusting.  It will then perform the calculations it needs to make adjustments to both the rectangle and the associated filter value.  It sets the value, tells itself to redraw and returns.  Here&#8217;s an excerpt:</p>
<pre>
// dragging the position control rect
if(mControlState == kKDTwirlDistortionControlState_PositionControlActive)
{
 // center the rect around the mouse point
 float aNewXPosition = aMousePoint.x-mPositionControlRect.size.width*.5;
 float aNewYPosition = aMousePoint.y-mPositionControlRect.size.height*.5;
 mPositionControlRect.origin = NSMakePoint(aNewXPosition, aNewYPosition);

 [self setPositionX:aNewXPosition];
 [self setPositionY:aNewYPosition];
 [self setNeedsDisplay:YES];

 return;
}
</pre>
<h4>Mouse Up</h4>
<p>The mouse up simply sets the control state to be inactive and tells itself to redraw.
</pre>
<h4>Key Down and Key Up</h4>
<p>The key down event handler looks for arrow key presses.  When an arrow key is pressed, it adjusts the origin of the position rectangle a few points in the appropriate direction.  It also sets the current control state so that the position rectangle is active and redraws. Here's an excerpt from the method.  It uses a switch statement to find the arrow keys:</p>
<pre>
case NSUpArrowFunctionKey:
   mControlState = kKDTwirlDistortionControlState_PositionControlActive;
   mPositionControlRect.origin.y = mPositionControlRect.origin.y+5;
   [self setPositionY:mPositionControlRect.origin.y];
   [self setNeedsDisplay:YES];
break;
</pre>
<p>The key up method also checks for arrow keys.  If the event is from one of the arrow keys, it resets the control state to inactive and redraws.</p>
<p>Event handling was the last thing on our to-do list.  Scratch it off, we're done.  We have a control.</p>
<h3>Hi Asimo! Nice Hair-do!</h3>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/03/picture-21.png" alt="Picture 21.png" border="0" width="404" height="364" /></h3>
</div>
<p></p>
<p>The KDTwirlDistortionControl example is very specific to the kind of data it is controlling and it could be used with any Core Image filter that has the same attributes, despite its name.  </p>
<p>In a future post, I will explore ways to abstract the design a little more to make the control more useful in more situations.  This will be necessary for designing OpenGL controls and could be useful if you're using CALayers as the basis for a control.  I haven't had a chance to work with CALayers, but I notice that they're not descendants of NSResponder. Odd for such a view-like class. </p>
<h3>Resources</h3>
<p> <a href="http://katidev.com/blog/wp-content/uploads/2008/03/coreimagecontrol.zip" title="CoreImageControl.zip">The Example Project</a><br/><br />
<a href="http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/Introduction/chapter_1_section_1.html">Cocoa Event handling Guide</a><br/><br />
<a href="http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/chapter_2_section_6.html">The Responder Chain</a><br/><br />
<a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaDrawingGuide/index.html">Cocoa drawing guide</a><br/><br />
<a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_intro/chapter_1_section_1.html">Quartz2D Programming Guide</a><br/><br />
<a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaViewsGuide/WorkingWithAViewHierarchy/chapter_5_section_1.html">NSView - Working With the View Hierarchy</a><br/><br />
<a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/">Cocoa Bindings</a><br/><br />
More advanced bindings examples: mmalc's bindings <a href="http://homepage.mac.com/mmalc/CocoaExamples/controllers.html">examples</a>, look at graphics bindings</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/03/07/how-to-create-a-custom-control-with-nsview/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Bye Bye, IB2</title>
		<link>http://katidev.com/blog/2008/02/27/bye-bye-ib2/</link>
		<comments>http://katidev.com/blog/2008/02/27/bye-bye-ib2/#comments</comments>
		<pubDate>Wed, 27 Feb 2008 10:10:58 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[HIstory]]></category>
		<category><![CDATA[Research]]></category>
		<category><![CDATA[Widgets]]></category>
		<category><![CDATA[IB]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=47</guid>
		<description><![CDATA[I&#8217;m still using IB2 at work, but we&#8217;ll be making the move to Leopard over the next few months. I feel a slight pang of pre-nostalgia when I think about trading in Interface Builder 2 and its historical code base for its shiny new successor, Interface Builder 3. I know that IB3 is going to [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/02/ibicons.jpg" alt="IBIcons.jpg" border="0" width="450" height="172" /></div>
<p>I&#8217;m still using IB2 at work, but we&#8217;ll be making the move to Leopard over the next few months.  I feel a slight pang of pre-nostalgia when I think about trading in Interface Builder 2 and its historical code base for its shiny new successor, Interface Builder 3.  I know that IB3 is going to be a million times more usable and that it was past time for a real change in the world of IB, but those who know me know that I tend to pine for the old before embracing the new. I&#8217;ll pine now and get it over with. </p>
<p>I remember the exact moment when I realized how amazingly cool Interface Builder is. I was making a custom palette for some GUI classes, implementing the drawing and mouse event handling methods for when they would be running in IB.  While I was typing, it struck me that what I was doing was a little strange.  I was giving these classes a second, meta life only to be invoked by Interface Builder.  All of the views and controls in Cocoa have this second IB life.  When we drop them into a window, they draw preview versions of themselves and sometimes even respond to our mouse and key events (if we poke around in just the right spots).  Interface Builder takes over from there.  It guides us as we drag the views around, adjust their sizes and much more.  Wow, what a clever and useful application.  Who thought of this?  They&#8217;re a genius.</p>
<h3>Jean-Marie Hullot and his Interface Builder</h3>
<p></p>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/02/965797a3-7bb9-4d8e-8207-2fd87bf7906e.jpg" alt="965797A3-7BB9-4D8E-8207-2FD87BF7906E.jpg" border="0" width="450"/></div>
<p><a href="http://en.wikipedia.org/wiki/Interface_Builder">Interface Builder</a> was developed by <a href="http://en.wikipedia.org/wiki/Jean-Marie_Hullot">Jean-Marie Hullot</a>, pictured above during his days at NeXT.  There is little written about him or his invention on the internet except that Hullot wrote the original version in some Lispy language and that it was originally called &#8216;SOS Interface&#8217;.  Steve Jobs loved it, kidnapped Hullot and Tim Berners-Lee used it to make the first web browser, <a href="http://en.wikipedia.org/wiki/WorldWideWeb">WorldWideWeb</a>.  Now we all use Interface Builder.</p>
<p>While I was scouring the net for information about Hullot, I came across a PDF excerpt from the book <a href="http://www.amazon.com/How-Web-was-Born-Story/dp/0192862073">&#8220;How the Web was Born: The Story of the World Wide Web&#8221;</a> by James Gillies and Robert Cailliau.  There is a short section about Hullot and Interface Builder, titled &#8220;Monsieur Hullot&#8217;s holiday&#8217;.  This is my favorite bit (emphasis is mine):</p>
<blockquote><p>Hullot was using a Macintosh, and like many developers, he rapidly found that although the Mac&#8217;s GUI might have been brilliant, it was a pig of a machine to write applications on.  &#8216;When the Macintosh was invented,&#8217; he explains, &#8216;suddenly, compared to what you had to do before, you had to add at least 60 or 70 percent of your time to make the user interface.&#8217;  Before the Macintosh, the interface was pretty basic-you would just type a line of text and the computer would respond with successive lines scrolling up the screen-but that meant that programmers didn&#8217;t have to worry about it.  <strong>All the windows and menus that came with the Mac were great for the people who used the end applications, but for the people who had to write them they were a nightmare.</strong>  Each time they wanted a menu or a window in their application, they had to program it in from scratch.  Hullot&#8217;s big idea was to turn the problem into a simple question of drawing lines on the screen.  He made a palette of objects for things like menu items and windows.  Then to build the outline of an application you would simply take objects from the palette and draw lines between them.  So, for example, you could pick up a menu object, and then by drawing lines from the other objects like &#8216;Open&#8217; or &#8216;Print&#8217;, you would put those functions in the menu.</p>
<p>Hullot called his invention Interface Builder.  It was a powerful tool that, like Smalltalk, put the power of objects at the developer&#8217;s disposal.</p></blockquote>
<p>Kind of amazing, huh?  These days, it&#8217;s easy to take things like windows and menus for granted.  They come free with our development tools.  On top of that, the responder chain and target/action mechanisms make it simple to dynamically link buttons and menu items to actions.  If your app has a simple interface, there&#8217;s very little code that needs to be written for UI development.  Even if your interface is complex, much of the burden is lifted by Hullot&#8217;s technology.  Thank you, Jean-Marie.</p>
<p>The book goes on to describe Hullot and Jobs&#8217; first meeting and the rest is history.  In case you haven&#8217;t seen it, here&#8217;s a video of Steve Jobs presenting some applications on NeXTSTEP.  He shows Interface Builder at 23:40.  Funny how little has changed until now.  </p>
<p><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/j02b8Fuz73A&#038;rel=1"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/j02b8Fuz73A&#038;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object></p>
<p>So, I&#8217;ll say goodbye to Inteface Builder 2 and end my pining now.  Bye bye, IB2.  Your interface was really strange and awkward but you were really cool and useful.  I&#8217;ll miss palettes (not really, actually).</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/02/27/bye-bye-ib2/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Styling an NSTableView (DTTAH)</title>
		<link>http://katidev.com/blog/2008/02/22/styling-an-nstableview-dttah/</link>
		<comments>http://katidev.com/blog/2008/02/22/styling-an-nstableview-dttah/#comments</comments>
		<pubDate>Fri, 22 Feb 2008 14:49:30 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Style]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Widgets]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[NSCell]]></category>
		<category><![CDATA[NSTableView]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=36</guid>
		<description><![CDATA[NSTableView is a great class for displaying long lists of data, but its default implementation is kind of boring looking. This post will show you how give your table views extra sex appeal. I&#8217;m categorizing it as a &#8220;don&#8217;t try this at home&#8221; tutorial because it sometimes involves overriding private NSTableView methods. Be warned that [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSTableView_Class/Reference/Reference.html">NSTableView</a> is a great class for displaying long lists of data, but its default implementation is kind of boring looking.  This post will show you how give your table views extra sex appeal.  I&#8217;m categorizing it as a &#8220;don&#8217;t try this at home&#8221; tutorial because it sometimes involves overriding private NSTableView methods.  <strong>Be warned that Apple can and will change the private framework code without notice and that some of the techniques used in this tutorial may no longer work.</strong>  The tutorial and the example project are meant to be educational and exploratory.  They&#8217;re not necessarily &#8220;right&#8221;, so use them wisely.</p>
<p>If anyone out there knows how to get comparable results without using NSTableView private methods, please please leave a comment.</p>
<h3>The Example Project</h3>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/02/drag.jpg" alt="drag.jpg" border="0" width="409" height="479" /></div>
<p>The CustomTableView Xcode project can be dowloaded <a href="http://katidev.com/blog/wp-content/uploads/2008/02/customtableview.zip" title="CustomTableView.zip">here</a>.</p>
<p>If you&#8217;re new to Cocoa or subclassing NSTableView, the tutorial will be most useful if you download the project and follow along in the source code.  The comments will help explain implementation details.  The project has 3 classes:</p>
<ul>
<li><strong>MyController</strong> (the application&#8217;s main controller and the table&#8217;s delegate and data source)</li>
<li><strong>MyTableView</strong> (the NSTableView subclass)</li>
<li><strong>MyCell</strong> (the NSCell subclass)</li>
</ul>
<p>It also adds <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_4_section_1.html">categories</a> to NSColor and NSBezierPath for custom alternating background colors and rounded rectangles.  </p>
<p>In the sample project, customizations are made to the following visual properties of the table:</p>
<ul>
<strong>
<li>Alternating background colors </li>
<li>Selection highlight </li>
<li>Drag image </li>
<li>Drop highlight on rows</li>
<li>Drop highlight between rows</strong></li>
</ul>
<p>The table also uses an NSCell subclass to draw an icon and two rows of text. Let&#8217;s start with NSCell.</p>
<h3>NSCell</h3>
<p>Table views use the <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ControlCell/Concepts/AboutControlsCells.html%23//apple_ref/doc/uid/20000731">NSCell</a> class to draw content in their rows.  The first step to customizing the look of your table is to create an NSCell subclass and override the method </p>
<pre>-(void)drawInteriorWithFrame:(NSRect)theFrame inView:(NSView *)theView</pre>
<p>In the example project, the MyCell class divides the NSRect passed in the frame argument into three smaller rectangles that it uses to position the image, title and subtitle.  The image and text are then drawn into those rectangles using <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSImage_Class/Reference/Reference.html">NSImage</a> and <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSString_AppKitAdditions/Reference/Reference.html">NSString</a>&#8216;s respective -(void)drawInRect methods.  </p>
<p>After you make your subclass, you need to let the table view know about it.  You can set the cell for the columns of the table using NSTableColumn&#8217;s method</p>
<pre>-(void)setDataCell:(NSCell *)theCell</pre>
<p>In the example project, the MyController class sets the data cell for the table&#8217;s column with the following lines of code in awakeFromNib:</p>
<pre>
MyCell * aCustomCell = [[[MyCell alloc] init] autorelease];
[[oMyTableView tableColumnWithIdentifier:@"theTableColumn"] setDataCell:aCustomCell];
</pre>
<h3>NSTableView</h3>
<p>After you have an NSCell subclass, you may also want to customize some of NSTableView&#8217;s visual properties.  You can set the background color, row height, whether or not the table should draw horizontal or vertical lines and the color of the lines using the NSTableView inspector palette in Interface Builder.  Other adjustments take a little bit of code.</p>
<h4>Alternating Background Colors</h4>
<p>If you choose to display alternating background colors, the default colors are light blue and white.  A simple way to customize the alternating background color scheme in your application is to add a <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_4_section_1.html">category</a> to NSColor that overrides the method</p>
<pre>+(NSArray *)controlAlternatingRowBackgroundColors </pre>
<p>In your implementation of this method, return an NSArray containing the two colors you want your tables to use.</p>
<h4>Selection Highlight</h4>
<p>In the example project, MyTableView draws a rounded rectangle in the selected rows.  If you want to draw your own selection highlight, override the following method in your NSTableView subclass:</p>
<pre>-(void)highlightSelectionInClipRect:(NSRect)theClipRect</pre>
<p>This method is asking you to draw the highlights for the rows that are currently selected within the &#8220;clip rect&#8221;, or the area of the table that is visible.  One way to do this is to:</p>
<ol>
<li>Use NSTableView&#8217;s method
<pre>-(NSRange)rowsInRect:(NSRect)theRect;</pre>
<p>to get the range of row indexes that are currently visible in the clip rect.</li>
<li>Use NSTableView&#8217;s method
<pre>-(NSIndexSet)selectedRowIndexes;</pre>
<p> to get a list of all of the selected rows in the table.</li>
<li>Go through the list of visible row indexes.  If an index is included in the list of selected indexes, get the NSRect for that row with the NSTableView method:
<pre>-(NSRect)rectOfRow:(int)theRowIndex;</pre>
</li>
<li>Draw your custom highlight style inside this rectangle.</li>
</ol>
<p>If your application is running on Tiger or any previous OS and you only override this method, you&#8217;ll notice that the table still draws its default highlight on top of your drawing.  The second thing you must do to draw a custom selection highlight in this case is override the private method:</p>
<pre>-(id)_highlightColorForCell:(NSCell *)cell
{
    return nil;
}</pre>
<p>Returning nil in this method will &#8220;stop&#8221; the table view from drawing the default highlight rectangle (weird, huh?).</p>
<p>If you only want to change the highlight selection color instead of drawing a custom highlight, you can simply override the method</p>
<pre>-(id)_highlightColorForCell:(NSCell *)cell</pre>
<p>to return the color of your choice.  </p>
<h4>Drag Image</h4>
<p>If your NSTableView subclass supports dragging, you can create a custom drag image by overriding the method</p>
<pre>- (NSImage *)dragImageForRowsWithIndexes:(NSIndexSet *)theRowIndexes
			    tableColumns:(NSArray *)theTableColumns
				   event:(NSEvent *)theEvent
				  offset:(NSPointPointer)theOffset</pre>
<p>In this method make an NSImage, draw what you want into the image and return it.  You can get your NSTableView subclass to give you an NSImage with the content of the cell drawn inside by calling super&#8217;s implementation of the method.  </p>
<p>In the example project, MyTableView composites the NSImage returned by super onto another NSImage with a rounded rectangle drawn inside.  The new NSImage is returned as the drag image. </p>
<h4>Drop Highlights</h4>
<p>Drop highlights in NSTableView are notoriously fugly and they are not &#8220;legally&#8221; customizable.  In the example project, MyTableView overrides some private methods to draw a black rounded rectangle to highlight drags over rows and a line with a small accent circle (like NSOutlineView) to highlight drags between rows.  </p>
<p>For Tiger and earlier, there are two private methods that your NSTableView subclass can override to draw custom drop highlights on and between rows:</p>
<pre>
-(void)_drawDropHighlightOnRow:(int)theRowIndex;
-(void)_drawDropHighlightBetweenUpperRow:(int)theUpperRowIndex
			     andLowerRow:(int)theLowerRowIndex
				atOffset:(float)theOffset; </pre>
<p>In both cases, use the NSTableView method
<pre>-(NSRect)rectOfRow:(int)theRowIndex</pre>
<p> to retrieve the rectangle of the row you want to highlight.</p>
<p>In Leopard, things get a little more complicated.  There are several private methods that NSTableView might use to draw the drop highlight between rows.  Through trial and error, I found that overriding the following method does the trick:</p>
<pre>- (void)_drawDropHighlightBetweenUpperRow:(int)theUpperRowIndex
			      andLowerRow:(int)theLowerRowIndex
				    onRow:(int)theRow
				 atOffset:(float)theOffset</pre>
<p>A new NSTableView feature in Leopard is the drop highlight color.  Like the rest of the drop highlight visual properties, it is only customizable by overriding a private method.  If you don&#8217;t override this method, the default implementation will draw a light blue background over the row that is the current drop target. If light blue isn&#8217;t your thing, you can override</p>
<pre>+(id)_dropHighlightBackgroundColor;</pre>
<p>to return the color of your choice.  If you want your table to have the same highlights running in Leopard as it does in Tiger, return [NSColor clearColor].</p>
<h3>Do Not Try This At Home!!!</h3>
<p>I hope that this post will help you build a beuatiful table view that your users will love to look at, but once again, please please be careful when using private NSTableView methods for selection and drop highlights.  While it&#8217;s fun and educational to explore the AppKit framework, you absolutely should not override private methods in your shipping app.  I&#8217;ve filed an enhancement radar in the hopes that Apple will make these methods public: </p>
<p>rdar://problem/5758731</p>
<p>If anyone knows of other techniques that are more legal, please share them in the comments. </p>
<h3>Resources</h3>
<p>The source code in the <a href="http://katidev.com/blog/wp-content/uploads/2008/02/customtableview.zip" title="CustomTableView.zip">CustomTableView</a> example project has detailed comments that should help answer any questions you may have about implementing the techniques described in this post.</p>
<p>Other useful projects with alternate approaches to customizing the visual elements of a table:</p>
<ul>
<li>Mark Alldritt&#8217;s <a href="http://www.latenightsw.com/blog/?p=45">SourceListView</a></li>
<li>Cocoa Pirate&#8217;s <a href="http://indiehig.com/wiki/Source_Lists">Source List implementation</a></a>
<li>Apple&#8217;s <a href="http://developer.apple.com/samplecode/ImageBackground/listing4.html">ImageAndTextCell</a> example code</li>
</ul>
<p>If you are new to Cocoa drawing, I&#8217;d suggest reading the <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_intro/chapter_1_section_1.html">Quartz 2D Programming Guide</a> as well the <a href="http://cocoadevcentral.com/d/intro_to_quartz_two/">Learn Quartz</a> tutorials at <a href="http://cocoadevcentral.com/">CocoaDevCentral</a>.</p>
<p>For more information on NSTableView, start with the <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/TableView/TableView.html">Introduction to Table Views Programming Guide</a>.  There is an NSTableView <a href="http://www.cocoadev.com/index.pl?NSTableViewTutorial">tutorial</a> on the CocoaDev wiki as well as <a href="http://cocoadevcentral.com/articles/000063.php">one</a> at CocoaDevCentral.  These will help with the less superficial parts of programming an NSTableView (like how to really implement drag and drop and data sources).</p>
<p>For more information on NSCell, read the <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ControlCell/Concepts/AboutControlsCells.html%23//apple_ref/doc/uid/20000731">Control and Cell Programming Topics for Cocoa</a>.</p>
<p>If NSTableView isn&#8217;t exactly what you&#8217;re looking for and you&#8217;re targeting OS 10.5+, you might want to look into the new Cocoa class, <a href="http://developer.apple.com/documentation/Cocoa/Reference/NSCollectionView_Class/Introduction/Introduction.html">NSCollectionView</a>.</p>
<p>Also, If you&#8217;re targeting OS 10.5+, take a look at the new <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSTableView_Class/Reference/Reference.html%23//apple_ref/c/tdef/NSTableViewSelectionHighlightStyle">source list selection style</a> for NSTableView.</p>
<p>Finally, <a href="http://www.codethecode.com/projects/class-dump/">class-dump</a> lets you look at stuff you shouldn&#8217;t be looking at.</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/02/22/styling-an-nstableview-dttah/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Computer Administrative Debris</title>
		<link>http://katidev.com/blog/2008/02/15/computer-administrative-debris/</link>
		<comments>http://katidev.com/blog/2008/02/15/computer-administrative-debris/#comments</comments>
		<pubDate>Fri, 15 Feb 2008 13:58:34 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Research]]></category>
		<category><![CDATA[Widgets]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=20</guid>
		<description><![CDATA[Edward Tufte recently posted a video analysis of the iPhone interface on his website. If you haven&#8217;t seen it yet, I highly recommend taking a look. My favorite part is when he offhandedly states, &#8220;The white frames are too thick and should be in gray and only a single pixel thick,&#8221; as he&#8217;s scrolling the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.amazon.com/Visual-Display-Quantitative-Information-2nd/dp/0961392142/ref=pd_bbs_sr_1?ie=UTF8&amp;s=books&amp;qid=1202980461&amp;sr=8-1">Edward Tufte</a> recently posted a video analysis of the iPhone interface on his website.  If you haven&#8217;t seen it yet, I highly recommend <a href="http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=00036T">taking a look</a>.  </p>
<p>My favorite part is when he offhandedly states, &#8220;The white frames are too thick and should be in gray and only a single pixel thick,&#8221; as he&#8217;s scrolling the thumbnail browser.  I imagine Edward Tufte working as a design supervisor at Apple, watching over people&#8217;s shoulders, scolding young designers for not displaying enough information.  I&#8217;m sure he would run a tight ship where every pixel would have a meaningful purpose.</p>
<p>Actually, I lied, my real favorite part is a term Tufte uses frequently in the video, &#8220;computer administrative debris&#8221;, usually as he&#8217;s noting the lack of it on the iPhone&#8217;s UI.  That&#8217;s a great way to describe all the crap on our interfaces, the important stuff that enables users to perform complex tasks in a tiny two-dimensional workspace. Things like windows, menus, tabs, check boxes, toolbars, scroll bars, etc. </p>
<p>One of the challenges of interface design is to reduce computer administrative debris while maintaining a high standard of usability.  Of course, the difficulty of this challenge is related to the complexity of the application.  Pro apps are going to have more computer administrative debris than consumer apps simply because they have more features.  The iPhone and Apple TV-type applications have it easy in this sense, because their users are mostly browsing content.  The developers don&#8217;t often need to provide them with a context to adjust or create the content.  Most desktop apps, on the other hand, are all about providing that context.  Still, there are some things that desktop application developers can do to trim the amount of debris on their interfaces. </p>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/02/acorn.jpg" alt="Acorn.jpg" border="0" width="450" height="281" /></div>
<div style="text-align:center;">
<p><img src="http://katidev.com/blog/wp-content/uploads/2008/02/pshop.jpg" alt="PShop.jpg" border="0" width="450" height="281" /></div>
<p>Top: <a href="http://www.flyingmeat.com/">Flying Meat</a>&#8216;s consumer image editor, <a href="http://flyingmeat.com/acorn/">Acorn</a><br /> <br />
Bottom: <a href="http://www.adobe.com/">Adobe&#8217;s</a> pro image editor, <a href="http://www.adobe.com/products/photoshop/index.html">Photoshop</a></p>
<h3>Features</h3>
<p>As Jeff Atwood points out in his post, <a href="http://www.codinghorror.com/blog/archives/001048.html">Every User Lies</a>, users don&#8217;t actually use most of the features of the applications they buy.  They want to, and might even tell you that they do, but they usually don&#8217;t.  Jeff&#8217;s advice is good.  Observe. Figure out what is critical for your users to get their work done and go from there.  Also, don&#8217;t be afraid to say no to feature requests if you&#8217;re in the position to do so.  Keeping the feature set streamlined is a simple way to reduce the amount of computer administrative debris your users will have to wade through to get a simple task done.  </p>
<p>A good example of this is <a href="http://flyingmeat.com/">Flying Meat</a>&#8216;s consumer image editor, <a href="http://flyingmeat.com/acorn/">Acorn</a>.  Pictured above are both Acorn and its comparable pro application, <a href="http://www.adobe.com/products/photoshop/index.html">Adobe Photoshop</a>.  They&#8217;re both shown at their initial states, just after I opened an image.  Acorn is clearly more approachable because there is less debris on the screen.  Its feature set is not nearly as rich a Photoshop&#8217;s, but Acorn&#8217;s developer, <a href="http://gusmueller.com/blog/">Gus Mueller</a>, knew that his users were not going to use all of those features anyway.  He made a succinct feature list and because of that he is able to minimize computer administrative debris on his interface.  </p>
<h3>Organization</h3>
<p>Pro and prosumer apps, like Apple&#8217;s <a href="http://www.apple.com/aperture">Aperture</a>,  are in a constant state of struggle with computer administrative debris.  They are the applications with the most features, but with some organization, even they manage improve their computer administrative debris to content ratio over time.</p>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/02/aperture2.jpg" alt="Aperture2.jpg" border="0" width="450" height="275" /></div>
<div style="text-align:center;">
<p><img src="http://katidev.com/blog/wp-content/uploads/2008/02/aperture1.jpg" alt="Aperture1.jpg" border="0" width="450" height="274" /></div>
<p>Top:  <a href="http://www.apple.com/aperture">Aperture 2</a><br />
Bottom: Aperture 1.5.6</p>
<p>Pictured above are Apple&#8217;s <a href="http://www.apple.com/aperture">Aperture 2</a>, which came out this week, and its predecessor,  Aperture 1.5.6.  The Aperture 2 team did some re-organizing for this release.  The most notable organizational improvement is the shifting of the Adjustments and Metadata widgets over to the source list area.  The arrangement that we see in 1.5.6 is no longer possible.  Users will never see the source list, adjustments, and metadata debris at the same time.  The Aperture team understood that the users will never need to access more than one of these features at a time, so they made the decision to consolidate. Using tabs as an organizational tool, they reduced debris.  </p>
<h3>Directness</h3>
<p>Tufte makes an important observation about the iPhone when he talks about computer administrative debris.  For many features, the iPhone uses the content as the interface and users interact with it directly rather than through interface widgets.  Again, the fact that users of the iPhone are mostly browsing makes it easier to do this, but there&#8217;s something to be learned from their model.</p>
<p>A simple example of letting the users interact directly with content to trim debris is drag and drop, something we&#8217;re all familiar with by now.  By letting users either pick up items from one container and drag them into another or reorder items in a single container, we reduce the need for buttons or action menus.  Less debris.  Apple&#8217;s <a href="http://www.apple.com/ilife/imovie/">iMovie 08</a> boasts, &#8220;Drag-and-drop moviemaking&#8221;.  In fact, Apple&#8217;s entire <a href="http://www.apple.com/ilife/">iLife</a> and <a href="http://www.apple.com/iwork">iWork</a> repertoire is full of examples of interacting directly with content instead of through menus, buttons or text fields, greatly reducing the amount of computer administrative debris on their interfaces.</p>
<div style="text-align:center;"><img src="http://katidev.com/blog/wp-content/uploads/2008/02/keynote.jpg" alt="Keynote.jpg" border="0" width="450" height="293" /></div>
<p>Apple&#8217;s <a href="http://www.apple.com/iwork/keynote">Keynote</a></p>
<p><a href="http://www.apple.com/iwork/keynote/">Keynote</a>, pictured above,  has a very clean interface with little debris because users interact directly with the interface representations of the content.  Can your interaction model be more direct?  When could users interact directly with content instead of through text fields or action menus?  This is a tough one and often requires some creative coding, but its worth it.</p>
<h3>Free of Debris (not really)</h3>
<p>It&#8217;s not possible to completely eliminate widgets from a desktop application, but we have the tools we need to reduce the amount of unsightly and distracting computer administrative debris on our interface designs.  With the introduction of <a href="http://cocoadex.com/2008/02/nsevent-modifications-swipe-ro.html">gesture events</a> and <a href="http://developer.apple.com/documentation/GraphicsImaging/Reference/CALayer_class/Introduction/Introduction.html">CALayers</a> in Cocoa, the Mac developer&#8217;s toolbox is becoming more sophisticated and we have lots of room to be creative and innovative.  </p>
<p>Users are also becoming more sophisticated and their expectations are evolving.  It won&#8217;t be long until the mere sight of a pop up menu will be enough to make them quit an application and never open it again.  Trust that they can handle an unorthodox interaction model.  They might be liars, as Jeff Atwood points out, but they learn quick if they&#8217;re presented with a well thought out and executed design.  The iPhone interface proves that and as Tufte notes over and over in his video, there is often no computer administrative debris in sight.</p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/02/15/computer-administrative-debris/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
		<item>
		<title>Why I Say &#8216;NO&#8217; to Autoresizing</title>
		<link>http://katidev.com/blog/2008/02/12/why-i-say-no-to-autoresizing/</link>
		<comments>http://katidev.com/blog/2008/02/12/why-i-say-no-to-autoresizing/#comments</comments>
		<pubDate>Tue, 12 Feb 2008 13:11:52 +0000</pubDate>
		<dc:creator>Cathy</dc:creator>
				<category><![CDATA[Layout]]></category>
		<category><![CDATA[Autoresizing]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[NSView]]></category>

		<guid isPermaLink="false">http://katidev.com/blog/?p=5</guid>
		<description><![CDATA[Cocoa does so much so well, but like any framework, it has its quirks. It can be difficult to decide when it&#8217;s time to put your foot down and say &#8220;No. Thanks. I&#8217;ll take over from here.&#8221; For me, one of those moments came when I had finally had it with NSView&#8217;s autoresizing behavior. Like [...]]]></description>
			<content:encoded><![CDATA[<p>Cocoa does so much so well, but like any framework, it has its quirks.  It can be difficult to decide when it&#8217;s time to put your foot down and say &#8220;No. Thanks. I&#8217;ll take over from here.&#8221;  For me, one of those moments came when I had finally had it with NSView&#8217;s autoresizing behavior.  Like a self-doubting girlfriend, convinced that I must be doing something wrong, I let it go for a long time.  Eventually I had to face the truth.  My views were not where I expected them to be and it wasn&#8217;t because my expectations were unreasonable.  Autoresizing just wasn&#8217;t working.</p>
<h3>Autoresizing</h3>
<p>NSView has an &#8220;autoresizing&#8221; mechanism.  It&#8217;s a layout tool that lets the developer configure how a subview will resize and reposition itself when its superview&#8217;s frame rectangle changes.  For example, let&#8217;s say that we have a window with a button in the bottom right corner and we want it to stay there when the user resizes the window.
<p style="text-align: center"><img src="http://katidev.com/blog/wp-content/uploads/2008/02/picture-2.png" height="289" width="399" border="0" alt="Picture 2.png" /></p>
<p>The button is a subview of the window&#8217;s &#8220;content view&#8221;, so we&#8217;ll configure the button&#8217;s autoresizing behavior.  The button is fine being positioned at the bottom of the window, but we want it to move along the x-axis as the window&#8217;s width changes.  To do this, we&#8217;ll use the autoresizing mask constant <strong>NSViewMinXMargin</strong>. According to the <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaViewsGuide/WorkingWithAViewHierarchy/chapter_5_section_6.html">docs</a>,<br />
<blockquote>If set, the view&#8217;s left edge is repositioned proportionally to the change in the superview&#8217;s width. Otherwise, the view&#8217;s left edge remains in the same position relative to the superview&#8217;s left edge.</p></blockquote>
<p>If we want to configure the view programmatically, we&#8217;ll first let the superview know that it needs to trigger the autoresizing, then we&#8217;ll configure the subview&#8217;s autoresizing mask.</p>
<pre>
[oWindowContentView setAutoresizesSubviews:YES];
[oButton setAutoresizingMask: NSViewMinXMargin];
</pre>
<p>Or we can use the nifty visual editor in Interface Builder to set &#8220;springs and struts&#8221;:
<p style="text-align: center"><img src="http://katidev.com/blog/wp-content/uploads/2008/02/picture-41.png" height="494" width="390" border="0" alt="Picture 41.png" /></p>
<p></p>
<h3>The Problem</h3>
<p>The example above works great, but it doesn&#8217;t take much to get autoreszing to misbehave. I&#8217;m going to make a view and give it one subview.  I want the outer view to adjust its width and height with the window and the inner view to stay its original size, but to remain centered in its superview. To achieve this layout, I&#8217;ll use the following code:</p>
<pre>
// turn on autoresizing
[oWindowContentView setAutoresizesSubviews:YES];
[oOuterView setAutoresizesSubviews:YES];

// set autoresizing mask
[oOuterView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[oInnerView setAutoresizingMask:(NSViewMinXMargin | NSViewMinYMargin |
		 		 NSViewMaxXMargin | NSViewMaxYMargin)];
</pre>
<p>This is what happens:<br />
<object height="355" width="425"><param value="http://www.youtube.com/v/Bb0qXo_kWFI&amp;rel=1" name="movie"></param><param value="transparent" name="wmode"></param><embed src="http://www.youtube.com/v/Bb0qXo_kWFI&amp;rel=1" height="355" width="425" wmode="transparent" type="application/x-shockwave-flash"></embed></object></p>
<p>Everything is fine for a little while, the inner view stays centered. But at one point, after the outer view&#8217;s height becomes smaller than the inner view&#8217;s height and I expand the window back out, the inner view&#8217;s Y margin is lost and its original setting is broken. The inner view is stuck to the top of the outer view&#8217;s frame.</p>
<p>This is a very simple example.  In real life, view hierarchies are much more complex.  We have views inside split views inside other split views next to other views containing buttons, text fields and sliders and they all have to know what to do when the user resizes the window or drags a divider.  Behavioral quirks like the one in the video become harder and harder to live with as our interfaces grow.</p>
<h3>Taking Control</h3>
<p>I sometimes think that designing a dynamic layout is a bit like choreographing a dance routine.  What should I do when the dancers just can&#8217;t get it right, no matter how many times we&#8217;ve been over it? I could instruct them to just stay still when they forget what to do and to jump back in when they&#8217;re ready.  I could hire someone to stand on the sidelines during the performance, reminding them of their next move when they look lost. Another option is to just replace them with dancers who listen and remember.</p>
<p>I spoke with an Apple engineer at the last WWDC about the problems I was having with autoresizing. I can still see the look on his face when he realized what I was talking about.  It was as if he was thinking, &#8220;Oh yeahhhhh <em>THAT</em>&#8230;&#8221;  Yeah. <em>That</em>.  I asked if the NSView people had fixed <em>That</em> in Leopard.  He confirmed that no, they had not and suggested that I set a minimum size for the superviews to prevent the situation.  He also asked me what I thought they could do to anticipate resizing past certain sizes.</p>
<p>The idea of setting a minimum size for the superview is the common fix for this.  You see it most often with split views, where superviews are very likely to be sized smaller than their subviews.  It seems to be an accepted practice to restrict split view divider dragging past some arbitrary point when there is no real usability or layout-related reason to do so.  The behavior I see time and again is that just before the split view divider reaches the subview&#8217;s amnesia-inducing point, it&#8217;ll automatically jump closed and when it&#8217;s dragged back out, it&#8217;ll jump back.  This is bad interaction design.  It&#8217;s a work-around that has nothing to do with what is good or bad in terms of &#8220;user experience&#8221;.  In fact, it creates a bad user experience.  Things shouldn&#8217;t be jumping around under the mouse, especially in the middle of a split view divider drag when the user is expecting some measure of control over the layout.</p>
<p>So what could NSView do to prevent this behavior?  It could cache margins or at least the proportions we&#8217;re trying to preserve. That way, it will always have the correct value to use for its calculations. Seems kind of easy to me.</p>
<p>For the time being, we&#8217;re stuck with this behavior and we have to either set minimum sizes for superviews, pollute our application code with controllers to monitor and adjust the layout, or subclass NSView and all of its subclasses and define our own resizing behavior.  None of these situations is ideal.   The first results in less dynamic layouts and less enjoyable interactions, but it&#8217;s simple.  The second is just dirty and the last is a pretty big undertaking considering how many subclasses NSView has.  I&#8217;m sure there are other creative solutions we could consider.  You can probably guess what I do from the title of this post.  I subclass and bypass the whole autoresizing mechanism.  The only time I turn on autoresizing is for the view that&#8217;s at the very top of the hierarchy so that it resizes with the window.  My solution has its own issues, but they&#8217;re pretty easy to deal with and I get an amazing dance troupe that can handle even my most avant-garde choreographic efforts.</p>
<p>A zip file containing the Xcode project I use in the video can be downloaded <a href="http://katidev.com/blog/wp-content/uploads/2008/02/resizingtestapp1.zip" title="ResizingTestApp.zip">here</a>.</p>
<h3>UPDATE (02-16-08)</h3>
<p>I was just thinking about what the bug really is.  I don&#8217;t think that it&#8217;s an issue of simply cacheing a value anymore.  There&#8217;s something else going on.  </p>
<p>If we look at NSViewMinYMargin.  Again from the docs:</p>
<blockquote><p>If set and the superview is not flipped, the view&#8217;s top edge is repositioned proportionally to the change in the superview&#8217;s height.</p></blockquote>
<p>I think it has to do with the <em>change</em> calculation.  You&#8217;ll notice in the video, it didn&#8217;t happen each time i shrank the superview.  I think that when you&#8217;re resizing fast enough, it&#8217;s possible that the notification of the frame change is a little behind and when it goes to make the calculation, the change is 0.  That doesn&#8217;t explain why it stays &#8220;stuck&#8221;, but it is possible to &#8220;unstick&#8221; it if you keep resizing over and over.  When it unsticks, the proportions are off, so that it&#8217;s no longer centered, so there&#8217;s something weird there, too.  Very very weird. </p>
]]></content:encoded>
			<wfw:commentRss>http://katidev.com/blog/2008/02/12/why-i-say-no-to-autoresizing/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.534 seconds -->
<!-- Cached page served by WP-Cache -->

