`

Toggle & Radio menu contributions

 
阅读更多
转载于:http://blog.eclipse-tips.com/2009/03/commands-part-6-toggle-radio-menu.html
Commands Part 6: Toggle & Radio menu contributions

In the previous parts of the series, we saw how Commands contribute to push style menu items. But commands allow you to contribute menu items with 'toggle' and 'radio' style as well. Let us see how to contribute the familiar "Format" menu thru Commands:





First we will look at the toggle style menu contribution. Commands can have states associated with it. A state id known by its id and it can have any value, which is stored in a subclass of org.eclipse.core.commands.State. To know whether a command is checked or not, the Command Framework looks for a state with the id 'org.eclipse.ui.commands.toggleState'. Lets specify the default checked state of Bold to true and Italic to false:

<command
      defaultHandler="com.eclipse_tips.commandstate.BoldHandler"
      id="com.eclipse-tips.commandState.boldCommand"
      name="Bold">
   <state
         class="org.eclipse.ui.handlers.RegistryToggleState:true"
         id="org.eclipse.ui.commands.toggleState">
   </state>
</command>
<command
      defaultHandler="com.eclipse_tips.commandstate.ItalicHandler"
      id="com.eclipse-tips.commandState.italicCommand"
      name="Italic">
   <state
         class="org.eclipse.ui.handlers.RegistryToggleState:false"
         id="org.eclipse.ui.commands.toggleState">
   </state>
</command>

The Framework expects a Boolean value from the state. It doesn't care about which class that holds the state. So why should we use the RegistryToggleState instead of our own state class? Two reasons:

It implements IExecutableExtension. So you can specify the default values in the plugin.xml as I've done above.
It extends PersistentState, so it can remember the value between Eclipse sessions. So if the user had checked/unchecked the menu, restarts Eclipse, he will get the same state as he left before - all this, you get without even your plugin being loaded.
So how should the handler work for this command?

public Object execute(ExecutionEvent event) throws ExecutionException {
     Command command = event.getCommand();
     boolean oldValue = HandlerUtil.toggleCommandState(command);
     // use the old value and perform the operation

    return null;
}

Basically, its the Handler's responsibility to update the Command's state. The HandlerUtil has a convenient method which toggles the state and gives you the old value of the state. You can use the value to perform the operation.

The radio state is also similar, which expects the state with a predefined id. Since the same command is contributed for various option, its should be a parameterized command. The id of the parameter which denotes the radio state is also predefined:

<command
      defaultHandler="com.eclipse_tips.commandstate.AlignHandler"
      id="com.eclipse-tips.commandState.alignCommand"
      name="Align Command">
   <commandParameter
         id="org.eclipse.ui.commands.radioStateParameter"
         name="State"
         optional="false">
   </commandParameter>
   <state
         class="org.eclipse.ui.handlers.RadioState:left"
         id="org.eclipse.ui.commands.radioState">
   </state>
</command>

Just like toggle state, the state must have the id and the class could be anything that stores the value as String. The RadioState class provides initializing from plugin.xml and also persists the value across sessions.

The menu contribution would specify the parameter value:

<menuContribution
      locationURI="menu:org.eclipse.ui.main.menu?after=additions">
   <menu
         label="Format">
      ... other contributions here
      <command
            commandId="com.eclipse-tips.commandState.alignCommand"
            label="Align Left"
            style="radio">
         <parameter
               name="org.eclipse.ui.commands.radioStateParameter"
               value="left">
         </parameter>
      </command>
      <command
            commandId="com.eclipse-tips.commandState.alignCommand"
            label="Align Center"
            style="radio">
         <parameter
               name="org.eclipse.ui.commands.radioStateParameter"
               value="center">
         </parameter>
      </command>
      <command
            commandId="com.eclipse-tips.commandState.alignCommand"
            label="Align Right"
            style="radio">
         <parameter
               name="org.eclipse.ui.commands.radioStateParameter"
               value="right">
         </parameter>
      </command>
   </menu>
</menuContribution>

The Command Framework understands this parameter and sets the UI contributions according to this value. Again its the handler's job to set the correct state from the command's parameter during execution. You have helper methods in the HandlerUtil to perform this:

public Object execute(ExecutionEvent event) throws ExecutionException {
    if(HandlerUtil.matchesRadioState(event))
        return null; // we are already in the updated state - do nothing
    String currentState = event.getParameter(RadioState.PARAMETER_ID);
    // perform task for current state
    if(currentState.equals("left"))
    // perform left alignment
    else if(currentState.equals("center"))
    // perform center alignment
    // and so on ...

    // and finally update the current state
    HandlerUtil.updateRadioState(event.getCommand(), currentState);

    return null;
}

Bonus:

Q: I want the initial value always loaded from the plugin.xml, the state should not be remembered between sessions. Should I write my own State class?

A: Not necessary. You can specify both the default value of the state and whether to persist or not in the plugin.xml itself:

<command
      defaultHandler="com.eclipse_tips.commandstate.AlignHandler"
      id="com.eclipse-tips.commandState.alignCommand"
      name="Align Command">
   <commandParameter
         id="org.eclipse.ui.commands.radioStateParameter"
         name="State"
         optional="false">
   </commandParameter>
   <state
         id="org.eclipse.ui.commands.radioState">
      <class
            class="org.eclipse.ui.handlers.RadioState">
         <parameter
               name="default"
               value="left">
         </parameter>
         <parameter
               name="persisted"
               value="false">
         </parameter>
      </class>
   </state>
</command>

This applies for toggle state as well.

Q: I want to know the state of the command elsewhere in the code. How do I get it?

A: Just use Command.getState(<state id>).getValue(). The state ids are available as constants at RegistryToggleState.STATE_ID and RadioState.STATE_ID

My patch for this feature has just been checked in and should be available from 3.5 M6 onwards. If you are curious, pick up a recent Nightly build and play with this.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics