Переглянути джерело

wxGUI: Single-Window GUI: Integrate new map display wx.Panels into a AuiNotebook center pane #1735 (#1732)

Linda Kladivova 3 роки тому
батько
коміт
0537933d1c
1 змінених файлів з 190 додано та 144 видалено
  1. 190 144
      gui/wxpython/main_window/frame.py

+ 190 - 144
gui/wxpython/main_window/frame.py

@@ -69,7 +69,11 @@ from lmgr.toolbars import LMWorkspaceToolbar, LMToolsToolbar
 from lmgr.toolbars import LMMiscToolbar, LMNvizToolbar, DisplayPanelToolbar
 from lmgr.toolbars import LMMiscToolbar, LMNvizToolbar, DisplayPanelToolbar
 from lmgr.workspace import WorkspaceManager
 from lmgr.workspace import WorkspaceManager
 from lmgr.pyshell import PyShellWindow
 from lmgr.pyshell import PyShellWindow
-from lmgr.giface import LayerManagerGrassInterface
+from lmgr.giface import (
+    LayerManagerGrassInterface,
+    LayerManagerGrassInterfaceForMapDisplay,
+)
+from mapdisp.frame import MapPanel
 from datacatalog.catalog import DataCatalog
 from datacatalog.catalog import DataCatalog
 from gui_core.forms import GUI
 from gui_core.forms import GUI
 from gui_core.wrap import Menu, TextEntryDialog
 from gui_core.wrap import Menu, TextEntryDialog
@@ -151,8 +155,8 @@ class GMFrame(wx.Frame):
 
 
         # set pane sizes according to the full screen size of the primary monitor
         # set pane sizes according to the full screen size of the primary monitor
         size = wx.Display().GetGeometry().GetSize()
         size = wx.Display().GetGeometry().GetSize()
-        self.PANE_BEST_SIZE = tuple(t / 5 for t in size)
-        self.PANE_MIN_SIZE = tuple(t / 10 for t in size)
+        self.PANE_BEST_SIZE = tuple(t / 3 for t in size)
+        self.PANE_MIN_SIZE = tuple(t / 7 for t in size)
 
 
         # create widgets and build panes
         # create widgets and build panes
         self.CreateMenuBar()
         self.CreateMenuBar()
@@ -290,6 +294,22 @@ class GMFrame(wx.Frame):
             return self._auimgr.GetPane(name).IsShown()
             return self._auimgr.GetPane(name).IsShown()
         return False
         return False
 
 
+    def _createMapNotebook(self):
+        """Create Map Display notebook"""
+        # create the notebook off-window to avoid flicker
+        client_size = self.GetClientSize()
+        notebook_style = (
+            aui.AUI_NB_DEFAULT_STYLE | aui.AUI_NB_TAB_EXTERNAL_MOVE | wx.NO_BORDER
+        )
+        self.mapnotebook = aui.AuiNotebook(
+            self,
+            -1,
+            wx.Point(client_size.x, client_size.y),
+            wx.Size(430, 200),
+            agwStyle=notebook_style,
+        )
+        self.mapnotebook.SetArtProvider(aui.AuiDefaultTabArt())
+
     def _createDataCatalog(self, parent):
     def _createDataCatalog(self, parent):
         """Initialize Data Catalog widget"""
         """Initialize Data Catalog widget"""
         self.datacatalog = DataCatalog(parent=parent, giface=self._giface)
         self.datacatalog = DataCatalog(parent=parent, giface=self._giface)
@@ -360,21 +380,152 @@ class GMFrame(wx.Frame):
         else:
         else:
             self.pyshell = None
             self.pyshell = None
 
 
-    def _createMapDisplay(self, parent):
-        """Set up Map Display"""
-        # blank panel for testing
-        self.mapdisplay = wx.Panel(parent=parent)
+    def OnNewDisplay(self, event=None):
+        """Create new layer tree and map display window instance"""
+        self.NewDisplay()
+
+    def NewDisplay(self, name=None, show=True):
+        """Create new layer tree structure and associated map display and
+        add it to display notebook tab
+        :param name: name of new map display window
+        :param show: show map display window if True
+        """
+        Debug.msg(1, "GMFrame.NewDisplay(): idx=%d" % self.displayIndex)
+        if not name:
+            name = _("Map Display {number}").format(number=self.displayIndex + 1)
+
+        # make a new page in the bookcontrol for the layer tree (on page 0 of
+        # the notebook)
+        self.pg_panel = wx.Panel(
+            self.notebookLayers, id=wx.ID_ANY, style=wx.BORDER_NONE
+        )
+        self.notebookLayers.AddPage(page=self.pg_panel, text=name, select=True)
+        self.currentPage = self.notebookLayers.GetCurrentPage()
+        self.currentPageNum = self.notebookLayers.GetSelection()
+
+        def CreateNewMapDisplay(layertree):
+            """Callback function which creates a new Map Display window
+            :param layertree: layer tree object
+            :return: reference to mapdisplay instance
+            """
+            # create instance of Map Display interface
+            self._gifaceForDisplay = LayerManagerGrassInterfaceForMapDisplay(
+                self._giface, layertree
+            )
+
+            # create Map Display
+            mapdisplay = MapPanel(
+                parent=self.mapnotebook,
+                giface=self._gifaceForDisplay,
+                id=wx.ID_ANY,
+                tree=layertree,
+                lmgr=self,
+                Map=layertree.Map,
+                title=name,
+                size=globalvar.MAP_WINDOW_SIZE,
+            )
+            # add map display panel to notebook and make it current
+            self.mapnotebook.AddPage(mapdisplay, name)
+            self.mapnotebook.SetSelection(self.currentPageNum)
+
+            # set map display properties
+            self._setUpMapDisplay(mapdisplay)
+
+            return mapdisplay
+
+        # create layer tree (tree control for managing GIS layers)  and put on
+        # new notebook page and new map display frame
+        self.currentPage.maptree = LayerTree(
+            parent=self.currentPage,
+            giface=self._giface,
+            createNewMapDisplay=CreateNewMapDisplay,
+            id=wx.ID_ANY,
+            pos=wx.DefaultPosition,
+            size=wx.DefaultSize,
+            style=wx.TR_HAS_BUTTONS
+            | wx.TR_LINES_AT_ROOT
+            | wx.TR_HIDE_ROOT
+            | wx.TR_DEFAULT_STYLE
+            | wx.NO_BORDER
+            | wx.FULL_REPAINT_ON_RESIZE,
+            lmgr=self,
+            notebook=self.notebookLayers,
+            title=name,
+        )
+
+        # layout for controls
+        cb_boxsizer = wx.BoxSizer(wx.VERTICAL)
+        cb_boxsizer.Add(self.GetLayerTree(), proportion=1, flag=wx.EXPAND, border=1)
+        self.currentPage.SetSizer(cb_boxsizer)
+        cb_boxsizer.Fit(self.GetLayerTree())
+        self.currentPage.Layout()
+        self.GetLayerTree().Layout()
+
+        self.displayIndex += 1
+
+        return self.GetMapDisplay()
+
+    def _setUpMapDisplay(self, mapdisplay):
+        """Set up Map Display properties"""
+        page = self.currentPage
+
+        def CanCloseDisplay(askIfSaveWorkspace):
+            """Callback to check if user wants to close display"""
+            pgnum = self.notebookLayers.GetPageIndex(page)
+            name = self.notebookLayers.GetPageText(pgnum)
+            caption = _("Close Map Display {}").format(name)
+            if not askIfSaveWorkspace or (
+                askIfSaveWorkspace and self.workspace_manager.CanClosePage(caption)
+            ):
+                return pgnum
+            return None
+
+        mapdisplay.canCloseDisplayCallback = CanCloseDisplay
+
+        # bind various events
+        mapdisplay.Bind(
+            wx.EVT_ACTIVATE,
+            lambda event, page=self.currentPage: self._onMapDisplayFocus(page),
+        )
+
+        mapdisplay.starting3dMode.connect(
+            lambda firstTime, mapDisplayPage=self.currentPage: self._onStarting3dMode(
+                mapDisplayPage
+            )
+        )
+        mapdisplay.starting3dMode.connect(self.AddNvizTools)
+        mapdisplay.ending3dMode.connect(self.RemoveNvizTools)
+        mapdisplay.closingDisplay.connect(self._closePageNoEvent)
+
+        # set default properties
+        mapdisplay.SetProperties(
+            render=UserSettings.Get(
+                group="display", key="autoRendering", subkey="enabled"
+            ),
+            mode=UserSettings.Get(
+                group="display", key="statusbarMode", subkey="selection"
+            ),
+            alignExtent=UserSettings.Get(
+                group="display", key="alignExtent", subkey="enabled"
+            ),
+            constrainRes=UserSettings.Get(
+                group="display", key="compResolution", subkey="enabled"
+            ),
+            showCompExtent=UserSettings.Get(
+                group="display", key="showCompExtent", subkey="enabled"
+            ),
+        )
 
 
     def BuildPanes(self):
     def BuildPanes(self):
         """Build panes - toolbars as well as panels"""
         """Build panes - toolbars as well as panels"""
 
 
         # initialize all main widgets
         # initialize all main widgets
+        self._createMapNotebook()
         self._createDataCatalog(parent=self)
         self._createDataCatalog(parent=self)
         self._createDisplay(parent=self)
         self._createDisplay(parent=self)
         self._createSearchModule(parent=self)
         self._createSearchModule(parent=self)
         self._createConsole(parent=self)
         self._createConsole(parent=self)
         self._createPythonShell(parent=self)
         self._createPythonShell(parent=self)
-        self._createMapDisplay(parent=self)
         self.toolbars = {
         self.toolbars = {
             "workspace": LMWorkspaceToolbar(parent=self),
             "workspace": LMWorkspaceToolbar(parent=self),
             "tools": LMToolsToolbar(parent=self),
             "tools": LMToolsToolbar(parent=self),
@@ -416,8 +567,8 @@ class GMFrame(wx.Frame):
             )
             )
 
 
         self._auimgr.AddPane(
         self._auimgr.AddPane(
-            self.mapdisplay,
-            aui.AuiPaneInfo().Name("map display").CenterPane().PaneBorder(True),
+            self.mapnotebook,
+            aui.AuiPaneInfo().Name("map display content").CenterPane().PaneBorder(True),
         )
         )
 
 
         self._auimgr.AddPane(
         self._auimgr.AddPane(
@@ -552,17 +703,28 @@ class GMFrame(wx.Frame):
             ("toolbarWorkspace", "toolbarTools", "toolbarMisc", "toolbarNviz")
             ("toolbarWorkspace", "toolbarTools", "toolbarMisc", "toolbarNviz")
         ):
         ):
             self._auimgr.GetPane(toolbar).Row(1).Position(pos)
             self._auimgr.GetPane(toolbar).Row(1).Position(pos)
-        self._auimgr.Update()
 
 
         # create nviz tools tab
         # create nviz tools tab
         self.nviz = NvizToolWindow(
         self.nviz = NvizToolWindow(
-            parent=self.notebook, tree=self.GetLayerTree(), display=self.GetMapDisplay()
+            parent=self, tree=self.GetLayerTree(), display=self.GetMapDisplay()
         )
         )
-        idx = self.notebook.GetPageIndexByName("layers")
-        self.notebook.InsertNBPage(
-            index=idx + 1, page=self.nviz, text=_("3D view"), name="nviz"
+        self._auimgr.AddPane(
+            self.nviz,
+            aui.AuiPaneInfo()
+            .Name("nviz")
+            .Caption("3D view")
+            .Left()
+            .Layer(1)
+            .Position(3)
+            .BestSize(self.PANE_BEST_SIZE)
+            .MinSize(self.PANE_MIN_SIZE)
+            .CloseButton(False)
+            .MinimizeButton(True)
+            .MaximizeButton(True),
         )
         )
-        self.notebook.SetSelectionByName("nviz")
+
+        self._auimgr.GetPane("nviz").Show()
+        self._auimgr.Update()
 
 
         # this is a bit strange here since a new window is created everytime
         # this is a bit strange here since a new window is created everytime
         if not firstTime:
         if not firstTime:
@@ -573,8 +735,6 @@ class GMFrame(wx.Frame):
         """Remove nviz notebook page"""
         """Remove nviz notebook page"""
         # if more mapwindow3D were possible, check here if nb page should be
         # if more mapwindow3D were possible, check here if nb page should be
         # removed
         # removed
-        self.notebook.SetSelectionByName("layers")
-        self.notebook.DeleteNBPage("nviz")
 
 
         # hide toolbar
         # hide toolbar
         self._auimgr.GetPane("toolbarNviz").Hide()
         self._auimgr.GetPane("toolbarNviz").Hide()
@@ -582,6 +742,8 @@ class GMFrame(wx.Frame):
             ("toolbarWorkspace", "toolbarTools", "toolbarMisc")
             ("toolbarWorkspace", "toolbarTools", "toolbarMisc")
         ):
         ):
             self._auimgr.GetPane(toolbar).Row(1).Position(pos)
             self._auimgr.GetPane(toolbar).Row(1).Position(pos)
+        self._auimgr.DetachPane(self.nviz)
+        self.nviz.Destroy()
         self._auimgr.Update()
         self._auimgr.Update()
 
 
     def OnLocationWizard(self, event):
     def OnLocationWizard(self, event):
@@ -723,8 +885,7 @@ class GMFrame(wx.Frame):
         self.currentPage = self.notebookLayers.GetCurrentPage()
         self.currentPage = self.notebookLayers.GetCurrentPage()
         self.currentPageNum = self.notebookLayers.GetSelection()
         self.currentPageNum = self.notebookLayers.GetSelection()
         try:
         try:
-            self.GetMapDisplay().SetFocus()
-            self.GetMapDisplay().Raise()
+            self.mapnotebook.SetSelection(self.GetMapDisplayIndex())
         except Exception:
         except Exception:
             pass
             pass
 
 
@@ -744,6 +905,7 @@ class GMFrame(wx.Frame):
 
 
         maptree = self.notebookLayers.GetPage(event.GetSelection()).maptree
         maptree = self.notebookLayers.GetPage(event.GetSelection()).maptree
         maptree.GetMapDisplay().CleanUp()
         maptree.GetMapDisplay().CleanUp()
+        self.mapnotebook.DeletePage(self.GetMapDisplayIndex())
         maptree.Close(True)
         maptree.Close(True)
 
 
         self.currentPage = None
         self.currentPage = None
@@ -756,6 +918,7 @@ class GMFrame(wx.Frame):
         self.notebookLayers.Unbind(FN.EVT_FLATNOTEBOOK_PAGE_CLOSING)
         self.notebookLayers.Unbind(FN.EVT_FLATNOTEBOOK_PAGE_CLOSING)
         self.notebookLayers.DeletePage(page_index)
         self.notebookLayers.DeletePage(page_index)
         self.notebookLayers.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.OnCBPageClosing)
         self.notebookLayers.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.OnCBPageClosing)
+        self.mapnotebook.DeletePage(page_index)
 
 
     def RunSpecialCmd(self, command):
     def RunSpecialCmd(self, command):
         """Run command from command line, check for GUI wrappers"""
         """Run command from command line, check for GUI wrappers"""
@@ -884,7 +1047,7 @@ class GMFrame(wx.Frame):
         :param bool onlyCurrent: True to return only active mapdisplay
         :param bool onlyCurrent: True to return only active mapdisplay
                                  False for list of all mapdisplays
                                  False for list of all mapdisplays
 
 
-        :return: MapFrame instance (or list)
+        :return: MapPanel instance (or list)
         :return: None no mapdisplay selected
         :return: None no mapdisplay selected
         """
         """
         if onlyCurrent:
         if onlyCurrent:
@@ -903,6 +1066,11 @@ class GMFrame(wx.Frame):
         """Get all (open) map displays"""
         """Get all (open) map displays"""
         return self.GetMapDisplay(onlyCurrent=False)
         return self.GetMapDisplay(onlyCurrent=False)
 
 
+    def GetMapDisplayIndex(self):
+        """Get the index of the currently active map display tab.
+        Can be different than index of related layertree."""
+        return self.mapnotebook.GetPageIndex(self.GetMapDisplay())
+
     def GetLogWindow(self):
     def GetLogWindow(self):
         """Gets console for command output and messages"""
         """Gets console for command output and messages"""
         return self._gconsole
         return self._gconsole
@@ -1404,8 +1572,7 @@ class GMFrame(wx.Frame):
         if dlg.ShowModal() == wx.ID_OK:
         if dlg.ShowModal() == wx.ID_OK:
             name = dlg.GetValue()
             name = dlg.GetValue()
             self.notebookLayers.SetPageText(page=self.currentPageNum, text=name)
             self.notebookLayers.SetPageText(page=self.currentPageNum, text=name)
-            mapdisplay = self.GetMapDisplay()
-            mapdisplay.SetTitle(name)
+            self.mapnotebook.SetPageText(page_idx=self.GetMapDisplayIndex(), text=name)
         dlg.Destroy()
         dlg.Destroy()
 
 
     def OnRasterRules(self, event):
     def OnRasterRules(self, event):
@@ -1697,109 +1864,6 @@ class GMFrame(wx.Frame):
         # show ATM window
         # show ATM window
         dbmanager.Show()
         dbmanager.Show()
 
 
-    def OnNewDisplay(self, event=None):
-        """Create new layer tree and map display instance"""
-        self.NewDisplay()
-
-    def NewDisplay(self, name=None, show=True):
-        """Create new layer tree, which will
-        create an associated map display frame
-
-        :param name: name of new map display
-        :param show: show map display window if True
-
-        :return: reference to mapdisplay intance
-        """
-        Debug.msg(1, "GMFrame.NewDisplay(): idx=%d" % self.displayIndex)
-
-        # make a new page in the bookcontrol for the layer tree (on page 0 of
-        # the notebook)
-        self.pg_panel = wx.Panel(self.notebookLayers, id=wx.ID_ANY, style=wx.EXPAND)
-        if name:
-            dispName = name
-        else:
-            dispName = _("Map Display {number}").format(number=self.displayIndex + 1)
-        self.notebookLayers.AddPage(page=self.pg_panel, text=dispName, select=True)
-        self.currentPage = self.notebookLayers.GetCurrentPage()
-
-        # create layer tree (tree control for managing GIS layers)  and put on
-        # new notebook page
-        self.currentPage.maptree = LayerTree(
-            self.currentPage,
-            giface=self._giface,
-            id=wx.ID_ANY,
-            pos=wx.DefaultPosition,
-            size=wx.DefaultSize,
-            style=wx.TR_HAS_BUTTONS
-            | wx.TR_LINES_AT_ROOT
-            | wx.TR_HIDE_ROOT
-            | wx.TR_DEFAULT_STYLE
-            | wx.NO_BORDER
-            | wx.FULL_REPAINT_ON_RESIZE,
-            idx=self.displayIndex,
-            lmgr=self,
-            notebook=self.notebookLayers,
-            showMapDisplay=show,
-            title=dispName,
-        )
-
-        # layout for controls
-        cb_boxsizer = wx.BoxSizer(wx.VERTICAL)
-        cb_boxsizer.Add(self.GetLayerTree(), proportion=1, flag=wx.EXPAND, border=1)
-        self.currentPage.SetSizer(cb_boxsizer)
-        cb_boxsizer.Fit(self.GetLayerTree())
-        self.currentPage.Layout()
-        self.GetLayerTree().Layout()
-
-        mapdisplay = self.currentPage.maptree.mapdisplay
-        mapdisplay.Bind(
-            wx.EVT_ACTIVATE,
-            lambda event, page=self.currentPage: self._onMapDisplayFocus(page),
-        )
-        mapdisplay.starting3dMode.connect(
-            lambda firstTime, mapDisplayPage=self.currentPage: self._onStarting3dMode(
-                mapDisplayPage
-            )
-        )
-        mapdisplay.starting3dMode.connect(self.AddNvizTools)
-        mapdisplay.ending3dMode.connect(self.RemoveNvizTools)
-        mapdisplay.closingDisplay.connect(self._closePageNoEvent)
-
-        # use default window layout
-        if UserSettings.Get(group="general", key="defWindowPos", subkey="enabled"):
-            dim = UserSettings.Get(group="general", key="defWindowPos", subkey="dim")
-            idx = 4 + self.displayIndex * 4
-            try:
-                x, y = map(int, dim.split(",")[idx : idx + 2])
-                w, h = map(int, dim.split(",")[idx + 2 : idx + 4])
-                self.GetMapDisplay().SetPosition((x, y))
-                self.GetMapDisplay().SetSize((w, h))
-            except Exception:
-                pass
-
-        # set default properties
-        mapdisplay.SetProperties(
-            render=UserSettings.Get(
-                group="display", key="autoRendering", subkey="enabled"
-            ),
-            mode=UserSettings.Get(
-                group="display", key="statusbarMode", subkey="selection"
-            ),
-            alignExtent=UserSettings.Get(
-                group="display", key="alignExtent", subkey="enabled"
-            ),
-            constrainRes=UserSettings.Get(
-                group="display", key="compResolution", subkey="enabled"
-            ),
-            showCompExtent=UserSettings.Get(
-                group="display", key="showCompExtent", subkey="enabled"
-            ),
-        )
-
-        self.displayIndex += 1
-
-        return self.GetMapDisplay()
-
     def _onMapDisplayFocus(self, notebookLayerPage):
     def _onMapDisplayFocus(self, notebookLayerPage):
         """Changes bookcontrol page to page associated with display."""
         """Changes bookcontrol page to page associated with display."""
         # moved from mapdisp/frame.py
         # moved from mapdisp/frame.py
@@ -1937,9 +2001,6 @@ class GMFrame(wx.Frame):
             )
             )
         )
         )
 
 
-        # show map display
-        self.GetMapDisplay().Show()
-
     def OnAddVector(self, event):
     def OnAddVector(self, event):
         """Add vector map to the current layer tree"""
         """Add vector map to the current layer tree"""
         # start new map display if no display is available
         # start new map display if no display is available
@@ -1961,9 +2022,6 @@ class GMFrame(wx.Frame):
             )
             )
         )
         )
 
 
-        # show map display
-        self.GetMapDisplay().Show()
-
     def OnAddVectorTheme(self, event):
     def OnAddVectorTheme(self, event):
         """Add thematic vector map to the current layer tree"""
         """Add thematic vector map to the current layer tree"""
         self.GetLayerTree().AddLayer("thememap")
         self.GetLayerTree().AddLayer("thememap")
@@ -1989,9 +2047,6 @@ class GMFrame(wx.Frame):
             )
             )
         )
         )
 
 
-        # show map display
-        self.GetMapDisplay().Show()
-
     def OnAddRaster3D(self, event):
     def OnAddRaster3D(self, event):
         """Add 3D raster map to the current layer tree"""
         """Add 3D raster map to the current layer tree"""
         self.GetLayerTree().AddLayer("raster_3d")
         self.GetLayerTree().AddLayer("raster_3d")
@@ -2049,9 +2104,6 @@ class GMFrame(wx.Frame):
 
 
         self.GetLayerTree().AddLayer("command")
         self.GetLayerTree().AddLayer("command")
 
 
-        # show map display
-        self.GetMapDisplay().Show()
-
     def OnAddGroup(self, event):
     def OnAddGroup(self, event):
         """Add layer group"""
         """Add layer group"""
         # start new map display if no display is available
         # start new map display if no display is available
@@ -2060,9 +2112,6 @@ class GMFrame(wx.Frame):
 
 
         self.GetLayerTree().AddLayer("group")
         self.GetLayerTree().AddLayer("group")
 
 
-        # show map display
-        self.GetMapDisplay().Show()
-
     def OnAddGrid(self, event):
     def OnAddGrid(self, event):
         """Add grid map layer to the current layer tree"""
         """Add grid map layer to the current layer tree"""
         self.GetLayerTree().AddLayer("grid")
         self.GetLayerTree().AddLayer("grid")
@@ -2083,9 +2132,6 @@ class GMFrame(wx.Frame):
 
 
         self.GetLayerTree().AddLayer("labels")
         self.GetLayerTree().AddLayer("labels")
 
 
-        # show map display
-        self.GetMapDisplay().Show()
-
     def OnShowRegionExtent(self, event):
     def OnShowRegionExtent(self, event):
         """Add vector labels map layer to the current layer tree"""
         """Add vector labels map layer to the current layer tree"""
         # start new map display if no display is available
         # start new map display if no display is available