package org.simantics.modeling.ui.actions.e4; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.e4.ui.di.UISynchronize; import org.eclipse.e4.ui.model.application.ui.menu.MToolControl; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.simantics.Simantics; import org.simantics.browsing.ui.NodeContext; import org.simantics.browsing.ui.common.NodeContextBuilder; import org.simantics.browsing.ui.model.InvalidContribution; import org.simantics.browsing.ui.model.actions.ActionBrowseContext; import org.simantics.browsing.ui.model.actions.IActionCategory; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.BinaryRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.Listener; import org.simantics.modeling.ui.Activator; /** * Used like this in E4 model fragments: * *
 * 
 *  
 *    
 *      
 *        http://www.simantics.org/Project-1.2/MainToolbarActionContext
 *      
 *    
 *  
 * 
 * 
* * @author Antti Villberg * @author Jani Simomaa * @author Tuukka Lehtonen */ public class GlobalModeledToolbarActions { @Inject UISynchronize sync; private List browseContexts; private boolean disposed; private Composite composite; @PostConstruct protected void create(Composite parent, MToolControl control) { this.composite = parent; browseContexts = new ArrayList<>(control.getTags()); Simantics.getSession().asyncRequest( new GetContributions(Simantics.getProjectResource(), browseContexts), new ContributionListener()); } @PreDestroy private void dispose() { disposed = true; if (composite != null) { for (Control c : composite.getChildren()) c.dispose(); composite = null; } } class ContributionListener implements Listener>, Runnable { AtomicReference> lastResult = new AtomicReference<>(); @Override public void execute(List result) { if (composite != null) { lastResult.set(result); sync.asyncExec(this); } } @Override public void run() { List result = lastResult.getAndSet(null); if (result == null || composite == null || composite.isDisposed()) return; ToolBar tb = (ToolBar) composite.getParent(); for (ToolItem item : tb.getItems()) item.dispose(); for (IContributionItem item : result) item.fill(tb, -1); Composite tbp = tb.getParent(); tbp.layout(true, true); } @Override public void exception(Throwable t) { Activator.getDefault().getLog().log( new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.GlobalModeledToolbarActions_ActivatorGlobalModeledToolbarException, t)); } @Override public boolean isDisposed() { return disposed; } } static class GetContributions extends BinaryRead, List> { public GetContributions(Resource from, Collection browseContextNames) { super(from, browseContextNames); } @Override public List perform(ReadGraph graph) throws DatabaseException { return getContributionItems(graph, parameter, parameter2); } } private static Collection getBrowseContextResources(ReadGraph graph, Collection browseContexts) throws DatabaseException { List result = new ArrayList(browseContexts.size()); for (String name : browseContexts) result.add(graph.getResource(name)); return result; } private static List getContributionItems(ReadGraph graph, Resource from, Collection browseContextNames) throws DatabaseException { Collection browseContexts = getBrowseContextResources(graph, browseContextNames); NodeContext nodeContext = NodeContextBuilder.buildWithInput(from); try { ActionBrowseContext defaultContext = ActionBrowseContext.create(graph, browseContexts); ActionBrowseContext browseContext = ActionBrowseContext.get(graph, nodeContext, defaultContext); Map> result = browseContext.getActions(graph, nodeContext, Collections.singletonList(nodeContext)); return toContributionItems(result); } catch (InvalidContribution e) { Activator.getDefault().getLog().log( new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.GlobalModeledToolbarActions_ActivatorEncounteredInvalidContributionException, e)); } return Collections.emptyList(); } private static List toContributionItems(Map> map) { if (map.isEmpty()) return Collections.emptyList(); IActionCategory[] categories = map.keySet().toArray(new IActionCategory[map.size()]); Arrays.sort(categories, IActionCategory.ACTION_CATEGORY_COMPARATOR); ArrayList items = new ArrayList<>(); boolean first = true; for (IActionCategory category : categories) { List actions = map.get(category); Collections.sort(actions, ACTION_COMPARATOR); if (category != null && category.isSubmenu()) { MenuManager manager = new MenuManager(category.getLabel()); for (Action action : actions) manager.add(new ActionContributionItem(action)); items.add(manager); } else { if (first) first = false; else items.add(new Separator(category == null ? "" : category.getLabel())); //$NON-NLS-1$ for (Action action : actions) items.add(new ActionContributionItem(action)); } } return items; } private static final Comparator ACTION_COMPARATOR = (o1, o2) -> { String t1 = o1.getText(); String t2 = o2.getText(); return t1 == null ? (t2 == null ? 0 : -1) : (t2 == null ? 1 : t1.compareTo(t2)); }; }