Beispiel #1
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));
            }
        }