adding annotations to file outside workspace - eclipse

I need to show annotations on files outside of Workspace.
I am able to show annotations on files present in Worspace
When i try to do the same for files outside the Workspace I need to create resource and ifile object. How do i achieve the same?
How do i read contents of file outside workspace since i am unable to create a ifile object.
Here is what i am doing right now:
IEditorPart editor =(IEditorPart) wins[i].getPartService().getActivePart()
IEditorInput input = editor.getEditorInput();
IPath path = ((FileEditorInput)input).getPath();
IFile file= workspace.getRoot().getFileForLocation(path);

You cannot annotation files outside of workspace. An IFile is only defined for workspace files.

Just in case you don't know, files and projects don't have to the under the workspace's folder on the file system to be in the workspace.
Maybe you can surreptitiously add a hidden project to the workspace and link the file as a resource in it. I don't think that an external file converted to an internal file loses any behaviors. But, it could gain more than you want. One that I can think of is that source control plugins might then detect it.
Or, you could point out to the user that there are advantages to adding the file to the workspace and let them make the choice. You might be able to show a dialog asking which new or existing project/folder to add it to. Of course, if they decline then you should remember and not ask again about that external file.
UPDATE:
FileStoreEditorInput represents a file that is not part of the current workspace. To listen for external files being opened, subscribe with an IPartListener2 on each window.
public class Activator extends AbstractUIPlugin implements IStartup {
#Override
public void earlyStartup() {
final PartListener partListener = new PartListener();
for (final IWorkbenchWindow window : getWorkbench().getWorkbenchWindows()) {
window.getPartService().addPartListener(partListener);
}
getWorkbench().addWindowListener(new IWindowListener() {
#Override
public void windowOpened(IWorkbenchWindow window) {
window.getPartService().addPartListener(partListener);
}
});
}
private class PartListener implements IPartListener2 {
#Override
public void partOpened(final IWorkbenchPartReference partRef) {
if (partRef.getPart(false) instanceof EditorPart) {
final EditorPart editor = (EditorPart) partRef.getPart(false);
if (editor.getEditorInput() instanceof FileStoreEditorInput) {
final FileStoreEditorInput input = (FileStoreEditorInput) editor.getEditorInput();
System.out.println(input.getURI());
}
}
}
}

Related

Open DialectEditor programmatically outside of main editor area (E3/E4 hybrid)

what I want to do:
In my RCP an E3/E4 hybrid I have a project and library based on sirius tree. The User can drag an drop item from the library tree to the project tree. This works fine and was no great problem to build in. So now I want to make the UI more usable. It should looks like this layout:
what works:
After application startup I open my library presentation with the DialectUIManager.
final DialectEditor editor = (DialectEditor)
DialectUIManager.INSTANCE.openEditor(siriusSession, description, monitor);
Okay, this works. But it open it in the editor in the part market as org.eclipse.ui.editorss. This it not what I want
what does not work:
I want to show it in the "Library Part". I can move it manually with the mouse after open the editor, but how can i tell DialectUIManager to open it direct there. Or how can I programmatically it move there.
I do a lot of google research but i don't found a solution. The only thing I found was a hint Pierre-Charles David https:// www. eclipse.org/forums/index.php?t=msg&th=998476&goto=1631138&#msg_1631138
If you need is simply to show the editor outside of the main editor
area, this is possible since Eclipse 4.2 (e4 does not really treat the
main editor area as something special), so you can have your editor
"around" another editor in the middle of other views.
But at this step I stuck. I also ask it in the Sirius Forum but they say its a Eclipse E4 problem
Thanks for help, code snippets or links to correct part of manual.
I've found a solution. It's not very nice, but it works. I execute these code here after the editors have opened.
What the code does:
He is looking for the MPlaceholder which has the ID: org. eclipse. ui. editorss. There he descends until he is with the parts. These are in the Compatibly editor mode. Then he chooses the part we wants to move out of and Attach them to the MPartStack target.
public static void movePart(MApplication application,
EModelService modelService) {
MPart partToMove = null;
MUIElement muiElement =
modelService.find("org.eclipse.ui.editorss", application);
if (muiElement instanceof MPlaceholder) {
MPlaceholder placeholder = (MPlaceholder) muiElement;
MUIElement ref = placeholder.getRef();
if (ref instanceof MArea) {
MArea area = (MArea) ref;
List<MPartSashContainerElement> children = area.getChildren();
for (MPartSashContainerElement mPartSashContainerElement
: children) {
if (mPartSashContainerElement instanceof MPartStack) {
MPartStack partStack = (MPartStack) mPartSashContainerElement;
List<MStackElement> children2 = partStack.getChildren();
for (MStackElement mStackElement : children2) {
if (mStackElement instanceof MPart) {
MPart part = (MPart) mStackElement;
// Library is the Editor Name wiche I want to move
if (part.getLabel().equals("Library")) {
partToMove = part;
break;
}
}
}
}
}
}
}
if (partToMove != null) {
moveElement(modelService, application, partToMove);
}
}
private static void moveElement(EModelService modelService,
MApplication application, MPart part) {
// target PartStack
MUIElement find = modelService.find("de.bsg.onesps.rcp.
partstack.library", application);
if (find instanceof MPartStack) {
MPartStack mPartStack = (MPartStack) find;
mPartStack.getChildren().add(part);
mPartStack.setSelectedElement(part);
}
}

How to retain the state of a treeviewer in Java RCP application?

I have a simple RCP application having couple of wizards out of which one is having a tree viewer. I want to retain the state of the selected item in the tree viewer next time I open that particular view. As of now I have implemented using static variables and its working fine.I want to know how it can be done in a better way?
//Sample Code
private static RepositoryLocationItem lastRepoItemSelected;
Composite parent=new Composite(SWT.NONE)
treeViewer = new TreeViewer(parent);
treeViewer.setContentProvider(new MovingBoxContentProvider());
treeViewer.setLabelProvider(new MovingBoxLabelProvider());
treeViewer.setInput(getInitalInput());
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
/* Setting the value of lastRepoItemSelected */
});
if(lastRepoItemSelected !=null)
{
treeViewer.setSelection(new StructuredSelection(lastRepoItemSelected),true);
}
Assuming this is a 3.x style RCP (your view extends ViewPart) you can use the saveState method to save your view state:
#Override
public void saveState(final IMemento memento)
{
// TODO set values in the 'memento'
}
You can then use the init method to restore values from the memento when the view is shown again:
#Override
public void init(final IViewSite site, final IMemento memento)
throws PartInitException
{
super.init(site, memento);
// TODO restore from 'memento'
}
Note: Mementos are persisted across restarts of your RCP so you need to store values in them which are valid in a new instance of the RCP.
Also look at the Eclipse wiki entry for more information.
For a WizardPage you can use the IDialogSettings. You must set this up in your Wizard using something like:
IDialogSettings pluginSettings = Activator.getDefault().getDialogSettings();
IDialogSettings wizardSettings = pluginSettings.getSection("id of your wizard");
if (wizardSettings == null) {
wizardSettings= new DialogSettings("id of your wizard");
pluginSettings.addSection(wizardSettings);
}
setDialogSettings(wizardSettings);
where Activator is your plugin activator class and "name of your wizard" is a id for your wizard (which can be anything as long as it is unique in your plugin).
In your wizard page you can then get the settings with:
IDialogSettings settings = getDialogSettings();
IDialogSettings has lots of methods for saving and restore various sorts of values, such as:
settings.put("key", "string value");
String value = settings.get("key");

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

Making Ctrl-C copy from whichever SourceViewer has focus in Eclipse plug-in

I successfully extended the PyDev editor in Eclipse with a side-by-side display, but I can't copy the contents of the extra SourceViewer that I added. I can select some text in the display, but when I press Ctrl+C, it always copies the main PyDev editor's selected text.
I found an article on key bindings in Eclipse editors, but the code there seems incomplete and a bit out-of-date. How can I configure the copy command to copy from whichever SourceViewer has focus?
The reason I want to do this is that I've written a tool for live coding in Python, and it would be much easier for users to submit bug reports if they could just copy the display and paste it into the bug description.
David Green's article was a good start, but it took a bit of digging to make it all work. I published a full example project on GitHub, and I'll post a couple of snippets here.
The TextViewerSupport class wires up a new action handler for each command you want to delegate to the extra text viewer. If you have multiple text viewers, just instantiate a TextViewerSupport object for each of them. It wires up everything in its constructor.
public TextViewerSupport(TextViewer textViewer) {
this.textViewer = textViewer;
StyledText textWidget = textViewer.getTextWidget();
textWidget.addFocusListener(this);
textWidget.addDisposeListener(this);
IWorkbenchWindow window = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow();
handlerService = (IHandlerService) window
.getService(IHandlerService.class);
if (textViewer.getTextWidget().isFocusControl()) {
activateContext();
}
}
The activateContext() method has a list of all the commands you want to delegate, and registers a new handler for each one. This was one of the changes from David's article; his ITextEditorActionDefinitionIds has been deprecated and replaced with IWorkbenchCommandConstants.
protected void activateContext() {
if (handlerActivations.isEmpty()) {
activateHandler(ITextOperationTarget.COPY,
IWorkbenchCommandConstants.EDIT_COPY);
}
}
// Add a single handler.
protected void activateHandler(int operation, String actionDefinitionId) {
StyledText textWidget = textViewer.getTextWidget();
IHandler actionHandler = createActionHandler(operation,
actionDefinitionId);
IHandlerActivation handlerActivation = handlerService.activateHandler(
actionDefinitionId, actionHandler,
new ActiveFocusControlExpression(textWidget));
handlerActivations.add(handlerActivation);
}
// Create a handler that delegates to the text viewer.
private IHandler createActionHandler(final int operation,
String actionDefinitionId) {
Action action = new Action() {
#Override
public void run() {
if (textViewer.canDoOperation(operation)) {
textViewer.doOperation(operation);
}
}
};
action.setActionDefinitionId(actionDefinitionId);
return new ActionHandler(action);
}
The ActiveFocusControlExpression gives the new handler a high enough priority that it will replace the standard handler, and it's almost identical to David's version. However, to get it to compile, I had to add extra dependencies to my plug-in manifest: I imported packages org.eclipse.core.expressions and org.eclipse.ui.texteditor.

Handling drag and drop of files inside Eclipse Package Explorer

I'm trying to create an Eclipse plugin to support a proprietary project file format. My goal is to be able to drag and drop a file in the Project Explorer (any type of file) onto a file of the type I support, and have the name of the file being dragged appended to the end of the proprietary file.
Right now, I have a custom editor that can parse out some data from an existing file in a manageable way. This means that I have an editor associated with the file type, such that my special icon shows up next to it. I don't know if that's relevant.
I'm attempting to use the extension point "org.eclipse.ui.dropActions" but I'm not sure how to register my DropActionDelegate (implements org.eclipse.ui.part.IDropActionDelegate) such that it will be called when a file is dropped onto one of my type within the Project Explorer.
Anybody have any ideas? Am I even on the right track with the DropActionDelegate?
You are on the right track implementing an IDropActionDelegate:
class DropActionDelegate implements IDropActionDelegate {
#Override
public boolean run(Object source, Object target) {
String transferredData (String) target; // whatever type is needed
return true; // if drop successful
}
}
The purpose of the extension point org.eclipse.ui.dropActions is to provide drop behaviour to views which you don't have defined yourself (like the Project Explorer).
You register the drop action extension like this:
<extension point="org.eclipse.ui.dropActions">
<action
id="my_drop_action"
class="com.xyz.DropActionDelegate">
</action>
</extension>
Don't forget to attach an adequate listener to your editor in your plugin code:
class DragListener implements DragSourceListener {
#Override
public void dragStart(DragSourceEvent event) {
}
#Override
public void dragSetData(DragSourceEvent event) {
PluginTransferData p;
p = new PluginTransferData(
"my_drop_action", // must be id of registered drop action
"some_data" // may be of arbitrary type
);
event.data = p;
}
#Override
public void dragFinished(DragSourceEvent event) {
}
}