Esempio n. 1
0
        public override void OnModifierMouseWheel(ModifierMouseArgs e)
        {
            e.Handled = true;
            var usey   = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
            var usex   = true;
            var factor = 1 - e.Delta * 0.001;

            using (ParentSurface.SuspendUpdates())
            {
                var p = TransformMousePoint(GetPointRelativeTo(e.MousePoint, ParentSurface.RenderSurface));
                if (usex)
                {
                    var vr        = ParentSurface.XAxis.VisibleRange.AsDoubleRange();
                    var leftPart  = p.X - vr.Min;
                    var rightPart = vr.Max - p.X;
                    leftPart  *= factor;
                    rightPart *= factor;
                    ParentSurface.XAxis.VisibleRange = new DoubleRange(p.X - leftPart, p.X + rightPart);
                }
                if (usey)
                {
                    var vr         = ParentSurface.YAxis.VisibleRange.AsDoubleRange();
                    var bottomPart = p.Y - vr.Min;
                    var topPart    = vr.Max - p.Y;
                    bottomPart *= factor;
                    topPart    *= factor;
                    ParentSurface.YAxis.VisibleRange = new DoubleRange(p.Y - bottomPart, p.Y + topPart);
                }
            }
        }
Esempio n. 2
0
        public override void OnModifierMouseUp(ModifierMouseArgs e)
        {
            if (!IsExportMode || _exporter == null)
            {
                return;
            }

            if (e.MouseButtons != MouseButtons.Left)
            {
                return;
            }

            _uiDispatcher = Application.Current.Dispatcher;

            AddDataRangeBoundaryAnnotation(e.MousePoint.X);

            if (IsFirstClick())
            {
                _rangeBeginXCoord = e.MousePoint.X;
                _dataRangeLinesCount++;
            }
            else
            {
                _rangeEndXCoord = e.MousePoint.X;
                Export();
            }

            base.OnModifierMouseUp(e);
        }
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            base.OnModifierMouseMove(e);

            // Are we editing a data-point?
            if (_pointBeingEdited.HasValue == false)
            {
                e.Handled = false;
                return;
            }
            ;

            var dataSeries = _pointBeingEdited.Value.DataSeries;

            // Compute how far we want to drag the point
            var    currentMousePoint = e.MousePoint;
            double currentYValue     = _selectedSeries.YAxis.GetCurrentCoordinateCalculator().GetDataValue(currentMousePoint.Y);
            double startYValue       = _selectedSeries.YAxis.GetCurrentCoordinateCalculator().GetDataValue(_lastMousePoint.Y);

            var deltaY = currentYValue - startYValue;

            Canvas.SetLeft(_markerEllipse, _pointBeingEdited.Value.HitTestInfo.HitTestPoint.X - markerSize * 0.5);
            Canvas.SetTop(_markerEllipse, currentMousePoint.Y - markerSize * 0.5);

            // Offset the point
            OffsetPointAt(dataSeries, _pointBeingEdited.Value.IndexOfDataSeries, deltaY);

            _lastMousePoint = currentMousePoint;
        }
        public override void OnMasterMouseLeave(ModifierMouseArgs e)
        {
            base.OnMasterMouseLeave(e);

            // Remove the rollover line and markers from the surface
            ClearModifierSurface();
        }
 public override void OnModifierMouseUp(ModifierMouseArgs e)
 {
     _selectedSeries   = null;
     _pointBeingEdited = null;
     ModifierSurface.Children.Remove(_markerEllipse);
     base.DeselectAll();
 }
        public override void OnModifierMouseDown(ModifierMouseArgs e)
        {
            // Deliberately call OnModifierMouseUp in MouseDown handler to perform selection on mouse-down
            base.OnModifierMouseUp(e);

            // Get the selected series
            var selectedSeries = this.ParentSurface.RenderableSeries.FirstOrDefault(x => x.IsSelected);

            if (selectedSeries == null)
            {
                e.Handled = false;
                return;
            }

            // Perform a hit-test. Was the mouse over a data-point?
            var pointHitTestInfo = selectedSeries.HitTest(e.MousePoint, 10.0, false);

            if (pointHitTestInfo.IsHit)
            {
                // Store info about point selected
                int dataIndex = pointHitTestInfo.DataSeriesIndex; // Gets the index to the DataSeries. Same as selectedSeries.DataSeries.FindIndex(pointHitTestInfo.XValue);
                _pointBeingEdited = new PointEditInfo()
                {
                    HitTestInfo = pointHitTestInfo, IndexOfDataSeries = dataIndex, DataSeries = selectedSeries.DataSeries
                };

                Canvas.SetLeft(_markerEllipse, pointHitTestInfo.HitTestPoint.X - markerSize * 0.5);
                Canvas.SetTop(_markerEllipse, pointHitTestInfo.HitTestPoint.Y - markerSize * 0.5);
                ModifierSurface.Children.Add(_markerEllipse);
            }

            _selectedSeries = selectedSeries;
            _lastMousePoint = e.MousePoint;
        }
Esempio n. 7
0
 public override void OnModifierMouseMove(ModifierMouseArgs e)
 {
     if (!IsClicked)
     {
         base.OnModifierMouseMove(e);
     }
 }
 public override void OnModifierMouseDown(ModifierMouseArgs e)
 {
     if (e.MouseButtons == MouseButtons.Left && Keyboard.Modifiers == ModifierKeys.Control)
     {
         base.OnModifierMouseDown(e);
     }
 }
Esempio n. 9
0
        public override void OnModifierMouseDown(ModifierMouseArgs e)
        {
            base.OnModifierMouseDown(e);
            if (e.MouseButtons == MouseButtons.Right)
            {
                var saveFileDialog = new SaveFileDialog
                {
                    Filter           = "Png|*.png|Jpeg|*.jpeg|Bmp|*.bmp",
                    InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
                };

                if (saveFileDialog.ShowDialog() == true)
                {
                    var surface = ParentSurface as SciChartSurface;
                    if (surface == null)
                    {
                        return;
                    }

                    var exportType = (ExportType)saveFileDialog.FilterIndex - 1;

                    surface.ExportToFile(saveFileDialog.FileName, exportType, false);
                }
            }
        }
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            base.OnModifierMouseMove(e);

            if (_selectedSeries == null)
            {
                e.Handled = false;
                return;
            }
            ;

            var dataSeries = _selectedSeries.DataSeries as XyDataSeries <DateTime, double>;

            if (dataSeries == null)
            {
                throw new InvalidOperationException("This modifier is only configured to work with XyDataSeries<double,double>");
            }

            var    currentMousePoint = e.MousePoint;
            double currentYValue     = _selectedSeries.YAxis.GetCurrentCoordinateCalculator().GetDataValue(currentMousePoint.Y);
            double startYValue       = _selectedSeries.YAxis.GetCurrentCoordinateCalculator().GetDataValue(_lastMousePoint.Y);

            var deltaY = currentYValue - startYValue;

            OffsetSeries(dataSeries, deltaY);

            _lastMousePoint = currentMousePoint;
        }
Esempio n. 11
0
        public override void OnModifierDoubleClick(ModifierMouseArgs e)
        {
            base.OnModifierDoubleClick(e);

            // First double-click, start drawing
            if (_dataSeries == null)
            {
                _dataSeries = new XyDataSeries <DateTime, double>()
                {
                    AcceptsUnsortedData = true
                };
                var renderableSeries = new FastLineRenderableSeries()
                {
                    StrokeThickness = 2,
                    Stroke          = Colors.LimeGreen,
                    PointMarker     = new EllipsePointMarker()
                    {
                        Fill = Colors.White,
                    }
                };
                renderableSeries.DataSeries = _dataSeries;
                ParentSurface.RenderableSeries.Add(renderableSeries);

                // Start point
                AppendPoint(e.MousePoint);

                // (Dynamic) end point
                AppendPoint(e.MousePoint);
            }
            // Last double-click, complete drawing
            else
            {
                _dataSeries = null;
            }
        }
Esempio n. 12
0
 public override void OnModifierMouseDown(ModifierMouseArgs e)
 {
     if (Keyboard.Modifiers != ModifierKeys.Control)
     {
         base.OnModifierMouseDown(e);
     }
 }
Esempio n. 13
0
        public override void OnModifierMouseDown(ModifierMouseArgs e)
        {
            base.OnModifierMouseDown(e);

            // Mouse down - a new point
            AppendPoint(e.MousePoint);
        }
        public override void OnModifierMouseWheel(ModifierMouseArgs e)
        {
            e.Handled = true;
            var usey = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
            var usex = true;
            var factor = 1 - e.Delta*0.001;

            using (ParentSurface.SuspendUpdates())
            {
                var p = TransformMousePoint(GetPointRelativeTo(e.MousePoint, ParentSurface.RenderSurface));
                if (usex)
                {
                    var vr = ParentSurface.XAxis.VisibleRange.AsDoubleRange();
                    var leftPart = p.X - vr.Min;
                    var rightPart = vr.Max - p.X;
                    leftPart *= factor;
                    rightPart *= factor;
                    ParentSurface.XAxis.VisibleRange = new DoubleRange(p.X - leftPart, p.X + rightPart);
                }
                if (usey)
                {
                    var vr = ParentSurface.YAxis.VisibleRange.AsDoubleRange();
                    var bottomPart = p.Y - vr.Min;
                    var topPart = vr.Max - p.Y;
                    bottomPart *= factor;
                    topPart *= factor;
                    ParentSurface.YAxis.VisibleRange = new DoubleRange(p.Y - bottomPart, p.Y + topPart);
                }
            }
        }
        public override void OnModifierDoubleClick(ModifierMouseArgs e)
        {
            if (!e.MouseButtons.HasFlag(MouseButtons.Left)) return;

            ParentSurface.ZoomExtents();
            e.Handled = true;
        }
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            base.OnModifierMouseMove(e);
            if (_lastPoint == null)
            {
                return;
            }

            var currentPoint = e.MousePoint;
            var xDelta       = currentPoint.X - _lastPoint.Value.X;
            var yDelta       = _lastPoint.Value.Y - currentPoint.Y;

            using (ParentSurface.SuspendUpdates())
            {
                // Scroll the XAxis by the number of pixels since the last update
                XAxis.Scroll(XAxis.IsHorizontalAxis ? xDelta : -yDelta, ClipMode.None);

                // Scroll the YAxis by the number of pixels since the last update
                YAxis.Scroll(YAxis.IsHorizontalAxis ? -xDelta : yDelta, ClipMode.None);

                // Note.. can be extended for multiple YAxis XAxis, just iterate over all axes on the parent surface
            }

            _lastPoint = currentPoint;
        }
Esempio n. 17
0
        /// <summary>
        /// Called when a Mouse Button is pressed on the parent <see cref="SciChartSurface"/>
        /// </summary>
        /// <param name="e">Arguments detailing the mouse button operation</param>
        /// <remarks></remarks>
        public override void OnModifierMouseDown(ModifierMouseArgs e)
        {
            base.OnModifierMouseDown(e);

            if (_isDragging || !MatchesExecuteOn(e.MouseButtons, ExecuteOn))
            {
                return;
            }

            // Exit if the mouse down was outside the bounds of the ModifierSurface
            if (e.IsMaster && !ModifierSurface.GetBoundsRelativeTo(ModifierSurface).Contains(e.MousePoint))
            {
                return;
            }

            e.Handled = true;

            ModifierSurface.CaptureMouse();

            // Translate the mouse point (which is in RootGrid coordiantes) relative to the ModifierSurface
            // This accounts for any offset due to left Y-Axis
            Point ptTrans = RootGrid.TranslatePoint(e.MousePoint, ModifierSurface);

            _startPoint = ptTrans;
            _rectangle  = new Rect();

            SetPosition(_startPoint, _startPoint);

            _isDragging = true;
        }
Esempio n. 18
0
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            e.Handled = false;
            var xy = GetXY(e.MousePoint, ParentSurface, ModifierSurface);

            _chartingService.RaiseMouseMove((DateTime)xy.X, (double)xy.Y, () => e.Handled = true);
        }
        public override void OnModifierMouseDown(ModifierMouseArgs e)
        {
            base.OnModifierMouseDown(e);

            e.Handled  = true;
            _lastPoint = e.MousePoint;
        }
Esempio n. 20
0
        public override void OnModifierDoubleClick(ModifierMouseArgs e)
        {
            if (!e.MouseButtons.HasFlag(MouseButtons.Left))
            {
                return;
            }

            ParentSurface.ZoomExtents();
            e.Handled = true;
        }
Esempio n. 21
0
        /// <summary>
        /// Called when a Mouse Button is released on the parent <see cref="T:Abt.Controls.SciChart.Visuals.SciChartSurface" />
        /// </summary>
        /// <param name="e">Arguments detailing the mouse button operation</param>
        /// <remarks></remarks>
        public override void OnModifierMouseUp(ModifierMouseArgs e)
        {
            if (Mouse.Captured != null && Mouse.Captured.Equals(this.ModifierSurface))
            {
                if (ChartingService.ChartMode == ChartMode.Zoom)
                {
                    ChartingService.ChartMode = null;
                }
            }

            base.OnModifierMouseUp(e);
        }
Esempio n. 22
0
 public override void OnModifierMouseDown(ModifierMouseArgs e)
 {
     if (e.MouseButtons == MouseButtons.Left && Keyboard.Modifiers == ModifierKeys.Control)
     {
         DragMode = AxisDragModes.Scale;
         base.OnModifierMouseDown(e);
     }
     else
     {
         DragMode = AxisDragModes.Pan;
         base.OnModifierMouseDown(e);
     }
 }
        public override void OnModifierMouseDown(ModifierMouseArgs e)
        {
            base.OnModifierMouseDown(e);

            IEnumerable <IHitTestable> chartElements = this.YAxes.Cast <IHitTestable>()
                                                       .Concat(this.XAxes)
                                                       .Concat(new[] { this.ModifierSurface });

            var clickedElement = chartElements.FirstOrDefault(ce => IsPointWithinBounds(e.MousePoint, ce));

            if (clickedElement != null)
            {
                Debug.WriteLine("The following element was clicked: " + WhatElement(clickedElement));
            }
        }
Esempio n. 24
0
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            if (_currentLine != null)
            {
                var xy = GetXY(e.MousePoint, ParentSurface, ModifierSurface);
                _currentLine.X2 = xy.X is DateTime t1 ? ((ICategoryCoordinateCalculator)_currentLine.ParentSurface.XAxis.GetCurrentCoordinateCalculator()).TransformDataToIndex(t1) : xy.X;
                _currentLine.Y2 = xy.Y;

                if (_currentLinkedLine != null)
                {
                    _currentLinkedLine.X2 = xy.X is DateTime t2 ? ((ICategoryCoordinateCalculator)_currentLinkedLine.ParentSurface.XAxis.GetCurrentCoordinateCalculator()).TransformDataToIndex(t2) : xy.X;
                    _currentLinkedLine.Y2 = xy.Y;
                }
            }
        }
Esempio n. 25
0
        public override void OnModifierDoubleClick(ModifierMouseArgs e)
        {
            base.OnModifierDoubleClick(e);

            var surface = ParentSurface as SciChartSurface;

            if (surface != null)
            {
                var image = surface.ExportToBitmapSource();

                Clipboard.SetImage(image);

                MessageBox.Show("Success");
            }
        }
        public override void OnModifierMouseUp(ModifierMouseArgs e)
        {
            ModifierSurface.ReleaseMouseCapture();
            endPoint = GetPointRelativeTo(e.MousePoint, ModifierSurface);
            OnAttached();

            if (Math.Abs(startPoint.X - endPoint.X) > 10)
            {
                int i = 0;
                foreach (CustomWaterfallNumericAxis YAxis in ParentSurface.XAxes)
                {
                    YAxis.Zoom(startPoint.X + i * 2, endPoint.X + i * 2, TimeSpan.FromMilliseconds(1000));
                    i++;
                }
            }
        }
        public override void OnModifierMouseDown(ModifierMouseArgs e)
        {
            // Deliberately call OnModifierMouseUp in MouseDown handler to perform selection
            base.OnModifierMouseUp(e);

            var selectedSeries = this.ParentSurface.RenderableSeries.FirstOrDefault(x => x.IsSelected);

            if (selectedSeries == null)
            {
                e.Handled = false;
                return;
            }

            _selectedSeries = selectedSeries;
            _lastMousePoint = e.MousePoint;
        }
        /// <summary>
        /// Called when the Mouse is moved on the parent <see cref="SciChartSurface" />
        /// </summary>
        /// <param name="e">Arguments detailing the mouse move operation</param>
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            if (!_isDragging)
            {
                return;
            }

            base.OnModifierMouseMove(e);
            e.Handled = true;

            // Translate the mouse point (which is in RootGrid coordiantes) relative to the ModifierSurface
            // This accounts for any offset due to left Y-Axis
            var ptTrans = GetPointRelativeTo(e.MousePoint, ModifierSurface);

            // Update the zoom recticule position
            SetReticulePosition(_rectangle, _startPoint, ptTrans, e.IsMaster);
        }
Esempio n. 29
0
        private LineAnnotation CreateLine(ModifierMouseArgs e, ISciChartSurface surface, IComparable x, IComparable y, Guid id)
        {
            var currentLine = new LineAnnotation
            {
                Tag             = "Added_" + id,
                StrokeThickness = StrokeThickness,
                Opacity         = Opacity,
                Stroke          = Stroke,
                X1 = x is DateTime t1 ? ((ICategoryCoordinateCalculator)surface.XAxis.GetCurrentCoordinateCalculator()).TransformDataToIndex(t1) : x,
                Y1 = y,
                X2 = x is DateTime t2 ? ((ICategoryCoordinateCalculator)surface.XAxis.GetCurrentCoordinateCalculator()).TransformDataToIndex(t2) : x,
                Y2 = y
            };

            surface.Annotations.Add(currentLine);

            return(currentLine);
        }
Esempio n. 30
0
        /// <summary>
        /// Called when the Mouse is moved on the parent <see cref="SciChartSurface"/>
        /// </summary>
        /// <param name="e">Arguments detailing the mouse move operation</param>
        /// <remarks></remarks>
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            if (!_isDragging)
            {
                return;
            }

            base.OnModifierMouseMove(e);
            e.Handled = true;

            // Translate the mouse point (which is in RootGrid coordiantes) relative to the ModifierSurface
            // This accounts for any offset due to left Y-Axis
            Point ptTrans = RootGrid.TranslatePoint(e.MousePoint, ModifierSurface);

            SetPosition(_startPoint, ptTrans);

            UpdateSurface();
        }
Esempio n. 31
0
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            base.OnModifierMouseMove(e);

            var pt = GetPointRelativeTo(e.MousePoint, ModifierSurface);

            var xAxis = XAxes.FirstOrDefault();
            var yAxis = YAxes.FirstOrDefault();

            var xAxisBandInfo = GetAxisBandInfo(xAxis, pt, out var xAxisInfo);
            var yAxisBandInfo = GetAxisBandInfo(yAxis, pt, out var yAxisInfo);

            ChartBandsInfo.XAxisBandInfo.BandInfo    = xAxisBandInfo;
            ChartBandsInfo.XAxisBandInfo.HitTestInfo = xAxisInfo;

            ChartBandsInfo.YAxisBandInfo.BandInfo    = yAxisBandInfo;
            ChartBandsInfo.YAxisBandInfo.HitTestInfo = yAxisInfo;
        }
        /// <summary>
        /// Called when a Mouse Button is pressed on the parent <see cref="SciChartSurface" />
        /// </summary>
        /// <param name="e">Arguments detailing the mouse button operation</param>
        public override void OnModifierMouseDown(ModifierMouseArgs e)
        {
            base.OnModifierMouseDown(e);

            // Check the ExecuteOn property and if we are already dragging. If so, exit
            if (_isDragging || !MatchesExecuteOn(e.MouseButtons, ExecuteOn))
            {
                return;
            }

            // Check the mouse point was inside the ModifierSurface (the central chart area). If not, exit
            var modifierSurfaceBounds = ModifierSurface.GetBoundsRelativeTo(RootGrid);

            if (!modifierSurfaceBounds.Contains(e.MousePoint))
            {
                return;
            }

            // Capture the mouse, so if mouse goes out of bounds, we retain mouse events
            if (e.IsMaster)
            {
                ModifierSurface.CaptureMouse();
            }

            // Translate the mouse point (which is in RootGrid coordiantes) relative to the ModifierSurface
            // This accounts for any offset due to left Y-Axis
            var ptTrans = GetPointRelativeTo(e.MousePoint, ModifierSurface);

            _startPoint = ptTrans;
            _rectangle  = new Rectangle
            {
                Style = SelectionPolygonStyle,
            };

            // Update the zoom recticule position
            SetReticulePosition(_rectangle, _startPoint, _startPoint, e.IsMaster);

            // Add the zoom reticule to the ModifierSurface - a canvas over the chart
            ModifierSurface.Children.Add(_rectangle);

            // Set flag that a drag has begun
            _isDragging = true;
        }
        public override void OnModifierDoubleClick(ModifierMouseArgs e)
        {
            base.OnModifierDoubleClick(e);
            var currentMousePoint = e.MousePoint;
            Point relPnt = this.GetPointRelativeTo(currentMousePoint, base.YAxis);

            if (relPnt != null && relPnt.X >= 0)
            {
                Debug.WriteLine("User clicked on axis. Relative position {0}:{1}", relPnt.X, relPnt.Y);
                Debug.WriteLine("Y Axis Visible Range {0}:{1} ", this.YAxis.VisibleRange.Min, this.YAxis.VisibleRange.Max);
                Debug.WriteLine("Y Axis Data Range {0}:{1} ", this.YAxis.DataRange.Min, this.YAxis.DataRange.Max);

                var frstChrtSer = ParentSurface.RenderableSeries.FirstOrDefault();

                double currentYValue = frstChrtSer.YAxis.GetCurrentCoordinateCalculator().GetDataValue(currentMousePoint.Y);

                var sciChart = (SciChartSurface)ParentSurface;
                var modifiers = sciChart.ChartModifier as ModifierGroup;
                foreach (var m in modifiers.ChildModifiers)
                {
                    if (m is AnnotationCreationModifier)
                    {
                        var a = m as AnnotationCreationModifier;
                        a.AnnotationStyle = (Style)FindResource("HorizontalLineAnnotationStyle");
                        a.AnnotationType = typeof(HorizontalLineAnnotation);
                        Debug.WriteLine("Adding horizontal line annotation");
                        break;
                    }
                }

                //var horizLine = new XyDataSeries<DateTime, double>();
                //foreach (var datum in frstChrtSer.DataSeries.XValues)
                //{horizLine.Append((DateTime)datum, currentYValue);}

                //using (var ssp = ParentSurface.SuspendUpdates())
                //{
                //    ParentSurface.SeriesSource.Add(new ChartSeriesViewModel(horizLine, new FastLineRenderableSeries()));
                //    ParentSurface.ResumeUpdates(ssp);
                //}
            }
        }
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            e.Handled = true;

            if (!ModifierSurface.Children.Contains(tooltipControl))
            {
                ModifierSurface.Children.Add(tooltipControl);
            }

            var p = TransformMousePoint(GetPointRelativeTo(e.MousePoint, ParentSurface.RenderSurface));

            var seriesCol = ParentSurface.RenderableSeries;
            foreach (var gseries in seriesCol)
            {
                var rseries = gseries as RectangleRenderableSeries2;
                var series = rseries?.DataSeries as ISeriesWithAttributes;
                var i = series?.FindNearest(p);
                if (i == null)
                {
                    continue;
                }

                tooltipControl.Visibility = Visibility.Visible;
                strb.Clear();
                for (int j = 0; j < series.AttributeNames.Count; j++)
                {
                    strb.Append($"{series.AttributeNames[j]?.ToUpper()}: {series.GetAttribute(i.Value, j)}\n");
                }
                strb.Append($"X: {series.XValues[i.Value]:F1} m\nY: {series.YValues[i.Value]:F2} rad");
                textBlock.Text = strb.ToString();

                var mp = GetPointRelativeTo(e.MousePoint, ModifierSurface);

                Canvas.SetLeft(tooltipControl, mp.X);
                Canvas.SetTop(tooltipControl, mp.Y);
                return;
            }

            tooltipControl.Visibility = Visibility.Hidden;
        }