Resource Change Plugin for eclipse - eclipse

I created an RCP application which detects resource change in its own view by extending CommonNavigator.
public abstract class NavigatorView extends CommonNavigator implements
IResourceChangeListener {
public void createPartControl(Composite parent) {
super.createPartControl(parent);
hookResourceChangeCommand(); // my resource tracking function.
}
}
But now I need to create a plugin for this which detects resource change in project explorer in eclipse itself. I cannot create a view now and I need to detect already existing view. How should I do it ?

Please completely remove the view that you created. You should not do anything in the UI, if you want to track resource changes, as resources are part of the workspace concept, and the workspace is generally headless (that is without UI).
Instead use the code below (taken from the resource change listener tutorial):
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IResourceChangeListener listener = new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
System.out.println("Something changed!");
}
};
workspace.addResourceChangeListener(listener);
//... some time later one ...
workspace.removeResourceChangeListener(listener);

Related

How to get/inject EPartService outside part or in LifeCycle Manager or How to control life cycle of e4 RCP app in true sense?

My application consists of many parts and they are defined in application's e4xmi file. I want to hide and show them dynamically. I am using EpartService to do so in handlers, where I can inject it.
But I also want to control the show/hide of parts with something like life cycle manager, where I can not inject EPartService. Is there any way to achieve and fully control RCP application's life cycle?
There seems the exact same question here and void of solution:
https://www.eclipse.org/forums/index.php/t/595958/
I want to implement 'remember me like feature' where part having sign in screen is shown instead of other parts. Also after log out same sign-in part is to be shown. So I need to control life cycle of RCP app. But I cant inject EPartService before anything in Application's e4xmi is initiated.
If you are creating a class from something which is injected (such as the LifeCycle class) you can create your class with injection using ContextInjectionFactory:
#Inject
IEclipseContext context;
MyClass myClass = ContextInjectionFactory.make(MyClass.class, context);
Or if you just pass an IEclipseContext to the class you can get the part service using:
EPartService partService = context.get(EPartService.class);
Note: There is a separate instance of the part service for each part. Depending on what you are doing you may need to make sure you have the service for the active part.
If you are not locked in to using SWT, you could use the e(fx)clipse e4 renderer for JavaFX instead.
e(fx)clipse has more possibilities to control the lifecycle of the application. For example you can return a Boolean from #PostContextCreate to signal whether you want to continue the startup or not. You will not be able to use EPartService here though, but you can roll your own login dialog using dependency injection as greg-449 has described it in his answer.
public class StartupHook {
#PostContextCreate
public Boolean startUp(IEclipseContext context) {
// show your login dialog
LoginManager loginManager = ContextInjectionFactory.make(LoginManager.class, context);
if(!loginManager.askUserToLogin()) {
return Boolean.FALSE;
}
return Boolean.TRUE;
}
}
(You can also restart the application. Form
more details see http://tomsondev.bestsolution.at/2014/11/03/efxclipse-1-1-new-features-api-to-restart-your-e4-app-on-startup/).

Creating a "live" view in the background

I'd like to define an Eclipse view that is self-contained, but able to respond to selection events as soon as the Workbench app is launched, even if the view is not visible, as long as it appears as one of the "background views" in a folder. In other words, I need a "hook" which is invoked when placeholder for my view is created.
The problem is that when a Workbench app launches, the background views are normally not instantiated. You can of course implement an IPerspectiveFactory to do an initial perspective layout in Eclipse, but the factory is only used when the perspective is initially chosen; after that, on subsequent launches, Eclipse persists mementos that don't involve creating the view.
Is there any way to accomplish this?
I think it would be a good idea to separate the data model that's driving your view from the view UI. This will allow the data model to be continuously updated and the view to be added or removed without having to maintain any kind of state.
You can add the data model as a SelectionService listener in your plugin Activator:
private ISelectionListener listener;
public void start(BundleContext context) throws Exception {
super.start(context);
listener = new ISelectionListener() {
#Override
public void selectionChanged(IWorkbenchPart part,
ISelection selection) {
// Update model
}
};
PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getSelectionService()
.addSelectionListener(listener);
}
public void stop(BundleContext context) throws Exception {
PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getSelectionService().removeSelectionListener(listener);
super.stop(context);
}
When the view is created it can use the data model to populate the UI components and listen to the data model for any live updates.
You'll need to make sure that your plugin is activated when the application is launched. The following question can help with that.
auto-start OSGi service
Edit
The following code can be used to activate your view (calling createPartControl) even if the view is currently hidden. By placing this code in your activator it can start listening to model events as soon as your plugin is activated.
PlatformUI.getWorkbench().addWindowListener(new IWindowListener() {
...
#Override
public void windowActivated(IWorkbenchWindow window) {
IViewReference view = window.getActivePage().findViewReference(
VIEW_ID);
if (view != null) {
view.getPart(true);
}
}
});

Eclipse: Converting actions in commands for a specific view

My original RCP was started in 3.x and currently I am running it on Juno with the compatibility layer. I was looking into doing a soft migration so I have started to slowly change my practices. One of the things I am doing is to change my actions into commands.
I have a view (which is like a directory explorer) currently that adds actions to the toolbar and popup menu of the view. These actions call specific methods in the view, for example to go up one directory.
It was easy to do this by action because I just create my action in the View class itself and programmatically add them to the toolbar
IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager();
mgr.add(upDirectory);
mgr.add(refresh);
mgr.add(changeRoot);
and the creation of the actions are called from the createPartControl()
upDirectory = new Action("Go up one directory") {
public void run() {
goUpOneDirectory();
}
};
where goUpOneDirectory() is a method in the view
If I want to convert this to a command, I want to be able to access this method of the view in my handler. So I tried the following,
private void createHandlers()
{
IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class);
IHandler upDirHandler = new AbstractHandler() {
public Object execute(ExecutionEvent event)
throws ExecutionException {
goUpOneDirectory();
return null;
}
};
handlerService.activateHandler("updir.id", upDirHandler);
}
And createHandlers is called in the createPartControl, and the command is added via the plugin.xml to the toolbar of the view. The problem is that the moment my view is out of focus it disables the buttons in the toolbar for these commands.
I want them to remain enabled at all times. How can I do that?
I know that the isEnabled() returns true all the time so I am not sure why it happens. The activateHanlder is called once in createPartControl so I feel that it should remain active all the time.
Edit: Ok I just saw this ,
IHandlerService from the workbench part site is the part handler
service. Any handlers activated through the part handlers service will
only be active when that part is active. Any listeners added to the
part handler service will be removed when the part is disposed, and
any active handlers will be deactivated (but not disposed).
So how can I get this,
IHandlerService from the workbench is the global handler service. it
provides no special activation scoping or lifecycle.
Sorry, I should have waited a bit longer before asking, I figured it out!
I changed the,
IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class);
to
IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);
and it worked.
I will leave the question in case it helps other people.

Key and Mouse Listener for CEditor in Eclipse

I need to add a listener to one of my plugin views. I need the view to update when a mouse or key event occurs in the CEditor in Eclipse. I have done it by:
((StyledText)((AbstractTextEditor)activeEditor).getAdapter(Control.class)).addKeyListener(l);
But when I change to a different file in the editor the listeners do not work. Any ideas?
Solved: I scrapped the idea of key/mouse listeners and just added a SelectionListener to my Eclipse page. Then created a custom selectionListener that only responded when the selection was in the CEditor.
Made my view class implement ISelectionListener
getViewSite().getPage().addSelectionListener(this);
#Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if(part.getClass() == CEditor.class){
//Do what I needed
}
}
This made it so it only responded to selection changes in my CEditor.

Eclipse Modeling Framework: Linking an alternative view to the model

I have an ECore model I exploit to automatically generate the model source and JFace edit package. I am trying to develop an alternative view for contents of that model, basically a graph view based on JFreeChart. I have managed to create a JFreeChart based view plugin. Now I need to link the view with the model. How can I do that? I would like to edit the model with the TreeBased editor and see the effects of such editing in the graph view. Is that possible?
thank you
If you open your Graphbased-View ask for the IFile of the current opened editor. After you got the file, you can load the model (see the generated Editor how to load the Model from the underlying resource) attach a IResourceChangeListener to get a notification, if the underlying IFile of your EMF Model changed.
After a notification you can reload the model from your file and show the model in your view.
In addition you have to register a PartListener to get a notification if the user brings another emf-editor to top or he closes the editor (you also have to unload (on close) or refresh (another editor with your emf-model was brought to top).
Yes, it is, as the generated EMF code provides a notification layer: use EObject.eAdapters to add a new adapter, that is notified if the model is changed.
object.eAdapters().add(new Adapter() {
public void setTarget(Notifier newTarget) {
// TODO Auto-generated method stub
}
public void notifyChanged(Notification notification) {
// TODO Auto-generated method stub
}
public boolean isAdapterForType(Object type) {
// TODO Auto-generated method stub
return false;
}
public Notifier getTarget() {
// TODO Auto-generated method stub
return null;
}
});
Ok I have managed to do that following the Zoltán suggestions. Anyway I admit I would have preferred a more structured answer, and that is why I am answering my own question with a brief summary of the solution.
basically the idea is that a view plugin implements the ViewPart interface. Because of this it can actually invoke the following methods
getSite().getWorkbenchWindow().getSelectionService()
in order to get the workbench selection service. You can therefore invoke the SelectionService method
addSelectionListener(ISelectionListener listener)
passing as parameter your own ISelectionListener which can be the same ViewPart you are implementing. You just have to implement the ISelectionListener interface and thus provide an implementation of the selectionChanged method
public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection)