Browse Source

wxGUI: new context menu for statusbar settings (#2251)

Linda Kladivova 2 years ago
parent
commit
0b5618d0f5

+ 3 - 4
gui/wxpython/gcp/mapdisplay.py

@@ -106,7 +106,6 @@ class MapPanel(SingleMapPanel):
             sbgcp.SbRMSError,
         ]
         self.statusbar = self.CreateStatusbar(statusbarItems)
-        self.statusbarManager.SetMode(5)  # goto GCP
 
         #
         # Init map display (buffered DC & set default cursor)
@@ -163,6 +162,9 @@ class MapPanel(SingleMapPanel):
         # windows
         self.list = self.CreateGCPList()
 
+        # set Go To GCP item as active in statusbar
+        self.mapWindowProperties.sbItem = 5
+
         # self.SrcMapWindow.SetSize((300, 300))
         # self.TgtMapWindow.SetSize((300, 300))
         self.list.SetSize((100, 150))
@@ -210,9 +212,6 @@ class MapPanel(SingleMapPanel):
 
         self.decorationDialog = None  # decoration/overlays
 
-        # doing nice things in statusbar when other things are ready
-        self.statusbarManager.Update()
-
     def _setUpMapWindow(self, mapWindow):
         # TODO: almost the same implementation as for MapPanelBase (only names differ)
         # enable or disable zoom history tool

+ 0 - 1
gui/wxpython/gui_core/mapdisp.py

@@ -347,7 +347,6 @@ class MapPanelBase(wx.Panel):
         self.statusbarManager.AddStatusbarItem(
             sb.SbRender(self, statusbar=statusbar, position=2)
         )
-        self.statusbarManager.Update()
         return statusbar
 
     def AddStatusbarPane(self):

+ 3 - 5
gui/wxpython/image2target/ii2t_mapdisplay.py

@@ -111,8 +111,6 @@ class MapPanel(SingleMapPanel):
         # create statusbar and its manager
         self.statusbar = self.CreateStatusbar(statusbarItems)
 
-        self.statusbarManager.SetMode(5)  # goto GCP
-
         #
         # Init map display (buffered DC & set default cursor)
         #
@@ -168,6 +166,9 @@ class MapPanel(SingleMapPanel):
         # windows
         self.list = self.CreateGCPList()
 
+        # set Go To GCP item as active in statusbar
+        self.mapWindowProperties.sbItem = 5
+
         # self.SrcMapWindow.SetSize((300, 300))
         # self.TgtMapWindow.SetSize((300, 300))
         self.list.SetSize((100, 150))
@@ -215,9 +216,6 @@ class MapPanel(SingleMapPanel):
 
         self.decorationDialog = None  # decoration/overlays
 
-        # doing nice things in statusbar when other things are ready
-        self.statusbarManager.Update()
-
     def _setUpMapWindow(self, mapWindow):
         # TODO: almost the same implementation as for MapPanelBase (only names differ)
         # enable or disable zoom history tool

+ 4 - 6
gui/wxpython/mapdisp/frame.py

@@ -451,7 +451,7 @@ class MapPanel(SingleMapPanel):
         self.statusbarManager.DisableStatusbarItemsByClass(
             self.statusbarItemsDisabledInNviz
         )
-        self.statusbarManager.SetMode(0)
+        self.mapWindowProperties.sbItem = 0
 
         # erase map window
         self.MapWindow.EraseMap()
@@ -548,12 +548,11 @@ class MapPanel(SingleMapPanel):
             pass
 
         # update status bar
+        self.SetStatusText(_("Please wait, unloading data..."), 0)
         self.statusbarManager.disabledItems = {}
-        self.statusbarManager.SetMode(
-            UserSettings.Get(group="display", key="statusbarMode", subkey="selection")
+        self.mapWindowProperties.sbItem = UserSettings.Get(
+            group="display", key="statusbarMode", subkey="selection"
         )
-        self.SetStatusText(_("Please wait, unloading data..."), 0)
-        self.statusbarManager.Update()
 
         # unloading messages from library cause highlight anyway
         self._giface.WriteCmdLog(
@@ -1563,7 +1562,6 @@ class MapPanel(SingleMapPanel):
         self.mapWindowProperties.autoRender = render
         if self.statusbarManager:
             self.statusbarManager.SetMode(mode)
-            self.StatusbarUpdate()
         self.mapWindowProperties.useDefinedProjection = projection
         self.mapWindowProperties.showRegion = showCompExtent
         self.mapWindowProperties.alignExtent = alignExtent

+ 29 - 25
gui/wxpython/mapdisp/properties.py

@@ -65,7 +65,7 @@ class PropertyItem:
     def _disconnect(self):
         self.mapWindowPropertyChanged().disconnect(self._setValue)
 
-    def _onToggleCheckBox(self, event):
+    def _onToggle(self, event):
         self._disconnect()
         self.mapWindowProperty = self.GetValue()
         self._connect()
@@ -83,7 +83,7 @@ class ChBRender(PropertyItem):
         self.widget.SetValue(self.mapWindowProperty)
         self.widget.SetToolTip(wx.ToolTip(_("Enable/disable auto-rendering")))
 
-        self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox)
+        self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle)
         self._connect()
 
     @property
@@ -124,7 +124,7 @@ class ChBAlignExtent(PropertyItem):
                 )
             )
         )
-        self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox)
+        self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle)
         self._connect()
 
     @property
@@ -162,7 +162,7 @@ class ChBResolution(PropertyItem):
                 )
             )
         )
-        self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox)
+        self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle)
         self._connect()
 
     @property
@@ -176,9 +176,9 @@ class ChBResolution(PropertyItem):
     def mapWindowPropertyChanged(self):
         return self._properties.resolutionChanged
 
-    def _onToggleCheckBox(self, event):
+    def _onToggle(self, event):
         """Update display when toggle display mode"""
-        super()._onToggleCheckBox(event)
+        super()._onToggle(event)
 
         # redraw map if auto-rendering is enabled
         if self._properties.autoRender:
@@ -208,7 +208,7 @@ class ChBShowRegion(PropertyItem):
                 )
             )
         )
-        self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox)
+        self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle)
         self._connect()
 
     @property
@@ -222,12 +222,12 @@ class ChBShowRegion(PropertyItem):
     def mapWindowPropertyChanged(self):
         return self._properties.showRegionChanged
 
-    def _onToggleCheckBox(self, event):
+    def _onToggle(self, event):
         """Shows/Hides extent (comp. region) in map canvas.
 
         Shows or hides according to checkbox value.
         """
-        super()._onToggleCheckBox(event)
+        super()._onToggle(event)
 
         # redraw map if auto-rendering is enabled
         if self._properties.autoRender:
@@ -253,7 +253,7 @@ class ChBProjection(PropertyItem):
                 )
             )
         )
-        self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox)
+        self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle)
         self._connect()
 
     @property
@@ -267,8 +267,8 @@ class ChBProjection(PropertyItem):
     def mapWindowPropertyChanged(self):
         return self._properties.useDefinedProjectionChanged
 
-    def _onToggleCheckBox(self, event):
-        super()._onToggleCheckBox(event)
+    def _onToggle(self, event):
+        super()._onToggle(event)
         epsg = self._properties.epsg
         if epsg:
             label = _("{label} (EPSG: {epsg})").format(
@@ -279,10 +279,11 @@ class ChBProjection(PropertyItem):
             self.widget.SetLabel(self.defaultLabel)
 
 
-class RBShowInStatusbar:
+class RBShowInStatusbar(PropertyItem):
     """Radiobox managing widgets in statusbar."""
 
-    def __init__(self, parent, sbmanager):
+    def __init__(self, parent, mapWindowProperties, sbmanager):
+        PropertyItem.__init__(self, mapWindowProperties)
         self.name = "showInStatusbar"
         self.statusbarManager = sbmanager
 
@@ -295,10 +296,11 @@ class RBShowInStatusbar:
             majorDimension=1,
             style=wx.RA_SPECIFY_COLS,
         )
-        self._setValue(self.statusbarManager.GetMode())
+        self._setValue(self.mapWindowProperty)
         self._disableItems()
 
-        self.widget.Bind(wx.EVT_RADIOBOX, self._onToggleRadioBox)
+        self.widget.Bind(wx.EVT_RADIOBOX, self._onToggle)
+        self._connect()
 
     def _setValue(self, mode):
         self.widget.SetSelection(mode)
@@ -311,16 +313,16 @@ class RBShowInStatusbar:
         for item in self.statusbarManager.disabledItems.keys():
             self.widget.EnableItem(n=item, enable=False)
 
-    def GetWidget(self):
-        """Returns underlying widget.
+    @property
+    def mapWindowProperty(self):
+        return self._properties.sbItem
 
-        :return: widget or None if doesn't exist
-        """
-        return self.widget
+    @mapWindowProperty.setter
+    def mapWindowProperty(self, value):
+        self._properties.sbItem = value
 
-    def _onToggleRadioBox(self, event):
-        self.statusbarManager.SetMode(self.GetValue())
-        self.statusbarManager.Update()
+    def mapWindowPropertyChanged(self):
+        return self._properties.sbItemChanged
 
 
 class MapDisplayPropertiesDialog(wx.Dialog):
@@ -433,7 +435,9 @@ class MapDisplayPropertiesDialog(wx.Dialog):
         sizer = wx.BoxSizer(wx.VERTICAL)
 
         self.shownInStatusbar = RBShowInStatusbar(
-            parent=panel, sbmanager=self.statusbarManager
+            parent=panel,
+            mapWindowProperties=self.mapWindowProperties,
+            sbmanager=self.statusbarManager,
         )
         sizer.Add(
             self.shownInStatusbar.GetWidget(),

+ 46 - 2
gui/wxpython/mapdisp/statusbar.py

@@ -32,7 +32,7 @@ import wx
 from core import utils
 from core.gcmd import RunCommand
 from core.settings import UserSettings
-from gui_core.wrap import TextCtrl
+from gui_core.wrap import TextCtrl, Menu, NewId
 
 from grass.pydispatch.signal import Signal
 
@@ -85,6 +85,9 @@ class SbManager:
         self.progressbar.progressShown.connect(self._progressShown)
         self.progressbar.progressHidden.connect(self._progressHidden)
 
+        self.statusbar.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
+        self.mapFrame.mapWindowProperties.sbItemChanged.connect(self.SetMode)
+
         self._oldStatus = ""
 
         self.disabledItems = {}
@@ -150,6 +153,14 @@ class SbManager:
             if value.GetPosition() == 0
         ]
 
+    def GetDisabledItemLabels(self):
+        """Get list of disabled item labels"""
+        return [
+            value.label
+            for value in self.disabledItems.values()
+            if value.GetPosition() == 0
+        ]
+
     def ShowItem(self, itemName):
         """Invokes showing of particular item
 
@@ -181,6 +192,9 @@ class SbManager:
                     group="display", key="statusbarMode", subkey="selection"
                 )
             )
+            self.mapFrame.mapWindowProperties.sbItem = UserSettings.Get(
+                group="display", key="statusbarMode", subkey="selection"
+            )
         self.Reposition()
 
         self._postInitialized = True
@@ -252,12 +266,13 @@ class SbManager:
         self.statusbar.SetStatusText(self._oldStatus, 0)
 
     def SetMode(self, mode):
-        """Sets current mode
+        """Sets current mode and updates statusbar
 
         Mode is usually driven by user through map display settings.
         """
         self._mode = mode
         self._modeIndexSet = True
+        self.Update()
 
     def GetMode(self):
         """Returns current mode"""
@@ -270,6 +285,35 @@ class SbManager:
         if text:
             self.statusbar.SetStatusText(text)
 
+    def OnContextMenu(self, event):
+        """Popup context menu enabling to choose a widget that will be shown in statusbar."""
+
+        def setSbItemProperty(idx):
+            self.mapFrame.mapWindowProperties.sbItem = idx
+
+        def getSbItemProperty():
+            return self.mapFrame.mapWindowProperties.sbItem
+
+        menu = Menu()
+        for i, label in enumerate(self.GetItemLabels()):
+            wxid = NewId()
+            self.statusbar.Bind(
+                wx.EVT_MENU,
+                lambda evt, idx=i: setSbItemProperty(idx),
+                id=wxid,
+            )
+            menu.Append(wxid, label, kind=wx.ITEM_RADIO)
+            item = menu.FindItem(wxid)[0]
+            if i == getSbItemProperty():
+                item.Check(item.IsChecked() is False)
+            if label in (self.GetDisabledItemLabels()):
+                item.Enable(enable=False)
+
+        # show the popup menu
+        self.statusbar.PopupMenu(menu)
+        menu.Destroy()
+        event.Skip()
+
 
 class SbItem:
     """Base class for statusbar items.

+ 12 - 0
gui/wxpython/mapwin/base.py

@@ -44,6 +44,8 @@ class MapWindowProperties(object):
         self.useDefinedProjectionChanged = Signal(
             "MapWindowProperties.useDefinedProjectionChanged"
         )
+        self._sbItem = None
+        self.sbItemChanged = Signal("MapWindowProperties.sbItemChanged")
 
     def setValuesFromUserSettings(self):
         """Convenient function to get values from user settings into this object."""
@@ -112,6 +114,16 @@ class MapWindowProperties(object):
     def epsg(self):
         return UserSettings.Get(group="projection", key="statusbar", subkey="epsg")
 
+    @property
+    def sbItem(self):
+        return self._sbItem
+
+    @sbItem.setter
+    def sbItem(self, mode):
+        if mode != self._sbItem:
+            self._sbItem = mode
+            self.sbItemChanged.emit(mode=mode)
+
 
 class MapWindowBase(object):
     """Abstract map display window class

+ 3 - 4
gui/wxpython/photo2image/ip2i_mapdisplay.py

@@ -104,7 +104,6 @@ class MapPanel(SingleMapPanel):
 
         # create statusbar and its manager
         self.statusbar = self.CreateStatusbar(statusbarItems)
-        self.statusbarManager.SetMode(5)  # goto GCP
 
         #
         # Init map display (buffered DC & set default cursor)
@@ -161,6 +160,9 @@ class MapPanel(SingleMapPanel):
         # windows
         self.list = self.CreateGCPList()
 
+        # set Go To GCP item as active in statusbar
+        self.mapWindowProperties.sbItem = 5
+
         # self.SrcMapWindow.SetSize((300, 300))
         # self.TgtMapWindow.SetSize((300, 300))
         self.list.SetSize((100, 150))
@@ -208,9 +210,6 @@ class MapPanel(SingleMapPanel):
 
         self.decorationDialog = None  # decoration/overlays
 
-        # doing nice things in statusbar when other things are ready
-        self.statusbarManager.Update()
-
     def _setUpMapWindow(self, mapWindow):
         # TODO: almost the same implementation as for MapPanelBase (only names differ)
         # enable or disable zoom history tool