/**
* 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.ui.menu;
import static org.whole.lang.e4.ui.actions.IE4UIConstants.SELECT_LANGUAGE_ICON_URI;
import static org.whole.lang.e4.ui.actions.IE4UIConstants.WRAP_ICON_URI;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.whole.lang.bindings.IBindingManager;
import org.whole.lang.e4.ui.actions.AbstractCompositeContributionItem;
import org.whole.lang.e4.ui.actions.IContextProvider;
import org.whole.lang.e4.ui.util.E4Utils;
import org.whole.lang.matchers.Matcher;
import org.whole.lang.model.IEntity;
import org.whole.lang.queries.factories.QueriesEntityFactory;
import org.whole.lang.reflect.EntityDescriptor;
import org.whole.lang.reflect.ILanguageKit;
import org.whole.lang.reflect.ReflectionFactory;
import org.whole.lang.resources.IResourceRegistry;
import org.whole.lang.ui.actions.EnablerPredicateFactory;
import org.whole.lang.ui.actions.IUpdatableAction;
import org.whole.lang.ui.editor.IGEFEditorKit;
import org.whole.lang.ui.enablerpredicate.AssignableToPredicate;
import org.whole.lang.ui.enablerpredicate.IEnablerPredicate;
import org.whole.lang.ui.menu.ActionContainer;
import org.whole.lang.ui.menu.ActionSet;
import org.whole.lang.ui.menu.FullMenuNameStrategy;
import org.whole.lang.ui.menu.HierarchicalFillMenuStrategy;
import org.whole.lang.ui.menu.IItemContainer;
import org.whole.lang.ui.menu.MenuManagerSet;
import org.whole.lang.util.DefaultWrapInTransformer;
import org.whole.lang.util.EntityUtils;
import org.whole.lang.util.IEntityTransformer;
import org.whole.lang.util.ResourceUtils;
import org.whole.lang.util.StringUtils;
/**
* @author Enrico Persiani
*/
public class EntityAssistCompositeContributionItem extends AbstractCompositeContributionItem {
protected ImageDescriptor languageIcon;
public EntityAssistCompositeContributionItem(IContextProvider contextProvider) {
super(contextProvider);
try {
this.languageIcon = ImageDescriptor.createFromURL(new URL(SELECT_LANGUAGE_ICON_URI));
} catch (MalformedURLException e) {
}
}
protected IContributionItem[] getItems() {
List<IContributionItem> items = new ArrayList<IContributionItem>();
Object selection = contextProvider.getContext().get(ESelectionService.class).getSelection();
if (!(selection instanceof IBindingManager))
return new IContributionItem[0];
else {
fillItems(MenuManagerListContainer.create(items), ActionListContainer.create(items), (IBindingManager) selection);
return items.toArray(new IContributionItem[items.size()]);
}
}
protected boolean fillItems(IItemContainer<MenuManager, ImageDescriptor> menuContainer, IItemContainer<IAction, ImageDescriptor> actionContainer, IBindingManager bm) {
IEntity focusEntity = bm.wGet("focusEntity");
IEntity targetEntity = getTargetEntity(focusEntity);
IEntity targetParent = targetEntity.wGetParent();
ILanguageKit targetLanguageKit = EntityUtils.isResolver(targetEntity) && !EntityUtils.isNull(targetParent) ?
targetParent.wGetLanguageKit() : targetEntity.wGetLanguageKit();
boolean hasExtendedActions = fillExtendedEntityAssistMenu(menuContainer, focusEntity, targetLanguageKit);
actionContainer.addSeparator();
boolean hasActions = fillEntityAssistMenu(actionContainer, focusEntity, targetLanguageKit);
return hasExtendedActions || hasActions;
}
protected boolean fillExtendedEntityAssistMenu(IItemContainer<MenuManager, ImageDescriptor> container, IEntity focusEntity, ILanguageKit targetLanguageKit) {
List<MenuManager> menus = new ArrayList<MenuManager>();
IResourceRegistry<ILanguageKit> registry = ReflectionFactory.getLanguageKitRegistry();
for (ILanguageKit languageKit : registry.getResources(false, ResourceUtils.SIMPLE_COMPARATOR)) {
if (languageKit.equals(targetLanguageKit))
continue;
String label = ResourceUtils.SIMPLE_NAME_PROVIDER.toString(registry, languageKit);
MenuManager languageMenu = new MenuManager(label, languageIcon, null);
if (fillEntityAssistMenu(ActionContainer.create(languageMenu), focusEntity, languageKit))
menus.add(languageMenu);
}
HierarchicalFillMenuStrategy.instance(FullMenuNameStrategy.instance())
.fillMenu(container,
MenuManagerSet.create(menus.toArray(new MenuManager[menus.size()])), 0, menus.size());
return menus.size() > 0;
}
protected boolean fillEntityAssistMenu(IItemContainer<IAction, ImageDescriptor> container, IEntity focusEntity, ILanguageKit lk) {
boolean hasActions = false;
final IEntity targetEntity = getTargetEntity(focusEntity).wGetAdaptee(false);
if (EntityUtils.isComposite(targetEntity)) {
List<IAction> addActions = new ArrayList<IAction>();
EntityDescriptor<?> componentEntityDescriptor = targetEntity.wGetEntityDescriptor(0);
for (EntityDescriptor<?> ed : lk.getEntityDescriptorEnum()
.getExtendedLanguageConcreteSubtypesOf(componentEntityDescriptor))
addActions.add(getAddEntityAction(ed));
Collections.sort(addActions, comparator);
HierarchicalFillMenuStrategy.instance().fillMenu(
container, ActionSet.create(addActions.toArray(new IAction[0])), 0, addActions.size());
hasActions |= addActions.size() > 0;
}
List<IAction> replaceElements = new ArrayList<IAction>();
EntityDescriptor<?> formalEntityDescriptor = EntityUtils.getFormalEntityDescriptor(targetEntity);
for (EntityDescriptor<?> ed : lk.getEntityDescriptorEnum()
.getExtendedLanguageConcreteSubtypesOf(formalEntityDescriptor))
if (!ed.equals(targetEntity.wGetEntityDescriptor()))
replaceElements.add(getReplaceEntityAction(ed));
container.addSeparator();
Collections.sort(replaceElements, comparator);
HierarchicalFillMenuStrategy.instance().fillMenu(
container, ActionSet.create(replaceElements.toArray(new IAction[0])), 0, replaceElements.size());
hasActions |= replaceElements.size() > 0;
List<IAction> wrapElements = createWrapActions(lk, targetEntity);
container.addSeparator();
Collections.sort(wrapElements, comparator);
HierarchicalFillMenuStrategy.instance().fillMenu(
container, ActionSet.create(wrapElements.toArray(new IAction[0])), 0, wrapElements.size());
hasActions |= wrapElements.size() > 0;
List<IAction> textElements = createTextActions(lk, targetEntity);
container.addSeparator();
Collections.sort(textElements, comparator);
HierarchicalFillMenuStrategy.instance().fillMenu(
container, ActionSet.create(textElements.toArray(new IAction[0])), 0, textElements.size());
hasActions |= textElements.size() > 0;
return hasActions;
}
protected IEntity getTargetEntity(IEntity focusEntity) {
return focusEntity;
}
protected IUpdatableAction getAddEntityAction(EntityDescriptor<?> ed) {
return contextProvider.getActionRegistry().getAddEntityAction(ed);
}
protected IUpdatableAction getReplaceEntityAction(EntityDescriptor<?> ed) {
return contextProvider.getActionRegistry().getReplaceEntityAction(ed);
}
protected List<IAction> createWrapActions(ILanguageKit lk, IEntity targetEntity) {
List<IAction> wrapActions = new ArrayList<IAction>();
Set<EntityDescriptor<?>> wrapTypes = new HashSet<EntityDescriptor<?>>();
IGEFEditorKit editorKit = (IGEFEditorKit) (targetEntity.wGetLanguageKit().equals(lk) ?
ReflectionFactory.getEditorKit(targetEntity) : lk.getDefaultEditorKit());
for (Object[] wrapAction : editorKit.getActionFactory().wrapActions()) {
EntityDescriptor<?> ed = (EntityDescriptor<?>) wrapAction[1];
if (isWrappable(targetEntity, ed, (IEnablerPredicate) wrapAction[0])) {
String label = (String) wrapAction[2];
IEntityTransformer transformer = (IEntityTransformer) wrapAction[3];
wrapActions.add(contextProvider.getActionRegistry().getActionFactory().createPerformAction(label, WRAP_ICON_URI,
QueriesEntityFactory.instance.createBooleanLiteral(true), getBehavior(ed, transformer)));
wrapTypes.add(ed);
}
}
for (EntityDescriptor<?> ed : lk.getEntityDescriptorEnum())
if (EntityUtils.isComposite(ed) && !wrapTypes.contains(ed) &&
isWrappable(targetEntity, ed, EnablerPredicateFactory.instance.assignableTo(ed.getEntityDescriptor(0)))) {
String label = StringUtils.camelCaseToSpacedWords(ed.getName());
wrapActions.add(contextProvider.getActionRegistry().getActionFactory().createPerformAction(label, WRAP_ICON_URI,
QueriesEntityFactory.instance.createBooleanLiteral(true), getBehavior(ed, DefaultWrapInTransformer.instance)));
}
return wrapActions;
}
protected boolean isWrappable(IEntity targetEntity, EntityDescriptor<?> ed, IEnablerPredicate predicate) {
return (predicate == EnablerPredicateFactory.instance.alwaysTrue() ||
((AssignableToPredicate) predicate).getEntityDescriptor()
.isPlatformSupertypeOf(targetEntity.wGetEntityDescriptor()) ) &&
EntityUtils.isReplaceable(targetEntity, ed);
}
protected IEntity getBehavior(EntityDescriptor<?> ed, IEntityTransformer transformer) {
return E4Utils.wrapToBehavior(ed, transformer);
}
protected List<IAction> createTextActions(ILanguageKit lk, IEntity targetEntity) {
List<IAction> textActions = new ArrayList<IAction>();
IGEFEditorKit editorKit = (IGEFEditorKit) (targetEntity.wGetLanguageKit().equals(lk) ?
ReflectionFactory.getEditorKit(targetEntity) : lk.getDefaultEditorKit());
for (Object[] textAction : E4Utils.textActionsFor(lk, ((IGEFEditorKit) editorKit).getActionFactory().textActions())) {
EntityDescriptor<?> ed = (EntityDescriptor<?>) textAction[1];
if (Matcher.matchImpl(ed, targetEntity)) {
@SuppressWarnings("unchecked")
Class<IUpdatableAction> actionClass = (Class<IUpdatableAction>) textAction[2];
try {
IUpdatableAction action = actionClass
.getConstructor(IEclipseContext.class)
.newInstance(contextProvider.getContext());
action.update();
if (action.isEnabled())
textActions.add(action);
} catch (Exception e) {
}
}
}
return textActions;
}
}