<?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>Red Sweater Blog &#187; Free Code</title>
	<atom:link href="http://www.red-sweater.com/blog/category/articles/programming/free-code/feed" rel="self" type="application/rss+xml" />
	<link>http://www.red-sweater.com/blog</link>
	<description>Mac &#38; Technology Writings by Daniel Jalkut</description>
	<lastBuildDate>Mon, 15 Mar 2010 14:58:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Hexy Little Thing</title>
		<link>http://www.red-sweater.com/blog/279/hexy-little-thing</link>
		<comments>http://www.red-sweater.com/blog/279/hexy-little-thing#comments</comments>
		<pubDate>Wed, 14 Feb 2007 18:59:08 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Free Code]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/279/hexy-little-thing</guid>
		<description><![CDATA[I&#8217;m working on an application now that uses a custom document format. Since my code manipulates this format and spits it back out to disk, I find myself frequently examining the resulting documents using Peter Ammon&#8217;s excellent Hex Fiend to examine the resulting files, and make sure the content is still format-compliant.

But while I&#8217;m debugging [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working on an application now that uses a custom document format. Since my code manipulates this format and spits it back out to disk, I find myself frequently examining the resulting documents using Peter Ammon&#8217;s excellent <a href="http://ridiculousfish.com/hexfiend/">Hex Fiend</a> to examine the resulting files, and make sure the content is still format-compliant.</p>
<p>
But while I&#8217;m debugging the code that actually does the manipulation, I find myself stuck doing stupid stuff like:
</p>
<p><pre>
(gdb) p/x ((char*)[imageData bytes])[14]
$1 = 0x28
</pre>
</p>
<p>
Ugh! That&#8217;s no way to win the software wars. It occurred to me today that what I really want is something like Hex Fiend built right into the debugger. Why shouldn&#8217;t I be able to hex-dump my NSData objects directly from the console? It turns out I wasn&#8217;t alone in this wish, because Dan Wood <a href="http://gigliwood.com/weblog/Cocoa/Better_description_.html">recently published</a> a category on NSData that allows just that.
</p>
<p>
By simply compiling the NSData category into a given application, you give NSData&#8217;s debugging description superpowers. For instance, here&#8217;s me at the gdb console, examining the contents of the favicon.ico response I just received from NSURLConnection:</p>
<pre style="font-size:1em;">
<code>
(gdb) po imageData
NSData 350 bytes:
00 00 01 00 01 00 10 10 10 00 00 00 00 00 28 01 | ..............(.
00 00 16 00 00 00 28 00 00 00 10 00 00 00 20 00 | ......(....... .
00 00 01 00 04 00 00 00 00 00 C0 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF | ................
FF 00 00 00 FF 00 00 00 EF 00 00 00 DE 00 00 00 | ................
CE 00 00 00 BD 00 00 00 AD 00 00 00 9C 00 00 00 | ................
8C 00 00 00 7B 00 00 00 52 00 00 00 42 00 00 00 | ....{...R...B...
29 00 00 00 10 00 00 00 00 00 00 00 00 00 11 11 | )...............
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 | ................
11 11 11 11 11 11 13 31 11 11 12 55 21 11 1B B1 | .......1...U!...
13 D8 7F FF FB 31 1B B1 6F D4 FB 65 9F D2 1B DB | ....1..o..e....
FB 21 84 11 15 F5 1B FF FC 41 12 78 8D D1 1B B1 | .!.......A.x....
3C C1 2D FF FB 51 1B B1 1A D1 5F 71 11 11 1B C5 | < .-..Q...._q....
BF 81 1C C7 58 61 1A FF C6 11 12 BF FF 81 12 54 | ....Xa.........T
11 11 11 13 52 11 11 11 11 11 11 11 11 11 11 11 | ....R...........
11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00       | ..............
Current language:  auto; currently objective-c
(gdb)
</code>
</code></pre>
</p>
<p>
Dan&#8217;s code is pretty much perfect as-is, but I couldn&#8217;t resist tacking on some additional features. His category hardcodes the dumped data to 1024 bytes, but in my case there are times when I&#8217;m interested in seeing more. I added two category methods to the mix:
</p>
<p><pre style="font-size:1em;">
<code>
// startOffset may be negative, indicating offset from end of data
- (NSString *)descriptionFromOffset:(int)startOffset;
- (NSString *)descriptionFromOffset:(int)startOffset
				limitingToByteCount:(unsigned int)maxBytes;
</code>
</pre>
</p>
<p>
Now I can peek at a specific subrange, or expand the default limit of 1024 bytes. I can even peek at the end of a chunk of data, by specifying a negative offset:
</p>
<p><pre style="font-size:1em;">
<code>
(gdb) po [mDocumentData descriptionFromOffset:-11]
NSData 109 bytes (showing bytes 98 through 109):
02 43 41 54 41 54 4F 4E 49 43 00                | .CATATONIC.
(gdb)
</code>
</pre>
</p>
<p>
Wow! This is a pretty huge addition to my debugging and development toolbelt. Many thanks to Dan Wood for providing the ready-made code to speed up my implementation.
</p>
<p>
<a href="http://www.red-sweater.com/blog/downloads/NSData+RSHexDump.zip">NSData+RSHexDump</a> is freely available to you, under an MIT license.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/279/hexy-little-thing/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>A Moveable Beast</title>
		<link>http://www.red-sweater.com/blog/274/a-moveable-beast</link>
		<comments>http://www.red-sweater.com/blog/274/a-moveable-beast#comments</comments>
		<pubDate>Fri, 09 Feb 2007 17:31:52 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Free Code]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/274/a-moveable-beast</guid>
		<description><![CDATA[Implementing reordering table views is something of a first-time obstacle in Cocoa. The basic gist is you take responsibility for dragging from and to the table view in question, and thereby implicitly support drag reordering. This technique is demonstrated by Apple&#8217;s DragNDropOutlineView example.

Faced with the desire to implement such functionality in a bindings-oriented application (FlexTime), [...]]]></description>
			<content:encoded><![CDATA[<p>Implementing reordering table views is something of a first-time obstacle in Cocoa. The basic gist is you take responsibility for dragging <em>from</em> and <em>to</em> the table view in question, and thereby implicitly support drag reordering. This technique is demonstrated by Apple&#8217;s <a href="file://localhost/Developer/Examples/AppKit/DragNDropOutlineView/">DragNDropOutlineView</a> example.</p>
<p>
Faced with the desire to implement such functionality in a bindings-oriented application (<a href="http://www.red-sweater.com/flextime/">FlexTime</a>), I realized it would make sense to have the dragging handled by a the NSArrayController, which is already handling so much of the behavior associated with the table view.
</p>
<p>
<a href="http://www.red-sweater.com/blog/downloads/RSRTVArrayController.zip">RSRTVArrayController</a> implements a subclass of NSArrayController whose responsibilities are extended to provide simple row reordering via Drag-and-Drop. The basic gist is:
</p>
<p><ol>
<li>Drop this one class into your project.</li>
<li>Drag the header file to Interface Builder</li>
<li>Set it as the custom class on an array controller instance</li>
<li>Connect the dataSource and delegate outlets from the table view to the controller.</li>
<li>Connect the oTableView outlet from the controller to the table view.</li>
</ol>
<p>
 Et voila!
</p>
<p>
You can also temporarily disable reordering by calling &#8220;setDraggingEnabled:&#8221; on the controller. I do this for instance in FlexTime while the routine is running so users can&#8217;t completely confuse my world.</p>
<p>
<strong>Update:</strong> <a href="http://centrix.ca/">Rick Fillion</a> pointed out a possible day-ruining bug in the code, which will only rear it&#8217;s head if you happen to be assigning all ownership of your model objects to the array controller. Since the &#8220;move&#8221; code accomplishes the move by removing and then inserting an object from the array, it turns out that once it&#8217;s removed, it&#8217;s deallocated if nothing else in your app is retaining it!  So the workaround is to be retain the object while moving it, and then release it. Thanks for reporting that, Rick. The downloadable class is now updated.
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/274/a-moveable-beast/feed</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>We Need a Hero</title>
		<link>http://www.red-sweater.com/blog/195/we-need-a-hero</link>
		<comments>http://www.red-sweater.com/blog/195/we-need-a-hero#comments</comments>
		<pubDate>Wed, 27 Sep 2006 14:59:12 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[AppleScript]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Free Code]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/195/we-need-a-hero</guid>
		<description><![CDATA[

You&#8217;re a good developer. You&#8217;ve tackled lots of tough problems they&#8217;ve thrown your way. You are respected by your peers. You&#8217;ve done a great job with your life! And then there&#8217;s that nagging in the back of your head. You can&#8217;t kill the guilt of that glaring omission &#8211; the horror of horrors. The place [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css"><!-- .caption { border-style:dashed; border-width:1px; border-color:#BBBBBB; margin-left:20px; padding:10px;}--></style>
<p>
You&#8217;re a good developer. You&#8217;ve tackled lots of tough problems they&#8217;ve thrown your way. You are respected by your peers. You&#8217;ve done a great job with your life! And then there&#8217;s that nagging in the back of your head. You can&#8217;t kill the guilt of that glaring omission &#8211; the horror of horrors. The place where your code just doesn&#8217;t stack up.
</p>
<p>
<strong>You&#8217;ve got sucky AppleScript support.<br />
</strong></p>
<p>
Don&#8217;t beat yourself up. Apple is to blame for this, and they should step up and start taking responsibility. Adding AppleScript support to an application, even with the pleasure/pain of Cocoa scripting, is as much of a rite of passage for developers as learning to write AppleScripts is for users. That is, it&#8217;s a nearly universally agreed upon royal pain in the ass. And that&#8217;s wrong.
</p>
<p>
Why is it so painful? With Cocoa Scripting it&#8217;s common to hear that adding support is almost as simple as <a href="http://www.red-sweater.com/blog/150/minimal-scriptability">flipping a switch</a>, and it sort of can be. But it&#8217;s also true that skydiving is as easy as finding something tall to jump off of. Now how do we go about ensuring a safe landing?
</p>
<p>
I talk to a lot of developers through mailing lists, IRC, and even live in person. I&#8217;ve never met one who was completely confident about adding scripting support to an app. Even the smartest Mac programmers I&#8217;ve ever met tend to confess that they &#8220;just tweaked things until they magically worked, then stopped touching it.&#8221;
</p>
<p>
This mirrors my own experience. So let me vent some things that I think are wrong with Apple&#8217;s handling of &#8220;the AppleScript situation.&#8221;
</p>
<ol>
<li><strong>Inadequate Documentation</strong>. The Cocoa Scripting Guide is <em>pretty frickin&#8217; good</em> but it falls short on some frustrating levels. The <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ScriptableCocoaApplications/SApps_design_apps/chapter_3_section_2.html#//apple_ref/doc/uid/TP40001978-BCIEIHEJ">step-by-step</a> is encouraging, but it fails to mention key points like &#8220;for some features, an sdef just totally won&#8217;t work, and you&#8217;ll want to resort to using old-fashioned script suites or even an &#8216;aete&#8217; resource.&#8221;
<p>
Worse are the misleading details about indexed array operators. I ran into this with FlexTime. I need the scripter to be able to manipulate the list of activities associated with a given document. My code-level name for these objects is &#8220;TimedEvent.&#8221; The documentation suggests that methods of this form should do the trick:</p>
<pre>
- (void)insertObject:(TimedEvent *)newEvent
		inTimedEventsAtIndex:(int)index
</pre>
</p>
<p>
But in practice, I had to google my way through blood, sweat and tears to discover that this form was required for scripting:</p>
<pre>
- (void) insertInTimedEvents:(TimedEvent*)newEvent
		atIndex:(int)index
</pre>
</p>
<p>
Ugh! Kill! Kill!
</p>
</li>
<li><strong>Buggy Examples</strong>. Like any good programmer, you&#8217;re looking to stand on the backs of giants. In the case of scripting, you&#8217;re going to want a good &#8220;scripting definition&#8221; file, consisting of all the standard Cocoa-supplied handlers, and any custom goodies you add on yourself. So that &#8220;standard handlers&#8221; stuff should be easy to copy and paste, right? If you look for such a starting point, you&#8217;ll find several options. And they all seem to be buggy. It&#8217;s not easy for me to advise a developer starting with AppleScript whether they should use <a href="http://developer.apple.com/samplecode/ScriptingDefinitions/listing1.html">Skeleton.sdef</a>, <a href="file://localhost/Developer/Examples/Scripting%20Definitions/NSCoreSuite.sdef">NSCoreSuite.sdef</a>, or some other less scientific approach. The documentation is equally vague:
<p><div class="caption">
If your application supports any of the commands, classes, or other scriptability information defined in the Standard and Text suites, as most do, you should copy the suite elements for those suites into your sdef from an existing sdef file, such as Sketch.sdef.
</div>
</p>
<p>
It doesn&#8217;t matter which path you take, you&#8217;ll end up banging your head bloody against the keyboard as you try to decipher endless, frustratingly nuanced bugs. Script results will come back with confusing chevron values instead of class names:
</p>
<div class="caption">
<pre>
&laquo;class &raquo; &laquo;constant ****all &raquo;
	of script item "Text Input - 2 Btns"
</pre>
</div>
<p>
Confusing console log messages will appear, complaining that methods like &#8220;scriptingAnyDescriptor&#8221; are not implemented in your objects. You&#8217;ll wonder aloud what the hell that method is for, and even ask around on mailing lists and search google, only to find the plaintive cries of other frustrated developers.
</p>
<p>
There should be no &#8220;hunt-and-gather&#8221; phase in adding Scripting support to an application. <strong>Apple should include a perfectly functioning standard sdef as part of the Xcode templates for all application targets.</strong> If they want good scripting support, they need to throw us a bone.
</p>
</li>
<li><strong>Spotty e-Mail Support</strong>. There&#8217;s a <a href="http://lists.apple.com/mailman/listinfo/applescript-implementors">mailing list</a> dedicated to allegedly solving the problems of frustrated scripting support implementors. The problem is, nobody from Apple reliably steps up to answer the most vexing questions posed there. Inevitably the tough questions either go unanswered, or are eventually acknowledged by <a href="http://www.cocoadev.com/index.pl?DustinVoss">Dustin Voss</a> or <a href="http://www.prefab.com/uibrowser/">Bill Cheeseman</a>. The two most reliable sources for AppleScript implementation support are non-Apple employees who usually have to painfully admit they only figured it out after hours of scientific experimentation. When Dustin or Bill doesn&#8217;t chime in, occasionally an Apple representative does, but it&#8217;s highly unpredictable, and more often than not silence reigns. This sucks!
<p>
OK, I know, it&#8217;s not their &#8220;job&#8221; at Apple to monitor and reply to issues on the free mailing lists. But maybe it should be. The fact is, if there was anybody on that list replying to questions with the accuracy and authority of somebody like Eric Schlegel on Carbon-Dev, then AppleScript support would be a lot better. We&#8217;re treading water, here!
</p>
<p>
Other groups at Apple also provide stellar support through their lists. <a href="http://lists.apple.com/mailman/listinfo/coreaudio-api">Core Audio</a> leaps to mind. <a href="http://lists.apple.com/mailman/listinfo/usb">USB</a>, <a href="http://lists.apple.com/mailman/listinfo/quartzcomposer-dev">Quartz Composer</a>, <a href="http://lists.apple.com/mailman/listinfo/cocoa-dev">Cocoa</a>,  and <a href="http://lists.apple.com/mailman/listinfo/macnetworkprog">Networking</a> also have real experts &#8211; the developers themselves &#8211; providing quick and friendly support to developers on a daily basis. Most of these groups in fact have 2 or more team members actively tackling problems on the lists. And when something is undocumented or broken, they admit it and we move on. I&#8217;m sure there are others. At Apple, helping developers is the <em>rule</em> rather than the exception, and I&#8217;m grateful for that. </p>
<p>
Thank you, Eric! Thank you Jeff Moore, Bill Stewart, Fernando Urbina, Barry Twycross, David Ferguson, Pierre-Olivier Latour, Chris Kane, Douglas Davidson, Ali Ozer, Becky Willrich, and Quinn! I&#8217;m sure there are dozens more that don&#8217;t spring to mind or whose lists I don&#8217;t read. You&#8217;re all heroes, and we appreciate it. Truly.
</p>
<p>
<strong>But we need a <em>Cocoa Scripting</em> hero.</strong>
</p>
</li>
</ol>
<h3>Contained By What?</h3>
</p>
<p>
One of the biggest hurdles in adding Cocoa Scripting support to an application seems to be coming to terms with AppleScript&#8217;s &#8220;containment hierarchy.&#8221; It requires that any scripted object be able to fully specify its location in the containment hierarchy. For instance, in MarsEdit this text paragraph I&#8217;m typing right now needs to know that it&#8217;s the:
</p>
<div class="caption">
	last paragraph of current text of post window &#8220;We Need a Hero&#8221; of application &#8220;MarsEdit&#8221;
</div>
<p>
See, that&#8217;s how AppleScript refers to things. And Cocoa Scripting exposes objects directly to AppleScript, so that scripters can manipulate them directly. Long story short, is your Cocoa objects need to know how to tell AppleScript where they live. The way this happens is by way of the &#8220;objectSpecifier&#8221; method, which most of your scriptable objects will end up needing to implement.
</p>
<p>
This was a big mental block to me, because I&#8217;m not used to &#8220;back-referencing&#8221; from my objects to their containers. Maybe it&#8217;s my application design naivet&eacute;, but I find it awkward that in FlexTime for instance, my &#8220;cue action&#8221; object should know that it&#8217;s owned by a particular activity in a particular document. This just seems clunky to me. But as far as I know we&#8217;re stuck with it.
</p>
<p>
But just because the object exposes the objectSpecifier method, doesn&#8217;t mean it has to <em>be in charge</em> of it. I&#8217;m more comfortable in general with the containing object being responsible for claiming and disavowing ownership of a given object. So I came up with a generic solution that works pretty well for me.
</p>
<p>
<a href="http://www.red-sweater.com/blog/downloads/RSContainableObject.zip">RSContainableObject</a> (Free, MIT License) is a generic NSObject subclass that can have its owning object and relevant key set on it. Then, when somebody asks it for its objectSpecifier, it uses that information to provide the required directions. The actual specification is accomplished by asking the containing object to reckon the object relative to itself, so the parent must itself respond to &#8220;objectSpecifier,&#8221; either because it&#8217;s also an RSContainableObject, or because it implements the method itself.
</p>
<p>
This approach works for me because I discovered that the vast majority of scriptable objects in my applications are in fact direct subclasses of NSObject. Those that are not, like my NSDocument subclass, inherit the objectSpecifier magic directly from Cocoa. So my typical set up is an NSDocument subclass that contains trees of various RSContainableObject subclasses, which all know how to reckon themselves recursively back up the chain in terms of their container.
</p>
<p>
These custom model objects end up with declarations that look something like this:
</p>
<div class="caption">
<pre>
@interface TimedEvent : RSContainableObject &lt;NSCopying&gt;
</pre>
</div>
<p>
Then when such a model object is set as a property or added as an element of a containing object, <em>the container</em> takes responsibility by setting the pertinent ownership terms on the object:
</p>
<div class="caption">
<pre>
// Associate the object with us
[newEvent setObjectContainer:self
			containedByKeyName:@"timedEvents"
			asToManyRelationship:YES];
</pre>
</div>
<p>
The above example is for a &#8220;to many&#8221; relationship, meaning it&#8217;s a member of a list of items. But the same event object could be associated as a property relationship with a similar type of pattern. Here I pretend there&#8217;s an attribute of this object called &#8220;best damn timer&#8221; with an associated Cocoa method of &#8220;bestDamnTimer&#8221;:
</p>
<div class="caption">
<pre>
// Disassociate from the old object
[mBestDamnTimer setObjectContainer:nil
		containedByKeyName:nil
		asToManyRelationship:NO];

// Retain &#038; Release
[mBestDamnTimer release];
mBestDamnTimer = [newTimer retain];

// Associate
[newTimer setObjectContainer:self
		containedByKeyName:@"bestDamnTimer"
		asToManyRelationship:NO];
</pre>
</div>
<p>
By factoring the messy &#8220;objectSpecifier&#8221; code into one place for a wide variety of use scenarios, I avoid having to engage too often in the (for me, at least) bug-prone ritual of writing that method from scratch.
</p>
<p>
You might observe that a problem with this approach is that objects can&#8217;t be owned by more than one object. That&#8217;s true, but that&#8217;s also a basic limitation of AppleScript. Objects have &#8220;one true specifier&#8221; even if there are multiple legal specifiers that lead to it. For instance &#8220;default timer of document 1&#8243; might resolve to the same object as &#8220;timer 3 of application &#8216;ClockThing&#8217;&#8221;, but the RSContainableObject relationship should only be between the application and the object. A given object at one time can have only one &#8220;canonical&#8221; object specifier, and that is the relationship that this class affords.
</p>
<p>
Hope this helps&#8230;. but we still need a hero!
</p>
<p>
<strong>Update:</strong> A couple readers have pointed out that I might as well link to some good resources for AppleScript debugging and design:
</p>
<p>
<a href="http://developer.apple.com/technotes/tn2002/tn2106.html">TN 2106 &#8211; Scripting Interface Guidelines</a>. This has a good discussion of the containment hierarchy, what it means for your application, and how it relates to the world-view of the scripter. Thanks, <a href="http://www.timestretch.com/site/home/">Erik Wrenholt</a>.
</p>
<p>
<a href="http://developer.apple.com/technotes/tn2004/tn2124.html">TN 2124 &#8211; Mac OS X Debugging Magic</a>. This talks about general techniques for debugging AppleEvents and also reminds us of the Cocoa Scripting debugging &#8220;defaults&#8221; setting NSScriptingDebugLogLevel. I always forget about that and maybe I wouldn&#8217;t be quite so tightly wound up about AppleScript if I remembered it! Thanks, <a href="http://www.toxicsoftware.com/">Jonathan Wight</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/195/we-need-a-hero/feed</wfw:commentRss>
		<slash:comments>60</slash:comments>
		</item>
		<item>
		<title>A Table View For The Ages</title>
		<link>http://www.red-sweater.com/blog/165/a-table-view-for-the-ages</link>
		<comments>http://www.red-sweater.com/blog/165/a-table-view-for-the-ages#comments</comments>
		<pubDate>Thu, 27 Jul 2006 04:35:51 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Free Code]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/165/a-table-view-for-the-ages</guid>
		<description><![CDATA[Cocoa contains an awesome but sort of half-baked infrastructure for &#8220;autosaving&#8221; UI configurations for the user. Many of the common UI elements, such as windows, table views, and toolbars possess the ability to write out their configuration to the app&#8217;s preferences so they can be automatically restored the next time the app is launched.

When this [...]]]></description>
			<content:encoded><![CDATA[<p>Cocoa contains an awesome but sort of half-baked infrastructure for &#8220;autosaving&#8221; UI configurations for the user. Many of the common UI elements, such as windows, table views, and toolbars possess the ability to write out their configuration to the app&#8217;s preferences so they can be automatically restored the next time the app is launched.</p>
<p>
When this works, it works. And it is, as I said, awesome. But for such a cool idea there is a great lack of consistency in its implementation. NSWindow lets you autosave the frame by setting a unique name under which it will be saved. The API is rather extensive:
</p>
<p><pre>
+ removeFrameUsingName:
&#8211; saveFrameUsingName:
&#8211; setFrameUsingName:
&#8211; setFrameUsingName:force:
&#8211; setFrameAutosaveName:
&#8211; frameAutosaveName
&#8211; setFrameFromString:
&#8211; stringWithSavedFrame
</pre>
</p>
<p>
Notice that there is no BOOL &#8220;autosavesFrame&#8221; method &#8211; it just figures if you set a name, you want it to be saved. This name can even be set from Interface Builder. The number of methods is a bit large for what seems like a simple operation, but what&#8217;s really nice is it exposes the &#8220;magic format&#8221; to  developers so we can override the default behavior or make different use of the autosave information.
</p>
<p>
For example, let&#8217;s say you wanted to implement a funky little &#8220;Expos&eacute;&#8221; feature for just your application, something that tiles all the windows so that they fit neatly into the available screen real estate. That&#8217;s fine, but you should be prepared to put all the windows back the way the user had them before. Using &#8220;stringWithSavedFrame,&#8221; this is trivial. Just iterate over your open windows and collect the screen position information in a format that <em>NSWindow itself</em> guarantees to be usable for resetting it.  It&#8217;s not like we couldn&#8217;t figure it out ourselves, but AppKit already figuerd it out! Thanks for sharing.
</p>
<p>
NSToolbar takes a different approach. Instead of allowing developers to participate in the complicated question of &#8220;naming&#8221; the autosaved information, it offers a simpler API, implying it will come up with a way of saving the information itself:
</p>
<p><pre>
&#8211; autosavesConfiguration
&#8211; setAutosavesConfiguration:
&#8211; configurationDictionary
&#8211; setConfigurationFromDictionary:
</pre>
</p>
<p>
This is a great compromise. We&#8217;ve lost the ability to influence naming conventions, but who cares? They still give us access to the magic format! So if we don&#8217;t like the way it&#8217;s handling autosave, we just turn it off and implement our own with the help of &#8220;configurationDictionary.&#8221;
</p>
<p>
But NSTableView, oh NSTableView. You had to go your own way:
</p>
<p><pre>
&#8211; autosaveName
&#8211; setAutosaveName:
&#8211; autosaveTableColumns
&#8211; setAutosaveTableColumns:
</pre>
</p>
<p>
NSTableView lets us alter the autosave name, but unlike NSWindow, merely setting the name doesn&#8217;t imply that the feature is active. We have to set that BOOL separately. Notice how NSToolbar&#8217;s technique uses the same number of methods, but provides a lot more flexibility. The worst part about NSTableView&#8217;s approach is it <em>hides the magic data</em> so we can&#8217;t even override the default mechanism.
</p>
<p>
If only NSTableView exposed its magic data!
</p>
<p>
I really wanted this functionality, because in developing <a href="http://www.red-sweater.com/flextime/">FlexTime</a>, I decided to offer a feature to &#8220;save window layout&#8221; to the document itself. The other autosaving mechanisms work well with this approach &#8211; just grab the magic data and archive it. NSTableView stymies me, though! Perhaps I could set an autosaveName, then do something to provoke it being saved, then look it up manually. Nah! It&#8217;s all too fragile.
</p>
<p>
<a href="http://www.red-sweater.com/blog/downloads/NSTableView+RSAutosaving.zip">NSTableView+RSAutosaving</a> is my solution. Yours too, under MIT License. It&#8217;s a category on NSTableView that adds the missing (IMHO) methods:
</p>
<p><pre>
- dictionaryForAutosavingLayout
- adjustLayoutForAutosavedDictionary:
</pre>
</p>
<p>
The &#8220;magic data&#8221; in this case consists of the widths of every column and their ordering in the table. There are a few subtle gotchas to doing this right, and I think I did it right. So you&#8217;ll be glad if you end up not writing it yourself.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/165/a-table-view-for-the-ages/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>What a Difference a Cell Makes</title>
		<link>http://www.red-sweater.com/blog/148/what-a-difference-a-cell-makes</link>
		<comments>http://www.red-sweater.com/blog/148/what-a-difference-a-cell-makes#comments</comments>
		<pubDate>Sun, 18 Jun 2006 00:43:42 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Free Code]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/148/what-a-difference-a-cell-makes</guid>
		<description><![CDATA[
I&#8217;ve been bothered for a long time by a limitation of NSTextFieldCell that prevents developers from specifying a vertically centered alignment. This is particular annoying in contexts where Apple practically rolls out the red carpet for a particular UI feature, but where taking advantage of that feature is almost guaranteed to produce an ugly result. [...]]]></description>
			<content:encoded><![CDATA[<p>
I&#8217;ve been bothered for a long time by a limitation of NSTextFieldCell that prevents developers from specifying a vertically centered alignment. This is particular annoying in contexts where Apple practically rolls out the red carpet for a particular UI feature, but where taking advantage of that feature is almost guaranteed to produce an ugly result. Take NSTableView for example. What is the most common cell type in a table? NSTextFieldCell of course. But what happens when you add the slightest bit of creativity to a table, say by changing the row height to a value not suited to the font size?
</p>
<p>
<img width="500" src="http://www.red-sweater.com/blog/images/VertTextBadAlign.jpg"/>
</p>
<p>
That&#8217;s bad enough,  but let&#8217;s say you find good reason to reach for even taller table columns? It can only get worse from here:
</p>
<p>
<img width="500" src="http://www.red-sweater.com/blog/images/VertTextWorstAlign.jpg"/>
</p>
<p>
In the past I&#8217;ve just worked around this problem by finding another way to present my UI. In other words: just keep the freakin&#8217; table view rows shallow, or else live with the funny looking top-alignment of the text. Today I got fed up with that and decided to shoot for a general-purpose solution.
</p>
<p>
I didn&#8217;t want to implement my own completely custom text cell. NSTextFieldCell is pretty good, you know! It does a lot for me, and I&#8217;d like to continue taking advantage of that. Through a bit of experimentation, I discovered that I could make a pretty minor tweak to NSTextFieldCell and get the behavior I wanted. By overriding &#8220;drawingRectForBounds:&#8221; and returning, instead of the whole lot of real estate available to me, a centered subset of that area, I convinced AppKit to render the text in the middle like I wanted it:
</p>
<p>
<img width="500" src="http://www.red-sweater.com/blog/images/VertTextGoodAlign.jpg"/>
</p>
<p>
Hey! That&#8217;s looking a lot better. I like it. It looks pretty. You know, like a Mac. But you know what doesn&#8217;t look pretty? When I double-click this bad boy and try to edit the text:
</p>
<p>
<img width="500" src="http://www.red-sweater.com/blog/images/VertTextBadEdit.jpg"/>
</p>
<p>
Ouch! That&#8217;s a pretty freaky looking user experience. Apparently NSTextFieldCell or some other component of AppKit is not used to having the drawing rect drastically adjusted without its knowledge. I might have to call this whole deal off. However bad top-aligned text in my table cell is, it&#8217;s a bajillion times less offensive than that. But then I realized that as a cell, I am given a lot of control over the edit process. What if I can limit my rect adjustment so that it&#8217;s normal while we&#8217;re editing, but weird (i.e. good) all the rest of the time?
</p>
<p>
I added two methods to my custom subclass, overriding &#8220;selectWithFrame:&#8230;&#8221; and &#8220;editWithFrame:&#8230;&#8221;.  In these methods, I use my rect calculation method to transform the proposed edit or selection rect into the more desirable &#8220;centered rect,&#8221; then I set a flag in the class &#8220;mIsEditingOrSelecting&#8221; which tells my rect calculator to stop the funny business. The result is an NSTextFieldCell with very little code that, as far as I can tell, behaves appropriately in all circumstances:
</p>
<p>
<img width="500" src="http://www.red-sweater.com/blog/images/VertTextGoodEdit.jpg"/>
</p>
<p>
Good enough for beta software! But here&#8217;s where you come in. You want this sexy vertically aligned cell for your app, right? So let&#8217;s share and figure out whether it&#8217;s monumentally busted or not.
</p>
<p>
Download <a href="http://www.red-sweater.com/blog/downloads/RSVerticallyCenteredTextFieldCell.zip">RSVerticallyCenteredTextFieldCell</a>. MIT License. Pop it into your project and, upon waking from nib, set your text column data cells (or other text field cells, if you have good reason) to instances of it. Let me know if you spot any bugs!
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/148/what-a-difference-a-cell-makes/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Drag If You Want To</title>
		<link>http://www.red-sweater.com/blog/142/drag-if-you-want-to</link>
		<comments>http://www.red-sweater.com/blog/142/drag-if-you-want-to#comments</comments>
		<pubDate>Wed, 07 Jun 2006 17:44:57 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Free Code]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/142/drag-if-you-want-to</guid>
		<description><![CDATA[Handling drags to your Cocoa application is pretty simple: you just have to implement the informal NSDraggingDestination protocol in some view hierarchy object that has been registered for particular drag types. 

Usually a drag is handled by a specific view that can make sense of the drag&#8217;s data type. For instance, an NSTextView will accept [...]]]></description>
			<content:encoded><![CDATA[<p>Handling drags to your Cocoa application is pretty simple: you just have to implement the informal NSDraggingDestination protocol in some view hierarchy object that has been registered for particular drag types. </p>
<p>
Usually a drag is handled by a specific view that can make sense of the drag&#8217;s data type. For instance, an NSTextView will accept text from the dragging clipboard and plop it down into the edited documnt. Most of the time, drags should only be handled by these specific views, but sometimes it makes sense to intercept &#8220;unhandled drags&#8221; and make something useful happen for the user. For instance, when a user drags a URL to a web browser, you might as well assume that they want to open the URL, even if they carelessly let go somewhere in the browser window&#8217;s non-descript background texture.
</p>
<p>
Apple made it easy to handle such &#8220;drags of last resort&#8221; at the window level, by kindly passing along all dragging offers from NSWindow to the window&#8217;s delegate. If your delegate simply implements the required methods, you can snag and make useful any drag that would otherwise bounce back to the originator.
</p>
<p>
But handling such non-specific drags at any level lower than NSWindow becomes tricky. There is no corresponding &#8220;delegation&#8221; when it comes to NSView, so drags that hover over or release in an uncooperative view will not be accepted, even if you&#8217;ve asked the view to register for the desired types.
</p>
<p>
When you are faced with the desire to &#8220;stake out&#8221; part of a window&#8217;s real-estate as a drag destination, the simplest way to do so is to sneak a custom NSView into the hierarchy that <em>does</em> accept drags. But instead of writing a custom view every time you need to do this, why don&#8217;t we follow AppKit&#8217;s lead and write our own NSView subclass that makes use of the delegation strategy.
</p>
<p>
<a href="http://www.red-sweater.com/blog/downloads/RSDragDelegationView.zip">RSDragDelegationView</a> (MIT License) is a very simple NSView subclass that does just this. To mark the background area of a part of your UI as dragging-receptive, just select items in Interface Builder and &#8220;make subviews of custom view.&#8221; Set the class of the custom NSView to RSDragDelegationView (drag the header file to your IB document to teach it about the class), and connect the &#8220;mDraggingDelegate&#8221; outlet to the delegate instance. From your delegate code, you can now ask the custom view to register for your desired drag types, and all dragging messages will be forwarded on to you as they&#8217;re received.
</p>
<p>
An example of where I use this in my own code is in the &#8220;product registration pane.&#8221; I want to accept drags generously, because I advise users to drag their product registration email into the window after they&#8217;ve paid. If they can&#8217;t figure it out, they might email me, and while I&#8217;m always up for a nice customer chat, I&#8217;d just as soon talk about other things. There&#8217;s no reason for me not to make this as error-proof as possible, so I stake out the entire space of the tab view item in which the pane is installed. By using a custom drag-enabled view I avoid inflicting drag receptivity on the rest of the window, and keep the dragging-related code right near the controller code for the UI that needs it. If another section of the window&#8217;s UI needs to accept drags liberally, the same trick can be applied without complicating drag-handling at the window level.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/142/drag-if-you-want-to/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
