Friday, December 29, 2006

IndieHIG contribution: Source list implementation

My contribution to the IndieHIG: A source list implementation.



The demo is simply displays my NSTableView subclass called JKSourceTableView in a single window. JKSourceTableView makes it easy to use different NSCells in a single column, using different row heights. This enables you for example to create the effect of separator lines.

When I've got a bit more time i'll update the code to use a gradient row background. I'll also create an article explaining how you can use JKSourceTableView in your own code.

Download | Mirror (xcode project zip, 84kb)

Automator command line utility bug?

OS X comes with a commant line utility, /usr/bin/automator to execute Automator workflows from the command line. This is what man automator has to say:

NAME
automator -- runs an Automator workflow

SYNOPSIS
automator document

DESCRIPTION
automator runs the specified workflow document. To create or edit a
workflow, use the Automator application. There are no options.

Not very usefull. All we know now is how to specify which workflow we want to be run, no information on how to add input to the workflow, like a list of url's or a list of files.

I created a simple test workflow that display's two confirmation boxes. When the first one is dismissed with a negative response, the second one shouldn't appear. This works fine in Automator, when run I am presented with a dialog, when I click OK I get to see the second dialog. But when I run the workflow using /usr/bin/automator I never see the second dialog.

Some research using strings /usr/bin/automator reveals the presence of applicationShouldTerminateAfterLastWindowClosed: So perhaps this selector causes /usr/bin/automator to terminate after a dialog is closed, even before the Automator action is completed succesfully.

Thursday, December 21, 2006

Interface Builder and custom NSViews

My previous post was about JKDistributedView, my custom layout view I use in one of my applications. In my layout code I loop thru all subviews added in Interface Builder to calculate their sizes. I still don't know why but today an error occured that wasn't there before. The initial layout was totally messed up and instead of three views layed out vertically some random gaps seemed to appear between the views. It appeared JKDistributedView didn't have three subviews like I added in Interface Builder but it had four subviews. And even stranger, on the next layout the fourth unknown subview was gone all the sudden. After some debugging I found out what this fourth subview was.

Loading Resources: What Happens When a Nib File is Loaded

When you drag a standard object into the design window, Interface Builder encodes the actual class for that object, initializing the object as it builds the nib file. For custom subclasses of such objects, Interface Builder encodes the standard object but tells the archiver to swap in your custom class when the object is unarchived. These objects are also initialized when the nib file is built. Therefore, when the nib file is loaded, initWithFrame: is not called for either standard objects or custom subclasses of standard objects.

On the other hand, because the actual code for your subclass of NSView is not resident in Interface Builder, it does not encode the actual subclass when you drag a custom view object into the design window. Instead, it encodes a special object called NSCustomView that knows how to build the real custom view subclass. After NSCustomView has been instantiated by initWithCoder:, it calls alloc and initWithFrame: for the real class, and swaps in the real instance.

So when your nib file contains a subclass of NSView this class will be initiated using initWithFrame: by a NSCustomView instance that was saved in the nib file as a temporary replacement for your custom NSView.

Normally you shouldn't need to worry about NSCustomView but JKDistributedView contained a custom view and my layout code was performed before the temporary NSCustomView for this custom view had the time to clean up itself. The NSCustomView was layed out like all other subviews causing an empty space to appear. This was easily fixed by skipping all NSCustomView instances in the layout code:
if ([subview isKindOfClass:NSClassFromString(@"NSCustomView")]) { 
continue; /* skip this loop */
}

Tuesday, December 19, 2006

JKDistributedView

While trying to duplicate the RuleView used by Apple in the Finder for example I ran into the problem of resizing views. The RuleView needs to grow in size when a new rule is added. Each view following the RuleView needs to be resized to to create space for the RuleView. Since layout in InterfaceBuilder works using springs, but you can't attach two edges of view together, I created a helper view called JKDistributedView which helps me resize and reposition it's children views.



To use JKDistributedView you add a NSView subclass to Interface Builder and set it's custom class to JKDistributedView. Every nsview added to JKDistributedView will be layout according to the following rules:

  • top to bottom
  • Every view will get it's preferred height
  • When a views vertical springs are dynamic the view will fill all remaining vertical space after the fixed height views are sized.
When a rule is added to the JKRuleView it needs to grow in size. JKRuleView calls descendantFrameChanged: on it's parent view (JKDistributedView) to indicate all children of JKDistributedView need to be resized and repositioned.

So the finder smart folder view would be created using 3 views as subviews in a JKDistributedView. The JKRuleView, the NSOutlineView (using a dynamic vertical resize hint) and a third view at the bottom to display the path of the selected file. JKDistributedView makes sure the JKRuleView and the path view have a fixed size, the NSOutlineView will fill all space in between. Now when you click the add button in the JKRuleView a new rule will be added, JKDistributedView will increase JKRuleViews height and decrease the height of the NSOutlineView

Wednesday, December 13, 2006

Cocoa UI spit & polish

When playing with Interface Builder to create a UI for my application I sometimes run into the problem of trying to recreate a visual element used in Apple software. There are a lot of buttons and gradients used repeatedly in several Apple applications. When adding buttons with similar functionality I try to use the same artwork Apple uses for consistency.

The problem is that most of the buttons for example are custom designed by Apple and are not available by drag-n-drop in Interface builder.

So here is a collection of some images and custom classes that can be used for free in you application to add the spit and polish that makes your application look like a real Apple application. (Be sure to read the licenses for the specifics on copyrights).


An effort to give developers guidelines for replicated Apple interface elements was started under the name IndieHIG:
The IndieHIG Wiki is a place where developers and UI designers can come together to create a new set of Human Interface Guidelines to supplement Apple’s guidelines. Apple has neglected to update their HIG with modern UI designs and controls, so developers have been forced to replicate these UI elements on their own to keep their applications from looking dated. Since each developer has slightly different implementations of these elements, it has resulted in a fairly inconsistent look and feel for Mac OS users.

Maybe it's an idea to provide implementations of interface elements that follow these guidelines? For example the Polished Metal page describes the properties of a currect Polished window, for wich an implementation already exists in the form of TunesWindow.

I'm currently working on an implementation of a RuleEditor as used by the Finder to create smart folders:



When finished I'll document the properties of a rule editor in the IndieHIG and publish the sources of this class.

Sunday, December 10, 2006

XCode todo list

One of the things I use in TextMate regularly is the apple-cmd-b key combo, to bring up a todo list for the current project. Whenever I have something planned in my code, but don't feel like implementing it yet I annotate this piece of code with a comment like:

// TODO: check if url exists before saving it
saveURL(url);
The todo plugin will list all these TODO's from my code which gives me an indication on how to improve my code further.

The problem is that while I use TextMate for my web and java programming, I use XCode for most of the real programming done using Objective-C/Cocoa. But XCode doesn't have the todo feature and there is no way to add plugin's to XCode. Even a google search resulted in nothing on the subject.

So for now I'm using the Lightweight issue tracking bash script I found which seems like the only solution usable in combination with XCode.

# grep for "TODO" string
todo()
{
if [ $# -lt 1 ]; then
grep -R -n "TODO: " . | grep -v ".svn"
else
# loop through the args
while [ -n "$1" ]
do
grep -R -n "TODO: " "$1" | grep -v ".svn"
shift
done
fi
}


Add this script to your ~/.bash_profile to be able to execute the todo command that searches the current directory, or the directories given as argument for // TODO: lines.

Saturday, December 09, 2006

XCode Animations - Core Graphics

XCode Animations - Core Graphics:

Ever wanted to be able to use fancy transitions and animations in your Xcode applications? This tutorial provides the method and the means to implement terrific flips and ripples throughout your app, showing window transition effects using both undocumented and documented Objective-C code that can be implemented anywhere quickly and efficiently.


A small, quickly readable eBook that teaches the use of undocumented Core Graphics functionality. This certainly falls in the category of Undocumented Goodness and usage is therefore discouraged. That being said, if you would like to add effects like the ones used in applications like Quicksilver, Virtue Desktops and certain Apple applications I recommend you read this eBook.

Download (zip | pdf)

Thursday, December 07, 2006

RubyOSA on Rails

As posted before, I'm currently playing with with Ruby on Rails a lot. While doing so I discover more and more about the beauty of Ruby programming on Mac OS X (with or without rails). For example using the Ruby/Objective-C bridge it's possible to use any Cocoa Framework in a Ruby script. Even better, Apple seems to like Ruby and already made it clear Ruby on rails will be included in the next version of OS X.

So while searching for Ruby and OS X using google I found another useful gem: RubyOSA, a Ruby/AppleScript bridge. The bridge makes it possible to use any scriptable application as an object in your script.

The RubyOSA website gives a simple example of using Ruby to control iTunes. As an experiment I created a Rails application to do the same, but from a remote location. Not very useful on a live website because RubyOSA commands might take some time to execute. But combined with a wifi enabled phone or pda it results in a nice remote control for iTunes in a home network.

Friday, December 01, 2006

Ruby on Rails

About 2 weeks ago I started looking into Ruby on Rails. I've programmed using ruby before, and I installed a rails based blog before, but I never used rails to develop something myself. What I've seen so far really makes me think why I didn't start using Ruby on Rails before.

All the tools that come with Rails really make development much more easier than what I've used before. The scripts used to generate models, migrations and controllers from templates take away the need to repeat yourself with the most basic code.

More interesting is the tool called Capistrano. I just started using Capistrano only two weeks ago, but already I'm sold. Gone are the problems of releasing a new version and having a different version online then the one I'm working on. Since using Capistrano releasing websites to the web has become way more organized.

The current setup I'm using for the live server is an apache2 installation with 3 mongrel servers running in a cluster for each Rails application.

I develop the Rails application on my powerbook and test it using mongrel installed using Locomotive. The Rails installation is of course stored in a subversion repository. As soon as I think the current development version is ready for a release (feature complete and the tests show no errors occur) I tell Capistrano to deploy. A few seconds later my new version is online without me ever starting a ftp application. The database tables are updated automatically, files are checked out from subversion and all I have to do is sit and watch. And if somehow my unit tests didn't catch a bug, or something else has gone wrong, I'm back at the old version within 2 seconds. No more troubles with ftp, searching for the files that caused the error.

Because of all the information available on the internet you don't need a book nowadays to start programming a new language or to start learning a new framework. I usually find using Google to find API documentation is much faster then browsing a book. Tutorials on the web are usually more updated and provide useful user feedback in the comments. That's why you won't find much books at my place about programming.

I do buy books on occasion that provide me with information not available on the web. That's why I bought the book Rails Recipes. I read several positive reviews and after reading through the book myself I immediately felt like I would use it for each rails project. The book contains small 'recipes' usually not longer than 2 or 3 pages that provide snippets of code that show how an experienced Rails developer would solve a specific problem.




I own the book for two days now, and already I've learned more from it than from all the tutorials I've read. So if you know Rails already from the tutorials you've ready, but you're looking for more interesting pieces of code to read and use check out Rails Recipes.

Wednesday, November 22, 2006

WWDC Videos (2)

As of a few days ago, around 70 sessions from WWDC 2005 and WWDC 2004 have been posted on iTunes under the Foundational Sessions. This obviously answers a question I got as a comment on my previous post about the WWDC Videos:

Any mention of sessions from previous WWDCs ending up on ADC on iTunes?

Let's see what usefull resources Apple will post on iTunes after this.

Tuesday, November 07, 2006

More on SimilarTunes

Currently SimilarTunes is a very simple application to help you create playlists with somehow similar songs from your own library. After searching for an artist you set the similarity slider to the percentage of similarity of the songs and you create the playlist. To figure out how similar songs are, SimilarTunes uses several webservices like Last.fm and MusicMobs.

After posting this software on osx.iusethis.com, I received a few positive reactions. SimilarTunes was even mentioned on the MusicMobs weblog. I'm currently working on fixing one known problem: SimilarTunes only creates empty playlists for one user. I'm also working on some additional features, like adding the original artists searched for to the playlist.

Competition
There is some competition out there trying to reach the same goal, automatically create playlists with similar music:

While I use webservices based on social community input to determine similarity, most other software use properties like beat per minute count of a song to find similar music.

One particular interesting application is Tangerine recently introduced by Potion Factory. It's the only mac application in the list. Like most others it analyzes the BPM count of a song but it really adds a innovative and delicious UI.

Tuesday, October 31, 2006

WWDC Videos

Today another set of WWDC videos was posted on iTunes. The ADC on iTunes section in the iTunes Store now has two sub-sections with video's available, the Leopard Sessions from WWDC 2006 and the new WWDC 2006 Sessions. The two remaining sub-sections Scientific Poster Session Podcasts and Foundational Sessions have yet to be filled with content.

ADC on iTunesWhen I attended a session it was made clear every time the session would be recorded, either slides and sound only, or using video for the bigger sessions. At WWDC everybody was already wondering if the sessions would become available on DVD like a few years ago. In 2005 the sessions were only available as video streams the size of a stamp, with the additional disadvantage that you had to re-stream them if you wanted to view them again.

So no DVD's this year, but in my opinion an even better solution, video's on iTunes. The video's can be downloaded without DRM, and replayed over and over again.

According to the Apple developer website only Select and Premier Members can download the videos. I'm a student developer who visited the WWDC this summer, so it seems everyone who visited WWDC can download the videos too, cool!

Monday, October 30, 2006

My Software

So far I didn't create really interesting software yet. Most of the stuff I created isn't finished yet or abandoned already. However there are a few pieces of code I created which I thought were good enough to release into the wild.

Ribbit
Ribbit is a plugin for the popular Azureus bittorrent client. Ribbit takes advantage of Growl to display notifications like Download Finished.

SimilarTunes
This is my first public Cocoa application. It is a helper tool to create playlists in iTunes based on music similarity. When you enter an artist, SimilarTunes uses different webservices to find similar artists. It then shows a list of all similar artists you actually have in you music library.

Update:
My primary web server is down because of a dsl upgrade, the ISP has shut down all ports. I set up a mirror: Ribbit and SimilarTunes

Why this weblog?

Welcome to my new weblog. I won't introduce myself again, see my profile for more about me. I will tell you that I've started multiple weblogs before, none of which existed very long, but I intend to change this. So why another weblog and why do I think this one will survive?

I own a Apple Powerbook 12" for over three years now. I've always programmed, mostly using Java. Being interested in programming I had to explore the Java features of XCode. I wasn't that impressed, but I was impressed about what I could do with XCode and Objective-C. I almost instantly liked Objective-C better then Java. This eventually made me signup for an Apple Student Developer membership, with in the back of my mind the possibility to sign up for a WWDC scholarship. I did send in a WWDC scholarship application, not knowing what my chances were, but eventually a WWDC ticket showed up in my ADC library.

So this summer I made my first visit to an Apple WWDC conference!

Inspired by all the things I've seen there, I got back to the Netherlands with renewed energy to start developing new software. I'll try to keep you posted about my adventures on my journey as a cocoa developer as much as possible.

For the one or two readers that are actually reading this weblog, wondering why it's called Cocoa Pirate: I said I will post about my Cocoa adventures (Adventures -> Pirate - Thus Cocoa Pirate, lol)