How to enable global save functionality in Eclipse RCP plugin - eclipse

I have an RCP application based on the 3.x platform. The application enables the user to view and modify a single data set. Some ViewParts are only observers of part of the data set, whilst other can modify data. When a ViewPart modifies same data I want to be able to save the data set, preferably using the standard org.eclipse.ui.file.save command, independent of which ViewPart that currently has focus.
My approach is to define extensions to the plugin.xml like so:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension
point="org.eclipse.ui.menus">
<menuContribution
allPopups="false"
locationURI="toolbar:org.eclipse.ui.main.toolbar">
<toolbar
id="se.file.maintoolbar"
label="File Toolbar">
<command
commandId="org.eclipse.ui.file.save"
label="&Save Project"
style="push"
tooltip="Save the project">
</command>
</toolbar>
</menuContribution>
</extension>
.
.
.
</plugin>
In my implementation of ActionBarAdvisor I register actions:
#Override
protected void makeActions(IWorkbenchWindow window) {
saveProjectAction = ActionFactory.SAVE.create(window);
register(saveProjectAction);
}
My ViewParts, three kinds, all implements the ISaveablePart2, it feels wrong, but haven't seen any other approach. Two of the views control their isDirty() function, so save buttons are enabled when they have focus and if they are dirty, but if one of them is dirty, save should be enabled in all views, not just the dirty view. Enabling save functionality for the third view, without indicating dirty, seems impossible.
Anybody know a better approach? I guess I can create my own handling of saving, but would be good to use standard as much as possible.

You could call firePropertyChange(IWorkbenchPartConstants.PROP_DIRTY) in all the views that should be shown as dirty.

Related

Can the window title include the version number of the core plugin in an Eclipse 4 application with compatibility layer?

In a mixed mode Eclipse RCP application, I'd like to change the application window title to something like "Great App v1.3.22".
I basically have application (3.x based) and product (4.5 (Mars) based) split up into two plugins (following a helpful blog post describing how to use 3.x views in Eclipse 4, I need the CNF).
At the moment, the title is "got" from the org.eclipse.core.runtime.products extension point defined in the product plugin:
<extension
id="my_product_id"
point="org.eclipse.core.runtime.products">
<product
name="Great App"
application="my.application">
</product>
</extension>
Can I use a variable in the <product name> property? If so, what variables are available? Or can this be achieved by "overriding" the window title via the Trimmed Window entry in Application.e4xmi, and again what variables would be available? Or do I have to resort to ancient ways and set the title programmatically in the old ApplicationWorkbenchWindowAdvisor (which, however, wouldn't be available if I was able to switch to a pure E4 app once the CNF is available as a native E4 plugin)?
There are no variables you can use.
You can change the main window title in the LifeCycle class. The #ProcessAdditions method is the earliest you can do this:
#ProcessAdditions
public void processAdditions(MApplication app, EModelService modelService, IApplicationContext applicationContext)
{
MWindow window = (MWindow)modelService.find("id of main trimmed window", app);
window.setLabel("new text");
}
I am not sure where you want to get the version from. One possibility is a property in the product definition:
<extension
id="my_product_id"
point="org.eclipse.core.runtime.products">
<product
name="Great App"
application="my.application">
<property
name="version"
value="1.3.22">
</property>
</product>
</extension>
You will have to maintain this property manually or do something in your build to set it.
You can access this using the IApplicationContext
applicationContext.getBrandingProperty("version")

Extend the Eclipse Project->Clean... Extension point to trigger a method and add some code like validation etc

Recently I need a function that when click the Project->clean item from the Eclipse menu and then do a re-validation to do some checking, so I need to add some code in a method which is triggered by clicking the Project-clean item. And I look up some materials, and seems that Builder and Nature can handle this, and I also try to add some extension in my plugin.xml like,
<extension id="nature" name="Nature" point="org.eclipse.core.resources.natures">
<runtime>
<run class="xxx.xxx.xxx"></run>
</runtime>
<builder id="MyDesigner.builder">
</builder>
</extension>
<extension id="builder" name="Builder" point="org.eclipse.core.resources.builders">
<builder hasNature="true" isConfigurable="false">
<run class="xxx.xxx.MyBuilder"></run>
</builder>
</extension>
And in the MyBuilder class, I add some code in the method "protected void clean(IProgressMonitor monitor) throws CoreException {...}"
After that I run the Eclipse Application to start the sub-studio, and then click the Project->Clean, but the clean method doesn't trigger? So is this way OK to achieve that? Or does anyone have any idea for it? Thanks a lot for all your help!

Property Testers do not load despite forcePluginActivation. For popup menu enablement

I am in charge of refactoring the popup menus in my company's Eclipse Plugin to use the new commands/handler/menu extension point scheme. We had some business logic for when certain menu items should enabled or not, and this was handled through the onSelectionChanged method of the SelectionListener they applied to the action. I am now trying to control the enablement using a custom PropertyTester, but it seems that my custom PropertyTesters are not being loaded. I've followed Eclipse's doc as well as any tutorials I could find online and for some reason it just does not want to work. Even if I simply set the "test" method to return true, it doesn't work because the tester is never even loaded (I threw some break points in and they never get hit). I've tried setting the "forcePluginActivation='true'" flag in the test in the xml, but that also does not remedy the situation. Here is some code, with the company name replaced by "company" and the product replaced by "product"...
COMMAND XML
<extension
point="org.eclipse.ui.commands">
<command
categoryId="com.company.product.android.core.category2"
id="com.company.product.android.core.commands.convertToProduct"
name="Convert to product Android Project"
description="The resources, jars and native library to begin developing an product for Android project application will be added to the Android project">
</command>
<category
id="com.company.product.android.core.category2"
name="Product Tools">
</category>
</extension>
HANDLER XML
<extension
point="org.eclipse.ui.handlers">
<handler
class="com.company.product.android.core.commands.ConvertToProduct"
commandId="com.company.product.android.core.commands.convertToProduct">
<enabledWhen>
<reference
definitionId="com.company.product.android.core.expressions.productProject">
</reference>
</enabledWhen>
</handler>
</extension>
DEFINITIONS XML
<extension>
point="org.eclipse.core.expressions.definitions">
<definition
id="com.company.product.android.core.expressions.androidProjectNature">
<with variable="selection">
<iterate ifEmpty="false">
<test
property="org.eclipse.core.resources.projectNature"
value="com.android.ide.eclipse.adt.AndroidNature">
</test>
</iterate>
</with>
</definition>
<definition
id="com.company.product.android.core.expressions.productProject">
<with variable="selection">
<iterate ifEmpty="false">
<test
property="com.company.product.android.expressions.productProjectProperty"
forcePluginActivation="true">
</test>
</iterate>
</with>
</definition>
</extension>
MENU XML
<extension
point="org.eclipse.ui.menus">
<menuContribution
locationURI="popup:org.eclipse.ui.navigator.ProjectExplorer#PopupMenu?after=additions">
<menu
icon="icons/wht_ws.gif"
id="com.company.product.android.core.tools"
label="Product Tools">
<visibleWhen>
<reference
definitionId="com.company.product.android.core.expressions.androidProjectNature">
</reference>
</visibleWhen>
<command
commandId="com.company.product.android.core.commands.convertToProduct"
label="Convert to Product Android Project"
tooltip="The resources, jars and native library to begin developing an product for Android project application will be added to the Android project.">
</command>
</menu>
</menuContribution>
</extension>
PROPERTY TESTER XML
<extension
point="org.eclipse.core.expressions.propertyTesters">
<propertyTester
class="com.company.product.android.core.expressions.ProductProjectTester"
id="com.company.product.android.core.expressions.productProjectTester"
namespace="com.company.product.android.core.expressions"
properties="productProjectProperty"
type="java.lang.Object">
</propertyTester>
</extension>
PROPERTY TESTER JAVA
package com.company.product.android.core.expressions;
import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.PlatformUI;
import com.company.product.android.core.ProjectUtils;
public class ProductProjectTester extends PropertyTester {
public ProductProjectTester() {
System.out.println("I AM PRODUCT PROJECT TESTER, AND I HAVE BEEN CREATED");
}
#Override
public boolean test(Object receiver, String property, Object[] args,
Object expectedValue) {
//IJavaProject project = null;
//ISelectionService selectionService =
// PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService();
//ISelection selection = selectionService.getSelection();
//boolean enabled = ProjectUtils.isSingleProjectSelected(selection);
System.out.println("I entered the test method");
boolean enabled = false;
System.out.println("The receiver is a " + receiver.getClass().toString());
IJavaProject project = (IJavaProject)receiver;
//if (enabled && selection instanceof StructuredSelection) {
//project = ProjectUtils.getJavaProject();
if (project != null) {
enabled = ProjectUtils.hasNeedVersion(project)
&& (!ProjectUtils.isProductAndroidProject(project.getProject()));
}
//}
return enabled;
}
}
For the java code, I tried both the current implementation and what is commented out as well. I have tried a lot of different variations that I saw in tutorials that worked for others but not me. The messages are never printed to console, and if i set breakpoints in the constructor or test method, they are never hit. Please let me know if additional information would be useful...
I use PropertyTester for my Project and it works fine
In your DEFINITIONS XML
You do not make a proper reference to your PropertyTester definition:
<definition
id="com.company.product.android.core.expressions.productProject">
<with variable="selection">
<iterate ifEmpty="false">
<test
property="com.company.product.android.**core**.expressions.productProjectProperty"
forcePluginActivation="true">
</test>
</iterate>
</with>
</definition>
Then in your MENU.XML
You should make a reference to the right definition (productProject instead of androidProjectNature)
<menu
icon="icons/wht_ws.gif"
id="com.company.product.android.core.tools"
label="Product Tools">
<visibleWhen>
<with variable="activeMenuSelection">
<iterate ifEmpty="false">
<reference
definitionId="com.company.product.android.core.expressions.productProject"/>
</iterate>
</with>
</visibleWhen>
<command
commandId="com.company.product.android.core.commands.convertToProduct"
label="Convert to Product Android Project"
tooltip="The resources, jars and native library to begin developing an product for Android project application will be added to the Android project.">
</command>
</menu>
Finally you don't need the EnableWhen Tag in your HANDLER.XML
I hope this helps
Alright so after 2 days of fighting with this, I was not able to get it to work this way. I followed at least 10 different tutorials on how to get custom property testers to work, but to no avail. I went as far as using the startup extension point to force the plugin to load early. Used a SelectionChangedListener to request updates from the evaluation server anytime the project explorer selection changed. NOTHING seemed like it was going to make the custom property tester work. It simply would not load the property testers... they would never get called by anything, despite everything saying it was set up fine, and perfectly mirror all the tutorials I followed.
Eventually I got tired of trying to make that work and looked for an alternative. What I ended up finding was this: http://blog.eclipse-tips.com/2009/02/commands-part-5-authentication-in-rcp.html
I implemented a SourceProvider to have a variable with values corresponding to different project states. I then use , and check which of the possible values it is. Finally, when the plugin loads, I hook a SelectionChangedListener to the PackageExplorer's viewer, so that any time a selection change occurs, then the logic is reevaluated and that variable is changed if needed. Although it's not the ideal way I wanted to do it, it works, and it's not deprecated. I simply couldn't waste more time trying to get the property testers to work...
Hope this helped someone!
I had a similar issue but wasn't aware of the existence of forcePluginActivation.
So I forced the plug-in activation using
/**
* Necessary to have working menu right from the start
*/
public class Startup implements IStartup {
#Override
public void earlyStartup() {
// this is necessary to have working menu right from the start
}
}
and this extensions :
<extension point="org.eclipse.ui.startup">
<startup
class="com.example.package.Startup">
</startup>
</extension>
I happened to find myself in the exact same situation: everything scrupulously configured to the very detail (so I was convinced and I was true except one thing missing), still it would not call my property tester. Nothing happened at all, no log. So I started debugging down into the abyss of the Eclipse 3.7 runtime environment and found, after three hours of patiently digging, a somewhat surprising error:
java.lang.NoClassDefFoundError: org/eclipse/core/expressions/PropertyTester
Unfortunately it got swallowed again shortly after being raised inside the org.eclipse.core.internal.expressions framework, inside class TypeExtension, with no log whatsoever and not giving any chance to the developer to discover the error without debugging and not even with the Eclipse debug log enabled.
But the nature of the error was straightforward: the plugin containing my property tester was missing the dependency to the Eclipse plugin
org.eclipse.core.expressions
After including it as a required plugin it all seamlessly worked, the property tester was called and the context menu shown properly.
So consider your plugin's dependencies as well while trying to make your property tester work.
Hope this helps.
I was unable to get PropertyTesters working as well. Eventually gave up on them and moved to SourceProviders. Nice writeup on how to implement them here:
How to enable and disable menu items upon condition with using SourceProvider (eclipse rcp Indigo 3.7)

How do I have my custom toolbar have its items updated via IElementUpdater

I've implemented a custom toolbar in my RCP application. I'm also using the org.eclipse.ui.menus extension to contribute commands to the custom toolbar.
<extension
point="org.eclipse.ui.menus">
<menuContribution
locationURI="toolbar:com.my.custom.toolbar.identifier.toolbar">
<command
commandId="com.my.command.id"
icon="icons/my_icon.png"
style="toggle"
tooltip="My Toggle Tooltip">
</command>
</menuContribution>
</extension>
I've written the code that finds these IConfigurationElements and turns them into CommandContributionItems which I use to add them to my custom toolbar.
I have some toolbar items that are of type toggle, and I need these to update their UI using the IElementUpdater interface that the command's handler implements.
I also contribute this command to a standard Eclipse menu... like "toolbar:org.eclipse.ui.main.toolbar" and its toggle state is updated via the IElementUpdater when appropriate.
I'm probably missing something in my custom toolbar that hooks it up to the IElementUpdater, but I have no idea where to start looking to make this work.
I've used the IElementUpdater, but not for cases to update the toggle state, as this should be done by the connection to the respective Command. There exist, however, some problems in Eclipse 4 which I have already started to point out in a blog article.
What Eclipse variant are you using? 3.x or 4.x? There exists a bug in 4.x concerning the synchronization of contributions and their command states.

Override builtin perspective layout in Eclipse-RCP product

Is it possible to override the layout of a built-in perspective in my Eclipse-RCP product?
In particular, I wish to add a custom view and change the layout of the Debug perspective. I know how to do it with a custom perspective (IPerspectiveFactory.createInitialLayout()). I'd want that my custom layout to be permanent -survive the "Reset perspective" command.
Create a class that implements IPerspectiveFactory.
Add a perspectives extension to your plugin.xml. Here's one of mine.
<extension point="org.eclipse.ui.perspectives">
<perspective
class="gov.bop.cobolsupport.perspectives.CobolPerspectiveFactory"
icon="icons/ispf_editor.gif"
id="gov.bop.cobolsupport.CobolPerspective"
name="Cobol"/>
</extension>
Your users can change your perspective, and save their changes if they wish. That's built into Eclipse.
However, when you extend your perspective, the Reset Perspective command resets the perspective to how you defined it in your Perspectivefactory class.
Extending a perspective is possible by using the extension point org.eclipse.ui.perspectiveExtensions.
Plug-ins can add their own action sets, views, and various shortcuts
to existing perspectives by contributing to the
org.eclipse.ui.perspectiveExtensions extension point.
To extend the default debug perspective paste the following code in your plugin.xml:
<extension
point="org.eclipse.ui.perspectiveExtensions">
<perspectiveExtension
targetID="org.eclipse.debug.ui.DebugPerspective">
<view
ratio="0.5"
relative="org.eclipse.ui.views.TaskList"
relationship="right"
id="com.jens.customdebug.views.SampleView">
</view>
</perspectiveExtension>
</extension>
You have to define a relative view (in my case the task view named org.eclipse.ui.views.TaskList) and the id of your own view (in my case com.jens.customdebug.views.SampleView)
Source:
To get further information how to use this extension point, take a look here.
For the configuration markup of this extension point you may also take a look at this page.