How to access the model explorer programmatically in eclipse? - eclipse

How can I access the elements of the Sirius Model Explorer in Eclipse? Actually, I have a NatTable in another view and this NatTable has objects of the model in its cells. What I want to achieve is whenever I click on the cell of the nattable I can get the object associated to it. But how to pass it to the model explorer so the selection in NatTable gets synched with NatTable?
What I have in mind is get the selected object from NatTable and programmatically parse it to the model explorer. Is it possible?
There is something here for Package Explorer but how to make it work for model explorer?
Code Sample:
final IWorkbenchPart activePart = getActivePart();
if (activePart != null && activePart instanceof IPackagesViewPart) {
((IPackagesViewPart) activePart).selectAndReveal(newElement);
}
Supporting Code:
private IWorkbenchPart getActivePart() {
final IWorkbench workbench = PlatformUI.getWorkbench();
final IWorkbenchWindow activeWindow = workbench.getActiveWorkbenchWindow();
if (activeWindow != null) {
final IWorkbenchPage activePage = activeWindow.getActivePage();
if (activePage != null) {
return activePage.getActivePart();
}
}
return null;
}

Probably the Sirius Model Explorer is hooked to the Eclipse Selection Service (see https://www.eclipse.org/articles/Article-WorkbenchSelections/article.html) - in which case you simply need for your NatTable view to be some sort of ISelectionProvider.

Related

Programmatically resize a view in Eclipse

I'm testing an non-e4 RCP application using SWTBot and I need to change the size of my view. (Move the sash-bar)
I unsuccessfully tried
Resize my view using SWTBot (no such api)
Resize my view using Eclipse 3 API (no supported)
Resize my view using underlying e4 model (resizing not working)
e4 model seams to be promising, but I'm missing something, so it doesn't work.
I can
Get MPart of my view: view = ePartService.findPart(ID)
Get MTrimmedWindow: window = (view as EObject).eContainer as MTrimmedWindow
I can't
locale correct MPartSashContainer
move sash-bar with setContainerData()
I would like to know
How can I move from MPart to its direct parent (e.g. MPartStack)
Why common EObject methods like eContainer() are not present on M... objects?
Ok, I found a solution myself.
The thing is, that the view is not a part of the e4 UI-Tree. view.eContainer is directly the MWindow. To be placed at the right spot the view is connected to the MPlaceholder, that is a part of the e4 UI-Tree and has getParent() != null.
In order to resize a view the steps are:
Show view
Find MPlaceholder of the view
Find MPartStack and `MPartSashContainer´ object
Set containerData
Redraw widget (yes, auto-update seam not to work in this case)
Example:
EModelService modelService = PlatformUI.getWorkbench().getService(EModelService.class);
EPartService partService = PlatformUI.getWorkbench().getService(EPartService.class);
// Show view
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
page.showView(MyView.ID, null, IWorkbenchPage.VIEW_ACTIVATE);
MPart view = partService.findPart(MyView.ID);
// view.getParent() => null, because 'view' is not a part of the e4 UI-model!
// It is connected to the Model using MPlaceholder
// Let's find the placeholder
MWindow window = (MWindow)(((EObject)eView).eContainer);
MPlaceholder placeholder = modelService.findPlaceholderFor(window, view);
MUIElement element = placeholder;
MPartStack partStack = null;
while (element != null) {
// This may not suite your configuration of views/stacks/sashes
if (element instanceof MPartStack && ((Object)element.parent) instanceof MPartSashContainer) {
partStack = (MPartStack)element;
break;
}
element = element.parent;
}
}
if (partStack == null) { /* handle error */ }
// Now let's change the width weights
for (MUIElement element : partStack.getParent().getChildren()) {
if (element == partStack) {
element.setContainerData("50"); // Width for my view
} else {
element.setContainerData("25"); // Widths for other views & editors
}
}
// Surprisingly I had to redraw tho UI manually
// There is for sure a better way to do it. Here is my (quick & very dirty):
partStack.toBeRendered = false
partStack.toBeRendered = true

In ecplipse RCP application automatically get Run option in menubar Want to remove it

enter image description hereIn my Eclipse RCP application i am getting Run option automatically in menu bar. Without writing any code.So, i want to remove this.
Also getting search menu by default. which is ok for this application. But, my manually created menu item like(File, editor) , these items and search menu item distance not same manner.please help me out this situation to overcome on distance on manu item in eclipse RCP.
I suggest use plugin spy feature. Alt+shift+F1, Alt+shift+F2.
You can use in your development environment first, and you can use plugin spy on your rcp. just add org.eclipse.pde.runtime plugin to your rcp.
And you can figure out which plugin contributes menu item on your rcp, and if you think that plugin is not necessary, you can remove that plugin from your rcp.
For removing all defaults options in menu, You need to add this below code in ApplicationWorkbenchWindowAdvisor.java class.
#Override
public void postWindowOpen() {
IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IContributionItem[] items = ((WorkbenchWindow)workbenchWindow).getMenuBarManager().getItems();
for (IContributionItem item : items) {
item.setVisible(false);
}
}
The compiler will remind that it is not recommended to use WorkbenchWindow to access the UI, which conflicts with the library org.eclipse.ui.workbench in the Target.
#Override
public void postWindowCreate() {
IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
for (int i = 0; i < windows.length; i++) {
IWorkbenchPage page = windows[i].getActivePage();
if (page != null) {
IMenuManager menuMgr = getWindowConfigurer().getActionBarConfigurer().getMenuManager();
IContributionItem[] items = menuMgr.getItems();
for (IContributionItem item: items) {
if (item.getId().equals("org.eclipse.ui.run")) {
item.setVisible(false);
} else if (item.getId().equals("org.eclipse.search.menu")) {
item.setVisible(false);
}
System.out.println(item);
}
page.hideActionSet("org.eclipse.search.searchActionSet");
}
}
}
I changed it to get the MenuManager from getWindowConfigurer().getActionBarConfigurer().getMenuManager();
This can solve it.
Just paste this below code in ApplicationWorkbenchWindowAdvisor.java class.
public void postWindowOpen() {
// remove unwanted UI contributions that eclipse makes by default
IWorkbenchWindow[] windows = PlatformUI.getWorkbench ().getWorkbenchWindows();
for (int i = 0; i < windows.length; ++i) {
IWorkbenchPage page = windows[i].getActivePage();
if (page != null) {
WorkbenchWindow workbenchWin = (WorkbenchWindow)PlatformUI.getWorkbench().getActiveWorkbenchWindow();
MenuManager menuManager = workbenchWin.getMenuManager();
IContributionItem[] items = menuManager.getItems();
for(IContributionItem item : items) {
if(item.getId().equals("org.eclipse.ui.run")){
item.setVisible(false);
}
}
// hide 'Search' commands
page.hideActionSet("org.eclipse.search.searchActionSet");
}
}
}

E4: drag an object from a TableViewer to Windows Explorer (or OS specific file system)

In my Eclipse RCP application I display some business data in a TableViewer.
I want the user to be able to drag a row from the table viewer and drop it on the windows desktop/explorer. Windows should then create a file with the data from the selected row that I could provide in the dragSetData(..) method of the DragSourceAdapter class.
How to implement this? It seems that using FileTransfer as the dragSourceSupport on the table viewer is the way to go as it trigger a call to the dragSetData() method. But what object should I create and assign to "event.data" in this method?
A working example would be appreciated.
I've implemented the reverse without problem, i.e. drag a file from windows explorer onto the TableViewer and add a row in the table. There are plenty on sample for this on the net but can't find a sample of the opposite, drag from eclipse to the OS
[edit + new requirement]
So I understand that I have to create a temporary file somewhere and set the name of that temp file in event.data in dragSetData()
Q: is there a simpler way to do that, eg set somewhere (iun data) the content of the file directly without the temp file?
There is another requirement. When the drop operation is about to occur, I want to show a popup to the user that will have to choose what "business data" from the "row" he wants to export and the name of the file that will be created. I tried the following (only asking for the filename for now) but it does not work as expected as the popup shows up as soon as the cursor reach the first pixel outside my app. I would like to show the popup just "before" the drop operation occurs.
Q: is there a way to have this popup show just before the drop operation occurs, ie when the user "release" the mouse button?
#Override
public void dragSetData(final DragSourceEvent event){
if (FileTransfer.getInstance().isSupportedType(event.dataType)) {
// Will be a more complex dialog with multiple fields..
InputDialog inputDialog = new InputDialog(shell, "Please enter a file name", "File Name:", "", null);
if (inputDialog.open() != Window.OK) {
event.doit = false;
return;
}
event.data = new String[] { inputDialog.getValue() };
}
}
The event.data for FileTransfer is an array of file path strings.
You DragSourceAdapter class might look something like:
public class MyDragSourceAdapter extends DragSourceAdapter
{
private final StructuredViewer viewer;
public MyDragSourceAdapter(final StructuredViewer viewer)
{
super();
this.viewer = viewer;
}
#Override
public void dragStart(final DragSourceEvent event)
{
IStructuredSelection selection = viewer.getStructuredSelection();
if (selection == null)
return;
// TODO check if the selection contains any files
// TODO set event.doit = false if not
}
#Override
public void dragSetData(final DragSourceEvent event)
{
if (!FileTransfer.getInstance().isSupportedType(event.dataType))
return;
IStructuredSelection selection = viewer.getStructuredSelection();
List<String> files = new ArrayList<>(selection.size());
// TODO add files in the selection to 'files'
event.data = files.toArray(new String [files.size()]);
}
}
and you install it on your viewer with:
MyDragSourceAdapter adapter = new MyDragSourceAdapter(viewer);
viewer.addDragSupport(DND.DROP_COPY, new Transfer [] {FileTransfer.getInstance()}, adapter);

Eclipse RCP: Can I remove Orphaned Perspectives from the Perspective Bar?

I'm developing an RCP that has two product versions, a core app and one with some extensions. If a user opens the core app after having opened the extended app in the same workspace, eclipse detects a perspective used only in the extended app and makes a local copy of it, so it shows up in the perspective toolbar as an orphaned extension.
I created an activity to hide the extended app perspective when running the core app. That hides it from the perspective menu and the perspective shortcut menu, but it doesn't remove it from the perspective toolbar.I also tried detecting orphaned perspectives from the active page of the active workbench window (by looking for angle brackets in the label) and removing them with PlatformUI.getWorkbench().getPerspectiveRegistry().deletePerspective(perspective), but this doesn't affect the perspective toolbar either. The perspective I'm removing is not present in the core app.
Is there a way I can access the perspective toolbar programmatically so I can remove any orphaned perspectives? Or any other approach tha would work?
I thought a good solution would be creating a custom perspective switcher, but that path was blocked by an eclipse bug. There is a suggested workaround, but it did not work for me. I created a custom perspective switcher toolbar, but I could find no way to make it update when perspectives are opened or activated. My attempts are documented here.
I removed the orphan perspectives in a workspace shutdown hook, but for some reason an NPE is thrown by the E4 workbench (LazyStackRenderer line 238) when I select a perspective in the switcher that was opened but not selected when I launched the app.
I got it to work as desired by closing all open perspectives on shutdown, after storing their IDs in a preference value, and then opening them again when the app is launched in the WorkbenchWindowAdvisor. It's a bit of a hack, but it's the only way I could find to avoid the E4 workbench NPE, which also prevents setting the perspective from the toolbar until it's closed and re-opened from the Window menu.
Here's my code.
...
IWorkbench workbench = ...
static final String PERPSECTIVE_ID_1 = ...
static fnal String PERSPECTIVE_ID_2 = ...
static final String PREFERENCE_KEY = ...
workbench.addWorkbenchListener( new IWorkbenchListener() {
public boolean preShutdown( IWorkbench workbench, boolean forced ) {
IPerspectiveDescriptor[] openPerspectives = page.getOpenPerspectives();
page.closeAllPerspectives(false, false);
StringBuilder sb = new StringBuilder();
String delim = "";
for (IPerspectiveDescriptor persp : openPerspectives) {
if (!persp.getId().equals(PERSPECTIVE_ID_1) && !persp.getId().equals(PERSPECTIVE_ID_2) {
sb.append(delim + persp.getId());
delim = ";";
}
}
getPreferenceStore().setValue(PREF_KEY, sb.toString());
return true;
}
public void postShutdown( IWorkbench workbench ) {
}
});
class MyWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {
static final String PRODUCT_ID_1 = ...
static final String PRODUCT_ID_2 = ...
static final String PREFERENCE_KEY = ...
...
#Override
public void postWindowOpen() {
IWorkbenchPage page = getWindowConfigurer().getWindow().getActivePage();
String savedOpenPerspectiveStr = getPreferenceStore().getString(PREFERENCE_KEY);
if (!"".equals(savedOpenPerspectiveStr)) {
List<IPerspectiveDescriptor> openPerspectives = new ArrayList<IPerspectiveDescriptor>();
String[] perspectiveIds = savedOpenPerspectiveStr.split(";");
if (perspectiveIds.length == 0) {
openPerspectives.add(PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(savedOpenPerspectiveStr));
} else {
for (String id : perspectiveIds) {
openPerspectives.add(PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(id));
}
}
//successively setting perspectives causes them to appear in the perspective switcher toolbar
for (IPerspectiveDescriptor persp : openPerspectives) {
page.setPerspective(persp);
}
}
//now we set the appropriate perspective
if (Platform.getProduct().getId().equals(PRODUCT_ID_1)) {
page.setPerspective(PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(PERSPECTIVE_ID_1));
} else if (Platform.getProduct().getId().equals(PRODUCT_ID_2)) {
page.setPerspective(PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(PERSPECTIVE_ID_2));
}
}
...
}

How to pass an object from one part to another part in Eclispe e4 RCP?

I am building an application with eclipse e4 RCP. I have a navigator (similar to Navigator in eclipse IDE) and I would like to link it to an editor (similar to how a file in Navigator in eclipse IDE is linked to an editor). Currently I am using EPartService to open up my editor Part (by creating a new instance) when the user double clicks on a file in the Navigator tree. But I would like to pass it a parameter (a String or an Object) to let it know which file to open in the editor. I want to be able to open multiple editors for different nodes of the Navigator tree. I have done a lot of research on internet but could not find a solution. I think its a common problem and the e4 framework should provide an mechanism to pass such parameters from one Part to another Part. Current code is as below:
viewer.addDoubleClickListener(event -> {
final IStructuredSelection selection = (IStructuredSelection) event.getSelection();
FileNode file = null;
boolean partExists = false;
if (selection.getFirstElement() instanceof FileNode ) {
file = (FileNode ) selection.getFirstElement();
for (MPart part1 : partService.getParts()) {
if (part1.getLabel().equals(file.getName())) {
partService.showPart(part1, PartState.ACTIVATE);
partExists = true;
break;
}
}
if (!partExists) {
MPart part2 = partService
.createPart("com.parts.partdescriptor.fileeditor");
part2.setLabel(file.getName());
partService.showPart(part2, PartState.ACTIVATE);
}
}
});
Is it possible to say something like part2.setParameter("PARAM_NAME", "FILE_NAME"); ?
When you have an MPart you can call:
MPart mpart = ...
MyClass myClass = (MyClass)mpart.getObject();
to get your class for the part (the class defined in the 'Class URI' for the part in the Application.e4xmi). You can then call any methods you have defined on your part class.
You can also set data in the 'transient data' area of a part:
mpart.getTransientData().put("key", "data");
Object data = mpart.getTransientData().get("key");