using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.IO; using System.Drawing; using FastReport.Utils; using FastReport.Data; using FastReport.Design.ImportPlugins; namespace FastReport.Design { internal class DesignerClipboard { private readonly Designer designer; public bool CanPaste { get { try { return Clipboard.ContainsData("FastReport") || Clipboard.ContainsText() || Clipboard.ContainsImage(); } catch { return false; } } } public void Cut() { Copy(); designer.cmdDelete.Invoke(); } public void Copy() { // Things that we should consider: // - when copy an object that is selected, we must save its absolute position instead of relative Top, Left. // This is necessary when copying several objects that have different parents. // - when copy a parent object and its child, and both are selected, we must exclude a child from the // selected objects. This is necessary to avoid duplicate copy of the child object - it will be // copied by its parent. if (designer.SelectedObjects == null) return; using (ClipboardParent parent = new ClipboardParent()) { Hashtable bounds = new Hashtable(); parent.PageType = designer.SelectedObjects[0].Page.GetType(); foreach (Base c in designer.Objects) { if (c.IsSelected) { if (c.HasFlag(Flags.CanCopy)) { if (!parent.Contains(c)) { if (c is ComponentBase) { ComponentBase c1 = c as ComponentBase; bounds[c1] = c1.Bounds; c1.SetDesigning(false); c1.Left = c1.AbsLeft; c1.Top = c1.AbsTop; } parent.Objects.Add(c); } } } } using (MemoryStream stream = new MemoryStream()) using (FRWriter writer = new FRWriter()) { writer.SerializeTo = SerializeTo.Clipboard; writer.Write(parent); writer.Save(stream); Clipboard.SetData("FastReport", stream); } // restore components' state foreach (Base c in parent.Objects) { if (c is ComponentBase) { ComponentBase c1 = c as ComponentBase; if (bounds[c1] != null) c1.Bounds = (RectangleF)bounds[c1]; c1.SetDesigning(true); } } } } public void Paste() { if (Clipboard.ContainsData("FastReport")) { using (ClipboardParent parent = new ClipboardParent()) using (MemoryStream stream = Clipboard.GetData("FastReport") as MemoryStream) using (FRReader reader = new FRReader(null)) { reader.DeserializeFrom = SerializeTo.Clipboard; reader.Load(stream); reader.Read(parent); PageBase page = designer.ActiveReportTab.ActivePage; if (page.GetType() == parent.PageType) { designer.ActiveReportTab.ActivePageDesigner.Paste(parent.Objects, InsertFrom.Clipboard); } } } if (Clipboard.ContainsText()) { ObjectCollection list = new ObjectCollection(); TextObject obj = new TextObject(); obj.Text = Clipboard.GetText(); list.Add(obj); designer.ActiveReportTab.ActivePageDesigner.Paste(list, InsertFrom.NewObject); return; } if (Clipboard.ContainsImage()) { ObjectCollection list = new ObjectCollection(); PictureObject pic = new PictureObject(); Image x = Clipboard.GetImage(); pic.Image = x; pic.Width = x.Width; pic.Height = x.Height; list.Add(pic); designer.ActiveReportTab.ActivePageDesigner.Paste(list, InsertFrom.NewObject); return; } } public DesignerClipboard(Designer designer) { this.designer = designer; } static DesignerClipboard() { RegisteredObjects.InternalAdd(typeof(ClipboardParent), "", 0); } private class ClipboardParent : Base { private ObjectCollection objects; private Type pageType; public ObjectCollection Objects { get { return objects; } } public new ObjectCollection AllObjects { get { ObjectCollection result = new ObjectCollection(); foreach (Base c in Objects) EnumObjects(c, result); return result; } } public Type PageType { get { return pageType; } set { pageType = value; } } private void EnumObjects(Base c, ObjectCollection list) { if (c != this) list.Add(c); foreach (Base obj in c.ChildObjects) EnumObjects(obj, list); } public bool Contains(Base obj) { return AllObjects.Contains(obj); } public override void Assign(Base source) { BaseAssign(source); } public override void Serialize(FRWriter writer) { writer.ItemName = Name; writer.WriteStr("PageType", pageType.Name); foreach (Base c in objects) { writer.Write(c); } } public override void Deserialize(FRReader reader) { pageType = RegisteredObjects.FindType(reader.ReadStr("PageType")); while (reader.NextItem()) { Base c = reader.Read() as Base; if (c != null) objects.Add(c); } } public ClipboardParent() { objects = new ObjectCollection(); Name = "ClipboardParent"; } } } }