Posted in: Flash
I highly recommend that you write it with a friend. Sometimes the only thing that keeps me writing is the guilt I feel knowing that Juan is working and I am not. Well, that and emails like this:
![]() |
Posted in: General
Check out this post by Ian Beck, the guy that put together the Things screencast and TagaMac. The post is full of great info on most of the available GTD applciations available for Mac, and the rest of his blog is outstanding too!
Posted in: General
I woke up last Saturday morning to find that the OmniGroup had finally opened a public beta of their long-awaited OmniFocus application. Oh, man, I was excited! OmniFocus is designed to be a GTD (David Allen’s Getting Things Done) trusted system for collecting and organizing your tasks so you can, um, well, get things done. The teasing screen-casts and feature lists have made it look like it’s going to be way better than the current version of iGTD, or any other GTD tool available right now. I sent out half-a-dozen emails to friends to tell them the great news, then watched the latest screen-cast before anxiously downloading the app. I spent an hour or so manually importing all of my tasks, projects and contexts from iGTD. It was a little tedious, but what a refreshing way to interact with my tasks! It has a nice clean interface, reasonably intuitive input methods, and a few new powerful paradigms (which we’ll get into later). It doesn’t get any better than this… or does it?
A week later, a friend and co-worker announced via Twitter that he was going to start messing with iGTD and learn that until he could get his hands on Things. What the hell is Things, I thought? I googled and found this beautiful CulturedCode website. How could I have missed this? My heart sank. I’d just spent the last week falling in love with OmniFocus, and now here’s this sexy young Thing flirting with me, and testing my loyalty. While no one was looking, I clicked the Get Preview button at the top of the page. The link merely took to me to the bottom of the page where I could enter my email address and be among the first to try the upcoming beta once it’s available. Damn it. Then I found the Things screen-cast. I watched skeptically, hoping to find some fatal flaw in Things so I could rest easy knowing that OmniFocus was still a superior solution; hoping not to see a slew of Things-only features that I’d be dying to try, thus starting another long wait for a beta release.
Obviously, I was biased, but I did indeed find [what I thought to be] a fatal flaw in Things. Where the hell are contexts?! The guy on the screen-cast seemed to spend an awful lot of time organizing his tasks into projects (cool) and areas (huh?), and then dragging them around and prioritizing them into today, someday and postponed categories. I am not a GTD expert, but this doesn’t seem very GTD to me. When I create tasks with a GTD system, I very rarely enter due-dates, let alone start-dates. I create them and assign them a context. That way when I’m in that particular context I can figure out what I should be doing Right Now, not Today, Someday, or Maybe Never. The more I thought about it, the more worked up I got. I thought maybe I had incorrectly assumed that Things was a GTD tool, when actually it was intended to be just a killer to-do list application. I restarted the screen-cast, and listened closely. Dude definitely said "GTD". Hmm…? Am I missing something? I emailed CulturedCode and diplomatically explained my concern about there seeming to be no support for contexts, and too much emphasis on prioritizing tasks.
I got a very prompt response from someone named Jürgen explaining that Ian, the guy that did the screen-cast, is not a typical GTD user, and he agreed that the screen-cast put emphasis on certain aspects of Things that might be misleading. He further explained that the using the Today list is optional, but provides a way for people (like him) with a ton of to-dos to some broad-sweep prioritization. That’s cool, I can dig that. In my email to him I asked if users were expected to "create a notion of context using the tags in Things". His response really cleared things up, so here it is:
If you are just using contexts then you can simply think tag = context. You don’t have to ‘"create a notion" of contexts using tags. It just works like contexts should work. But if you are interested in implementing what David Allen describes in Chapter 9 "Doing: Making Best Action Choices" then you can do that as well. In Chapter 9 he describes the "Four-Criteria Model for Choosing Actions in the Moment". Those criteria consists of "Context", "Time available", "Energy available", and "Priority". The beauty is, you don’t have to use those. There is no input form that requires you to enter such stuff, no empty columns when you don’t. But these options are readily available if the user so desires. In that respect, I think we are even closer to the book than many other apps, but we let users decide whether they want to make use of those options.
At this point, I’ve calmed down from when I wrote the email and would be feeling like a bit of a jerk for sending it, except that along with his response, Jürgen also sent me an invitation to the pre-release beta. Sweet. I replied to Jûrgen to thank him for the clarification and the pre-release invitation, and told him I’d be happy to manage two GTD systems in my ongoing quest to find the [near] perfect trusted system.
So, I’ve told you all of this to share with you my experience of OmniFocus vs. Things, now that I’ve used them both.
And in this corner…
Disclaimers:
- Things is not done. I mean, OmniFocus isn’t either, but Things isn’t as far along as OmniFocus (I don’t think).
- I’ve only used Things for a couple of days, and OmniFocus for a little over a week, so I haven’t had a chance to touch all the features of either system.
Round 1: Creating/Editing Tasks (in the application)
OmniFocus
Adding new tasks in OmniFocus is a lot like creating an outline using OmniOutliner (go figure). It’s like you’re creating a to-do list as a single document, which makes sense, but this actually feels really strange to me. Pressing Cmd+N creates a whole new OmniFocus window, not a new task, which was really confusing. Instead you press enter while one task is focused to create another. There’s not a really intuitive way to just say "create new task". Also, one way to remove a task is by deleting all the characters in the description (as you might expect you could do if you were editing an outline), but it’s really easy to push delete too many times and delete half the description of previous task. You can also remove a task by selecting the task, and pressing delete. The trick here is selecting a task without also focusing the description field (it depends where on the task your mouse is when you click). If the description field is focused, pressing delete will just backspace the characters in your description. All in all, I found entering tasks in OmniFocus to be rather kludgy; not better than iGTD, just quirky in different ways.
Things
Hey, this makes sense! Cmd+N gets me a new blank task or I can click a New Task button at the bottom. Once I fill out the mini task form (which appears right inline), and press return, I get another blank task. Cool. It was so much easier to migrate all of my tasks into Things than it was into OmniOut…err OmniFocus. To remove a task, I click on it (anywhere) to select it and press delete, or drag it to the trash can. To edit it, I double click it and I get the same mini form I got when I created it. Simple.
Winner: Things, obviously
Round 2: Creating New Tasks (with quick entry)
While iGTD had QuickSilver integration, both OmniFocus and Things have their own globally accessible quick entry dialogs.
OmniFocus
With OmniFocus you can create more than one entry at a time. Type in the description, and optional context and project, press return and you’ll get a blank line on which you can create another task. Create as many as you’d like, and then click save (or press Cmd+S) to save them and close the window. This is pretty slick. If you don’t like having to save, you can adjust the OmniFocus preferences so that return also invokes save. But, beware, if return invokes save, there’s no way to enter more than one task in the quick entry dialog, at least not that I can figure out.
Things
The Things quick entry dialog looks nicer. It’s stylized more like what I might expect a HUD to look like, and not just another system-chromed window. But, it only lets you enter one task at a time. You get to choose where your task goes: inbox, project, etc., which is pretty cool, I suppose.
Winner: OmniFocus, multiple tasks at once is pretty handy.
Round 3: Organizing Tasks
A mile-long to-do list is intimidating, it’s good to keep them organized.
OmniFocus
Tasks in OmniFocus either live in your inbox or in your library. It’s as simple as that. Your library can subdivided using folders and projects. Folders can have other folders or projects. Projects have tasks, which can have sub-tasks. Suffice it to say you can go wild here organizing your tasks. A project is only a project if it lives in your library. As far as I can tell, that’s the only thing that distinguishes it from a task with sub-tasks. I had to mess around a bit before I came up with a good system for my stuff, and found myself wanting to add sub-projects to projects in the library, but having to use folders instead. Also, getting a hold of a task and dragging it around to the correct project or folder or whatever, is sorta tricky… it’s another symptom of the document-ness of the lists… it’s way to easy to select and focus the description field. I find myself clicking-and-holding the check box on a task so that I can get a hold of it, which is really counter intuitive.
Things
Things lets you put tasks into projects or areas [of responsibility]. I didn’t understand this at first, but then I realized I had effectively tried to use the notion of areas of responsibilities in OmniFocus. I had created some projects in a folder called "Personal" that are kind of on-going projects. Projects like, finance, household, travel, etc. This is exactly what areas are for. Projects can then be assigned an area of responsibility, though I really had to hunt around to figure out how to do this. You have to click on top-level Project link under Organize. From there you can drag the projects into an Area. I’d love to see a more discoverable way to do this. Maybe there’s an inspector for a project that allows me to choose what area it belongs to.
Winner: Things, while not as powerful, I find the simplicity of this refreshing. I was having anxiety with OmniFocus because I could have organized my tasks hundreds of different ways.
Round 4: Assigning Contexts, Priority, Energy available, Time available
Tasks are more useful with some important meta-data
OmniFocus
OmniFocus comes with several pre-defined contexts, and I only had to add a couple to suit my needs. It supports nested contexts, which I find really handy. Many of my tasks classify as errands, but some of them are specific to a certain store (usually Target). With OmniFocus I can assign somethings to Errands and some to Errands:Target. If I’m going directly to Target, I’ll just look at what’s in Errands:Target, but if I’m going out to run errands, which might include a Target run, I’ll check out everything in Errands. Assigning these context to tasks with the auto-complete gadget in OmniFocus is a breeze. Nice work guys! Now, what about the other stuff like priority? Well, I can flag a task, but I don’t see support for much more. Admittedly, I don’t often use any thing other than context, though I messed around a bit with priority in iGTD.
Things
Jürgen told me that tag support was developed for Things so that we could assign context, priority, energy available, time available, or any combination thereof. If you don’t use some of these, don’t use ‘em, and they’ll never be there to bother you or clutter your interface. That sounds sorta nice, right? I’m not so sure. You can have nested tags in Things, which is sorta like nested contexts in OmniFocus, but that structure doesn’t live through the rest of the application. For example, when I choose a tag for a task, there’s no indication that Target is a sub-tag of the Errand tag. Weird. There is also no differentiation between a priority tag and a context tag. Maybe I got carried away when I defined my contexts in OmniFocus but I like the work flow it afforded me. I’m still not sold on tags for everything. It feels a bit too one-size-fits-all for me.
Winner: OmniFocus, even though it doesn’t support stuff other than context, I like it being more structured
Round 5: Doing Something
When I’m not capturing tasks, I use a GTD system to figure out what I should be doing, naturally.
OmniFocus
OmniFocus has introduced an idea I’ve never seen in a GTD system. There are two discrete modes in the application: one for planning and one for doing. I actually like this. In the doing mode, I see a hierarchal list of my contexts, and I simply choose the context I have access to right now, and look at what I should be doing. If I select the Errands context, I see a list of my general errands and the items in my sub-contexts of Target and Safeway. If I click on Target, I see my Target errands. OmniFocus fell short in the last round in being able to prioritize things, but once I have a list of things to do in a given context, I can do some quick ad-hoc prioritization… though, it might be nice to do a little more with the items in the list. I guess I could flag them.
Things
I’ll tell you right now that Things is going to lose this round. The only place I can see a comprehensive list of my tasks is to select the Next focus, and I only see them all here because I’ve not moved any of them into a different focus like Today or Someday. When looking at the list in the Next focus, my tasks are sub-categorized by project and areas, but not in a way that I can distinguish projects from areas. "Send out christmas cards" is a project that in an area called "Friends / Family". The tasks within it show up under the Send out.. project, and not in the Friends/Family area. I’m so confused. Ok, forget it, seeing a comprehensive list isn’t really what I want to do right now anyway, I want to see what errands to run. I guess the only way to see tasks with the errands tag is to use the search input. I type in "errands". I see things I’ve tagged errands, but not my Target or Safeway tasks. Apparently giving something a tag does not implicitly assign it the parent tag of the one I just picked. Weak. Forget that too… I’m going to Target and then to Safeway. Crap. I can’t enter more than one tag in the search field, and if I could, I wouldn’t know if it would show me tasks that had both tags or had one or the other. I can’t really trust that I’m seeing enough tasks here to make an informed decision. This seems like a fatal flaw.
Winner: OmniFocus, far from perfect, but at least I can see the tasks I so painfully entered previously.
The results
There is no winner here, which sucks. One system does well what the other one doesn’t, at least for how I want to use a GTD system. I guess I’ll keep tracking them both. Just between us, I’m hoping that Things shapes up and costs less than $80. It’s got a lot of potential, and a better icon.
UPDATE:
Things does show a bit of support for the nested tag structure when you select tags from the tag bar instead of searching for them. This more or less enables the work flow I was hoping for. Also, I set it up so that all my context tags are prefaces with an @ symbol, so that they are distinguished from priority or time/energy available. And, I’m using a naming convention for my nested contexts that makes it so I can search for them… my Target errand tag now looks like @Errands:Target.
Posted in: General
Something relating to the structure of the Pages file, and it being a “package” and not an actual binary file makes it so that version controlling it with SVN doesn’t work. You can check it in and out, but as soon as you open it again, it overwrites some meta stuff that SVN wrote inside of the package, and will no longer play nice. I thought I’d save you the trouble in case you were considering co-authoring a book with someone and considering SVN as a good way to collaborate. I knew we wouldn’t be able to “diff’ the files or anything, but I figured we could at least be able to intelligently handle the case when we both worked on the same chapter with out the other person knowing it. Looks like we’re going to use FTP, and come up with some convention for checking stuff in and out. Meh.
Check out our own Anthony Franco discussing and demonstrating Discovery Channel’s Cancer Collage with Adobe’s Julie Campagna:
http://blog.adobemax2007.com/2007/10/living-with-cancer-ria-with-mission.html
Yup. Juan Sanchez and I are writing a book about creating visual experiences with Flex. If you saw our 360|Flex presentation in Seattle, the book is an expanded and formalize version of that. Basically, we’re covering:
- Styling
- Graphical Skinning
- Programmatic Skinning
- Effects
- Transitions
- Filters
- Fonts
- Dynamic Layout
- More!
We’ll go in depth about each of these things; show samples of how they’re used in the wild; discuss how they support the fundaments of Rich User Experience; and tie it all together in a cookbook-like walk through. We’ve also got some ideas brewing for some really handy reference stuff in there too; things that’ll make this book worth having even if you know Flex UI development inside and out.
This should be a great, long, exhausting, exciting journey. We’ve already received some excellent support and feedback from the Flex team, David Coletta and other really smart folks. We’re going to have a thank you list that is a mile long.
Posted in: Flash
me: OK, so how do you use Spotlight?
tony: I use it to open Quicksilver if it’s not already running.
During and after my Creating a Visual Experience with Flex 2 presentation with Juan Sanchez, I received a ton of great feedback and great questions. Several people expressed interest in learning more about programmatic skinning. So, my intention here is to create a small series of posts to dive deeper into that topic.
As a quick recap on skinning, paraphrased from the Flex documentation: The term “skinning” refers to the process of changing a component’s appearance by changing or replacing its visual elements. In contrast, “styling” is the process of changing a component’s appearance by editing a predefined set of attributes. This gets a little messy because you actually specify skins using styles. But, the point here is that you can only get so far with styling. If you want a truly unique-looking Flex app, you’re going to have to do some skinning.
There are two methods of skinning: graphical and programmatic. With graphical skinning you embed pre-made artwork from a program like Fireworks or Flash, whereas with programmatic you write a class to dynamically draw artwork. Programmatic skinning is not unlike custom component development (on a small scale).
Understanding how skins are applied to Flex components.
To really understand skinning, graphical or programmatic, it is useful to know how skins are created and displayed for the standard Flex 2 components. This speaks really loudly to a point that Doug McCune made in his presentation, and that is READ THE FRAMEWORK CODE! This will be the topic of this week’s post as we look under the hood of a couple of common components.
Containers and Controls
Generally speaking, Flex components fall into two categories: containers and controls. Containers have a skin to represent the border; controls have a series of skins to represent various phases (up, over, down, etc). Let’s have a look at what’s going on inside of mx.core.Container – the base class of Panel, Canvas, VBox, HBox, etc; and inside of mx.controls.Button.
Container
This method is called when a Container instantiates or when a border-related style (such as borderSkin, borderStyle, etc) changes:
mx.core.Container [4033]
protected function createBorder():void { if (!border && isBorderNeeded()) { var borderClass:Class = getStyle(“borderSkin”); border = new borderClass(); border.name = “border”; … // Add the border behind all the children. rawChildren.addChildAt(DisplayObject(border), 0); … } }
Basically it is just creating an instance of a class (whatever you set for the borderSkin style-attribute), and adding it behind everything else in the component. Later, in updateDisplayList() the border’s size is set to the component’s overall size.
Button
Button introduces the notion of a “phase”. A phase is either up, down, over, or disabled; or a selected variation (e.g., selectedOver). Current phase is determined by the value of the selected and enabled properties as well as the user’s interaction with the control. A change in phase will trigger the following method:
mx.controls.Button [1488]
/** * @private * Displays one of the several possible skins, * depending on the skinName and creating * it if it doesn’t already exist. */ mx_internal function viewSkinForPhase(skinName:String):void { // Has this skin already been created? var newSkin:IFlexDisplayObject = IFlexDisplayObject(getChildByName(skinName)); // If not, create it. if (!newSkin) { var newSkinClass:Class = Class(getStyle(skinName)); if (newSkinClass) { newSkin = IFlexDisplayObject(new newSkinClass()); newSkin.name = skinName; … addChild(DisplayObject(newSkin)); newSkin.setActualSize(unscaledWidth, unscaledHeight) … } } // Hide the old skin. if (currentSkin) currentSkin.visible = false; // Keep track of which skin is current. currentSkin = newSkin; // Show the new skin. if (currentSkin) currentSkin.visible = true; … }
Again, an instance of a class is created and then added as a child. This method sizes the skin to match the component’s size, and later on in a method called layoutContents, the various elements (skin, label, icon) are stacked in the proper z-order.
mx.controls.Button [1947]
… if (currentSkin) setChildIndex(DisplayObject(currentSkin), numChildren - 1); if (currentIcon) setChildIndex(DisplayObject(currentIcon), numChildren - 1); if (textField) setChildIndex(textField, numChildren - 1); …
Conclusion
In a nutshell, that’s basically how skins are applied to the out-of-the-box Flex components. Each component may vary slightly, but the pattern is the same:
- Create an instance of a class, specified via CSS (either a class or a embedded image)
- Add the instances as a child of the compoent being skinned
- Make sure the instance is behind everythign else in the component
As I mentioned earlier, programmatic skinning is kind of like writing custom components. It’s useful to understand the UIComponent lifecycle, including initialization, invalidation, and measurement. Describing that in detail is out of scope for this post, but we’ll see how skins can affect measurement in the next post. Thanks for reading. Check back soon.
Posted in: Flash
Remember that optimization effort you spent all night on? Don’t hoard your learnings. Share them with everyone at MAX 2007. David Coletta of Buzzword fame is hosting a session on Flex performance optimization and has invited you to join him and demo your lightning fast application.
Be part of [David’s] Flex performance optimization talk at MAX!
Posted in: General
David Coletta just posted a list of 10 tips for public speaking here. His session on Buzzword at 360Flex was very engaging and it was for the very reasons he’s listed in his post. Check it out.
