In e3 to create not restorable View I set field "restorable" to false in extension org.eclipse.ui.views and it works. In my e4 application I create PartDescriptor with tag "NoRestore" but it do nothing. After restart Part is shown. What I do wrong? Or it is bug?
If you let e4 save the workbench model on exit it is restored exactly as saved the next time the RCP is started. There is no support for a NoRestore tag.
Specifying the -clearPersistedState flag on startup will reset the model to the initial state. You can also specify -persistState false to stop the model being saved on exit.
If you just want to deal with one part you can alter the model in your life cycle class during startup. Something like:
#ProcessAdditions
public void processAdditions(MApplication app, EModelService modelService)
{
MUIElement el = modelService.find("your part id", app);
if (el != null) {
el.setToBeRendered(false);
}
}
which just finds a part and turns off the 'to be rendered' flag.
For compatibility with future versions, in which the IPresentationEngine.NO_RESTORE("NoRestore") tag will be present, you can use the following code.
#PreSave
void preSave(MApplication a_app, EModelService a_modelService){
ArrayList<MElementContainer<MUIElement>> containers = new ArrayList<>();
List<MPart> parts = a_modelService.findElements(a_app, null, MPart.class, Arrays.asList("NoRestore"));
parts.forEach(p -> {
p.setToBeRendered(false); // hide parts
containers.add(p.getParent()); // collect containers with no restorable parts
});
// hide containers which contains only no restorable parts
containers.stream().filter(c -> c.getChildren().stream().allMatch(ch -> ch.getTags().contains("NoRestore"))).forEach(c -> c.setToBeRendered(false));
}
NOTE. Attempts to add the same code to methods with annotations #ProcessAdditions or #ProcessRemovals did not help: errors occurred and after the restart of the application no parts were displayed. So I added my code to the #PreSave method.
Related
My eclipse 3.x RCP app has 2 perspectives. When the app starts and Perspective A is active then all parts are created and displayed correctly. When the app starts and Perspective B is active then most parts are empty and createControl is never called. If I reset the perspective then all parts are created properly.
So far I have found that part in PartActivationHistory.activate has a null context and this causes a NullPointerException. Why might this be? Who sets the context and when?
void activate(MPart part, boolean activateBranch) {
IEclipseContext context = part.getContext();
if (activateBranch) {
context.activateBranch();
} else {
IEclipseContext parent = context.getParent();
do {
context.activate();
context = parent;
parent = parent.getParent();
} while (parent.get(MWindow.class) != null);
}
prepend(part);
}
The problem was caused by performing certain actions before the Workbench was fully initialised. This does not seem to have been a problem in the past but I have recently updated the platform from Kepler to 2020/6.
I built a small e4 RCP application containing both an "e4 xmi" tree view populated by emf generated model code (using ComposedAdapterFactory) and an "e3 properties view".
Tried following "dirksmetric tutorial" to display property view in application.e4xmi (shared elements) with an empty property view.
To get a tree's selected element displayed in my property sheet (IItemPropertySource), I did the following things :
On my e4 treeviewer side, I use the e4 selection service in #createComposite:
// Register the viewer as a selection provider (to be consumed by the property view...)
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
// set the selection to the service
selectionService.setSelection(
selection.size() == 1? selection.getFirstElement(): selection.toArray());
}
});
On the e3 "classical" property sheet side, I defined a couple of things :
I called IDE.registerAdapters in my ApplicationWorkbenchAdvisor#initialize.
I declared my property source adapter as follow in my plugin.xml :
extension point="org.eclipse.core.runtime.adapters">
factory adaptableType="org.eclipse.emf.ecore.EObject"
class="myappmodeler.properties.ModelPropertiesAdapter">
adapter type="org.eclipse.ui.views.properties.IPropertySource">
My ModelPropertiesAdapter#getAdapter returns a property source :
public Object getAdapter(Object adaptableObject, Class adapterType) {
if (adapterType== IPropertySource.class && adaptableObject instanceof EObject){
emfGlobalFactory = new ComposedAdapterFactory();
emfGlobalFactory.addAdapterFactory(new RepositorystructureItemProviderAdapterFactory());
emfGlobalFactory.addAdapterFactory(new ApplicationItemProviderAdapterFactory());
emfGlobalFactory.addAdapterFactory(new ServiceItemProviderAdapterFactory());
return new AdapterFactoryContentProvider(emfGlobalFactory).getPropertySource(adaptableObject);
}
return null;
}
My problem is this adapter is not even executed.
Currently using Eclipse neon (it was recently updated to synchronise E3 and E4 selection service)
https://bugs.eclipse.org/bugs/show_bug.cgi?id=403930
There are different ways to fix this problem, but for my case, these are the steps
I took to these steps to solve mine
Take control of the base model - create an interface which extends EObject
Create custom property provider, source and descriptor - extends org.eclipse.emf.edit.ui.provider.*
at runtime we need IItemPropertySource
Create a content provider class (extends AdapterFactoryContentProvider) and override createPropertySource with custom property source
Note; I also developed a table layout which means implementing custom ItemProvider (implement ITableItemLabelProvider) for individual elements in the model
Worked perfectly with ESelectionService
Hope these notes helps somebody
For an RCP E4 Text Editor application implemented with a StyledText/SourceViewer it is necessary receive the status of the inset key.
Once received the state (insert, smart-insert), the application shall modify the cursor icon and notify other parts the INSERT state (i.e. notify to the status bar control like in a normal plain text editor behavior).
SWT.INSERT only listens for the key to be pressed, but nothing if the StyledText is in INSERT MODE.
styledText.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
if(e.keyCode == SWT.INSERT){
System.out.println("INSERT KEY PRESSED!!!");
}
}
};
I have avoided to extend
org.eclipse.ui.texteditor.AbstractTextEditor
and use the method
getInsertMode()
since the application is intended to be pure E4 text editor.
Any hint?
Thanks in advance
First off you need to tell the StyledText not to do the default action when it sees the Insert key:
textWidget.setKeyBinding(SWT.INSERT, SWT.NULL);
Next you need to define a Command, Handler and Key Binding in the context for the editor to deal with the Insert key.
The Handler for the insert command can update the status display and shoyld then tell the StyledText to update the overwrite mode:
textWidget.invokeAction(ST.TOGGLE_OVERWRITE);
Also note that Mac keyboards don't have an Insert key!
Since I found some difficulties to deal with the INSERT_KEY within a sourceviewer control for E4 RCP text editor, I will write extra details to gregg449's answer (great help from him as everytime!).
Following the above answer, I have created Binding Context, Binding Table, Command, Handler and added the Binding Context to the required Part (the part implementing the SourceViewer).
The next code is for SourceViewer and InserKey Handler:
public class CheckKeyBindingSourceViewer extends ITextEditorPart{
public SourceViewer sv = null;
public StyledText st = null;
#PostConstruct
public void postConstruct(Composite parent) {
sv = new SourceViewer(parent, null, null, true, SWT.MULTI | SWT.V_SCROLL |SWT.H_SCROLL);
IDocument doc = new Document("");
sv.setDocument(doc);
st = sv.getTextWidget();
//tell the StyledText not to do the default action when it sees the Insert key
st.setKeyBinding(SWT.INSERT, SWT.NULL);
}
}
public class InsertKeyHandler {
#Execute
public void execute(#Named(IServiceConstants.ACTIVE_PART) MPart activePart) {
if (activePart.getObject() instanceof ITextEditorPart){
ITextEditorPart theSourceViewer = (ITextEditorPart) activePart.getObject();
theSourceViewer.st.invokeAction(ST.TOGGLE_OVERWRITE);
//TODO
//Change cursor sourcewiewer, notify to Statusbar...
}
}
}
The next figure shows the Application.e4xmi with the Binding Context and Binding Table created.
Note that if you do not add the supplementary tag "type:user" to the Binding Table, the bindings are not working at all.
This is not reflected into vogella's tutorial (http://www.vogella.com/tutorials/EclipseRCP/article.html) neither his book.
The only place I found this information was at stackoverflow question:
eclipse rcp keybindings don't work
I'm using eclipse Mars (4.5.0) for both Linux and Windows, I do not know if for newer verions this 'bug' is solved.
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");
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.