Pre loader

Extending RubberBandXyZoomModifier -- Growing height or width based on distance off the chart

Welcome to the SciChart Forums!

  • Please read our Question Asking Guidelines for how to format a good question
  • Some reputation is required to post answers. Get up-voted to avoid the spam filter!
  • We welcome community answers and upvotes. Every Q&A improves SciChart for everyone

WPF Forums | JavaScript Forums | Android Forums | iOS Forums

Answered
0
0

I’m looking to either extend the RubberBandXyZoomModifier to provide this size growing behavior when the mouse has left the chart area (shown in the attached image) or build one from scratch (having to rebuild the normal box-zoom components (the box etc).

I assume from reading around the the latter option will be the only option.

Thanks!

Version
4.2.3.10185
Images
  • Riley Huddleston
    I’ve got a box-zoom modifier working, but I can’t figure out how to Capture the mouse (as a part of the modifier API). The normal OnMouseDown functions do not seem to be working as expected either. Thoughts?
  • You must to post comments
Best Answer
0
0
    public class AnalogChartBoxZoomModifier : ChartModifierBase
{
    public override void OnModifierMouseDown(ModifierMouseArgs e)
    {
        base.OnModifierMouseDown(e);

        if (CanExecute(e.MouseButtons))
        {
            e.Handled = true;
            _startPoint = GetPointRelativeTo(e.MousePoint, ModifierSurface);
        }
    }

    public override void OnModifierMouseMove(ModifierMouseArgs e)
    {
        base.OnModifierMouseMove(e);
        if (_startPoint != null)
        {
            DoMouseMove((Point)_startPoint, e.MousePoint, (e.Modifier & MouseModifier.Shift) != 0);
        }
    }

    private void DoMouseMove(Point start, Point point, bool isXZoom)
    {
        if (_rect == null)
        {
            _rect = new System.Windows.Shapes.Rectangle()
            {
                Stroke = new SolidColorBrush(Color.FromArgb(119, 66, 182, 73)),
                Fill = new SolidColorBrush(Color.FromArgb(51, 66, 182, 73))
            };

            ParentSurface.ModifierSurface.Children.Add(_rect);
            ZoomStart(start);
        }

        var currentPoint = GetPointRelativeTo(point, ModifierSurface);


        if (isXZoom)
        {
            UpdateRect_XZoom(start, currentPoint);
        }
        else
        {
            UpdateRect_XYZoom(start, currentPoint);
        }
    }

    private void ZoomStart(Point start)
    {
        Canvas.SetLeft(_rect, start.X);
        Canvas.SetTop(_rect, start.Y);
    }

    private void UpdateRect_XYZoom(Point startPoint, Point currentPoint)
    {
        if (currentPoint.X > startPoint.X)
        {
            _rect.Width = currentPoint.X - startPoint.X;
        }

        if (currentPoint.Y > startPoint.Y)
        {
            _rect.Height = currentPoint.Y - startPoint.Y;
        }

        if (currentPoint.X < startPoint.X)
        {
            Canvas.SetLeft(_rect, currentPoint.X);
            _rect.Width = startPoint.X - currentPoint.X;
        }

        if (currentPoint.Y < startPoint.Y)
        {
            Canvas.SetTop(_rect, currentPoint.Y);
            _rect.Height = startPoint.Y - currentPoint.Y;
        }
    }

    private void UpdateRect_XZoom(Point startPoint, Point currentPoint)
    {
        if (currentPoint.X > startPoint.X)
        {
            _rect.Width = currentPoint.X - startPoint.X;
        }

        if (currentPoint.X < startPoint.X)
        {
            Canvas.SetLeft(_rect, currentPoint.X);
            _rect.Width = startPoint.X - currentPoint.X;
        }

        Canvas.SetTop(_rect, 1);
        _rect.Height = ParentSurface.ModifierSurface.ActualHeight-2;
    }

    private void ZoomEnd(double x, double y, double width, double height)
    {
        using (ParentSurface.SuspendUpdates())
        {
            ParentSurface.ModifierSurface.Children.Remove(_rect);
            XAxis.Zoom(x, x + width, TimeSpan.FromMilliseconds(450));
            YAxis.Zoom(y, y + height, TimeSpan.FromMilliseconds(450));
        }
    }

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

        if (IsZoomCompleted())
        {
            double x = Canvas.GetLeft(_rect);
            double y = Canvas.GetTop(_rect);
            ZoomEnd(x, y, _rect.ActualWidth, _rect.ActualHeight);
        }

        _startPoint = null;
        _rect = null;
    }

    private bool IsZoomCompleted()
    {
        return _rect != null;
    }
    private bool CanExecute(MouseButtons mouseButtons)
    {
        return _mouseButtonsToExecuteOn.ContainsKey(mouseButtons) && _mouseButtonsToExecuteOn[mouseButtons] == ExecuteOn;
    }

    private readonly Dictionary<MouseButtons, ExecuteOn> _mouseButtonsToExecuteOn = new Dictionary<MouseButtons, ExecuteOn>
    {
        {MouseButtons.Left, ExecuteOn.MouseLeftButton   },
        {MouseButtons.Right,  ExecuteOn.MouseRightButton  },
        {MouseButtons.Middle, ExecuteOn.MouseMiddleButton  },
    };

    private Point? _startPoint;
    private System.Windows.Shapes.Rectangle _rect;
}

Note when you right click (with a right click menu) at x position A and then left click at position B, this causes the following sequence (on the left click): OnModifierMouseDown, OnModifierMouseMove, and OnModifierMouseUp. This is completely unexpected (the RubberBand modifer doesn’t do this).

If I could know if the mouse button is still down– then I could validate each function call more easily. I must going about this entirely in the wrong way because this seems hard.

  • Riley Huddleston
    I added point check which seems to have side stepped the problem. Its still strange that the Move code is called when its just a simple click. I’d like to know if this is intended or not .
  • You must to post comments
0
0

Hi Riley,

I’m not sure what you mean by “to provide this size growing behavior when the mouse has left the chart area” ? I

t looks to me like you want the series scale to fit the chart after mouse-up of the rubber band operation?

If so, set the following properties:

  1. Set RubberBandXyZoomModifier.IsXAxisOnly = true. This ensures the Rectangle is drawn over the entire Y-range
  2. Set RubberBandXyZoomModifier.ZoomExtentsY = true. This ensures that the Axis zooms to extents after you finish the operation
  3. Assign each series to its own axis. This ensures each series scales to fit the viewport, as the axis is responsible for scaling. You may hide axis if you wish the chart to appear with only one axis, although if they have different scales its recommended to allow them to show.

You could potentially override the RubberBandXyZoomModifier by overriding mouse-up to perform step #3 ONLY right before calling base.OnModifierMouseUp where the zoom operation is performed.

Let me know if I’ve got your requirements right.

Best regards,
Andrew

  • Riley Huddleston
    Not quite. See the thing is is it is a normal box zoom. But when you run out of dragging room I want to have it increase that dimension proportionally. So if you drag off the bottom 20 pixels, the height will grow 20 pixels (maybe you missed some signal peak or feature so you want to expand the size). Please see the secondary part in the below answer section (used this for code formatting).
  • You must to post comments
Showing 2 results
Your Answer

Please first to submit.