View Actions
Espresso provides several kinds of actions, but they all share a similar Sugar architecture. This section documents the generic aspects of text and file actions, and points out the areas where things start diverging depending on the type of action. To simplify the generic documentation, let’s assume we are talking about Text Actions, which are located in the TextActions folder of the Sugar.
There are three types of allowed XML files in the GenericActions folder, each treated differently:
- Files with a filename ending in “Categories.xml”: category definitions
- Files with a filename ending in “Sorting.xml”: sorting definitions
- All other XML files: action definitions
Action definitions
Action definition XML files have the following structure:
<?xml version="1.0"?>
<action-recipes>
<action id="com.yourdomain.GenericActions.unique.action.identifier"
category="actions.generic.category.identifier">
<class>CocoaActionClass</class>
<title>Human readable default action name</title>
</action>
<action id="..." category="...">
<class>...</class>
<title>...</title>
<when-disabled>show</when-disabled>
<setup>
<custom>Anything here</custom>
<custom2>
<array>
<string>property list syntax also works here</string>
<string>really!</string>
</array>
</custom2>
</setup>
</action>
</action-recipes>
You can define any number of actions. Let’s dissect the various pieces:
- id attribute: define a globally unique identifier for your action here. It’s a good idea to use the com.yourdomain.GenericActions.unique.action.identifier naming convention, where GenericActions is replaced by the specific type of action.
- category attribute: actions are grouped into categories for display in the UI. The value of this attribute needs to reference a category defined in a category definition (see below). This category might be located in another sugar or be a default category. Specifying an nonexistent value here is harmless, and treats the action as having no category.
- <class> tag: the value you enter here is a class name for a Cocoa class that Espresso can use to initialize action instances. See below for more info on compiled action objects. [Espresso 1.0 will ship with some generic default actions to easily define new script-based actions using only XML]
- <title> tag: a human readable title for the action, used for its menu item. Note that this may be overridden if the compiled class implements custom titles.
- (Optional) <setup> tag: extremely valuable when creating generic action classes that change behavior depending on the XML definition. Each tag inside the <setup> block will be treated as a custom variable and passed to the action class on initialization as a dictionary. See the Example Sugar in CocoaSugars for a simple demonstration of this capability.
- (Optional) <when-disabled> tag: specify explicitly if the action should disappear from the UI or stay visible but dimmed when it’s not usable. Allowed values are “show” and “hide”. It’s recommended to leave the tag out, so the default behavior is used.
Category definitions
Because actions can come from an arbitrary number of Sugars, grouping them happens by means of category identifiers. Using the category paths in the action definitions (see above), an action tree is generated and used to create the action UI. Category definitions specify how each category should be presented to the user.
<?xml version="1.0"?>
<action-categories>
<category id="actions.generic.MyOwnSection" show="sub">
<title>My Own Section Title</title>
</category>
<category id="..." show="inline separated">
...
</category>
</action-categories>
- id attribute: the identifier of the category (used by the action definitions; see above)
- show attribute: the value of this attribute defines how the category is displayed between other categories. It has two hierarchical options (sub to display in a submenu and inline to display in the same menu as other categories at its level), and one decorative (separated, which defines whether or not the menu items for the category should be surrounded by separators; typically only desirable for inline categories).
- <title> tag: a human readable title for the category.
Category definitions and the UI
Using category attributes (sub/inline) and category paths, you can exactly achieve the menu structure you need. Some basic category sorting will be provided [documentation forthcoming] by default. For subcategories that also need ordering (and will not be used by other Sugars), ensuring an exact ordering can be accomplished by adding “anonymous” categories (not defined in any category definitions) to the path, with numeric values as the last identifier component.
For example: three actions with categories like path/randomcategory.1, path/randomcategory.2 and path/randomcategory.3 (where the random categories are anonymous) will be sorted in that order. Visually, they will belong to “path”.
Sorting definitions
[documentation forthcoming; sorting is not enabled for Sugars in 0.9b2]
Compiled code
Cocoa action objects can be written using only 4 methods (of which 2 are optional):
@interface NSObject (Action)
// Optional; called instead of -init if implemented.
// Dictionary contains the keys defined in the <setup> tag of action definitions. This is
// how you can create generic item classes that behave differently depending on the
// XML settings.
- (id)initWithDictionary:(NSDictionary *)dictionary bundlePath:(NSString *)bundlePath;
// Required: return whether or not the action can be performed on the context.
// It's recommended to keep this as lightweight as possible, since you're not the only
// action in Espresso.
- (BOOL)canPerformActionWithContext:(id)context;
// Required: actually perform the action on the context.
// If an error occurs, pass an NSError via outError (warning: outError may be NULL!)
- (BOOL)performActionWithContext:(id)context error:(NSError **)outError;
// Optional; useful for changing titles depending on characteristics of the context.
// By default, actions will use the title from the <title> tag in their definition.
- (NSString *)titleWithContext:(id)actionContext;
@end
The specific “context” argument depends on the type of action. See TextActions and FileActions for more information. A documented example of Cocoa action implementations can be found under CocoaSugars.