Refresh menu item in view - java

Context
I'm building a plugin for eclipse 3.4 and more.
I have a view with id mrp.view with a menuContribution set to toolbar:mrp.view.
This menuContribution has some command, and I have this one:
<handler
class="mrp.handlers.export"
commandId="mrp.commands.export">
</handler>
<command
commandId="mrp.commands.export"
label="My command"
style="push">
</command>
My handler, mrp.handlers.export has a dynamic ìsEnabled()` method, looking like that :
#Override
public boolean isEnabled() {
return !getMySelection().isEmpty();
}
Question
How can I refresh the button on my toolbar when data changed ?
(refresh is done automatically if I click anothr button of the toolbar, but if I don't...)
I tried..
ICommandService service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class);
service.refreshElements("mrp.commands.export", null);
But it doesn't seems to do anything.
Also this one:
public class Export extends AbstractHandler implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
setBaseEnabled(!getSelection().isEmpty());
}
// ....
}
It is called, but the icon on my view's menu is not refreshed (on eclipse 3.7).
Did I do something wrong ?

Your handler must fire an event when it's enablement changes. If you have the change update your handler using org.eclipse.core.commands.AbstractHandler.setBaseEnabled(boolean) it will fire the required event.

Thanls to Paul Webster's answer, I got it working.
public class Export extends AbstractHandler implements PropertyChangeListener {
public Export() {
Activator.getDefault().AddListener(this);
setBaseEnabled(!getMySelection().isEmpty());
}
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
// My handler
return null;
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(Activator.EVENT_SELECTION_CHANGED)) {
boolean before = isEnabled();
boolean after = !getMySelection().isEmpty();
if (after != before) {
setBaseEnabled(after);
}
}
}
}

Related

The correct way to edit internal java files in Android

I would like to implement changes in the functionality of GestureDetector.java. The easy way should be just to create a custom GestureDetector that extends from the original one, and to implement the changes:
public class CustomGestureDetector extends GestureDetector {
public CustomGestureDetector(OnGestureListener listener, Handler handler) {
super(listener, handler);
}
public CustomGestureDetector(OnGestureListener listener) {
super(listener);
}
public CustomGestureDetector(Context context, OnGestureListener listener) {
super(context, listener);
}
public CustomGestureDetector(Context context, OnGestureListener listener, Handler handler) {
super(context, listener, handler);
}
public CustomGestureDetector(Context context, OnGestureListener listener, Handler handler, boolean unused) {
super(context, listener, handler, unused);
}
#Override
public void setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener) {
super.setOnDoubleTapListener(onDoubleTapListener);
}
#Override
public void setContextClickListener(OnContextClickListener onContextClickListener) {
super.setContextClickListener(onContextClickListener);
}
#Override
public void setIsLongpressEnabled(boolean isLongpressEnabled) {
super.setIsLongpressEnabled(isLongpressEnabled);
}
#Override
public boolean isLongpressEnabled() {
return super.isLongpressEnabled();
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(ev);
}
#Override
public boolean onGenericMotionEvent(MotionEvent ev) {
return super.onGenericMotionEvent(ev);
}
}
But I would like to override the function onTouchEvent and implement very specific changes so I cannot just implement them here and then call the super class, nor take the whole code for this function and copy it here because it relies on other variables.
In such case, should I create an alternative GestureDetector and then import the custom one in my project, instead of the regular one?
If it matters, the default behavior of the detector is to disable the scrolling function when long pressed it triggered:
case MotionEvent.ACTION_MOVE:
if (mInLongPress || mInContextClick) {
break;
}
But I would like it to still fire while the user is long pressing, and then scrolling.
Also, another problem is that I cannot just copy the code from GestureDetector.java to my own class in my project, since it actually contains many errors and then it won't compile anymore.

onShow and onHide listener in ViewPart - Java Eclipse RCP

I would like to trigger method when ViewPart is being hidden (hidden == it starts to be invisible) and it is being opened (opened == it starts to be visible). Something like:
void onHide(){removeAllListeners();}
void onShow(){refreshView();}
I tried to use:
getSite().getPage().addSelectionListener(new ISelectionListener() {
#Override
public void selectionChanged(final IWorkbenchPart workbenchPart, final ISelection selection) {
System.out.println("TEST");
}});
but it works only when ViewPart become invisible and it is not triggered when become visible
This has nothing to do with selection being changed. Use an IPartListener2.
You can use IPartListener2 (or the older IPartListener) to listen to changes to the state of all parts.
getSite().getPage().addPartListener(new IPartListener2() ....
You probably want to react to the 'partHidden' and 'partVisible' methods. In these methods you will need to check that the event is for your part:
IViewPart myViewPart = ... your view part
#Override
public void partHidden(IWorkbenchPartReference ref) {
IWorkbenchPart part = ref.getPart(false);
if (part == myViewPart) {
// Event is for your view
}
}
#Override
public void partVisible(IWorkbenchPartReference ref) {
IWorkbenchPart part = ref.getPart(false);
if (part == myViewPart) {
// Event is for your view
}
}

org.eclipse.ui.popupMenus link is grayed out

I created my own eclipse view and is trying to add a link in a popup menu. I am able to add the link but it's grayed out. I wonder how I can activate the link. I just want to be able to click on the link and trigger run(). DeleteAction is the class i want to trigger. SegmentReferencesView is the view I created. Would be very thankful for help.
This is from the plugin.xml:
<extension point="org.eclipse.ui.popupMenus">
<viewerContribution
id="se.test.views.categories.segmentreferences.ui.views"
targetID="se.test.views.categories.segmentreferences.ui.views.SegmentReferencesView">
<action
class="se.test.views.categories.segmentreferences.ui.views.DeleteAction"
enablesFor="1"
icon="icons/Delete.gif"
id="se.test.views.categories.segmentreferences.ui.views.DeleteReferenceAction"
label="Do action"
menubarPath="additions-ext">
</action>
</viewerContribution>
This is the Java class:
public class DeleteAction implements IViewActionDelegate {
#Override
public void init(org.eclipse.ui.IViewPart view) {
super.init(view);
};
#Override
public void run(IAction action) {
}
}
Your view must set the view site 'Selection Provider'. This is used by the menu system to find out what is selected. If you are using a TableViewer or TreeViewer you can just do:
getSite().setSelectionProvider(viewer);
in the view code immediately after you have created viewer (which should be the TableViewer or TreeViewer).
I managed to get the link to work by extending org.eclipse.core.commands.AbstractHandler in the DeleteAction class. I don't know if this is the best way to do it but it's working for now.
public class DeleteAction extends AbstractHandler implements IViewActionDelegate {
#Override
public void init(org.eclipse.ui.IViewPart view) {
// Not used
}
#Override
public void run(IAction action) {
System.out.println("run"); //$NON-NLS-1$
}
#Override
public void selectionChanged(IAction action, ISelection selection) {
// Not used
}
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
return null;
}
}

PopupDateField Listener

I've got a PopupDateField with a ValueChangeListener.
Is there a way to differentiate if the Event was fired from an .setValue()-Call or an User-Input?
I want the Event to be excuted only if the user changes the value, not if it was changed by program.
I've made a dirty Workaround by removing the ValueChangListener before setting a new Value and adding it afterwards, but I'm thankfull for better solutions...
private static void setDateFieldValue(final PopupDateField dateField, Date value) {
Collection<Property.ValueChangeListener> listeners = (Collection<Property.ValueChangeListener>)dateField.getListeners(Property.ValueChangeEvent.class);
listeners.forEach(new Consumer<Property.ValueChangeListener>() {
#Override
public void accept(Property.ValueChangeListener listener) {
dateField.removeValueChangeListener(listener);
}
});
dateField.setValue(value);
listeners.forEach(new Consumer<Property.ValueChangeListener>() {
#Override
public void accept(Property.ValueChangeListener listener) {
dateField.addValueChangeListener(listener);
}
});
}

Eclipse RCP - add a Listener right after a View has been created

Greetings fellow Stackoverflowians,
I am developing an Eclipse RCP application, and must add a SelectionListener to the Project Explorer view the moment after it's created.
I've realized that I cannot do this in the Activator of my contributing plug-in, whereas in order to get the SelectionService via PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService() I must have an active workbench window (which is null when the Activator start() is called)
So my question:
When can I get the SelectionService so that the Project Explorer view has been created and is visible, but the user has not yet been able to 'push any buttons'?
Any opinions and suggestions are appreciated!
When you really want to track user selection from startup without having a UI (like a view) that can register an ISelectionListener on creation, you can us a startup hook.
Eclipse provides the extension point org.eclipse.ui.startup. It accepts a class that implements the interface org.eclipse.ui.IStartup. It will be called after the UI has been created, so the ISelectionService is already available then:
public class StartupHook implements IStartup, ISelectionListener {
#Override
public void earlyStartup() {
final IWorkbench workbench = PlatformUI.getWorkbench();
workbench.addWindowListener(new IWindowListener() {
#Override
public void windowOpened(IWorkbenchWindow window) {
addSelectionListener(window);
}
#Override
public void windowClosed(IWorkbenchWindow window) {
removeSelectionListener(window);
}
/* ... */
});
workbench.getDisplay().asyncExec(new Runnable() {
public void run() {
for (IWorkbenchWindow window : workbench.getWorkbenchWindows()) {
addSelectionListener(window);
}
}
});
}
private void addSelectionListener(IWorkbenchWindow window) {
if (window != null) {
window.getSelectionService().addSelectionListener("org.eclipse.ui.navigator.ProjectExplorer", this);
}
}
private void removeSelectionListener(IWorkbenchWindow window) {
if (window != null) {
window.getSelectionService().removeSelectionListener("org.eclipse.ui.navigator.ProjectExplorer", this);
}
}
#Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
// TODO handle selection changes
System.out.println("selection changed");
}
}
Note that it is discouraged to use this UI startup hook as it forces OSGi to activate your bundle very early (and so all dependent bundles too!) and slows down system startup. So please make sure that your bundle is neat and slim. Reduce bundle dependencies to a minimum. Sometimes it is necessary move the startup hook code into a separate bundle to achieve that.
You could add your selection listener in the ApplicationWorkbenchWindowAdvisor.postWindowOpen() method (at this point you can be sure workbench is already created). If you want to add it, when 'Project explorer view' gets visible, then it is possible to do something like this:
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().addPartListener(new PartAdapter() {
#Override
public void partVisible(IWorkbenchPartReference partRef) {
if ("org.eclipse.ui.navigator.ProjectExplorer".equals(partRef.getId())) {
// add selection listener
}
}
});
UPD: OK, if you don't have access to AppliationWorkbenchWindowAdvisor (which is weird, if you are developing Eclipse RCP product), then ASAIK, there is no clean solution to get notified about availability of the UI. So one of such solutions could be adding a job, which would wait for the UI to be initializd. In your plugin Activator.start() method consider adding following job (sure you can extract it to separate class and improve in many ways, but for the beginning it should be sufficient):
Job j = new Job("") {
#Override
protected IStatus run(IProgressMonitor monitor) {
final boolean[] workbenchAvailable = new boolean[] { false };
Display.getDefault().syncExec(new Runnable() {
#Override
public void run() {
if (PlatformUI.isWorkbenchRunning() && PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null) {
workbenchAvailable[0] = true;
}
}
});
if (workbenchAvailable[0]) {
System.out.println("Workbench is available");
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run() {
ISelectionService selectionService =
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService();
System.out.println(selectionService);
}
});
} else {
System.out.println("Waiting for the Workbench ...");
schedule(1000);
}
return Status.OK_STATUS;
}
};
j.schedule();

Categories