Using Cappuccino to build the MemoryMiner Web Viewer
When I first started working on MemoryMiner in December 2004, I had completely had it with building web applications. I’d spent the prior 8 years creating a sophisticated and completely web-based Digital Asset Management system using great server-side technology from NeXT/Apple called WebObjects. Being able to deploy our app from day one as a hosted-service was huge, but there was only so much you could do to make a web application come close to what was possible, user-experience wise, on the desktop. I was therefore utterly thrilled to work full-time with Cocoa, especially since I was completely familiar with its precursor from my days working on NeXTSTEP applications.
Still, the web is critically important for a project like MemoryMiner, and it has been this part of the adventure with which I’ve most struggled. From version 1.0 onwards, MemoryMiner for the Mac has been able to publish sets of annotated photos to the web using a self-contained story viewer. The first two versions were done in Flash (by someone else), and while they worked OK what amazed me was how much effort it took to do something that I thought should have been easy, namely to read an XML file with descriptive data about a bunch of photos and display them in a coherent, pleasing fashion.
Flash has its origins as tool for creating animated content. Tools for building applications using Flash came about much later in its evolution and weren’t available in 2005/2006. If you wanted to create 2D shapes and tween them about a stage, no problem. If you needed a scroll view to display a number of thumbnail images, then it was roll your own from scratch or license somebody else’s code. There were quite a number of different UI widget sets available, but all came with a different look and feel, and none of them really felt right compared to what one was used to on the desktop. Still, back in 2006, given the sorry state of Javascript performance in browsers and the lack of coherent libraries, Flash was the better choice.
Here’s an example of the Flash-based Web Wiewer:
Fast-forward a year and a half and the techniques of web development have improved dramatically as Javascript libraries such as Prototype and Scriptaculous came on the scene. I decided to try creating a new web viewer that didn’t need Flash. A big reason I wanted to ditch Flash was that the performance on the Mac was lousy. Prototype did a nice job of hiding some of the inconsistencies between the different browsers, while filling in a bunch of holes in the Javascript language. However, to do anything fancy UI wise, you have to devote a considerable amount of time learning the ins and outs of CSS. While indeed extremely powerful, it just wasn’t something that I, as a desktop application developer, ever really wanted to deal with.
Beyond styling, even basic behaviors such as having an image resize proportionally and remain anchored while the browser window is resized was maddening. Was I asking for too much? I could never get it to work consistently across IE/Firefox/WebKit, so I just gave up. On the plus side, the general performance was quite good (loading time, CPU usage). Still, it bugged the crap out of me that doing the most basic things proved so difficult.
Here’s an example of the Javascript-based Web Wiewer:
Fast-forward another year or so, and I hear about this web application called 280Slides and the Cappuccino framework used to create it. Playing with that app the first time was a revelation. I almost wept the first time that I started looking under the hood: the APIs and code syntax were immediately familiar to me as a Cocoa developer. I knew I could leverage a lot of know-how, and maybe even some code.
As soon as Cappuccino was made available to the general public, I started experimenting. How do you display an image using Cappuccino? You create a CPImageView instance and call setImage: passing it your CPImage instance. Works for me (and probably causes “traditional” web developers to roll their eyes). As a first experiment, I made a test app with the idea of creating a simplified version of the image annotation view I use in MemoryMiner for the desktop. I actually just started copying and pasting Obj-C code into a text editor, changing the class prefixes (i.e. NSImage becomes CPImage) and getting rid of pointers (e.g. NSImage *myImage becomes var myImage). Pretty soon, I had a view that could display a photo as well as draw selection markers (ummmm, drawRect:). Amazingly enough when I resized the browser window, things just worked. I didn’t write a line of CSS, I didn’t have to do one thing in FF/WebKit and something else in IE. This is what I was looking for!
By late Spring of 2009, I was pretty addicted, so I kept going with my prototype, adding the ability to create and edit selection markers, add captions to them and persist my model objects via a RESTful Rails back end. Mapping? Easy. There’s MapKit for that, along with a growing selection of high-quality third party code. Community? Got that as well. Among Cappuccino developers, I’ve found the same willingness to help each other out as we all strive for excellence.
This past fall, by the time I had mostly finished the development of MemoryMiner 2 for Mac, I spent about 2 person weeks finishing up on the MemoryMiner web viewer. When I was done, the biggest problem I had was that the deployment footprint of a Cappuccino application is quite a bit bigger than using something like jQuery or other javascript libraries. This is largely due to the fact that Cappuccino is designed for creating Applications, so you get a ton of functionality such as Undo, Key-Value Observation, etc. along with sophisticated UI widgets that you may not need in a read-only viewer such as I was building.
In order to get the initial load time to where I needed it to be, I created a single application that I host on a small slicehost instance, with the web server configured to automatically compress all the .j (Objective-J) files in my application. Between the compression, and the image spiriting techniques that were introduced late last year, I’m pretty happy with the load speed. It could certainly be made faster by eliminating some of the unused code and image sprite data, and I’m confident that this, or other optimizations will be made. All you have to do is take note of the progress made by a tiny team in a rather short period of time.
Best of all, unlike the old system where each web viewer instance had all the code needed to display the content in the same folder as the content itself, the new system works by simply redirecting to the hosted web viewer app’s URL, passing the published RSS feed as a variable in the redirect URL. This means that once a user looks at their first published MemoryMiner viewer, any subsequent loading of any other story viewer will have the viewer code already in the browser’s local cache. Improvements made need only be made once in one place, just like in the “good old days” at my prior company.
Here’s an example of the Cappuccino-based web viewer:
While my first publicly shipping Cappuccino project is a read-only viewer, I’ve been working on a full-blown version of MemoryMiner for the web. It’s currently in early Alpha testing, and the feedback thus far has been extremely positive. The viewer and the app actually share a fair amount of code. Most importantly, both use the same Model View Controller design patterns we all know and love. My MMSSelectionMarker class in Cappuccino is virtually the same as its cousin on the desktop: the main difference is that one is persisted in a local sqlite database, the other in a web-service. Believe it or not, I’ve become pretty comfortable moving code back and forth between desktop and web. I implemented undo using Cappuccino before doing the same in Cocoa.
Still, compared to developing with Xcode & Interface Builder, developing a Cappuccino app still feels a bit primitive Fortunately, as Cappuccino has matured, it has been getting better tools, such as 280Atlas which lets you compose your UI layer graphically using real “freeze dried” objects that connect to each other using the familiar control-click and drag mechanism just like on the desktop It’s essentially IB and Xcode mixed together.
For whatever reason, people can easily get into flame-wars about web apps vs. desktop apps, and this toolkit vs. that toolkit. For my part, I really don’t care. I want MemoryMiner to be a person-centric application. Generally speaking, people want to interact their stuff on whatever device they happen to be using. I’ve found that Obj-C/Obj-J and Cocoa/Cappuccino give me lots of leverage because of the dynamic nature of the language, the richness of the frameworks and the availability of quality third party code. Others will say the same thing about Java/C#/Ruby/Python, etc. etc. To each their own, but if you’re a Cocoa developer and care at all about the web, you’d be crazy not to give Cappuccino a serious look.
July 9th, 2010 at 4:36 pm
[…] already written about using the Cappuccino framework to create the current generation of the web viewer. One of the great benefits of using this […]
November 16th, 2010 at 4:57 pm
Great story I did almost the same way while I searched the right tool for developing web apps. I found the Cappuccino framework on the other day and I was deeply impressed – it looks the perfect tool to make a complex web application GUI.
October 20th, 2011 at 11:18 pm
[…] Using Cappuccino to build the MemoryMiner Web Viewer […]