LicenseKeeper User Interface Refinements

Over the last few days, as I’ve been working on the help pages. for LicenseKeeper, I’ve also taken the time to add a few minor refinements to the user interface.

The changes are primarily focused on the new status bar. One of the things I was unhappy about was how hard it was to use the splitter. With the splitter essentially being 1 pixel in width (that’s the style now a days), it was very hard to use. So adding a splitter handle to the bottom of the page helped this out. Along with this change, I took the opportunity to add the convenience “+” and gear buttons to the mix.

To round out the balance of the application I added a status bar to the right side of the application. Right now it doesn’t do anything other than give the window an aesthetic balance. I originally went with listing the registered user’s name, but found that a bit gaudy. So for now, it’ll remain empty.

Doom, Quake, NeXT and Apple

John Romero (co-founder of id) has an interesting history write up about developing DOOM and Quake on NeXT computers with John Carmack.

They even wrote their original level editors, DoomEd and QuakeEd in Objective-C! Back in 1993 this pre-Cocoa based application allowed them to edit the same DOOM levels simultaneously over their network:

In fact, with the superpower of NeXTSTEP, one of the earliest incarnations of DoomEd had Carmack in his office, me in my office, DoomEd running on both our computers and both of us editing one map together at the same time. I could see John moving entities around on my screen as I drew new walls. Shared memory spaces and distributed objects. Pure magic.

How cool is that!

found via: Tiny Subversions

Automatically Index your Help Book with Xcode

A simple way to improve your workflow and minimize human error while authoring your application’s help book is to automate the indexing of your help pages.

Xcode provides a simple way to add automated steps to your build process with shell scripts. The Help Indexer tool can be called with command line arguments via a shell script. Add these two together and you have automated help indexing as part of your normal build process.

Here is how to set this up:

1. First, find your projects build target and expand the build steps:

2. Then Control-Click on the Target and select the New Run Script Build Phase menu item.

3. In the Script Phase Editor window type the following, replacing your root help path in the script:

/Developer/Applications/Utilities/Help Indexer ~/WorkSpace/LicenseKeeper/trunk/English.lproj/LicenseKeeperHelp/

Make sure there is a space between “Help Indexer” and your help project path.

4. Close the editor, rename your new build phase to something like “Index Help” and drag it to the top of the build phase list or other appropriate spot.

5. There is no step 5.

Now whenever you build your project, your help files will be automatically indexed for use in Apple’s Help Viewer.

Building a Game Engine with Cocoa

If you are itching to learn some basic game development techniques in Cocoa on Mac OS X, O’Reilly Mac DevCenter has part 1 of a series on building a game engine with Cocoa.

Matthew Russell leads you through the development of a Lines of Action (checkers derivative) computer game. In this first part he sets up the checkers board using a custom view subclass and provides all the source code. He promises to introduce some Artificial Intelligence in a later entry when he ads a computer opponent to the mix.

If you want a deeper look into game programming with Cocoa, I wrote about a book covering similar ground on my Make Mac Games site, a little over a year ago: Cocoa Game Programming Workshop.

Update (Jan 5, 2007): Building a Game Engine with Cocoa, Part 2

LicenseKeeper Nearing Beta

Work on LicenseKeeper has been moving along very well this past month. This week I’ve reached the feature complete milestone.

All that remains before I’m ready for the first beta test phase is writing the help book, testing, working on all the e-commerce bits (store front, demo mode, registration support code, etc.).

This morning I began work on the LicenseKeeper help book. As part of this process, I’ve been taking screen shots of the user interface in various states of use. I thought I would share the one I’m currently using on the help slash page (this may change prior to release).

So here, for the first time anywhere is the first full screen shot of LicenseKeeper:

What you see in this image is the main LicenseKeeper window and the attachment viewer window. LicenseKeeper not only tracks your application and registration information, but it also retains your emailed purchase receipts, license files, and any other files you may want to store along with an application’s record.

Attachments are stored inside the LicenseKeeper’s CoreData database, safe from accidental loss or deleted email. Attachments can be exported back to disk any time you like.

Code Review

One of the major negatives to programming on your own, especially with a new language or framework, is the lack of an external input to your learning process.

Other People’s Code

I have been learning Cocoa and Objective-C for over a year part-time and on my own. I have learned enough to get by and be reasonably productive.

Recently, I finished up a full-time C# consulting contract and have been working full-time in Cocoa and Objective-C. I’ve made huge leaps forward in my understanding of Apple’s development frameworks now that I’m concentrating on one language for most of the day.

What helped the most to improve my grasp of Apple’s powerful frameworks was taking on a part-time Cocoa development contract. Aside from example code from a few outdated Cocoa books, Apple’s documentation, and a few open source projects; this was the first time I had the opportunity to view complex production-ready Cocoa source code.

The problem with proactively searching help and example code is you have to know what to search for and that you even need to look. Reviewing other people’s code gives you an insight on better ways to do the things you thought you were already doing correctly.

What do I mean? Perhaps an oversimplified Cocoa example would help.

Finding out how to log trace messages was easy. I opened up help in Xcode and searched for logging. The third entry found was “Logging Messages” showing this example:

int recNum;
NSString *recName;
/* ... */
NSLog( @"Record %d is %@", recNum, recName );

So, I’ve been calling NSLog all over the place to help track method execution and the order event messages are called. Here is how I was logging my trace messages:

- (void)foo

I had a problem. Every time I had to rename a method signature, I was having to change my NSLog trace messages. Five minutes of looking at my client’s code and I learned a new trick that will save me countless hours of time going forward when re-factoring code:

- (void)foo
	NSLog(@"%s", _cmd);

Searching through Cocoa documentation, I found references to __FUNCTION__ and __PRETTY_FUNCTION__ for C/C++ but I didn’t find anything for Objective-C. So, I moved on. Maybe, I didn’t look hard enough.

Code Review

This morning, my client sent me an email titled “code review“. “Oh no”, I thought to myself. I’m going to get fired because I’m doing something seriously wrong.

But, what I received was an incredibly generous and detailed review of the code I had written so far. Some of the comments were simple style suggestions, but the bulk of the feedback contained invaluable insights in to best practices for Cocoa Bindings and CoreData from someone who has several years of Cocoa development experience over me and a successful and selling commercial product.

I realize my client has a self-serving reason behind reviewing my code and giving me feedback. The better my code, the better his product will be. But, this feedback can not be gained working by yourself on your own code.

It’s easy to forget how important outside influence on your learning process really is. We (here I mean me) tend to think we can learn anything with a good instructional book and some example code. Up to a point, I think this is true; but having a mentor in this business is invaluable.