public static DatumList CloneList(IEnumerable <Datum> original, Document document) { // makes a copy of all of the objects in the list, returning the new list // contained objects are cloned, but don't appear in the list (they do appear in the ID lookup table) // the new list will also contain any necessary objects referenced by these (e.g. textures) // links between objects will be updated if both halves are in the list, or broken if only the linking object (e.g. connector, paint splat) // is in the list DatumList newList = new DatumList(); Mapping mapID = new Mapping(); // lookup table from old to new IDs foreach (Datum data in original.Where(x => x != null)) // will ignore any missing objects in list { if (!mapID.ContainsKey(data.ID)) // check is needed because containers will include contents, and original list could include both container and content if selected from page (select all especially) { newList.Add(data.Clone(mapID)); } } foreach (Datum data in original.Where(x => x != null)) { // It would have been much easier to just iterate colNew, but we can't because the line below might modify the list mapID[data.ID].AddRequiredReferencesRecurseToContained(newList.Add, mapID); } foreach (Datum shape in newList.Values) { shape.UpdateReferencesIDsChanged(mapID, document); } return(newList); }
public override void CopyFrom(Datum other, CopyDepth depth, Mapping mapID) { base.CopyFrom(other, depth, mapID); MaskedImage mask = (MaskedImage)other; // largely copied fom scriptable Debug.Assert((Image == null) == (MaskShape == null)); if (depth == CopyDepth.Transform && MaskShape != null) // m_Mask and m_Image will either both be null or neither { // first time must copy reference, below if (MaskShape != mask.MaskShape) { MaskShape?.CopyFrom(mask.MaskShape, depth, mapID); } if (Image != mask.Image) { Image?.CopyFrom(mask.Image, depth, mapID); } } else // if (depth == CopyDepth.Duplicate) { if (mapID?.ContainsKey(mask.MaskShape.ID) ?? false) { MaskShape = (Lined)mapID[mask.MaskShape.ID]; } else { MaskShape = (Lined)mask.MaskShape.Clone(mapID ?? new Mapping()); // use actual mapID if there is one, otherwise need a real one as Container aspects of Item don't like Ignore } MaskShape.Parent = this; if (mapID?.ContainsKey(mask.Image.ID) ?? false) { Image = (ImportedImage)mapID[mask.Image.ID]; } else { Image = (ImportedImage)mask.Image.Clone(mapID ?? new Mapping()); // use actual mapID if there is one, otherwise need a real one as Container aspects of Item don't like Ignore } Image.Parent = this; } m_Bounds = RectangleF.Empty; }
public override void CopyFrom(Datum other, CopyDepth depth, Mapping mapID) { // this is slightly flaky for Undo still, in that the scriptable must be put into the transaction FIRST // (otherwise it will refernce differing copies of the contained element) base.CopyFrom(other, depth, mapID); Scriptable scriptable = (Scriptable)other; if (depth > CopyDepth.Transform) { CopyPresentationFrom(scriptable, false); } //Debug.WriteLine("Scriptable.CopyFrom, depth=" + depth + " ID=" + scriptable.SAWID); // contained element. Works like ShapeStack containment - Element is tightly bound within this if (depth == CopyDepth.Transform && Element != null) { // first time must copy reference, below if (Element != scriptable.Element) { Element?.CopyFrom(scriptable.Element, depth, mapID); } } else // if (depth == CopyDepth.Duplicate) { if (mapID?.ContainsKey(scriptable.Element.ID) ?? false) { Element = (Shape)mapID[scriptable.Element.ID]; } else { Element = (Shape)scriptable.Element.Clone(mapID ?? new Mapping()); // use actual mapID if there is one, otherwise need a real one as Container aspects of Item don't like Ignore } Element.Parent = this; } //else //{ // Element = scriptable.Element; //} ////else if (depth == CopyDepth.Duplicate) ////{ //// if (mapID == null) //// mapID = Mapping.Ignore; //// Element = (Shape)scriptable.Element.Clone(mapID); //// Element.Parent = this; ////} //else //{ // // undo requires all shapes are copied, because they could later be edited by styling changes // //Element = Shape.CreateShape(scriptable.Element.ShapeCode); // <- this is inadequate as it doesn't clone contents of the items which leaves some reference problems // //Element.CopyFrom(scriptable.Element, depth, null); // Element = (Shape)scriptable.Element.Clone(mapID ?? new Mapping()); // use actual mapID if there is one, otherwise need a real one as Container aspects of Item don't like Ignore // Element.Parent = this; //} // other fields: if (depth > CopyDepth.Transform) { SAWID = scriptable.SAWID; Popup = scriptable.Popup; Shown = scriptable.Shown; AutoRepeat = scriptable.AutoRepeat; RepeatTimeout = scriptable.RepeatTimeout; for (int i = 0; i < Scripts.Length; i++) { Scripts[i] = scriptable.Scripts[i]?.Clone(); } } m_Bounds = RectangleF.Empty; // because content may have moved - especially on Undo }