The Axamblis Blog » User Interface
Developing Software is an Art.
Cocoa — Wednesday, November 11, 2009 4:27

F-Script: The Ultimate Debugging Console

Have you ever heard of F-Script? If you are a Cocoa developer I honestly hope you do. For those of you who haven’t, F-Script is supposed to be “A set of open source tools that complement Xcode and Interface Builder” that provide “Interactive introspection, manipulation and scripting of Cocoa objects”. So its a bunch of tools that allow you to interact with Objective-C and Cocoa during runtime through its own scripting mechanism, whose syntax differs significantly from the Objective-C language. So the line of source code…

1
MyClass * var = [[MyClass alloc] initWithName:@"John"];

is written like the following in F-Script:

1
var := MyClass alloc initWithName:'John'

If you download F-Script from www.fscript.org you end up with a bundle full of source code, executables and useful information. The most important are F-Script.app, FScript.framework and Extras/F-Script Anywhere.

Exploring Cocoa

The first file I mentioned — F-Script.app — is the toolchain in its simplest form: A script interpreter console. So what you can do is write your script lines to the console which will then be executed by the F-Script interpreter. For example: Writing the script line

1
NSApplication sharedApplication terminate:nil

will make the application quit. But more interestingly, it gives you access to everything that is currently loaded into the Objective-C runtime. So you may create a window and populate it with UI through the F-Script console. Everything you can do from code in Xcode, you can do in F-Script through the console.

Debug Your Application

The second file — FScript.framework — is the most important one for developers. As you might guess, it is a framework that bundles all the F-Script functionality. If you’re writing a Cocoa application, add FScript.framework to your project and link against it. Somewhere in your loading code, insert the line

1
[[NSApp mainMenu] addItem:[[[FScriptMenuItem alloc] init] autorelease]];

to add the F-Script menu to your main menu bar. What this gives you is a complete and immensly powerful scripting environment that is available to you at runtime. When you launch your app, go to the “F-Script” menu and choose “Show Console”. A new script interpreter will pop up ready to execute input from you through which you have access to all your objects: If your app has a controller object assigned as the app’s delegate, enter

1
controller := NSApplication sharedApplication delegate

to assign the object to the controller script variable. So if your controller features the method -makeNoise, you can go ahead and hack

1
controller makeNoise

into the script console and BOOM, your method gets called. What can you use this for? Obviously there’s no point in calling methods from the console that can also be executed through the press of a UI button. But if you’re developing a huge application that has some very complex functionality at its core, you’re very likely to end up with the situation that your core functionality is written and needs debugging, but lacking a user interface your app is not ready to take advantage of its core. Nevertheless you would like to debug the core you’ve written without having to go through the hassle of UI design yet. This is where F-Script comes in really handy. Launch the app, open the F-Script console and start debuggin your core! It’s all there right at your fingertips, ready to be thoroughly tested and evaluated, checked for bugs and all the other nasty app-killers.

That’s exactly what I did with Artifica today. Obviously writing a user interface for an application with the complexity of an image editor is no easy task and introduces a completely new source of bugs to your application. Therefore, I wrote the layer architecture from A to Z with the only testing UI available being a NSView that draws the final result of the layer rendering. As usually, after finishing the layering mechanism and launching the app for a try, everything stayed gray and empty. Bug. So I thought about the best way of debuggin the app. Writing some debugging code that created layers somewhere in the launch code of the app? Nah… that’s kind of lame and not very efficient. That was when I remembered F-Script. So I went to the website, grabbed my copy of it and added the framework and menu item to my app. And suddenly I was able to conduct the most thorough testing of my layers without having to create some testing UI for doing so. But not only does F-Script serve as a replacement for UI, it is also very useful for debugging. If you set one of your layer’s properties for example and nothing changes on the final result, you can use F-Script to inspect the layer object and look for where your updating mechanism broke down.

F-Script adds an invaluable means of debugging to your application. Things that were very uncomfortable to do beforehand, now are easy and fast. And if you have some frequently used object, for example your controller object, all you have to do is simply call

1
2
FSInterpreter * interpreter = [[fscriptMenuItem interpreterView] interpreter];
[interpreter setObject:[NSApp delegate] forIdentifier:@"controller"];

with fscriptMenuItem being the FScriptMenuItem you added to the main menu before. This line will assign your app’s delegate to the “controller” script variable which you may then use during debugging to directly access your controller object.

Code Injection

The third important part of the tools is the F-Script Anywhere application. What this application does is that it allows you to inject F-Script into running Cocoa applications. When you do that, the running application gets a “F-Script” menu item which gives you a means to inspect and experiment with that app through the console and object browser. This technique is very useful if you want to know how some of the private APIs work or just want to know how another application is structured.

F-Script saves the Day

Being very robust and extremely powerful, F-Script is the ultimate tool for debuggin, inspecting or hacking other applications. As a developer, the most valuable thing you can do with F-Script is to include the framework into your application and use the console and object browser for debugging. It saves you hours of debugging hassle since you don’t have to return to your source code and recompile everytime you want to check whether some operation returned a valid value. But most of all, you don’t have to write any specific debuggin code to your app except the creation of the menu item and maybe the declaration of the most important objects in the F-Script namespace for easy access.

If it weren’t for F-Script, I would have spent 5 hours today writing debugging code and creating some testing UI for Artifica which would have been another source for bugs which increases complexity of the debugging process again. F-Script gives you the possibility to completely split up the development of your object model and your view model, which not only saves you a lot of time and is more productive, but is also less frustrating since you never have to go figure whether your app’s functionality is broken due to a bug in the UI, the object model or even worse, somewhere in between.

— — —

Thanks for reading and enjoy coding with F-Script! It really is worth the 20 minutes of getting used to the scripting syntax!
Cheers

Artifica — Tuesday, November 10, 2009 16:01

Accessibility for Noobs* and Pros**

* short for “Newbies” — ** short for “Professionals”

Depending on what kind of application you write you end up having to deal with the more or less complex task of making the software attractive to a wide range of users. If you develop a Twitter client, there’s literally only one group of users: those who want to Twitter. Every user wants to be able to write a Tweet, read those of others and maybe view the Tweets where he was mentioned. There’s no feature that would overburdern the average user’s computer skills.

The Problem

Unfortunately, the genre of image editing software is probably the one featuring the widest range of users: There is the average user that knows what an aperture is and how a camera takes a picture, which wants to retouch his pictures exposure and color tones. Then there’s the user whose only concern is the size and weight of the camera when he’s buying one. He wants to have one button in his image editor which adjusts exposure and color tones automatically. And last but not least, there’s the professional ultra-skilled über-user which has a thorough understanding of everything from the architecture of the camera’s CCD sensor up to the background layer architecture and image data processing of his image editor. How do you make the app attractive to all these types of users?

Solving this problem is like designing an aircraft which a child can fly from Zürich to New York and a fighter pilot can do the wildest air acrobatics with, yet both immediately feel comfortable and in control when sitting in its cockpit. So how do you prevent the child from turning off the autopilot accidently but not have the pilot to go through 20 layers of security before granting him full control over the bird?

This is exactly the problem I’m working on at the moment. The layer architecture of Artifica (yes, the app has been named) as intend to engineer it is of a complexity never seen before. Drawing one layer incorporates the evaluation of 5 filters and about 10 intermediate drawing steps, user filters not included. The newbie might probably not even want to get in touch with layers in general. On the other hand, the professional user might not only want to use layers, but also access and adjust certain steps of the layer rendering process. Take filters for example. There are three points in the layer rendering process where a user might want to add a filter to the color channel: At the beginning on the color information of the layer, in the middle after the sublayers have been rendered onto the color information, and at the end when the layer is through the masking process. Adding a blur filter yields to different results at each of these points.

The possible Solution

Fortunately, almost all users have one thing in common: They like tidy and functional user interfaces. A professional user will probably not complain about having to click a button to bring up the powerful controls he might want to use on an image. He’s thankful if that control doesn’t pop up everytime he opens an image: He might only want to look at the image, crop it, or just hit the “auto-adjust exposer and lighting (noobs only)” button!

So there goes the partial solution: Making only a very small part of the functionality available through the interface that is presented to the user whenever an image is opened. So there might be a window for color controls which actually adds an image filter in the background and provides an opaque way of modifying it. No layer lists, no complicated tools, nothing. But the more advanced user mustn’t have to click more than one button, one menu item to bring up the layer list and advanced tools. Maybe the app should try to guess the user’s intentions. And by that, I don’t mean the Microsoft way of guessing what the user wants (because they’re in 99% of the cases completely wrong about it). If the user opens an image, the layering and everything is deactivated. As soon as the user chooses anything from “Add Layer…” in the menu down to the “Select Layer” tool, the layering should automatically be enabled.

Of course, as always when doing this kind of automated censorship, you should give your more advanced users the opportunity to get rid of it. So if a user knows, in two out of three images I open with Artifica I intend to do some layer work, he should be able to set a “Always Enable Layering” option globally for the app.

The clue here is…

…to make your app attractive to all user groups. A newbie should not be discouraged by unnecessary buttons or complicated lists when he opens an image. The advanced user should be pleased by the apps simplicity but must have access to the full functionality just one (or with some good guesswork of the app, zero) clicks away. The app should hide everything complicated from the first glance of a newbie at the app, but should not exclude him from the higher functionality. As soon as he starts to tamper around with the “Layers” menu, he also has to face the consequences of the layering mechanism being enabled and adding some complexity to the usage of the app.

These are my thoughts on complexity and accessibility of applications. Unfortunately, not all other application developers go through this kind of process, planning their UI. In Photoshop or Word, you’re pretty much confronted with a ton of functionality that you either don’t need or don’t understand as a beginner. There should be no fixed complexity, but a very dynamic system of reveiling functionality to your users depending on his needs. Start simple, with the option of exploring the app yourself and eventually ticking the “immediately start on complexity level 2″ preference if the user feels like he always needs to be presented with a certain basic functionality and usage complexity.

— — —

Thanks for reading, as always, comments are very welcome :)

Take care.

Axamblis Developer Podcast — Friday, September 18, 2009 19:48

Episode 1: SplitView-aligned Toolbar

 

» Download the episode

This is the very first episode of the Axamblis Developer Podcast. We’re looking at how to create a custom NSToolbar which aligns a subset of its items along the right side of a split view divider in the same window. This behaviour which makes the items feel like they stick to the divider can also be found in other apps like Apple Mail or Espresso (my favourite web editor, by the way).

SplitView-aligned Toolbar

In order to get the desired bevaviour we make use of some undocumented API in the NSToolbar class, and we use method swizzling to inject some custom code into the NSToolbarFlexibleSpaceItem class.

The category used for swizzling methods:

The project file (Xcode 3.1 and higher) as well as the .h and .m files:

Enjoy the show and drop me a line if you have any comments or questions or other feedback!