I have succesfully managed to add view-specific toolbars to my RCP application by adding the following block to the org.eclipse.ui.menus extension point:
<menuContribution
allPopups="false"
locationURI="toolbar:my.package.path.views.ClassOfMyView">
<dynamic
class="my.package.path.toolbars.ViewToolBar"
id="MyViewToolbar">
</dynamic>
</menuContribution>
However, trying to do the same with my editorpart does not seem to work:
<menuContribution
allPopups="false"
locationURI="toolbar:my.package.path.views.ClassOfMyEditorPart">
<dynamic
class="my.package.path.toolbars.EditorPartToolBar"
id="MyEditorpartToolbar">
</dynamic>
</menuContribution>
Is there something obvious that I am missing, or is this simply not supported in RCP?
Following up on the hint about the Presentation API given by Tonny Madsen, I've come up with a solution to my problem. My solution is based on the following articles:
Eclipse RCP - Hide minimize / maximize buttons for editors and views (showing me how to supply my own presentation factory)
Incompatibilities between Eclipse 3.7 and 4.2 (helping me figure out why my presentation factory wasn't being used)
Custom RCP editor with the view header (helping me figure out how to make sure my presentation factory was being used)
To make my solution work, I ended up with changes in two files and a new class:
In the plugin.xml file, I added the following extension:
<extension point="org.eclipse.ui.presentationFactories">
<factory
name="Extended Presentation Factory"
class="org.eclipse.minicrm.ui.swt.custom.ExtendedPresentationFactory"
id="org.eclipse.minicrm.ui.swt.custom.ExtendedPresentationFactory"
/>
</extension>
This seems to be ignored by Eclipse 4.x, so to cater for those cases, I added the following line to the plugin_customisation.ini file:
org.eclipse.ui/presentationFactoryId = org.eclipse.minicrm.ui.swt.custom.ExtendedPresentationFactory
I then created the corresponding class:
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.internal.presentations.util.TabbedStackPresentation;
import org.eclipse.ui.presentations.IStackPresentationSite;
import org.eclipse.ui.presentations.StackPresentation;
import org.eclipse.ui.presentations.WorkbenchPresentationFactory;
#SuppressWarnings("restriction")
public class ExtendedPresentationFactory extends WorkbenchPresentationFactory {
private ToolBarManager m_toolBarManager = null;
private ToolBar m_toolbar = null;
#Override
public StackPresentation createEditorPresentation(final Composite parent, final IStackPresentationSite site) {
final TabbedStackPresentation presentation = (TabbedStackPresentation) super.createViewPresentation(parent, site);
m_toolbar = new ToolBar(presentation.getTabFolder().getToolbarParent(), 0);
m_toolBarManager = new ToolBarManager(m_toolbar);
m_toolBarManager.add(new MyAction1());
m_toolBarManager.add(new MyAction2());
m_toolBarManager.add(new MyAction3());
m_toolBarManager.update(true);
presentation.getTabFolder().setToolbar(m_toolbar);
return presentation;
}
}
This adds a toolbar with three buttons to my editor area.
I will still need to fiddle with some of the finer points (placement etc), but for a start it satisfies my need for a toolbar in the editor area.
These are some important visual differences between editors and views:
Editors provide additional actions to the top-level menu and the tool bar; views do not*
Views have an independent menu bar and tool bar; editors do not
There are at most one active editor in a perspective; there can be any number of active views
The are at most one view of each “type”; there can be any number of editors*
Editors are all placed in the “editor area”; views are placed in a number of “view stacks”
Some of these differences (marked with * above) can be ironed out using various functionality of the RCP platform:
The interface ISaveblePart can give a view the same life-cycle as an editor.
The menues extension point can add items to the main menu and tool bar when a view is active.
The views extension point can be used to allow multiple views of the same type.
With Eclipse 4, you can also combine editors and views in the same stack or folder.
But adding a menu or tool bar as seen with views require more work! But it can be done using the Presentation API, where most of the visual difference can be ironed out.
One additional comment: It is not toolbar:my.package.path.views.ClassOfMyView but toolbar:id-of-the-view.
Related
Description
I have developed a Visual Studio extension (VSPackage) which adds a new Project Type to Visual Studio (using CPS Project System). I also have added some Commands to the VSPackage.
When right clicking on my Project Node in the Solution Explorer, I want to have a customized context menu to appear.
Example
For example: in the screen shot below, I want to get rid of the Build command and add a custom command (e.x. mycommand).
I tried..
Setting the Parent of my custom command to IDM_VS_CTXT_PROJNODE.
Question
When I create a new Custom Project Type, How to create a new Context Menu for my Project Nodes in the Solution Explorer?
How to remove/add Commands to the Context Menu only for the Custom Projects:
If I have a C# project, the context menu should be the default one, if I add a MyProjectType project, I want to see a different context menu when right clicking on the Project Node in the Solution Explorer.
You were close with the IDM_VS_CTXT_PROJNODE parent.
Here is how I achieved it in my FluentMigratorRunner extension, which only shows its context menu item for a project if it has a reference to the FluentMigrator NuGet package.
Step 1: Add a submenu to the context menu
<Menus>
<Menu guid="guidCmdSet" id="packageMenu" priority="0x0300" type="Menu">
<Parent guid="guidSHLMainMenu" id="IDG_VS_CTXT_PROJECT_BUILD" />
<CommandFlag>DynamicVisibility</CommandFlag>
<CommandFlag>DefaultInvisible</CommandFlag>
<Strings>
<ButtonText>CPSProject</ButtonText>
<CommandName>CPSProject</CommandName>
</Strings>
</Menu>
Note the added special CommandFlag elements.
Step 2: Add a group to the menu
<Groups>
<Group guid="guidCmdSet" id="packageMenuGroup" priority="0x0600">
<Parent guid="guidCmdSet" id="packageMenu" />
</Group>
</Groups>
Step 3: Add a button
<Button guid="guidCmdSet" id="specialBuildActionId" priority="0x0100" type="Button">
<Parent guid="guidCmdSet" id="packageMenuGroup" />
<CommandFlag>DynamicVisibility</CommandFlag>
<Strings>
<ButtonText>Special build</ButtonText>
</Strings>
Step 4: Add the menu in your *Package.cs
protected override async System.Threading.Tasks.Task InitializeAsync(System.Threading.CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
// Initialize the Fluent Migrator Menu, should only be visible for projects with FluentMigrator reference
var mcs = await GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
var menuCommandId = new CommandID(packageCmdSetGuidString, 0x1010);
var menuItem = new OleMenuCommand(null, menuCommandId);
menuItem.BeforeQueryStatus += MenuItem_BeforeQueryStatus;
mcs.AddCommand(menuItem);
}
private void MenuItem_BeforeQueryStatus(object sender, EventArgs e) =>
((OleMenuCommand)sender).Visible = ???;
Note the added BeforeQueryStatus eventhandler.
In that eventhandler you can check the type of the project and return a boolean controlling if the extra context menu should be shown yes or no
I'm not sure about removing the existing Build menu item... but as for having context menu items appear only when right-clicking on your custom project type, <VisibilityConstraints> might help:
(Excerpt from an example usage):
Often a package is being loaded to run a BeforeQueryStatus method for a button to determine its visibility. With <VisibilityConstraints> we can determine the visibility of a button without running BeforeQueryStatus and therefore don't need to load the package before the user clicks the button.
I've only ever used this strategy to show menu items for specific file types, but there are also some term types related to projects that might be more useful for this scenario.
I'm trying to write a custom text editor with a reconciler that will update the AST and create markers for the errors, if there are any. I managed to add markers that show up in the left ruler of the editor and in the problems view. However, I also want those errors to be underlined in the text. That doesn't work. None of the text is underlined. If I double click on one of the errors in the problem view however, the corresponding text in the text editor is selected. As far as I understand, I need to add an annotation in addition to the marker. This is what I have tried so far:
final IResource resource = ResourceUtil.getResource(getEditorInput());
final IMarker marker = resource.createMarker("com.test.myproblemmarker");
marker.setAttribute(IMarker.MESSAGE, "hello");
marker.setAttribute(IMarker.CHAR_START, 2);
marker.setAttribute(IMarker.CHAR_END, 10);
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
final IDocumentProvider idp = getDocumentProvider();
final IDocument document = idp.getDocument(getEditorInput());
final IAnnotationModel iamf = idp.getAnnotationModel(getEditorInput());
final SimpleMarkerAnnotation ma = new SimpleMarkerAnnotation("org.eclipse.ui.workbench.texteditor.error", marker);
ma.setText("hello");
iamf.connect(document);
iamf.addAnnotation(ma, new Position(2, 8));
ma.update();
iamf.disconnect(document);
ma.update();
The relevant parts from plugin.xml:
<extension id="com.test.problemmarker" point="org.eclipse.core.resources.markers" name="A Problem">
<super type="org.eclipse.core.resources.problemmarker"/>
<super type="org.eclipse.core.resources.textmarker"/>
<persistent value="true"/>
</extension>
<extension point="org.eclipse.ui.editors.markerAnnotationSpecification" id="myannotationspecification" name="MyAnnotation">
<specification
annotationType="com.test.problemannotation"
label="MyAnnotation"
icon="icons/icon16x16.png"
overviewRulerPreferenceKey="clruler"
overviewRulerPreferenceValue="true"
colorPreferenceKey="clcolor"
colorPreferenceValue="255,0,0"
textPreferenceKey="cltext"
textPreferenceValue="true"
verticalRulerPreferenceKey="clvertical"
verticalRulerPreferenceValue="true"
textStylePreferenceKey="clstyle"
textStylePreferenceValue="UNDERLINE"
presentationLayer="4">
</specification>
</extension>
<extension point="org.eclipse.ui.editors.annotationTypes">
<type
markerSeverity="2"
super="org.eclipse.ui.workbench.texteditor.error"
name="com.test.problemannotation"
markerType="com.test.problemmarker"/>
</extension>
The custom text editor inherits from TextEditor and the reconciler is a MonoReconciler. Seems like a pretty standard setup, when I look at existing editor / reconciler implementations. I appreciate any help!
Ok, I was able to fix it myself. The problem was, that I set my own preference store in the constructor of the TextEditor subclass:
setPreferenceStore(MyPlugin.getDefault().getPreferenceStore());
I set a few breakpoints in the AnnotationPainter class and realized that all
annotations were disabled. When I removed this line from the editor, the annotations appeared.
I also noticed that it is sufficient to just create a marker. A corresponding annotation will be added automatically.
I added a JFace action to the workbench coolbar of an RCP application using a subclass of the ActionBarAdvisor. For some reason the corresponding menu is drawn with what I guess is an extra line. It is causing the whole coolbar including the list of open perspectives to be way too tall:
Anyone know how to make it single-lined? I tried adding SWT.SINGLE style to the Action constructor, but that didn't help. Any help would be appreciated. Thanks.
ActionBarAdvisor.fillCoolBar() implementation:
protected void fillCoolBar(final ICoolBarManager coolBar) {
final IToolBarManager toolbar = new ToolBarManager(coolBar.getStyle());
coolBar.add(new ToolBarContributionItem(toolbar, "main"));
toolbar.add(new Pulldown());
}
Action implementation:
public class Pulldown extends Action {
public Pulldown() {
super("Saved Layouts");
setMenuCreator(menuCreator);
}
...
}
It's not direct the answer of your problem, but I would declare the button as menu extension with dropdown/radio style. Thus you don't have to change the code of the coolbar.Here is a tutorial about toolbar menu contributions.
<extension
point="org.eclipse.ui.menus">
<menuContribution
allPopups="false"
locationURI="toolbar:de.example.com">
<command
commandId="de.abas.erp.wb.base.marker.commands.PullDownCommand"
icon="icons/16x16/layouts.png"
label="Saved Layouts"
style="pulldown">
</command>
</menuContribution>
</extension>
I've added to my perspective's org.eclipse.ui.menus
<command
commandId="org.eclipse.ui.views.showView"
style="pulldown">
</command>
This adds Show View item to main menu, but this item is not a menu (as in the Eclipse Window menu). Instead pressing it shows a dialog where I can select a view. How do I get a menu instead?
You have to create ContributionItem class like below:
public class MyShowViewContributionItem extends org.eclipse.ui.internal.ShowViewMenu {
public MyShowViewContributionItem() {
this("om.myplugin.myShowViewId");
}
public MyShowViewContributionItem(String id) {
super(org.eclipse.ui.PlatformUI.getWorkbench().getActiveWorkbenchWindow(), id);
}
}
then in your plugin.xml org.eclipse.ui.menus extension:
<menu
label="My Show View">
<dynamic
class="com.myplugin.MyShowViewContributionItem"
id="com.myplugin.myShowViewId">
</dynamic>
</menu>
Cheers,
Max
Just to share on my recent experiment in trying to do the same thing, what Max suggested in his answer will work but leaves you using internal code (resulting in a 'Discouraged Access' warning).
Another approach is to build the menu through your applications action bar advisor. Although, this approach will leave you to having to write code (oppose to use providing menu contributions in the plugin XML definition). Consider the following example:
public class ApplicationActionBarAdvisor extends ActionBarAdvisor
{
private IContributionItem contributionOpenPerspective;
private IContributionItem contributionShowView;
...
protected void makeActions(IWorkbenchWindow window)
{
...
contributionOpenPerspective = ContributionItemFactory.
PERSPECTIVES_SHORTLIST.create(window);
contributionShowView = ContributionItemFactory.
VIEWS_SHORTLIST.create(window);
...
}
protected void fillMenuBar(IMenuManager menuBar)
{
...
MenuManager windowMenu = new MenuManager("&Window",
IWorkbenchActionConstants.M_WINDOW);
menuBar.add(windowMenu);
MenuManager openPerspectiveMenu = new MenuManager("&Open Perspective");
openPerspectiveMenu.add(perspectivesContribution);
windowMenu.add(openPerspectiveMenu);
MenuManager showViewMenu = new MenuManager("Show &View");
showViewMenu.add(viewsContribution);
windowMenu.add(showViewMenu);
...
}
}
A possible downside to this approach is with the interaction between menus created in the advisor and menus created by menu contributions. Since advisor menu items are created before menu contributions, you are left to deal with adding more sorting logic in your menu contributions. This might be fine for most people, however, you lose the 'feel' of a centralized menu structure from org.eclipse.ui.menus (even if the feeling is an illusion when other plugins come into play with their own menu contributions).
I've also included the building of a perspective menu as well; completely option, but I added it if anyone was attempting to perform the same menu building with perspectives.
I have a custom graphical EditorPart in a Eclipse RCP application.
It sets a custom ISelectionProvider in the createPartControl(..) method:
#Override
public void createPartControl(Composite parent) {
// [snip]
getSite().setSelectionProvider((ISelectionProvider)model.getSelection());
}
I have two ViewParts listening to selection changes via the ISelectionService. They get notified when the selection in the EditorPart changes. So far so good.
Now I've added a handler using the following XML:
<handlerclass="my.custom.Handler" commandId="org.eclipse.ui.edit.delete">
<enabledWhen>
<count value="+"/>
</enabledWhen>
</handler>
If the selection in the EditPart contains > 0 elements, this should enable the handler my.custom.Handler, but it doesn't.
It is, however enabled if the selection provided by built-in selection providers changes to > 0 element (i.e. those provided by JFace viewers).
Any hint how to integrate a custom implementation of ISelectionProvider with the expression framework used in the handler declaration?
enabledWhen can contain any expression. You need to specify that you want the selection variable there. See here for an example: http://eclipse-tips.com/tutorials/1-actions-vs-commands?start=1