Eclipse Modeling Framework: Linking an alternative view to the model - eclipse

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)

Related

Eclipse Scout add right click on button

I am new at Scout and I would like to add Mouse Listener to Button, so I can implement right click on button.
I knew that there is MouseListener object :
MouseListener mouseListener = new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
};
but how to add it to a button?
I find function
addButtonListener(listener);
but mouselistener is not class of button listener (But both are extended from EventListener)
An important concept behind Eclipse Scout is the separation of UI and GUI. You do not program against a GUI-Library like SWT, but you define forms containing fields. This represents a kind of model of your application. This model is rendered with different technologies (SWT, Swing, and Eclipse RAP to create web application).
The price of this approach is that the model layer does not have as much possibilities as what is offered by each Graphical Library. The model layer focusses on what is necessary for business application (typically form based).
This is why you won’t be able to register a SWT or a Swing MouseListener directly to the Scout model. If you really need to go in this direction, extending the Scout Model might be a good approach. (See this recent example: Scout tables with fixed columns, it concerns the web-ui domain)
The advantage of this approach is that you do not need to rewrite your application when the underlying technologies changes (Graphical Library, Eclipse Platform…). This matters when you are working on applications that have a long lifecycle (like 10+ years).
Duplicate post on the Scout Forum

Refresh Eclipse 4 RCP view on wizard perform finish

Rookie question that I'm not having much luck with. In my e4 RCP application, I have a couple of instances where I create an object in a wizard that should then appear in one of my views.
The desired behavior is similar to how the eclipse Package Explorer View updates after a new project is created.
I was thinking I could just grab the view from the partService and run my own update method:
MPart ingredientsView = partService.showPart("com.personal.recipes.part.ingredientsview", PartState.ACTIVATE);
IngredientsView iv = (IngredientsView) ingredientsView.getObject();
iv.updateView();
While this works in other places, when called from a wizard 'partService' is null and the app NPE's out.
So what is the proscribed method of forcing e4 views to update after modifying their contents?
EDIT:
I tried to use the ContextInjectionFactory like #greg-449 showed in his answer, but I'm uncertain where to place it in my code, or how to define the context. I'm launching the wizard from a toolbar button, and placed the following code in my handler:
#Execute
public void execute(Shell shell) {
IEclipseContext context = EclipseContextFactory.create();
IWizard ingredientWizard = ContextInjectionFactory.make(IngredientWizard.class, context);
WizardDialog wizardDialog = new WizardDialog(shell, ingredientWizard);
wizardDialog.open();
}
However, when I tried to get the part service with #Inject EPartService partService; I got an InjectionException saying no error was found.
Once injection is available, using the EventBroker looks like the way to go.
enter code hereThe best way to update a view is to use a model for the content of the view. Your wizard seems to allow editing or creating ingredients. When you perform the finish of your wizard you are probably modifying some ingredient data. The ingredient model should be informed of these changes. If the view uses a content provider that observes this model is will update automatically when the model sees the update (this is the observer pattern).
How this works depends on the nature of your data. You could use the PropertyChange-Support in Java.
To do so let the content provider implement the org.eclipse.jface.util.IPropertyChangeListener interface and fire property change events when the data is changed.
UPDATE
My ContentProvider implements the property change interface. Whenever a property change event is received the viewer is refreshed(asynchronously). All my persistence operations are handled by data managers similar to Fowler's the table data gateway pattern but sometimes for more than one table. The data manager fires the property change event. This way the UI (wizard) does not need to know about persistence
Injection is only done on objects that the application model knows about. So it is not done on Wizards or Dialogs unless you do it 'manually' using ContextInjectionFactory when you create the dialog:
IWizard wizard = ContextInjectionFactory.make(YourWizardClass.class, eclipseContext);
WizardDialog dialog = new WizardDialog(shell, wizard);
This will do injection on your wizard class giving you access to the EPartService.
You could also use the 'event broker' (IEventBroker) to broadcast an event to anything that is interested rather than finding your specific view.

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);
}
}
});

Resource Change Plugin for 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);

Dealing with model save and update with GWT Platform

I'm trying to adapt my GWT web application from my home-grown MVC to GWT Platform.
I've managed to port the my application views with presenters, and essentially able to access views via PlaceRequest. And with changing the URL (#).
However I am not sure how to deal with Models using this GWT platform, in the common MVP I know there is a go() method in the presenter which fetches data, say from server via RPC.
In the GWT platform presenter here are the methods automatically generated by the Eclipse plugin:
Constructor
revealInParent
onBind
onReset
Where should I put the RPC code that will fetch and update my model. Say in the presenter I have:
ProfilePresenter.java:
public class ProfilePresenter
extends
Presenter<ProfilePresenter.MyView, ProfilePresenter.MyProxy> {
public interface MyView extends View {
HasText getFullname();
HasText getLocation();
HasText getAboutme();
HasText getLastlogin();
}
private User user; // Model which represents the User information etc.
And when the View associated with the Presenter is shown I need to fetch the User model from the server and update the model and then subsequently update the view through the interfaces it expose.
Also, say I have some buttons in the view, which then can be accessed by the presenter through HasClickHandler where should I put the event handlers?
I would put the RPC call in the onReset method.
See the presenter lifecycle
Personally I deal with events using the reversed MVP pattern. But you can also call a handler this way:
getView().getSubmitButton().addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
}
});
with the following signature for getSubmitButton in your view interface:
HasClickHandlers getSubmitButton()
Sydney covered most of your questions.
In general onResetmethod is a good place to make backend calls.
Sometimes when the backend call takes longer and you want to display the view only after the data was loaded you can use manual reveal.
But for the profile page I don't think that is necessary.
I also agree with the reverse MVP pattern. It's way easer to test presenters using the reverse MVP Pattern than using the HasXXXHandlers interfaces.