//Calculates end point for object movement
        public void OnMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            _Canvas = sender as Canvas;

            dragEnd[0] = e.GetPosition(_Canvas).X;
            dragEnd[1] = e.GetPosition(_Canvas).Y;

            if (_DragSelection)
            {
                if (dragBox != null)
                {
                    double width  = LerpMath.CalculateDelta(dragOrigin[0], dragEnd[0]);
                    double height = LerpMath.CalculateDelta(dragOrigin[1], dragEnd[1]);

                    width  = (width < 0) ? width * -1 : width;
                    height = (height < 0) ? height * -1 : height;

                    dragBox.Width  = width;
                    dragBox.Height = height;

                    double offsetX = (dragOrigin[0] < dragEnd[0]) ? dragOrigin[0] : dragEnd[0];
                    double offsetY = (dragOrigin[1] < dragEnd[1]) ? dragOrigin[1] : dragEnd[1];

                    Canvas.SetLeft(dragBox, offsetX);
                    Canvas.SetTop(dragBox, offsetY);
                }
                else
                {
                    Rectangle rect = new Rectangle();
                    rect.IsHitTestVisible = false;
                    rect.Fill             = new SolidColorBrush(Colors.Blue);
                    rect.Opacity          = 0.4;
                    rect.Name             = "dragArea";

                    rect.Width  = LerpMath.CalculateDelta(dragOrigin[0], dragEnd[0]);
                    rect.Height = LerpMath.CalculateDelta(dragOrigin[1], dragEnd[1]);

                    Items.Add(rect);
                    dragBox = rect;

                    Canvas.SetLeft(rect, dragOrigin[0]);
                    Canvas.SetTop(rect, dragOrigin[1]);

                    dragIndex = Items.Count - 1;
                }
            }
        }
        //TODO: Fix adorners not being drawn correctly after moving if scale != 1 or being redrawn on scale change

        /// <summary>
        /// Adds adorner to items in list
        /// </summary>
        /// <param name="modifiedList">List of item Points</param>
        private void RenderAdorner(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add && selectedItems.Count > 0)
            {
                ClearAdorner();

                Point pos;
                var   item = Items[0];

                if (selectedPos.Count > 1)
                {
                    pos = LerpMath.CalculateAverage(selectedPos);
                }
                else
                {
                    pos = selectedPos[0];
                }

                var myAdornerLayer = AdornerLayer.GetAdornerLayer(item);
                RenderDragHandles(item, myAdornerLayer, camera.OffsetPosition(pos, true));

                for (int i = 0; i < selectedPos.Count; i++)
                {
                    for (int j = 0; j < Items.Count; j++)
                    {
                        if (Items[j] is Rectangle)
                        {
                            var   listItem = Items[j];
                            Point itemPos  = camera.OffsetPosition(new Point(Canvas.GetLeft(listItem), Canvas.GetTop(listItem)));

                            if (LerpMath.CalculateDelta(selectedPos[i].X, itemPos.X) <= 2.5 && LerpMath.CalculateDelta(selectedPos[i].Y, itemPos.Y) <= 2.5)
                            {
                                RenderSelection(listItem, AdornerLayer.GetAdornerLayer(item));
                                break;
                            }
                        }
                    }
                }
            }
            else
            {
                ClearAdorner();
            }
        }
        /// <summary>
        /// Calculates delta movement
        /// </summary>
        /// <param name="model"></param>
        private void CalculatePosition(CurveGraphModel model)
        {
            Point dest;

            if (!MiddleMouseUsed)
            {
                dest = LerpMath.CalculateDelta(new Point(dragOrigin[0], dragOrigin[1]), new Point(dragEnd[0], dragEnd[1]), false, true);
            }
            else
            {
                dest = LerpMath.CalculateDelta(new Point(dragOrigin[2], dragOrigin[3]), new Point(dragEnd[0], dragEnd[1]), false, true);
                double offsetMultiplier = 0.55;

                dest = new Point(
                    (dest.X * offsetMultiplier),
                    (dest.Y * offsetMultiplier)
                    );

                MiddleMouseUsed = false;
                dragDirection   = 0;
            }

            movementQueue.Add(new Point(dest.X, dest.Y));
        }
        private void HandleSelection(object sender, MouseButtonEventArgs e)
        {
            //If rectangle hit
            if (e.OriginalSource.GetType() == typeof(Rectangle))
            {
                if (selectedItems.Count > 0 && !_shift)
                {
                    ClearItems();
                }

                Rectangle rect = (Rectangle)e.OriginalSource;
                selectedPos.Add(camera.OffsetPosition(new Point(Canvas.GetLeft(rect), Canvas.GetTop(rect))));

                if (rect != null && String.IsNullOrEmpty(rect.Name))
                {
                    var myAdornerLayer = AdornerLayer.GetAdornerLayer(rect);

                    if (myAdornerLayer != null)
                    {
                        if (selectedPos.Count > 1)
                        {
                            Point avgPosition = LerpMath.CalculateAverage(selectedPos);

                            Point offset = LerpMath.CalculateDelta(
                                modelitems.Item.Curve[selectedItems[0].Item1].Points[selectedItems[0].Item2],
                                avgPosition,
                                true
                                );
                        }
                        else
                        {
                            RenderSelection(rect, myAdornerLayer);
                        }

                        var matches = Regex.Matches(rect.Tag.ToString(), "[0-9]{1,3}");

                        if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
                        {
                            ClearItems();
                            selectedPos.Add(camera.OffsetPosition(new Point(Canvas.GetLeft(rect), Canvas.GetTop(rect))));
                        }

                        selectedItems.Add(new Tuple <int, int>(Convert.ToInt32(matches[0].ToString()), Convert.ToInt32(matches[1].ToString())));
                    }
                }

                _shift = false;
            }

            //Drag selection
            else if (_dragDropped && (3 * camera.GetScale) < LerpMath.CalculateDelta(dragOrigin[0], dragEnd[0]) ||
                     (3 * camera.GetScale) < LerpMath.CalculateDelta(dragOrigin[1], dragEnd[1]))
            {
                if ((DateTime.Now - _time).Milliseconds > 100)
                {
                    if (!_shift)
                    {
                        ClearItems();
                    }

                    _shift = false;

                    for (int j = 0; j < modelitems.Item.Curve.Count; j++)
                    {
                        var list = modelitems.Item.Curve[j].Original;

                        double minX = (dragOrigin[0] < dragEnd[0]) ? dragOrigin[0] : dragEnd[0];
                        double minY = (dragOrigin[1] < dragEnd[1]) ? dragOrigin[1] : dragEnd[1];

                        double maxX = (dragOrigin[0] > dragEnd[0]) ? dragOrigin[0] : dragEnd[0];
                        double maxY = (dragOrigin[1] > dragEnd[1]) ? dragOrigin[1] : dragEnd[1];


                        for (int i = 0; i < _Canvas.Children.Count; i++)
                        {
                            if (_Canvas.Children[i] is Rectangle)
                            {
                                Rectangle rect = (Rectangle)_Canvas.Children[i];

                                if ((minX - 3) < Canvas.GetLeft(rect) && (maxX + 3) > Canvas.GetLeft(rect))
                                {
                                    if ((minY - 3) < Canvas.GetTop(rect) && (maxY + 3) > Canvas.GetTop(rect))
                                    {
                                        var matches = Regex.Matches(rect.Tag.ToString(), "[0-9]{1,3}");
                                        Tuple <int, int> curvePointNr = new Tuple <int, int>(Convert.ToInt32(matches[0].ToString()), Convert.ToInt32(matches[1].ToString()));
                                        bool             exists       = false;

                                        if (selectedItems.IndexOf(curvePointNr) != -1)
                                        {
                                            exists = true;
                                        }

                                        if (!exists)
                                        {
                                            selectedPos.Add(camera.OffsetPosition(new Point(Canvas.GetLeft(rect), Canvas.GetTop(rect))));
                                            selectedItems.Add(curvePointNr);

                                            dragOrigin[0] = Canvas.GetLeft(rect);
                                            dragOrigin[1] = Canvas.GetTop(rect);

                                            var myAdornerLayer = AdornerLayer.GetAdornerLayer(rect);
                                            RenderSelection(rect, myAdornerLayer);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //Remove selection
            else
            {
                ClearItems();
                draggedItem = null;
            }
        }
        public void OnMouseUp(object sender, MouseButtonEventArgs e)
        {
            List <Point> modifiedList = new List <Point>();

            switch (GraphView_ToolHandler.ActiveTool)
            {
            case 0:

                if (dragIndex < Items.Count && Items[dragIndex].Name == "dragArea")
                {
                    Items.RemoveAt(dragIndex);
                }

                if (_DragSelection)
                {
                    _dragDropped   = true;
                    _DragSelection = false;
                    dragBox        = null;
                }

                //Move
                if (draggedItem != null || MiddleMouseUsed || oldPosition.X != 0)
                {
                    CurveGraphModel model = new CurveGraphModel();
                    model = modelitems;

                    if (oldPosition.X != 0)
                    {
                        Point delta = LerpMath.CalculateDelta
                                      (
                            oldPosition,
                            Mouse.GetPosition(Application.Current.MainWindow),
                            true
                                      );

                        double x = camera.GetTransform(0, 0);
                        double y = camera.GetTransform(0, 1);

                        camera.SetTransform(x + delta.X, y + delta.Y);
                        oldPosition.X = 0;
                    }

                    CalculatePosition(model);
                    ApplyMovement(ref model, ref modifiedList);
                    Add(model);

                    draggedItem = null;
                }
                //Selection
                else
                {
                    HandleSelection(sender, e);
                }

                modifiedList.Clear();
                break;

            case 1:

                ClearItems();
                break;

            default:
                break;
            }
        }