From a754de4c324518edc1ab931e01253a51b94bea99 Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Tue, 26 Jun 2018 11:17:30 +0200
Subject: [PATCH] Fixed panning in Layers view

---
 lib/Slic3r/GUI/Plater/2DToolpaths.pm | 69 ++++++++++++++++++----------
 xs/xsp/BoundingBox.xsp               |  4 ++
 2 files changed, 48 insertions(+), 25 deletions(-)

diff --git a/lib/Slic3r/GUI/Plater/2DToolpaths.pm b/lib/Slic3r/GUI/Plater/2DToolpaths.pm
index 96a252a08..382310f24 100644
--- a/lib/Slic3r/GUI/Plater/2DToolpaths.pm
+++ b/lib/Slic3r/GUI/Plater/2DToolpaths.pm
@@ -199,11 +199,11 @@ sub new {
         my $old_zoom = $self->_zoom;
         
         # Calculate the zoom delta and apply it to the current zoom factor
-        my $zoom = $e->GetWheelRotation() / $e->GetWheelDelta();
+        my $zoom = -$e->GetWheelRotation() / $e->GetWheelDelta();
         $zoom = max(min($zoom, 4), -4);
         $zoom /= 10;
         $self->_zoom($self->_zoom / (1-$zoom));
-        $self->_zoom(1) if $self->_zoom > 1;  # prevent from zooming out too much
+        $self->_zoom(1.25) if $self->_zoom > 1.25;  # prevent from zooming out too much
         
         {
             # In order to zoom around the mouse point we need to translate
@@ -227,7 +227,6 @@ sub new {
         }
         
         $self->_dirty(1);
-        $self->Refresh;
     });
     EVT_MOUSE_EVENTS($self, \&mouse_event);
     
@@ -255,8 +254,8 @@ sub mouse_event {
     return if !$self->GetParent->enabled;
     
     my $pos = Slic3r::Pointf->new($e->GetPositionXY);
-    if ($e->Entering && &Wx::wxMSW) {
-        # wxMSW needs focus in order to catch mouse wheel events
+    if ($e->Entering && (&Wx::wxMSW || $^O eq 'linux')) {
+        # wxMSW and Linux needs focus in order to catch key events
         $self->SetFocus;
     } elsif ($e->Dragging) {
         if ($e->LeftIsDown || $e->MiddleIsDown || $e->RightIsDown) {
@@ -276,7 +275,6 @@ sub mouse_event {
                 );
                 
                 $self->_dirty(1);
-                $self->Refresh;
             }
             $self->_drag_start_xy($pos);
         }
@@ -631,6 +629,27 @@ sub Resize {
     glLoadIdentity();
     
     my $bb = $self->bb->clone;
+
+    # rescale in dependence of window aspect ratio
+    my $bb_size = $bb->size;    
+    my $ratio_x = ($x != 0.0) ? $bb_size->x / $x : 1.0;
+    my $ratio_y = ($y != 0.0) ? $bb_size->y / $y : 1.0;
+        
+    if ($ratio_y < $ratio_x) {
+        if ($ratio_y != 0.0) {
+            my $new_size_y = $bb_size->y * $ratio_x / $ratio_y;
+            my $half_delta_size_y = 0.5 * ($new_size_y - $bb_size->y);        
+            $bb->set_y_min($bb->y_min - $half_delta_size_y);
+            $bb->set_y_max($bb->y_max + $half_delta_size_y);
+        }
+    } elsif ($ratio_x < $ratio_y) {
+        if ($ratio_x != 0.0) {
+            my $new_size_x = $bb_size->x * $ratio_y / $ratio_x;
+            my $half_delta_size_x = 0.5 * ($new_size_x - $bb_size->x);        
+            $bb->set_x_min($bb->x_min - $half_delta_size_x);
+            $bb->set_x_max($bb->x_max + $half_delta_size_x);
+        }
+    }
     
     # center bounding box around origin before scaling it
     my $bb_center = $bb->center;
@@ -645,25 +664,25 @@ sub Resize {
     # translate camera
     $bb->translate(@{$self->_camera_target});
     
-    # keep camera_bb within total bb
-    # (i.e. prevent user from panning outside the bounding box)
-    {
-        my @translate = (0,0);
-        if ($bb->x_min < $self->bb->x_min) {
-            $translate[X] += $self->bb->x_min - $bb->x_min;
-        }
-        if ($bb->y_min < $self->bb->y_min) {
-            $translate[Y] += $self->bb->y_min - $bb->y_min;
-        }
-        if ($bb->x_max > $self->bb->x_max) {
-            $translate[X] -= $bb->x_max - $self->bb->x_max;
-        }
-        if ($bb->y_max > $self->bb->y_max) {
-            $translate[Y] -= $bb->y_max - $self->bb->y_max;
-        }
-        $self->_camera_target->translate(@translate);
-        $bb->translate(@translate);
-    }
+#    # keep camera_bb within total bb
+#    # (i.e. prevent user from panning outside the bounding box)
+#    {
+#        my @translate = (0,0);
+#        if ($bb->x_min < $self->bb->x_min) {
+#            $translate[X] += $self->bb->x_min - $bb->x_min;
+#        }
+#        if ($bb->y_min < $self->bb->y_min) {
+#            $translate[Y] += $self->bb->y_min - $bb->y_min;
+#        }
+#        if ($bb->x_max > $self->bb->x_max) {
+#            $translate[X] -= $bb->x_max - $self->bb->x_max;
+#        }
+#        if ($bb->y_max > $self->bb->y_max) {
+#            $translate[Y] -= $bb->y_max - $self->bb->y_max;
+#        }
+#        $self->_camera_target->translate(@translate);
+#        $bb->translate(@translate);
+#    }
     
     # save camera
     $self->_camera_bb($bb);
diff --git a/xs/xsp/BoundingBox.xsp b/xs/xsp/BoundingBox.xsp
index df8e6baea..ebeb17822 100644
--- a/xs/xsp/BoundingBox.xsp
+++ b/xs/xsp/BoundingBox.xsp
@@ -29,6 +29,10 @@
     int x_max() %code{% RETVAL = THIS->max.x; %};
     int y_min() %code{% RETVAL = THIS->min.y; %};
     int y_max() %code{% RETVAL = THIS->max.y; %};
+    void set_x_min(double val) %code{% THIS->min.x = val; %};
+    void set_x_max(double val) %code{% THIS->max.x = val; %};
+    void set_y_min(double val) %code{% THIS->min.y = val; %};
+    void set_y_max(double val) %code{% THIS->max.y = val; %};
     std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld;%ld,%ld", THIS->min.x, THIS->min.y, THIS->max.x, THIS->max.y); RETVAL = buf; %};
     bool defined() %code{% RETVAL = THIS->defined; %};