RCP Problem mit MenuManager

dzim

Top Contributor
Hallo zusammen,

ich habe vor kurzem begonnen eine Anwendung noch ein wenig zu "pimpen".
Dazu fiel mir auf, das vor allem viele Tabellen und Trees keine Menüs haben und viele Funktionen umständliche (also: weiter Weg mit der Maus) nur über Buttons steuerbar sind (add/edit/remove/...)

Ich habe daher angefangen mittels MenuManager das ganze aufzupeppen:
Java:
final MenuManager menuManager = new MenuManager();
menuManager.setRemoveAllWhenShown(true);
final Menu menu = menuManager.createContextMenu(tableViewer
		.getControl());
menuManager.addMenuListener(new IMenuListener() {

	@Override
	public void menuAboutToShow(final IMenuManager manager) {
		manager.setRemoveAllWhenShown(true);
		fillContextMenu(ssdModel, tableViewer, manager);
	}
});
tableViewer.getControl().setMenu(menu);

Das funktioniert für meinen ersten TreeViewer hervorragend, für einen anderen aber überhaupt nicht.
Ich wollte zur fillContextMenu-Methode debuggen, stellte aber einfach fest, dass der Listener offenbar nie ausgelöst wurde.
Der folgende Hack zeigt beim ersten Rechtsklick das Menü (mit DropDown-Menü-Item), beim zweiten Klick sind die DropDown-Items auf einmal auf der Hauptebene der Menü-Items. Beim dritten Klick verrent sich (reproduzierbar) offenbar mein fglrx Graphiktreiber (Ubuntu 11.04/Unity).
Java:
ispTableViewer.getTable().addMenuDetectListener(
		new MenuDetectListener() {

			@Override
			public void menuDetected(MenuDetectEvent e) {
				if (!menuManager.getMenu().isDisposed())
					menuManager.getMenu().setVisible(true);
				}
		});

Ich versteh aber schlicht und ergreifend nicht, warum der grundsätzlich gleiche Code in einem Composite geht, und in einem anderen nicht.
Kann es an inkompatibilitäten mit anderen Listenern liegen, die die Ausführung des IMenuListener des MenuManagers verhindern?

Vielen Dank und Grüße,
Daniel

PS: meine fillContextMenu-Methode:
Java:
	private void fillContextMenu(SSDModel ssdModel, TableViewer viewer,
			IMenuManager manager) {

		Object[] selection = ((IStructuredSelection) viewer.getSelection())
				.toArray();

		Action action = new AddEditRemoveEntryAction(ssdModel, selection,
				viewer, AddEditRemoveEntryAction.Type.ADD);
		manager.add(action);

		action = new AddEditRemoveEntryAction(ssdModel, selection, viewer,
				AddEditRemoveEntryAction.Type.EDIT);
		if (selection == null || selection.length == 0 || selection.length > 1) {
			action.setEnabled(false);
		}
		manager.add(action);

		action = new AddEditRemoveEntryAction(ssdModel, selection, viewer,
				AddEditRemoveEntryAction.Type.REMOVE);
		if (selection == null || selection.length == 0) {
			action.setEnabled(false);
		}
		manager.add(action);

		manager.add(new Separator());

		action = new AddEditRemoveEntryAction(ssdModel, selection, viewer,
				AddEditRemoveEntryAction.Type.MENU);
		if (selection == null || selection.length == 0 || selection.length > 1) {
			action.setEnabled(false);
		}
		manager.add(action);
	}

PPS: Die Action(s), die ich in den MenuManager rein werfe (gekürzt, da zu lang):
Java:
public class AddEditRemoveEntryAction extends Action {

	private static final Image ADD = IconProvider.getImageByIconName(
			"fugue_plus.png", true); //$NON-NLS-1$
	private static final Image REMOVE = IconProvider.getImageByIconName(
			"fugue_minus.png", true); //$NON-NLS-1$
	private static final Image EDIT = IconProvider.getImageByIconName(
			"fugue_pencil.png", true); //$NON-NLS-1$
	private static final Image CALENDAR = IconProvider
			.getImageByIconName("fugue_calendar--pencil.png", true); //$NON-NLS-1$

	public static enum Type {
		ADD, EDIT, REMOVE, MENU;
	}

	private SSDModel ssdModel;
	private Object[] selection;

	private Viewer parentViewer;

	private AddEditRemoveEntryAction.Type type;

	// used only if Type == MENU
	private MenuCreatorImpl menuCreator = null;

	public AddEditRemoveEntryAction(SSDModel ssdModel, Object[] selection,
			Viewer parentViewer, AddEditRemoveEntryAction.Type type) {

		super("", Type.MENU == type ? AS_DROP_DOWN_MENU : AS_PUSH_BUTTON); //$NON-NLS-1$

		this.ssdModel = ssdModel;
		this.selection = selection;
		this.parentViewer = parentViewer;
		this.type = type;

		switch (type) {
		case ADD:
			setText(Messages
					.getString("EntrySettingsComposite.addButton.text")); //$NON-NLS-1$
			setImageDescriptor(ImageDescriptor.createFromImage(ADD));
			break;
		case EDIT:
			setText(Messages
					.getString("EntrySettingsComposite.editButton.text")); //$NON-NLS-1$
			setImageDescriptor(ImageDescriptor.createFromImage(EDIT));
			break;
		case REMOVE:
			setText(Messages
					.getString("EntrySettingsComposite.deleteButton.text")); //$NON-NLS-1$
			setImageDescriptor(ImageDescriptor.createFromImage(REMOVE));
			break;
		case MENU:
			setText("Edit Retention Time");
			setImageDescriptor(ImageDescriptor.createFromImage(CALENDAR));
			// create MenuCreatorImpl (private class at the end of this one)
			menuCreator = new MenuCreatorImpl();
			setMenuCreator(menuCreator);
			break;
		}
	}

	@Override
	public void run() {

		switch (type) {
		case ADD:
			handleAdd();
			break;
		case EDIT:
			handleEdit();
			break;
		case REMOVE:
			handleRemove();
			break;
		case MENU:
			// create menu
			handleMenu();
			break;
		}
	}

	private void handleAdd() {
		[...]
	}

	private void handleEdit() {
		[...]
	}

	private void handleRemove() {
		[...]
	}

	private void handleMenu() {
		setMenuCreator(menuCreator);
		Menu menu = menuCreator.getMenu(parentViewer.getControl());
		if (menu != null && !menu.isDisposed())
			menu.setVisible(true);
	}

	private class MenuCreatorImpl implements IMenuCreator {

		private Menu menu;

		@Override
		public void dispose() {
			if (menu != null) {
				menu.dispose();
			}
		}

		@Override
		public Menu getMenu(Menu parent) {
			return getMenu(parent.getShell());
		}

		@Override
		public Menu getMenu(Control parent) {

			if (menu != null) {
				menu.dispose();
			}

			menu = new Menu(parent);

			int i = 0;
			for (LookupTimes.Day day : LookupTimes.Day.values()) {
				LookupTimeAction action = new LookupTimeAction(day,
						selection[0]);
				addActionToMenu(menu, action, i + 1);
				i++;
			}

			return menu;
		}

		private void addActionToMenu(Menu parent, Action action, int accelerator) {
			if (accelerator < 10) {
				StringBuffer label = new StringBuffer();
				// add the numerical accelerator
				label.append("&"); //$NON-NLS-1$
				label.append(accelerator);
				label.append(" "); //$NON-NLS-1$
				label.append(action.getText());
				action.setText(label.toString());
			}
			ActionContributionItem item = new ActionContributionItem(action);
			item.fill(parent, -1);
		}
	}

	private class LookupTimeAction extends Action {

		private lookupTimes.Day day;

		private Object firstSelection;

		public LookupTimeAction(LookupTimes.Day day, Object firstSelection) {
			super(day.getName(), AS_PUSH_BUTTON);
			this.day = day;
			this.firstSelection = firstSelection;
		}

		@Override
		public void run() {

			if (day == null)
				return;

			Entry e = (Entry) firstSelection;
			if (e == null)
				return;

			ModifyLookupTimeShell shell = new ModifyLookupTimeShell(
					parentViewer.getControl().getDisplay());
			shell.setData(e, day);
			Point location = parentViewer.getControl().getDisplay()
					.getCursorLocation();
			if (location != null)
				shell.openShellAtLocation(location, true);
			else
				shell.openShellOverlay(parentViewer.getControl(), true);

			ModifyLookupTimeResult result = shell.getRetentionTime();
			if (result.isCanceled()) {
				return;
			}

			if (result.getEntry() != null && result.getDay() != null) {
				Entry e = result.getEntry();
				LookupTimes lookupTimes = entry.getLookupTimes();
				if (result.getLookupTime() != null) {
					lookupTimes.setLookupTime(result.getLookupTime());
				} else {
					lookupTimes.setLookupTime(new LookupTime(result
							.getDay()));
				}
				parentViewer.refresh();
			}
		}
	}
}
 

Semox

Bekanntes Mitglied
Hallo dzim

Möglicherweise bin ich auf dem Holzweg, aber probier doch mal, ob Du bessere Ergebnisse beider Darstellung erzielst, wenn Du beim Login in Dein System von Ubuntu auf Ubuntu Classic stellst. Das geht, wenn Du auf Deinen Account klickst und unten in der Taskleiste den Anzeigemanager aus einem Drop-Down Menu wählst.

Ich habe selbst einige Probleme, bei der Darstellung der Menüs unter Ubuntu 11.04 gehabt. Dort wird in RCP Anwendungen gar kein Menü der Anwendung ins global Menu geladen. Erst als ich statt Unity auf Classic beim Login geschaltet habe, wurde das Menü wieder im eigentlichen Anwendungsfenster anständig gezeigt und war zugreifbar.

Viele Grüße,
Semo
 

dzim

Top Contributor
Das Problem kenn' ich auch: Das globale Eclipse-Menü wird noch dargestellt, aber nicht von der eigenen RCP. Das habe ich "gelöst" indem ich alle packages mit "appmenu" im Namen (sind nur eine Hand voll) deinstalliert habe. Seitdem habe ich auch kein Problem mit dem globalen Menü meiner Anwendung mehr.
Ich gebe an dieser Stelle zu, dass mir der Weg, wie Eclipse das gelöst hat lieber gewesen wäre (dann ist es universell einsetzbar), aber da der Kunde für den das Programm ist, nur Windows und Mac verwendet, spielt das eh keine Rolle.

Kurzum: Ich denke, dass mein Problem damit nichts zu tun hat. Hier habe ich irgendwie Bockmist gebaut und weiß nur nicht wo und wie! Es wird ja nur der Listener, der das Menü der Tabelle erstellen soll (wie gesagt, es geht nicht ums globale Menü der Anwendung), nicht ausgelöst wird.

Ich kann aber dennoch mal auf KDE oder so ausprobieren, wie es sich da verhält...

Thx anyway!
Daniel
 

dzim

Top Contributor
Hallo zusammen,

schade, dass mir bei dem Problem offenbar keiner weiterhelfen konnte.
Ich verstehe bis heute nicht, warum das Event (menuAboutToShow) nicht ausgelöst wird, ich habe - nachdem ich hier wieder ein wenig Zeit zum "experimentieren" hatte aber erst einmal einen Workaround gefunden, der mich die MenuManager weiter nutzen lässt:
Java:
		final MenuManager menuManager = new MenuManager();
		menuManager.setRemoveAllWhenShown(true);
		menuManager.addMenuListener(new IMenuListener() {
			@Override
			public void menuAboutToShow(final IMenuManager manager) {
				SelectionSettingsComposite.this.fillContextMenu(manager);
			}
		});
		final Menu menu = menuManager.createContextMenu(settingsTreeViewer
				.getControl());
		settingsTreeViewer.getControl().setMenu(menu);
		// FIXME this hack enables the menu
		// The menuAboutToShow method from the MenuManager is never triggered
		// for some unknown reason! (At least unknown to me...)
		settingsTreeViewer.getControl().addMenuDetectListener(
				new MenuDetectListener() {
					@Override
					public void menuDetected(MenuDetectEvent e) {
						SelectionSettingsComposite.this
								.fillContextMenu(menuManager);
						settingsTreeViewer.getControl().setMenu(
								menuManager.getMenu());
						settingsTreeViewer.getControl().getMenu()
								.setVisible(true);
					}
				});

Das Problem ist damit nicht wirklich behoben, aber ich betrachte das Thema damit erst einmal als erledigt.
Das nächste folgt allerdings auch schon wieder ;-)

Daniel
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
K Problem bei Einbinden einer DLL in Java-Projekt Plattformprogrammierung 4
Wurstsemmel RCP SWT-Problem: Programm sucht Cocoa-Bibliothek unter Windows Plattformprogrammierung 6
Shams Antbuild - Problem bei OSGi Anfängertutorial Plattformprogrammierung 0
D Problem mit eclipse Plattformprogrammierung 2
J JNA Implimentierungs Problem Plattformprogrammierung 0
Shams Problem bei der Knopflerfischinstallation Plattformprogrammierung 2
J Charset-Problem nach Plugin-Export Plattformprogrammierung 1
TheWhiteShadow RCP Problem mit Plugin Interaktion Plattformprogrammierung 6
D Eclipse_Visual Editor Problem Plattformprogrammierung 2
J Eclipse Plug-In für UML-Diagramme Problem Plattformprogrammierung 4
O Eclipse Plugin - Einfachstes Problem, das es gibt. Plattformprogrammierung 2
dzim OSGi Problem beim Verwenden von Declaratice Services Plattformprogrammierung 18
T netbeans problem? Plattformprogrammierung 4
H RCP Problem mit Extension Schema Plattformprogrammierung 10
R JFace Databinding Problem Plattformprogrammierung 5
F Ecilpse plugin und MWE Workflow: classpath Problem Plattformprogrammierung 12
W Wahrscheinlich triviales Problem, aber komm nicht weiter Plattformprogrammierung 7
K SelectionListener / SelectionProvider Problem Plattformprogrammierung 2
M Xpand Anfäger Problem Plattformprogrammierung 3
K Eclipse RCP, EMF, Hibernate Problem Plattformprogrammierung 7
dzim RCP Problem mit Umsetzen des Workspace unter Win Plattformprogrammierung 4
B PreferencesService Problem Plattformprogrammierung 2
K EMF/Teneo EMap Problem Plattformprogrammierung 6
K Problem mit EMF/Teneo, GregorianCalendar, Date, Hibernate Timestamp Plattformprogrammierung 6
L RCP TreeViewer Listener Problem Plattformprogrammierung 12
C target platform problem Plattformprogrammierung 2
K NoClassDefFoundError Problem Plattformprogrammierung 24
F Eclipse: Plug-In mit Ecoding Problem Plattformprogrammierung 7
O Problem mit relativen Pfaden in einem RCP-Plugin Plattformprogrammierung 5
dzim Problem beim neuanlegen von Composites Plattformprogrammierung 4
hdi Problem bei Eclipse Plugin Export Plattformprogrammierung 9
K Bild Problem in exportierter RCP Anwendung Plattformprogrammierung 5
M Problem beim Zugriff auf Klasse aus Fragment in einem anderen Plugin Plattformprogrammierung 3
D Problem mit Synth Painter und OSGi (Equinox) Plattformprogrammierung 8
G plugin.xml Problem Plattformprogrammierung 4
I SWT Popup-Menu Problem (Position) Plattformprogrammierung 4

Ähnliche Java Themen

Neue Themen


Oben