Eclipse plugin - add mouse listener to an editor everytime its opened - eclipse

I am developing an Eclipse plugin and I need to store the click location in X and Y axis coordinates.
So far, I am doing this by using the org.eclipse.ui.IStartup interface and using this in the class implementing it:
#Override
public void earlyStartup() {
IWorkbench wb = PlatformUI.getWorkbench();
wb.addWindowListener(generateWindowListener());
}
And the in the given method I do this:
private IWindowListener generateWindowListener()
{
return new IWindowListener() {
private MouseListener clickMouseListener = new ClickMouseListener();
#Override
public void windowOpened(IWorkbenchWindow window) {
//Nothing
}
#Override
public void windowDeactivated(IWorkbenchWindow window) {
System.out.println("deactivaed");
IWorkbenchPage activePage = window.getActivePage();
activePage.getActiveEditor().getAdapter(org.eclipse.swt.widgets.Control.class).addMouseListener(clickMouseListener);
}
#Override
public void windowClosed(IWorkbenchWindow window) {
//Nothing
}
#Override
public void windowActivated(IWorkbenchWindow window) {
System.out.println("activated");
IWorkbenchPage activePage = window.getActivePage();
activePage.getActiveEditor().getAdapter(org.eclipse.swt.widgets.Control.class).addMouseListener(clickMouseListener);
}
};
}
So I basically register a listener to the general workbench with the intent to register a new MouseListener - where I save the coordinates - on newly opened editors.
This, however, works only if the entire eclipse window is minimized/maximized, as this listener is bound to the main window. If a new editor is opened, nothing happens (as it probably should work).
I would like to register new MouseListeners everytime a new editor is opened/activated/clicked on - so I can register them to the editor right when a new editor is opened. How can I subscribe/listen to any events related to editors (mostly activated/open new editor) so I can then subscribe a MouseListener to the editor and get current X and Y axis of the mouse-clicks?
Thank for any suggestions.

Use an IPartListener to listen to part events in a workbench window:
IPartService partService = window.getPartService();
partService.addPartListener(listener);
This will tell you about all editors (and views) being opened, closed, activiated, ....
In the early startup method the workbench window is not yet available. Use Display.asyncExec to delay running your code until the UI initialization is complete:
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run() {
IPartService service = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService();
......
}
});

Related

Close Eclipse ViewPart tab when createPartControl function fails when launched from "Quick Access"?

The default behaviour when creating a new Eclipse ViewPart is to show the new tab regardless of what happens in the createPartControl function. For example, if didn't create anything, no widgets, nothing, a blank tab will be shown. I don't like this behaviour. I want to close that tab if initialization in createPartControl fails.
Now, I have a mouse-button-context-menu handler that can do this, e.g.
public class MyPartMB3Handler extends AbstractHandler {
#Override
public Object execute(final ExecutionEvent event)
throws ExecutionException {
// Create a view and show it.
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event);
IWorkbenchPage page = window.getActivePage();
try {
MyPart viewPart = (MyPart)page.showView(MyPart.ID);
if(!viewPart.isCreated()) {
page.hideView(viewPart);
}
}
catch(PartInitException e) {
e.printStackTrace();
}
return null;
}
}
The isCreated function is a little hack that lets me know if my ViewPart initialization fails, e.g.
public class MyPart extends ViewPart {
public static final String ID = "com.myplugin.MyPart";
private Composite _parent = null;
#Override
public void createPartControl(Composite parent) {
if(!MyPlugin.createPartControl(parent) { // Some common part creation code I use.
//PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().hideView(this);
return;
}
_parent = parent;
}
#Override
public void setFocus() {
}
public boolean isCreated() {
return _parent != null;
}
}
The problem arises when I launch this ViewPart from the Eclipse "Quick Access" field. I don't own the handler now. From an exception I forced, the handler might be org.eclipse.ui.internal.e4.compatibility.CompatibilityPart.createPartControl or org.eclipse.ui.internal.e4.compatibility.CompatibilityView.createPartControl or org.eclipse.ui.internal.e4.compatibility.CompatibilityPart.create.
I tried hiding the view inside the createPartControl function (see the commented line above), but Eclipse did not like that and spewed a pile of exceptions.
I thought maybe I could throw a PartInitException in createPartControl, but Eclipse tells me I'm not allowed to do that.
So, how do I get my menu handler behaviour when launching from "Quick Access"?
An underlying question might be, is there a better/proper way to achieve this behaviour?
You can close the view by running the hideView asynchronously after the createPartControl has finished - like this:
#Override
public void createPartControl(Composite parent) {
parent.getDisplay().asyncExec(new Runnable() {
#Override
public void run()
{
getSite().getPage().hideView(MyPart.this);
}
});

GWT is making an unexpected event call

My code is below: I am seeing that on running the app the loadWidget method gets invoked even when the adminLink is not clicked. This is not want I want, but I'm not sure what is causing the issue. Please advise
public class LoginModule implements EntryPoint {
LoginPopup loginPopup;
private class LoginPopup extends PopupPanel {
public LoginPopup() {
super(true);
}
public void loadWidget(){
System.out.println("I am called 1");
CommonUi cUi = new CommonUi();
//#342 moved code to common area
FormPanel loginForm = cUi.getLoginFormUi();
setWidget(loginForm);
}
}
#Override
public void onModuleLoad() {
//#251 improved login popup ui.
final Anchor adminLink = new Anchor("User Login");
// final Label adminLink = new Label("User Login");
adminLink.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// Instantiate the popup and show it.
loginPopup = new LoginPopup();
loginPopup.loadWidget();
loginPopup.showRelativeTo(adminLink);
loginPopup.show();
}
});
if(RootPanel.get("admin") !=null)
RootPanel.get("admin").add(adminLink);
}
}
Running Dev Mode, set a breakpoint in that method in your Java IDE, and take a look at the current stack, what code is calling that method. If that is the only code in your app, then this only appears to be invokable from that onClick handlers, so it is a matter of figuring out why that is being invoked.

What are wrong with this code on Activating/Deactivating IHandlerActivation of Command Eclipse Plugin Development

So, I have 2 commands, which are identified by PLAY_COMMAND_ID and STOP_COMMAND_ID. Each of command have each handler, respectively playHandler and stopHandler (these are extending AbstractHandler class).
These commands are contributed to my view's toolbar in Button style. Basically what I want is initially the PLAY_COMMAND is active but the STOP_COMMAND not. When the PLAY_COMMAND is clicked, then it will activate the STOP_COMMAND then deactivate itself(PLAY_COMMAND). And vice versa when the STOP_COMMAND clicked.
So what I do is like this. At first it works (I clicked play-button, then stop-button is activated and play-button disabled. I clicked stop-button, then play-button is active and stop-button is disabled. But when I clicked the play-button again, the play-button is still active when the stop-button is active too). So what's wrong with my code here:
private AbstractHandler playHandler, stopHandler, pauseHandler, stepHandler;
private IHandlerActivation playActivation, stopActivation, pauseActivation, stepActivation;
private void createHandlers(){
final IHandlerService handlerService = (IHandlerService)getSite().getService(IHandlerService.class);
playHandler = new AbstractHandler() {
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
handlerService.deactivateHandler(playActivation);
if(stopActivation == null){
stopActivation = handlerService.activateHandler(STOP_COMMAND_ID, stopHandler);
} else {
handlerService.activateHandler(stopActivation);
}
return null;
}
};
stopHandler = new AbstractHandler() {
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
handlerService.deactivateHandler(stopActivation);
handlerService.activateHandler(playActivation);
return null;
}
};
playActivation = handlerService.activateHandler(PLAY_COMMAND_ID, playHandler);
}
}
The createHandlers() method is called at the end of createPartControl(Composite parent) method in my View.
Okay, so here what I found. The IHandlerActivation, that is returned when calling activateHandler(IHandlerActivation) method, when it is deactivated, can't be used again in activating the same handler. So the solution is try calling handlerService.activateHandler(commandID, playHandler) instead of calling handlerService.activateHandler(playActivation).

Is there a way to have Eclipse flash its taskbar icon once a time consuming task finishes?

I often minimize Eclipse to read or work on something else for a few minutes while I wait for it to do something (e.g., run a large JUnit test suite, synchronize a huge number of files with a repo, run a long Ant build, etc.). I have to check back every 30 seconds or so to see if it's finished yet. I would like Eclipse to alert me, preferably by blinking its taskbar icon, after it finishes a time consuming operation. Are there any settings or plugins that can make this happen?
I believe is you have Mylyn installed, this should be enabled by default for Windows 7. See here and here. Regarding the post-build actions, I do not know of any existing Eclipse plugins that do this. However, I have not exhaustively searched the marketplace. However, this could be accomplished with existing Eclipse APIs but it would require someone to author a new Eclipse plugin.
The Eclipse Platform jobs framework has an API called IJobManager. A developer could write a new Eclipse plugin that could use this API to listen for job changes and do the following:
Create an eclipse plugin, register a listener to IJobManager on startup.
Once any interesting job is completed, it could fire off some external task/script using normal java process execution API in the JDK
This all could be accomplished in one Java file, probably less than 500 lines long.
You could use this template to setup a basic Eclipse plugin project including build system and have it built and ready to install into your existing Eclipse.
Update I just found a maven archetype for building eclipse plugins with tycho here. It would be my recommendation for someone new to building an eclipse feature/updatesite.
You can create a new plugin project and create this kind of functionality for yourself. The
IJobchangeListener from the Eclipse Jobs API is probably very interesting for you.
The IJobChangeListener is an interface where you can receive notifications for the different type of job states.
I have created a class called JobListener which adds the IJobchangeListener to the JobManager. With the action SampleAction you can register or unregister the listener. that means, if the listener is registered and your application is minimized you will be notified with a MessageDialog (no blinking taskbar).
I found a link where someone made his swing application blink. This functionality should be included in the method public void done(final IJobChangeEvent event). I haven't done this in my test class.
You can also get additional information about the Job with
event.getJob();
Here you are able to check the Job name:
String jobName = event.getJob().getName();
The name of the Job is human readable, for example "Collecting garbage", "Update for Decoration Completion", "Building workspace", etc.
The JobListener class.
/**
* A job listener which may be added to a job manager
*/
public class JobListener {
private MyJobListener listener = null;
private IWorkbenchWindow window = null;
private boolean active = false;
public JobListener(IWorkbenchWindow window) {
this.window = window;
}
/**
* register the job listener
*/
public void register() {
listener = new MyJobListener(window);
IJobManager jobMan = Job.getJobManager();
jobMan.addJobChangeListener(listener);
active = true;
}
/**
* unregister the job listener
*/
public void unregister() {
IJobManager jobMan = Job.getJobManager();
jobMan.removeJobChangeListener(listener);
active = false;
}
public boolean isActive() {
return active;
}
class MyJobListener implements IJobChangeListener {
private IWorkbenchWindow window;
public MyJobListener(IWorkbenchWindow window) {
this.window = window;
}
#Override
public void sleeping(IJobChangeEvent event) {
}
#Override
public void scheduled(IJobChangeEvent event) {
}
#Override
public void running(IJobChangeEvent event) {
}
#Override
public void done(final IJobChangeEvent event) {
window.getShell().getDisplay().asyncExec(new Runnable() {
#Override
public void run() {
if(window.getShell().getMinimized()) {
MessageDialog.openInformation(
window.getShell(),
"Test",
"Job " + event.getJob().getName() + " done.");
}
}
});
}
#Override
public void awake(IJobChangeEvent event) {
}
#Override
public void aboutToRun(IJobChangeEvent event) {
System.out.println("About to run: " + event.getJob().getName());
}
}
}
I called this class from a class called SampleAction.java
public class SampleAction implements IWorkbenchWindowActionDelegate {
private IWorkbenchWindow window;
private JobListener listener;
/**
* The constructor.
*/
public SampleAction() {
}
public void run(IAction action) {
if(listener.isActive()) {
listener.unregister();
MessageDialog.openInformation(
window.getShell(),
"Lrt",
"Unregistered");
}
else {
listener.register();
MessageDialog.openInformation(
window.getShell(),
"Lrt",
"Registered");
}
}
public void selectionChanged(IAction action, ISelection selection) {
}
public void dispose() {
}
public void init(IWorkbenchWindow window) {
this.window = window;
this.listener = new JobListener(window);
}
You can get started with eclipse plugin development by creating a new plugin project:
File > New > Project > Plugin Project
I used the Hello World plugin project template to test the code above.

How can I hook into Eclipse editor events in my own plugin?

I don't want to create my own editor but I would like to extend existing editors by hooking into their editing events.
For example whenever the text changes in a text or xml editor I would get a callback and be able to react to the change.
Does such a suitable extension point exist?
You can do this by accessing the IEditorPart, use getAdapter(IDocument.class) and then add a listener to this...
But this is really a hack... ;-)
EDIT: On request, here is a little more code.
public void hookToEditor() {
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
if (page == null) return;
IEditorPart editor = page.getActiveEditor();
if (editor == null) return;
IDocument doc = (IDocument) editor.getAdapter(IDocument.class);
if (doc == null) return;
doc.addDocumentListener(new IDocumentListener() {
#Override
public void documentChanged(DocumentEvent event) {
// Do something
}
#Override
public void documentAboutToBeChanged(DocumentEvent event) {
// About to do something
}
});
}
Note that
there are many ways to get the page - e.g. via the current site
there are just as many ways to get the editor part - e.g. via a handler
many editors don't have a embedded document - e.g. PDE editors
You can add resource change listener.
IResourceChangeListener listener = new IResourceChangeListener() {
#Override
public void resourceChanged(IResourceChangeEvent arg0) {
System.out.println("Text changed");
}
};
ResourcesPlugin.getWorkspace().addResourceChangeListener(listener);