From ec8b5cfc0027bba5d6f988394f9d2668e24e9a5a Mon Sep 17 00:00:00 2001 From: Ansgar Radermacher Date: Tue, 10 May 2016 16:25:34 +0200 Subject: Bug 493334 - [State machine diagram] The first state within a composite state is badly placed Change-Id: I0e2f701e9294c8db576c6e74909a247d9292f867 --- ...RegionInCompositeStateCreateElementCommand.java | 59 +-- .../commands/CustomVertexCreateElementCommand.java | 174 --------- .../CustomStateCompartmentCreationEditPolicy.java | 103 ++---- .../policies/CustomStateCreationEditPolicy.java | 402 ++++++++++++--------- 4 files changed, 289 insertions(+), 449 deletions(-) delete mode 100644 plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/commands/CustomVertexCreateElementCommand.java (limited to 'plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram') diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/commands/CustomFirstRegionInCompositeStateCreateElementCommand.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/commands/CustomFirstRegionInCompositeStateCreateElementCommand.java index 0861749f8ff..753f44d9d21 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/commands/CustomFirstRegionInCompositeStateCreateElementCommand.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/commands/CustomFirstRegionInCompositeStateCreateElementCommand.java @@ -31,7 +31,7 @@ import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.NotationFactory; import org.eclipse.gmf.runtime.notation.View; -import org.eclipse.papyrus.uml.diagram.common.commands.SemanticAdapter; +import org.eclipse.papyrus.infra.gmfdiag.common.adapter.SemanticAdapter; import org.eclipse.papyrus.uml.diagram.statemachine.custom.helpers.Zone; import org.eclipse.papyrus.uml.diagram.statemachine.edit.parts.RegionEditPart; import org.eclipse.papyrus.uml.diagram.statemachine.edit.parts.StateCompartmentEditPart; @@ -44,8 +44,7 @@ import org.eclipse.uml2.uml.State; import org.eclipse.uml2.uml.UMLFactory; /** - * Create a region. - * TODO: Differences with generated RegionCreateCommand ? (is the latter used?) + * Create a region (UML and associated view) */ public class CustomFirstRegionInCompositeStateCreateElementCommand extends AbstractTransactionalCommand { IAdaptable adaptable; @@ -54,7 +53,12 @@ public class CustomFirstRegionInCompositeStateCreateElementCommand extends Abstr CreateViewRequest.ViewDescriptor viewDescriptor; CreateElementRequest createElementRequest; String dropLocation = Zone.NONE; - + + /** + * An existing UML region + */ + protected Region umlRegion; + public CustomFirstRegionInCompositeStateCreateElementCommand(IAdaptable adaptable, IAdaptable adaptableForDropped, PreferencesHint prefHints, TransactionalEditingDomain domain, String label, String dropLocation) { super(domain, label, null); this.adaptable = adaptable; @@ -65,8 +69,18 @@ public class CustomFirstRegionInCompositeStateCreateElementCommand extends Abstr // executing/undoing/redoing setResult(CommandResult.newOKCommandResult(viewDescriptor)); this.dropLocation = dropLocation; + umlRegion = null; } + /** + * Pass an existing (semantic) region. In this case, no new region is created during command + * execution, only the view is passed. + * @param umlRegion an existing semantic region + */ + public void useExistingRegion(Region umlRegion) { + this.umlRegion = umlRegion; + } + @Override public boolean canExecute() { View compartment = (View) adaptable.getAdapter(View.class); @@ -76,23 +90,7 @@ public class CustomFirstRegionInCompositeStateCreateElementCommand extends Abstr if (state.getSubmachine() == null) { return true; } - return false; } - // CHECK THIS - // else{ - // ENamedElement namedElement = PackageUtil.getElement("notation.View.visible"); - // if(ViewUtil.getStructuralFeatureValue(compartment, (EStructuralFeature)namedElement).equals(new Boolean(false))){ - // SetPropertyCommand showCompartment = new SetPropertyCommand(getEditingDomain(), adaptable, "notation.View.visible", "Visibility", true); - // showCompartment.setOptions(Collections.singletonMap(Transaction.OPTION_UNPROTECTED, Boolean.TRUE)); - // - // try { - // showCompartment.execute(null, null); - // } catch (ExecutionException e) { - // } - // - // } - // return false; - // } return false; } @@ -123,17 +121,21 @@ public class CustomFirstRegionInCompositeStateCreateElementCommand extends Abstr width = Zone.defaultWidth; Zone.setWidth(ownerView, width); } + if (adaptableForDropped == null) { - Region umlRegion = UMLFactory.eINSTANCE.createRegion(); - createElementRequest = new CreateElementRequest(getEditingDomain(), ownerView, UMLElementTypes.Region_Shape); - State umlState = (State) ownerView.getElement(); - umlState.getRegions().add(umlRegion); - ElementInitializers.getInstance().init_Region_Shape(umlRegion); - doConfigure(umlRegion, monitor, info); + if (umlRegion == null) { + umlRegion = UMLFactory.eINSTANCE.createRegion(); + createElementRequest = new CreateElementRequest(getEditingDomain(), ownerView, UMLElementTypes.Region_Shape); + State umlState = (State) ownerView.getElement(); + umlState.getRegions().add(umlRegion); + ElementInitializers.getInstance().init_Region_Shape(umlRegion); + doConfigure(umlRegion, monitor, info); + } adaptableForDropped = new SemanticAdapter(umlRegion, null); } // create a view for the new region on the stateMachineCompartment String semanticHint = ((IHintedType) UMLElementTypes.Region_Shape).getSemanticHint(); + View newRegion = ViewService.getInstance().createNode(adaptableForDropped, compartment, semanticHint, -1, prefHints); // add region specific annotation Zone.createRegionDefaultAnnotation(newRegion); @@ -171,6 +173,9 @@ public class CustomFirstRegionInCompositeStateCreateElementCommand extends Abstr } } viewDescriptor.setView(newRegion); - return CommandResult.newOKCommandResult(viewDescriptor); + // do not return the view descriptor. Otherwise, the region edit part is seen as result of composite commands that + // create a sub-vertex within the first region (see AspectUnspecifiedTypeCreationTool). In turn, the region instead + // of the new vertex is selected (implying no name edit prompt for the new vertex). + return CommandResult.newOKCommandResult(null); } } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/commands/CustomVertexCreateElementCommand.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/commands/CustomVertexCreateElementCommand.java deleted file mode 100644 index c848b3113fd..00000000000 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/commands/CustomVertexCreateElementCommand.java +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Copyright (c) 2014 CEA LIST. - * - * 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: - * CEA LIST - Initial API and implementation - */ -package org.eclipse.papyrus.uml.diagram.statemachine.custom.commands; - -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.emf.transaction.TransactionalEditingDomain; -import org.eclipse.gmf.runtime.common.core.command.CommandResult; -import org.eclipse.gmf.runtime.common.core.command.ICommand; -import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint; -import org.eclipse.gmf.runtime.diagram.core.services.ViewService; -import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest; -import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor; -import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; -import org.eclipse.gmf.runtime.emf.type.core.IElementType; -import org.eclipse.gmf.runtime.emf.type.core.IHintedType; -import org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest; -import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; -import org.eclipse.gmf.runtime.notation.View; -import org.eclipse.papyrus.uml.diagram.common.commands.SemanticAdapter; -import org.eclipse.papyrus.uml.diagram.statemachine.providers.ElementInitializers; -import org.eclipse.papyrus.uml.diagram.statemachine.providers.UMLElementTypes; -import org.eclipse.uml2.uml.FinalState; -import org.eclipse.uml2.uml.Pseudostate; -import org.eclipse.uml2.uml.Region; -import org.eclipse.uml2.uml.State; -import org.eclipse.uml2.uml.UMLFactory; -import org.eclipse.uml2.uml.Vertex; - -/** - * Create a vertex (sub-state), used only in composition with region creation - * in CustomStateCreationEditPolicy - * TODO: create a more cleaner combination of region creation and state creation that behaves exactly like the state - * creation. Current differences: there's no pop-up for editing its name, (2) positioning is always top-left. - * => use unchanged StateCreateCommand instead - */ -@Deprecated -public class CustomVertexCreateElementCommand extends AbstractTransactionalCommand { - - IAdaptable adaptable; - - PreferencesHint prefHints; - - IHintedType hint; - - CreateViewRequest.ViewDescriptor viewDescriptor; - - CreateElementRequest createElementRequest; - - public CustomVertexCreateElementCommand(IAdaptable adaptable, IHintedType hint, PreferencesHint prefHints, TransactionalEditingDomain domain, String label) { - super(domain, label, null); - this.adaptable = adaptable; - this.hint = hint; - this.prefHints = prefHints; - - viewDescriptor = new ViewDescriptor(adaptable, prefHints); - - // make sure the return object is available even before - // executing/undoing/redoing - setResult(CommandResult.newOKCommandResult(viewDescriptor)); - - } - - protected void doConfigure(Vertex newElement, IProgressMonitor monitor, IAdaptable info) throws ExecutionException { - IElementType elementType = createElementRequest.getElementType(); - ConfigureRequest configureRequest = new ConfigureRequest(getEditingDomain(), newElement, elementType); - configureRequest.setClientContext(createElementRequest.getClientContext()); - configureRequest.addParameters(createElementRequest.getParameters()); - ICommand configureCommand = elementType.getEditCommand(configureRequest); - if (configureCommand != null && configureCommand.canExecute()) { - configureCommand.execute(monitor, info); - } - } - - @Override - protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { - // adapt the view at execution time - View regionView = (View) adaptable.getAdapter(View.class); - View compartment = (View) regionView.getChildren().get(0); - // hack - viewDescriptor = new ViewDescriptor(new SemanticAdapter(null, adaptable.getAdapter(EObject.class)), prefHints); - - Region owner = (Region) regionView.getElement(); - Vertex newVertex = null; - if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.FinalState_Shape).getSemanticHint())) { - newVertex = UMLFactory.eINSTANCE.createFinalState(); - owner.getSubvertices().add(newVertex); - ElementInitializers.getInstance().init_FinalState_Shape((FinalState) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.FinalState_Shape); - } else if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.State_Shape).getSemanticHint())) { - newVertex = UMLFactory.eINSTANCE.createState(); - owner.getSubvertices().add(newVertex); - ElementInitializers.getInstance().init_State_Shape((State) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.State_Shape); - } else { - newVertex = UMLFactory.eINSTANCE.createPseudostate(); - if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_InitialShape).getSemanticHint())) { - owner.getSubvertices().add(newVertex); - ElementInitializers.getInstance().init_Pseudostate_InitialShape((Pseudostate) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.Pseudostate_InitialShape); - } else if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_JoinShape).getSemanticHint())) { - owner.getSubvertices().add(newVertex); - ElementInitializers.getInstance().init_Pseudostate_JoinShape((Pseudostate) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.Pseudostate_JoinShape); - } else if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_ForkShape).getSemanticHint())) { - owner.getSubvertices().add(newVertex); - ElementInitializers.getInstance().init_Pseudostate_ForkShape((Pseudostate) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.Pseudostate_ForkShape); - } else if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_ChoiceShape).getSemanticHint())) { - owner.getSubvertices().add(newVertex); - ElementInitializers.getInstance().init_Pseudostate_ChoiceShape((Pseudostate) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.Pseudostate_ChoiceShape); - } else if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_JunctionShape).getSemanticHint())) { - owner.getSubvertices().add(newVertex); - ElementInitializers.getInstance().init_Pseudostate_JunctionShape((Pseudostate) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.Pseudostate_JunctionShape); - } else if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_ShallowHistoryShape).getSemanticHint())) { - owner.getSubvertices().add(newVertex); - ElementInitializers.getInstance().init_Pseudostate_ShallowHistoryShape((Pseudostate) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.Pseudostate_ShallowHistoryShape); - } else if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_DeepHistoryShape).getSemanticHint())) { - owner.getSubvertices().add(newVertex); - ElementInitializers.getInstance().init_Pseudostate_DeepHistoryShape((Pseudostate) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.Pseudostate_DeepHistoryShape); - } else if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_TerminateShape).getSemanticHint())) { - owner.getSubvertices().add(newVertex); - ElementInitializers.getInstance().init_Pseudostate_TerminateShape((Pseudostate) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.Pseudostate_TerminateShape); - } else if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_EntryPointShape).getSemanticHint())) { - ((State) owner.eContainer()).getConnectionPoints().add((Pseudostate) newVertex); - ElementInitializers.getInstance().init_Pseudostate_EntryPointShape((Pseudostate) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.Pseudostate_EntryPointShape); - } else if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_ExitPointShape).getSemanticHint())) { - ((State) owner.eContainer()).getConnectionPoints().add((Pseudostate) newVertex); - ElementInitializers.getInstance().init_Pseudostate_ExitPointShape((Pseudostate) newVertex); - createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.Pseudostate_ExitPointShape); - } - } - - doConfigure(newVertex, monitor, info); - - // create a view for the new vertex on the regionCompartment - IAdaptable newVertexAdapatable = new SemanticAdapter(newVertex, null); - - // see below - // View newVertexView; - - if (hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_EntryPointShape).getSemanticHint()) || hint.getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_ExitPointShape).getSemanticHint())) { - // newVertexView = - ViewService.getInstance().createNode(newVertexAdapatable, (View) regionView.eContainer().eContainer(), hint.getSemanticHint(), -1, prefHints); - } else { - // newVertexView = - ViewService.getInstance().createNode(newVertexAdapatable, compartment, hint.getSemanticHint(), -1, prefHints); - - } - // removed viewDescriptor.setView: problematic since region can be moved along with state immediately after creation along with state - // can cause bug 397730 - // viewDescriptor.setView(newVertexView); - - return CommandResult.newOKCommandResult(viewDescriptor); - } - -} diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/policies/CustomStateCompartmentCreationEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/policies/CustomStateCompartmentCreationEditPolicy.java index bb981fdf99f..cb29572f94a 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/policies/CustomStateCompartmentCreationEditPolicy.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/policies/CustomStateCompartmentCreationEditPolicy.java @@ -31,6 +31,7 @@ import org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy; import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateUnspecifiedTypeRequest; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest; +import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor; import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest; import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.emf.type.core.IElementType; @@ -51,17 +52,33 @@ public class CustomStateCompartmentCreationEditPolicy extends CreationEditPolicy @Override public Command getCommand(Request request) { - // CHECK THIS TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()).getEditingDomain(); CompositeTransactionalCommand cc = new CompositeTransactionalCommand(editingDomain, DiagramUIMessages.AddCommand_Label); if (understandsRequest(request)) { - if (request instanceof CreateUnspecifiedTypeRequest) { + if (request instanceof CreateViewRequest) { + // used by popup-bar assistant + CreateViewRequest createViewRequest = (CreateViewRequest) request; + for (ViewDescriptor vd : createViewRequest.getViewDescriptors()) { + if (vd.getSemanticHint().equals(((IHintedType) UMLElementTypes.Region_Shape).getSemanticHint())) { + // starting point is the state compartment on which mouse was moving + View stateCompartmentView = (View) getHost().getModel(); + // get and adaptable for it, to pass on to commands + IAdaptable adaptableForStateCompartmentView = new SemanticAdapter(null, stateCompartmentView); + // do the whole job + CustomFirstRegionInCompositeStateCreateElementCommand createNewRegion = new CustomFirstRegionInCompositeStateCreateElementCommand(adaptableForStateCompartmentView, null, ((IGraphicalEditPart) getHost()).getDiagramPreferencesHint(), + editingDomain, DiagramUIMessages.CreateCommand_Label, dropLocation); + cc.compose(createNewRegion); + return new ICommandProxy(cc.reduce()); + } + } + } + else if (request instanceof CreateUnspecifiedTypeRequest) { + // used by palette CreateUnspecifiedTypeRequest unspecReq = (CreateUnspecifiedTypeRequest) request; for (Iterator iter = unspecReq.getElementTypes().iterator(); iter.hasNext();) { IElementType elementType = (IElementType) iter.next(); if (((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Region_Shape).getSemanticHint())) { - // starting point is the state compartment on - // which mouse was moving + // starting point is the state compartment on which mouse was moving View stateCompartmentView = (View) getHost().getModel(); // get and adaptable for it, to pass on to commands IAdaptable adaptableForStateCompartmentView = new SemanticAdapter(null, stateCompartmentView); @@ -160,82 +177,4 @@ public class CustomStateCompartmentCreationEditPolicy extends CreationEditPolicy } return super.getTargetEditPart(request); } - // @Override - // public void eraseTargetFeedback(Request request) { - // if(sizeOnDropFeedback != null) { - // LayerManager.Helper.find(getHost()).getLayer(LayerConstants.FEEDBACK_LAYER).remove(sizeOnDropFeedback); - // sizeOnDropFeedback = null; - // } - // } - // protected IFigure getSizeOnDropFeedback() { - // if(sizeOnDropFeedback == null) { - // sizeOnDropFeedback = new RectangleFigure(); - // FigureUtilities.makeGhostShape((Shape)sizeOnDropFeedback); - // ((Shape)sizeOnDropFeedback).setLineStyle(Graphics.LINE_DASHDOT); - // sizeOnDropFeedback.setForegroundColor(ColorConstants.white); - // LayerManager.Helper.find(getHost()).getLayer(LayerConstants.FEEDBACK_LAYER).add(sizeOnDropFeedback); - // } - // return sizeOnDropFeedback; - // } - // @Override - // public EditPart getTargetEditPart(Request request) { - // - // if(request instanceof CreateUnspecifiedTypeRequest) { - // CreateUnspecifiedTypeRequest createUnspecifiedTypeRequest = (CreateUnspecifiedTypeRequest)request; - // - // if(understandsRequest(request)) { - // List elementTypes = createUnspecifiedTypeRequest.getElementTypes(); - // // Treat the case where only one element type is listed - // // Only take EntryPoint or ExitPoint element type into account - // if((elementTypes.size() == 1) && (((IElementType)(elementTypes.get(0)) == UMLElementTypes.Pseudostate_EntryPointShape) || ((IElementType)(elementTypes.get(0)) == UMLElementTypes.Pseudostate_ExitPointShape))) { - // // If the target is a compartment replace by its grand parent edit part - // if((getHost() instanceof ShapeCompartmentEditPart)) { - // return getHost().getParent().getParent().getParent(); - // } - // } - // } - // } - // - // return super.getTargetEditPart(request); - // } - // - // @Override - // public void showTargetFeedback(Request request) { - // if(request instanceof CreateUnspecifiedTypeRequest) { - // CreateUnspecifiedTypeRequest unspecReq = (CreateUnspecifiedTypeRequest)request; - // for(Iterator iter = unspecReq.getElementTypes().iterator(); iter.hasNext();) { - // IElementType elementType = (IElementType)iter.next(); - // if(elementType.equals(UMLElementTypes.Region_Shape)) { - // RegionFigure targetFig = ((RegionEditPart)getHost().getParent()).getPrimaryShape(); - // - // // make a local copy - // Rectangle targetFigBounds = targetFig.getBounds().getCopy(); - // // transform the coordinates to absolute - // targetFig.translateToAbsolute(targetFigBounds); - // // retrieve mouse location - // Point mouseLocation = unspecReq.getLocation(); - // - // // get the drop location, i.e. RIGHT, LEFT, TOP, BOTTOM - // dropLocation = Zone.getZoneFromLocationInRectangleWithAbsoluteCoordinates(mouseLocation, targetFigBounds); - // - // // perform corresponding change (scaling, translation) on - // // targetFigBounds - // // and updates the graph node drop location property - // if(Zone.isTop(dropLocation)) { - // targetFigBounds.setSize(targetFigBounds.getSize().scale(1.0, 0.5)); - // } else if(Zone.isLeft(dropLocation)) { - // targetFigBounds.setSize(targetFigBounds.getSize().scale(0.5, 1.0)); - // } else if(Zone.isRight(dropLocation)) { - // targetFigBounds.setSize(targetFigBounds.getSize().scale(0.5, 1.0)); - // targetFigBounds.translate(targetFigBounds.width, 0); - // } else if(Zone.isBottom(dropLocation)) { - // targetFigBounds.setSize(targetFigBounds.getSize().scale(1.0, 0.5)); - // targetFigBounds.translate(0, targetFigBounds.height); - // } - // - // getSizeOnDropFeedback().setBounds(new PrecisionRectangle(targetFigBounds)); - // } - // } - // } - // } } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/policies/CustomStateCreationEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/policies/CustomStateCreationEditPolicy.java index 8304a219f7b..b9159f4bc66 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/policies/CustomStateCreationEditPolicy.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.statemachine/custom-src/org/eclipse/papyrus/uml/diagram/statemachine/custom/policies/CustomStateCreationEditPolicy.java @@ -12,142 +12,117 @@ package org.eclipse.papyrus.uml.diagram.statemachine.custom.policies; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.draw2d.IFigure; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.draw2d.geometry.Point; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.Request; import org.eclipse.gef.commands.Command; import org.eclipse.gef.requests.ChangeBoundsRequest; +import org.eclipse.gef.requests.CreateRequest; +import org.eclipse.gmf.runtime.common.core.command.CommandResult; +import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.diagram.core.commands.SetPropertyCommand; +import org.eclipse.gmf.runtime.diagram.core.services.ViewService; import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; +import org.eclipse.gmf.runtime.diagram.ui.commands.SetBoundsCommand; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateUnspecifiedTypeRequest; +import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest; +import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor; import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest; +import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.emf.type.core.IElementType; import org.eclipse.gmf.runtime.emf.type.core.IHintedType; +import org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; +import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.View; -import org.eclipse.papyrus.uml.diagram.common.commands.SemanticAdapter; +import org.eclipse.papyrus.infra.gmfdiag.common.commands.SemanticAdapter; import org.eclipse.papyrus.uml.diagram.common.editpolicies.SideAffixedNodesCreationEditPolicy; import org.eclipse.papyrus.uml.diagram.statemachine.custom.commands.CustomFirstRegionInCompositeStateCreateElementCommand; -import org.eclipse.papyrus.uml.diagram.statemachine.custom.commands.CustomVertexCreateElementCommand; import org.eclipse.papyrus.uml.diagram.statemachine.custom.edit.part.CustomStateEditPart; import org.eclipse.papyrus.uml.diagram.statemachine.custom.helpers.Zone; import org.eclipse.papyrus.uml.diagram.statemachine.edit.parts.RegionEditPart; import org.eclipse.papyrus.uml.diagram.statemachine.edit.parts.StateCompartmentEditPart; import org.eclipse.papyrus.uml.diagram.statemachine.providers.UMLElementTypes; +import org.eclipse.uml2.uml.Region; import org.eclipse.uml2.uml.State; +import org.eclipse.uml2.uml.UMLFactory; +import org.eclipse.uml2.uml.Vertex; public class CustomStateCreationEditPolicy extends SideAffixedNodesCreationEditPolicy { - IFigure sizeOnDropFeedback = null; - String dropLocation = Zone.NONE; - - // @Override - // public void eraseTargetFeedback(Request request) { - // if(sizeOnDropFeedback != null) { - // LayerManager.Helper.find(getHost()).getLayer(LayerConstants.FEEDBACK_LAYER).remove(sizeOnDropFeedback); - // sizeOnDropFeedback = null; - // } - // } + + /** + * constants for changing the visibility attribute of a view + */ + public static final String NOTATION_VIEW_VISIBLE = "notation.View.visible"; //$NON-NLS-1$ + public static final String VISIBILITY = "Visibility"; //$NON-NLS-1$ + + /** + * Default location for new vertex, if called from popup-bar + */ + public final static Rectangle defaultLocation = new Rectangle(20, 20, -1, -1); + + /** + * No specific ZONE + */ + public final static String dropLocation = Zone.NONE; + + /** + * Vertical offset for region compartment within composite state (cannot be calculated from host figure, since + * the region compartment has not been created when the position calculation is done. + */ + public final static int REGION_OFFSET = 20; + @Override public Command getCommand(Request request) { - TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()).getEditingDomain(); - CompositeTransactionalCommand cc = new CompositeTransactionalCommand(editingDomain, DiagramUIMessages.AddCommand_Label); if (understandsRequest(request)) { - if (request instanceof CreateUnspecifiedTypeRequest) { + if (request instanceof CreateViewRequest) { + // used by popup-bar assistant + CreateViewRequest createViewRequest = (CreateViewRequest) request; + for (ViewDescriptor vd : createViewRequest.getViewDescriptors()) { + Command cmd = getCustomCreateCommand(request, null, vd.getSemanticHint()); + if (cmd != null) { + return cmd; + } + } + } + else if (request instanceof CreateUnspecifiedTypeRequest) { + // used by palette CreateUnspecifiedTypeRequest unspecReq = (CreateUnspecifiedTypeRequest) request; - for (Iterator iter = unspecReq.getElementTypes().iterator(); iter.hasNext();) { - IElementType elementType = (IElementType) iter.next(); - if (((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Region_Shape).getSemanticHint())) { - // starting point is the state node on - // which mouse was moving - View stateView = (View) getHost().getModel(); - View stateCompartmentView = CustomStateEditPart.getStateCompartmentView(stateView); - - // get and adaptable for it, to pass on to commands - IAdaptable adaptableForStateCompartmentView = new SemanticAdapter(null, stateCompartmentView); - if (!stateCompartmentView.getChildren().isEmpty()) { - // CHECK THIS - // ENamedElement namedElement = PackageUtil.getElement("notation.View.visible"); - // if(ViewUtil.getStructuralFeatureValue(stateCompartmentView, (EStructuralFeature)namedElement).equals(new Boolean(false))){ - // SetPropertyCommand showCompartment = new SetPropertyCommand(editingDomain, adaptableForStateCompartmentView, "notation.View.visible", "Visibility", true); - // showCompartment.setOptions(Collections.singletonMap(Transaction.OPTION_UNPROTECTED, Boolean.TRUE)); - // - // try { - // showCompartment.execute(null, null); - // } catch (ExecutionException e) { - // } - // } - return null; - } - // do the whole job - CustomFirstRegionInCompositeStateCreateElementCommand createNewRegion = new CustomFirstRegionInCompositeStateCreateElementCommand(adaptableForStateCompartmentView, null, ((IGraphicalEditPart) getHost()).getDiagramPreferencesHint(), - editingDomain, DiagramUIMessages.CreateCommand_Label, dropLocation); - SetPropertyCommand showCompartment = new SetPropertyCommand(editingDomain, adaptableForStateCompartmentView, "notation.View.visible", "Visibility", true); - cc.compose(showCompartment); - cc.compose(createNewRegion); - return new ICommandProxy(cc.reduce()); - } else if (((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_InitialShape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_JoinShape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_ForkShape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_ChoiceShape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_JunctionShape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_ShallowHistoryShape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_DeepHistoryShape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_TerminateShape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_EntryPointShape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.Pseudostate_ExitPointShape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.State_Shape).getSemanticHint()) - || ((IHintedType) elementType).getSemanticHint().equals(((IHintedType) UMLElementTypes.FinalState_Shape).getSemanticHint())) { - // starting point is the state node on - // which mouse was moving - View stateView = (View) getHost().getModel(); - /* - * TO Check from last version - * - * View stateCompartmentView = (View)stateView.getChildren().get(1); - */ - View stateCompartmentView = ViewUtil.getChildBySemanticHint(stateView, String.valueOf(StateCompartmentEditPart.VISUAL_ID)); - // transfer the request to the super method to deal with regular Entry/ExitPoint creation - if (!stateCompartmentView.getChildren().isEmpty() || !((State) stateView.getElement()).getRegions().isEmpty()) { - return super.getCommand(request); - } - // get and adaptable for it, to pass on to commands - IAdaptable adaptableForStateCompartmentView = new SemanticAdapter(null, stateCompartmentView); - // do the whole job - CustomFirstRegionInCompositeStateCreateElementCommand createNewRegion = new CustomFirstRegionInCompositeStateCreateElementCommand(adaptableForStateCompartmentView, null, ((IGraphicalEditPart) getHost()).getDiagramPreferencesHint(), - editingDomain, DiagramUIMessages.CreateCommand_Label, dropLocation); - SetPropertyCommand showCompartment = new SetPropertyCommand(editingDomain, adaptableForStateCompartmentView, "notation.View.visible", "Visibility", true); - CustomVertexCreateElementCommand createVertex = new CustomVertexCreateElementCommand((IAdaptable) createNewRegion.getCommandResult().getReturnValue(), (IHintedType) elementType, - ((IGraphicalEditPart) getHost()).getDiagramPreferencesHint(), editingDomain, DiagramUIMessages.CreateCommand_Label); - cc.compose(showCompartment); - cc.compose(createNewRegion); - cc.compose(createVertex); - return new ICommandProxy(cc.reduce()); + for (Object elementTypeObj : unspecReq.getElementTypes()) { + IElementType elementType = (IElementType) elementTypeObj; + + CreateRequest createRequest = unspecReq.getRequestForType(elementType); + Command cmd = getCustomCreateCommand(request, createRequest, ((IHintedType) elementType).getSemanticHint()); + if (cmd != null) { + return cmd; } } - } else if (request instanceof ChangeBoundsRequest) { + } + else if (request instanceof ChangeBoundsRequest) { ChangeBoundsRequest changeBoundsRequest = (ChangeBoundsRequest) request; Point mouseLocation = changeBoundsRequest.getLocation(); DropObjectsRequest dropRequest = new DropObjectsRequest(); dropRequest.setLocation(mouseLocation); List list = new ArrayList(); - Iterator it = changeBoundsRequest.getEditParts().iterator(); - while (it.hasNext()) { - Object next = it.next(); - if (next instanceof EditPart) { - EditPart ep = (EditPart) next; - if (ep instanceof RegionEditPart) { - View regionToDrag = (View) ep.getModel(); - list.add(regionToDrag); - } + for (Object epObj : changeBoundsRequest.getEditParts()) { + if (epObj instanceof RegionEditPart) { + EditPart ep = (EditPart) epObj; + View regionToDrag = (View) ep.getModel(); + list.add(regionToDrag); } } dropRequest.setObjects(list); @@ -157,75 +132,170 @@ public class CustomStateCreationEditPolicy extends SideAffixedNodesCreationEditP } return null; } - // protected IFigure getSizeOnDropFeedback() { - // if(sizeOnDropFeedback == null) { - // sizeOnDropFeedback = new RectangleFigure(); - // FigureUtilities.makeGhostShape((Shape)sizeOnDropFeedback); - // ((Shape)sizeOnDropFeedback).setLineStyle(Graphics.LINE_DASHDOT); - // sizeOnDropFeedback.setForegroundColor(ColorConstants.white); - // LayerManager.Helper.find(getHost()).getLayer(LayerConstants.FEEDBACK_LAYER).add(sizeOnDropFeedback); - // } - // return sizeOnDropFeedback; - // } - // @Override - // public EditPart getTargetEditPart(Request request) { - // - // if(request instanceof CreateUnspecifiedTypeRequest) { - // CreateUnspecifiedTypeRequest createUnspecifiedTypeRequest = (CreateUnspecifiedTypeRequest)request; - // - // if(understandsRequest(request)) { - // List elementTypes = createUnspecifiedTypeRequest.getElementTypes(); - // // Treat the case where only one element type is listed - // // Only take EntryPoint or ExitPoint element type into account - // if((elementTypes.size() == 1) && (((IElementType)(elementTypes.get(0)) == UMLElementTypes.Pseudostate_EntryPointShape) || ((IElementType)(elementTypes.get(0)) == UMLElementTypes.Pseudostate_ExitPointShape))) { - // // If the target is a compartment replace by its grand parent edit part - // if((getHost() instanceof ShapeCompartmentEditPart)) { - // return getHost().getParent().getParent().getParent(); - // } - // } - // } - // } - // - // return super.getTargetEditPart(request); - // } - // - // @Override - // public void showTargetFeedback(Request request) { - // if(request instanceof CreateUnspecifiedTypeRequest) { - // CreateUnspecifiedTypeRequest unspecReq = (CreateUnspecifiedTypeRequest)request; - // for(Iterator iter = unspecReq.getElementTypes().iterator(); iter.hasNext();) { - // IElementType elementType = (IElementType)iter.next(); - // if(elementType.equals(UMLElementTypes.Region_Shape)) { - // RegionFigure targetFig = ((RegionEditPart)getHost().getParent()).getPrimaryShape(); - // - // // make a local copy - // Rectangle targetFigBounds = targetFig.getBounds().getCopy(); - // // transform the coordinates to absolute - // targetFig.translateToAbsolute(targetFigBounds); - // // retrieve mouse location - // Point mouseLocation = unspecReq.getLocation(); - // - // // get the drop location, i.e. RIGHT, LEFT, TOP, BOTTOM - // dropLocation = Zone.getZoneFromLocationInRectangleWithAbsoluteCoordinates(mouseLocation, targetFigBounds); - // - // // perform corresponding change (scaling, translation) on - // // targetFigBounds - // // and updates the graph node drop location property - // if(Zone.isTop(dropLocation)) { - // targetFigBounds.setSize(targetFigBounds.getSize().scale(1.0, 0.5)); - // } else if(Zone.isLeft(dropLocation)) { - // targetFigBounds.setSize(targetFigBounds.getSize().scale(0.5, 1.0)); - // } else if(Zone.isRight(dropLocation)) { - // targetFigBounds.setSize(targetFigBounds.getSize().scale(0.5, 1.0)); - // targetFigBounds.translate(targetFigBounds.width, 0); - // } else if(Zone.isBottom(dropLocation)) { - // targetFigBounds.setSize(targetFigBounds.getSize().scale(1.0, 0.5)); - // targetFigBounds.translate(0, targetFigBounds.height); - // } - // - // getSizeOnDropFeedback().setBounds(new PrecisionRectangle(targetFigBounds)); - // } - // } - // } - // } + + /** + * Create a vertex (sub-state) within the region that is retrieved from the passed adaptable during + * execution. This command is used in the context that the region has not been created yet, i.e. when + * the first addition of a vertex implies creating the region first. This requires the use of the + * adaptable and does not allow the use of the standard creation commands. + * This command is used only in composition with region creation in CustomStateCreationEditPolicy + */ + public class CustomVertexCreateElementCommand extends AbstractTransactionalCommand { + + IAdaptable adaptable; + + CreateViewRequest.ViewDescriptor viewDescriptor; + + CreateElementRequest createElementRequest; + + public CustomVertexCreateElementCommand(TransactionalEditingDomain domain, ViewDescriptor viewDescriptor, IAdaptable adaptable, String label) { + super(domain, label, null); + this.adaptable = adaptable; + this.viewDescriptor = viewDescriptor; + // make sure the return object is available even before executing/undoing/redoing + setResult(CommandResult.newOKCommandResult(viewDescriptor)); + + } + + protected void doConfigure(Vertex newElement, IProgressMonitor monitor, IAdaptable info, View regionView) throws ExecutionException { + + String semanticHint = viewDescriptor.getSemanticHint(); + createElementRequest = new CreateElementRequest(getEditingDomain(), regionView, UMLElementTypes.getElementType(semanticHint)); + + IElementType elementType = createElementRequest.getElementType(); + ConfigureRequest configureRequest = new ConfigureRequest(getEditingDomain(), newElement, elementType); + configureRequest.setClientContext(createElementRequest.getClientContext()); + configureRequest.addParameters(createElementRequest.getParameters()); + ICommand configureCommand = elementType.getEditCommand(configureRequest); + if (configureCommand != null && configureCommand.canExecute()) { + configureCommand.execute(monitor, info); + } + } + + @Override + protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { + // adapt the view at execution time + View regionView = (View) adaptable.getAdapter(View.class); + View compartment = (View) regionView.getChildren().get(0); + + IElementType elementType = UMLElementTypes.getElementType(viewDescriptor.getSemanticHint()); + Vertex newVertex = (Vertex) + UMLFactory.eINSTANCE.create((EClass) UMLElementTypes.getElement(elementType)); + + Region region = (Region) regionView.getElement(); + region.getSubvertices().add(newVertex); + + doConfigure(newVertex, monitor, info, regionView); + + View view = + ViewService.getInstance().createView( + viewDescriptor.getViewKind(), + new SemanticAdapter(newVertex, null), + compartment, + viewDescriptor.getSemanticHint(), + viewDescriptor.getIndex(), + viewDescriptor.isPersisted(), + viewDescriptor.getPreferencesHint()); + Assert.isNotNull(view, "failed to create a view"); //$NON-NLS-1$ + viewDescriptor.setView(view); + + return CommandResult.newOKCommandResult(viewDescriptor); + } + } + + public Command getCustomCreateCommand(Request request, CreateRequest createReq, String semanticHint) { + TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()).getEditingDomain(); + CompositeTransactionalCommand cc = new CompositeTransactionalCommand(editingDomain, DiagramUIMessages.AddCommand_Label); + + if (semanticHint.equals(((IHintedType) UMLElementTypes.Region_Shape).getSemanticHint())) { + + // starting point is the state node on which mouse was moving + View stateView = (View) getHost().getModel(); + View stateCompartmentView = CustomStateEditPart.getStateCompartmentView(stateView); + + // get and adaptable for it, to pass on to commands + IAdaptable adaptableForStateCompartmentView = new SemanticAdapter(null, stateCompartmentView); + + // do the whole job + CustomFirstRegionInCompositeStateCreateElementCommand createNewRegion = new CustomFirstRegionInCompositeStateCreateElementCommand(adaptableForStateCompartmentView, null, ((IGraphicalEditPart) getHost()).getDiagramPreferencesHint(), + editingDomain, DiagramUIMessages.CreateCommand_Label, dropLocation); + SetPropertyCommand showCompartment = new SetPropertyCommand(editingDomain, adaptableForStateCompartmentView, NOTATION_VIEW_VISIBLE, VISIBILITY, true); + cc.compose(showCompartment); + cc.compose(createNewRegion); + return new ICommandProxy(cc.reduce()); + } + else if (semanticHint.equals(((IHintedType) UMLElementTypes.Pseudostate_InitialShape).getSemanticHint()) + || semanticHint.equals(((IHintedType) UMLElementTypes.Pseudostate_JoinShape).getSemanticHint()) + || semanticHint.equals(((IHintedType) UMLElementTypes.Pseudostate_ForkShape).getSemanticHint()) + || semanticHint.equals(((IHintedType) UMLElementTypes.Pseudostate_ChoiceShape).getSemanticHint()) + || semanticHint.equals(((IHintedType) UMLElementTypes.Pseudostate_JunctionShape).getSemanticHint()) + || semanticHint.equals(((IHintedType) UMLElementTypes.Pseudostate_ShallowHistoryShape).getSemanticHint()) + || semanticHint.equals(((IHintedType) UMLElementTypes.Pseudostate_DeepHistoryShape).getSemanticHint()) + || semanticHint.equals(((IHintedType) UMLElementTypes.Pseudostate_TerminateShape).getSemanticHint()) + || semanticHint.equals(((IHintedType) UMLElementTypes.State_Shape).getSemanticHint()) + || semanticHint.equals(((IHintedType) UMLElementTypes.FinalState_Shape).getSemanticHint())) { + + // starting point is the state node on which mouse was moving + View stateView = (View) getHost().getModel(); + + View stateCompartmentView = ViewUtil.getChildBySemanticHint(stateView, String.valueOf(StateCompartmentEditPart.VISUAL_ID)); + // transfer the request to the super method to deal with regular Entry/ExitPoint creation + if (!stateCompartmentView.getChildren().isEmpty()) { + return super.getCommand(request); + } + // get an adaptable for it, to pass on to commands + IAdaptable adaptableForStateCompartmentView = new SemanticAdapter(null, stateCompartmentView); + + CustomFirstRegionInCompositeStateCreateElementCommand createNewRegion = new CustomFirstRegionInCompositeStateCreateElementCommand(adaptableForStateCompartmentView, null, ((IGraphicalEditPart) getHost()).getDiagramPreferencesHint(), + editingDomain, DiagramUIMessages.CreateCommand_Label, dropLocation); + EList regions = ((State) stateView.getElement()).getRegions(); + if (!regions.isEmpty()) { + // the view does not contain any region, but the model has already at least one. Use the first + // existing region. + createNewRegion.useExistingRegion(regions.get(0)); + } + + SetPropertyCommand showCompartment = new SetPropertyCommand(editingDomain, adaptableForStateCompartmentView, NOTATION_VIEW_VISIBLE, VISIBILITY, true); + + ViewDescriptor viewDescriptor = new ViewDescriptor( + (IAdaptable) createNewRegion.getCommandResult().getReturnValue(), + Node.class, + semanticHint, + ((IGraphicalEditPart) getHost()).getDiagramPreferencesHint()); + CustomVertexCreateElementCommand createVertex = + new CustomVertexCreateElementCommand(editingDomain, viewDescriptor, (IAdaptable) createNewRegion.getCommandResult().getReturnValue(), DiagramUIMessages.CreateCommand_Label); + + cc.compose(showCompartment); + cc.compose(createNewRegion); + cc.compose(createVertex); + + if (request instanceof CreateRequest) { + CreateRequest req = (CreateRequest) request; + + // Retrieve parent location + Point parentLocation = getHostFigure().getBounds().getLocation().getCopy(); + + // Compute relative creation location + Point requestedLocation = req.getLocation().getCopy(); + // normally, shape would be relative to region (which has not been created yet). Since we + // calculate relative to the hosting composite state, we use the REGION_OFFSET below to + // take this into account. + getHostFigure().translateToRelative(requestedLocation); + Rectangle proposedBounds = new Rectangle(requestedLocation.x, requestedLocation.y - REGION_OFFSET, -1, -1); + + // Convert the calculated preferred bounds as relative to parent location + Rectangle creationBounds; + if (request instanceof CreateUnspecifiedTypeRequest) { + creationBounds = proposedBounds.getTranslated(parentLocation.getNegated()); + } + else { + // call from pop-up bar (coordinates from request are not useful) + creationBounds = defaultLocation; + } + cc.compose(new SetBoundsCommand(editingDomain, DiagramUIMessages.SetLocationCommand_Label_Resize, viewDescriptor, creationBounds)); + } + return new ICommandProxy(cc.reduce()); + } + return null; + } } -- cgit v1.2.3