Skip to content
Robert Silverton edited this page Jul 3, 2014 · 4 revisions

View this tutorial's changes on GitHub.

If you're working with the tutorial repo, open a Git Shell in the CoreEditor-HelloWorld-Example-as folder and run the following command:

git checkout -f step-3

Otherwise, follow the instructions below.


About Actions

An Action is a class that describes a button or menu item associated with a View. In this tutorial we will add an action to the HelloWorldView we created in the previous tutorial.

When your view is added to the app it gets wrapped up in a IViewContainer. The concrete implementation of this view is responsible for displaying the appropriate buttons and menu items that correspond to each Action.

Although the concrete implementation can choose to implement these buttons and menu items how it likes, the default implementation has the following two visible UI elements:

  • Its MenuBar is the bar along the top (much like the File, Edit, Window menu you find in most applications).
  • Its ToolBar is the strip of buttons that appear just below the MenuBar.

A single Action can appear in a MenuBar, ToolBar or both. For example, the 'Undo' action in a lot of applications appears in the menubar Edit->Undo, and also on the Toolbar.

For your current purposes, you don't need to understand how this mechanism is implemented as the IViewContainer wrapping your view will take care of it and any Actions you create will simply appear around your View.

Adding Your Own Action

To add an Action, add the following code to your extension's constructor:

CoreApp.resourceManager.addResource( new ActionFactory( HelloWorldContext, null, "My Action", "myActions" ) );

Here you'll see we're using an ActionFactory class, unlike the previous tutorial where we used a Factory. An ActionFactory still performs the same function as a Factory (they both implement IFactory), however it adds a few properties that it passes on to the instances it creates.

Let’s explain each parameter.

  • The first parameter, 'target', is the type of the Context whose view you want the action to appear on. In this case, we are targeting the Context we created in the previous tutorial.
  • The second parameter is 'command' - we'll explain this later. For know lets leave it as null.
  • The next parameter is 'label'. For a ToolBar button, this text becomes its tooltip.
  • The final parameter is the 'toolbarPath'. This value dictates which 'group' of toolbar buttons it appears in.

If you build your extension and run the app, you should now see a button on your View's ToolBar. However you'll notice that it's disabled, and you can't click it. This is because Actions are intimately tied in with the concept of 'Commands'.


About Commands

A Command is simply a string. Commands are a mechanism for de-coupling code invoking a command, and code carrying out the command. Commands should be unique, so no two Commands should have the same value. For this reason, by convention they work much like package names and are stored as static constants. For an example of what commands look like, take a look at the following class: core.editor.entities.Commands

Creating Your Own Command

Create a new Class:

package helloWorld.entities
{
	public class Commands
	{
		public static const MY_COMMAND:String = "helloWorld.myCommand";
	}
}

About CommandHandlers

A Command is not much use unless there is something to carry out the command. These are called CommandHandlers. All CommandHandlers implement the core.appEx.core.commandHandlers.ICommandHandler interface. This interface has a single method, execute(parameters:Object).

CommandHandlers are responsible for most of the behaviour you see within the application. If they don't carry out the work themselves, at the very least they delegate the work out to Operations (more on that later).

Adding Your Own CommandHandler

Create a new Class:

package helloWorld.commandHandlers
{
	import core.appEx.core.commandHandlers.ICommandHandler;
	import core.ui.components.Alert;
	
	public class MyCommandHandler implements ICommandHandler
	{
		public function MyCommandHandler()
		{
			
		}
		
		public function execute(parameters:Object):void
		{
			Alert.show("Alert", "Hello World", ["OK"]);
		}
	}
}

Now that we have our CommandHandler, we need to contribute this by adding the following line to our extension's constructor:

CoreApp.resourceManager.addResource( new CommandHandlerFactory( Commands.MY_COMMAND, MyCommandHandler ) );

Again, we are adding a Factory to the ResourceManager. Much like the ActionFactory, we have another slightly specialised Factory for creating CommandHandlers. As you can see, we are passing the Command and the type of our CommandHandler to its constructor. This means that this particular CommandHandler is now associated with this Command. Invoking MY_COMMAND will now cause the framework to find the CommandHandler associated with this command and call its execute() function. But how do we invoke Commands?


Manually Invoking Commands

One way of invoking Commands is by directly accessing the CommandManager on the CoreEditor API. Do this now by adding the following line to the end of your extension's constructor (it is important to place it after we add the CommandHandlerFactory, as there is nothing to handle the Command yet).

CoreEditor.commandManager.executeCommand(Commands.MY_COMMAND);

Build and run the Application to see your CommandHandler being invoked as soon as your Extension is loaded during application start up.

Invoking Commands via Actions

Although invoking Commands manually is perfectly valid, most Commands are invoked by clicking on an Action. Do you remember the 'command' property we skipped over when creating our ActionFactory earlier? If we set this property we associate an Action with a Command. Let’s do this now by replacing this line:

CoreApp.resourceManager.addResource( new ActionFactory( HelloWorldContext, null, "My Action", "myActions" ) );

With this:

CoreApp.resourceManager.addResource( new ActionFactory( HelloWorldContext, Commands.MY_COMMAND, "My Action", "myActions" ) );

Build your extension and run the application. You should now be able to click your Action to invoke the command.

To recap, we have added an Action and associated it with a Command. We have also added a CommandHandler and associated it with the same Command. Action <--> Command <--> CommandHandler

As you can see, the Action and CommandHandler are indirectly associated via the Command. At first glance this may seem overly complicated, why not just associate an Action with a CommandHandler and remove the need for Commands altogether? Well, the idea is to keep Actions and CommandHandlers loosely coupled so that your code linking Actions to Commands doesn't have any dependencies on the concrete implementation of a CommandHandler. Essentially your Action is saying 'I don't care how you implement UNDO, all I know is that the user who clicked me wants something undone'.

Also by having the notion of Commands, it allows any code you write to indirectly invoke a CommandHandler without any direct knowledge of its implementation.


< Previous | Next >