/**
* Copyright (c) 2012-2016 Marsha Chechik, Alessio Di Sandro, Michalis Famelis,
* Rick Salay, Naama Ben-David.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Naama Ben-David - Initial implementation.
* Alessio Di Sandro - Refactoring and fixes.
*/
package edu.toronto.cs.se.mmint.mavo.diagram.outline.context;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import edu.toronto.cs.se.mavo.MAVOCollection;
import edu.toronto.cs.se.mavo.MAVODecision;
import edu.toronto.cs.se.mavo.MAVOElement;
import edu.toronto.cs.se.mavo.MAVORoot;
import edu.toronto.cs.se.mavo.MAVOPackage;
import edu.toronto.cs.se.mavo.MayDecision;
import edu.toronto.cs.se.mavo.SetDecision;
import edu.toronto.cs.se.mavo.VarDecision;
import edu.toronto.cs.se.mmint.mavo.diagram.context.MAVODiagramContextAddListener;
import edu.toronto.cs.se.mmint.mavo.diagram.context.MAVODiagramContextRefineListener;
import edu.toronto.cs.se.mmint.mavo.diagram.context.MAVODiagramContextRemoveListener;
import edu.toronto.cs.se.mmint.mid.diagram.library.MIDContextMenuListener;
public class MAVODiagramOutlineContextMenu extends ContributionItem {
private static final @NonNull String MAVO_OUTLINE_MENU_HIGHLIGHTDECISION_LABEL = "Highlight this decision in the diagram";
private static final @NonNull String MAVO_OUTLINE_MENU_HIGHLIGHTALTERNATIVE_LABEL = "Highlight this alternative in the diagram";
private static final @NonNull String MAVO_OUTLINE_MENU_HIGHLIGHTDOMAIN_LABEL = "Highlight this domain in the diagram";
private static final @NonNull String MAVO_OUTLINE_MENU_HIGHLIGHTENTITY_LABEL = "Highlight this entity in the diagram";
private static final @NonNull String MAVO_OUTLINE_MENU_HIGHLIGHTELEMENT_LABEL = "Highlight this element in the diagram";
private static final @NonNull String MAVO_OUTLINE_MENU_REFINEALTERNATIVE_LABEL = "Choose this alternative and refine";
private static final @NonNull String MAVO_OUTLINE_MENU_REFINEDOMAIN_LABEL = "Merge this domain and refine";
private static final @NonNull String MAVO_OUTLINE_MENU_REFINEMAYELEMENT_LABEL = "Choose this may element and refine";
private static final @NonNull String MAVO_OUTLINE_MENU_REFINEVAR_SUBMENU_INTO_LABEL = "Into";
private static final @NonNull String MAVO_OUTLINE_MENU_REFINEVAR_SUBMENU_INTONEW_LABEL = MAVO_OUTLINE_MENU_REFINEVAR_SUBMENU_INTO_LABEL + " a new object";
private static final @NonNull String MAVO_OUTLINE_MENU_REFINEVARELEMENTS_LABEL = "Merge these var elements and refine";
private static final @NonNull String MAVO_OUTLINE_MENU_ADDDECISION_LABEL = "Add new decision";
private static final @NonNull String MAVO_OUTLINE_MENU_ADDDECISION_SUBMENU_MAY_LABEL = "May";
private static final @NonNull String MAVO_OUTLINE_MENU_ADDDECISION_SUBMENU_VAR_LABEL = "Var";
private static final @NonNull String MAVO_OUTLINE_MENU_ADDDECISION_SUBMENU_SET_LABEL = "Set";
private static final @NonNull String MAVO_OUTLINE_MENU_ADDALTERNATIVE_LABEL = "Add new alternative";
private static final @NonNull String MAVO_OUTLINE_MENU_ADDDOMAIN_LABEL = "Add new domain";
private static final @NonNull String MAVO_OUTLINE_MENU_ADDENTITY_LABEL = "Add new entity";
private static final @NonNull String MAVO_OUTLINE_MENU_REMOVEDECISION_LABEL = "Remove this decision";
private static final @NonNull String MAVO_OUTLINE_MENU_REMOVEALTERNATIVE_LABEL = "Remove this alternative";
private static final @NonNull String MAVO_OUTLINE_MENU_REMOVEDOMAIN_LABEL = "Remove this domain";
private static final @NonNull String MAVO_OUTLINE_MENU_REMOVEENTITY_LABEL = "Remove this entity";
private static final @NonNull String MAVO_OUTLINE_MENU_REMOVEALTERNATIVEELEMENT_LABEL = "Remove this element from the alternative";
private static final @NonNull String MAVO_OUTLINE_MENU_REMOVEDOMAINELEMENT_LABEL = "Remove this element from the domain";
private static final @NonNull String MAVO_OUTLINE_MENU_REMOVEENTITYELEMENT_LABEL = "Remove this element from the entity";
private TreeViewer viewer;
public MAVODiagramOutlineContextMenu(TreeViewer viewer) {
this.viewer = viewer;
}
@Override
public boolean isDynamic() {
return true;
}
@Override
public void fill(Menu menu, int index) {
// check selection
IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
if (selection == null || selection.isEmpty() || !(selection instanceof TreeSelection)) {
return;
}
Object[] objects = ((TreeSelection) selection).toArray();
//TODO MMINT[MU-MMINT] Allow refine with multiple may model objects
if (objects.length > 1) {
MAVOCollection mavoCollection = null;
for (Object object : objects) {
if (!(object instanceof MAVOElement)) { // only model objects
return;
}
//TODO MMINT[MAVO] Check when same element is in two open paths (e.g. a may alternative and a var domain)
Object treeContainer = ((TreeSelection) selection).getPathsFor(object)[0].getParentPath().getLastSegment();
if (
!(treeContainer instanceof MAVOCollection) || // only in decisions
!(((MAVOCollection) treeContainer).eContainer() instanceof VarDecision) // only var decision
) {
return;
}
if (mavoCollection == null) {
mavoCollection = (MAVOCollection) treeContainer;
}
if (treeContainer != mavoCollection) { // only from the same var domain
return;
}
}
}
// create menus
Object object = objects[0];
if (object instanceof MAVORoot) {
MAVORoot mavoRootModelObj = (MAVORoot) object;
// add
Menu addMenu = addCascadeMenuItem(menu, MAVO_OUTLINE_MENU_ADDDECISION_LABEL);
addMenuItem(
addMenu,
MAVO_OUTLINE_MENU_ADDDECISION_SUBMENU_MAY_LABEL,
new MAVODiagramContextAddListener(MAVO_OUTLINE_MENU_ADDDECISION_LABEL + " " + MAVO_OUTLINE_MENU_ADDDECISION_SUBMENU_MAY_LABEL, mavoRootModelObj, MAVOPackage.eINSTANCE.getMayDecision())
);
addMenuItem(
addMenu,
MAVO_OUTLINE_MENU_ADDDECISION_SUBMENU_VAR_LABEL,
new MAVODiagramContextAddListener(MAVO_OUTLINE_MENU_ADDDECISION_LABEL + " " + MAVO_OUTLINE_MENU_ADDDECISION_SUBMENU_VAR_LABEL, mavoRootModelObj, MAVOPackage.eINSTANCE.getVarDecision())
);
addMenuItem(
addMenu,
MAVO_OUTLINE_MENU_ADDDECISION_SUBMENU_SET_LABEL,
new MAVODiagramContextAddListener(MAVO_OUTLINE_MENU_ADDDECISION_LABEL + " " + MAVO_OUTLINE_MENU_ADDDECISION_SUBMENU_SET_LABEL, mavoRootModelObj, MAVOPackage.eINSTANCE.getSetDecision())
);
}
else if (object instanceof MAVODecision) {
MAVODecision mavoDecision = (MAVODecision) object;
// highlight
addMenuItem(
menu,
MAVO_OUTLINE_MENU_HIGHLIGHTDECISION_LABEL,
new MAVODiagramOutlineContextHighlightListener(MAVO_OUTLINE_MENU_HIGHLIGHTDECISION_LABEL, mavoDecision)
);
// add
if (
mavoDecision instanceof MayDecision ||
(mavoDecision instanceof VarDecision && ((VarDecision) mavoDecision).getDomain() == null) ||
(mavoDecision instanceof SetDecision && ((SetDecision) mavoDecision).getEntity() == null)
) {
String addText = "";
if (mavoDecision instanceof MayDecision) {
addText = MAVO_OUTLINE_MENU_ADDALTERNATIVE_LABEL;
}
else if (mavoDecision instanceof VarDecision) {
addText = MAVO_OUTLINE_MENU_ADDDOMAIN_LABEL;
}
else if (mavoDecision instanceof SetDecision) {
addText = MAVO_OUTLINE_MENU_ADDENTITY_LABEL;
}
addMenuItem(
menu,
addText,
new MAVODiagramContextAddListener(addText, mavoDecision)
);
}
// remove
addMenuItem(
menu,
MAVO_OUTLINE_MENU_REMOVEDECISION_LABEL,
new MAVODiagramContextRemoveListener(MAVO_OUTLINE_MENU_REMOVEDECISION_LABEL, mavoDecision)
);
}
else if (object instanceof MAVOCollection) {
MAVOCollection mavoCollection = (MAVOCollection) object;
String highlightText = "", removeText = "";
if (mavoCollection.eContainer() instanceof MayDecision) {
highlightText = MAVO_OUTLINE_MENU_HIGHLIGHTALTERNATIVE_LABEL;
removeText = MAVO_OUTLINE_MENU_REMOVEALTERNATIVE_LABEL;
}
else if (mavoCollection.eContainer() instanceof VarDecision) {
highlightText = MAVO_OUTLINE_MENU_HIGHLIGHTDOMAIN_LABEL;
removeText = MAVO_OUTLINE_MENU_REMOVEDOMAIN_LABEL;
}
else if (mavoCollection.eContainer() instanceof SetDecision) {
highlightText = MAVO_OUTLINE_MENU_HIGHLIGHTENTITY_LABEL;
removeText = MAVO_OUTLINE_MENU_REMOVEENTITY_LABEL;
}
// highlight
addMenuItem(
menu,
highlightText,
new MAVODiagramOutlineContextHighlightListener(highlightText, mavoCollection)
);
// refine
if (mavoCollection.eContainer() instanceof MayDecision) {
addMenuItem(
menu,
MAVO_OUTLINE_MENU_REFINEALTERNATIVE_LABEL,
new MAVODiagramContextRefineListener(MAVO_OUTLINE_MENU_REFINEALTERNATIVE_LABEL, mavoCollection)
);
}
else if (mavoCollection.eContainer() instanceof VarDecision) {
//TODO MMINT[VAR-MMINT] Unify with var refine for mavo elements
Menu varRefineMenu = addCascadeMenuItem(menu, MAVO_OUTLINE_MENU_REFINEDOMAIN_LABEL);
for (MAVOElement varModelObj : mavoCollection.getMavoElements()) {
String mergeText = MAVO_OUTLINE_MENU_REFINEVAR_SUBMENU_INTO_LABEL + " " + varModelObj.getFormulaVariable();
addMenuItem(
varRefineMenu,
mergeText,
new MAVODiagramContextRefineListener(mergeText, mavoCollection, varModelObj, mavoCollection.getMavoElements())
);
}
addMenuItem(
varRefineMenu,
MAVO_OUTLINE_MENU_REFINEVAR_SUBMENU_INTONEW_LABEL,
new MAVODiagramContextRefineListener(MAVO_OUTLINE_MENU_REFINEVAR_SUBMENU_INTONEW_LABEL, mavoCollection, null, mavoCollection.getMavoElements())
);
}
// remove
addMenuItem(
menu,
removeText,
new MAVODiagramContextRemoveListener(removeText, mavoCollection)
);
}
else if (object instanceof MAVOElement) {
@SuppressWarnings("unchecked")
List<MAVOElement> mavoModelObjs = new ArrayList<MAVOElement>((List<? extends MAVOElement>) Arrays.asList(objects));
Object treeContainer = ((TreeSelection) selection).getPathsFor(mavoModelObjs.get(0))[0].getParentPath().getLastSegment();
// highlight
addMenuItem(
menu,
MAVO_OUTLINE_MENU_HIGHLIGHTELEMENT_LABEL,
new MAVODiagramOutlineContextHighlightListener(MAVO_OUTLINE_MENU_HIGHLIGHTELEMENT_LABEL, mavoModelObjs.get(0))
);
// refine
if (
!(treeContainer instanceof MAVOCollection) ||
((MAVOCollection) treeContainer).eContainer() instanceof MayDecision
) {
addMenuItem(
menu,
MAVO_OUTLINE_MENU_REFINEMAYELEMENT_LABEL,
new MAVODiagramContextRefineListener(MAVO_OUTLINE_MENU_REFINEMAYELEMENT_LABEL, mavoModelObjs)
);
}
/*TODO MMINT[VAR-MMINT]
* 1) Merge (x+y elements in domain):
* 1a) Select x elements, merge contents, remove x elements, remove V from x+y, remove decision
* 1abis) Clicking on the domain itself means y is empty
* 1ater) Clicking a single element doesn't allow merge
* 1b) Submenu to select where to merge, one of the x elements or a new one
* 1c) Apply same listener to outline context and diagram context
* 1d) Assign new formula id to the merge result if a new element is created
* 2) Check highlighting:
* 2a) of contained objects not in compartments
* 2b) of contained objects in compartments when var
* 2c) of compartments only (non-square)
* 3) Add to domain should be constrained by mergeable function
*/
else if (
(((MAVOCollection) treeContainer).eContainer() instanceof VarDecision) &&
(mavoModelObjs.size() > 1)
) {
Menu varRefineMenu = addCascadeMenuItem(menu, MAVO_OUTLINE_MENU_REFINEVARELEMENTS_LABEL);
MAVOCollection varDomain = (MAVOCollection) treeContainer;
for (MAVOElement varModelObj : mavoModelObjs) {
String mergeText = MAVO_OUTLINE_MENU_REFINEVAR_SUBMENU_INTO_LABEL + " " + varModelObj.getFormulaVariable();
addMenuItem(
varRefineMenu,
mergeText,
new MAVODiagramContextRefineListener(mergeText, varDomain, varModelObj, mavoModelObjs)
);
}
addMenuItem(
varRefineMenu,
MAVO_OUTLINE_MENU_REFINEVAR_SUBMENU_INTONEW_LABEL,
new MAVODiagramContextRefineListener(MAVO_OUTLINE_MENU_REFINEVAR_SUBMENU_INTONEW_LABEL, varDomain, null, mavoModelObjs)
);
}
// remove
if (treeContainer instanceof MAVOCollection) {
MAVOCollection mavoCollection = (MAVOCollection) treeContainer;
String removeText = "";
if (mavoCollection.eContainer() instanceof MayDecision) {
removeText = MAVO_OUTLINE_MENU_REMOVEALTERNATIVEELEMENT_LABEL;
}
else if (mavoCollection.eContainer() instanceof VarDecision) {
removeText = MAVO_OUTLINE_MENU_REMOVEDOMAINELEMENT_LABEL;
}
else if (mavoCollection.eContainer() instanceof SetDecision) {
removeText = MAVO_OUTLINE_MENU_REMOVEENTITYELEMENT_LABEL;
}
addMenuItem(
menu,
removeText,
new MAVODiagramContextRemoveListener(removeText, mavoCollection, mavoModelObjs)
);
}
}
}
//TODO MMINT[MISC] Move in some util class, use it everywhere
private @NonNull MenuItem addMenuItem(@NonNull Menu menu, @NonNull String menuItemText, @NonNull MIDContextMenuListener menuItemListener) {
MenuItem menuItem = new MenuItem(menu, SWT.NONE);
menuItem.setText(menuItemText);
menuItem.addSelectionListener(menuItemListener);
return menuItem;
}
//TODO MMINT[MISC] Move in some util class, use it everywhere
private @NonNull Menu addCascadeMenuItem(@NonNull Menu menu, @NonNull String menuItemText) {
MenuItem cascadeMenuItem = new MenuItem(menu, SWT.CASCADE);
cascadeMenuItem.setText(menuItemText);
Menu cascadeMenu = new Menu(menu);
cascadeMenuItem.setMenu(cascadeMenu);
return cascadeMenu;
}
}