Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

wpf graph - zoom with touch

How do I configure Graph to support Pinch/Spread for zooming?

0 Kudos
Message 1 of 4
(7,068 Views)

We did not have time to integrate multi-touch gestures into the WPF controls for the first release, so to get gesture support you will need to handle the touch events and call Zoom manually.


To have this work like the existing mouse-based zoom interaction, you would need to target the events on the protected PlotArea object:


    public class MyGraph : Graph {
        public override void OnApplyTemplate( ) {
            if( PlotArea != null ) { PlotArea.TouchMove -= OnTouchMove; }
            base.OnApplyTemplate( );
            if( PlotArea != null ) { PlotArea.TouchMove += OnTouchMove; }
        }

        private void OnTouchMove(object sender, TouchEventArgs e) {
            ...
        }
    }


Otherwise, there are no special implementation requirements.

~ Paul H
0 Kudos
Message 2 of 4
(7,056 Views)

There is my code. Seems to work, but zoom is quite slow, probably because there are too many small zoom events while is move fingers. Any idea how to accumulate the events?

 

    private void graph_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
      if (m_currentToolPanel == pMainZoom)
      {
        if (e.DeltaManipulation.Scale.X != 1 && e.DeltaManipulation.Scale.X < 2)
        {
          var center = e.ManipulationOrigin;
          var size = graph.GetPlotAreaSize();
 
          var dx = (AxisX.Range.Maximum - AxisX.Range.Minimum) * (1 - e.DeltaManipulation.Scale.X) / 2;
          var dy = (AxisY.Range.Maximum - AxisY.Range.Minimum) * (1 - e.DeltaManipulation.Scale.X) / 2;
          AxisX.Range = new Range<double>(AxisX.Range.Minimum - dx, AxisX.Range.Maximum + dx);
          AxisY.Range = new Range<double>(AxisY.Range.Minimum - dy, AxisY.Range.Maximum + dy);
        }
        else if (e.DeltaManipulation.Translation.X != 0 || e.DeltaManipulation.Translation.Y != 0)
        {
          var size = graph.GetPlotAreaSize();
 
          if (e.DeltaManipulation.Translation.X != 0)
          {
            var delta = (AxisX.Range.Maximum - AxisX.Range.Minimum) / size.Width * e.DeltaManipulation.Translation.X * -1;
            AxisX.Range = new Range<double>(AxisX.Range.Minimum + delta, AxisX.Range.Maximum + delta);
          }
 
          if (e.DeltaManipulation.Translation.Y != 0)
          {
            var delta = (AxisY.Range.Maximum - AxisY.Range.Minimum) / size.Height * e.DeltaManipulation.Translation.Y;
            AxisY.Range = new Range<double>(AxisY.Range.Minimum + delta, AxisY.Range.Maximum + delta);
          }
        }
      }
    }
 
    private void graph_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
    {
      e.Mode = ManipulationModes.Scale | ManipulationModes.Translate;
    }
0 Kudos
Message 3 of 4
(7,016 Views)

Would it make sense for you to use the ManipulationCompleted event? The TotalManipulation property contains the accumulated deltas over all the manipulation events.


Otherwise, from the definition of Translation and Scale, it looks like the values can be accumulated through addition and multiplication respectively (i.e. in pseudo-code: totalTranslation += deltaTranslation; totalScale *= deltaScale;). Then you can throttle the incoming events, only processing the accumulated values after a sufficient time delta, or at the end of the manipulation.


Also, the Zoom method is available if you want to adjust all of the scales simultaneously. To get the relative translation values in the Cartesian graph, you can divide by the size of the plot area; the scale factors are already relative values and can be used directly.

~ Paul H
0 Kudos
Message 4 of 4
(7,005 Views)