public AdvancedCarnassialOptions(CarnassialState state, MarkableCanvas markableCanvas, Window owner)
        {
            this.InitializeComponent();
            this.Owner = owner;
            this.carnassialState = state;
            this.markableCanvas = markableCanvas;

            // Throttles
            this.ImageRendersPerSecond.Minimum = Constant.ThrottleValues.DesiredMaximumImageRendersPerSecondLowerBound;
            this.ImageRendersPerSecond.Maximum = Constant.ThrottleValues.DesiredMaximumImageRendersPerSecondUpperBound;
            this.ImageRendersPerSecond.Value = this.carnassialState.Throttles.DesiredImageRendersPerSecond;
            this.ImageRendersPerSecond.ValueChanged += this.ImageRendersPerSecond_ValueChanged;
            this.ImageRendersPerSecond.ToolTip = this.carnassialState.Throttles.DesiredImageRendersPerSecond;

            // The Max Zoom Value
            this.MaxZoom.Value = this.markableCanvas.ZoomMaximum;
            this.MaxZoom.ToolTip = this.markableCanvas.ZoomMaximum;
            this.MaxZoom.Maximum = Constant.MarkableCanvas.ImageZoomMaximumRangeMaximum;
            this.MaxZoom.Minimum = Constant.MarkableCanvas.ImageZoomMaximumRangeMinimum;

            // Image Differencing Thresholds
            this.DifferenceThreshold.Value = this.carnassialState.DifferenceThreshold;
            this.DifferenceThreshold.ToolTip = this.carnassialState.DifferenceThreshold;
            this.DifferenceThreshold.Maximum = Constant.Images.DifferenceThresholdMax;
            this.DifferenceThreshold.Minimum = Constant.Images.DifferenceThresholdMin;
        }
        public MagnifyingGlass(MarkableCanvas markableCanvas)
        {
            this.FieldOfView = Constant.MarkableCanvas.MagnifyingGlassDefaultFieldOfView;
            this.IsEnabled = false;
            this.IsHitTestVisible = false;
            this.HorizontalAlignment = HorizontalAlignment.Left;
            this.Parent = markableCanvas;
            this.VerticalAlignment = VerticalAlignment.Top;
            this.Visibility = Visibility.Collapsed;

            this.lensAngle = 0.0;
            this.magnifyingGlassAngle = 0.0;

            // Create the handle of the magnifying glass
            Line handle = new Line();
            handle.StrokeThickness = 5;
            handle.X1 = Constant.MarkableCanvas.MagnifyingGlassHandleStart;
            handle.Y1 = Constant.MarkableCanvas.MagnifyingGlassHandleStart;
            handle.X2 = Constant.MarkableCanvas.MagnifyingGlassHandleEnd;
            handle.Y2 = Constant.MarkableCanvas.MagnifyingGlassHandleEnd;
            LinearGradientBrush handleBrush = new LinearGradientBrush();
            handleBrush.StartPoint = new Point(0.78786, 1);
            handleBrush.EndPoint = new Point(1, 0.78786);
            handleBrush.GradientStops.Add(new GradientStop(Colors.DarkGreen, 0));
            handleBrush.GradientStops.Add(new GradientStop(Colors.LightGreen, 0.9));
            handleBrush.GradientStops.Add(new GradientStop(Colors.Green, 1));
            handle.Stroke = handleBrush;
            this.Children.Add(handle);

            // Create the lens of the magnifying glass
            this.lensCanvas = new Canvas();
            this.Children.Add(this.lensCanvas);

            // lens has a white backgound
            Ellipse lensBackground = new Ellipse();
            lensBackground.Width = Constant.MarkableCanvas.MagnifyingGlassDiameter;
            lensBackground.Height = Constant.MarkableCanvas.MagnifyingGlassDiameter;
            lensBackground.Fill = Brushes.White;
            this.lensCanvas.Children.Add(lensBackground);

            this.magnifierLens = new Ellipse();
            this.magnifierLens.Width = Constant.MarkableCanvas.MagnifyingGlassDiameter;
            this.magnifierLens.Height = Constant.MarkableCanvas.MagnifyingGlassDiameter;
            this.magnifierLens.StrokeThickness = 3;

            // fill the lens
            VisualBrush lensFill = new VisualBrush();
            lensFill.ViewboxUnits = BrushMappingMode.Absolute;
            lensFill.Viewbox = new Rect(0, 0, 50, 50);
            lensFill.ViewportUnits = BrushMappingMode.RelativeToBoundingBox;
            lensFill.Viewport = new Rect(0, 0, 1, 1);
            this.magnifierLens.Fill = lensFill;

            // outline the lens
            LinearGradientBrush outlineBrush = new LinearGradientBrush();
            outlineBrush.StartPoint = new Point(0, 0);
            outlineBrush.EndPoint = new Point(0, 1);
            ColorConverter cc = new ColorConverter();
            outlineBrush.GradientStops.Add(new GradientStop((Color)cc.ConvertFrom("#AAA"), 0));
            outlineBrush.GradientStops.Add(new GradientStop((Color)cc.ConvertFrom("#111"), 1));
            this.magnifierLens.Stroke = outlineBrush;
            this.lensCanvas.Children.Add(this.magnifierLens);

            Ellipse lensImage = new Ellipse();
            Canvas.SetLeft(lensImage, 2);
            Canvas.SetTop(lensImage, 2);
            lensImage.StrokeThickness = 4;
            lensImage.Width = Constant.MarkableCanvas.MagnifyingGlassDiameter - 4;
            lensImage.Height = Constant.MarkableCanvas.MagnifyingGlassDiameter - 4;
            this.lensCanvas.Children.Add(lensImage);

            // crosshairs
            Line verticalCrosshair = new Line();
            verticalCrosshair.StrokeThickness = 0.25;
            verticalCrosshair.X1 = 5;
            verticalCrosshair.Y1 = Constant.MarkableCanvas.MagnifyingGlassDiameter / 2;
            verticalCrosshair.X2 = Constant.MarkableCanvas.MagnifyingGlassDiameter - 5;
            verticalCrosshair.Y2 = Constant.MarkableCanvas.MagnifyingGlassDiameter / 2;
            verticalCrosshair.Stroke = Brushes.Black;
            verticalCrosshair.Opacity = 0.5;
            this.lensCanvas.Children.Add(verticalCrosshair);

            Line horizontalCrosshair = new Line();
            horizontalCrosshair.StrokeThickness = 0.25;
            horizontalCrosshair.X1 = Constant.MarkableCanvas.MagnifyingGlassDiameter / 2;
            horizontalCrosshair.Y1 = 5;
            horizontalCrosshair.X2 = Constant.MarkableCanvas.MagnifyingGlassDiameter / 2;
            horizontalCrosshair.Y2 = Constant.MarkableCanvas.MagnifyingGlassDiameter - 5;
            horizontalCrosshair.Stroke = Brushes.Black;
            horizontalCrosshair.Opacity = 0.5;
            this.lensCanvas.Children.Add(horizontalCrosshair);

            // set render transform
            // Rotate the glass before translating it as that ordering means translation calculations don't have to account for rotation.  If this is changed
            // RedrawIfVisible() must be updated.
            this.rotation = new RotateTransform(this.magnifyingGlassAngle, Constant.MarkableCanvas.MagnifyingGlassDiameter, Constant.MarkableCanvas.MagnifyingGlassDiameter);
            this.translation = new TranslateTransform();

            TransformGroup transformGroup = new TransformGroup();
            transformGroup.Children.Add(this.rotation);
            transformGroup.Children.Add(this.translation);
            this.RenderTransform = transformGroup;
        }