Skip to content

Commit

Permalink
wxGUI: refactoring: Map Display inheriting from wx.Panel (OSGeo#1675)
Browse files Browse the repository at this point in the history
Map Display GUI logic is being changed. For purposes of the Single-Window GUI, MapFrameBase was replaced by MapPanelBase. It subsequently influeced all GUI tools which had been build based on MapFrameBase.
All these tools had to be adapted for new wx.Panel based solution.
  • Loading branch information
lindakarlovska authored and ninsbl committed Feb 17, 2023
1 parent 4fa2258 commit a94ba36
Show file tree
Hide file tree
Showing 23 changed files with 914 additions and 468 deletions.
10 changes: 7 additions & 3 deletions doc/gui/wxpython/example/README
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,14 @@ a few more things to be done.

def OnExample(self, event):
"""!Launch ExampleTool"""
from example.frame import ExampleMapFrame
win = ExampleMapFrame(parent=self, giface=self._giface)
from example.frame import ExampleMapDisplay

frame = wx.Frame(
parent=None, size=globalvar.MAP_WINDOW_SIZE, title=_("Example Tool")
)
win = ExampleMapDisplay(parent=frame, giface=self._giface)
win.CentreOnScreen()

win.Show()

7. Run make again.
Expand Down
111 changes: 62 additions & 49 deletions doc/gui/wxpython/example/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
@brief Example tool for displaying raster map and related information
Classes:
- frame::ExampleMapFrame
- frame::ExampleMapPanel
- frame::ExampleMapDisplay
- frame::ExampleInfoTextManager
(C) 2011-2014 by the GRASS Development Team
Expand All @@ -27,16 +28,17 @@
# So we need to import it before any of the GUI code.
from grass.script import core as gcore

from gui_core.mapdisp import SingleMapFrame
from gui_core.mapdisp import SingleMapPanel, FrameMixin
from mapwin.buffered import BufferedMapWindow
from mapwin.base import MapWindowProperties
from mapdisp import statusbar as sb
from core.render import Map
from core.debug import Debug
from core.gcmd import RunCommand, GError
from core import globalvar

from toolbars import ExampleMapToolbar, ExampleMiscToolbar, ExampleMainToolbar
from dialogs import ExampleMapDialog
from example.toolbars import ExampleMapToolbar, ExampleMiscToolbar, ExampleMainToolbar
from example.dialogs import ExampleMapDialog

# It is possible to call grass library functions (in C) directly via ctypes
# however this is less stable. Example is available in trunk/doc/python/, ctypes
Expand All @@ -52,13 +54,13 @@
# errMsg = _("Loading raster lib failed.\n%s") % e


class ExampleMapFrame(SingleMapFrame):
"""! Main frame of example tool.
class ExampleMapPanel(SingleMapPanel):
"""! Main panel of example tool.
Inherits from SingleMapFrame, so map is displayed in one map widow.
In case two map windows are needed, use DoubleMapFrame from (gui_core.mapdisp).
Inherits from SingleMapPanel, so map is displayed in one map widow.
In case two map windows are needed, use DoubleMapPanel from (gui_core.mapdisp).
@see IClassMapFrame in iclass.frame
@see IClassMapPanel in iclass.frame
"""

def __init__(
Expand All @@ -71,22 +73,21 @@ def __init__(
name="exampleWindow",
**kwargs,
):
"""!Map Frame constructor
"""!Map Panel constructor
@param parent (no parent is expected)
@param title window title
@param toolbars list of active toolbars (default value represents all toolbars)
@param size default size
"""
SingleMapFrame.__init__(
SingleMapPanel.__init__(
self, parent=parent, title=title, name=name, Map=Map(), **kwargs
)

# Place debug message where appropriate
# and set debug level from 1 to 5 (higher to lower level functions).
# To enable debug mode write:
# > g.gisenv set=WX_DEBUG=5
Debug.msg(1, "ExampleMapFrame.__init__()")
Debug.msg(1, "ExampleMapPanel.__init__()")

#
# Add toolbars to aui manager
Expand All @@ -109,7 +110,7 @@ def __init__(
#

# choose items in statusbar choice, which makes sense for your application
self.statusbarItems = [
statusbarItems = [
sb.SbCoordinates,
sb.SbRegionExtent,
sb.SbCompRegionExtent,
Expand All @@ -121,24 +122,7 @@ def __init__(
sb.SbGoTo,
sb.SbProjection,
]

# create statusbar and its manager
statusbar = self.CreateStatusBar(number=4, style=0)
statusbar.SetStatusWidths([-5, -2, -1, -1])
self.statusbarManager = sb.SbManager(mapframe=self, statusbar=statusbar)

# fill statusbar manager
self.statusbarManager.AddStatusbarItemsByClass(
self.statusbarItems, mapframe=self, statusbar=statusbar
)
self.statusbarManager.AddStatusbarItem(
sb.SbMask(self, statusbar=statusbar, position=2)
)
self.statusbarManager.AddStatusbarItem(
sb.SbRender(self, statusbar=statusbar, position=3)
)

self.statusbarManager.Update()
self.statusbar = self.CreateStatusbar(statusbarItems)

# create map window
self.MapWindow = BufferedMapWindow(
Expand All @@ -164,7 +148,6 @@ def __init__(
self.GetMapToolbar().SelectDefault()

self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

self.SetSize(size)

Expand All @@ -173,20 +156,10 @@ def __del__(self):
gcore.del_temp_region()

def OnCloseWindow(self, event):
"""!Destroy frame"""
"""!Destroy panel"""
self._mgr.UnInit()
self.Destroy()

def IsStandalone(self):
"""!Check if application is standalone.
Standalone application can work without parent.
Parent can be e.g. Layer Manager.
"""
if self.parent:
return False

return True

def InitVariables(self):
"""!Initialize any variables nneded by application"""
self.currentRaster = None
Expand Down Expand Up @@ -224,6 +197,9 @@ def _addPanes(self):
.Left(),
)

# statusbar
self.AddStatusbarPane()

def AddToolbar(self, name):
"""!Add defined toolbar to the window
Expand All @@ -234,7 +210,8 @@ def AddToolbar(self, name):
"""
# see wx.aui.AuiPaneInfo documentation for understanding all options
if name == "MapToolbar":
self.toolbars[name] = ExampleMapToolbar(self, self._toolSwitcher)
if "MapToolbar" not in self.toolbars:
self.toolbars[name] = ExampleMapToolbar(self, self._toolSwitcher)

self._mgr.AddPane(
self.toolbars[name],
Expand All @@ -254,7 +231,8 @@ def AddToolbar(self, name):
)

if name == "MiscToolbar":
self.toolbars[name] = ExampleMiscToolbar(self)
if "MiscToolbar" not in self.toolbars:
self.toolbars[name] = ExampleMiscToolbar(self)

self._mgr.AddPane(
self.toolbars[name],
Expand All @@ -274,7 +252,8 @@ def AddToolbar(self, name):
)

if name == "MainToolbar":
self.toolbars[name] = ExampleMainToolbar(self)
if "MainToolbar" not in self.toolbars:
self.toolbars[name] = ExampleMainToolbar(self)

self._mgr.AddPane(
self.toolbars[name],
Expand Down Expand Up @@ -325,7 +304,7 @@ def SetLayer(self, name):
@param name layer (raster) name
"""
Debug.msg(3, "ExampleMapFrame.SetLayer(): name=%s" % name)
Debug.msg(3, "ExampleMapPanel.SetLayer(): name=%s" % name)

# this simple application enables to keep only one raster
self.GetMap().DeleteAllLayers()
Expand Down Expand Up @@ -378,6 +357,40 @@ def UpdateStatistics(self):
self.info.WriteStatistics(name=self.currentRaster, statDict=stats)


class ExampleMapDisplay(FrameMixin, ExampleMapPanel):
"""Map display for wrapping map panel with frame methods"""

def __init__(self, parent, giface, **kwargs):

# init map panel
ExampleMapPanel.__init__(
self,
parent=parent,
giface=giface,
**kwargs,
)
# set system icon
parent.iconsize = (16, 16)
parent.SetIcon(
wx.Icon(
os.path.join(globalvar.ICONDIR, "grass_map.ico"), wx.BITMAP_TYPE_ICO
)
)

# bindings
parent.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

# extend shortcuts and create frame accelerator table
self.shortcuts_table.append((self.OnFullScreen, wx.ACCEL_NORMAL, wx.WXK_F11))
self._initShortcuts()

# add Map Display panel to Map Display frame
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self, proportion=1, flag=wx.EXPAND)
parent.SetSizer(sizer)
parent.Layout()


class ExampleInfoTextManager:
"""!Class for displaying information.
Expand Down
36 changes: 24 additions & 12 deletions doc/gui/wxpython/example/g.gui.example.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
############################################################################

# %module
# % description: Example GUI application which displays raster map and further information
# % description: Example GUI app which displays raster map and further information
# % keyword: example
# % keyword: GUI
# % keyword: raster
Expand All @@ -31,7 +31,6 @@

import os
import sys
import wx


# i18n is taken care of in the grass library code.
Expand All @@ -43,15 +42,21 @@
if wxbase not in sys.path:
sys.path.append(wxbase)

from core.globalvar import CheckWxVersion
from core.giface import StandaloneGrassInterface
from core.utils import GuiModuleMain
from core.settings import UserSettings
from example.frame import ExampleMapFrame


def main():
options, flags = gcore.parser()

import wx

from grass.script.setup import set_gui_path

set_gui_path()

from core.globalvar import CheckWxVersion, MAP_WINDOW_SIZE
from core.giface import StandaloneGrassInterface
from core.settings import UserSettings
from example.frame import ExampleMapDisplay

if options["input"]:
map_name = gcore.find_file(name=options["input"], element="cell")["fullname"]
if not map_name:
Expand All @@ -72,15 +77,22 @@ def main():
wx.InitAllImageHandlers()

# show main frame
giface = StandaloneGrassInterface()
frame = ExampleMapFrame(parent=None, giface=giface)
frame = wx.Frame(
parent=None, size=MAP_WINDOW_SIZE, title=_("Example Tool - GRASSGIS")
)
frame = ExampleMapDisplay(
parent=frame,
giface=StandaloneGrassInterface(),
)
if options["input"]:
giface.WriteLog(_("Loading raster map <{raster}>...").format(raster=map_name))
frame.giface.WriteLog(
_("Loading raster map <{raster}>...").format(raster=map_name)
)
frame.SetLayer(map_name)

frame.Show()
app.MainLoop()


if __name__ == "__main__":
GuiModuleMain(main)
main()
Loading

0 comments on commit a94ba36

Please sign in to comment.