private void Stroke_MouseLeave(object sender, MouseEventArgs e)
        {
            Shape  leftShape  = sender as Shape;
            Stroke leftStroke = leftShape.DataContext as Stroke;

            //Debug.WriteLine("mouse leave on stroke {0} of rally {1}", leftStroke.Number, leftStroke.Rally.Number);

            foreach (var strokeShape in StrokeShapes)
            {
                foreach (var shape in strokeShape.Value)
                {
                    StrokeInteraction interactionType = StrokeInteraction.None;
                    if (SelectedStroke == null)
                    {
                        interactionType = StrokeInteraction.Normal;
                    }
                    else
                    if (!strokeShape.Key.Equals(SelectedStroke))
                    {
                        interactionType = StrokeInteraction.Normal;
                    }

                    if (interactionType != StrokeInteraction.None)
                    {
                        SetShapeStyleForInteractionType(shape, ((Stroke)shape.DataContext).Stroketechnique, interactionType);
                    }
                }
            }
        }
        private void SelectStroke(Stroke stroke)
        {
            SelectedStroke = stroke;

            foreach (var strokeShape in StrokeShapes)
            {
                foreach (var shape in strokeShape.Value)
                {
                    StrokeInteraction interactionType = StrokeInteraction.None;
                    if (strokeShape.Key.Equals(stroke))
                    {
                        interactionType = StrokeInteraction.Selected;
                    }
                    else
                    {
                        interactionType = StrokeInteraction.HoverOther;
                    }

                    if (interactionType != StrokeInteraction.None)
                    {
                        SetShapeStyleForInteractionType(shape, ((Stroke)shape.DataContext).Stroketechnique, interactionType);
                    }
                }
            }
        }
        private void Stroke_MouseEnter(object sender, MouseEventArgs e)
        {
            Shape  hoveredShape  = sender as Shape;
            Stroke hoveredStroke = hoveredShape.DataContext as Stroke;

            //Debug.WriteLine("mouse enter on stroke {0} of rally {1}", hoveredStroke.Number, hoveredStroke.Rally.Number);

            foreach (var strokeShape in StrokeShapes)
            {
                foreach (var shape in strokeShape.Value)
                {
                    StrokeInteraction interactionType = StrokeInteraction.None;
                    if (strokeShape.Key.Equals(hoveredStroke))
                    {
                        if (SelectedStroke == null || !strokeShape.Key.Equals(SelectedStroke))
                        {
                            interactionType = StrokeInteraction.Hover;
                        }
                    }
                    else
                    {
                        if (SelectedStroke != null && strokeShape.Key.Equals(SelectedStroke))
                        {
                            interactionType = StrokeInteraction.Selected;
                        }
                        else
                        {
                            interactionType = StrokeInteraction.HoverOther;
                        }
                    }

                    if (interactionType != StrokeInteraction.None)
                    {
                        SetShapeStyleForInteractionType(shape, ((Stroke)shape.DataContext).Stroketechnique, interactionType);
                    }
                }
            }
        }
        private void SetShapeStyleForInteractionType(Shape shape, Stroketechnique stroketechnique, StrokeInteraction interactionType)
        {
            Brush  fill            = shape.Fill;
            Brush  stroke          = shape.Stroke;
            double opacity         = shape.Opacity;
            double strokeThickness = shape.StrokeThickness;

            switch (interactionType)
            {
            case StrokeInteraction.Normal:
                if (SelectedStroke == null)
                {
                    opacity = StrokeOpacity;
                    if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Flip)
                    {
                        stroke = StrokeBrushBanana;
                        if (shape is Path && (ShapeType)shape.Tag != ShapeType.Direction)
                        {
                            fill = StrokeBrushBanana;
                        }
                    }
                }
                else
                {
                    if ((ShapeType)shape.Tag == ShapeType.SpinShape)
                    {
                        opacity = StrokeOpacityDisabledSpin;
                    }
                    else
                    {
                        opacity = StrokeOpacityDisabled;
                    }
                    if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Flip)
                    {
                        stroke = StrokeBrushBananaDisabled;
                        if (shape is Path && (ShapeType)shape.Tag != ShapeType.Direction)
                        {
                            fill = StrokeBrushBananaDisabled;
                        }
                    }
                }

                if ((ShapeType)shape.Tag == ShapeType.Intercept)
                {
                    if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Smash)
                    {
                        strokeThickness = StrokeThicknessSmashIntercept;
                    }
                    else
                    {
                        strokeThickness = StrokeThicknessIntercept;
                    }
                }
                else if ((ShapeType)shape.Tag == ShapeType.Debug_preceding)
                {
                    strokeThickness = StrokeThicknessPreceding_Debug;
                }
                else if ((ShapeType)shape.Tag == ShapeType.SpinShape)
                {
                    strokeThickness = StrokeThicknessSpinArrow;
                }
                else
                {
                    if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Smash)
                    {
                        strokeThickness = StrokeThicknessSmash;
                    }
                    else
                    {
                        strokeThickness = StrokeThickness;
                    }
                }
                break;

            case StrokeInteraction.Hover:
                if (SelectedStroke == null)
                {
                    opacity = StrokeOpacity;
                }
                else
                {
                    opacity = StrokeOpacityHover;
                }

                if ((ShapeType)shape.Tag == ShapeType.SpinShape)
                {
                    strokeThickness = StrokeThicknessSpinArrowHover;
                }
                else if ((ShapeType)shape.Tag == ShapeType.Intercept)
                {
                    if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Smash)
                    {
                        strokeThickness = StrokeThicknessSmashInterceptHover;
                    }
                    else
                    {
                        strokeThickness = StrokeThicknessInterceptHover;
                    }
                }
                else if ((ShapeType)shape.Tag == ShapeType.Debug_preceding)
                {
                    strokeThickness = StrokeThicknessPrecedingHover_Debug;
                }
                else
                {
                    if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Smash)
                    {
                        strokeThickness = StrokeThicknessSmashHover;
                    }
                    else
                    {
                        strokeThickness = StrokeThicknessHover;
                    }
                }

                if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Flip)
                {
                    stroke = StrokeBrushBanana;
                    if (shape is Path && (ShapeType)shape.Tag != ShapeType.Direction)
                    {
                        fill = StrokeBrushBanana;
                    }
                }
                break;

            case StrokeInteraction.HoverOther:
                if (SelectedStroke == null)
                {
                    if ((ShapeType)shape.Tag == ShapeType.SpinShape)
                    {
                        opacity         = StrokeOpacityHoverUnselectedSpin;
                        strokeThickness = StrokeThicknessSpinArrow;
                    }
                    else
                    {
                        opacity = StrokeOpacityHoverUnselected;
                    }
                }
                else
                {
                    if ((ShapeType)shape.Tag == ShapeType.SpinShape)
                    {
                        opacity         = StrokeOpacityDisabledSpin;
                        strokeThickness = StrokeThicknessSpinArrow;
                    }
                    else
                    {
                        opacity = StrokeOpacityDisabled;
                    }
                }

                if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Flip)
                {
                    stroke = StrokeBrushBananaDisabled;
                    if (shape is Path && (ShapeType)shape.Tag != ShapeType.Direction)
                    {
                        fill = StrokeBrushBananaDisabled;
                    }
                }
                break;

            case StrokeInteraction.Selected:
                opacity = StrokeOpacity;

                if ((ShapeType)shape.Tag == ShapeType.SpinShape)
                {
                    strokeThickness = StrokeThicknessSpinArrowSelected;
                }
                else if ((ShapeType)shape.Tag == ShapeType.Intercept)
                {
                    if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Smash)
                    {
                        strokeThickness = StrokeThicknessSmashInterceptSelected;
                    }
                    else
                    {
                        strokeThickness = StrokeThicknessInterceptSelected;
                    }
                }
                else if ((ShapeType)shape.Tag == ShapeType.Debug_preceding)
                {
                    strokeThickness = StrokeThicknessPrecedingSelected_Debug;
                }
                else
                {
                    if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Smash)
                    {
                        strokeThickness = StrokeThicknessSmashSelected;
                    }
                    else
                    {
                        strokeThickness = StrokeThicknessSelected;
                    }
                }

                if (stroketechnique != null && stroketechnique.EnumType == Models.Util.Enums.Stroke.Technique.Flip)
                {
                    stroke = StrokeBrushBanana;
                    if (shape is Path && (ShapeType)shape.Tag != ShapeType.Direction)
                    {
                        fill = StrokeBrushBanana;
                    }
                }
                break;
            }

            shape.Fill            = fill;
            shape.Stroke          = stroke;
            shape.Opacity         = opacity;
            shape.StrokeThickness = strokeThickness;
        }