blob: aa27f1a8251f9f9369ae01dbd422b1b1448927a8 [file] [log] [blame]
/*********************************************************************************
* Copyright (c) 2021 Robert Bosch GmbH and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Robert Bosch GmbH - initial API and implementation
********************************************************************************
*/
package org.eclipse.app4mc.amalthea.model.editor.contribution.menu;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem;
import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory;
/**
* Builds a hierarchical menu structure based on path description of added menu items.
*
* Path segments are separated by "|".
*
*/
public class MenuBuilder {
private Map<String, MenuBuilder> subMenus = new HashMap<>();
private Map<String, MHandledMenuItem> menuItems = new HashMap<>();
/**
* Adds a menu item to the menu.
*
* @param path describes the position in the hierarchical menu (e.g. "Actions | Undo")
* @param menuItem the configured menu item (the last segment of the path is set as label)
*/
public void addMenuItem(String path, MHandledMenuItem menuItem) {
StringTokenizer tokenizer = new StringTokenizer(path, "|");
addMenuItem(tokenizer, menuItem);
}
private void addMenuItem(StringTokenizer tokenizer, MHandledMenuItem menuItem) {
String label = tokenizer.nextToken().trim();
if (tokenizer.countTokens() == 0) {
// last token -> add menu item
menuItem.setLabel(label);
menuItems.put(label, menuItem);
} else {
// intermediate token -> enter sub menu
MenuBuilder builder = subMenus.computeIfAbsent(label, k -> new MenuBuilder());
builder.addMenuItem(tokenizer, menuItem);
}
}
/**
* Adds the menu structure (sub menus and menu items) to a given list of menu elements.
* <p>
* Order:
* <ul>
* <li>sub menus before menu entries</li>
* <li>sub menus in alphabetic order</li>
* <li>menu entries in alphabetic order</li>
* </ul>
*
* @param items
*/
public void populateMenuElementsList(List<MMenuElement> items) {
// add sub menus
subMenus.entrySet().stream()
.sorted(Comparator.comparing(Entry::getKey))
.forEachOrdered(e -> {
MMenu subMenu = MMenuFactory.INSTANCE.createMenu();
subMenu.setLabel(e.getKey());
items.add(subMenu);
e.getValue().populateMenuElementsList(subMenu.getChildren());
});
// add menu items
menuItems.entrySet().stream()
.sorted(Comparator.comparing(Entry::getKey))
.forEachOrdered(e -> items.add(e.getValue()));
}
}