David S. Ackerman web cowboy (+ software development tales of the wild west…)

25Jul/110

The Curious Case of the Backwards Touchpad

There's one small change that comes with OSX 10.7 (Lion) that I'm finding fascinating from a user interface perspective: the reversal of scrolling direction with the touchpad. By default in Lion, when you move your fingers down, your view goes to the top of the page, and when you move your fingers up, your view goes to the bottom of the page.

Huh?!?!?

At first, this feels incredibly awkward, and I was thankful that there was a setting to reverse everything back to normal. I mean, of course when I move my fingers down on the touchpad, I want to go further down the page, right? Why would Apple dare change something so obvious and intuitive?

But wait a minute... the obvious way wasn't the way I scrolled on a touch surface like the iPhone or iPad and I didn't remember those feeling awkward. So I decided to experiment with leaving the reverse (back to "normal") setting off.

A few days later, and now the crazy new way of scrolling feels obvious. I suspected that it might, that it just felt odd because I was used to doing things the other way. But I didn't expect to be able to switch back and forth between old and new easily, which is what happened. I now hardly notice the change from a 10.6 default touchpad scrolling style to the 10.7 default style.

Why is that?

Well, the best I can reason is that both are pretty decent mental models. To make the "old" way feel natural, you simply imagine that the portion of a page that you see represents your field of vision, and to see more beyond the last point at the bottom, you need to move your "eyes" (via the touchpad) down. To make the "new" way feel natural, you move the virtual page instead of your virtual field of vision. So, just as you would read the bottom of a real page if you couldn't move your eyes, you push up on the "page" (via the touchpad).

You could make an argument that the "page" model is the more accurate one, as you can actually see other parts of the screen (and thus the page isn't really just out of your field of vision, but rather it's completely obscured by other elements on the page or the bottom of your monitor). If you think of it, it seems like a lot less work to push one element up in order to see the bottom of it, as opposed to pushing all the other elements down. And that's effectively what you're doing with the "old" style of scrolling.

It will be interesting to see if Apple manages to push overall change in this area. I imagine they're going to have a few things going against them: (1) the option they provided to switch back is probably easier than forcing your brain to recalibrate its expectations, (2) most people will probably mistake "habit" (or "tradition") for "natural" (it's not like we don't do this in other areas of life), and (3) the touch interface isn't directly connected to the display like it is with an iPhone or iPad. I think the last of these is why this "new" method feels odd in the first place. When the touch interface is the display, we have to construct even less of a mental model. Most of it's just there for us. With a touchpad and regular monitor, our brain has to do one extra translation step, and that's just enough to make it a challenge to switch models.

To be clear, I think both ways are completely valid and don't think that one provides a huge advantage over the other when the touch interface and viewing interface are disconnected as with a laptop or desktop. But I think it raises an important question that should be on the mind of anyone designing user interfaces: are you adapting the machine to the person, or are you counting on their ability to adapt to the machine? The former can feel frustrating and nitpicky and far more trouble than it's worth, but after you get it right, it's hard to imagine settling for the latter.

30Oct/101

Why frameworks are not a silver bullet for rapid development…

It had been a while since I'd worked on my current OSX app. The code seemed strange and unfriendly. But after a few hours of re-introducing myself to everything I'd written over the last year, I managed to find my groove again. That is, until I decided to try a new interface for one of the pieces of functionality. I'd actually done the same thing in another area of the application before, so it should be easy, right?

The coding gods were not on my side.

I was trying to simply turn a div inside a WebView into a contenteditable div. This basically meant putting:

contenteditable="true"

on the div tag. Try as I might, I could not get that content to be editable. To make it even more frustrating, copying the same generated HTML content out of my application and into a regular HTML page allowed me to edit the content I wanted to without issue.

There were no error messages. I whipped out the google-fu on "WebView contenteditable" and other variations and could find nothing. I tried explicitly setting the WebView component to be editable. Nothing.

By luck, I ended up stumbling on the following in my code:


- (BOOL)canBecomeKeyWindow {
  return YES;
}

which must have been how I made the other contenteditable area work. Sure enough, that was it. You run into problems like this often with frameworks. Simple things become incredibly difficult because you haven't flipped the right switch. You haven't flipped the right switch because no one said you had to. No one said you had to because they didn't predict you'd try to do this specific thing with the framework. But I did. And now after endless hours of frustration, I know not to make that mistake again. Onto the next one!

(297 words)

Filed under: Cocoa, Programming 1 Comment
15Feb/100

3 Essential Concepts for learning Cocoa/Objective-C

This post assumes that you know a bit about object oriented programming and one or two other object oriented languages.

One of the best ways of learning a new programming language is to look at code samples. And usually, you'll find that the structural concepts you've learned from other languages apply to the new language in such a way that you only really have to make a few syntax and naming translations and you're there. This is mainly true when learning to develop in Cocoa/Objective-C, but the more unique concepts it does use (and that the code samples often assume you know), can make the learning process a bit trickier. So, without further ado, I'm going to go over some of those concepts that turned into "aha!" moments for me and made the code samples I was looking at seem much clearer...

1. Categories, categories, categories!

Please picture a sweaty Steve Ballmer yelling this over and over and over at you. It's such a simple concept, but it's rare enough in other programming languages and used so heavily by Apple that to not know it could actually lead you towards a complete nervous breakdown while learning Cocoa/Objective-C (see above reference to Steve Ballmer). So, what's a category?

@interface NSString (MyCategory)
- (BOOL) someNewMethodThatReturnsYESorNO;
@end

Provided that you give an implementation for someNewMethodThatReturnsYESorNO, you can now call it on any NSString object. It's like re-opening a class in Ruby. As far as I know, Java doesn't have an equivalent (in Java, you'd need to subclass String and then change all of your references to create YourVersionOfString instead of just String). So using Categories for Objective-C can be quite useful for adding convenience methods onto base classes without having to change a bunch of class references (and also make it easier to shoot yourself in the foot with conflicting implementations from competing categories). But why would this be essential when learning Cocoa/Objective-C?

Enter "informal protocols". Now, current (10.6) Apple frameworks have replaced a lot of old school protocol definitions with the newer Objective-C 2.0 style @protocol syntax, but there is still a lot of sample code out there with stuff like this (taken from the NSWindow.h header of the 10.5 SDK – check out the 10.6 SDK for the @protocol version):

@interface NSObject (NSWindowDelegate)
- (BOOL) windowShouldClose:(id)sender;
@end

And Cocoa uses delegates A LOT. If you go through the various tutorials out there without understanding what a delegate really is, things will seem a bit magical. Just define this method on Object X, set it as a delegate for Object Y, and voila! Instant drag and drop! Or something like that. But this is really just a very general way to define an interface that any object can implement. And whenever you see something like the above in a header file, it suggests that you can change the behaviour of the class by adding the "delegate" methods to one of your classes and then setting that as the delegate class of the object you're looking at.

2. Bindings

Another thing you'll see a lot of in the tutorials floating around out there is "now bind your new text field to the someValue property of the selection of your NSArrayController and you're done!" Huh? This is all wonderful if what you're trying to do never falls that far from what the tutorial is showing you, but how many times does that actually happen?

Well, first of all, believe it or not, you won't often find yourself needing more than an NSObjectController, NSArrayController, or NSTreeController, and the closer you stick to using these, the better off you'll be in the long run. Basically, ask yourself if you're going to be working with a single value, a list of values, or a hierarchy of values, and then choose the corresponding controller in Interface Builder to bridge the gap. You bind the controller to a property of some object in your code and then you bind the interface element to the controller. The controller then mediates between the GUI and all the ugly internals of your application.

But how do I tell the controller that my object's value has changed so that it can then update the GUI component? Well, you don't really have to, as long as you've followed all of Apple's key-value coding admonitions (i.e. made sure that your properties are Key Value Observing Compliant). This gets done by default when you use @property declarations to define the object properties you're binding to and when you use @synthesize or @dynamic to generate the getter and setter methods in your object implementation. Really, all this does is make sure that you call willChangeValueForKey: before changing the actual property value and didChangeValueForKey: after. It's these methods that inform the controller that it needs to update the GUI component. But as long as you're key value observing compliant, you don't really have to know that.

Note that, until you "get" working with bindings, you'll probably find the use of Interface Builder very frustrating. "Just show me how to set this stuff up without IB and I'll do it by hand!" Unless you've used the Mediator pattern at some other point and recognize that this is that same pattern under a different name, and that the extra work you go through to keep your GUI and your data model in sync via this pattern is more than made up for by the time you'll save keeping multiple components in sync or switching GUI components in and out.

3. Responder Chains

There's this thing called a First Responder that you'll see when you create an interface builder file (aka XIB or NIB). And you'll often run into tutorials telling you to hook a menu item or a button up to the "First Responder" object in your interface builder file and then define a method somewhere else deep in your code and you'll find that somehow that method gets called when you click the menu item even though you didn't make this connection explicitly. More magic?

Well, as usual, what looks like magic is something pretty simple if you look closer. Check out Apple's Event Handling Guide for a more in depth explanation (particularly the "Responder Chain for Action Messages" section). But basically, what's happening is that, by default, the "first responder" is the GUI element that either has keyboard focus or is being operated on via the mouse, and when you click the menu item, the Cocoa framework is going to check if you've got the appropriate method defined on the implementation of that GUI element. It might also check that element's delegate if it has one. Then it checks the window object, then the window's delegate, then the application object, then the application's delegate, basically working its way up through successive containers of the object where the event actually occurred. Defining the necessary method at any point along that chain allows that particular object to handle it.

This can be made even more interesting when you use the setNextResponder: method of any NSResponder in the chain. Using this method, you can effectively insert your own objects into the chain to help make your code more intuitive.

Conclusion

This is by no means meant to be an exhaustive description of categories, bindings, and responder chains. Books devote full chapters to concepts like these. However, if you're at the point where you just want enough understanding to make some of the Cocoa/Objective-C code examples you'll see seem less like Voodoo magic and more like what you see in other languages and frameworks, I hope this provided a bit of enlightenment. As with anything else, it'll always be imperfect, so if you have questions, comments, or corrections, please let me know, and I'll update it accordingly.

Filed under: Cocoa No Comments
1Dec/090

Applying Cocoa patterns to Javascript

Before Nexopia, most of my coding experience was writing enterprise-style applications in Java. I had done a lot of website stuff on the side, but nothing all that complex. Removing the languages from the equation, these are two very different styles of development. The main hurdle I find, in coming from developing desktop applications, is that GET/POST wall. It seems to break down a lot of patterns that work great with desktop apps. So I've done my best to leave my "desktop app" brain behind and start thinking in "web". And for the most part, that's been for the best. Recently, though, I've been re-learning my desktop dev skills via Cocoa and Objective-C and found I was able to apply them to some Nexopia problems! This makes sense, as we're doing a lot more ajax and client-side stuff these days, which tends to feel more like regular application development. So, without further ado, here are some of the ideas I've moved over into our framework:

1. Events

NexopiaPanels (the ones you see whenever you create or edit a new block) are getting a real event system, thanks mainly to YUI! So, instead of creating a panel subclass or trying to attach various custom hooks into the panels, you can "subscribe" to one of 4 events: there's one that fires after the panel opens, one that fires after it saves, one that fires after it closes, and one that fires whenever a new panel is created (this last one is especially useful when dealing with unpredictable javascript loading orders between modules).

A great way to attach one of these listeners is by putting another minion on the same element that is opening the panel:

minion_name="async_panel some_other_initialization"

and then using:

NexopiaPanel.onSave(element, handler_function)

in your load handler for "some_other_initialization". You don't have to worry about whether the panel gets created before your load handler is called or not. If the panel hasn't been created, this method just sets up a listener that waits for you and attaches the handler function to the panel associated with that element when everything's ready.

2. Notification Centers

So, listening to "saved", "closed", etc. events on panels is great for a lot of things, but what if you're not sure where an event is going to come from? That's where NotificationCenters come in. Apple uses them heavily, and I'm using a very stripped down version. It uses YUI CustomEvents behind the scenes. Basically, in one area of the code, I call:

NotificationCenter.defaultNotificationCenter.subsc​ribe(event_name, event_handler)

Just as before, we're passing in a function as the event_handler which will get run when the even occurs. But unlike before, we're just registering for a particular event to occur from anywhere on the page. Somewhere else in the code, we call:

NotificationCenter.defaultNotificationCenter.fire(​event_name, event_info_hash)

where event_name is that event that we're listening for and event_info_hash is a hash of information that our listener might be interested in. This could be something about the object that is firing the event or anything else really.

Thus the only coupling we have is to do with the event_info_hash contents. Yes, if they change in one area, we would have to make sure all of the areas of the code that listen for those events are appropriately updated, but I don't see a way around it, and it's better than the alternatives - what those alternatives are, I'm not sure, but I think they involve going down a dark road of one-off hackery that's probably a lot more brittle.

3. Last but not least: Delegates!

This is another one I borrowed that is used heavily in Cocoa. It takes a bit to get used to in coming from the Java world where you try to subclass everything in order to bend it to your will. A delegate is just an object that another object defers some functionality to. And they come in handy when you want the low-coupling of a listener, but need to interact with the results of the custom code.

Back to NexopiaPanels, there was another area where we were doing a lot of one-off solutions. Suppose you want to stop a panel from opening based on some custom validation code. Or suppose you want to stop it from saving based on some custom validation code. Listeners and NotifcationCenters are fire-and-forget. So to solve this one, I'm adding the ability to set a delegate on a NexopiaPanel. As with the listeners, there are convenience methods so you don't have to worry about initialization order:

NexopiaPanel.setDelegate(summoning_element, delegate)

The delegate can define however many supported functions it wants, and where those functions are defined, we will defer to it. Right now, I have only two:

validateBeforeOpen
validateBeforePostAndClose

Each passes the inner form of the panel (if it exists) as an argument. If they return true, the panel proceeds as usual. But if validateBeforeOpen returns false, the panel won't open, and if validateBeforePostAndClose returns false, the panel won't save and won't close. This way, we can make very custom validation logic for a particular panel without having to subclass it (which is messy anyway in javascript).

That's all folks. Back to your regular programming!

Filed under: Cocoa, Javascript No Comments