eclipse-rcpe4

Evaluation of @CanExecute for RCP e4 application


A RCP E4 application includes a TreeViewer to manage the visivility/selection of a collection of “Packages”. The part is named as Package Navigator.

enter image description here

When one Package is ready to be send, the TreeViewer icon shows enter image description here and the button to start the shipment enter image description here should be enabled.

When the package is not ready, the icon is enter image description here and the button (handler) to ship should be disabled.

The code to implement such behavior is:

private TreeViewer viewer;
    @PostConstruct
    public void createComposite(Composite parent, IEnviosService theModel) {
        ...         
        Tree t = (Tree) viewer.getControl();
        t.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                boolean check = false;
                System.out.print("Selection listener ....");
                IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
                if (selection.getFirstElement() instanceof Package) {
                    check = ((Package)selection.getFirstElement()).isReadyToShip();
                    System.out.print("IT'S A PACKAGE....");
                    // evaluate all @CanExecute methods
                    broker.post(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC, check);
                }
                System.out.print("\n");
            }
        });
    }

The handler to execute the shipment is

public class ShipmentHandler {
    @Execute
    public void execute(Shell shell) {
        //TODO
    }
    
    @Inject
    @Optional
    @CanExecute
    public boolean canExecute(@UIEventTopic(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC) boolean checkPackageReady) {
        System.out.println("Inside canExecute method... " + checkPackageReady);
        if (checkPackageReady)
            return true;
        return false;
    }
}

But the button never is disabled, even whe the @canExecute method returns false, for example, after click on Packages 88 , 89 and 110 and 112 shows the following console output whith the button always enabled:

Selection listener  PACKAGE: 88...true
Inside canExecute method... true
Selection listener  PACKAGE: 89...false
Inside canExecute method... false
Selection listener  PACKAGE: 110...false
Inside canExecute method... false
Selection listener  PACKAGE: 112...true
Inside canExecute method... true

Solution

  • I don't think you can mix @CanExecute and @UIEventTopic like that. In any case UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC is a rather special topic which isn't intended to be handled like this.

    The argument to the broker.post(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC is supposed to be an element id, UIEvents.ALL_ELEMENT_ID or a org.eclipse.e4.ui.workbench.Selector, nothing else. The argument selects which handlers are updated.

    So you can't pass the 'checkPackageReady' value directly to the handler, you will have to use some other mechanism - such as a model object that the view and the handler can both inject.

    You could also use the ESelectionService to set the current selection for the part, you can then access this information in the handler:

    View part:

    @Inject 
    ESelectionService selectionService;
    
    ...
    
    public void widgetSelected(SelectionEvent e)
    {
      selectionService.setSelection(viewer.getStructuredSelection());
    
      broker.post(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC, ... selector);
    }
    

    Can execute:

    @CanExecute
    public boolean canExecute(@Named(IServiceConstants.ACTIVE_SELECTION) IStructuredSelection selection, @Named(IServiceConstants.ACTIVE_PART)  MPart part)
    {
      // TODO check part is your part
      // TODO check the selection
    }