| /********************************************************************************* |
| * 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())); |
| } |
| |
| } |