Beispiel #1
0
        private void Render()
        {
            if (tracePoints != null && tracePoints.Count > 2)
            {
                PointF[] polygon = CreateSelectionPolygon();

                if (polygon.Length > 2)
                {
                    DocumentWorkspace.ResetOutlineWhiteOpacity();
                    this.newSelectionRenderer.ResetOutlineWhiteOpacity();

                    Selection.SetContinuation(polygon, this.combineMode);

                    CombineMode cm;

                    if (SelectionMode == CombineMode.Replace)
                    {
                        cm = CombineMode.Replace;
                    }
                    else
                    {
                        cm = CombineMode.Xor;
                    }

                    this.newSelection.SetContinuation(polygon, cm);

                    Update();
                }
            }
        }
Beispiel #2
0
        protected override void OnPulse()
        {
            if (this.tracking)
            {
                DocumentWorkspace.ResetOutlineWhiteOpacity();
            }

            base.OnPulse();
        }
Beispiel #3
0
        protected override void OnPulse()
        {
            if (Tracking)
            {
                DocumentWorkspace.ResetOutlineWhiteOpacity();
                NewSelectionRenderer.ResetOutlineWhiteOpacity();
            }

            base.OnPulse();
        }
Beispiel #4
0
        private void Render()
        {
            if (tracePoints != null && tracePoints.Count > 2)
            {
                PointF[] polygon = CreateSelectionPolygon();

                if (polygon.Length > 2)
                {
                    DocumentWorkspace.ResetOutlineWhiteOpacity();
                    Selection.SetContinuation(polygon, this.combineMode);
                    Update();
                }
            }
        }
Beispiel #5
0
        private void OnMouseMoveImpl(MouseEventArgs e, StringBuilder sbLogger)
        {
            if (!this.tracking)
            {
                sbLogger.Append("1 ");
                Cursor cursor = this.moveToolCursor;

                for (int i = 0; i < this.moveNubs.Length; ++i)
                {
                    sbLogger.Append("2 ");
                    MoveNubRenderer nub = this.moveNubs[i];
                    sbLogger.Append("3 ");

                    if (nub.Visible && nub.IsPointTouching(new Point(e.X, e.Y), true))
                    {
                        sbLogger.Append("4 ");
                        cursor = this.handCursor;
                        break;
                    }
                }

                this.Cursor = cursor;
                sbLogger.Append("5 ");
            }
            else
            {
                sbLogger.Append("6 ");
                if (this.context.currentMode != Mode.Translate)
                {
                    sbLogger.Append("7 ");
                    this.Cursor = this.handCursorMouseDown;
                }

                sbLogger.Append("8 ");
                Point newMouseXY = new Point(e.X, e.Y);
                Point newOffset  = new Point(newMouseXY.X - context.startMouseXY.X, newMouseXY.Y - context.startMouseXY.Y);

                PreRender();

                this.dontDrop = true;

                sbLogger.Append("9 ");
                Selection.PerformChanging();

                using (Matrix translateMatrix = new Matrix())
                {
                    RectangleF rect;
                    translateMatrix.Reset();

                    if (this.context.baseTransform != null)
                    {
                        Selection.SetInterimTransform(this.context.baseTransform);
                    }

                    Matrix interim = Selection.GetInterimTransformCopy();

                    switch (this.context.currentMode)
                    {
                    case Mode.Translate:
                        translateMatrix.Translate((float)newOffset.X, (float)newOffset.Y, MatrixOrder.Append);
                        break;

                    case Mode.Rotate:
                        rect = this.context.liftedBounds;
                        PointF center = new PointF(rect.X + (rect.Width / 2.0f), rect.Y + (rect.Height / 2.0f));
                        center = Utility.TransformOnePoint(interim, center);
                        double theta1     = Math.Atan2(context.startMouseXY.Y - center.Y, context.startMouseXY.X - center.X);
                        double theta2     = Math.Atan2(e.Y - center.Y, e.X - center.X);
                        double thetaDelta = theta2 - theta1;
                        this.angleDelta = (float)(thetaDelta * (180.0f / Math.PI));
                        float angle = this.context.startAngle + this.angleDelta;

                        if ((ModifierKeys & Keys.Shift) != 0)
                        {
                            angle      = ConstrainAngle(angle);
                            angleDelta = angle - this.context.startAngle;
                        }

                        translateMatrix.RotateAt(angleDelta, center, MatrixOrder.Append);
                        this.rotateNub.Location = center;
                        this.rotateNub.Angle    = this.context.startAngle + angleDelta;
                        break;

                    case Mode.Scale:
                        PointF xyAxes = GetEdgeVector(this.context.startEdge);
                        PointF xAxis  = new PointF(xyAxes.X, 0);
                        PointF yAxis  = new PointF(0, xyAxes.Y);
                        PointF edgeX  = Utility.TransformOneVector(interim, xAxis);
                        PointF edgeY  = Utility.TransformOneVector(interim, yAxis);
                        PointF edgeXN = Utility.NormalizeVector2(edgeX);
                        PointF edgeYN = Utility.NormalizeVector2(edgeY);

                        PointF xu;
                        float  xulen;
                        PointF xv;
                        Utility.GetProjection((PointF)newOffset, edgeXN, out xu, out xulen, out xv);

                        PointF yu;
                        float  yulen;
                        PointF yv;
                        Utility.GetProjection((PointF)newOffset, edgeYN, out yu, out yulen, out yv);

                        PdnGraphicsPath startPath2 = this.context.startPath.Clone();
                        RectangleF      sp2Bounds  = startPath2.GetBounds();

                        PointF sp2BoundsCenter = new PointF((sp2Bounds.Left + sp2Bounds.Right) / 2.0f,
                                                            (sp2Bounds.Top + sp2Bounds.Bottom) / 2.0f);

                        float tAngle    = Utility.GetAngleOfTransform(interim);
                        bool  isFlipped = Utility.IsTransformFlipped(interim);

                        using (Matrix spm = new Matrix())
                        {
                            spm.Reset();
                            spm.RotateAt(-tAngle, sp2BoundsCenter, MatrixOrder.Append);
                            translateMatrix.RotateAt(-tAngle, sp2BoundsCenter, MatrixOrder.Append);
                            startPath2.Transform(spm);
                        }

                        RectangleF spBounds2 = startPath2.GetBounds();

                        startPath2.Dispose();
                        startPath2 = null;

                        float xTranslate;
                        float yTranslate;
                        bool  allowConstrain;

                        Edge theEdge = this.context.startEdge;

                        // If the transform is flipped, then GetTransformAngle will return 180 degrees
                        // even though no rotation has actually taken place. Thus we have to scratch
                        // our head and go "hmm, let's make some adjustments to this." Otherwise stretching
                        // the top and bottom nubs goes in the wrong direction.
                        if (isFlipped)
                        {
                            theEdge = FlipEdgeVertically(theEdge);
                        }

                        switch (theEdge)
                        {
                        default:
                            throw new InvalidEnumArgumentException();

                        case Edge.TopLeft:
                            allowConstrain = true;
                            xTranslate     = -spBounds2.X - spBounds2.Width;
                            yTranslate     = -spBounds2.Y - spBounds2.Height;
                            break;

                        case Edge.Top:
                            allowConstrain = false;
                            xTranslate     = 0;
                            yTranslate     = -spBounds2.Y - spBounds2.Height;
                            break;

                        case Edge.TopRight:
                            allowConstrain = true;
                            xTranslate     = -spBounds2.X;
                            yTranslate     = -spBounds2.Y - spBounds2.Height;
                            break;

                        case Edge.Left:
                            allowConstrain = false;
                            xTranslate     = -spBounds2.X - spBounds2.Width;
                            yTranslate     = 0;
                            break;

                        case Edge.Right:
                            allowConstrain = false;
                            xTranslate     = -spBounds2.X;
                            yTranslate     = 0;
                            break;

                        case Edge.BottomLeft:
                            allowConstrain = true;
                            xTranslate     = -spBounds2.X - spBounds2.Width;
                            yTranslate     = -spBounds2.Y;
                            break;

                        case Edge.Bottom:
                            allowConstrain = false;
                            xTranslate     = 0;
                            yTranslate     = -spBounds2.Y;
                            break;

                        case Edge.BottomRight:
                            allowConstrain = true;
                            xTranslate     = -spBounds2.X;
                            yTranslate     = -spBounds2.Y;
                            break;
                        }

                        translateMatrix.Translate(xTranslate, yTranslate, MatrixOrder.Append);

                        float newWidth  = spBounds2.Width + xulen;
                        float newHeight = spBounds2.Height + yulen;
                        float xScale    = newWidth / spBounds2.Width;
                        float yScale    = newHeight / spBounds2.Height;

                        if (allowConstrain && (this.ModifierKeys & Keys.Shift) != 0)
                        {
                            ConstrainScaling(this.context.liftedBounds, spBounds2.Width, spBounds2.Height,
                                             newWidth, newHeight, out xScale, out yScale);
                        }

                        translateMatrix.Scale(xScale, yScale, MatrixOrder.Append);
                        translateMatrix.Translate(-xTranslate, -yTranslate, MatrixOrder.Append);
                        translateMatrix.RotateAt(+tAngle, sp2BoundsCenter, MatrixOrder.Append);

                        break;

                    default:
                        throw new InvalidEnumArgumentException();
                    }

                    this.context.deltaTransform.Reset();
                    this.context.deltaTransform.Multiply(this.context.liftTransform, MatrixOrder.Append);
                    this.context.deltaTransform.Multiply(translateMatrix, MatrixOrder.Append);

                    translateMatrix.Multiply(this.context.baseTransform, MatrixOrder.Prepend);

                    Selection.SetInterimTransform(translateMatrix);

                    interim.Dispose();
                    interim = null;
                }

                // advertise our angle of rotation to any host (i.e. mainform) that might want to use that information
                this.hostShouldShowAngle = this.rotateNub.Visible;
                this.hostAngle           = -this.rotateNub.Angle;

                Selection.PerformChanged();
                dontDrop = false;

                Render(newOffset, true);
                Update();

                sbLogger.Append("a ");
                this.context.offset = newOffset;

                sbLogger.Append("b ");

                if (this.enableOutline)
                {
                    DocumentWorkspace.ResetOutlineWhiteOpacity();
                }

                sbLogger.Append("c ");
            }

            sbLogger.Append("d ");
        }
Beispiel #6
0
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (tracking)
            {
                return;
            }

            bool determinedMoveMode = false;
            Mode newMode            = Mode.Translate;
            Edge newEdge            = Edge.None;

            if (Selection.IsEmpty)
            {
                SelectionHistoryMemento shm = new SelectionHistoryMemento(
                    HistoryFunctions.SelectAllFunction.StaticName,
                    PdnResources.GetImageResource("Icons.MenuEditSelectAllIcon.png"),
                    DocumentWorkspace);

                DocumentWorkspace.History.PushNewMemento(shm);

                DocumentWorkspace.Selection.PerformChanging();
                DocumentWorkspace.Selection.Reset();
                DocumentWorkspace.Selection.SetContinuation(Document.Bounds, CombineMode.Replace);
                DocumentWorkspace.Selection.CommitContinuation();
                DocumentWorkspace.Selection.PerformChanged();

                if (e.Button == MouseButtons.Right)
                {
                    newMode = Mode.Rotate;
                }
                else
                {
                    newMode = Mode.Translate;
                }

                newEdge = Edge.None;

                determinedMoveMode = true;
            }

            DocumentWorkspace.EnableSelectionOutline = this.enableOutline;

            if (!context.lifted)
            {
                Lift(e);
            }

            PushContextHistoryMemento();

            if (!determinedMoveMode)
            {
                DetermineMoveMode(e, out newMode, out newEdge);
                determinedMoveMode = true;
            }

            if (this.context.deltaTransform != null)
            {
                this.context.deltaTransform.Dispose();
                this.context.deltaTransform = null;
            }

            this.context.deltaTransform = new Matrix();
            this.context.deltaTransform.Reset();

            if (newMode == Mode.Translate ||
                newMode == Mode.Scale ||
                newMode != this.context.currentMode ||
                newMode == Mode.Rotate)
            {
                this.context.startBounds  = Selection.GetBoundsF();
                this.context.startMouseXY = new Point(e.X, e.Y);
                this.context.offset       = new Point(0, 0);

                if (this.context.baseTransform != null)
                {
                    this.context.baseTransform.Dispose();
                    this.context.baseTransform = null;
                }

                this.context.baseTransform = Selection.GetInterimTransformCopy();
            }

            this.context.startEdge   = newEdge;
            this.context.currentMode = newMode;
            PositionNubs(this.context.currentMode);

            tracking = true;
            this.rotateNub.Visible = (this.context.currentMode == Mode.Rotate);

            if (this.context.startPath != null)
            {
                this.context.startPath.Dispose();
                this.context.startPath = null;
            }

            this.context.startPath  = Selection.CreatePath();
            this.context.startAngle = Utility.GetAngleOfTransform(Selection.GetInterimTransformReadOnly());

            SelectionHistoryMemento sha1 = new SelectionHistoryMemento(this.Name, this.Image, this.DocumentWorkspace);

            this.currentHistoryMementos.Add(sha1);

            OnMouseMove(e);

            if (this.enableOutline)
            {
                DocumentWorkspace.ResetOutlineWhiteOpacity();
            }
        }
Beispiel #7
0
        private void Done()
        {
            if (tracking)
            {
                // Truth table for what we should do based on three flags:
                //  append  | moved | tooQuick | result                             | optimized expression to yield true
                // ---------+-------+----------+-----------------------------------------------------------------------
                //     F    |   T   |    T     | clear selection                    | !append && (!moved || tooQuick)
                //     F    |   T   |    F     | emit new selected area             | !append && moved && !tooQuick
                //     F    |   F   |    T     | clear selection                    | !append && (!moved || tooQuick)
                //     F    |   F   |    F     | clear selection                    | !append && (!moved || tooQuick)
                //     T    |   T   |    T     | append to selection                | append && moved
                //     T    |   T   |    F     | append to selection                | append && moved
                //     T    |   F   |    T     | reset selection                    | append && !moved
                //     T    |   F   |    F     | reset selection                    | append && !moved
                //
                // append   --> If the user was holding control, then true. Else false.
                // moved    --> If they never moved the mouse, false. Else true.
                // tooQuick --> If they held the mouse button down for more than 50ms, false. Else true.
                //
                // "Clear selection" means to result in no selected area. If the selection area was previously empty,
                //    then no HistoryMemento is emitted. Otherwise a Deselect HistoryMemento is emitted.
                //
                // "Reset selection" means to reset the selected area to how it was before interaction with the tool,
                //    without a HistoryMemento.

                PointF[] polygon = CreateSelectionPolygon();
                this.hasMoved &= (polygon.Length > 1);

                // They were "too quick" if they weren't doing a selection for more than 50ms
                // This takes care of the case where someone wants to click to deselect, but accidentally moves
                // the mouse. This happens VERY frequently.
                bool tooQuick = Utility.TicksToMs((DateTime.Now - startTime).Ticks) <= 50;

                // If their selection was completedly out of bounds, it will be clipped
                bool clipped = (polygon.Length == 0);

                // What the user drew had no effect on the slection, e.g. subtraction where there was nothing in the first place
                bool noEffect = false;

                WhatToDo whatToDo;

                // If their selection gets completely clipped (i.e. outside the image canvas),
                // then result in a no-op
                if (append)
                {
                    if (!hasMoved || clipped || noEffect)
                    {
                        whatToDo = WhatToDo.Reset;
                    }
                    else
                    {
                        whatToDo = WhatToDo.Emit;
                    }
                }
                else
                {
                    if (hasMoved && !tooQuick && !clipped && !noEffect)
                    {
                        whatToDo = WhatToDo.Emit;
                    }
                    else
                    {
                        whatToDo = WhatToDo.Clear;
                    }
                }

                switch (whatToDo)
                {
                case WhatToDo.Clear:
                    if (wasNotEmpty)
                    {
                        // emit a deselect history action
                        undoAction.Name  = DeselectFunction.StaticName;
                        undoAction.Image = DeselectFunction.StaticImage;
                        HistoryStack.PushNewMemento(undoAction);
                    }

                    Selection.Reset();
                    break;

                case WhatToDo.Emit:
                    // emit newly selected area
                    undoAction.Name = this.Name;
                    HistoryStack.PushNewMemento(undoAction);
                    Selection.CommitContinuation();
                    break;

                case WhatToDo.Reset:
                    // reset selection, no HistoryMemento
                    Selection.ResetContinuation();
                    break;
                }

                DocumentWorkspace.ResetOutlineWhiteOpacity();
                this.newSelectionRenderer.ResetOutlineWhiteOpacity();
                this.newSelection.Reset();
                this.newSelectionRenderer.Visible = false;

                this.tracking = false;

                DocumentWorkspace.EnableSelectionOutline = true;
                DocumentWorkspace.InvalidateSurface(Utility.RoundRectangle(DocumentWorkspace.VisibleDocumentRectangleF));
            }
        }