In Bug 514458, I added the “Theme” dynamic menu to the Eclipse IDE. This post explains how I did this.
Menu Eclipse 3.x style
First edit the plugin.xml
, and add a menu contribution. With the locationURI menu:org.eclipse.ui.appearance?after=org.eclipse.ui.window.appearance.separator1
, you’ll contribute a submenu to the Window > Appearance menu, just after the separator.
Add a Theme menu under the menuContribution, and then add a child dynamic element.
<menuContribution
locationURI="menu:org.eclipse.ui.appearance?after=org.eclipse.ui.window.appearance.separator1">
<menu
id="org.eclipse.ui.appearance.theme"
label="Theme">
<dynamic
class="org.eclipse.ui.internal.actions.ThemeDynamicMenu"
id="org.eclipse.ui.ide.dynamic1">
</dynamic>
</menu>
</menuContribution>
Next, create the java class implementing the dynamic menu, and add mock code to verify the menu works.
public class ThemeDynamicMenu extends ContributionItem {
@Override
public void fill(Menu menu, int index) {
MenuItem menuItem = new MenuItem(menu, SWT.CHECK, index);
menuItem.setText("Theme 1"); //$NON-NLS-1$
menuItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// executed on menu select
System.out.println("Selected"); //$NON-NLS-1$
}
});
}
}
Verify the menu is displayed where you expect, and the submenu dynamic entries are working.
Now remove the line which adds the “Theme 1” item, and rewrite the body of the widgetSelected.
The menu should have one menu item for each available theme, and each widgetSelected(){…}
should activate the corresponding theme.
The theme selection code is inspired tothe ViewsPreferencePage
one.
/**
* Implements the Dynamic Menu to choose the Theme.
*/
public class ThemeDynamicMenu extends ContributionItem {
private static String THEME_ID = "THEME_ID"; //$NON-NLS-1$
private IThemeEngine engine;
private boolean highContrastMode;
public ThemeDynamicMenu() {
IWorkbench workbench = PlatformUI.getWorkbench();
MApplication application = workbench.getService(MApplication.class);
IEclipseContext context = application.getContext();
engine = context.get(IThemeEngine.class);
highContrastMode = workbench.getDisplay().getHighContrast();
}
@Override
public void fill(Menu menu, int index) {
for (ITheme theme : engine.getThemes()) {
if (!highContrastMode && !Util.isGtk() && theme.getId().equals(E4Application.HIGH_CONTRAST_THEME_ID)) {
continue;
}
MenuItem menuItem = new MenuItem(menu, SWT.CHECK, index);
menuItem.setText(theme.getLabel());
menuItem.setData(THEME_ID, theme.getId());
menuItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
engine.setTheme(theme, !highContrastMode);
}
});
}
menu.addMenuListener(new MenuAdapter() {
@Override
public void menuShown(MenuEvent e) {
for (MenuItem item : menu.getItems()) {
boolean isActive = item.getData(THEME_ID).equals(engine.getActiveTheme().getId());
item.setEnabled(!isActive);
item.setSelection(isActive);
}
}
});
}
}
Finally, launch the Eclipse IDE to check the menu works as expected.
7 Comments
Tom Schindl · April 11, 2017 at 20:22
Should you call setSelection instead of set enabled?
psuzzi · May 7, 2017 at 16:15
The user should not select a theme that is already active. So, the setEnabled(!active) disables the menuItem, for the next time the menu is shown, the user can not select it.
The setSelected, on the other hand, is responsible for showing the “v” mark next to the menuItem.
Dennis · April 12, 2017 at 08:46
Improvement suggestion: sort the themes by name, before adding them as entries to the menu.
Max · April 12, 2017 at 16:41
Your link points to the wrong bug. Here is the correct link:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=514458
Michael Keppler · April 13, 2017 at 07:51
Link behind the bug number is wrong.
Andreas Sewe · April 13, 2017 at 11:39
Thank you for the interesting blog post, Patrik. One thing I am curious about, however, is why you chose this curious mixture of Eclipse 3.x and 4.x APIs. While you use an 3.x-style menu contribution, you later on use the 4.x IEclipseContext and IThemeEngine. Why not Eclipse 4.x all the way through?
(One more thing: The link to Bug 514458 above actually takes you to a different, unrelated bug.)
psuzzi · May 7, 2017 at 16:19
Actually, It is because I am using a dynamic menu item, linked to the Eclipse IDE via plugin.xml
see: https://git.eclipse.org/r/#/c/94854/5/bundles/org.eclipse.ui.ide.application/plugin.xml