<?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"
	>

<channel>
	<title>Red Sweater Blog &#187; FlexTime</title>
	<atom:link href="http://www.red-sweater.com/blog/category/red-sweater-news/flextime/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.red-sweater.com/blog</link>
	<description>Mac &#38; Technology Writings by Daniel Jalkut</description>
	<pubDate>Thu, 14 Aug 2008 22:56:42 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<item>
		<title>FlexTime 1.2.2</title>
		<link>http://www.red-sweater.com/blog/499/flextime-122</link>
		<comments>http://www.red-sweater.com/blog/499/flextime-122#comments</comments>
		<pubDate>Mon, 19 May 2008 17:04:47 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
		
		<category><![CDATA[FlexTime]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=499</guid>
		<description><![CDATA[Ever since FlexTime 1.0 came out almost two years ago, people have been asking me why they can&#8217;t use the space bar to start and stop a routine. 

Sorry it took so long, folks. FlexTime 1.2.2 now supports this!
]]></description>
			<content:encoded><![CDATA[<p>Ever since FlexTime 1.0 came out almost two years ago, people have been asking me why they can&#8217;t use the space bar to start and stop a routine. </p>
<p>
Sorry it took so long, folks. <a href="http://red-sweater.com/flextime/">FlexTime 1.2.2</a> now supports this!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/499/flextime-122/feed</wfw:commentRss>
		</item>
		<item>
		<title>FlexTime Gets Some Love</title>
		<link>http://www.red-sweater.com/blog/420/flextime-gets-some-love</link>
		<comments>http://www.red-sweater.com/blog/420/flextime-gets-some-love#comments</comments>
		<pubDate>Mon, 15 Oct 2007 14:27:52 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
		
		<category><![CDATA[FlexTime]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/420/flextime-gets-some-love</guid>
		<description><![CDATA[Things have been hectic. Real hectic! Between acquiring two major applications this year, renovating and rebranding one, and building a significant 2.0 upgrade for the other, oh and getting married among other things, I&#8217;ve had very little extra time to work on anything else (or not work, for that matter!).

But I finally got a bit [...]]]></description>
			<content:encoded><![CDATA[<p>Things have been hectic. <em>Real hectic!</em> Between acquiring two major applications this year, renovating and rebranding one, and building a significant 2.0 upgrade for the other, oh and <a href="http://www.red-sweater.com/blog/334/married-life">getting married</a> among other things, I&#8217;ve had very little extra time to work on anything else (or not work, for that matter!).</p>
<p>
But I finally got a bit of time to address a few nagging issues with <a href="http://www.red-sweater.com/flextime/">FlexTime</a>. People have been complaining since very early on that the &#8220;reset&#8221; and &#8220;back&#8221; buttons should behave more like the familiar CD-players that the UI sort of roughly resembles. That is to say, pressing back should not skip to the <em>previous</em> item in the timeline, unless you&#8217;re already really close to the beginning. And pressing reset shouldn&#8217;t stop the playback, it should just start it over.
</p>
<p>
These minor usability tweaks should come as a great relief to people who have been fighting the unintuitive nature of the old behavior. Also, when I added the &#8220;Export to iTunes&#8221; feature, which is awesome for taking your routines on the road, I neglected to produce a toolbar icon for it. Now we&#8217;ve got a very cute, very obvious little iTunes button that you can install in the routine window:
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/iTunesButton-20071015-102444.jpg" />
</p>
<p>
The button will be present by default for all new users. If you&#8217;re an existing user you may have to customize the toolbar to drag it in, since your old preferences won&#8217;t include it.
 </p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/420/flextime-gets-some-love/feed</wfw:commentRss>
		</item>
		<item>
		<title>MacBreak Weekly Mentions</title>
		<link>http://www.red-sweater.com/blog/299/macbreak-weekly-mentions</link>
		<comments>http://www.red-sweater.com/blog/299/macbreak-weekly-mentions#comments</comments>
		<pubDate>Wed, 14 Mar 2007 20:50:30 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
		
		<category><![CDATA[FlexTime]]></category>

		<category><![CDATA[MarsEdit]]></category>

		<category><![CDATA[Technology]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/299/macbreak-weekly-mentions</guid>
		<description><![CDATA[Wow! What a thrill to be listening to one of my favorite podcasts, MacBreak Weekly, and suddenly Leo Laporte is uttering my name, and expressing his satisfaction about my acquisition of MarsEdit.

And then I think I was so excited that I started hallucinating, because it almost sounded like Merlin Mann chimed in about FlexTime, and [...]]]></description>
			<content:encoded><![CDATA[<p>Wow! What a thrill to be listening to one of my favorite podcasts, <a href="http://www.twit.tv/mbw">MacBreak Weekly</a>, and suddenly Leo Laporte is uttering my name, and expressing his satisfaction about my acquisition of <a href="http://www.red-sweater.com/marsedit/">MarsEdit</a>.</p>
<p>
And then I think I was so excited that I started hallucinating, because it almost sounded like <a href="http://www.merlinmann.com/">Merlin Mann</a> chimed in about <a href="http://www.red-sweater.com/flextime/">FlexTime</a>, and lo, there was a great praising. And everybody was happy. Especially me.
</p>
<p>
Listen to <a href="http://www.twit.tv/mbw33">Episode 33: The Stay-At-Homers</a>, and be sure to perk your ears up around 1:18:00 (that&#8217;s 1 <em>hour</em>, 18 minutes in).
</p>
<p>
My favorite quote is from Leo Laporte about FlexTime, &#8220;You know, I have FlexTime and I&#8217;m trying to think of what to do with it.&#8221; Yeah, the story of that app&#8217;s life. Reminds me of John Gruber&#8217;s <a href="http://daringfireball.net/linked/2006/august#thu-17-flextime">initial reaction</a>. Suffice to say, once you figure out what the heck to use FlexTime for, it will become indispensable :)
</p>
<p>
Thanks, Leo &#038; Merlin!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/299/macbreak-weekly-mentions/feed</wfw:commentRss>
		</item>
		<item>
		<title>FlexTime 1.2</title>
		<link>http://www.red-sweater.com/blog/261/flextime-12</link>
		<comments>http://www.red-sweater.com/blog/261/flextime-12#comments</comments>
		<pubDate>Tue, 16 Jan 2007 17:18:02 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
		
		<category><![CDATA[FlexTime]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/261/flextime-12</guid>
		<description><![CDATA[FlexTime 1.2 is out today, with the highly anticipated &#8220;Send Audio to iTunes&#8221; feature!




Why would you want to send audio to iTunes? It&#8217;s the fastest route to the iPod.  Many FlexTime routines beg to be taken away from the computer. By sending audio to iTunes, users can easily collect a number of routines on [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.red-sweater.com/flextime/">FlexTime 1.2</a> is out today, with the highly anticipated &#8220;Send Audio to iTunes&#8221; feature!</p>
<p>
<img src="http://www.red-sweater.com/blog/images/SendAudioItunes.png"/>
</p>
<p>
Why would you want to send audio to iTunes? It&#8217;s the fastest route to the iPod.  Many FlexTime routines beg to be taken away from the computer. By sending audio to iTunes, users can easily collect a number of routines on their iPod and play them at their convenience.
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/MetronomeItunes.png"/>
</p>
<p>
Me, personally? I&#8217;ll probably use this feature to take my yoga routine with me on trips.  Back when I was in music school I would have loved this feature for practicing complex polyrhythms. Basically you&#8217;d spot me walking down the street in a sort of hypnotic daze as I conducted one rhythm with my arm and spoke a different one (&#8221;ta, ta, ta-ta&#8221;). FlexTime would have been a great practice aid for that!
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/261/flextime-12/feed</wfw:commentRss>
		</item>
		<item>
		<title>First 100 Billable Days</title>
		<link>http://www.red-sweater.com/blog/252/first-100-billable-days</link>
		<comments>http://www.red-sweater.com/blog/252/first-100-billable-days#comments</comments>
		<pubDate>Mon, 08 Jan 2007 18:33:09 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
		
		<category><![CDATA[Business]]></category>

		<category><![CDATA[FlexTime]]></category>

		<category><![CDATA[Links]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/252/first-100-billable-days</guid>
		<description><![CDATA[Mike Zornek wrote a great summary of his experience so far as an indie Mac software vendor. Billable is a slick time-tracking and invoice-generating application. The graph plotting &#8220;interest&#8221; (number of downloads) is especially illuminating since it shows how quickly the buzz of internet linking can dwindle away. Depressing, innit?

He&#8217;s about to release Billable 1.1, [...]]]></description>
			<content:encoded><![CDATA[<p>Mike Zornek wrote a <a href="http://clickablebliss.com/blog/2007/01/08/billable_the_first_100_days/">great summary</a> of his experience so far as an indie Mac software vendor. <a href="http://clickablebliss.com/billable">Billable</a> is a slick time-tracking and invoice-generating application. The graph plotting &#8220;interest&#8221; (number of downloads) is especially illuminating since it shows how quickly the buzz of internet linking can dwindle away. Depressing, innit?</p>
<p>
He&#8217;s about to release Billable 1.1, which he points out has taken longer than he expected. I&#8217;m jealous, because I&#8217;m also quite late in getting my 1.2 release of <a href="http://www.red-sweater.com/flextime/">FlexTime</a> out the door. Hopefully it will be ready before the month is up!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/252/first-100-billable-days/feed</wfw:commentRss>
		</item>
		<item>
		<title>FlexTime 1.2b1</title>
		<link>http://www.red-sweater.com/blog/237/flextime-12b1</link>
		<comments>http://www.red-sweater.com/blog/237/flextime-12b1#comments</comments>
		<pubDate>Sat, 16 Dec 2006 18:09:27 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
		
		<category><![CDATA[FlexTime]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/237/flextime-12b1</guid>
		<description><![CDATA[An ability to export audio to iTunes has been part of my vision for FlexTime since the very beginning. How cool to be able to design a custom pattern of sound cues, send them to iTunes, then take them with you on your iPod?

I&#8217;ve been hard at work on this feature, and I&#8217;m nearing completion. [...]]]></description>
			<content:encoded><![CDATA[<p>An ability to export audio to iTunes has been part of my vision for FlexTime since the very beginning. How cool to be able to design a custom pattern of sound cues, send them to iTunes, then take them with you on your iPod?</p>
<p>
I&#8217;ve been hard at work on this feature, and I&#8217;m nearing completion. Just some fine-tuning and bug-fixes. But I&#8217;m not going to be able to find the time to finish up until probably sometime next month. I know many FlexTime users have been waiting patiently for this feature, so as a compromise I&#8217;m releasing a beta version with the feature as it exists so far.
</p>
<p>
<a href="http://www.red-sweater.com/flextime/FlexTime1.2b1.dmg">Download FlexTime 1.2b1</a>
</p>
<p>
To use the feature, just select &#8220;Send Audio to iTunes&#8221; from the Routine menu:
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/SendToITunes.png"/>
</p>
<p>
The audio from any &#8220;Play Sound&#8221; or &#8220;Speak Text&#8221; cues will be arranged into an audio file the length of your routine, and sent to iTunes. The audio file is meant to sound roughly the same as what you&#8217;d hear if you pressed play from the beginning in FlexTime, and allowed the routine to run all the way to the end. I don&#8217;t incorporate repeats because I figure you can use iTunes or your iPod to repeat the track as necessary.
</p>
<p>
Among the known bugs is a problem where &#8220;Speak Text&#8221; cues do not show up in the exported audio on the first try. Just export again and they should be in there.
</p>
<p>
Let me know if you run into any issues, or have any last-minute suggestions for improving the feature.
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/237/flextime-12b1/feed</wfw:commentRss>
		</item>
		<item>
		<title>Random Length FlexTime Activities</title>
		<link>http://www.red-sweater.com/blog/225/random-length-flextime-activities</link>
		<comments>http://www.red-sweater.com/blog/225/random-length-flextime-activities#comments</comments>
		<pubDate>Sat, 25 Nov 2006 16:57:52 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
		
		<category><![CDATA[AppleScript]]></category>

		<category><![CDATA[FlexTime]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/225/random-length-flextime-activities</guid>
		<description><![CDATA[A FlexTime customer recently asked me if there was any way to set up a routine such that each activity in the routine would take a random period of time. His interest was in having FlexTime remind him at irregular intervals to stay focused on the task at hand. Unfortunately, the short answer is &#8220;no.&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>A FlexTime customer recently asked me if there was any way to set up a routine such that each activity in the routine would take a random period of time. His interest was in having FlexTime remind him at irregular intervals to stay focused on the task at hand. Unfortunately, the short answer is &#8220;no.&#8221; FlexTime currently relies on having a specific time set for each of the activities in a routine. But as is so often the case, the long answer is &#8220;yes, sort of. kind of.&#8221;</p>
<p>
This is another instance where the presence of a robust AppleScript implementation allows me to offer at least a passable solution to the customer. By writing a script that configures a <em>new document</em> with a random arrangement of activities, and then runs it, it approximates the desired experience of being able to have a single document that runs differently each time it is run.
</p>
<p>
<a href="http://www.red-sweater.com/blog/downloads/FlexRandomTimes.zip">FlexRandomTimes</a> is a standalone applet that can simply be double-clicked to start playing a routine with random timings. You can place it in your dock or Finder sidebar for easy access. It can also be opened and edited with Script Editor to suit your particular needs. All of the &#8220;easy to change&#8221; settings are near the top of the script. For instance, if you want more than 20 randomized activities, just change the setting of &#8220;kMyNumberOfRandomActivities&#8221; to suit your needs. Likewise for the randomness range and for the sound that should be played on each activity.
</p>
<p>
A particularly advanced move would be to merge this script with some of the logic from <a href="http://www.red-sweater.com/blog/222/flextime-random-sounds">FlexTime Random Sounds</a> to get an especially randomized experience.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/225/random-length-flextime-activities/feed</wfw:commentRss>
		</item>
		<item>
		<title>Public Speaking With FlexTime</title>
		<link>http://www.red-sweater.com/blog/224/public-speaking-with-flextime</link>
		<comments>http://www.red-sweater.com/blog/224/public-speaking-with-flextime#comments</comments>
		<pubDate>Thu, 16 Nov 2006 17:09:37 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
		
		<category><![CDATA[FlexTime]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/224/public-speaking-with-flextime</guid>
		<description><![CDATA[Anybody who&#8217;s ever taken a public speaking class, in high school or college, remembers the strict time considerations that were placed on speech assignments. I remember mine, at City College of San Francisco, where the instructor would sit in the back corner of the room with a stopwatch around his neck. At the beginning of [...]]]></description>
			<content:encoded><![CDATA[<p>Anybody who&#8217;s ever taken a public speaking class, in high school or college, remembers the strict time considerations that were placed on speech assignments. I remember mine, at <a href="http://www.ccsf.edu/Resources/Faculty/cdewar/ElementsofPublicSpeakingSPCH1A.htm">City College of San Francisco</a>, where the instructor would sit in the back corner of the room with a stopwatch around his neck. At the beginning of every speech he would start the timer, and any deviation from the assigned time of the speech would cost you serious points. I believe in my class it was a full grade reduction if you under or overshot the target by something like 30 seconds or a minute.</p>
<p>
After I finished developing <a href="http://www.red-sweater.com/flextime/">FlexTime</a>, it occurred to me that it would have been the perfect tool to practice my public speaking assignments. By building a FlexTime routine comprised of different &#8220;activities&#8221; for each of the note cards comprising a speech, you could fine-tune the timing of a speech down to each specific topic and point.  FlexTime text cues would make perfect reminders that it&#8217;s time to move on to the next topic. Each time you practiced the speech, immediate feedback from FlexTime would let you know whether you were getting more or less on target for the ideal timing.
</p>
<p>
It&#8217;s been years since I&#8217;ve given a formal speech in any context, so I haven&#8217;t had a chance to put this particular use case to the test. Geoff Pado is a young Mac software developer who also happens to be taking his high school speech class this year. Faced with a speech that needed to be at least 5:50 but no longer than 6:10, he decided to <a href="http://www.elgebar.com/blog/2006/11/15/flextime/">put FlexTime to the test</a>. The results were glorious, as he describes being able to hit the target with very little practice. That&#8217;s a very tight window of time, and I&#8217;m sure most of his classmates weren&#8217;t nearly as successful at meeting the requirement.
</p>
<p>
Another weird success story for FlexTime!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/224/public-speaking-with-flextime/feed</wfw:commentRss>
		</item>
		<item>
		<title>FlexTime Random Sounds</title>
		<link>http://www.red-sweater.com/blog/222/flextime-random-sounds</link>
		<comments>http://www.red-sweater.com/blog/222/flextime-random-sounds#comments</comments>
		<pubDate>Fri, 03 Nov 2006 20:46:38 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
		
		<category><![CDATA[AppleScript]]></category>

		<category><![CDATA[FlexTime]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/222/flextime-random-sounds</guid>
		<description><![CDATA[Tim Altman asks whether a &#8220;Random Sound&#8221; option might be a good enhancement for FlexTime&#8217;s &#8220;Play Sound&#8221; cue type. I think this is an interesting idea, and definitely worth considering. But what can I do for Tim right now? 

Another case of AppleScript to the rescue.  By setting an activity&#8217;s starting cue to &#8220;Play [...]]]></description>
			<content:encoded><![CDATA[<p>Tim Altman <a href="http://www.red-sweater.com/blog/219/flextime-11#comment-22146">asks</a> whether a &#8220;Random Sound&#8221; option might be a good enhancement for <a href="http://www.red-sweater.com/flextime/">FlexTime&#8217;s</a> &#8220;Play Sound&#8221; cue type. I think this is an interesting idea, and definitely worth considering. But what can I do for Tim <em>right now</em>? </p>
<p>
Another case of AppleScript to the rescue.  By setting an activity&#8217;s starting cue to &#8220;Play Sound&#8221; and its finishing cue to <a href="http://www.red-sweater.com/blog/downloads/RandomSound.zip">RandomSound.scpt</a>, we can let FlexTime <em>change its own sound</em> as it runs. Everytime the activity starts, it plays a sound, and everytime it ends, it changes the sound to something different than it currently is.
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/WakeUp.png"/>
</p>
<p>
Unfortunately FlexTime doesn&#8217;t expose the list of possible sounds through AppleScript. That&#8217;s another enhancement I&#8217;ll have to consider. But by hardcoding the list of possible sounds in the script, I&#8217;m able to choose a random one until I get something different than what&#8217;s already set. So you&#8217;ll never hear the same sound twice in a row.
</p>
<p>
Would it be nice if this was easier? Heck yeah. But the fact a <em>random feature request</em> happens to be addressable with AppleScript today is testament to the extensibility of FlexTime.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/222/flextime-random-sounds/feed</wfw:commentRss>
		</item>
		<item>
		<title>Flex Your HIG</title>
		<link>http://www.red-sweater.com/blog/221/flex-your-hig</link>
		<comments>http://www.red-sweater.com/blog/221/flex-your-hig#comments</comments>
		<pubDate>Fri, 03 Nov 2006 18:01:14 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
		
		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[FlexTime]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Usability]]></category>

		<category><![CDATA[applebugfriday]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/221/flex-your-hig</guid>
		<description><![CDATA[Some readers pointed out that in announcing FlexTime 1.1, along with its snazzy new interface, I left out some of the most interesting details to programmers. How did I accomplish all of the little things that add up to the new UI? Like everything else in life, you just bite off a little bit at [...]]]></description>
			<content:encoded><![CDATA[<p>Some readers pointed out that in <a href="http://www.red-sweater.com/blog/219/flextime-11">announcing FlexTime 1.1</a>, along with its snazzy new interface, I left out some of the most interesting details to programmers. How did I accomplish all of the little things that add up to the new UI? Like everything else in life, you just bite off a little bit at a time, and hope for the best. And also like everything in life, it seems a lot easier once you&#8217;ve done it. But looking back I can see a lot of discrete obstacles that I had to overcome, and perhaps my path through the wilderness will prove helpful to you. I&#8217;m going to go over the steps that made up the redesign in roughly chronological order, including links to existing open source packages that I used, and also releasing some small contributions of my own for your review.</p>
<p><h3>Inspiration</h3>
<p>Before anything else, you&#8217;ve got to be inspired to change. That might sound fluffy, but it&#8217;s absolutely critical. If you&#8217;re not convinced that your UI needs an overhaul, then you might as well forget it. You can rub sticks together for an eternity, but if you&#8217;re not cold, you&#8217;ll never start a fire. You have got to be dissatisfied with something before you can make it better. For reference, this is what I was becoming increasingly dissatisfied with before embarking on this journey:
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/FlexTime1.0.png"/>
</p>
<p>
I was pretty happy with FlexTime 1.0 when I released it. It did the job. I had never designed toolbar icons before, so I felt pretty good about the matte blue stencils I came up with using <a href="http://www.nodebox.net/">NodeBox</a>. Hey, that <em>was</em> a nice piece of work for a newbie UI designer who is just trying to get something out the door. But it quickly started to grate on me. The interface was not suited to evolution. The inequities between the square corners of the list view and the round corners of the details box made it hard to embed anything more complicated than the few standard controls I have in there now. I was trapped my 1.0 interface, but I couldn&#8217;t figure out what needed to be done to fix it.
</p>
<p>
What followed was basically a month or more of working on anything but the interface. I couldn&#8217;t bear it. I found myself frustrated whenever I looked at it, because I knew something drastic had to change. But what? I worried I might have to scrap the whole thing and start from scratch.
</p>
<p>
Then I was sitting in Chicago at <a href="http://c4.rentzsch.com/">C4</a>, listening to <a href="http://www.daringfireball.net/">John Gruber</a> talk about the &#8220;death of the HIG.&#8221; He brought up <a href="http://inessential.com/">Brent Simmons</a>, using his <a href="http://www.newsgator.com/NGOLProduct.aspx?ProdID=NetNewsWire">NetNewsWire</a> as an example of somebody who had made a big impact by stepping outside the HIG guidelines. What Brent had done was an app that had broken with traditional HIG guidelines by <a href="http://rentzsch.com/macosx/pushingTheEdge">eliminating the margins</a> around the main views in his window. That&#8217;s when it struck me: &#8220;I&#8217;ve got too many margins.&#8221; I immediately envisioned FlexTime with its list view and details pane flush against the left and right edges of the window. That was it. I just realized that was where I&#8217;d start, and left it in my head to sink in. I spent the rest of the weekend on not really thinking about it.
</p>
<p><h3>Losing The Margins</h3>
<p>When I got home, I didn&#8217;t waste much time getting to work on this. I busted open Interface Builder and started moving stuff around. About the only &#8220;gotcha&#8221; with this exercise is getting the UI to look good flush against the edge. A trick I discovered (and recently saw repeated by Brent Simmons on a mailing list) is that many views, table view included, will look best if its border is hidden off the edge of the screen. To accomplish this, you can simply set the x origin of the view to -1. This is a good trick to keep in your back pocket for a variety of finishing touch-ups.
</p>
<p>
I realized quickly that zero-margins on the left and right sides made the text labels and associated whitespace above the respective sections look stupid. Gasp! Could I just take those labels out? But the user will be lost without them! The main instructiveness of those labels was to tell the user that the list on the left was an &#8220;Activity List.&#8221; I discovered that by changing the main column&#8217;s label from &#8220;Name&#8221; to &#8220;Activity Name,&#8221; I could get this point across well enough without using a sledgehammer to drive it home.
</p>
<p><h3>A Touch Of Polish</h3>
<p>I also decided pretty early on that the streamlined look might go well with one of the &#8220;polished metal&#8221; looks from Apple&#8217;s suite of applications. I ended up using <a href="http://mattgemmell.com/source/">PolishedWindow</a>, which masquerades as &#8220;TunesWindow&#8221; on Matt Gemmell&#8217;s web site. He basically put together an NSWindow subclass that draws its background with a bunch of images  to match Apple&#8217;s iTunes-ish windows. This was a real simple change to integrate. If I get time I might try to improve the code by getting it to use computed gradients instead of images. I feel like the code could probably be a bit faster during resizes. But for a quick fix this was a real champ.
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/FlexTimeHIG1.png"/>
</p>
<p>
Well shoot howdy, that looks pretty good. It&#8217;s such an improvement to my eye that I was frankly about ready to call it a day and ship it. But once you start moving, the inertia of change pulls you along until <em>it&#8217;s</em> ready to slow down. You set out to change one thing, and can&#8217;t estimate how many changes you&#8217;ll ultimately end up making. I showed the screenshot to a few friends, and what do you know, they found <em>plenty</em> to complain about. <em>The icons looks out of place. There is no dividing ridge between the content and the top/bottom sections. The selection of the table should be a gradient. What&#8217;s that funny blank column at the end of your table? Pinstripe grey looks wrong in a polished window.</em> The problem with having smart friends is they always have an opinion. You&#8217;ve got to learn to dismiss some feedback as a matter of taste. People feel passionately about Coke and Pepsi, but what do you know, they&#8217;re both successes. But often the things that rankle one person are going to upset a lot of others, too. So I take early feedback seriously. I might argue with a person, if only to make them justify why their suggestion is right. When the feathers have settled, usually it turns out that they were right, and I&#8217;m wrong. So I fix it.
</p>
<p><h3>Pinstripes, Ridges, and Gradients</h3>
</p>
<p>
It&#8217;s hard to see the pinstriping in the above screenshot, but trust me, it&#8217;s there. It&#8217;s not so bad, because it sort of blends visually to a light grey, but it really bothered some friends who saw it as out of place in the polished window. I also decided to add a gradient shine to the table view selection, and some defining &#8220;ridges&#8221; between the main content and the toolbar on top, and bottom section on the bottom.
</p>
<p>
The ridges are probably the most embarrassing of the three solutions, so I&#8217;ll start with them. I don&#8217;t know what the heck I&#8217;m doing. I&#8217;m a frickin&#8217; professional, but I&#8217;m also an amateur. We all are. Professionals are just amateurs who know it&#8217;s not worth faking like you know something you don&#8217;t. In all seriousness, one of the things that makes me a professional is my ability to prioritize &#8220;working code&#8221; over &#8220;correct code.&#8221;  I look at those ridges, as they appear in something like iTunes, and all manner of possible solutions spring to mind. I can rewrite the window subclass to draw the ridges as part of the background. Or I could devise a special &#8220;polished window content box&#8221; that draws the desired outline on the top and bottom edges. But the simplest solution at the time seemed to be popping arbitrarily colored &#8220;divider lines&#8221; into the UI at the appropriate spots.
</p>
<p>
I for one have always taken the &#8220;divider&#8221; for granted. It&#8217;s such a simple UI element. Usually you drag it in from Interface Builder and let it sit there undisturbed for the life of your product. But I want a <em>colored</em> divider line. In fact, I want four of them, positioned just right so they look like fancy iTunes ridges. In Cocoa, it turns out that divider lines are a very special variant of NSBox! Who knew? So I set about subclassing NSBox to provide colored divider lines. <a href="http://www.red-sweater.com/blog/downloads/RSColoredBox.zip">RSColoredBox</a> should really be called RSColoredDivider or something that is more honest about the presumptions the code makes. I don&#8217;t think it will make a very good colored box, per se. I thought it would at first, but it turns out that the way Cocoa and IB plop down &#8220;divider boxes&#8221;, they have boundaries that lie. Divider boxes are of a special variant and are actually much taller or wider than you&#8217;d assume. Anyway, use that code if you want a colored <em>line</em> in your interface. Just drag a divider in from IB, set its custom class to &#8220;RSColoredBox,&#8221; and then call &#8220;setBoxBorderColor&#8221; on the line at awakeFromNib time. Cheap hacks, baby. Take it or leave it.
</p>
<p>
Getting rid of the pinstripes in my NSTabView is also not quite as simple as one might guess. This is one of those moments where you think &#8220;why doesn&#8217;t NSTabView have a backgroundColor attribute?!&#8221; The options for NSBox are that you can have it draw nothing, or draw pinstripes. Tough love.  The cheapest way I could find to work around this deficiency was to subclass NSTabView and take over the drawing mechanism. Instead of drawing pinstripes, which is all the parent class does, I&#8217;ll just fill a rect. Again, this isn&#8217;t a very robust class - it only works when the tab view is &#8230; tabless. C&#8217;est la vie. <a href="http://www.red-sweater.com/blog/downloads/RSColorBackgroundTabView.zip">RSColorBackgroundTabView</a> is available for your perusal.
</p>
<p>
Finally, the gradient table view. This is one of those things that can be done right, or any of a million varieties of wrong. I was lucky to discover that <a href="http://www.wilshipley.com/blog/">Wil Shipley</a> had written, during his time at Omni, a perfectly reasonable <a href="http://wilshipley.com/blog/2005/07/pimp-my-code-part-3-gradient.html">gradient-highlighting table view</a>. You&#8217;ll need to snag the code from <a href="http://www.omnigroup.com/developer/sourcecode/">OmniAppKit</a>, where it&#8217;s provided with the same license as everything else in that fine package. The things Shipley&#8217;s code does right are that he computes the gradient programatically, and he obeys the user&#8217;s highlight color. These two qualities made the code an easy sell for me.
</p>
<p><h3>Pie In The Sky</h3>
</p>
<p>
The &#8220;empty column&#8221; in the screenshot above corresponds to the animated pie-chart progress that is displayed when a user is running a FlexTime routine. It becomes obvious what it is, as soon as you start running something. But I had to agree with my critics, a blank column header is kind of a cop-out.
</p>
<p>
My first thought was to simply reuse the excellent pie chart cell I use for the table content, which is based on Jon Wight&#8217;s <a href="http://toxicsoftware.com/blog/toxic_progress_indicator/">Toxic Progress Indicator</a>. I allocated one, configured it appropriately, and then &#8220;setHeaderCell:&#8221; on the NSTableColumn. This sorta kinda worked, but there were major drawbacks. First, the drawing of the pie chart at that size revealed aliasing problems that didn&#8217;t really look polished. I&#8217;d have to edit the code to improve the compositing over the background, or something. Second, when you take over responsibility as a header cell, you take over all responsibility. You&#8217;ve got to draw that cute polished background, in addition to the content. Now I&#8217;m sure I could have gotten this all to work, by employing the existing default table header cell to do some of the heavy lifting, or by subclassing it. But I heard a little voice in my head screaming &#8220;overengineering!&#8221; so I took a step back. <a href="http://www.noodlesoft.com/">Paul Kim</a> pointed out that I could simply &#8220;setImage:&#8221; on the existing header cell, and it would draw it for me, nicely composited over the polished background. Why go to the trouble of dynamically generating a pie chart image when one put together in PhotoShop will look just as good and be 100% predictable?
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/AssTable.png"/>
</p>
<p>
The image looks pretty good in the table header, but what&#8217;s that ugly crud on the edge? Why is it that I can&#8217;t spend more than 15 minutes at a computer without finding a bug in <em>somebody else&#8217;s code</em>? It&#8217;s the curse of the tester. I started my career in Quality Assurance and I&#8217;m doomed now to forever discover all the bugs. What&#8217;s going on here? It&#8217;s a bug in NSScrollView, or NSTableView. When a table view suddenly acquires a vertical slider, it causes the existing table headers to scrunch up and make room. In the space formerly occupied by the right-most table header, a special view is inserted called the &#8220;corner view.&#8221; This view is responsible, normally, for just drawing an empty background. After some debugging I discovered that when an NSTableView acquires a scroll bar, the cornerView is made visible, but not asked to redraw. That means whatever was on the screen before it appeared just gets left there. Usually you get lucky, because what was there is blank table header background. Most table headers are left-aligned (only on left-to-right language systems?), and the text rarely reaches the far right edge of the table. Leave it to me to find the exception.
</p>
<p>
When I run into a bug like this, I like to confirm as quickly and definitively as I can that it&#8217;s not my problem. If I take a simple project, like Apple&#8217;s &#8220;OutlineView&#8221; developer example, and cause it to have text that runs up against the right edge, then I see the same bug:
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/AssTable2.png"/><br />
(Radar #<a href="rdar://problem/4818521">4818521</a>)
</p>
<p>
A workaround is to aggressively listen for table column resizes, and force the corner view to redraw itself whenever this happens:
</p>
<p><pre>
- (void)tableViewColumnDidResize:(NSNotification *)notification
{
   // Force the tableview's cornerview to redraw.
   [[oTableView cornerView] setNeedsDisplay:YES];
}
</pre>
</p>
<h3>Clickable Text</h3>
<p>
One of the biggest payoffs of this redesign was that it suddenly made the most ambitious part of my evolving UI a lot more palatable. I heard loud and clear that people were asking for large timer feedback while a routine was running, but I was <a href="http://www.red-sweater.com/blog/210/flextime-11a1">having a hard time</a> integrating it into the FlexTime UI. While the timers are not perfect, I do think they fit in a lot better in the margin-free context of FlexTime 1.1.
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/FlexTimers.png"/>
</p>
<p>
It&#8217;s worth talking a little bit about that custom UI. I wanted to satisfy two major design requirements:</p>
<ol>
<li>The time display should be large and easy to read.</li>
<li>The time display should be easy to configure and disable.</li>
</ol>
<p>
I decided on large clickable displays. The simplicity of changing a configuration by simply clicking it is hard to argue with. Don&#8217;t like what you see? Click it and see if it gets better. I haven&#8217;t had a lot of feedback yet, but I suspect this &#8220;implicit configuration&#8221; is probably much preferable to a preferences panel or something where the options are painfully selected from a list of radio buttons.
</p>
<p>
Now if you&#8217;re like me and tend to stick with standard UI pieces, you&#8217;re probably wondering how I put that little piece of work together. One reasonable approach would be to design a custom NSView subclass and handle all the hit testing and state changes in there. In fact, that&#8217;s probably a smarter way to go about things, but for whatever reason I tended towards the &#8220;design entirely in IB&#8221; path this time around. The &#8220;custom view&#8221; in this case is an elaborate contraption formed out of NSTabViews, bindings, and clickable NSTextFields. When you click an NSTextField, it changes the &#8220;view mode&#8221; for the display, which is a property of the document. An NSTabView contains the three view modes, and is bound by its &#8220;selectedIndex&#8221; binding directly to the viewing mode (conveniently an enum that matches the NSTabView indices). The text fields for the time displays are bound directly to &#8220;time remaining&#8221; or &#8220;time elapsed&#8221; values, which are NSTimeInterval values (double precision seconds). To present the clock-style format I attach a value transormer, RSTimeIntervalToClockStyleFormat, which turns the seconds into a pretty string as shown.
</p>
<p>
If you imitate this approach, you&#8217;ll soon learn that NSTextField is not clickable by default. But it <em>is</em> an NSActionCell. It has these qualities but normally only uses them in an editable context, where the target/action paradigm is applied when the value changes or editing ends. To extend the functionality to mouse clicks, simply subclass NSTextField (mine is RSClickableTextField) and override mouseDown:
</p>
<p><pre>
- (void)mouseDown:(NSEvent *)theEvent
{
   [self sendAction:[[self cell] action] to:[[self cell] target]];
}
</pre>
</p>
<h3>Buttons 2.0</h3>
<p>By this time, things are really starting to look good. My margins are gone. I&#8217;ve got my gradient. My light grey background. My polish. My pie chart header cell. Up to this point people have been screaming about the buttons, but I&#8217;ve been laughing it off. Haha! Maybe for 1.2. I just couldn&#8217;t muster the psychic energy to tackle such a big part of the UI. But the incongruence of those flat buttons was really starting to gnaw at me. I decided to take a stab at improving at least the color, and it quickly turned into a day-long obsession.</p>
<p>
While the original buttons  were entirely built from NodeBox, I decided I needed  to add some lighting effects and anti-aliasing that were simply not feasible in NodeBox. So I started with the NodeBox generated images, but set up a PhotoShop document to apply various manipulations to the images by filter layers, semi-transparent gradients, etc. It was a learning experience, but I&#8217;m pretty happy with the results.
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/FlexTime1.1.png"/>
</p>
<p>
As you can imagine there was a lot of tweaking and testing in this process, and one of the best things to come of it was my decision to build a &#8220;Generate Toolbar Icons&#8221; script. I organized my PhotoShop document in such a way that all of the various toolbar icons are in one document, so to save a particular icon you just hide all the other buttons&#8217; layers. This is cool because all the effects layers and gradients are consistent and can be changed in one place, where you&#8217;ll be sure they apply to all of the buttons.
</p>
<p>
Hiding and showing the layers would be tedious to do by hand, but PhotoShop&#8217;s &#8220;layer set&#8221; concept makes it easy to script. By putting all the toolbar buttons in a layer set called &#8220;Buttons,&#8221; I am able to easily hide all of them:
</p>
<p><pre>
	set buttonSet to layer set "Buttons" of myDoc
	set visible of layers of buttonSet to false
</pre>
</p>
<p>
Then I can iterate through all the layers in that layer set, setting the visibility of the layer to true, exporting a copy of the image, and setting the visibility back to false:
</p>
<p><pre>
repeat with layerIndex from 1 to count of layers of buttonSet
	set thisLayer to layer layerIndex of buttonSet
	set visible of thisLayer to true
	set outputName to outputPathRoot &#038; name of thisLayer &#038; ".png"
	save myDoc in outputName as PNG with copying
	set visible of thisLayer to false
end repeat
</pre>
</p>
<p>If you&#8217;ve used PhotoShop to &#8220;Save As,&#8221; you know how painful it is to constantly go through the options dialogs. AppleScript makes exporting even one image easier, but with my script I can easily regenerate all nine icons and spit them out directly into the appropriate source directory.</p>
<p><h3>Wrapping Up</h3>
<p>The only downer to doing a GUI redesign is that all of your pictorial documentation becomes instantly obsolete. After the relatively fun work of designing the graphics and tweaking the layout, I realized I&#8217;d have to redo all of my Help Book graphics, and the screenshots for download sites and my web page. The lesson I learned from this is that to whatever extent possible, you should keep the &#8220;art&#8221; separate from the notation. For instance in my documentation I include a screenshot with various annotations made upon it:
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/FlexHelpExample.png"/>
</p>
<p>
In 1.0, I foolishly generated this graphic in Pages or something, and saved it as a bitmap image. Dumb, dumb, Daniel. From here on out I&#8217;ll be conscientious about saving with layers and keeping the application UI &#8220;swappable&#8221; with a new graphic, where only minor adjustments might need to be made to the overlays.
</p>
<p>
That&#8217;s the story of how FlexTime got its HIG on. Hope you enjoyed it picked up a few new tricks along the way.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/221/flex-your-hig/feed</wfw:commentRss>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.809 seconds -->
