Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

activeWhen is not evaluated by IEvaluationService.requestEvaluation #77

Open
pagew2000 opened this issue Nov 22, 2022 · 5 comments
Open

Comments

@pagew2000
Copy link

pagew2000 commented Nov 22, 2022

Defined a handler with activeWhen clause, something like:
<extension point="org.eclipse.ui.handlers"> <handler commandId="com.myapp.userSetting" class="com.myapp.handlers.CustomUserSettingHandler"> <activeWhen> <test property="com.myapp.user.role" value="PWTest"> </test> </activeWhen> </handler> </extension>

If user switches role to "PWTest", it should active this custom handler.

When role is changed, property tester code calls following to request re-evaluation.
IEvaluationService evalService = PlatformUI.getWorkbench().getService( IEvaluationService.class );
evalService.requestEvaluation( "com.myapp.user.role" );

However, I don't see property tester is called after role change.

In debug, I found EvaluationService.requestEvaluation() method goes through EvaluationService.refs list to do the re-eval, but this list only holds enableWhen, not activeWhen.

Here is the trace where "refs" variable is updated, as you can see it's only called for enabled states, not for activewhen:
EvaluationService.addEvaluationReference(IEvaluationReference) line: 225
EvaluationService.addEvaluationListener(Expression, IPropertyChangeListener, String) line: 218
MutableActivityManager.updateActivity(Activity) line: 686
MutableActivityManager.getActivity(String) line: 145
ProxyActivityManager.getActivity(String) line: 55
ActivityPersistanceHelper.loadEnabledStates(Set, Set) line: 226
ActivityPersistanceHelper.loadEnabledStates() line: 198
ActivityPersistanceHelper.() line: 146
ActivityPersistanceHelper.getInstance() line: 113

I am using E4.25.

@opcoach
Copy link
Member

opcoach commented Nov 25, 2022

In the stack trace it is calling loadEnableStates ...

I think that the active state is probably evaluated before the enable state... Active is used to select the right handler among different handlers defined for the same command, depending on current conditions (selection, role, ...). But being active does not mean that your command will be enabled (for instance you select an object X that makes the copyX handler active but you don't have the right to copy it)...

So there is for sure another mechanism that calls the activity state. I don't remember where...

May be you should consider to write now your commands and handler in a model fragment using the E4 paradigm, where the code of your handler contains a @CanExecute method that will be easy to debug in java and that will handle both active and enable states. To do that :

  • create a model fragment in your project
  • add a fragment for xpath:/ commands (element id : xpath:/ feature name commands)
  • add your command inside
  • add a fragment for xpath:/ handlers (element id : xpath:/ feature name handlers)
  • add your handler inside

This model fragment is totally miscible will all your E3 old fashion extensions and you can migrate step by step either commands or handlers when you need it. (For instance you can still use the org.eclipse.ui.menu extension to use this command...). If your command is already defined in another plugin you can import it in the fragment (use the 'imports' node).

Note also that the @Execute annotated method in your handler can receive by injection any needed object available in the context (check them using the context spy (Alt Shift F10)) and especially the current selection using '@Named(IServiceConstants.ACTIVE_SELECTION) IStructuredSelection sel'. (I guess your selection is probably an IStructuredSelection as your software is still coded using E3 paradigms).

To go further, if you need to manage the 'visibility' state, you can also define a menu contribution or any Menu with 'HandledMenuItem' (xpath:/ menuContributions) that will be bound to the command and setup an optional class to compute the visibility state (with @Evaluate annotation), but this is may be not needed ...

The content of your simple fragment :

image

The code of your handler :

image

@pagew2000
Copy link
Author

Thanks for the reply!

The trace I posted is only to show how variable "refs" is constructed and updated, which is used later by IEvaluationService.requestEvaluation, but it doesn't include "activeWhen". "activeWhen" is evaluated when the app is first launched.

My question is how to use "IEvaluationService.requestEvaluation" for activeWhen? According to the document, it should be supported but I don't see how it can work.

We have lots of legacy code, so move it to E4 paradigm is not an option for us.

@mickaelistria
Copy link
Contributor

activeWhen is only evaluated if the contributing bundle is not already active. Once the bundle is active, it's not re-evaluated. Usually, the contribution that support activeWhen can also support enabledWhen or have their interface providing some isEnabled method.

@opcoach
Copy link
Member

opcoach commented Dec 5, 2022

@mickaelistria Are you sure ? activeWhen is often evaluated considering the current selection... In this case it must be evaluated more than once. activeWhen is used to select the handler that must be used at the moment the command is executed. For instance, if you have an activeWhen for the org.eclipse.ui.edit.copy, it will be recomputed depending on the current selection as there are dozens of possible handlers candidates.

@pagew2000
Copy link
Author

I agree with @opcoach , the activeWhen is re-evaluated if I force a selection change. But in my case, I don't want to fire a selection change as it is not a selection change and it would cause other updates which is not desired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants