/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Whole Platform is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.lang.e4.actions; import static org.whole.lang.actions.reflect.ActionsEntityDescriptorEnum.*; import static org.whole.lang.e4.ui.actions.IE4UIConstants.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.jface.action.IAction; import org.eclipse.jface.resource.ImageDescriptor; import org.whole.lang.actions.model.Action; import org.whole.lang.actions.model.ActionKindEnum; import org.whole.lang.actions.model.ActionKindEnum.Value; import org.whole.lang.actions.model.ActionKind; import org.whole.lang.actions.model.Actions; import org.whole.lang.actions.model.CustomAction; import org.whole.lang.actions.model.FillStrategy; import org.whole.lang.actions.model.GroupAction; import org.whole.lang.actions.model.Hierarchical; import org.whole.lang.actions.model.Icon; import org.whole.lang.actions.model.PerformAction; import org.whole.lang.actions.model.Predicate; import org.whole.lang.actions.model.SeparatedAction; import org.whole.lang.actions.model.Size; import org.whole.lang.actions.model.SubgroupAction; import org.whole.lang.actions.model.TemplateAction; import org.whole.lang.actions.model.Text; import org.whole.lang.actions.visitors.ActionsInterpreterVisitor; import org.whole.lang.bindings.BindingManagerFactory; import org.whole.lang.commons.factories.CommonsEntityAdapterFactory; import org.whole.lang.e4.ui.actions.ActionFactory; import org.whole.lang.matchers.Matcher; import org.whole.lang.model.IEntity; import org.whole.lang.queries.factories.QueriesEntityFactory; import org.whole.lang.queries.reflect.QueriesEntityDescriptorEnum; import org.whole.lang.ui.actions.ActionsComparator; import org.whole.lang.ui.actions.EnablerPredicateFactory; import org.whole.lang.ui.actions.IUpdatableAction; import org.whole.lang.ui.editparts.IEntityPart; import org.whole.lang.ui.enablerpredicate.IEnablerPredicate; import org.whole.lang.ui.menu.ActionSet; import org.whole.lang.ui.menu.FlatFillMenuStrategy; import org.whole.lang.ui.menu.FullMenuNameStrategy; import org.whole.lang.ui.menu.HierarchicalFillMenuStrategy; import org.whole.lang.ui.menu.IFillMenuStrategy; import org.whole.lang.ui.menu.IItemContainer; import org.whole.lang.ui.menu.IMenuNameStrategy; import org.whole.lang.ui.menu.PrefixMenuNameStrategy; import org.whole.lang.util.DataTypeUtils; import org.whole.lang.util.EntityUtils; import org.whole.lang.util.IEntityTransformer; /** * @author Enrico Persiani */ @SuppressWarnings("unchecked") public class ActionsE4InterpreterVisitor extends ActionsInterpreterVisitor { @Override public void visit(Text entity) { setResult(entity); } @Override public void visit(Icon entity) { setResult(entity); } @Override public void visit(ActionKind entity) { setResult(entity); } @Override public void visit(Size entity) { setResult(entity); } @Override public void visit(SeparatedAction entity) { entity.getAction().accept(this); } @Override public void visit(PerformAction entity) { entity.getKind().accept(this); ActionKindEnum.Value kind = ((ActionKind) getResult()).getValue(); entity.getText().accept(this); String text = getResult().wStringValue(); Predicate enablerPredicate = entity.getEnablerPredicate(); IEnablerPredicate predicate = null; if (EntityUtils.isResolver(enablerPredicate)) predicate = EnablerPredicateFactory.instance.alwaysTrue(); else { enablerPredicate.accept(this); predicate = createEnablerPredicate(getResult()); } //TODO! entity.getConfiguration() entity.getTransformation().accept(this); IAction action = createAction(kind, predicate, null, getResult(), text); Icon icon = entity.getIcon(); if (DataTypeUtils.getDataKind(icon).isObject()) action.setImageDescriptor((ImageDescriptor) icon.wGetValue()); setResult(BindingManagerFactory.instance.createValue(action)); } @Override public void visit(TemplateAction entity) { entity.getKind().accept(this); ActionKindEnum.Value kind = ((ActionKind) getResult()).getValue(); entity.getText().accept(this); String text = getResult().wStringValue(); Predicate enablerPredicate = entity.getEnablerPredicate(); IEnablerPredicate predicate = null; if (EntityUtils.isResolver(enablerPredicate)) predicate = EnablerPredicateFactory.instance.alwaysTrue(); else { enablerPredicate.accept(this); predicate = createEnablerPredicate(getResult()); } //TODO? entity.getConfiguration() //TODO use custom IEntityTransformer if available entity.getTransformation().accept(this); IAction action = createAction(kind, predicate, null, getResult(), text); Icon icon = entity.getIcon(); if (DataTypeUtils.getDataKind(icon).isObject()) action.setImageDescriptor((ImageDescriptor) icon.wGetValue()); setResult(BindingManagerFactory.instance.createValue(action)); } @Override public void visit(CustomAction entity) { setResult(entity); } @Override public void visit(Actions entity) { IItemContainer<IAction, ImageDescriptor> container = (IItemContainer<IAction, ImageDescriptor>) getBindings().wGetValue("itemContainer"); IFillMenuStrategy strategy = (IFillMenuStrategy) getBindings().wGetValue("fillMenuStrategy"); int size=entity.wSize(); List<IAction> contributions = new ArrayList<IAction>(); for (int i=0; i < size; i++) { Action action = (Action) entity.wGet(i); if (Matcher.isAssignableAsIsFrom(GroupAction, action)) { //FIXME, add a boolean modifier to GroupAction and SubGroupAction if (strategy instanceof HierarchicalFillMenuStrategy) Collections.sort(contributions, ActionsComparator.instance()); IAction[] actions = contributions.toArray(new IAction[contributions.size()]); strategy.fillMenu(container, ActionSet.create(actions), 0, actions.length); contributions.clear(); } action.accept(this); IEntity result = getResult(); if (result == null) continue; IUpdatableAction updatableAction = (IUpdatableAction) result.wGetValue(); updatableAction.update(); if (updatableAction.isEnabled()) contributions.add(updatableAction); } //FIXME, add a sort boolean feature to GroupAction and SubGroupAction if (strategy instanceof HierarchicalFillMenuStrategy) Collections.sort(contributions, ActionsComparator.instance()); IAction[] actions = contributions.toArray(new IAction[contributions.size()]); strategy.fillMenu(container, ActionSet.create(actions), 0, actions.length); } @Override public void visit(GroupAction entity) { IItemContainer<IAction, ImageDescriptor> container = (IItemContainer<IAction, ImageDescriptor>) getBindings().wGetValue("itemContainer"); entity.getText().accept(this); String groupName = getResult().wStringValue(); IFillMenuStrategy strategy; FillStrategy fillStrategy = entity.getFillStrategy(); if (Matcher.match(Hierarchical, fillStrategy)) strategy = createFillMenuStrategy((Hierarchical) fillStrategy, groupName); else strategy = FlatFillMenuStrategy.instance(groupName); if (EntityUtils.hasParent(entity) && Matcher.match(SeparatedAction, entity.wGetParent())) container.addSeparator(groupName); else container.addGroupMarker(groupName); getBindings().wEnterScope(); getBindings().wDefValue("fillMenuStrategy", strategy); entity.getActions().accept(this); getBindings().wExitScope(); setResult(null); } @Override public void visit(SubgroupAction entity) { IItemContainer<IAction, ImageDescriptor> container = (IItemContainer<IAction, ImageDescriptor>) getBindings().wGetValue("itemContainer"); entity.getText().accept(this); String groupName = getResult().wStringValue(); IFillMenuStrategy strategy; FillStrategy fillStrategy = entity.getFillStrategy(); if (Matcher.match(Hierarchical, fillStrategy)) strategy = createFillMenuStrategy((Hierarchical) fillStrategy); else strategy = FlatFillMenuStrategy.instance(); IItemContainer<IAction, ImageDescriptor> subContainer = container.addIntoSubContainer(groupName, null); getBindings().wEnterScope(); getBindings().wDefValue("itemContainer", subContainer); getBindings().wDefValue("fillMenuStrategy", strategy); entity.getActions().accept(this); getBindings().wExitScope(); setResult(null); } private static class OpaqueEnablerPredicate implements IEnablerPredicate { private final IEntity value; public OpaqueEnablerPredicate(IEntity value) { this.value = value; } @Override public boolean evaluate(IEntityPart selectedPart, Object userdata) { throw new UnsupportedOperationException("cannot evaluate expression"); } } protected IAction createAction(Value kind, IEnablerPredicate enablerPredicate, IEntityTransformer transformer, IEntity prototype, String text) { //FIXME transformer always passed as null IEclipseContext context = (IEclipseContext) getBindings().wGetValue("context"); ActionFactory actionRegistry = new ActionFactory(context); QueriesEntityFactory qf = QueriesEntityFactory.instance; IEntity predicate = enablerPredicate instanceof OpaqueEnablerPredicate ? ((OpaqueEnablerPredicate) enablerPredicate).value : qf.createBooleanLiteral(true); switch (kind.getOrdinal()) { case ActionKindEnum.REPLACE_ord: return actionRegistry.createReplaceFragmentAction(text, predicate, prototype); case ActionKindEnum.INSERT_ord: return actionRegistry.createAddFragmentAction(text, predicate, prototype); case ActionKindEnum.WRAP_ord: IEntity behavior = qf.createPointwiseUpdate(qf.createVariableRefStep("focusEntity"), CommonsEntityAdapterFactory.createStageUpFragment(QueriesEntityDescriptorEnum.PathExpression, prototype)); return actionRegistry.createPerformAction(text, WRAP_ICON_URI, predicate, behavior); case ActionKindEnum.PERFORM_ord: return actionRegistry.createPerformAction(text, WRAP_ICON_URI, predicate, prototype); default: throw new IllegalArgumentException("not implemented yet"); } } private IFillMenuStrategy createFillMenuStrategy(Hierarchical hierarchicalStrategy) { return createFillMenuStrategy(hierarchicalStrategy, null); } private IFillMenuStrategy createFillMenuStrategy(Hierarchical hierarchicalStrategy, String groupName) { IMenuNameStrategy nameStrategy = Matcher.match(DistinctPrefix, hierarchicalStrategy.getNamingStrategy()) ? PrefixMenuNameStrategy.instance() : FullMenuNameStrategy.instance(); hierarchicalStrategy.getSplitSize().accept(this); int splitSize = getResult().wIntValue(); return new HierarchicalFillMenuStrategy(nameStrategy, splitSize, groupName); } private IEnablerPredicate createEnablerPredicate(IEntity predicate) { return new OpaqueEnablerPredicate(predicate); } }