[mapguide-commits] r6823 - branches/2.4/MgDev/Desktop/MapViewer

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Wed Jun 27 04:51:39 PDT 2012


Author: jng
Date: 2012-06-27 04:51:39 -0700 (Wed, 27 Jun 2012)
New Revision: 6823

Modified:
   branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj
   branches/2.4/MgDev/Desktop/MapViewer/MgMapViewer.cs
Log:
mg-desktop: Implement mouse wheel zoom!

Modified: branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj	2012-06-26 16:28:02 UTC (rev 6822)
+++ branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj	2012-06-27 11:51:39 UTC (rev 6823)
@@ -29,8 +29,7 @@
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>
-    </DefineConstants>
+    <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <DocumentationFile>bin\Release\OSGeo.MapGuide.Viewer.XML</DocumentationFile>

Modified: branches/2.4/MgDev/Desktop/MapViewer/MgMapViewer.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgMapViewer.cs	2012-06-26 16:28:02 UTC (rev 6822)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgMapViewer.cs	2012-06-27 11:51:39 UTC (rev 6823)
@@ -62,8 +62,6 @@
             }
         }
 
-        const double MINIMUM_ZOOM_SCALE = 5.0;
-
 #if VIEWER_DEBUG
         private MgdLayer _debugLayer;
 
@@ -174,11 +172,15 @@
             this.SelectionColor = Color.Blue;
             this.PointPixelBuffer = 2;
 
+            this.MinScale = 10;
+            this.MaxScale = 1000000000;
+
             this.DigitizingFillTransparency = 100;
             this.DigitizingOutline = Brushes.Red;
             this.DigitzingFillColor = Color.White;
             this.TooltipFillColor = Color.LightYellow;
             this.TooltipFillTransparency = 200;
+            this.MouseWheelDelayRenderInterval = 800;
 
             this.ActiveTool = MapActiveTool.None;
             this.DoubleBuffered = true;
@@ -203,6 +205,7 @@
             base.MouseDoubleClick += OnMapMouseDoubleClick;
             base.MouseHover += OnMapMouseHover;
             base.MouseEnter += OnMouseEnter;
+            base.MouseWheel += OnMapMouseWheel;
         }
 
         /// <summary>
@@ -318,6 +321,27 @@
             base.Dispose(disposing);
         }
 
+        /// <summary>
+        /// Gets or sets the minimum allowed zoom scale for this viewer
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("The minimum allowed zoom scale for this viewer")]
+        public int MinScale { get; set; }
+
+        /// <summary>
+        /// Gets or sets the maximum allowed zoom scale for this viewer
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("The maximum allowed zoom scale for this viewer")]
+        public int MaxScale { get; set; }
+
+        /// <summary>
+        /// The amount of time (in ms) to wait to re-render after a mouse wheel scroll
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("The amount of time (in ms) to wait to re-render after a mouse wheel scroll")]
+        public int MouseWheelDelayRenderInterval { get; set; }
+
         private Color _selColor;
 
         /// <summary>
@@ -436,18 +460,33 @@
             Trace.TraceInformation("OnPaint(e)");
 
             if (!translate.IsEmpty)
-                e.Graphics.TranslateTransform(translate.X, translate.Y);
+            {
+                if (mouseWheelTx.HasValue && mouseWheelTy.HasValue)
+                    e.Graphics.TranslateTransform(translate.X + mouseWheelTx.Value, translate.Y + mouseWheelTy.Value);
+                else
+                    e.Graphics.TranslateTransform(translate.X, translate.Y);
+            }
+            else
+            {
+                if (mouseWheelTx.HasValue && mouseWheelTy.HasValue)
+                    e.Graphics.TranslateTransform(mouseWheelTx.Value, mouseWheelTy.Value);
+            }
 
+            if (mouseWheelSx.HasValue && mouseWheelSy.HasValue && mouseWheelSx.Value != 0.0 && mouseWheelSy.Value != 0.0)
+            {
+                e.Graphics.ScaleTransform(mouseWheelSx.Value, mouseWheelSy.Value);
+            }
+
             if (_mapImage != null)
             {
-                Trace.TraceInformation("Render Map");
+                Trace.TraceInformation("Render buffered map image");
                 e.Graphics.DrawImage(_mapImage, new PointF(0, 0));
             }
 
             //Thread.Sleep(100);
             if (_selectionImage != null)
             {
-                Trace.TraceInformation("Render Selection");
+                Trace.TraceInformation("Render buffered map selection");
                 e.Graphics.DrawImage(_selectionImage, new PointF(0, 0));
             }
 
@@ -1133,6 +1172,7 @@
         {
             var action = new MethodInvoker(() =>
             {
+                ResetMouseWheelPaintTransforms();
                 if (_map != null)
                 {
                     Trace.TraceInformation("Performing delayed resize to (" + this.Width + ", " + this.Height + ")");
@@ -1643,7 +1683,7 @@
             Trace.TraceInformation("Center is (" + x + ", " + y + ")");
 #endif
             var oldScale = _map.ViewScale;
-            _provider.SetViewScale(Math.Max(scale, MINIMUM_ZOOM_SCALE));
+            _provider.SetViewScale(NormalizeScale(scale));
 
             if (oldScale != _map.ViewScale)
             {
@@ -2195,6 +2235,12 @@
             HandleMouseUp(e);
         }
 
+        private void OnMapMouseWheel(object sender, MouseEventArgs e)
+        {
+            this.Focus();
+            HandleMouseWheel(e);
+        }
+
         private void OnMapMouseClick(object sender, MouseEventArgs e)
         {
             this.Focus();
@@ -2229,6 +2275,152 @@
             }
         }
 
+        private double? delayRenderScale;
+        private PointF? delayRenderViewCenter;
+        private float? mouseWheelSx = null;
+        private float? mouseWheelSy = null;
+        private float? mouseWheelTx = null;
+        private float? mouseWheelTy = null;
+        private int? mouseWheelDelta = null;
+        private System.Timers.Timer delayRenderTimer = null;
+
+        private void HandleMouseWheel(MouseEventArgs e)
+        {
+            if (delayRenderTimer == null)
+            {
+                delayRenderTimer = new System.Timers.Timer();
+                delayRenderTimer.Enabled = false;
+                delayRenderTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnDelayRender);
+                delayRenderTimer.Interval = this.MouseWheelDelayRenderInterval;
+            }
+
+            delayRenderTimer.Stop();
+            delayRenderTimer.Start();
+            Trace.TraceInformation("Postponed delay render");
+            Trace.TraceInformation("Mouse delta: " + e.Delta + " (" + (e.Delta > 0 ? "Zoom in" : "Zoom out") + ")");
+            //Negative delta = zoom out, Positive delta = zoom in
+            //deltas are in units of 120, so treat each multiple of 120 as a "zoom unit"
+
+            if (!mouseWheelSx.HasValue && !mouseWheelSy.HasValue)
+            {
+                mouseWheelSx = 1.0f;
+                mouseWheelSy = 1.0f;
+            }
+
+            if (!mouseWheelDelta.HasValue)
+                mouseWheelDelta = 0;
+
+            if (e.Delta > 0) //Zoom In
+            {
+                mouseWheelDelta++;
+                mouseWheelSx -= 0.1f;
+                mouseWheelSy -= 0.1f;
+                Invalidate();
+            }
+            else if (e.Delta < 0) //Zoom Out
+            {
+                mouseWheelDelta--;
+                mouseWheelSx += 0.1f;
+                mouseWheelSy += 0.1f;
+                Invalidate();
+            }
+
+            Trace.TraceInformation("Delta units is: " + mouseWheelDelta);
+
+            //Completely ripped the number crunching here from the AJAX viewer with no sense of shame whatsoever :)
+            delayRenderScale = GetNewScale(_map.ViewScale, mouseWheelDelta.Value);
+            double zoomChange = _map.ViewScale / delayRenderScale.Value;
+
+            //Determine the center of the new, zoomed map, in current screen device coords
+            double screenZoomCenterX = e.X - (e.X - this.Width / 2) / zoomChange;
+            double screenZoomCenterY = e.Y - (e.Y - this.Height / 2) / zoomChange;
+            delayRenderViewCenter = ScreenToMapUnits(screenZoomCenterX, screenZoomCenterY);
+
+            var mpu = this.MetersPerUnit;
+            var mpp = GetMetersPerPixel(_map.DisplayDpi);
+            var w = (_extX2 - _extX1) * this.MetersPerUnit / (delayRenderScale * mpp);
+            if (w > 20000)
+            {
+                w = 20000;
+            }
+            var h = w * ((double)this.Height / (double)this.Width);
+            var xClickOffset = screenZoomCenterX - this.Width / 2;
+            var yClickOffset = screenZoomCenterY - this.Height / 2;
+
+            //Set the paint transforms. Will be reset once the delayed render is fired away
+            mouseWheelTx = (float)((double)this.Width / 2 - w / 2 - xClickOffset * zoomChange);
+            mouseWheelTy = (float)((double)this.Height / 2 - h / 2 - yClickOffset * zoomChange);
+            mouseWheelSx = (float)(w / (double)this.Width);
+            mouseWheelSy = (float)(h / (double)this.Height);
+
+            Trace.TraceInformation("Paint transform (tx: " + mouseWheelTx + ", ty: " + mouseWheelTy + ", sx: " + mouseWheelSx + ", sy: " + mouseWheelSy + ")");
+        }
+
+        static double GetMetersPerPixel(int dpi)
+        {
+            return 0.0254 / dpi;
+        }
+
+        double GetNewScale(double currentScale, int wheelZoomDelta)
+        {
+            var newScale = currentScale;
+            /*
+            //handle finite zoom scales for tiled map
+            if (finscale)
+            {
+                var newScaleIndex = sci - wheelDelta;
+                if (newScaleIndex < 0)
+                {
+                    newScaleIndex = 0;
+                }
+                if (newScaleIndex > scales.length - 1)
+                {
+                    newScaleIndex = scales.length - 1;
+                }
+                newScale = scales[newScaleIndex];
+            }
+            //no finite zoom scales (untiled map)
+            else */
+            {
+                var zoomChange = Math.Pow(1.5, wheelZoomDelta);
+                newScale = zoomChange > 0 ? currentScale / zoomChange : this.MaxScale;
+                newScale = NormalizeScale(newScale);
+            }
+            return newScale;
+        }
+
+        double NormalizeScale(double scale)
+        {
+            if (scale < this.MinScale)
+                return this.MinScale;
+            if (scale > this.MaxScale)
+                return this.MaxScale;
+            return scale;
+        }
+
+        void OnDelayRender(object sender, System.Timers.ElapsedEventArgs e)
+        {
+            Trace.TraceInformation("Delay rendering");
+            Trace.TraceInformation("Set new map coordinates to (" + delayRenderViewCenter.Value.X + ", " + delayRenderViewCenter.Value.Y + " at " + delayRenderScale.Value + ")");
+            ResetMouseWheelPaintTransforms();
+            MethodInvoker action = () => { ZoomToView(delayRenderViewCenter.Value.X, delayRenderViewCenter.Value.Y, delayRenderScale.Value, true); };
+            if (this.InvokeRequired)
+                this.Invoke(action);
+            else
+                action();
+        }
+
+        private void ResetMouseWheelPaintTransforms()
+        {
+            delayRenderTimer.Stop();
+            mouseWheelSx = null;
+            mouseWheelSy = null;
+            mouseWheelTx = null;
+            mouseWheelTy = null;
+            mouseWheelDelta = 0;
+            Trace.TraceInformation("Mouse wheel paint transform reset");
+        }
+
         private void HandleMouseClick(MouseEventArgs e)
         {
             if (e.Button == MouseButtons.Right)



More information about the mapguide-commits mailing list