To make it work, I built an MVC file-system, an application registry, a window manager, alerts and notifications, and a few simple applications inside the framework. The result is a fully-functional desktop environment. Try it yourself:
Go and play around with it: it's largely self-documenting. You'll find sample text files describing how things work and hints will appear automatically; there's even a built-in source code viewer.
It's not perfect. I learned a huge amount by exploring these ideas, I never put it through professional quality control. That's why it's sat on my hard-drive for a year; I didn't want to show it until it was "done," but couldn't really find any time to work on it. But I finally just said, "there are a lot of great ideas here, other's could learn from it, I'm just going to put it out there, perfectionism be damned."
The OWL Desktop project does not have an open source license yet; I have decided to reserve all rights for the time being. Partly because I know it's not quite finished, and partly because it's not really useful for anything beyond an idea incubator. I encourage you to read and understand the code, judge for yourself how useful each idea is, and to take that knowledge with you to your own projects rather than copying any code directly.
If you've had a chance to go and look at and are interested in how it works, I'm going to briefly go into some the biggest lesions learned from the project.
MVC File System
I wrote my own File and Directory classes to serve as models (the M of MVC) and gave them a good event model so that the folder window views (the V) could always show a synchronized, up-to-date view of what's really going on. The controller (the C) is the FileManagerApp, equivalent to Windows Explorer or Nautilus. It's basically an ordinary application. The file system is strict subset of the Unix file system: The rules for when you can view, edit, delete, rename, or move a file follow UNIX exactly, resulting in a familiar, time-tested, and intuitive system. However, there are no groups and only one privilege bit: public or private, so it's a simplified but faithful model of UNIX.
Drag and Drop
Implementing drag-n-drop between windows was kind of a pain, but absolutely necessary to get that "native desktop" feel. When windows overlap, and you drag a file into the intersection, both windows get notified of the drop. It took me a while to figure out what was going on and come up with a solution. I queued up drop events without processing them right away, and then had a deferred handler go back and determine which drop was on top and ignoring all the others. I had to dig pretty deeply into ExtJS's drag-n-drop library but in the end I learned a tremendous amount and got a pretty good solution.
Windows can be minimized or maximized. Every window gets an entry on the Taskbar that can be used to minimize or restore a window, or bring one to the front. All of this is possible because of the AppWindowMgr, a registry of windows. The Taskbar and AppWindowMgr have an MVC relationship: the AppWindowMgr has events that the taskbar binds to in order to stay in sync, and each AppWindow notifies the AppWindowMgr when it's created or destroyed.
Applications can be "plugged-into" the framework, by loading a separate
.js file which registers the application with the AppMgr (a registry of applications.) This gets it an entry on the Start button. You can also register an application to be the handler for any number of file extensions: for example, the TextEdit app handles the ".txt" extension and the HtmlEdit app handles the ".html" extension. By using Dependency Inversion consistently, I've completely eliminated any dependency of the framework on individual applications, allowing any number of "apps" to be registered, even at runtime, longer after the initial page load.
I introduced logging and notification utilities to serve as a Single Point of Logging as well as to provide a neat little prepackaged UI for showing them. Not only do these look cool, but they're recorded and available in the centralized SystemManager app. These are important services for a framework to provide; otherwise, everyone does it themselves in their own way, log files are fragmented, and the user experience is inconsistent.
Also included, in the top-level
owl namespace, are some really powerful utilities: a clone() function, a powerful array search/slice utility, an extensible comparison operator called
same() (inspired by the MochiKit comparison framework) and a namespace utility.
The last one, the namespace utility, is probably the most widely useful of them all. I can't even imagine starting a large JS project now without a similar utility. It's a small thing, to be sure, but is needed again and again. You can see throughout the source code how it's used to cleanly give each
.js file its own namespace.
- Oran Looney October 30th 2010