RCP小技巧之带勾(toggle)的菜单

时间:2022-03-09 22:49:35

  有时候我们需要级联菜单中前方可以勾选(√),来表示当前系统的某种状态,这就需要用到可以打勾的菜单。

先看最终效果:

 

RCP小技巧之带勾(toggle)的菜单

 

 

下面我们首先来看看怎么在plugin.xml中配置该菜单:

假设我们要做一个类似于powerdesigner样的数据库设计工具,其中表格在对话框中的显示只能是一下三种之一:

1)只显示主键  2)只显示主外键 3)全部显示

所以我们希望可以主菜单“视图”下加一个“表格图形显示”的级联菜单,“表格图形显示”下面有三个子菜单,用来表示上面的三种显示状态,于是在plugin.xml中org.eclipse.ui.commands扩展点下先建三个Command,截图如下:
RCP小技巧之带勾(toggle)的菜单


 注意,我们在每个command下都添加了一个state的节点,用来记录其command的状态值,下面附上state节点的截图:


RCP小技巧之带勾(toggle)的菜单

记住,一个command下建立多个state节点时,它们的id值是不能重复的,我们在id中写的org.eclipse.ui.commands.toggleState其实是系统中RegistryToggleState.STATE_ID所定义的值,我们在这三个command节点下添加的state节点id和class都是相同的,如果你想系统在运行时,默认选择一种表格显示方式,只需要在这个显示方式的command下的state节点中class改成org.eclipse.ui.handlers.RegistryToggleState:true就行了。这样,我们需要的三个Command就配置完了,附上其对应的xml内容:

<command
            id="sunline.suncard.powerdesigner.commands.onlyshowprimarykey"
            name="%onlyshowprimarykey">
         <state
               class="org.eclipse.ui.handlers.RegistryToggleState:false"
               id="org.eclipse.ui.commands.toggleState">
         </state>
      </command>
      <command
            id="sunline.suncard.powerdesigner.commands.showprimaryandforeign"
            name="%showprimaryandforeign">
         <state
               class="org.eclipse.ui.handlers.RegistryToggleState:false"
               id="org.eclipse.ui.commands.toggleState">
         </state>
      </command>
      <command
            id="sunline.suncard.powerdesigner.commands.showall"
            name="%showall">
         <state
               class="org.eclipse.ui.handlers.RegistryToggleState:false"
               id="org.eclipse.ui.commands.toggleState">
         </state>
      </command>

 

接下来我们给这三个command绑定handler,现在org.eclipse.ui.handlers扩展点下面建立三个handler,下面是其对应的xml内容:

<handler
            class="cn.sunline.suncard.powerdesigner.handler.TableModelShowType_P"
            commandId="sunline.suncard.powerdesigner.commands.onlyshowprimarykey">
      </handler>
      <handler
            class="cn.sunline.suncard.powerdesigner.handler.TableModelShowType_PF"
            commandId="sunline.suncard.powerdesigner.commands.showprimaryandforeign">
      </handler>
      <handler
            class="cn.sunline.suncard.powerdesigner.handler.TableModelShowType_ALL"
            commandId="sunline.suncard.powerdesigner.commands.showall">
      </handler>

其中,我们建立了三个类,TableModelShowType_P用于处理只显示主键,TableModelShowType_PF用于处理显示主外键,TableModelShowType_ALL用于处理现实全部。最后会附上其中一个类的代码。

 

接下来就是在org.eclipse.ui.menus扩展点下建立menu节点,截图如下:
RCP小技巧之带勾(toggle)的菜单

注意,这里的command节点需要在style的下拉列表中选择toggle风格!!
 xml内容如下:

           <menu
                  icon="icons/table_16.png"
                  label="%tablediagramshowtype">
               <command
                     commandId="sunline.suncard.powerdesigner.commands.onlyshowprimarykey"
                     label="%onlyshowprimarykey"
                     style="toggle">
               </command>
               <command
                     commandId="sunline.suncard.powerdesigner.commands.showprimaryandforeign"
                     id="sunline.suncard.powerdesigner.commands.showprimaryandforeign"
                     label="%showprimaryandforeign"
                     name="%showprimaryandforegin"
                     style="toggle">
               </command>
               <command
                     commandId="sunline.suncard.powerdesigner.commands.showall"
                     label="%showall"
                     name="%showall"
                     style="toggle">
               </command>
            </menu>
 

 接下来,我们可以看见效果了,运行系统后发现,这三个菜单都可以打勾,但根据我们的需求,只希望一个被大勾,这怎么办呢?于是,我们可以通过handler中的代码来控制,我们来看看其中一个handler——TableModelShowType_ALL(全部显示)中的代码内容:

public class TableModelShowType_ALL extends AbstractHandler{

 @Override
 public Object execute(ExecutionEvent event) throws ExecutionException {
   Command allShowCommand = event.getCommand();
  State allState = allShowCommand.getState(RegistryToggleState.STATE_ID);
  allState.setValue(true);
  
  // 因为全部显示菜单被勾选了,其他两个菜单需要设置为不勾选
  ICommandService service = (ICommandService) PlatformUI.getWorkbench()
    .getService(ICommandService.class);

// 设置“只显示主键”菜单为不勾选状态

  Command pCommand = service.getCommand("sunline.suncard.powerdesigner.commands.onlyshowprimarykey");
  State pState = pCommand.getState(RegistryToggleState.STATE_ID);
  pState.setValue(false);
  

// 设置“显示主外键”菜单为不勾选状态
  Command pfCommand = service.getCommand("sunline.suncard.powerdesigner.commands.showprimaryandforeign");
  State pfState = pfCommand.getState(RegistryToggleState.STATE_ID);
  pfState.setValue(false);  

 

// 刷新菜单状态

  service.refreshElements(allShowCommand.getId(), null);
  service.refreshElements(pCommand.getId(), null);
  service.refreshElements(pfCommand.getId(), null);


  return null;
 }

}  

 注意, allState.setValue(true); 保证了如果当前是“全部显示”菜单被勾选,用于如果继续点击“全部显示” 菜单,该菜单还是会被勾选,而不是被取消勾选。而且,如果这三个command下面的state节点的id不是org.eclipse.ui.commands.toggleState,假如“只显示主键”的command节点下的state节点的id是org.eclipse.ui.commands.toggleState_showall,则State pfState = pfCommand.getState(RegistryToggleState.STATE_ID); 需要改成State pfState = pfCommand.getState("org.eclipse.ui.commands.toggleState_showall");,否则获取的pfState将为空。但即使这样,你会发现行为达不到预期的效果,就是说“只显示主键”菜单依然我行我素,单击它它会勾选,再次单击它它会取消勾选,就是说pState.setValue(false);没有效果。调试过程中看下源代码会发现原因:

在HandlerProxy类中,有一个handleStateChange方法,该方法来自IStateListener接口,该接口也只有这一个方法,主要用来当菜单的状态改变时,需要旧的状态值需要用某一个值来更新。在HandlerProxy类中,实现代码如下

 

 public void handleStateChange(State state, Object oldValue) {
  if (state.getId().equals(RegistryToggleState.STATE_ID)) {
   checkedState = state;
   refreshElements();
  } else if (state.getId().equals(RadioState.STATE_ID)) {
   radioState = state;
   refreshElements();
  }
  if (handler instanceof IStateListener) {
   ((IStateListener) handler).handleStateChange(state, oldValue);
  }
 }
 

 因为你的state的id不是RegistryToggleState.STATE_ID,hander绑定的类也没有实现IStateListener接口,所以这个方法里面的代码根本没被执行,菜单的值和状态也没有得到更新。

 

 

 

 


 

  • RCP小技巧之带勾(toggle)的菜单
  • 大小: 20.1 KB
  • RCP小技巧之带勾(toggle)的菜单
  • 大小: 20.8 KB
  • RCP小技巧之带勾(toggle)的菜单
  • 大小: 9.6 KB
  • RCP小技巧之带勾(toggle)的菜单
  • 大小: 64.3 KB