X

Geertjan's Blog

  • September 7, 2010

Using Scene.setActiveTool from Context Aware Actions

Geertjan Wielenga
Product Manager
I spent some time today creating the select/move modes that you see in the bottom left of the screenshot below:

The two buttons in the bottom left, above, how are they created? The underlying approach is to use Scene.setActiveTool. However, in this case we're not using a right-click popup menu to select the mode because that menu is used to create the widgets above.

Instead, the modes are defined in Action classes, registered in the layer. So, we have two Actions in the layer. These, in turn, are bound to the JToolBar in the bottom of the TopComponent, as explained by David Rigsby.

OK, so now we have two Actions displayed in a JToolBar. How do we communicate from our Actions to our Scene? Here's the key to everything, in the constructor of the TopComponent:

InstanceContent ic = new InstanceContent();
ProxyLookup proxy = new ProxyLookup(
Lookups.singleton(ic),
new AbstractLookup(ic),
ExplorerUtils.createLookup(em, getActionMap()));
associateLookup(proxy);

We have an InstanceContent which we put into the Lookup of the TopComponent. First, we put it there as an object, so that our Actions can be sensitive to that object, then we insert that object into AbstractLookup, so that it is available to the Lookup of the TopComponent.

Next, I have an object that represents the mode:

public class SelectOrMoveMode {
boolean selectMode;
public boolean isSelectMode() {
return selectMode;
}
public void setSelectMode(boolean selectMode) {
this.selectMode = selectMode;
}
}

Then, within each Action, we are sensitive to the InstanceContent and then we add a new instance of the above object to the InstanceContent:

public final class SelectHouseAction implements ActionListener {
private final InstanceContent context;
public SelectHouseAction(InstanceContent context) {
this.context = context;
}
@Override
public void actionPerformed(ActionEvent ev) {
SelectOrMoveMode mode = new SelectOrMoveMode();
mode.setSelectMode(true);
context.add(mode);
}
}

The "MoveHouseAction" is the same as the above, except that "mode.setSelectMode(false)" is used.

Finally, in the TopComponent we listen for changes to "SelectOrMoveMode". And here is the "resultChanged":

@Override
public void resultChanged(LookupEvent ev) {
Collection<? extends SelectOrMoveMode> allModes = result.allInstances();
if (!allModes.isEmpty()) {
for (SelectOrMoveMode selectOrMoveMode : allModes) {
if (selectOrMoveMode.isSelectMode()) {
scene.setActiveTool(ACTION_SELECT);
StatusDisplayer.getDefault().setStatusText("select");
} else {
scene.setActiveTool(ACTION_MOVE);
StatusDisplayer.getDefault().setStatusText("move");
}
}
}
}

For background to the "Scene.setActiveTool", which this blog entry assumes you're familiar with, see this blog entry.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.