/// <summary> /// Handles property change events for the listed classes of this rule. /// </summary> /// <param name="e">The event args.</param> public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e) { Guard.NotNull(() => e, e); if (e.DomainProperty.Id == PropertySchema.TypeDomainPropertyId) { if (!e.ModelElement.Store.TransactionManager.CurrentTransaction.IsSerializing) { var property = (PropertySchema)e.ModelElement; // Clear any previous DefaultValue of the property. var defaultValueName = Reflector <PropertySchema> .GetPropertyName(x => x.RawDefaultValue); var descriptor = TypeDescriptor.GetProperties(property)[defaultValueName]; descriptor.ResetValue(property); // Repaint the owners compartment shape (to update the custom displayed text value) if (property.Owner != null) { foreach (var shape in PresentationViewsSubject.GetPresentation(property.Owner)) { CompartmentShape compartment = shape as CompartmentShape; if (compartment != null) { compartment.Invalidate(); } } } } } }
/// <summary> /// Repaints the compartment shape for the given element. /// </summary> private static void RepaintCompartmentShape(CustomizableElementSchema element) { Guard.NotNull(() => element, element); foreach (var shape in PresentationViewsSubject.GetPresentation(element)) { CompartmentShape compartment = shape as CompartmentShape; if (compartment != null) { compartment.Invalidate(); } } }
/// <summary> /// Finds the diagram item for the element in teh compartment with given selector. /// </summary> /// <typeparam name="TModelElement">The type of the model element.</typeparam> /// <param name="shape">The shape.</param> /// <param name="elementSelector">The element selector.</param> public static DiagramItem FindDiagramItem <TModelElement>(this CompartmentShape shape, Func <TModelElement, bool> elementSelector) { Guard.NotNull(() => shape, shape); var compartments = shape.NestedChildShapes.OfType <ElementListCompartment>().ToList(); foreach (var compartment in compartments) { for (var diagramItem = compartment.ListField.FindFirstChild(compartment, false); diagramItem != null; diagramItem = compartment.ListField.FindNextChild(diagramItem, false)) { if (diagramItem.RepresentedElements.OfType <TModelElement>().Any(element => elementSelector(element))) { return(diagramItem); } } } return(null); }
public static CompartmentMapping[] DecorateInheritedCompartmentNamedElements(this CompartmentShape shape, CompartmentMapping[] mappings) { Guard.NotNull(() => shape, shape); Guard.NotNull(() => mappings, mappings); // Iterate through each element in the compartment and update its image. foreach (var elementMap in mappings.OfType <ElementListCompartmentMapping>()) { if (elementMap != null) { // Set the image elementMap.ImageGetter = mel => { // Construct a composite image with both Inherited and Customization icons var customizableElement = mel as CustomizableElementSchema; var namedElement = mel as NamedElementSchema; if (namedElement != null) { // Example images for sizing calculation only using (Bitmap inheritedImage = Properties.Resources.Inherited) { using (Bitmap tempCustomizationImage = Properties.Resources.CustomizationInheritedDisabled) { // Calculate composite image Bitmap compositeGlyph = new Bitmap((inheritedImage.Width + tempCustomizationImage.Width + CompositeImageSpacing), System.Math.Max(inheritedImage.Height, tempCustomizationImage.Height)); using (Graphics graphics = Graphics.FromImage(compositeGlyph)) { // Add Inherited icon if (namedElement.IsInheritedFromBase) { // Add customizable icon if (customizableElement != null) { Bitmap customizationImage = GetCustomizationStateImage(customizableElement.IsCustomizationEnabledState); // Draw combined image graphics.DrawImage(inheritedImage, 0, 0); graphics.DrawImage(customizationImage, (inheritedImage.Width + CompositeImageSpacing), 0); } else { // Just draw inherited image graphics.DrawImage(inheritedImage, 0, 0); } } else { if (customizableElement != null) { Bitmap customizationImage = GetCustomizationStateImage(customizableElement.IsCustomizationEnabledState); // Just draw the customiable icon graphics.DrawImage(customizationImage, (inheritedImage.Width + CompositeImageSpacing), 0); } } return(compositeGlyph); } } } } return(null); }; // Set the displayed text elementMap.StringGetter = mel => { // Custom format for Properties var property = mel as PropertySchema; if (property != null) { return(property.GetDisplayText()); } // Custom format for AutomationSettings var automation = mel as AutomationSettingsSchema; if (automation != null) { return(automation.GetDisplayText()); } // Returns default string for other items return(SerializationUtilities.GetElementName(mel)); }; } } return(mappings); }
public static bool SelectModelElement(this DiagramView diagramView, ModelElement modelElement, bool ensureVisible) { // Get the shape element that corresponds to the model element ShapeElement shapeElement = PresentationViewsSubject.GetPresentation(modelElement) .OfType <ShapeElement>() .FirstOrDefault(s => s.Diagram == diagramView.Diagram); if (shapeElement != null) { // Make sure the shape element is visible (because connectors can be hidden) if (!shapeElement.IsVisible) { shapeElement.Show(); } // Create a diagram item for this shape element and select it diagramView.Selection.Set(new DiagramItem(shapeElement)); if (ensureVisible) { diagramView.Selection.EnsureVisible(DiagramClientView.EnsureVisiblePreferences.ScrollIntoViewCenter); diagramView.ZoomAtViewCenter(1); } shapeElement.Invalidate(); return(true); } // If the model element does not have a shape, try to cast it IModelElementCompartment if (modelElement is IModelElementInCompartment compartmentedModelElement) { // Get the parent IModelElementWithCompartments parentModelElement = compartmentedModelElement.ParentModelElement; if (parentModelElement != null) { // Get the compartment that stores the model element CompartmentShape parentShapeElement = PresentationViewsSubject.GetPresentation((ModelElement)parentModelElement) .OfType <CompartmentShape>() .FirstOrDefault(s => s.Diagram == diagramView.Diagram); ElementListCompartment compartment = parentShapeElement?.GetCompartment(compartmentedModelElement.CompartmentName); if (compartment != null) { if (!compartment.IsExpanded) { using (Transaction trans = modelElement.Store.TransactionManager.BeginTransaction("IsExpanded")) { compartment.IsExpanded = true; trans.Commit(); } } // Find the model element in the compartment int index = compartment.Items.IndexOf(modelElement); if (index >= 0) { // Create a diagram item and select it diagramView.Selection.Set(new DiagramItem(compartment, compartment.ListField, new ListItemSubField(index))); if (ensureVisible) { diagramView.Selection.EnsureVisible(DiagramClientView.EnsureVisiblePreferences.ScrollIntoViewCenter); diagramView.ZoomAtViewCenter(1); } compartment.Invalidate(); return(true); } } } } return(false); }
/// <summary> /// Correct the end points of a compartment connection to correspond to the entries of the compartmetn shapes. /// </summary> /// <param name="linkShape">the BinaryLinkShape</param> public void CorrectBinaryLinkShapeEndPoints(BinaryLinkShape linkShape) { CONNECTION connection = (CONNECTION)linkShape.ModelElement; if (connection == null) { return; } // source CompartmentShape fromShape = linkShape.FromShape as CompartmentShape; RectangleD fromRec = linkShape.FromShape.AbsoluteBoundingBox; PointD leftFrom; PointD rightFrom; if (fromShape != null) { // vertical offset on source Double fromOffset = GetVerticalOffset <SOURCE_COMPARTMENT_ENTRY>(fromShape, connection, GetBuilderInstance().IsEntryConnectionSource); leftFrom = new PointD(fromRec.Left, fromRec.Top + fromOffset); rightFrom = new PointD(fromRec.Right, fromRec.Top + fromOffset); } else { leftFrom = rightFrom = fromRec.Center; } // taget CompartmentShape toShape = linkShape.ToShape as CompartmentShape; RectangleD toRec = linkShape.ToShape.AbsoluteBoundingBox; PointD leftTarget; PointD rightTarget; if (toShape != null) { // vertical offset on source Double toOffset = GetVerticalOffset <TARGET_COMPARTMENT_ENTRY>(toShape, connection, GetBuilderInstance().IsEntryConnectionTarget); leftTarget = new PointD(toRec.Left, toRec.Top + toOffset); rightTarget = new PointD(toRec.Right, toRec.Top + toOffset); } else { leftTarget = rightTarget = toRec.Center; } // determinate the connection points ConnectionPoints points = GetConnectionPoints(leftFrom, rightFrom, leftTarget, rightTarget); // set point for source if (fromShape != null) { linkShape.FromEndPoint = points.Source; linkShape.FixedFrom = VGFixedCode.Caller; } // set point for taget if (toShape != null) { linkShape.ToEndPoint = points.Target; linkShape.FixedTo = VGFixedCode.Caller; } }
/// <summary> /// Determinates the vertical offset by searching the compartment entries connected by the given connection /// </summary> /// <typeparam name="T">The type of the compartment entry</typeparam> /// <param name="shape">the CompartmentShape</param> /// <param name="connection">the Connection</param> /// <param name="equaler">a delegate to the method to compare compartment entry with the connection</param> /// <returns></returns> protected virtual double GetVerticalOffset <T>(CompartmentShape shape, CONNECTION connection, IsEntryConnectionSourceTarget <T> equaler) where T : class { // the easy case: the header is meant or the shape is not expanded. so no entry must be searched if (!shape.IsExpanded || equaler(null, connection)) { return(shape.DefaultSize.Height / 2); //the half of the height (the height of a CompartmentShape means only the height of the header) } int elementListCompartmentCount = 0; bool entryFound = false; int entryPositionInListCompartment = -1; ElementListCompartment entryParent = null; // take a look at all children of the compartment shape foreach (DiagramItem item in shape.Children()) { // some of the children are ElementListCompartments if (item.Shape is ElementListCompartment) { // we have to count the ElementListCompartments elementListCompartmentCount++; // if we already found the entry and know the count of elementListCompartmentCount we can exit the foreach loop // I only need the information elementListCompartmentCount is == 1 or > 1, the exact count is irrelevant if (entryFound && elementListCompartmentCount > 1) { break; } ElementListCompartment compartmentList = (ElementListCompartment)item.Shape; int entryInList = 0; if (compartmentList.Items != null) { // now, take a look at the compartment entries of the compartment list foreach (object compartmentEntry in compartmentList.Items) { // is this entry of our type? if (compartmentEntry is T) { // finally check if this entry is targeted by the given connection if (equaler((T)compartmentEntry, connection)) { // hey found... :-) entryFound = true; entryParent = compartmentList; entryPositionInListCompartment = entryInList; break; // there is no need to search in this compartmentList any longer (breaks only the inner foreach loop) } // not found: count and next entryInList++; } } } } } if (entryFound) { // from msdn: IsSingleCompartmentHeaderVisible: Gets the compartment shape and checks to see whether the its header is visible (if there is only one header in the compartment). // to determinate if the compartment header is realy visible we need the IsSingleCompartmentHeaderVisible property and the number of compartment headers in this shape bool elementListCompartmentHeaderVisible = elementListCompartmentCount == 1 ? shape.IsSingleCompartmentHeaderVisible : true; int compartmentHeaderOffset = elementListCompartmentHeaderVisible ? 1 : 0; if (entryParent.IsExpanded) { // the entry is visible double singelElementRowHeight = entryParent.BoundingBox.Height / (entryParent.Items.Count + compartmentHeaderOffset); return(entryParent.BoundingBox.Top + singelElementRowHeight * (entryPositionInListCompartment + 0.6 + compartmentHeaderOffset)); } else { // the entry is not visible // so we target the middel of the compartment header return(entryParent.BoundingBox.Top + entryParent.BoundingBox.Height * 0.5); } } // if we come to this point, we cannot find the entry. just return null. :-/ return(0); }