public override void handleMouseDown(Point mouseLocation, 
                                         PlayFrame frame,
                                         PitchScreenCoordConverter converter,
                                         VisualOverlay overlay)
        {
            if (mSelectedPlayer == null)
              {
            PointF pitchCoords = converter.screenToPitchCoords(mouseLocation);

            // No player is yet selected so attempt to find the one closest
            // to the selected spot.
            mSelectedPlayer = frame.GetClosestPlayer(pitchCoords,
                                                 Settings.Default.PlayerDiameter * 2.0f);

            if (mSelectedPlayer == null)
            {
              LinearMovement prevCut = frame.GetClosestCutEnd(pitchCoords,
                                                          Settings.Default.PlayerDiameter * 2.0f);

              if (prevCut != null &&
              prevCut != frame.DiscFrameMovement.ReceivingCut)
              {
            mSelectedPlayer = prevCut.Player;
            overlay.DrawingNewCut = true;
            overlay.CutStart = prevCut;
              }
            }
            else
            {
              overlay.DrawingNewCut = true;
              overlay.CutStart = frame.PlayerMovement[mSelectedPlayer][0];
            }
              }
        }
        public override void handleMouseUp(Point mouseLocation,
                                       PlayFrame frame,
                                       PitchScreenCoordConverter converter,
                                       VisualOverlay overlay)
        {
            frame.AddPlayer(new Player(Team.BLUE_TEAM,
                                 "",
                                 Settings.Default.DefaultPlayerSpeed,
                                 frame.GetNextFreePlayerId(Team.BLUE_TEAM)),
                      converter.screenToPitchCoords(mouseLocation));

              IsComplete = true;
              ModelChanged = true;
        }
 public override void handleMouseUp(Point mouseLocation, 
                                PlayFrame frame,
                                PitchScreenCoordConverter converter,
                                VisualOverlay overlay)
 {
     if (mSelectedPlayer != null)
       {
     frame.PlayerMovement[mSelectedPlayer].Add(
       new LinearMovement(converter.screenToPitchCoords(mouseLocation),
                          100,
                          mSelectedPlayer));
     IsComplete = true;
     ModelChanged = true;
       }
 }
        public override void handleMouseUp(Point mouseLocation, 
                                       PlayFrame frame,
                                       PitchScreenCoordConverter converter,
                                       VisualOverlay overlay)
        {
            PointF pitchCoords = converter.screenToPitchCoords(mouseLocation);

              Player closestPlayer = frame.GetClosestPlayer(pitchCoords,
                                                    Settings.Default.PlayerDiameter);

              if (closestPlayer != null)
              {
            frame.AddDisc(closestPlayer);

            IsComplete = true;
            ModelChanged = true;
              }
        }
        public override void handleMouseUp(Point mouseLocation, 
                                       PlayFrame frame,
                                       PitchScreenCoordConverter converter,
                                       VisualOverlay overlay)
        {
            PointF pitchCoords = converter.screenToPitchCoords(mouseLocation);

              if (mSelectedPlayer != null)
              {
            // This function doesn't necessarily create a trigger but regardless
            // we say that the tool is complete anyway.
            if (frame.MaybeCreateTrigger(pitchCoords,
                                     Settings.Default.PitchLength,
                                     mSelectedPlayer))
            {
              ModelChanged = true;
            }

            IsComplete = true;
              }
        }
        /// <summary>
        /// In order to move an item we catch the mouse down event to decide which
        /// thing has been selected. This function chooses either the selected
        /// cut, trigger or player.
        /// </summary>
        /// <param name="mouseLocation">Screen coordinates.</param>
        /// <param name="frame">Frame currently being designed.</param>
        /// <param name="converter">Used to convert from screen to pitch 
        /// coordinates.</param>
        public override void handleMouseDown(Point mouseLocation, 
                                         PlayFrame frame,
                                         PitchScreenCoordConverter converter,
                                         VisualOverlay overlay)
        {
            PointF pitchCoords = converter.screenToPitchCoords(mouseLocation);

              // Choose closest selected item.
              mSelectedPlayer = frame.GetClosestPlayer(pitchCoords,
                                               SELECTION_MAX_DISTANCE);
              mSelectedCut = frame.GetClosestCutEnd(pitchCoords,
                                              SELECTION_MAX_DISTANCE);
              mSelectedTrigger = frame.GetClosestTrigger(pitchCoords,
                                                 SELECTION_MAX_DISTANCE);
              mIsMovingDiscControlPoint = frame.IsNearControlPoint(pitchCoords,
                                                           SELECTION_MAX_DISTANCE);

              // Note that the ordering of priorities here MUST be the same as the
              // ordering on mouse up.
              if (mSelectedTrigger != null)
              {
            overlay.SelectedTrigger = mSelectedTrigger;
            overlay.TriggerPlayer = mSelectedTrigger.AffectedPlayer;
              }
              else if (mSelectedCut != null)
              {
            overlay.DrawingNewCut = false;
            overlay.CutStart = mSelectedCut;
              }
              else if (mSelectedPlayer != null)
              {
            overlay.SelectedPlayer = mSelectedPlayer;
              }
              else if (mIsMovingDiscControlPoint)
              {
            overlay.MovingDiscControlPoint = true;
              }
        }
        public override void handleMouseUp(Point mouseLocation,
                                       PlayFrame frame,
                                       PitchScreenCoordConverter converter,
                                       VisualOverlay overlay)
        {
            PointF pitchCoords = converter.screenToPitchCoords(mouseLocation);

              LinearMovement cut = frame.GetClosestDiscFlightPoint(pitchCoords,
                                                           Settings.Default.PlayerDiameter);

              if (cut == null)
              {
            // The user has clicked away from any cut. They may want the disc to
            // go to ground so check before setting it.
            DialogResult result = MessageBox.Show(
              "You have not selected a cut to throw to, would you like the " +
              " disc to go here anyway",
              "Throw disc to ground?",
              MessageBoxButtons.YesNo);

            if (result == DialogResult.Yes)
            {
              frame.DiscFrameMovement.AbsoluteFlightPath = pitchCoords;
              frame.DiscFrameMovement.HasMoved = true;

              IsComplete = true;
              ModelChanged = true;
            }
              }
              else
              {
            frame.DiscFrameMovement.ReceivingCut = cut;
            frame.DiscFrameMovement.HasMoved = true;
            IsComplete = true;
            ModelChanged = true;
              }
        }
        /// <summary>
        /// Called whenever the underlying frame changes to redraw the frame.
        /// </summary>
        public void DrawFrame(PlayFrame frame, 
                          Graphics display, 
                          PitchScreenCoordConverter converter,
                          VisualOverlay overlay,
                          Rectangle displayRectangle)
        {
            BufferedGraphicsContext currentContext;
              BufferedGraphics myBuffer;
              currentContext = BufferedGraphicsManager.Current;
              myBuffer = currentContext.Allocate(display,
                                         displayRectangle);
              myBuffer.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
              myBuffer.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
              myBuffer.Graphics.Clear(mBackColor);

              // Draw the pitch itself.
              DrawPitch(myBuffer.Graphics, converter);

              // This moves items around based on what the user is doing.
              // e.g. If a user is dragging a cut at the moment it adds a new cut for
              // the given player.
              PlayFrame adjustableFrame = FrameRenderer.AdjustFrameForOverlay(frame,
                                                                      overlay,
                                                                      converter);

              foreach (Player player in adjustableFrame.PlayerMovement.Keys)
              {
            List<LinearMovement> playerMoves = adjustableFrame.PlayerMovement[player];

            if (playerMoves.Count > 0)
            {

              DrawPlayer(player,
                     playerMoves[0].FinalPosition,
                     myBuffer.Graphics,
                     converter,
                     false);

              if (playerMoves.Count > 1)
              {
            List<Point> cutLocations = new List<Point>();

            foreach (LinearMovement playerMove in playerMoves)
            {
              cutLocations.Add(converter.pitchToScreenCoords(playerMove.FinalPosition));
            }

            myBuffer.Graphics.DrawLines(mCutPen, cutLocations.ToArray<Point>());
              }
            }
              }

              foreach (Trigger trigger in adjustableFrame.Triggers)
              {
            DrawTrigger(myBuffer.Graphics, trigger, converter);
              }

              // Draw the disc after the players because the sprite sits on top of the
              // player sprite who is holding it.
              if (adjustableFrame.DiscFrameMovement.Thrower != null)
              {
            DrawDisc(myBuffer.Graphics,
                 adjustableFrame.DiscFrameMovement.StartPosition(),
                 converter);

            if (adjustableFrame.DiscFrameMovement.HasMoved)
            {
              DrawDiscFlight(myBuffer.Graphics,
                         adjustableFrame.DiscFrameMovement.StartPosition(),
                         adjustableFrame.DiscFrameMovement.ControlPoint,
                         adjustableFrame.DiscFrameMovement.EndPosition(),
                         converter);
            }
              }
              else if (overlay.PlacingDisc)
              {
            // The mouse location is stored in the overlay but we need to pass the
            // pitch coordinates to the drawing function.
            DrawDisc(myBuffer.Graphics,
                 converter.screenToPitchCoords(overlay.MouseLocation),
                 converter);
              }

              myBuffer.Render();
              myBuffer.Dispose();
        }
        /// <summary>
        /// There are two components to the drawing. The first is the data model
        /// which is represented by a single PlayFrame.
        /// 
        /// The second is a visual overlay indicating what the user is current 
        /// doing.
        /// 
        /// This function takes the frame and 'applies' the overlay to it by
        /// creating a deep copy and then moving/adding items as required by
        /// the overlay. For this to work we need to be able to uniquely
        /// reference items in a playmodel by an id (as their refs change on a
        /// deep copy).
        /// </summary>
        /// <param name="frame"></param>
        /// <param name="overlay"></param>
        /// <param name="converter"></param>
        /// <returns></returns>
        private static PlayFrame AdjustFrameForOverlay(PlayFrame frame, 
                                                   VisualOverlay overlay, 
                                                   PitchScreenCoordConverter converter)
        {
            // Take a deep copy of the frame so that we can adjust it based on what
              // visual overlay is required.
              PlayFrame adjustableFrame = frame.Clone();

              PointF pitchCoords = converter.screenToPitchCoords(overlay.MouseLocation);

              // First move any players who need to be.
              if (overlay.SelectedPlayer != null)
              {
            Player movedPlayer = adjustableFrame.GetPlayerById(overlay.SelectedPlayer.UniqueId);
            if (movedPlayer != null)
            {
              adjustableFrame.PlayerMovement[movedPlayer][0].FinalPosition = pitchCoords;
            }
            else
            {
              adjustableFrame.AddPlayer(overlay.SelectedPlayer, pitchCoords);
            }
              }

              // Either a new cut is being drawn or a cut is being moved.
              if (overlay.CutStart != null)
              {
            if (overlay.DrawingNewCut)
            {
              Player cuttingPlayer = adjustableFrame.GetPlayerById(overlay.CutStart.Player.UniqueId);

              adjustableFrame.PlayerMovement[cuttingPlayer].Add(
                                           new LinearMovement(pitchCoords,
                                                              100,
                                                              cuttingPlayer));
            }
            else
            {
              LinearMovement movedCut = adjustableFrame.GetCutById(overlay.CutStart.UniqueId);

              adjustableFrame.ReplaceCut(movedCut, pitchCoords);
            }
              }

              // Check if the user is drawing the disc movement at the moment.
              if (overlay.DrawingDiscMovement)
              {
            adjustableFrame.DiscFrameMovement.AbsoluteFlightPath = pitchCoords;
            adjustableFrame.DiscFrameMovement.HasMoved = true;
              }

              if (overlay.MovingDiscControlPoint)
              {
            adjustableFrame.DiscFrameMovement.ControlPoint = pitchCoords;
              }

              // If there is a trigger being moved then the selected trigger must have
              // it's position updated.
              if (overlay.SelectedTrigger != null)
              {
            CutRatio closestCutPoint = adjustableFrame.GetClosestCutPoint(pitchCoords,
              sPitchLength,
              overlay.SelectedTrigger.AffectedPlayer);

            if (closestCutPoint != null)
            {
              Trigger adjustedTrigger = adjustableFrame.GetTriggerById(overlay.SelectedTrigger.UniqueId);

              if (adjustedTrigger != null)
              {
            adjustedTrigger.CausingCutRatio = closestCutPoint;
              }
            }
              }
              else if (overlay.PlacingTrigger)
              {
            adjustableFrame.MaybeCreateTrigger(pitchCoords,
                                           sPitchLength,
                                           overlay.TriggerPlayer);
              }

              return adjustableFrame;
        }
        /// <summary>
        /// We capture the mouse up event and use it to place whatever it was that
        /// was selected on the mouse down event. If nothing was selected this does
        /// nothing. 
        /// </summary>
        /// <param name="mouseLocation"></param>
        /// <param name="frame"></param>
        /// <param name="converter"></param>
        public override void handleMouseUp(Point mouseLocation,
                                       PlayFrame frame,
                                       PitchScreenCoordConverter converter,
                                       VisualOverlay overlay)
        {
            PointF pitchCoords = converter.screenToPitchCoords(mouseLocation);

              if (mSelectedTrigger != null)
              {
            // If we are moving a trigger then only move it if the position it is
            // being placed is valid.
            if (frame.MaybeCreateTrigger(pitchCoords,
                                     SELECTION_MAX_DISTANCE,
                                     mSelectedTrigger.AffectedPlayer))
            {
              frame.RemoveTrigger(mSelectedTrigger);
              ModelChanged = true;
            }
              }
              else if (mSelectedPlayer != null)
              {
            frame.PlayerMovement[mSelectedPlayer][0].FinalPosition = pitchCoords;
            ModelChanged = true;
              }
              else if (mSelectedCut != null)
              {
            mSelectedCut.FinalPosition = pitchCoords;
            ModelChanged = true;
              }
              else if (mIsMovingDiscControlPoint)
              {
            frame.DiscFrameMovement.ControlPoint = pitchCoords;
            ModelChanged = true;
              }

              // Regardless of whether anything moved the move tool is complete on
              // mouse up.
              mSelectedCut = null;
              mSelectedPlayer = null;
              mSelectedTrigger = null;
              IsComplete = true;
        }