/// <summary>
 /// moves all the selected shapes according to the mousemove. It is constantly called
 /// as long as both mousemove event and rightDrag event are triggered
 /// </summary>
 /// <param name="x">current x position</param>
 /// <param name="y">current y position</param>
 internal void move(int x, int y)
 {
     try
     {
         PowerPoint.Selection selection;
         if (fillCurrentSelection(out selection))
         {
             lassoAllowed = false;
             PowerPoint.ShapeRange totalShapes = selection.HasChildShapeRange ? selection.ChildShapeRange : selection.ShapeRange;
             if (locked == false)
             {
                 prevXvalue = x;
                 prevYvalue = y;
                 stackMove(totalShapes);
                 locked = true;
             }
             totalShapes.IncrementLeft(x - prevXvalue);
             totalShapes.IncrementTop(y - prevYvalue);
             gestureOK  = false;
             prevXvalue = x;
             prevYvalue = y;
         }
     }
     catch (Exception a)
     {
         setFeedback(a.ToString());
     }
 }
 /// <summary>
 /// tryRotate is called when the drag event and the mousemove event happen together.
 /// It rotates all the shapes selected according to the mouse movement
 /// </summary>
 /// <param name="x">x coordinate</param>
 /// <param name="y">y coordinate</param>
 internal void tryRotate(int x, int y)
 {
     try
     {
         PowerPoint.Selection selection;
         if (!fillCurrentSelection(out selection))
         {
             return;
         }
         PowerPoint.ShapeRange totalShapes = selection.HasChildShapeRange ? selection.ChildShapeRange : selection.ShapeRange;
         float angle = 2F; // 2;
         if (locked == false)
         {
             double innerX, innerY;
             foreach (PowerPoint.Shape rotateShape in totalShapes)
             {
                 innerX = rotateShape.Left + (0.4 * rotateShape.Width);
                 innerY = rotateShape.Top + (0.4 * rotateShape.Height);
                 Rectangle innerRec = new Rectangle((int)innerX, (int)innerY,
                                                    (int)(0.2 * rotateShape.Width), (int)(0.2 * rotateShape.Height));
                 if (innerRec.Contains(x, y))
                 {
                     rotate    = true;
                     locked    = true;
                     gestureOK = false;
                     prevY     = y;
                     prevX     = x;
                     break;
                 }
             }
         }
         if (rotate)
         {
             foreach (PowerPoint.Shape rotateShape in totalShapes)
             {
                 if (y > prevY)
                 {
                     rotateShape.IncrementRotation(angle);
                 }
                 else
                 {
                     rotateShape.IncrementRotation(0 - angle);
                 }
             }
             resizeAllowed = false;
             prevY         = y;
         }
     }
     catch (Exception e)
     {
         // Code accounts for no selection, so this means something bad happened
         debugExceptionMessage("tryRotate", e);
     }
 }
        private void stackMoveEnd(PowerPoint.ShapeRange totalShapes)
        {
            List <ShapeAttributes> clones = new List <ShapeAttributes>();

            foreach (PowerPoint.Shape s in totalShapes)
            {
                ShapeAttributes sa = new ShapeAttributes(s);
                clones.Add(sa);
            }
            undoStack.Push(clones);
            undoStack.Push("Move");
        }
        /// <summary>
        /// rightClick is only called when a right click is recognized AND when there is a current
        /// selection on the slide.
        /// </summary>
        /// <param name="shapes">a collection of shapes</param>
        internal void rightClick(PowerPoint.ShapeRange shapes)
        {
            PowerPoint.Shape clickedShape = null;
            try
            {
                clickedShape = pptController.findShape(X, Y);
            }
            catch (Exception e)
            {
                debugExceptionMessage("right click", e);
                return;
            }

            // If the click wasn't on any shape, just return
            if (clickedShape == null)
            {
                PowerPoint.Selection selection = pptController.pptApp.ActiveWindow.Selection;
                selection.Unselect();
                return;
            }
            //  Then, if it falls on an unselected shape, select that and return
            //if(shapes.
            bool inRange = false; // first assume the cursor is NOT in range of any of the shapes

            try
            {
                foreach (PowerPoint.Shape shape in shapes)
                {
                    // if the cursor falls within the range of ANY of the shape selected
                    if (clickedShape.Equals(shape))
                    {
                        inRange = true;
                    }
                }
                if (inRange == false) // if the cursor does not fall within the range of any shapes currently selected
                {
                    // then try to see if it falls on top of a shape that is not currently selected,
                    // if so, select that one
                    PowerPoint.Shape shape = pptController.findShape(X, Y);
                    shape.Select(Microsoft.Office.Core.MsoTriState.msoTrue);
                }
            }
            catch (Exception e)
            {
                // this exception should only be thrown when the right click does NOT fall on top of any
                // shapes, so the select method complains. In that case, this does not need to do anything
                // However, it's now checked for above so we should know when it happens
                debugExceptionMessage("rightclick", e);
            }
        }
        }//end paste()

        #endregion


        #region Misc

        /// <summary>
        /// add the object on which the gesture started to the current selection
        /// </summary>
        /// <param name="allShapes">a list of all shapes on the current slide</param>
        private void multiSelect(List <PowerPoint.Shape> allShapes)
        {
            PowerPoint.Shape shape = pptController.findShape(X, Y);
            if (shape.Equals(null))
            {
                setFeedback("No shape selected - nothing added to selection");
                return;
            }
            PowerPoint.Selection selection;
            try
            {
                // if the selection is empty, add the shape anyways
                if (!fillCurrentSelection(out selection))
                {
                    shape.Select(MsoTriState.msoTrue);
                    setFeedback("Added object to previously empty selection");
                }
                else
                {
                    //else, get the selected shapes. I don't know what's the deal with ChildShapeRange.
                    selection = pptController.pptApp.ActiveWindow.Selection;

                    PowerPoint.ShapeRange shapes = selection.HasChildShapeRange ? selection.ChildShapeRange : selection.ShapeRange;
                    //allShapes = selection.HasChildShapeRange ? selection.ChildShapeRange : selection.ShapeRange;

                    // TODO: FIX: why do we need to reselect everything? Figure out why and replace if possible
                    foreach (PowerPoint.Shape s in shapes)
                    {
                        s.Select(MsoTriState.msoFalse); // why does FALSE actually select the object?!?
                    }

                    shape.Select(MsoTriState.msoFalse);

                    setFeedback("New object added to selection");
                }
            }
            catch (Exception ex)
            {
                debugExceptionMessage("case right, for removing exception", ex);
                shape.Select(MsoTriState.msoFalse);
                setFeedback("Added object to previously empty selection");
                //   setFeedback("No currently selection, please select at least one object first");
            }
        }//multiSelect()
        }//addLine()

        // sets the rotation of all selected shapes to 0 (unrotated).
        internal void rotateReset()
        {
            PowerPoint.Selection  selection;
            PowerPoint.ShapeRange selectedShapes = null;
            if (fillCurrentSelection(out selection))
            {
                selectedShapes = selection.HasChildShapeRange ? selection.ChildShapeRange : selection.ShapeRange;
            }
            else
            {
                setFeedback("Selection empty - nothing to rotate");
                return;
            }
            List <PowerPoint.Shape> rotated = new List <PowerPoint.Shape>(); // keep track of shapes for undo
            List <float>            angle   = new List <float>();

            foreach (PowerPoint.Shape s in selectedShapes)
            {
                angle.Add(s.Rotation);
                s.Rotation = 0;
                rotated.Add(s);
            }
            stackChangeRotation(angle, rotated);
        }