visibleWhen expression is not always evaluated when a custom source changes [message #326061] |
Thu, 06 March 2008 12:22  |
Eclipse User |
|
|
|
I'm using Eclipse 3.4M5. I have a visibleWhen expression defined for a
toolbar contribution to a view and the expression only gets evaluated
when the view is the active view. The expression uses a <with> tag that
checks a custom source provider's property. This property can change
independently of the active part. Is this a bug or is there a way to
have the expression always evaluated when the source provider changes?
It appears that the postingChanges property on the EvaluationReference
object is false when the view is not active and as a result the
expression doesn't get evaluated (in
EvaluationAuthority.refsWithSameExpression()) after the source provider
fires a source changed event.
I created a test case using a test plug-in and the Eclipse IDE where I
have a source provider that exposes a custom source name called
"customsource.visible". The values are true or false. I put an action
on the main menu that toggles the property. I then added an action to
the Package Explorer. This action should only be visible when
customsource.visible=true. If Package Explorer is the active part this
works. If it is not the active part it doesn't work.
Here's the xml for the menu contribution:
<menuContribution
locationURI="toolbar:org.eclipse.jdt.ui.PackageExplorer?after=additions ">
<command
commandId="com.sas.csp.test"
id="com.sas.csp.test.toolitem"
label="Test Action"
style="push"
tooltip="Test Action">
<visibleWhen
checkEnabled="false">
<with
variable="customsource.visible">
<equals
value="true">
</equals>
</with>
</visibleWhen>
</command>
</menuContribution>
Here's the definition of the custom source provider:
public class CustomSourceProvider extends AbstractSourceProvider {
public static final String CUSTOM_SOURCE = "customsource.visible";
private boolean _on;
public void dispose() {
// empty
}
public Map<String, Boolean> getCurrentState() {
Map<String, Boolean> map = new HashMap<String, Boolean>(1);
map.put(CUSTOM_SOURCE, _on);
return map;
}
public void toggle() {
_on = !_on;
fireSourceChanged(ISources.WORKBENCH, getCurrentState());
}
public String[] getProvidedSourceNames() {
return new String[] { CUSTOM_SOURCE };
}
}
Here's how I register the source provider in the activator's start():
IEvaluationService service =
(IEvaluationService)PlatformUI.getWorkbench().getService(IEv aluationService.class);
service.addSourceProvider(getCustomSourceProvider());
Thanks in advance for any help,
-Ryan
|
|
|
|
Re: visibleWhen expression is not always evaluated when a custom source changes [message #326534 is a reply to message #326080] |
Sun, 23 March 2008 00:46   |
Eclipse User |
|
|
|
Paul,
Thanks very much for the response. I've included some comments and
questions below.
-Ryan
Paul Webster wrote:
> This is a feature. A view's toolbar visibleWhens are only re-evaluated
> when the view is active. It works at the window level, a window's
> toolbar visibleWhens are only re-evaluated when that window is active.
> Otherwise changing the global state (which is what a source is) would
> cause "uninteresting" components like views your not working on,
> secondary windows that are not active, etc to have their toolbar
> flickering.
>
I'm trying to detect a change in the global state of my application in
all of my views. Perhaps I should describe the design of my application
to illustrate what I'm trying to do...
The application that I work on is an object manager type application.
That is, it contains views for viewing and managing various objects in
our system (each object type has its own view, which contains either a
table or a tree table...6 views total). We have a root object which
contains or has relationships with various other objects. Of the owned
or related objects, each has its own view for displaying and managing
them. The root object has a property which controls which behaviors are
available on the subordinate objects (type 1 allows more behavior, type
2 allows less). When the user enters the application they "open" one of
the available root objects. All views are then filtered based on this
root object. The user can then choose to change the "open" root object.
If the user changes the open object from type 1 to type 2, any open
views need to adapt to either allow or restrict the behaviors based on
this change.
In my previous post, I described a source provider. I created a source
provider that fires a change whenever the open object changes (the
global state for my application). I would like for the actions
contributed to the local menus, local tool bars and context menus of the
views in my application to have their visibleWhen conditions
re-evaluated when this event occurs. For example, if the open object is
type 1 several actions should appear on the action bars and if the open
object is type 2 they should disappear. As described in the previous
post I can only get this to occur for the active view whenever of the
change takes place.
I understand that in general it may not be a good idea for all views to
react to a global change especially for larger open applications like
the Eclipse IDE, however, this is the behavior I would like in my more
closed application.
Can you suggest a way for me to get this behavior to occur? Is there
another way of designing my views or for contributing such that I can
have actions appear and disappear in this manner?
Should I request a new feature? If so I suspect it wouldn't be
something that would or could be completed for 3.4 which is what I will
be shipping with. Perhaps views could register as interested parties
for source changes to enable re-evaluation of only a subset of
non-active views?
|
|
|
Re: visibleWhen expression is not always evaluated when a custom source changes [message #326611 is a reply to message #326534] |
Wed, 26 March 2008 10:31  |
Eclipse User |
|
|
|
Ryan Norris wrote:
> Can you suggest a way for me to get this behavior to occur? Is there
> another way of designing my views or for contributing such that I can
> have actions appear and disappear in this manner?
There aren't any easy ways, that I can think of. The "guy" causing your
problems is in org.eclipse.ui.internal.ViewReference.createPartHelper()
....
IMenuService menuService
= (IMenuService) site.getService(IMenuService.class);
This restricts your view toolbar and menu to your site (active view).
You can't control the items added to your view location URI, but you
could use add them via a secondary ID that you control.
i.e. in your createPartControl(*):
IMenuService menuService = PlatformUI.getWorkbench()
.getService(IMenuService.class);
if (getViewSite().getActionBars().getToolBarManager() instanceof
ContributionManager) {
menuService.populateContributionManager(
(ContributionManager) site.getActionBars().getToolBarManager(),
"toolbar:my.view.id.special.toolbar");
}
Because this is the global menu service, it wouldn't have the "active
view" restriction on it.
And of course, read the javadoc and make sure you release it (using the
same menu service) in your dispose() method:
IMenuService menuService = PlatformUI.getWorkbench()
.getService(IMenuService.class);
// ... etc
As an aside, it's a service best practice to get the services you when
you need them, as opposed to storing them in a field.
>
> Should I request a new feature? If so I suspect it wouldn't be
> something that would or could be completed for 3.4 which is what I will
> be shipping with. Perhaps views could register as interested parties
> for source changes to enable re-evaluation of only a subset of
> non-active views?
You can of course file a new feature ... I'd be looking for some
suggestions on a simple way to implement this kind of control, however.
PW
--
Paul Webster
http://wiki.eclipse.org/Platform_Command_Framework
http://wiki.eclipse.org/Command_Core_Expressions
http://wiki.eclipse.org/Menu_Contributions
http://wiki.eclipse.org/Menus_Extension_Mapping
http://help.eclipse.org/help33/index.jsp?topic=/org.eclipse. platform.doc.isv/guide/workbench.htm
|
|
|
Powered by
FUDForum. Page generated in 0.03724 seconds