Repository: spyder-ide/spyder

Issue:
Zoom buttons state and scaling percentage update when "Fits plot to window" is activated
## Problem Description

I think when the `Fits plot to window` option is checked, the zooming in/out capability should be deactivated. This would also serve as a visual indicator that the `Fits plot to window` is on.

Also, the displayed % should be updated to reflect the actual scaling of the figure when it is fitted to the Plots plane.

![image](https://user-images.githubusercontent.com/10170372/58253957-af588c80-7d37-11e9-899b-386de5638cb7.png)




Discussion:

Resolving patch:
diff --git a/spyder/plugins/plots/widgets/figurebrowser.py b/spyder/plugins/plots/widgets/figurebrowser.py
--- a/spyder/plugins/plots/widgets/figurebrowser.py
+++ b/spyder/plugins/plots/widgets/figurebrowser.py
@@ -17,7 +17,7 @@
 # ---- Third library imports
 from qtconsole.svg import svg_to_image, svg_to_clipboard
 from qtpy.compat import getsavefilename, getexistingdirectory
-from qtpy.QtCore import Qt, Signal, QRect, QEvent, QPoint, QTimer, Slot
+from qtpy.QtCore import Qt, Signal, QRect, QEvent, QPoint, QSize, QTimer, Slot
 from qtpy.QtGui import QPixmap, QPainter, QKeySequence
 from qtpy.QtWidgets import (QApplication, QHBoxLayout, QMenu,
                             QVBoxLayout, QWidget, QGridLayout, QFrame,
@@ -121,19 +121,18 @@ def setup(self, mute_inline_plotting=None, show_plot_outline=None,
         self.thumbnails_sb = ThumbnailScrollBar(
             self.figviewer, background_color=self.background_color)
 
-        # Option actions :
+        toolbar = self.setup_toolbar()
         self.setup_option_actions(mute_inline_plotting,
                                   show_plot_outline,
                                   auto_fit_plotting)
 
-        # Create the layout :
+        # Create the layout.
         main_widget = QSplitter()
         main_widget.addWidget(self.figviewer)
         main_widget.addWidget(self.thumbnails_sb)
         main_widget.setFrameStyle(QScrollArea().frameStyle())
 
         self.tools_layout = QHBoxLayout()
-        toolbar = self.setup_toolbar()
         for widget in toolbar:
             self.tools_layout.addWidget(widget)
         self.tools_layout.addStretch()
@@ -188,12 +187,12 @@ def setup_toolbar(self):
         vsep2 = QFrame()
         vsep2.setFrameStyle(53)
 
-        zoom_out_btn = create_toolbutton(
+        self.zoom_out_btn = create_toolbutton(
                 self, icon=ima.icon('zoom_out'),
                 tip=_("Zoom out (Ctrl + mouse-wheel-down)"),
                 triggered=self.zoom_out)
 
-        zoom_in_btn = create_toolbutton(
+        self.zoom_in_btn = create_toolbutton(
                 self, icon=ima.icon('zoom_in'),
                 tip=_("Zoom in (Ctrl + mouse-wheel-up)"),
                 triggered=self.zoom_in)
@@ -211,8 +210,8 @@ def setup_toolbar(self):
         layout = QHBoxLayout(zoom_pan)
         layout.setSpacing(0)
         layout.setContentsMargins(0, 0, 0, 0)
-        layout.addWidget(zoom_out_btn)
-        layout.addWidget(zoom_in_btn)
+        layout.addWidget(self.zoom_out_btn)
+        layout.addWidget(self.zoom_in_btn)
         layout.addWidget(self.zoom_disp)
 
         return [savefig_btn, saveall_btn, copyfig_btn, closefig_btn,
@@ -311,7 +310,8 @@ def change_auto_fit_plotting(self, state):
         """Change the auto_fit_plotting option and scale images."""
         self.option_changed('auto_fit_plotting', state)
         self.figviewer.auto_fit_plotting = state
-        self.figviewer.scale_image()
+        self.zoom_out_btn.setEnabled(not state)
+        self.zoom_in_btn.setEnabled(not state)
 
     def set_shellwidget(self, shellwidget):
         """Bind the shellwidget instance to the figure browser"""
@@ -422,6 +422,7 @@ def auto_fit_plotting(self, value):
         else:
             self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
             self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
+        self.scale_image()
 
     def setup_figcanvas(self):
         """Setup the FigureCanvas."""
@@ -439,7 +440,7 @@ def eventFilter(self, widget, event):
         """A filter to control the zooming and panning of the figure canvas."""
 
         # ---- Zooming
-        if event.type() == QEvent.Wheel:
+        if event.type() == QEvent.Wheel and not self.auto_fit_plotting:
             modifiers = QApplication.keyboardModifiers()
             if modifiers == Qt.ControlModifier:
                 if event.angleDelta().y() > 0:
@@ -492,7 +493,6 @@ def zoom_in(self):
             self._scalefactor += 1
             self.scale_image()
             self._adjust_scrollbar(self._scalestep)
-            self.sig_zoom_changed.emit(self.get_scaling())
 
     def zoom_out(self):
         """Scale the image down by one scale step."""
@@ -500,7 +500,6 @@ def zoom_out(self):
             self._scalefactor -= 1
             self.scale_image()
             self._adjust_scrollbar(1/self._scalestep)
-            self.sig_zoom_changed.emit(self.get_scaling())
 
     def scale_image(self):
         """Scale the image size."""
@@ -529,11 +528,14 @@ def scale_image(self):
             else:
                 new_height = int(height)
                 new_width = int(height / fheight * fwidth)
-        self.figcanvas.setFixedSize(new_width, new_height)
+
+        if self.figcanvas.size() != QSize(new_width, new_height):
+            self.figcanvas.setFixedSize(new_width, new_height)
+            self.sig_zoom_changed.emit(self.get_scaling())
 
     def get_scaling(self):
         """Get the current scaling of the figure in percent."""
-        return self._scalestep**self._scalefactor*100
+        return self.figcanvas.width() / self.figcanvas.fwidth * 100
 
     def reset_original_image(self):
         """Reset the image to its original size."""


Test patch:
diff --git a/spyder/plugins/plots/widgets/tests/test_plots_widgets.py b/spyder/plugins/plots/widgets/tests/test_plots_widgets.py
--- a/spyder/plugins/plots/widgets/tests/test_plots_widgets.py
+++ b/spyder/plugins/plots/widgets/tests/test_plots_widgets.py
@@ -380,9 +380,10 @@ def test_zoom_figure_viewer(figbrowser, tmpdir, fmt):
         scaling_factor += zoom_step
         scale = scaling_step**scaling_factor
 
-        assert figbrowser.zoom_disp.value() == np.floor(scale * 100)
-        assert figcanvas.width() == np.floor(fwidth * scale)
-        assert figcanvas.height() == np.floor(fheight * scale)
+        assert (figbrowser.zoom_disp.value() ==
+                np.floor(int(fwidth * scale) / fwidth * 100))
+        assert figcanvas.width() == int(fwidth * scale)
+        assert figcanvas.height() == int(fheight * scale)
 
 
 @pytest.mark.parametrize("fmt", ['image/png', 'image/svg+xml'])
@@ -418,6 +419,8 @@ def test_autofit_figure_viewer(figbrowser, tmpdir, fmt):
         new_height = int(height)
         new_width = int(height / fheight * fwidth)
 
+    assert (figbrowser.zoom_disp.value() ==
+            np.floor(figcanvas.width() / fwidth * 100))
     assert figcanvas.width() == new_width
     assert figcanvas.height() == new_height