Esempio n. 1
0
        private void PasteSplashData(Transaction transaction, EditableView pnlView)
        {
            DataObject data = (DataObject)Clipboard.GetDataObject();

            byte[] buffer = (byte[])data.GetData("Splash data", false);
            // will be nothing if deserialisation failed
            if (buffer == null)
            {
                Debug.Fail("Deserialisation failed");
                return;
            }
            using (MemoryStream stream = new MemoryStream(buffer, false))
                using (DataReader reader = new DataReader(stream, FileMarkers.ShapeList))
                {
                    List <Datum> list = reader.ReadDataList();
                    // cannot insert objects directly as that would mean pasting twice inserted 2 objects with same ID
                    Mapping    hashIDChanges  = new Mapping();
                    DatumList  newList        = new DatumList();
                    RectangleF bounds         = RectangleF.Empty;     // work out existing bounds of list
                    bool       includesShapes = false;
                    foreach (Datum datum in list)
                    {
                        if (datum is Shape)
                        {
                            // assumed that all shapes need to be created into page
                            Shape create = (Shape)datum.Clone(hashIDChanges);
                            transaction.Create(create);
                            newList.Add(create);
                            Geometry.Extend(ref bounds, create.MinimalBounds);                     // minimal makes, for example, the snapping of axes better
                            includesShapes = true;
                        }
                        else if (datum is SharedBase resource)
                        {
                            // no need to clone these as they are effectively invariant
                            if (CurrentDocument.FindExistingSharedResource <Datum>(resource.ID) == null)
                            {
                                transaction.Edit(CurrentDocument);
                                CurrentDocument.AddSharedResource(resource);
                                // if ID exists in this document it is assumed to be same object
                            }
                        }
                        else if (datum is ButtonStyle buttonStyle)
                        {
                            // as Shape, but don't add to page
                            // if IsShared it is not cloned.  Means styles in multi docs will share ID, which is good as further pasting in will reuse existing style
                            // does need to be added to document share
                            ButtonStyle create;
                            if (buttonStyle.IsShared)
                            {
                                create = buttonStyle;
                                if (CurrentDocument.GetButtonStyle(create.ID) == null)
                                {
                                    CurrentDocument.AddButtonStyle(create);                             // is new to this doc - either by cloning, or
                                    transaction.Create(create);
                                }
                            }
                            else
                            {
                                create = (ButtonStyle)buttonStyle.Clone(hashIDChanges);
                                transaction.Create(create);
                            }
                            newList.Add(create);
                        }
                        else
                        {
                            Debug.Fail("Datum not processed by by Paste: " + datum.TypeByte);
                        }
                    }
                    // want to centre shapes within current area, rather than pasting at original position (which leaves them on top of each other and largely invisible)
                    IShapeContainer container = CurrentPage;
                    if (includesShapes)
                    {
                        if (CurrentPage.SelectedCount == 1 && CurrentPage.SelectedShapes.First().AsContainer != null)
                        {
                            container = CurrentPage.SelectedShapes.First().AsContainer;
                            // but in SAW don't paste automatically into an empty container - chances are it's the item which was just copied!
                            // instead paste into that container's parent
                            if (!container.Any())
                            {
                                container = (container as Shape).Container.AsParentContainer;
                            }
                        }
                        PointF target = pnlView.ViewableArea().Centre();
                        // Or use cursor position if better
                        PointF cursor = pnlView.CursorPositionLocal;
                        // Automatically selects the drawing cursor if split cursors are used
                        // or the container
                        if (((Datum)container).TypeByte == (byte)Shape.Shapes.Container)
                        {
                            target = ((Shape)container).Bounds.Centre();
                        }
                        else if (cursor.X > 0 && cursor.Y > 0 && cursor.X < pnlView.Width && cursor.Y < pnlView.Height)
                        {
                            cursor = pnlView.MouseToData(cursor.ToPoint());
                            // And also need to check the cursor is within the page.  the above just checked it was within the control (there may be some dead area displayed)
                            if (cursor.X < pnlView.ViewableArea().Width&& cursor.Y < pnlView.ViewableArea().Height)
                            {
                                target = cursor;
                            }
                        }
                        target.X -= bounds.Width / 2;
                        target.Y -= bounds.Height / 2;                 // where we want the top left to be
                        if (pnlView.SnapMode == Shape.SnapModes.Grid)
                        {
                            target = CurrentPage.Paper.SnapPoint2(target);
                        }
                        var transform = new TransformMove(target.X - bounds.X, target.Y - bounds.Y);
                        transaction.Edit((Datum)container);
                        foreach (Shape shape in newList.Values.OfType <Shape>())                // of type needed in case other stuff was mixed in with it
                        {
                            container.Contents.Add(shape);
                            shape.Parent = container;
                            shape.ApplyTransformation(transform);
                        }
                        container.FinishedModifyingContents(transaction);
                    }
                    foreach (Datum shape in newList.Values)
                    {
                        try
                        {
                            // order changed
                            shape.UpdateReferencesObjectsCreated(CurrentDocument, reader);
                            shape.UpdateReferencesIDsChanged(hashIDChanges, Globals.Root.CurrentDocument);
                        }
                        catch (Exception ex)
                        {
                            Utilities.LogSubError(ex);
                        }
                    }
                    List <Shape> newShapes = newList.Values.OfType <Shape>().ToList();
                    if (newShapes.Count > 0 && container == CurrentPage)             // don't select the shapes when pasting into a container - leaves the container selected, which allows for more pastes
                    {
                        CurrentPage.SelectOnly(newShapes);
                    }
                    pnlView.InvalidateData(CurrentPage.SelectedRefreshBoundary(), StaticView.InvalidationBuffer.All);
                }
        }