blob: c56d74249d54cab9b459022d07ec0a50b3b6b697 [file] [log] [blame]
package org.eclipse.gmf.examples.layers.subdiagrams.popup;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gmf.examples.layers.Layer;
import org.eclipse.gmf.examples.layers.LayerEnablement;
import org.eclipse.gmf.examples.layers.LayersFactory;
import org.eclipse.gmf.examples.layers.SubDiagramSpec;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.emf.type.core.commands.EditElementCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.IEditCommandRequest;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.ui.IWorkbenchPage;
public class SwitchLayerVisibilityAction extends DiagramAction {
protected static final String EMPTY_LAYER_NAME = "<empty-name>";
private final Layer myLayer;
private final SubDiagramSpec mySpec;
public SwitchLayerVisibilityAction(IWorkbenchPage workbenchPage, Layer layer, SubDiagramSpec spec) {
super(workbenchPage);
myLayer = layer;
mySpec = spec;
}
@Override
protected Request createTargetRequest() {
return null;
}
@Override
protected boolean isSelectionListener() {
return true;
}
@Override
protected Command getCommand() {
DiagramEditPart diagramEditPart = getDiagramEditPart();
if (diagramEditPart == null) {
return UnexecutableCommand.INSTANCE;
}
if (mySpec == null) {
return UnexecutableCommand.INSTANCE;
}
IEditCommandRequest request = new DomainOnlyEditRequest(diagramEditPart);
return new ICommandProxy(new SwitchLayerVisibility("Switching Layer Visibility", myLayer, mySpec, request));
}
@Override
public boolean isEnabled() {
return getDiagramEditPart() != null;
}
@Override
public void refresh() {
super.refresh();
setText(calculateText());
setChecked(calculateChecked());
}
protected String calculateText() {
String name = myLayer.getName();
return name != null ? name : EMPTY_LAYER_NAME;
}
protected boolean calculateChecked() {
LayerEnablement layerEnablement = mySpec.findLayerEnablement(myLayer);
//may be null, but only if disabled
return layerEnablement != null && layerEnablement.isVisible();
}
protected static class SwitchLayerVisibility extends EditElementCommand {
private final Layer myLayer;
private final SubDiagramSpec myDiagramSpec;
protected SwitchLayerVisibility(String label, Layer layer, SubDiagramSpec spec, IEditCommandRequest request) {
super(label, layer, request);
myLayer = layer;
myDiagramSpec = spec;
}
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
final NodesBag mappedNodes = mapDiagramNodes();
LayerEnablement enablement = myDiagramSpec.findLayerEnablement(myLayer);
if (enablement != null && enablement.isVisible()) {
enablement.setVisible(false);
final Map<EObject, List<LayerEnablement>> mappedLayers = mapLayers();
for (EObject nextParticipant : enablement.getLayer().getParticipants()) {
List<LayerEnablement> allLayers = mappedLayers.get(nextParticipant);
if (!hasVisibleLayerOtherThan(allLayers, enablement.getLayer())) {
mappedNodes.setAllNodesVisibleFor(nextParticipant, false);
}
}
} else {
if (enablement == null) {
enablement = LayersFactory.eINSTANCE.createLayerEnablement();
enablement.setLayer(myLayer);
myDiagramSpec.getDiagramLayers().add(enablement);
}
enablement.setVisible(true);
//if element is in at least one visible layer, it is visible for sure
for (EObject nextParticiant : myLayer.getParticipants()) {
mappedNodes.setAllNodesVisibleFor(nextParticiant, true);
}
}
return CommandResult.newOKCommandResult(enablement);
}
private static boolean hasVisibleLayerOtherThan(List<LayerEnablement> allLayers, Layer layer) {
if (allLayers == null) {
return false;
}
for (LayerEnablement next : allLayers) {
if (next.getLayer() == layer) {
continue;
}
if (next.isVisible()) {
return true;
}
}
return false;
}
private NodesBag mapDiagramNodes() {
NodesBag result = new NodesBag();
LinkedList<View> queue = new LinkedList<View>();
queue.add(myDiagramSpec.getDiagram());
while (!queue.isEmpty()) {
View next = queue.removeFirst();
if (next.isSetElement() && next instanceof Node) {
EObject element = next.getElement();
if (element != null) {
result.putOne(element, (Node) next);
}
}
@SuppressWarnings("unchecked")
List<View> children = next.getChildren();
queue.addAll(children);
}
return result;
}
private BagByEObject<LayerEnablement> mapLayers() {
BagByEObject<LayerEnablement> result = new BagByEObject<LayerEnablement>();
for (LayerEnablement next : myDiagramSpec.getDiagramLayers()) {
for (EObject participant : next.getLayer().getParticipants()) {
result.putOne(participant, next);
}
}
return result;
}
}
@SuppressWarnings("serial")
private static class BagByEObject<V> extends HashMap<EObject, List<V>> {
public void putOne(EObject key, V value) {
if (key == null) {
return;
}
List<V> values = get(key);
if (values == null) {
values = new ArrayList<V>();
put(key, values);
}
values.add(value);
}
}
@SuppressWarnings("serial")
private static class NodesBag extends BagByEObject<Node> {
public void setAllNodesVisibleFor(EObject object, boolean visible) {
List<Node> nodes = this.get(object);
if (nodes != null) {
for (Node nextNode : nodes) {
nextNode.setVisible(visible);
}
}
}
}
}