package rolemodel; import java.util.ArrayList; import java.util.List; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.graphiti.features.IDeleteFeature; import org.eclipse.graphiti.features.IDirectEditingInfo; import org.eclipse.graphiti.features.IFeature; import org.eclipse.graphiti.features.IReason; import org.eclipse.graphiti.features.context.IAddContext; import org.eclipse.graphiti.features.context.ICreateContext; import org.eclipse.graphiti.features.context.IDeleteContext; import org.eclipse.graphiti.features.context.ILayoutContext; import org.eclipse.graphiti.features.context.IMoveShapeContext; import org.eclipse.graphiti.features.context.IResizeShapeContext; import org.eclipse.graphiti.features.context.IUpdateContext; import org.eclipse.graphiti.features.context.impl.DeleteContext; import org.eclipse.graphiti.features.context.impl.MoveShapeContext; import org.eclipse.graphiti.features.context.impl.MultiDeleteInfo; import org.eclipse.graphiti.features.custom.ICustomFeature; import org.eclipse.graphiti.features.impl.Reason; import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm; import org.eclipse.graphiti.mm.algorithms.Polyline; import org.eclipse.graphiti.mm.algorithms.Rectangle; import org.eclipse.graphiti.mm.algorithms.Text; import org.eclipse.graphiti.mm.algorithms.styles.Orientation; import org.eclipse.graphiti.mm.pictograms.ContainerShape; import org.eclipse.graphiti.mm.pictograms.Diagram; import org.eclipse.graphiti.mm.pictograms.PictogramElement; import org.eclipse.graphiti.mm.pictograms.Shape; import org.eclipse.graphiti.pattern.AbstractPattern; import org.eclipse.graphiti.pattern.IPattern; import org.eclipse.graphiti.ui.editor.DiagramEditorInput; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.framed.iorm.featuremodel.FRaMEDFeature; import org.framed.iorm.model.Model; import org.framed.iorm.model.ModelElement; import org.framed.iorm.model.OrmFactory; import org.framed.iorm.model.Segment; import org.framed.iorm.model.Type; import org.framed.iorm.ui.FRaMEDShapePattern; import org.framed.iorm.ui.UILiterals; import org.framed.iorm.ui.UIUtil; import org.framed.iorm.ui.editPolicy.EditPolicyService; import org.framed.iorm.ui.exceptions.NoDiagramFoundException; import org.framed.iorm.ui.palette.FeaturePaletteDescriptor; import org.framed.iorm.ui.palette.PaletteCategory; import org.framed.iorm.ui.palette.PaletteView; import org.framed.iorm.ui.palette.ViewVisibility; import org.framed.iorm.ui.references.AbstractAttributeAndOperationReference; import org.framed.iorm.ui.references.AbstractGroupingFeatureReference; import org.framed.iorm.ui.references.AbstractStepInReference; import org.framed.iorm.ui.wizards.RoleModelWizard; /** * This graphiti pattern class is used to work with {@link org.framed.iorm.model.Shape}s * of the type {@link Type#COMPARTMENT_TYPE} created by the role model feature in the editor. * <p> * It is mostly the same as the pattern of the compartment type, since a created role model is handled like * a compartment type if the corresponding feature is chosen. * <p> * It deals with the following aspects of role model:<br> * (1) adding a role model to the diagram, especially its pictogram elements<br> * (2) creating the role model, especially its business object<br> * (3) layout the group, especially setting lines and role model elements at the right positions<br> * (4) updating the role model's content overview<br> * (5) moves the drop shadow with the type body and disables moving the drop shadow manually<br> * (6) resizes the drop shadow with the type body and disables resizing the drop shadow manually<br> * (7) deleting all the role model's pictogram elements and its diagram, also disables deleting the drop * shadow manually * @author Kevin Kassin */ public class RoleModelPattern extends FRaMEDShapePattern implements IPattern { /** * the object to get names, ids and so on for this feature */ private final Literals literals = new Literals(); /** * the object to call utility operations on */ private final Util util = new Util(); /** * the reference to the step in feature */ private final AbstractStepInReference stepInReference = UIUtil.getStepInFeatureReference(); /** * a reference class which encapsulates the dependency to the attribute and operation features */ private final AbstractAttributeAndOperationReference attOpsReference = UIUtil.getAttributeAndOperationFeatureReference(); /** * the list of reference classes which save in module feature's shapes can group objects * @see AbstractGroupingFeatureReference */ private final List<AbstractGroupingFeatureReference> groupingFeatureReferences; /** * the feature palette descriptor manages the palette visibility, see {@link FeaturePaletteDescriptor} */ private final FeaturePaletteDescriptor spec_FPD = new FeaturePaletteDescriptor( PaletteCategory.ENTITIES_CATEGORY, ViewVisibility.TOPLEVEL_VIEW) { @Override public boolean featureExpression(List<String> framedFeatureNames, PaletteView paletteView) { return !(framedFeatureNames.contains("Compartment_Types")); } }; /** * class constructor */ public RoleModelPattern() { super(); FEATURE_NAME = literals.FEATURE_NAME; ICON_IMG_ID = literals.ICON_IMG_ID; ICON_IMG_PATH = literals.ICON_IMG_PATH; modelType = Type.COMPARTMENT_TYPE; FPD = spec_FPD; //Note groupingFeatureReferences = UIUtil.getGroupingFeatureReferences(); } /** * returns the double click feature of this pattern */ @Override public IFeature getDoubleClickFeature(ICustomFeature[] customFeatures) { if(stepInReference == null) return null; return (ICustomFeature) UIUtil.findFeatureByName(customFeatures, stepInReference.getStepInFeatureName()); } /** * checks if pattern is applicable for a given business object * @return true, if business object is a {@link org.framed.iorm.model.Shape} of type {@link Type#COMPARTMENT_TYPE} and the * compartment type feature is not chosen */ @Override public boolean isMainBusinessObjectApplicable(Object businessObject) { if(businessObject instanceof org.framed.iorm.model.Shape) { org.framed.iorm.model.Shape shape = (org.framed.iorm.model.Shape) businessObject; Diagram mainDiagram = UIUtil.getMainDiagramForAnyDiagram(getDiagram()); Model mainModel = (Model) getBusinessObjectForPictogramElement(mainDiagram); List<String> framedFeatureNames = new ArrayList<String>(); for(FRaMEDFeature framedFeature : mainModel.getFramedConfiguration().getFeatures()) { framedFeatureNames.add(framedFeature.getName().getLiteral()); } if(shape.getType() == Type.COMPARTMENT_TYPE && !(framedFeatureNames.contains("Compartment_Types"))) return true; } return false; } /** * checks if pattern is applicable for a given pictogram element * @return true, if business object of the pictogram element is a {@link org.framed.iorm.model.Shape} of type {@link Type#COMPARTMENT_TYPE} */ @Override protected boolean isPatternControlled(PictogramElement pictogramElement) { Object businessObject = getBusinessObjectForPictogramElement(pictogramElement); return isMainBusinessObjectApplicable(businessObject); } /** * checks if the pictogram element to edit with the pattern is its root * @return true, if business object of the pictogram element is a {@link org.framed.iorm.model.Shape} of type {@link Type#COMPARTMENT_TYPE} */ @Override protected boolean isPatternRoot(PictogramElement pictogramElement) { Object businessObject = getBusinessObjectForPictogramElement(pictogramElement); return isMainBusinessObjectApplicable(businessObject); } // add feature //~~~~~~~~~~~~~ /** * calculates if the role model can be added to the diagram * <p> * returns true if:<br> * (1) if the added business object is a compartment type and <br> * (2) if the target container is a diagram with a model linked * @return if the role model can be added */ @Override public boolean canAdd(IAddContext addContext) { if (addContext.getNewObject() instanceof org.framed.iorm.model.Shape) { org.framed.iorm.model.Shape shape = (org.framed.iorm.model.Shape) addContext.getNewObject(); if (shape.getType() == Type.COMPARTMENT_TYPE) { if (UIUtil.getLinkedModelForDiagram(getDiagram()) != null) { System.out.println("getContainer():" + addContext.getTargetContainer()+"."); if (addContext.getTargetContainer() instanceof Diagram) return EditPolicyService.getHandler(this.getDiagram()).canAdd(addContext, Type.COMPARTMENT_TYPE); } } } return false; } /** * adds the graphical representation of a role model to the pictogram model * <p> * It creates the following structure:<br> * <ul> * <li>container shape</li> * <ul> * <li>drop shadow shape</li> * <ul><li>drop shadow rectangle</li></ul> * <li>type body shape</li> * <ul><li>type body rectangle</li></ul> * <ul> * <li>name container</li> * <ul><li>name text</li></ul> * <li>first line container</li> * <ul><li>first polyline</li></ul> * <li>attribute container shape</li> * <ul><li>attribute container rectangle</li></ul> * <li>second line container</li> * <ul><li>second polyline</li></ul> * <li>operation container shape</li> * <ul><li>operation container rectangle</li></ul> * <li>third line container</li> * <ul><li>third polyline</li></ul> * <li>model content preview container</li> * <ul><li>model content preview rectangle</li></ul> * </ul> * </ul> * </ul> * <p> * The role model's diagram will be created outside of the role model <em>container shape</em>. It can be * found as child of the <em>container diagram</em> of the role model. If its not clear what <em>container diagram</em> * means, see {@link RoleModelWizard#createEmfFileForDiagram} for reference. * <p> * It uses follows this steps:<br> * Step 1: It gets the new object, the diagram to create the role model in and calculates the height and width * of the role model's representation.<br> * Step 2: It creates the structure shown above.<br> * Step 3: It sets the shape identifiers for the created graphics algorithms of the role model.<br> * Step 4: It links the created shapes of the group to its business objects.<br> * Step 5: It enables direct editing, anchors and layouting of the role model. It also updates the group in which * its created, if any. */ @Override public PictogramElement add(IAddContext addContext) { //Step 1 org.framed.iorm.model.Shape addedCompartmentType = (org.framed.iorm.model.Shape) addContext.getNewObject(); ContainerShape targetDiagram = getDiagram(); int width = addContext.getWidth(), height = addContext.getHeight(); if(addContext.getWidth() < literals.MIN_WIDTH) width = literals.MIN_WIDTH; if(addContext.getHeight() < literals.MIN_HEIGHT) height = literals.MIN_HEIGHT; //Step 2 //container for body shape and shadow ContainerShape containerShape = pictogramElementCreateService.createContainerShape(targetDiagram, false); //drop shadow ContainerShape dropShadowShape = pictogramElementCreateService.createContainerShape(containerShape, true); Rectangle dropShadowRectangle = graphicAlgorithmService.createRectangle(dropShadowShape); dropShadowRectangle.setForeground(manageColor(literals.COLOR_SHADOW)); dropShadowRectangle.setBackground(manageColor(literals.COLOR_SHADOW)); graphicAlgorithmService.setLocationAndSize(dropShadowRectangle, addContext.getX()+literals.SHADOW_SIZE, addContext.getY()+literals.SHADOW_SIZE, width, height); //body shape of type ContainerShape typeBodyShape = pictogramElementCreateService.createContainerShape(containerShape, true); Rectangle typeBodyRectangle = graphicAlgorithmService.createRectangle(typeBodyShape); typeBodyRectangle.setForeground(manageColor(literals.COLOR_LINES)); typeBodyRectangle.setBackground(manageColor(literals.COLOR_BACKGROUND)); graphicAlgorithmService.setLocationAndSize(typeBodyRectangle, addContext.getX(), addContext.getY(), width, height); //name Shape nameShape = pictogramElementCreateService.createShape(typeBodyShape, false); Text text = graphicAlgorithmService.createText(nameShape, addedCompartmentType.getName()); text.setForeground(manageColor(literals.COLOR_TEXT)); text.setHorizontalAlignment(Orientation.ALIGNMENT_CENTER); graphicAlgorithmService.setLocationAndSize(text, 0, 0, width, literals.HEIGHT_NAME_SHAPE); //first line Shape firstLineShape = pictogramElementCreateService.createShape(typeBodyShape, false); Polyline firstPolyline = graphicAlgorithmService.createPolyline(firstLineShape, new int[] {0, literals.HEIGHT_NAME_SHAPE, width, literals.HEIGHT_NAME_SHAPE}); firstPolyline.setForeground(manageColor(literals.COLOR_LINES)); //attribute container ContainerShape attributeContainer = pictogramElementCreateService.createContainerShape(typeBodyShape, false); Rectangle attributeRectangle = graphicAlgorithmService.createRectangle(attributeContainer); attributeRectangle.setLineVisible(false); attributeRectangle.setBackground(manageColor(literals.COLOR_BACKGROUND)); int horizontalFirstThird = util.calculateHorizontaltFirstThird(height); graphicAlgorithmService.setLocationAndSize(attributeRectangle, literals.PUFFER_BETWEEN_ELEMENTS, literals.HEIGHT_NAME_SHAPE+literals.PUFFER_BETWEEN_ELEMENTS, width-2*literals.PUFFER_BETWEEN_ELEMENTS, horizontalFirstThird-literals.HEIGHT_NAME_SHAPE-2*literals.PUFFER_BETWEEN_ELEMENTS); //second line Shape secondLineShape = pictogramElementCreateService.createShape(typeBodyShape, false); Polyline secondPolyline = graphicAlgorithmService.createPolyline(secondLineShape, new int[] {0, horizontalFirstThird, width, horizontalFirstThird}); secondPolyline.setForeground(manageColor(literals.COLOR_LINES)); //operation container ContainerShape operationContainer = pictogramElementCreateService.createContainerShape(typeBodyShape, false); Rectangle operationRectangle = graphicAlgorithmService.createRectangle(operationContainer); operationRectangle.setLineVisible(false); operationRectangle.setBackground(manageColor(literals.COLOR_BACKGROUND)); graphicAlgorithmService.setLocationAndSize(operationRectangle, literals.PUFFER_BETWEEN_ELEMENTS, horizontalFirstThird+literals.PUFFER_BETWEEN_ELEMENTS, width-2*literals.PUFFER_BETWEEN_ELEMENTS, horizontalFirstThird-literals.HEIGHT_NAME_SHAPE-2*literals.PUFFER_BETWEEN_ELEMENTS); //third line Shape thirdLineShape = pictogramElementCreateService.createShape(typeBodyShape, false); int horizontalSecondThird = util.calculateHorizontaltSecondThird(height); Polyline thirdPolyline = graphicAlgorithmService.createPolyline(thirdLineShape, new int[] {0, horizontalSecondThird, width, horizontalSecondThird}); thirdPolyline.setForeground(manageColor(literals.COLOR_LINES)); //model content preview container ContainerShape modelContainer = pictogramElementCreateService.createContainerShape(typeBodyShape, false); Rectangle modelRectangle = graphicAlgorithmService.createRectangle(modelContainer); modelRectangle.setLineVisible(false); modelRectangle.setBackground(manageColor(literals.COLOR_BACKGROUND)); graphicAlgorithmService.setLocationAndSize(modelRectangle, literals.PUFFER_BETWEEN_ELEMENTS, horizontalSecondThird+literals.PUFFER_BETWEEN_ELEMENTS, width-2*literals.PUFFER_BETWEEN_ELEMENTS, horizontalFirstThird-literals.HEIGHT_NAME_SHAPE-2*literals.PUFFER_BETWEEN_ELEMENTS); //role model's diagram Diagram contentDiagram = pictogramElementCreateService.createDiagram(UILiterals.DIAGRAM_TYPE_ID, addedCompartmentType.getName(), 10, true); UIUtil.setDiagram_KindValue(contentDiagram, literals.DIAGRAM_KIND); AddRoleModelContext agctc = (AddRoleModelContext) addContext; link(contentDiagram, agctc.getModelToLink()); getDiagram().getContainer().getChildren().add(contentDiagram); //Step 3 UIUtil.setShape_IdValue(containerShape, literals.SHAPE_ID_ROLEMODEL_CONTAINER); UIUtil.setShape_IdValue(typeBodyShape, literals.SHAPE_ID_ROLEMODEL_TYPEBODY); UIUtil.setShape_IdValue(dropShadowShape, literals.SHAPE_ID_ROLEMODEL_SHADOW); UIUtil.setShape_IdValue(nameShape, literals.SHAPE_ID_ROLEMODEL_NAME); UIUtil.setShape_IdValue(firstLineShape, literals.SHAPE_ID_ROLEMODEL_FIRSTLINE); UIUtil.setShape_IdValue(attributeContainer, literals.SHAPE_ID_ROLEMODEL_ATTRIBUTECONTAINER); UIUtil.setShape_IdValue(secondLineShape, literals.SHAPE_ID_ROLEMODEL_SECONDLINE); UIUtil.setShape_IdValue(operationContainer, literals.SHAPE_ID_ROLEMODEL_OPERATIONCONTAINER); UIUtil.setShape_IdValue(thirdLineShape, literals.SHAPE_ID_ROLEMODEL_THIRDLINE); UIUtil.setShape_IdValue(modelContainer, literals.SHAPE_ID_ROLEMODEL_CONTENT_PREVIEW); //Step 4 link(containerShape, addedCompartmentType); link(typeBodyShape, addedCompartmentType); link(dropShadowShape, addedCompartmentType); link(nameShape, addedCompartmentType); link(firstLineShape, addedCompartmentType); link(attributeContainer, addedCompartmentType); link(secondLineShape, addedCompartmentType); link(operationContainer, addedCompartmentType); link(thirdLineShape, addedCompartmentType); link(modelContainer, addedCompartmentType); //Step 5 getFeatureProvider().getDirectEditingInfo().setActive(true); IDirectEditingInfo directEditingInfo = getFeatureProvider().getDirectEditingInfo(); directEditingInfo.setMainPictogramElement(typeBodyShape); directEditingInfo.setPictogramElement(nameShape); directEditingInfo.setGraphicsAlgorithm(text); pictogramElementCreateService.createChopboxAnchor(typeBodyShape); layoutPictogramElement(containerShape); updateContainingGroupingFeaturesObject(); return containerShape; } //create feature //~~~~~~~~~~~~~~ /** * calculates if a role model can be created * <p> * returns true if:<br> * (1) the target container is a diagram with a model linked * @return if an role model can be created */ @Override public boolean canCreate(ICreateContext createContext) { if(UIUtil.getLinkedModelForDiagram(getDiagram()) != null) { System.out.println("getContainer():" + createContext.getTargetContainer()+"."); if (createContext.getTargetContainer() instanceof Diagram) return EditPolicyService.getHandler(getDiagram()).canCreate(createContext, this.modelType); } return false; } /** * creates the business objects of the role model, adds it to model of the diagram in which the role model is * created in and calls the add function for the role model * <p> * It creates the following structure:<br> * <ul> * <li>(org.framed.iorm.model.Shape) role model</li> * <ul> * <li>(Segment) first segment (for attributes)</li> * <li>(Segment) second segment (for operations)</li> * <li>(Model) role model model</li> * </ul> * </ul> * <p> * It follows this steps:<br> * Step 1: It creates the structure shown above.<br> * Step 2: It adds the new role model to the elements of the model of the diagram in which its created.<br> * Step 3: It call the add function to add the pictogram elements of the role model using a * {@link AddRoleModelContext}. * @return the created business object of the role model */ @Override public Object[] create(ICreateContext createContext) { //Step 1 //compartment type org.framed.iorm.model.Shape newCompartmentType = OrmFactory.eINSTANCE.createShape(); newCompartmentType.setType(Type.COMPARTMENT_TYPE); String standardName = UIUtil.calculateStandardNameRoleModelWide(getDiagram(), Type.COMPARTMENT_TYPE, literals.STANDARD_NAME); newCompartmentType.setName(standardName); //create segments Segment attributeSegment = OrmFactory.eINSTANCE.createSegment(), operationSegment = OrmFactory.eINSTANCE.createSegment(); getDiagram().eResource().getContents().add(attributeSegment); getDiagram().eResource().getContents().add(operationSegment); newCompartmentType.setFirstSegment(attributeSegment); newCompartmentType.setSecondSegment(operationSegment); //model Model compartmentsModel = OrmFactory.eINSTANCE.createModel(); getDiagram().eResource().getContents().add(compartmentsModel); newCompartmentType.setModel(compartmentsModel); //Step 2 Model model = UIUtil.getLinkedModelForDiagram((Diagram) getDiagram()); if(newCompartmentType.eResource() != null) getDiagram().eResource().getContents().add(newCompartmentType); model.getElements().add(newCompartmentType); newCompartmentType.setContainer(model); //Step 3 AddRoleModelContext actc = new AddRoleModelContext(); UIUtil.getAddContextForCreateShapeContext(actc, createContext); actc.setNewObject(newCompartmentType); actc.setModelToLink(compartmentsModel); if(canAdd(actc)) add(actc); return new Object[] { newCompartmentType }; } //layout feature //~~~~~~~~~~~~~~ /** * calculates if a pictogram element of a role model can be layouted * <p> * returns true if:<br> * (1) if exactly one pictogram element is given by the layout context * (2) the business object of the pictogram element is a {@link org.framed.iorm.model.Shape} * of the type {@link Type#COMPARTMENT_TYPE} * @return if the given pictogram can be layouted */ @Override public boolean canLayout(ILayoutContext layoutContext) { PictogramElement element = layoutContext.getPictogramElement(); if (element instanceof ContainerShape) { EList<EObject> businessObjects = element.getLink().getBusinessObjects(); if (businessObjects.size() == 1) { if (businessObjects.get(0) instanceof org.framed.iorm.model.Shape) { org.framed.iorm.model.Shape shape = (org.framed.iorm.model.Shape) businessObjects.get(0); if (shape.getType() == Type.COMPARTMENT_TYPE) return true; } } } return false; } /** * layout the whole role model using the following steps: * <p> * Step 1: Its fetches the type body shape and drop shadow shape<br> * Step 2: It calculates the new height, width and horizontal center. It also uses this data to set * the size of the type body and drop shadow shape.<br> * Step 3: It now iterates over all shapes of the role model:<br> * (a) It sets the width of the names shape.<br> * (b) It sets the points of the line that separates the name and content preview container.<br> * (c) It layouts the visualization of the elements in the content preview container. * <p> * If its not clear what the different shapes means, see {@link #add} for reference. */ @Override public boolean layout(ILayoutContext layoutContext) { boolean layoutChanged = false; int newHeight, newWidth, newY; Shape indicatorDotsShapeToDelete; ContainerShape container = (ContainerShape) layoutContext.getPictogramElement(); //Step 1 if(!(UIUtil.isShape_IdValue(container, literals.SHAPE_ID_ROLEMODEL_TYPEBODY))) return false; else { Rectangle typeBodyRectangle = (Rectangle) container.getGraphicsAlgorithm(); Rectangle dropShadowRectangle = (Rectangle) container.getContainer().getChildren().get(0).getGraphicsAlgorithm(); //Step 2 if(typeBodyRectangle.getWidth() < literals.MIN_WIDTH) typeBodyRectangle.setWidth(literals.MIN_WIDTH); if(typeBodyRectangle.getHeight() < literals.MIN_HEIGHT) typeBodyRectangle.setHeight(literals.MIN_HEIGHT); int width = typeBodyRectangle.getWidth(); int height = typeBodyRectangle.getHeight(); dropShadowRectangle.setWidth(width); dropShadowRectangle.setHeight(height); dropShadowRectangle.setX(typeBodyRectangle.getX()+literals.SHADOW_SIZE); dropShadowRectangle.setY(typeBodyRectangle.getY()+literals.SHADOW_SIZE); //Step 3 for (Shape shape : container.getChildren()){ GraphicsAlgorithm graphicsAlgorithm = shape.getGraphicsAlgorithm(); int horizontalFirstThird = util.calculateHorizontaltFirstThird(height); int horizontalSecondThird = util.calculateHorizontaltSecondThird(height); //(a) name shape if (graphicsAlgorithm instanceof Text) { Text text = (Text) graphicsAlgorithm; if(UIUtil.isShape_IdValue(shape, literals.SHAPE_ID_ROLEMODEL_NAME)) { graphicAlgorithmService.setLocationAndSize(text, 0, 0, width, literals.HEIGHT_NAME_SHAPE); layoutChanged=true; } } //(b) line shapes if (graphicsAlgorithm instanceof Polyline) { Polyline polyline = (Polyline) graphicsAlgorithm; if(UIUtil.isShape_IdValue(shape, literals.SHAPE_ID_ROLEMODEL_FIRSTLINE)) { polyline.getPoints().set(1, graphicAlgorithmService.createPoint(width, polyline.getPoints().get(1).getY())); layoutChanged=true; } if(UIUtil.isShape_IdValue(shape, literals.SHAPE_ID_ROLEMODEL_SECONDLINE)) { polyline.getPoints().set(0, graphicAlgorithmService.createPoint(0, horizontalFirstThird)); polyline.getPoints().set(1, graphicAlgorithmService.createPoint(width, horizontalFirstThird)); layoutChanged=true; } if(UIUtil.isShape_IdValue(shape, literals.SHAPE_ID_ROLEMODEL_THIRDLINE)) { polyline.getPoints().set(0, graphicAlgorithmService.createPoint(0, horizontalSecondThird)); polyline.getPoints().set(1, graphicAlgorithmService.createPoint(width, horizontalSecondThird)); layoutChanged=true; } } if (graphicsAlgorithm instanceof Rectangle) { Rectangle rectangle = (Rectangle) graphicsAlgorithm; //(c) attribute container shape if(UIUtil.isShape_IdValue(shape, literals.SHAPE_ID_ROLEMODEL_ATTRIBUTECONTAINER)) { //resize and positioning the container newHeight = horizontalFirstThird-literals.HEIGHT_NAME_SHAPE-2*literals.PUFFER_BETWEEN_ELEMENTS; newWidth = width-2*literals.PUFFER_BETWEEN_ELEMENTS; newY = literals.HEIGHT_NAME_SHAPE+literals.PUFFER_BETWEEN_ELEMENTS; rectangle.setHeight(newHeight); rectangle.setWidth(newWidth); ContainerShape attributeContainerShape = (ContainerShape) shape; EList<Shape> attributes = attributeContainerShape.getChildren(); //set place of attributes for(int m = 0; m<attributes.size(); m++) { Text attributeText = (Text) attributeContainerShape.getChildren().get(m).getGraphicsAlgorithm(); attributeText.setY(newY+m*attOpsReference.HEIGHT_OPERATION_SHAPE); attributeText.setWidth(newWidth); } //set all attributes visible indicatorDotsShapeToDelete = null; for(int j = 0; j<attributes.size(); j++) { attributes.get(j).setVisible(true); if(UIUtil.isShape_IdValue(attributes.get(j), attOpsReference.SHAPE_ID_ATTRIBUTE_INDICATOR_DOTS)) indicatorDotsShapeToDelete = attributes.get(j); } attributeContainerShape.getChildren().remove(indicatorDotsShapeToDelete); //check if not all attributes fit in the attribute field if(attributeContainerShape.getChildren().size()*attOpsReference.HEIGHT_ATTRIBUTE_SHAPE>newHeight) { int fittingAttributes = (newHeight-attOpsReference.HEIGHT_ATTRIBUTE_SHAPE)/attOpsReference.HEIGHT_ATTRIBUTE_SHAPE; //set not fitting attributes to invisible for(int k = fittingAttributes; k<attributes.size(); k++) { attributeContainerShape.getChildren().get(k).setVisible(false); } //add dots to indicate that not all attributes fit Shape indicatorDotsShape = pictogramElementCreateService.createShape(attributeContainerShape, true); Text indicatorDots = graphicAlgorithmService.createText(indicatorDotsShape, "..."); indicatorDots.setForeground(manageColor(literals.COLOR_TEXT)); graphicAlgorithmService.setLocationAndSize(indicatorDots, literals.PUFFER_BETWEEN_ELEMENTS, attOpsReference.HEIGHT_ATTRIBUTE_SHAPE+fittingAttributes*attOpsReference.HEIGHT_ATTRIBUTE_SHAPE, newWidth-2*literals.PUFFER_BETWEEN_ELEMENTS, attOpsReference.HEIGHT_OPERATION_SHAPE-2*literals.PUFFER_BETWEEN_ELEMENTS); UIUtil.setShape_IdValue(indicatorDotsShape, attOpsReference.SHAPE_ID_ATTRIBUTE_INDICATOR_DOTS); } layoutChanged=true; } //(d) operation container shape if(UIUtil.isShape_IdValue(shape, literals.SHAPE_ID_ROLEMODEL_OPERATIONCONTAINER)) { //resize and positioning the container newHeight = horizontalFirstThird-literals.HEIGHT_NAME_SHAPE-2*literals.PUFFER_BETWEEN_ELEMENTS; newWidth = width-2*literals.PUFFER_BETWEEN_ELEMENTS; newY = horizontalFirstThird+literals.PUFFER_BETWEEN_ELEMENTS; rectangle.setHeight(newHeight); rectangle.setWidth(newWidth); rectangle.setY(newY); ContainerShape operationContainerShape = (ContainerShape) shape; EList<Shape> operations = operationContainerShape.getChildren(); //set place of attributes for(int m = 0; m<operations.size(); m++) { Text operationText = (Text) operationContainerShape.getChildren().get(m).getGraphicsAlgorithm(); operationText.setY(newY+m*attOpsReference.HEIGHT_OPERATION_SHAPE); operationText.setWidth(newWidth); } //set all operations visible indicatorDotsShapeToDelete = null; for(int n = 0; n<operations.size(); n++) { operations.get(n).setVisible(true); if(UIUtil.isShape_IdValue(operations.get(n), attOpsReference.SHAPE_ID_OPERATION_INDICATOR_DOTS)) indicatorDotsShapeToDelete = operations.get(n); } operationContainerShape.getChildren().remove(indicatorDotsShapeToDelete); //check if not all operations fit in the operations field if(operations.size()*attOpsReference.HEIGHT_OPERATION_SHAPE>newHeight) { int fittingOperations = (newHeight-attOpsReference.HEIGHT_OPERATION_SHAPE)/attOpsReference.HEIGHT_OPERATION_SHAPE; //set not fitting operations to invisible for(int o = fittingOperations; o<operations.size(); o++) { operationContainerShape.getChildren().get(o).setVisible(false); } //add dots to indicate that not all operations fit Shape indicatorDotsShape = pictogramElementCreateService.createShape(operationContainerShape, true); Text indicatorDots = graphicAlgorithmService.createText(indicatorDotsShape, "..."); indicatorDots.setForeground(manageColor(literals.COLOR_TEXT)); graphicAlgorithmService.setLocationAndSize(indicatorDots, literals.PUFFER_BETWEEN_ELEMENTS, newY+fittingOperations*attOpsReference.HEIGHT_OPERATION_SHAPE, newWidth-2*literals.PUFFER_BETWEEN_ELEMENTS, attOpsReference.HEIGHT_OPERATION_SHAPE); UIUtil.setShape_IdValue(indicatorDotsShape, attOpsReference.SHAPE_ID_OPERATION_INDICATOR_DOTS); } layoutChanged=true; } //(c) content preview container if(UIUtil.isShape_IdValue(shape, literals.SHAPE_ID_ROLEMODEL_CONTENT_PREVIEW)) { //resize and positioning the container newHeight = horizontalFirstThird-literals.HEIGHT_NAME_SHAPE-2*literals.PUFFER_BETWEEN_ELEMENTS; newWidth = width-2*literals.PUFFER_BETWEEN_ELEMENTS; newY = horizontalSecondThird+literals.PUFFER_BETWEEN_ELEMENTS; rectangle.setHeight(newHeight); rectangle.setWidth(newWidth); rectangle.setY(newY); ContainerShape elementsShape = (ContainerShape) shape; EList<Shape> elements = elementsShape.getChildren(); //set all elements visible, delete indicator dots and positions of the elements indicatorDotsShapeToDelete = null; int counter = 0; for(Shape elementShape : elements) { elementShape.setVisible(true); graphicAlgorithmService.setLocationAndSize(elementShape.getGraphicsAlgorithm(), literals.PUFFER_BETWEEN_ELEMENTS, newY+literals.HEIGHT_COMPARTMENT_ELEMENT_SHAPE*counter, newWidth-2*literals.PUFFER_BETWEEN_ELEMENTS, literals.HEIGHT_COMPARTMENT_ELEMENT_SHAPE); if(UIUtil.isShape_IdValue(elementShape, literals.SHAPE_ID_ROLEMODEL_INDICATOR_DOTS)) indicatorDotsShapeToDelete = elementShape; counter++; } elementsShape.getChildren().remove(indicatorDotsShapeToDelete); //check if not all elements fit in the attribute field if(elements.size()*literals.HEIGHT_COMPARTMENT_ELEMENT_SHAPE > newHeight) { int fittingAttributes = (newHeight-literals.HEIGHT_COMPARTMENT_ELEMENT_SHAPE)/literals.HEIGHT_COMPARTMENT_ELEMENT_SHAPE; //set not fitting attributes to invisible for(int k = fittingAttributes; k<elements.size(); k++) { elements.get(k).setVisible(false); } //add dots to indicate not all elements fit Shape indicatorDotsShape = pictogramElementCreateService.createShape(elementsShape, true); Text indicatorDots = graphicAlgorithmService.createText(indicatorDotsShape, "..."); indicatorDots.setForeground(manageColor(literals.COLOR_TEXT)); graphicAlgorithmService.setLocationAndSize(indicatorDots, literals.PUFFER_BETWEEN_ELEMENTS, newY+fittingAttributes*literals.HEIGHT_COMPARTMENT_ELEMENT_SHAPE, newWidth-2*literals.PUFFER_BETWEEN_ELEMENTS, literals.HEIGHT_COMPARTMENT_ELEMENT_SHAPE); UIUtil.setShape_IdValue(indicatorDotsShape, literals.SHAPE_ID_ROLEMODEL_INDICATOR_DOTS); } layoutChanged = true; } } } } return layoutChanged; } //update feature //~~~~~~~~~~~~~~ @Override public boolean canUpdate(IUpdateContext updateContext) { //check if object to update is a compartment PictogramElement pictogramElement = updateContext.getPictogramElement(); Object businessObject = getBusinessObjectForPictogramElement(pictogramElement); if(businessObject instanceof org.framed.iorm.model.Shape) { org.framed.iorm.model.Shape shape = (org.framed.iorm.model.Shape) businessObject; if(shape.getType() == Type.COMPARTMENT_TYPE) { return true; } } return false; } @Override public IReason updateNeeded(IUpdateContext updateContext) { String rawModelContainerElementName, modelContainerElementName; PictogramElement pictogramElement = updateContext.getPictogramElement(); if(UIUtil.isShape_IdValue((Shape) pictogramElement, literals.SHAPE_ID_ROLEMODEL_TYPEBODY)) { //pictogram name, attributes, operations and elements String pictogramTypeName = util.getNameOfPictogramElement(pictogramElement); List<String> pictogramAttributeNames = util.getpictogramAttributeNames(pictogramElement); List<String> pictogramOperationNames = util.getpictogramOperationNames(pictogramElement); //model element names in model container of shape List<String> pictogramElementsNames = util.getContentPreviewElementsNames(pictogramElement); //business name and attributes String businessTypeName = UIUtil.getNameOfBusinessObject(getBusinessObjectForPictogramElement(pictogramElement)); List<String> businessAttributeNames = util.getBusinessAttributeNames(pictogramElement); List<String> businessOperationNames = util.getBusinessOperationNames(pictogramElement); //at creation no diagram is existing so catch this List<String> modelElementsNames = null; try { modelElementsNames = UIUtil.getGroupingFeaturesModelElementNames(pictogramElement, getDiagram(), Type.COMPARTMENT_TYPE); } catch(NoDiagramFoundException e) { return Reason.createFalseReason(); } //check for update: different names, different amount of attibutes/ operations if(pictogramTypeName==null || businessTypeName==null) return Reason.createTrueReason(literals.REASON_NAME_NULL); if(!(pictogramTypeName.equals(businessTypeName))) return Reason.createTrueReason(literals.REASON_NAME_OUT_OF_DATE); if(pictogramAttributeNames.size() != businessAttributeNames.size()) return Reason.createTrueReason(attOpsReference.REASON_AMOUNT_ATTRIBUTES); if(pictogramOperationNames.size() != businessOperationNames.size()) return Reason.createTrueReason(attOpsReference.REASON_AMOUNT_OPERATION); for(int i=0; i<pictogramAttributeNames.size(); i++) { if(!(pictogramAttributeNames.get(i).equals(businessAttributeNames.get(i)))) return Reason.createTrueReason(attOpsReference.REASON_NAMES_ATTRIBUTES); } for(int i=0; i<pictogramOperationNames.size(); i++) { if(!(pictogramOperationNames.get(i).equals(businessOperationNames.get(i)))) return Reason.createTrueReason(attOpsReference.REASON_NAMES_OPERATIONS); } if(modelElementsNames.size() != pictogramElementsNames.size()) { return Reason.createTrueReason(literals.REASON_AMOUNT_ELEMENTS); } for(int i=0; i<modelElementsNames.size(); i++) { modelContainerElementName = pictogramElementsNames.get(i); rawModelContainerElementName = modelContainerElementName.substring(modelContainerElementName.indexOf(" ")+1); if(!(modelElementsNames.get(i).equals(rawModelContainerElementName))) return Reason.createTrueReason(literals.REASON_NAMES_ELEMENTS); } } return Reason.createFalseReason(); } @Override public boolean update(IUpdateContext updateContext) { int counter; boolean changed = false; PictogramElement pictogramElement = updateContext.getPictogramElement(); //business names of natural type, attributes and operations String businessTypeName = UIUtil.getNameOfBusinessObject(getBusinessObjectForPictogramElement(pictogramElement)); List<String> businessAttributeNames = util.getBusinessAttributeNames(pictogramElement); List<String> businessOperationNames = util.getBusinessOperationNames(pictogramElement); //set type name in pictogram model if (pictogramElement instanceof ContainerShape) { ContainerShape typeBodyShape = (ContainerShape) pictogramElement; Diagram diagram = util.getCompartmentTypeDiagramForItsShape(typeBodyShape, getDiagram()); for (Shape shape : typeBodyShape.getChildren()) { if (shape.getGraphicsAlgorithm() instanceof Text) { Text text = (Text) shape.getGraphicsAlgorithm(); if(UIUtil.isShape_IdValue(shape, literals.SHAPE_ID_ROLEMODEL_NAME)) { diagram.setName(businessTypeName); //change group name text.setValue(businessTypeName); changed = true; } } //set attribute and operation names and thier places in pictogram model if(shape instanceof ContainerShape) { ContainerShape innerContainerShape = (ContainerShape) shape; if(innerContainerShape.getGraphicsAlgorithm() instanceof Rectangle) { //Attributes counter = 0; if(UIUtil.isShape_IdValue(innerContainerShape, literals.SHAPE_ID_ROLEMODEL_ATTRIBUTECONTAINER)) { for(Shape attributeShape : innerContainerShape.getChildren()) { if(UIUtil.isShape_IdValue(attributeShape, attOpsReference.SHAPE_ID_ATTRIBUTE_TEXT)) { Text text = (Text) attributeShape.getGraphicsAlgorithm(); text.setValue(businessAttributeNames.get(counter)); changed = true; counter++; } } } //Operations counter = 0; if(UIUtil.isShape_IdValue(innerContainerShape, literals.SHAPE_ID_ROLEMODEL_OPERATIONCONTAINER)) { for(Shape operationShape : innerContainerShape.getChildren()) { if(UIUtil.isShape_IdValue(operationShape, attOpsReference.SHAPE_ID_OPERATION_TEXT)) { Text text = (Text) operationShape.getGraphicsAlgorithm(); text.setValue(businessOperationNames.get(counter)); changed = true; counter++; } } } if(UIUtil.isShape_IdValue(shape, literals.SHAPE_ID_ROLEMODEL_CONTENT_PREVIEW)) { ContainerShape modelContainerShape = (ContainerShape) shape; Model compartmentModel = UIUtil.getLinkedModelForDiagram(diagram); counter = 0; modelContainerShape.getChildren().clear(); for(ModelElement modelElement : compartmentModel.getElements()) { if(modelElement instanceof org.framed.iorm.model.Shape) { Shape elementShape = pictogramElementCreateService.createShape(modelContainerShape, true); Text elementText = graphicAlgorithmService.createText(elementShape, UIUtil.getGroupingFeaturesElementText(modelElement)); elementText.setForeground(manageColor(literals.COLOR_TEXT)); UIUtil.setShape_IdValue(elementShape, literals.SHAPE_ID_ROLEMODEL_ELEMENT); counter++; } } changed = true; layoutPictogramElement(typeBodyShape); } } } } } return changed; } //move feature //~~~~~~~~~~~~ /** * disables that the user can move the drop shadow manually * <p> * Its also checks if the type body shape is moved onto the drop shadow shape and allows this. There for it takes * and expands some code of {@link AbstractPattern#canMoveShape}. */ @Override public boolean canMoveShape(IMoveShapeContext moveContext) { if(UIUtil.isShape_IdValue((Shape) moveContext.getPictogramElement(), literals.SHAPE_ID_ROLEMODEL_SHADOW)) { return false; } ContainerShape typeBodyShape = (ContainerShape) moveContext.getPictogramElement(); ContainerShape dropShadowShape = (ContainerShape) ((ContainerShape) typeBodyShape).getContainer().getChildren().get(0); //copied and expanded from super.canMoveShape(IMoveShapeContext moveContext) return moveContext.getSourceContainer() != null && (moveContext.getSourceContainer().equals(moveContext.getTargetContainer()) || moveContext.getTargetContainer().equals(dropShadowShape)) && isPatternRoot(moveContext.getPictogramElement()); } //move the type body and the drop shadow @Override public void moveShape(IMoveShapeContext moveContext) { ContainerShape typeBodyShape = (ContainerShape) moveContext.getPictogramElement(); Rectangle typeBodyRectangle = (Rectangle) typeBodyShape.getGraphicsAlgorithm(); ContainerShape dropShadowShape = (ContainerShape) ((ContainerShape) typeBodyShape).getContainer().getChildren().get(0); Rectangle dropShadowRectangle = (Rectangle) dropShadowShape.getGraphicsAlgorithm(); if(moveContext.getSourceContainer().equals(moveContext.getTargetContainer())) { dropShadowRectangle.setX(moveContext.getX()+literals.SHADOW_SIZE); dropShadowRectangle.setY(moveContext.getY()+literals.SHADOW_SIZE); super.moveShape(moveContext); } else { //targetContainer of moveContext is dropShadowShape //set targetContainer to diagram and use special calculation for the new position of type body and drop shadow dropShadowRectangle.setX(typeBodyRectangle.getX()+moveContext.getX()+2*literals.SHADOW_SIZE); dropShadowRectangle.setY(typeBodyRectangle.getY()+moveContext.getY()+2*literals.SHADOW_SIZE); MoveShapeContext changedMoveContextForTypeBody = new MoveShapeContext(moveContext.getShape()); changedMoveContextForTypeBody.setTargetContainer(dropShadowShape.getContainer()); changedMoveContextForTypeBody.setX(typeBodyRectangle.getX()+moveContext.getX()+literals.SHADOW_SIZE); changedMoveContextForTypeBody.setY(typeBodyRectangle.getY()+moveContext.getY()+literals.SHADOW_SIZE); super.moveShape(changedMoveContextForTypeBody); } } //resize feature //~~~~~~~~~~~~~~ /** * disables that the user can resize the drop shadow manually */ @Override public boolean canResizeShape(IResizeShapeContext resizeContext) { if(UIUtil.isShape_IdValue((Shape) resizeContext.getPictogramElement(), literals.SHAPE_ID_ROLEMODEL_SHADOW)) { return false; } return super.canResizeShape(resizeContext); } //delete feature //~~~~~~~~~~~~~~ /** * disables that the user can delete the drop shadow manually */ @Override public boolean canDelete(IDeleteContext deleteContext) { if(UIUtil.isShape_IdValue((Shape) deleteContext.getPictogramElement(), literals.SHAPE_ID_ROLEMODEL_SHADOW)) { return false; } return super.canDelete(deleteContext); } /** * deletes the group as cares about all related concerns using the following steps * <p> * Step 1: It deletes attached connection to it.<br> * Step 2: It gets the role model diagram and creates a {@link DeleteContext} for it.<br> * Step 3: It gets all compartment types that are a child of this compartment type to delete them as well. This is needed to be * explicitly since otherwise the diagrams of the child compartments would not be deleted.<br> * Step 4: It closes all editors that opened the diagram of this group to delete.<br> * Step 5: It gets the container shape of the role model, so this can be deleted instead of the type body shape.<br> * Step 6: It deletes the shapes gathered in Step 2, 3 and 5. * <p> * If its not clear what the different shapes means, see {@link #add} for reference. */ @Override public void delete(IDeleteContext deleteContext) { List<ContainerShape> innerGroupsOrCompartmentTypesToDelete = new ArrayList<ContainerShape>(); //Step 1 deleteAttachedConnections(deleteContext); //Step 2 Diagram compartmentDiagram = util.getCompartmentTypeDiagramForItsShape((Shape) deleteContext.getPictogramElement(), getDiagram()); if(compartmentDiagram != null) { DeleteContext deleteContextForGroupDiagram = new DeleteContext(compartmentDiagram); deleteContextForGroupDiagram.setMultiDeleteInfo(new MultiDeleteInfo(false, false, 0)); //Step 3 for(Shape shape : compartmentDiagram.getChildren()) { if(shape instanceof ContainerShape) { for(AbstractGroupingFeatureReference reference : groupingFeatureReferences) { if(UIUtil.isShape_IdValue(shape, reference.getShapeIdContainer())) innerGroupsOrCompartmentTypesToDelete.add(UIUtil.getTypeBodyForGroupingFeaturesContainer((ContainerShape) shape, reference.getShapeIdTypebody())); } } } //Step 4 IEditorReference[] openEditors = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getEditorReferences(); for(IEditorReference editorReference : openEditors) { try { if(editorReference.getEditorInput() instanceof DiagramEditorInput) { Resource resource = UIUtil.getResourceFromEditorInput(editorReference.getEditorInput()); Diagram diagramOfEditorInput = UIUtil.getDiagramForResourceOfDiagramEditorInput(resource); if(diagramOfEditorInput.getName().equals(compartmentDiagram.getName())) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeEditor(editorReference.getEditor(false), false); } } catch (PartInitException e) { e.printStackTrace(); } } //Step 5 ContainerShape containerShape = (ContainerShape) ((ContainerShape) deleteContext.getPictogramElement()).getContainer(); DeleteContext deleteContextForAllShapes = new DeleteContext(containerShape); deleteContextForAllShapes.setMultiDeleteInfo(new MultiDeleteInfo(false, false, 0)); //Step 6 for(ContainerShape innerGroupOrCompartmentTypeToDelete : innerGroupsOrCompartmentTypesToDelete) { DeleteContext deleteContextForChildDiagram = new DeleteContext(innerGroupOrCompartmentTypeToDelete); deleteContextForChildDiagram.setMultiDeleteInfo(new MultiDeleteInfo(false, false, 0)); IDeleteFeature deleteFeatureForCompartmentDiagram = getFeatureProvider().getDeleteFeature(deleteContextForChildDiagram); deleteFeatureForCompartmentDiagram.delete(deleteContextForChildDiagram); } super.delete(deleteContextForAllShapes); super.delete(deleteContextForGroupDiagram); updateContainingGroupingFeaturesObject(); } } }