Search code examples
eclipseeclipse-plugineclipse-cdteclipse-pde

How to make Eclipse enabledWhen expression work for selection in non-focused view?


I have a handler which is connected to a menu contribution and a command. The menu contribution adds a button to a view and I want to have the button enabled depending on a selection in the Debug view.

So here's the expression:

<handler
            class="com.example.myhandler"
            commandId=" com.example.mycommand">
         <enabledWhen>
            <with
                  variable="selection">
               <iterate
                     ifEmpty="false">
                  <instanceof
                        value="org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext">
                  </instanceof>
               </iterate>
            </with>
         </enabledWhen>
      </handler>

This works absolutely fine to the point where the Debug view has focus, meaning that if I select the element in the Debug view, the added button in a separate view is also enabled (as desired). As soon as I click on the view where I added the button via the menu contribution, then it's suddenly disabled (I guess because the selection is empty even though it's still selected; but the Debug view has no focus). How can I make this work so that the selection is still considered independently of the Debug view's focus state?


Solution

  • (You appear to be asking a DSF specific question, which has a different answer to the "general" case your title refers to. As such this answer probably solves your problem, but may not solve the general case.)

    A complete example of extending DSF-GDB is provided in the CDT source repo in the org.eclipse.cdt.examples.dsf.gdb bundle.

    That example defines a new command org.eclipse.cdt.examples.dsf.gdb.command.showVersion:

       <!-- Example showing how to add a custom command with toolbar/menu contributions with DSF.
            The example command id is org.eclipse.cdt.examples.dsf.gdb.command.showVersion.
            In this example, when run it will display the version of GDB that is connected. -->
       <extension point="org.eclipse.ui.commands">
          <command
              categoryId="org.eclipse.cdt.debug.ui.category.debugViewLayout"
              description="Show the GDB Version in a pop-up"
              id="org.eclipse.cdt.examples.dsf.gdb.command.showVersion"
              name="Show GDB Version">
          </command>
       </extension>
    

    It goes on to show how to contribute the command to the menus with the org.eclipse.ui.menus extension point. Then binds the command to a command handler with the org.eclipse.ui.handlers extension point.

    Up until this point, DSF behaves the same as "normal" commands. But in DSF (using the retargettable command infrastructure provided by platform debug), the handler is not directly the command you are trying to run, but is a subclass of DebugCommandHandler.

    DSF then can bind that command, using adapters to the concrete command implementation, depending on what the selected debug session in the Debug view is. In the show version case, this is GdbShowVersionHandler (implementation of IDebugCommandHandler). The handler has a canExecute which can connect to the back end if needed (gdb) to see if the current selection is applicable. The canExecute receives something that can be converted into a DSF context object like this:

    private Optional<ICommandControlDMContext> getContext(final IDebugCommandRequest request) {
        if (request.getElements().length != 1 || !(request.getElements()[0] instanceof IDMVMContext)) {
            return Optional.empty();
        }
    
        final IDMVMContext context = (IDMVMContext) request.getElements()[0];
        ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(context.getDMContext(),
                ICommandControlDMContext.class);
        if (controlDmc != null)
            return Optional.of(controlDmc);
        return Optional.empty();
    }
    

    PS I added this example to CDT to help another extender a while back. The conversation on cdt-dev may be useful too? This was all added initially for this bug, with its associated gerrit which pulls all the changes for adding a new command into one place.