Shotwell Architecture Overview: Photo Editor
Shotwell offers a built-in non-destructive photo editor. The design goal is not to match the features available in more powerful image editors (such as GIMP or Photoshop), but to make available common photo editing tools that users commonly need, and to make those tools easy to use.
The basic UI design is to display the photo scaled to the window size with editing tools immediately available. There is no edit mode. The editor is also the full-window photo viewer, and can be used simply to step through the collection one-by-one. The user can remove all changes at any time with Revert to Original. With the Undo feature, users can remove alterations as they were made step-by-step.
The Editing Host
EditingHostPage is so-named because the goal of its design is not to hold all editing logic, but rather to merely host a canvas the editing tools can draw on to perform their operations. When the user decides to commit these changes, the editing tools save them to the database.
Note that this currently is not a full-fledged plug-in architecture, and would require some work to get to that point. The design so far is to abstract out the various tools so that moving that direction is not onerous. Note also that not all editing tools (currently) go through this interface because of their simplicity. For example, the Rotate button has no UI element beyond the button, and so it can apply its change immediately.
As a photo viewer, EditingHostPage uses PixbufCache to prefetch images so they may be displayed instantly when the user navigates to them. If the PixbufCache does not have the pixbuf ready, EditingHostPage scales the photo’s largest thumbnail to fit the window; this allows for a rough view of the photo to get on the screen rapidly (or near instantly if the thumbnail is already in the cache). Then it loads the actual photo scaled appropriately and displays that.
As a photo editor, there are three components that work together:
EditingHostPage (which is a subclass of SinglePhotoPage): hosts the tools and the canvas (Gtk.DrawingArea) for the tools to perform immediate transformations for the user
EditingTool: an abstract class all editing tools must inherit from and implement. In addition to managing state changes (such as being activated and deactivated, or signaling that the user has applied changes or is canceling the operation), the EditingTool interface also receives calls from EditingHostPage for various UI events, such as button clicks and mouse motion. The EditingTool can also supply an EditingToolWindow, a transient window which floats over the main window offering additional controls for the user.
PhotoCanvas: a connector object that EditingHostPage gives to the EditingTool when it’s instantiated. The PhotoCanvas holds references to all the objects the editing tool would need to do its drawing work. It also offers helper functions so the tools draw directly to the photo’s area on the canvas and not have to worry about the border areas filling the remaining window regions. Both EditingHostPage and EditingTool work through this object. (Some of EditingTool’s interfaces (notably the ones for receiving GDK events) may be routed through PhotoCanvas in the future).
When the EditingTool is active, it is hooked into the EditingHostPage, receiving notifications when appropriate and affecting other EditingHostPage behaviors. (For example, drag-and-drop export is disabled when a tool is active.)
Currently EditingHostPage only allows one tool to be active at a time. Future work would allow more than one to remain active, such as the color adjustment tool.
Because there are distinct differences between editing in library mode and direct-edit mode, EditingHostPage is abstract. LibraryPhotoPage and DirectPhotoPage provide implementation for these different modes.