From f5e5abcac1e1f2889e24e6554e4fda0cd0f7d212 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Thu, 17 Feb 2022 10:07:12 -0600 Subject: [PATCH 01/26] sbmanager as a parameter, in progress --- gui/wxpython/gui_core/mapdisp.py | 2 +- gui/wxpython/mapdisp/properties.py | 94 +- gui/wxpython/mapdisp/refactoringPR/base.py | 459 ++++++++++ gui/wxpython/mapdisp/refactoringPR/mapdisp.py | 838 ++++++++++++++++++ .../mapdisp/refactoringPR/mapdisp_guicore.py | 838 ++++++++++++++++++ gui/wxpython/mapdisp/statusbar.py | 106 +-- gui/wxpython/mapdisp/statusbar_new.py | 745 ++++++++++++++++ gui/wxpython/mapdisp/untitled0.py | 33 + 8 files changed, 3046 insertions(+), 69 deletions(-) create mode 100644 gui/wxpython/mapdisp/refactoringPR/base.py create mode 100644 gui/wxpython/mapdisp/refactoringPR/mapdisp.py create mode 100644 gui/wxpython/mapdisp/refactoringPR/mapdisp_guicore.py create mode 100644 gui/wxpython/mapdisp/statusbar_new.py create mode 100644 gui/wxpython/mapdisp/untitled0.py diff --git a/gui/wxpython/gui_core/mapdisp.py b/gui/wxpython/gui_core/mapdisp.py index fb891eab38e..b4342d52b1b 100644 --- a/gui/wxpython/gui_core/mapdisp.py +++ b/gui/wxpython/gui_core/mapdisp.py @@ -498,7 +498,7 @@ def OnMapDisplayProperties(self, event): from mapdisp.properties import MapDisplayPropertiesDialog dlg = MapDisplayPropertiesDialog( - parent=self, mapframe=self, properties=self.mapWindowProperties + parent=self, mapframe=self, properties=self.mapWindowProperties, sbmanager=self.statusbarManager ) dlg.CenterOnParent() dlg.Show() diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index f7c4dfc5e08..26107916039 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -9,6 +9,8 @@ - properties::ChBShowRegion - properties::ChBAlignExtent - properties::ChBResolution + - properties::ChBProjection + - properties::RBShowInStatusbar - properties::MapDisplayPropertiesDialog (C) 2021 by the GRASS Development Team @@ -63,7 +65,7 @@ def _connect(self): def _disconnect(self): self.mapWindowPropertyChanged().disconnect(self._setValue) - def _onToggleCheckBox(self, event): + def _onToggle(self, event): self._disconnect() self.mapWindowProperty = self.GetValue() self._connect() @@ -81,7 +83,7 @@ def __init__(self, parent, mapWindowProperties): 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 @@ -122,7 +124,7 @@ def __init__(self, parent, mapWindowProperties): ) ) ) - self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox) + self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle) self._connect() @property @@ -160,7 +162,7 @@ def __init__(self, parent, mapframe, mapWindowProperties): ) ) ) - self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox) + self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle) self._connect() @property @@ -174,9 +176,9 @@ def mapWindowProperty(self, value): 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: @@ -206,7 +208,7 @@ def __init__(self, parent, mapframe, mapWindowProperties): ) ) ) - self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox) + self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle) self._connect() @property @@ -220,12 +222,12 @@ def mapWindowProperty(self, value): 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: @@ -251,7 +253,7 @@ def __init__(self, parent, mapWindowProperties): ) ) ) - self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox) + self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle) self._connect() @property @@ -265,8 +267,8 @@ def mapWindowProperty(self, value): 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( @@ -277,14 +279,66 @@ def _onToggleCheckBox(self, event): self.widget.SetLabel(self.defaultLabel) -class MapDisplayPropertiesDialog(wx.Dialog): - """Map Display properties dialog""" +class RBShowInStatusbar: + """Radiobox managing widgets in statusbar.""" + + def __init__(self, parent, sbmanager): + self.name = "showInStatusbar" + self.statusbarManager = sbmanager + + choices = self._getAttributes(attrType="label") + self.widget = wx.RadioBox( + parent=parent, + id=wx.ID_ANY, + label="Displayed content", + choices=choices, + majorDimension=1, + style=wx.RA_SPECIFY_COLS, + ) + self.names = self._getAttributes(attrType="name") + if self.statusbarManager.shownWidgetInStatusbar: + self._setValue(self.statusbarManager.shownWidgetInStatusbar) + else: + self._setValue(self.statusbarManager.GetMode()) + + self.widget.Bind(wx.EVT_RADIOBOX, self._onToggle) + def _setValue(self, value): + self.widget.SetSelection(value) + + def GetValue(self): + return self.widget.GetSelection() + + def GetWidget(self): + """Returns underlying widget. + + :return: widget or None if doesn't exist + """ + return self.widget + + def _getAttributes(self, attrType): + attributes = [] + for value in self.statusbarManager.statusbarItems.values(): + if value.GetPosition()==0: + if attrType=="label": + attributes.append(value.label) + elif attrType=="name": + attributes.append(value.name) + return attributes + + def _onToggle(self, event): + name = self._getAttributes(attrType="name")[self.GetValue()] + self.statusbarManager.shownWidgetInStatusbarChanged.emit(itemName=name) + + +class MapDisplayPropertiesDialog(wx.Dialog): + """Map Display properties dialog.""" def __init__( self, parent, mapframe, properties, + sbmanager, title=_("Map Display Settings"), size=(-1, 250), style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, @@ -296,6 +350,7 @@ def __init__( self.size = size self.mapframe = mapframe self.mapWindowProperties = properties + self.statusbarManager = sbmanager # notebook self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT) @@ -382,10 +437,17 @@ def _createStatusBarPage(self, parent): panel.SetupScrolling(scroll_x=False, scroll_y=True) parent.AddPage(page=panel, text=_("Status bar")) - # General settings sizer = wx.BoxSizer(wx.VERTICAL) - # Auto-rendering + self.shownInStatusbar = RBShowInStatusbar(parent=panel, sbmanager=self.statusbarManager) + sizer.Add( + self.shownInStatusbar.GetWidget(), + proportion=0, + flag=wx.EXPAND | wx.ALL, + border=3, + ) + + # Display coordinates in different CRS self.projection = ChBProjection(panel, self.mapWindowProperties) sizer.Add( self.projection.GetWidget(), diff --git a/gui/wxpython/mapdisp/refactoringPR/base.py b/gui/wxpython/mapdisp/refactoringPR/base.py new file mode 100644 index 00000000000..0c2caab3332 --- /dev/null +++ b/gui/wxpython/mapdisp/refactoringPR/base.py @@ -0,0 +1,459 @@ +""" +@package mapwin.mapwindow + +@brief Map display canvas basic functionality - base class and properties. + +Classes: + - mapwindow::MapWindowProperties + - mapwindow::MapWindowBase + +(C) 2006-2012 by the GRASS Development Team + +This program is free software under the GNU General Public License +(>=v2). Read the file COPYING that comes with GRASS for details. + +@author Martin Landa +@author Michael Barton +@author Jachym Cepicky +@author Vaclav Petras (handlers support) +@author Stepan Turek (handlers support) +""" + +import wx +import six + +from core.settings import UserSettings +from core.gcmd import GError +from gui_core.wrap import StockCursor + +from grass.script import core as grass +from grass.pydispatch.signal import Signal + + +class MapWindowProperties(object): + def __init__(self): + self._resolution = None + self.resolutionChanged = Signal("MapWindowProperties.resolutionChanged") + self._autoRender = None + self.autoRenderChanged = Signal("MapWindowProperties.autoRenderChanged") + self._showRegion = None + self.showRegionChanged = Signal("MapWindowProperties.showRegionChanged") + self._alignExtent = None + self.alignExtentChanged = Signal("MapWindowProperties.alignExtentChanged") + self._useDefinedProjection = False + self.useDefinedProjectionChanged = Signal( + "MapWindowProperties.useDefinedProjectionChanged" + ) + + def setValuesFromUserSettings(self): + """Convenient function to get values from user settings into this object.""" + self._resolution = UserSettings.Get( + group="display", key="compResolution", subkey="enabled" + ) + self._autoRender = UserSettings.Get( + group="display", key="autoRendering", subkey="enabled" + ) + self._showRegion = False # in statusbar.py was not from settings + self._alignExtent = UserSettings.Get( + group="display", key="alignExtent", subkey="enabled" + ) + + @property + def resolution(self): + return self._resolution + + @resolution.setter + def resolution(self, value): + if value != self._resolution: + self._resolution = value + self.resolutionChanged.emit(value=value) + + @property + def autoRender(self): + return self._autoRender + + @autoRender.setter + def autoRender(self, value): + if value != self._autoRender: + self._autoRender = value + self.autoRenderChanged.emit(value=value) + + @property + def showRegion(self): + return self._showRegion + + @showRegion.setter + def showRegion(self, value): + if value != self._showRegion: + self._showRegion = value + self.showRegionChanged.emit(value=value) + + @property + def alignExtent(self): + return self._alignExtent + + @alignExtent.setter + def alignExtent(self, value): + if value != self._alignExtent: + self._alignExtent = value + self.alignExtentChanged.emit(value=value) + + @property + def useDefinedProjection(self): + return self._useDefinedProjection + + @useDefinedProjection.setter + def useDefinedProjection(self, value): + self._useDefinedProjection = value + + @property + def epsg(self): + return UserSettings.Get(group="projection", key="statusbar", subkey="epsg") + + @property + def precision(self): + return int( + UserSettings.Get(group="projection", key="format", subkey="precision") + ) + + @property + def latlong(self): + return UserSettings.Get(group="projection", key="format", subkey="ll") + + @property + def proj4(self): + return UserSettings.Get( + group="projection", key="statusbar", subkey="proj4" + ) + + +class MapWindowBase(object): + """Abstract map display window class + + Superclass for BufferedWindow class (2D display mode), and GLWindow + (3D display mode). + + Subclasses have to define + - _bindMouseEvents method which binds MouseEvent handlers + - Pixel2Cell + - Cell2Pixel (if it is possible) + """ + + def __init__(self, parent, giface, Map): + self.parent = parent + self.Map = Map + self._giface = giface + + # Emitted when someone registers as mouse event handler + self.mouseHandlerRegistered = Signal("MapWindow.mouseHandlerRegistered") + # Emitted when mouse event handler is unregistered + self.mouseHandlerUnregistered = Signal("MapWindow.mouseHandlerUnregistered") + # emitted after double click in pointer mode on legend, text, scalebar + self.overlayActivated = Signal("MapWindow.overlayActivated") + # emitted when overlay should be hidden + self.overlayRemoved = Signal("MapWindow.overlayRemoved") + + # mouse attributes -- position on the screen, begin and end of + # dragging, and type of drawing + self.mouse = { + "begin": [0, 0], # screen coordinates + "end": [0, 0], + "use": "pointer", + "box": "point", + } + # last east, north coordinates, changes on mouse motion + self.lastEN = None + + # stores overridden cursor + self._overriddenCursor = None + + # dictionary where event types are stored as keys and lists of + # handlers for these types as values + self.handlersContainer = { + wx.EVT_LEFT_DOWN: [], + wx.EVT_LEFT_UP: [], + wx.EVT_LEFT_DCLICK: [], + wx.EVT_MIDDLE_DOWN: [], + wx.EVT_MIDDLE_UP: [], + wx.EVT_MIDDLE_DCLICK: [], + wx.EVT_RIGHT_DOWN: [], + wx.EVT_RIGHT_UP: [], + wx.EVT_RIGHT_DCLICK: [], + wx.EVT_MOTION: [], + wx.EVT_ENTER_WINDOW: [], + wx.EVT_LEAVE_WINDOW: [], + wx.EVT_MOUSEWHEEL: [], + wx.EVT_MOUSE_EVENTS: [], + } + + # available cursors + self._cursors = { + "default": StockCursor(cursorId=wx.CURSOR_ARROW), + "cross": StockCursor(cursorId=wx.CURSOR_CROSS), + "hand": StockCursor(cursorId=wx.CURSOR_HAND), + "pencil": StockCursor(cursorId=wx.CURSOR_PENCIL), + "sizenwse": StockCursor(cursorId=wx.CURSOR_SIZENWSE), + } + + # default cursor for window is arrow (at least we rely on it here) + # but we need to define attribute here + # cannot call SetNamedCursor since it expects the instance + # to be a wx window, so setting only the attribute + self._cursor = "default" + + wx.CallAfter(self.InitBinding) + + def __del__(self): + self.UnregisterAllHandlers() + + def InitBinding(self): + """Binds helper functions, which calls all handlers + registered to events with the events + """ + for ev, handlers in six.iteritems(self.handlersContainer): + self.Bind(ev, self.EventTypeHandler(handlers)) + + def EventTypeHandler(self, evHandlers): + return lambda event: self.HandlersCaller(event, evHandlers) + + def HandlersCaller(self, event, handlers): + """Hepler function which calls all handlers registered for + event + """ + for handler in handlers: + try: + handler(event) + except: + handlers.remove(handler) + GError( + parent=self, + message=_( + "Error occurred during calling of handler: %s \n" + "Handler was unregistered." + ) + % handler.__name__, + ) + + event.Skip() + + def RegisterMouseEventHandler(self, event, handler, cursor=None): + """Binds event handler + + @deprecated This method is deprecated. Use Signals or drawing API + instead. Signals do not cover all events but new Signals can be added + when needed consider also adding generic signal. However, more + interesting and useful is higher level API to create objects, graphics etc. + + Call event.Skip() in handler to allow default processing in MapWindow. + + If any error occurs inside of handler, the handler is removed. + + Before handler is unregistered it is called with + string value "unregistered" of event parameter. + + :: + + # your class methods + def OnButton(self, event): + # current map display's map window + # expects LayerManager to be the parent + self.mapwin = self.parent.GetLayerTree().GetMapDisplay().GetWindow() + if self.mapwin.RegisterEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction, + 'cross'): + self.parent.GetLayerTree().GetMapDisplay().Raise() + else: + # handle that you cannot get coordinates + + def OnMouseAction(self, event): + # get real world coordinates of mouse click + coor = self.mapwin.Pixel2Cell(event.GetPositionTuple()[:]) + self.text.SetLabel('Coor: ' + str(coor)) + self.mapwin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction) + event.Skip() + + + Emits mouseHandlerRegistered signal before handler is registered. + + :param event: one of mouse events + :param handler: function to handle event + :param cursor: cursor which temporary overrides current cursor + + :return: True if successful + :return: False if event cannot be bind + """ + self.mouseHandlerRegistered.emit() + # inserts handler into list + for containerEv, handlers in six.iteritems(self.handlersContainer): + if event == containerEv: + handlers.append(handler) + + self.mouse["useBeforeGenericEvent"] = self.mouse["use"] + self.mouse["use"] = "genericEvent" + + if cursor: + self._overriddenCursor = self.GetNamedCursor() + self.SetNamedCursor(cursor) + + return True + + def UnregisterAllHandlers(self): + """Unregisters all registered handlers + + @deprecated This method is deprecated. Use Signals or drawing API instead. + + Before each handler is unregistered it is called with string + value "unregistered" of event parameter. + """ + for containerEv, handlers in six.iteritems(self.handlersContainer): + for handler in handlers: + try: + handler("unregistered") + handlers.remove(handler) + except: + GError( + parent=self, + message=_( + "Error occurred during unregistration of handler: %s \n \ + Handler was unregistered." + ) + % handler.__name__, + ) + handlers.remove(handler) + + def UnregisterMouseEventHandler(self, event, handler): + """Unbinds event handler for event + + @deprecated This method is deprecated. Use Signals or drawing API instead. + + Before handler is unregistered it is called with string value + "unregistered" of event parameter. + + Emits mouseHandlerUnregistered signal after handler is unregistered. + + :param handler: handler to unbind + :param event: event from which handler will be unbinded + + :return: True if successful + :return: False if event cannot be unbind + """ + # removes handler from list + for containerEv, handlers in six.iteritems(self.handlersContainer): + if event != containerEv: + continue + try: + handler("unregistered") + if handler in handlers: + handlers.remove(handler) + else: + grass.warning( + _("Handler: %s was not registered") % handler.__name__ + ) + except: + GError( + parent=self, + message=_( + "Error occurred during unregistration of handler: %s \n \ + Handler was unregistered" + ) + % handler.__name__, + ) + handlers.remove(handler) + + # restore mouse use (previous state) + self.mouse["use"] = self.mouse["useBeforeGenericEvent"] + + # restore overridden cursor + if self._overriddenCursor: + self.SetNamedCursor(self._overriddenCursor) + + self.mouseHandlerUnregistered.emit() + return True + + def Pixel2Cell(self, xyCoords): + raise NotImplementedError() + + def Cell2Pixel(self, enCoords): + raise NotImplementedError() + + def OnMotion(self, event): + """Tracks mouse motion and update statusbar + + .. todo:: + remove this method when lastEN is not used + + :func:`GetLastEN` + """ + try: + self.lastEN = self.Pixel2Cell(event.GetPosition()) + except (ValueError): + self.lastEN = None + + event.Skip() + + def GetLastEN(self): + """Returns last coordinates of mouse cursor. + + @deprecated This method is deprecated. Use Signal with coordinates as parameters. + + :func:`OnMotion` + """ + return self.lastEN + + def SetNamedCursor(self, cursorName): + """Sets cursor defined by name.""" + cursor = self._cursors[cursorName] + self.SetCursor(cursor) + self._cursor = cursorName + + def GetNamedCursor(self): + """Returns current cursor name.""" + return self._cursor + + cursor = property(fget=GetNamedCursor, fset=SetNamedCursor) + + def SetModePointer(self): + """Sets mouse mode to pointer.""" + self.mouse["use"] = "pointer" + self.mouse["box"] = "point" + self.SetNamedCursor("default") + + def SetModePan(self): + """Sets mouse mode to pan.""" + self.mouse["use"] = "pan" + self.mouse["box"] = "box" + self.zoomtype = 0 + self.SetNamedCursor("hand") + + def SetModeZoomIn(self): + self._setModeZoom(zoomType=1) + + def SetModeZoomOut(self): + self._setModeZoom(zoomType=-1) + + def _setModeZoom(self, zoomType): + self.zoomtype = zoomType + self.mouse["use"] = "zoom" + self.mouse["box"] = "box" + self.pen = wx.Pen(colour="Red", width=2, style=wx.SHORT_DASH) + self.SetNamedCursor("cross") + + def SetModeDrawRegion(self): + self.mouse["use"] = "drawRegion" + self.mouse["box"] = "box" + self.pen = wx.Pen(colour="Red", width=2, style=wx.SHORT_DASH) + self.SetNamedCursor("cross") + + def SetModeQuery(self): + """Query mode on""" + self.mouse["use"] = "query" + self.mouse["box"] = "point" + self.zoomtype = 0 + self.SetNamedCursor("cross") + + def DisactivateWin(self): + """Use when the class instance is hidden in MapFrame.""" + raise NotImplementedError() + + def ActivateWin(self): + """Used when the class instance is activated in MapFrame.""" + raise NotImplementedError() diff --git a/gui/wxpython/mapdisp/refactoringPR/mapdisp.py b/gui/wxpython/mapdisp/refactoringPR/mapdisp.py new file mode 100644 index 00000000000..1b9f05ee778 --- /dev/null +++ b/gui/wxpython/mapdisp/refactoringPR/mapdisp.py @@ -0,0 +1,838 @@ +""" +@package gui_core.mapdisp + +@brief Base classes for Map display window + +Classes: + - mapdisp::MapPanelBase + - mapdisp::SingleMapPanel + - mapdisp::DoubleMapPanel + +(C) 2009-2014 by the GRASS Development Team + +This program is free software under the GNU General Public License +(>=v2). Read the file COPYING that comes with GRASS for details. + +@author Martin Landa +@author Michael Barton +@author Vaclav Petras +@author Anna Kratochvilova +""" + +import sys +import six + +import wx + +from core.debug import Debug +from gui_core.toolbars import ToolSwitcher +from gui_core.wrap import NewId +from mapdisp import statusbar as sb + +from grass.script import core as grass + + +class MapPanelBase(wx.Panel): + """Base class for map display window + + Derived class must use (create and initialize) \c statusbarManager + or override + GetProperty(), SetProperty() and HasProperty() methods. + + Several methods has to be overridden or + \c NotImplementedError("MethodName") will be raised. + + If derived class enables and disables auto-rendering, + it should override IsAutoRendered method. + + It is expected that derived class will call _setUpMapWindow(). + + Derived class can has one or more map windows (and map renders) + but implementation of MapPanelBase expects that one window and + one map will be current. + Current instances of map window and map renderer should be returned + by methods GetWindow() and GetMap() respectively. + + AUI manager is stored in \c self._mgr. + """ + + def __init__( + self, + parent=None, + id=wx.ID_ANY, + title="", + auimgr=None, + name="", + **kwargs, + ): + """ + + .. warning:: + Use \a auimgr parameter only if you know what you are doing. + + :param parent: gui parent + :param id: wx id + :param title: window title + :param toolbars: array of activated toolbars, e.g. ['map', 'digit'] + :param auimgr: AUI manager (if \c None, wx.aui.AuiManager is used) + :param name: panel name + :param kwargs: arguments passed to \c wx.Panel + """ + + self.parent = parent + + wx.Panel.__init__(self, parent, id, name=name, **kwargs) + + # toolbars + self.toolbars = {} + self.iconsize = (16, 16) + + # + # Fancy gui + # + if auimgr is None: + from wx.aui import AuiManager + + self._mgr = AuiManager(self) + else: + self._mgr = auimgr + + # handles switching between tools in different toolbars + self._toolSwitcher = ToolSwitcher() + self._toolSwitcher.toggleToolChanged.connect(self._onToggleTool) + + # set accelerator table + self.shortcuts_table = [ + (self.OnCloseWindow, wx.ACCEL_CTRL, ord("W")), + (self.OnRender, wx.ACCEL_CTRL, ord("R")), + (self.OnRender, wx.ACCEL_NORMAL, wx.WXK_F5), + ] + + self._initShortcuts() + + def _initShortcuts(self): + """init shortcuts to acceleration table""" + accelTable = [] + for handler, entry, kdb in self.shortcuts_table: + wxId = NewId() + self.Bind(wx.EVT_MENU, handler, id=wxId) + accelTable.append((entry, kdb, wxId)) + self.SetAcceleratorTable(wx.AcceleratorTable(accelTable)) + + def _initMap(self, Map): + """Initialize map display, set dimensions and map region""" + if not grass.find_program("g.region", "--help"): + sys.exit( + _("GRASS module '%s' not found. Unable to start map " "display window.") + % "g.region" + ) + + Debug.msg(2, "MapPanel._initMap():") + Map.ChangeMapSize(self.GetClientSize()) + Map.region = Map.GetRegion() # g.region -upgc + # self.Map.SetRegion() # adjust region to match display window + + def _resize(self): + Debug.msg(1, "MapPanel_resize():") + wm, hw = self.MapWindow.GetClientSize() + wf, hf = self.GetSize() + dw = wf - wm + dh = hf - hw + self.SetSize((wf + dw, hf + dh)) + + def _onToggleTool(self, id): + if self._toolSwitcher.IsToolInGroup(id, "mouseUse"): + self.GetWindow().UnregisterAllHandlers() + + def OnSize(self, event): + """Adjust statusbar on changing size""" + # reposition checkbox in statusbar + self.StatusbarReposition() + + # update statusbar + self.StatusbarUpdate() + + def OnCloseWindow(self, event): + self.Destroy() + + def GetToolSwitcher(self): + return self._toolSwitcher + + def SetProperty(self, name, value): + """Sets property""" + if self.HasProperty("projection"): + self.statusbarManager.SetProperty(name, value) + else: + self.mapWindowProperties.useDefinedProjection = value + + def GetProperty(self, name): + """Returns property""" + if self.HasProperty("projection"): + return self.statusbarManager.GetProperty(name) + else: + return self.mapWindowProperties.useDefinedProjection + + def HasProperty(self, name): + """Checks whether object has property""" + return self.statusbarManager.HasProperty(name) + + def GetPPM(self): + """Get pixel per meter + + .. todo:: + now computed every time, is it necessary? + + .. todo:: + enable user to specify ppm (and store it in UserSettings) + """ + # TODO: need to be fixed... + # screen X region problem + # user should specify ppm + dc = wx.ScreenDC() + dpSizePx = wx.DisplaySize() # display size in pixels + dpSizeMM = wx.DisplaySizeMM() # display size in mm (system) + dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4) # inches + sysPpi = dc.GetPPI() + comPpi = (dpSizePx[0] / dpSizeIn[0], dpSizePx[1] / dpSizeIn[1]) + + ppi = comPpi # pixel per inch + ppm = ((ppi[0] / 2.54) * 100, (ppi[1] / 2.54) * 100) # pixel per meter + + Debug.msg( + 4, + "MapPanelBase.GetPPM(): size: px=%d,%d mm=%f,%f " + "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" + % ( + dpSizePx[0], + dpSizePx[1], + dpSizeMM[0], + dpSizeMM[1], + dpSizeIn[0], + dpSizeIn[1], + sysPpi[0], + sysPpi[1], + comPpi[0], + comPpi[1], + ppm[0], + ppm[1], + ), + ) + + return ppm + + def SetMapScale(self, value, map=None): + """Set current map scale + + :param value: scale value (n if scale is 1:n) + :param map: Map instance (if none self.Map is used) + """ + if not map: + map = self.Map + + region = self.Map.region + dEW = value * (region["cols"] / self.GetPPM()[0]) + dNS = value * (region["rows"] / self.GetPPM()[1]) + region["n"] = region["center_northing"] + dNS / 2.0 + region["s"] = region["center_northing"] - dNS / 2.0 + region["w"] = region["center_easting"] - dEW / 2.0 + region["e"] = region["center_easting"] + dEW / 2.0 + + # add to zoom history + self.GetWindow().ZoomHistory(region["n"], region["s"], region["e"], region["w"]) + + def GetMapScale(self, map=None): + """Get current map scale + + :param map: Map instance (if none self.Map is used) + """ + if not map: + map = self.GetMap() + + region = map.region + ppm = self.GetPPM() + + heightCm = region["rows"] / ppm[1] * 100 + widthCm = region["cols"] / ppm[0] * 100 + + Debug.msg( + 4, "MapPanel.GetMapScale(): width_cm=%f, height_cm=%f" % (widthCm, heightCm) + ) + + xscale = (region["e"] - region["w"]) / (region["cols"] / ppm[0]) + yscale = (region["n"] - region["s"]) / (region["rows"] / ppm[1]) + scale = (xscale + yscale) / 2.0 + + Debug.msg( + 3, + "MapPanel.GetMapScale(): xscale=%f, yscale=%f -> scale=%f" + % (xscale, yscale, scale), + ) + + return scale + + def GetProgressBar(self): + """Returns progress bar + + Progress bar can be used by other classes. + """ + return self.statusbarManager.GetProgressBar() + + def GetMap(self): + """Returns current map (renderer) instance""" + raise NotImplementedError("GetMap") + + def GetWindow(self): + """Returns current map window""" + raise NotImplementedError("GetWindow") + + def GetWindows(self): + """Returns list of map windows""" + raise NotImplementedError("GetWindows") + + def GetMapToolbar(self): + """Returns toolbar with zooming tools""" + raise NotImplementedError("GetMapToolbar") + + def GetToolbar(self, name): + """Returns toolbar if exists and is active, else None.""" + if name in self.toolbars and self.toolbars[name].IsShown(): + return self.toolbars[name] + + return None + + def StatusbarUpdate(self): + """Update statusbar content""" + if self.statusbarManager: + Debug.msg(5, "MapPanelBase.StatusbarUpdate()") + self.statusbarManager.Update() + + def IsAutoRendered(self): + """Check if auto-rendering is enabled""" + # TODO: this is now not the right place to access this attribute + # TODO: add mapWindowProperties to init parameters + # and pass the right object in the init of derived class? + # or do not use this method at all, let mapwindow decide + return self.mapWindowProperties.autoRender + + def CoordinatesChanged(self): + """Shows current coordinates on statusbar.""" + # assuming that the first mode is coordinates + # probably shold not be here but good solution is not available now + if self.statusbarManager: + if self.statusbarManager.GetMode() == 0: + self.statusbarManager.ShowItem("coordinates") + + def CreateStatusbar(self, statusbarItems): + """Create statusbar (default items).""" + # create statusbar and its manager + statusbar = wx.StatusBar(self, id=wx.ID_ANY) + statusbar.SetMinHeight(24) + statusbar.SetFieldsCount(3) + statusbar.SetStatusWidths([-6, -2, -1]) + self.statusbarManager = sb.SbManager(statusbar=statusbar, giface=self._giface, mapDisplayProperties=self._mapWindowProperties) + + # fill statusbar manager + self.statusbarManager.AddStatusbarItemsByClass( + statusbarItems, statusbar=statusbar + ) + self.statusbarManager.AddStatusbarItem( + sb.SbRender(statusbar=statusbar, position=2) + ) + self.statusbarManager.Update() + return statusbar + + def AddStatusbarPane(self): + """Add statusbar as a pane""" + self._mgr.AddPane( + self.statusbar, + wx.aui.AuiPaneInfo() + .Bottom() + .MinSize(30, 30) + .Fixed() + .Name("statusbar") + .CloseButton(False) + .DestroyOnClose(True) + .ToolbarPane() + .Dockable(False) + .PaneBorder(False) + .Gripper(False), + ) + + def SetStatusText(self, *args): + """Overide wx.StatusBar method""" + self.statusbar.SetStatusText(*args) + + def ShowStatusbar(self, show): + """Show/hide statusbar and associated pane""" + self._mgr.GetPane("statusbar").Show(show) + self._mgr.Update() + + def IsStatusbarShown(self): + """Check if statusbar is shown""" + return self._mgr.GetPane("statusbar").IsShown() + + def StatusbarReposition(self): + """Reposition items in statusbar""" + if self.statusbarManager: + self.statusbarManager.Reposition() + + def StatusbarEnableLongHelp(self, enable=True): + """Enable/disable toolbars long help""" + for toolbar in six.itervalues(self.toolbars): + if toolbar: + toolbar.EnableLongHelp(enable) + + def ShowAllToolbars(self, show=True): + if not show: # hide + action = self.RemoveToolbar + else: + action = self.AddToolbar + for toolbar in self.GetToolbarNames(): + action(toolbar) + + def AreAllToolbarsShown(self): + return self.GetMapToolbar().IsShown() + + def GetToolbarNames(self): + """Return toolbar names""" + return list(self.toolbars.keys()) + + def AddToolbar(self): + """Add defined toolbar to the window""" + raise NotImplementedError("AddToolbar") + + def RemoveToolbar(self, name, destroy=False): + """Removes defined toolbar from the window + + :param name toolbar to remove + :param destroy True to destroy otherwise toolbar is only hidden + """ + self._mgr.DetachPane(self.toolbars[name]) + if destroy: + self._toolSwitcher.RemoveToolbarFromGroup("mouseUse", self.toolbars[name]) + self.toolbars[name].Destroy() + self.toolbars.pop(name) + else: + self.toolbars[name].Hide() + + self._mgr.Update() + + def IsPaneShown(self, name): + """Check if pane (toolbar, mapWindow ...) of given name is currently shown""" + if self._mgr.GetPane(name).IsOk(): + return self._mgr.GetPane(name).IsShown() + return False + + def OnRender(self, event): + """Re-render map composition (each map layer)""" + raise NotImplementedError("OnRender") + + def OnDraw(self, event): + """Re-display current map composition""" + self.MapWindow.UpdateMap(render=False) + + def OnErase(self, event): + """Erase the canvas""" + self.MapWindow.EraseMap() + + def OnZoomIn(self, event): + """Zoom in the map.""" + self.MapWindow.SetModeZoomIn() + + def OnZoomOut(self, event): + """Zoom out the map.""" + self.MapWindow.SetModeZoomOut() + + def _setUpMapWindow(self, mapWindow): + """Binds map windows' zoom history signals to map toolbar.""" + # enable or disable zoom history tool + if self.GetMapToolbar(): + mapWindow.zoomHistoryAvailable.connect( + lambda: self.GetMapToolbar().Enable("zoomBack", enable=True) + ) + mapWindow.zoomHistoryUnavailable.connect( + lambda: self.GetMapToolbar().Enable("zoomBack", enable=False) + ) + mapWindow.mouseMoving.connect(self.CoordinatesChanged) + + def OnPointer(self, event): + """Sets mouse mode to pointer.""" + self.MapWindow.SetModePointer() + + def OnPan(self, event): + """Panning, set mouse to drag""" + self.MapWindow.SetModePan() + + def OnZoomBack(self, event): + """Zoom last (previously stored position)""" + self.MapWindow.ZoomBack() + + def OnZoomToMap(self, event): + """ + Set display extents to match selected raster (including NULLs) + or vector map. + """ + self.MapWindow.ZoomToMap(layers=self.Map.GetListOfLayers()) + + def OnZoomToWind(self, event): + """Set display geometry to match computational region + settings (set with g.region) + """ + self.MapWindow.ZoomToWind() + + def OnZoomToDefault(self, event): + """Set display geometry to match default region settings""" + self.MapWindow.ZoomToDefault() + + +class SingleMapPanel(MapPanelBase): + """Panel with one map window. + + It is base class for panels which needs only one map. + + Derived class should have \c self.MapWindow or + it has to override GetWindow() methods. + + @note To access maps use getters only + (when using class or when writing class itself). + """ + + def __init__( + self, + parent=None, + giface=None, + id=wx.ID_ANY, + title="", + Map=None, + auimgr=None, + name="", + **kwargs, + ): + """ + + :param parent: gui parent + :param id: wx id + :param title: window title + :param map: instance of render.Map + :param name: panel name + :param kwargs: arguments passed to MapPanelBase + """ + + MapPanelBase.__init__( + self, + parent=parent, + id=id, + title=title, + auimgr=auimgr, + name=name, + **kwargs, + ) + + self.Map = Map # instance of render.Map + + # + # initialize region values + # + if self.Map: + self._initMap(Map=self.Map) + + def GetMap(self): + """Returns map (renderer) instance""" + return self.Map + + def GetWindow(self): + """Returns map window""" + return self.MapWindow + + def GetWindows(self): + """Returns list of map windows""" + return [self.MapWindow] + + def OnRender(self, event): + """Re-render map composition (each map layer)""" + self.GetWindow().UpdateMap(render=True, renderVector=True) + + # update statusbar + self.StatusbarUpdate() + + +class DoubleMapPanel(MapPanelBase): + """Panel with two map windows. + + It is base class for panels which needs two maps. + There is no primary and secondary map. Both maps are equal. + However, one map is current. + + It is expected that derived class will call _bindWindowsActivation() + when both map windows will be initialized. + + Drived class should have method GetMapToolbar() returns toolbar + which has methods SetActiveMap() and Enable(). + + @note To access maps use getters only + (when using class or when writing class itself). + + .. todo: + Use it in GCP manager (probably changes to both DoubleMapPanel + and GCP MapPanel will be necessary). + """ + + def __init__( + self, + parent=None, + id=wx.ID_ANY, + title=None, + firstMap=None, + secondMap=None, + auimgr=None, + name=None, + **kwargs, + ): + """ + + \a firstMap is set as active (by assign it to \c self.Map). + Derived class should assging to \c self.MapWindow to make one + map window current by dafault. + + :param parent: gui parent + :param id: wx id + :param title: window title + :param name: panel name + :param kwargs: arguments passed to MapPanelBase + """ + + MapPanelBase.__init__( + self, + parent=parent, + id=id, + title=title, + auimgr=auimgr, + name=name, + **kwargs, + ) + + self.firstMap = firstMap + self.secondMap = secondMap + self.Map = firstMap + + # + # initialize region values + # + self._initMap(Map=self.firstMap) + self._initMap(Map=self.secondMap) + self._bindRegions = False + + def _bindWindowsActivation(self): + self.GetFirstWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateFirstMap) + self.GetSecondWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateSecondMap) + + def _onToggleTool(self, id): + if self._toolSwitcher.IsToolInGroup(id, "mouseUse"): + self.GetFirstWindow().UnregisterAllHandlers() + self.GetSecondWindow().UnregisterAllHandlers() + + def GetFirstMap(self): + """Returns first Map instance""" + return self.firstMap + + def GetSecondMap(self): + """Returns second Map instance""" + return self.secondMap + + def GetFirstWindow(self): + """Get first map window""" + return self.firstMapWindow + + def GetSecondWindow(self): + """Get second map window""" + return self.secondMapWindow + + def GetMap(self): + """Returns current map (renderer) instance + + @note Use this method to access current map renderer. + (It is not guarented that current map will be stored in + \c self.Map in future versions.) + """ + return self.Map + + def GetWindow(self): + """Returns current map window + + :func:`GetMap()` + """ + return self.MapWindow + + def GetWindows(self): + """Return list of all windows""" + return [self.firstMapWindow, self.secondMapWindow] + + def ActivateFirstMap(self, event=None): + """Make first Map and MapWindow active and (un)bind regions of the two Maps.""" + if self.MapWindow == self.firstMapWindow: + return + + self.Map = self.firstMap + self.MapWindow = self.firstMapWindow + self.GetMapToolbar().SetActiveMap(0) + + # bind/unbind regions + if self._bindRegions: + self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap) + self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap) + + def ActivateSecondMap(self, event=None): + """Make second Map and MapWindow active and (un)bind regions of the two Maps.""" + if self.MapWindow == self.secondMapWindow: + return + + self.Map = self.secondMap + self.MapWindow = self.secondMapWindow + self.GetMapToolbar().SetActiveMap(1) + + if self._bindRegions: + self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap) + self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap) + + def SetBindRegions(self, on): + """Set or unset binding display regions.""" + self._bindRegions = on + if on: + if self.MapWindow == self.firstMapWindow: + self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap) + else: + self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap) + else: + if self.MapWindow == self.firstMapWindow: + self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap) + else: + self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap) + + def OnZoomChangedFirstMap(self): + """Display region of the first window (Map) changed. + + Synchronize the region of the second map and re-render it. + This is the default implementation which can be overridden. + """ + region = self.GetFirstMap().GetCurrentRegion() + self.GetSecondMap().region.update(region) + self.Render(mapToRender=self.GetSecondWindow()) + + def OnZoomChangedSecondMap(self): + """Display region of the second window (Map) changed. + + Synchronize the region of the second map and re-render it. + This is the default implementation which can be overridden. + """ + region = self.GetSecondMap().GetCurrentRegion() + self.GetFirstMap().region.update(region) + self.Render(mapToRender=self.GetFirstWindow()) + + def OnZoomIn(self, event): + """Zoom in the map.""" + self.GetFirstWindow().SetModeZoomIn() + self.GetSecondWindow().SetModeZoomIn() + + def OnZoomOut(self, event): + """Zoom out the map.""" + self.GetFirstWindow().SetModeZoomOut() + self.GetSecondWindow().SetModeZoomOut() + + def OnPan(self, event): + """Panning, set mouse to pan""" + self.GetFirstWindow().SetModePan() + self.GetSecondWindow().SetModePan() + + def OnPointer(self, event): + """Set pointer mode (dragging overlays)""" + self.GetFirstWindow().SetModePointer() + self.GetSecondWindow().SetModePointer() + + def OnQuery(self, event): + """Set query mode""" + self.GetFirstWindow().SetModeQuery() + self.GetSecondWindow().SetModeQuery() + + def OnRender(self, event): + """Re-render map composition (each map layer)""" + self.Render(mapToRender=self.GetFirstWindow()) + self.Render(mapToRender=self.GetSecondWindow()) + + def Render(self, mapToRender): + """Re-render map composition""" + mapToRender.UpdateMap( + render=True, renderVector=mapToRender == self.GetFirstWindow() + ) + + # update statusbar + self.StatusbarUpdate() + + def OnErase(self, event): + """Erase the canvas""" + self.Erase(mapToErase=self.GetFirstWindow()) + self.Erase(mapToErase=self.GetSecondWindow()) + + def Erase(self, mapToErase): + """Erase the canvas""" + mapToErase.EraseMap() + + def OnDraw(self, event): + """Re-display current map composition""" + self.Draw(mapToDraw=self.GetFirstWindow()) + self.Draw(mapToDraw=self.GetSecondWindow()) + + def Draw(self, mapToDraw): + """Re-display current map composition""" + mapToDraw.UpdateMap(render=False) + + +class FrameMixin: + """Mixin class for wx.Panel that provides methods standardly + used on wx.Frame widget""" + + def Show(self): + self.GetParent().Show() + + def SetTitle(self, name): + self.GetParent().SetTitle(name) + + def Raise(self): + self.GetParent().Raise() + + def SetFocus(self): + self.GetParent().SetFocus() + + def CenterOnScreen(self): + self.GetParent().CenterOnScreen() + + def CentreOnScreen(self): + self.GetParent().CentreOnScreen() + + def IsFullScreen(self): + return self.GetParent().IsFullScreen() + + def IsIconized(self): + self.GetParent().IsIconized() + + def Maximize(self): + self.GetParent().Maximize() + + def ShowFullScreen(self, show): + for toolbar in self.toolbars.keys(): + self._mgr.GetPane(self.toolbars[toolbar]).Show(self.IsFullScreen()) + if self.statusbar: + self._mgr.GetPane("statusbar").Show(self.IsFullScreen()) + self._mgr.Update() + + self.GetParent().ShowFullScreen(show) + + def OnFullScreen(self, event): + """!Switches frame to fullscreen mode, hides toolbars and statusbar""" + self.ShowFullScreen(not self.IsFullScreen()) + event.Skip() + + def BindToFrame(self, *args): + self.GetParent().Bind(*args) + + def Destroy(self): + self.GetParent().Destroy() diff --git a/gui/wxpython/mapdisp/refactoringPR/mapdisp_guicore.py b/gui/wxpython/mapdisp/refactoringPR/mapdisp_guicore.py new file mode 100644 index 00000000000..1b9f05ee778 --- /dev/null +++ b/gui/wxpython/mapdisp/refactoringPR/mapdisp_guicore.py @@ -0,0 +1,838 @@ +""" +@package gui_core.mapdisp + +@brief Base classes for Map display window + +Classes: + - mapdisp::MapPanelBase + - mapdisp::SingleMapPanel + - mapdisp::DoubleMapPanel + +(C) 2009-2014 by the GRASS Development Team + +This program is free software under the GNU General Public License +(>=v2). Read the file COPYING that comes with GRASS for details. + +@author Martin Landa +@author Michael Barton +@author Vaclav Petras +@author Anna Kratochvilova +""" + +import sys +import six + +import wx + +from core.debug import Debug +from gui_core.toolbars import ToolSwitcher +from gui_core.wrap import NewId +from mapdisp import statusbar as sb + +from grass.script import core as grass + + +class MapPanelBase(wx.Panel): + """Base class for map display window + + Derived class must use (create and initialize) \c statusbarManager + or override + GetProperty(), SetProperty() and HasProperty() methods. + + Several methods has to be overridden or + \c NotImplementedError("MethodName") will be raised. + + If derived class enables and disables auto-rendering, + it should override IsAutoRendered method. + + It is expected that derived class will call _setUpMapWindow(). + + Derived class can has one or more map windows (and map renders) + but implementation of MapPanelBase expects that one window and + one map will be current. + Current instances of map window and map renderer should be returned + by methods GetWindow() and GetMap() respectively. + + AUI manager is stored in \c self._mgr. + """ + + def __init__( + self, + parent=None, + id=wx.ID_ANY, + title="", + auimgr=None, + name="", + **kwargs, + ): + """ + + .. warning:: + Use \a auimgr parameter only if you know what you are doing. + + :param parent: gui parent + :param id: wx id + :param title: window title + :param toolbars: array of activated toolbars, e.g. ['map', 'digit'] + :param auimgr: AUI manager (if \c None, wx.aui.AuiManager is used) + :param name: panel name + :param kwargs: arguments passed to \c wx.Panel + """ + + self.parent = parent + + wx.Panel.__init__(self, parent, id, name=name, **kwargs) + + # toolbars + self.toolbars = {} + self.iconsize = (16, 16) + + # + # Fancy gui + # + if auimgr is None: + from wx.aui import AuiManager + + self._mgr = AuiManager(self) + else: + self._mgr = auimgr + + # handles switching between tools in different toolbars + self._toolSwitcher = ToolSwitcher() + self._toolSwitcher.toggleToolChanged.connect(self._onToggleTool) + + # set accelerator table + self.shortcuts_table = [ + (self.OnCloseWindow, wx.ACCEL_CTRL, ord("W")), + (self.OnRender, wx.ACCEL_CTRL, ord("R")), + (self.OnRender, wx.ACCEL_NORMAL, wx.WXK_F5), + ] + + self._initShortcuts() + + def _initShortcuts(self): + """init shortcuts to acceleration table""" + accelTable = [] + for handler, entry, kdb in self.shortcuts_table: + wxId = NewId() + self.Bind(wx.EVT_MENU, handler, id=wxId) + accelTable.append((entry, kdb, wxId)) + self.SetAcceleratorTable(wx.AcceleratorTable(accelTable)) + + def _initMap(self, Map): + """Initialize map display, set dimensions and map region""" + if not grass.find_program("g.region", "--help"): + sys.exit( + _("GRASS module '%s' not found. Unable to start map " "display window.") + % "g.region" + ) + + Debug.msg(2, "MapPanel._initMap():") + Map.ChangeMapSize(self.GetClientSize()) + Map.region = Map.GetRegion() # g.region -upgc + # self.Map.SetRegion() # adjust region to match display window + + def _resize(self): + Debug.msg(1, "MapPanel_resize():") + wm, hw = self.MapWindow.GetClientSize() + wf, hf = self.GetSize() + dw = wf - wm + dh = hf - hw + self.SetSize((wf + dw, hf + dh)) + + def _onToggleTool(self, id): + if self._toolSwitcher.IsToolInGroup(id, "mouseUse"): + self.GetWindow().UnregisterAllHandlers() + + def OnSize(self, event): + """Adjust statusbar on changing size""" + # reposition checkbox in statusbar + self.StatusbarReposition() + + # update statusbar + self.StatusbarUpdate() + + def OnCloseWindow(self, event): + self.Destroy() + + def GetToolSwitcher(self): + return self._toolSwitcher + + def SetProperty(self, name, value): + """Sets property""" + if self.HasProperty("projection"): + self.statusbarManager.SetProperty(name, value) + else: + self.mapWindowProperties.useDefinedProjection = value + + def GetProperty(self, name): + """Returns property""" + if self.HasProperty("projection"): + return self.statusbarManager.GetProperty(name) + else: + return self.mapWindowProperties.useDefinedProjection + + def HasProperty(self, name): + """Checks whether object has property""" + return self.statusbarManager.HasProperty(name) + + def GetPPM(self): + """Get pixel per meter + + .. todo:: + now computed every time, is it necessary? + + .. todo:: + enable user to specify ppm (and store it in UserSettings) + """ + # TODO: need to be fixed... + # screen X region problem + # user should specify ppm + dc = wx.ScreenDC() + dpSizePx = wx.DisplaySize() # display size in pixels + dpSizeMM = wx.DisplaySizeMM() # display size in mm (system) + dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4) # inches + sysPpi = dc.GetPPI() + comPpi = (dpSizePx[0] / dpSizeIn[0], dpSizePx[1] / dpSizeIn[1]) + + ppi = comPpi # pixel per inch + ppm = ((ppi[0] / 2.54) * 100, (ppi[1] / 2.54) * 100) # pixel per meter + + Debug.msg( + 4, + "MapPanelBase.GetPPM(): size: px=%d,%d mm=%f,%f " + "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" + % ( + dpSizePx[0], + dpSizePx[1], + dpSizeMM[0], + dpSizeMM[1], + dpSizeIn[0], + dpSizeIn[1], + sysPpi[0], + sysPpi[1], + comPpi[0], + comPpi[1], + ppm[0], + ppm[1], + ), + ) + + return ppm + + def SetMapScale(self, value, map=None): + """Set current map scale + + :param value: scale value (n if scale is 1:n) + :param map: Map instance (if none self.Map is used) + """ + if not map: + map = self.Map + + region = self.Map.region + dEW = value * (region["cols"] / self.GetPPM()[0]) + dNS = value * (region["rows"] / self.GetPPM()[1]) + region["n"] = region["center_northing"] + dNS / 2.0 + region["s"] = region["center_northing"] - dNS / 2.0 + region["w"] = region["center_easting"] - dEW / 2.0 + region["e"] = region["center_easting"] + dEW / 2.0 + + # add to zoom history + self.GetWindow().ZoomHistory(region["n"], region["s"], region["e"], region["w"]) + + def GetMapScale(self, map=None): + """Get current map scale + + :param map: Map instance (if none self.Map is used) + """ + if not map: + map = self.GetMap() + + region = map.region + ppm = self.GetPPM() + + heightCm = region["rows"] / ppm[1] * 100 + widthCm = region["cols"] / ppm[0] * 100 + + Debug.msg( + 4, "MapPanel.GetMapScale(): width_cm=%f, height_cm=%f" % (widthCm, heightCm) + ) + + xscale = (region["e"] - region["w"]) / (region["cols"] / ppm[0]) + yscale = (region["n"] - region["s"]) / (region["rows"] / ppm[1]) + scale = (xscale + yscale) / 2.0 + + Debug.msg( + 3, + "MapPanel.GetMapScale(): xscale=%f, yscale=%f -> scale=%f" + % (xscale, yscale, scale), + ) + + return scale + + def GetProgressBar(self): + """Returns progress bar + + Progress bar can be used by other classes. + """ + return self.statusbarManager.GetProgressBar() + + def GetMap(self): + """Returns current map (renderer) instance""" + raise NotImplementedError("GetMap") + + def GetWindow(self): + """Returns current map window""" + raise NotImplementedError("GetWindow") + + def GetWindows(self): + """Returns list of map windows""" + raise NotImplementedError("GetWindows") + + def GetMapToolbar(self): + """Returns toolbar with zooming tools""" + raise NotImplementedError("GetMapToolbar") + + def GetToolbar(self, name): + """Returns toolbar if exists and is active, else None.""" + if name in self.toolbars and self.toolbars[name].IsShown(): + return self.toolbars[name] + + return None + + def StatusbarUpdate(self): + """Update statusbar content""" + if self.statusbarManager: + Debug.msg(5, "MapPanelBase.StatusbarUpdate()") + self.statusbarManager.Update() + + def IsAutoRendered(self): + """Check if auto-rendering is enabled""" + # TODO: this is now not the right place to access this attribute + # TODO: add mapWindowProperties to init parameters + # and pass the right object in the init of derived class? + # or do not use this method at all, let mapwindow decide + return self.mapWindowProperties.autoRender + + def CoordinatesChanged(self): + """Shows current coordinates on statusbar.""" + # assuming that the first mode is coordinates + # probably shold not be here but good solution is not available now + if self.statusbarManager: + if self.statusbarManager.GetMode() == 0: + self.statusbarManager.ShowItem("coordinates") + + def CreateStatusbar(self, statusbarItems): + """Create statusbar (default items).""" + # create statusbar and its manager + statusbar = wx.StatusBar(self, id=wx.ID_ANY) + statusbar.SetMinHeight(24) + statusbar.SetFieldsCount(3) + statusbar.SetStatusWidths([-6, -2, -1]) + self.statusbarManager = sb.SbManager(statusbar=statusbar, giface=self._giface, mapDisplayProperties=self._mapWindowProperties) + + # fill statusbar manager + self.statusbarManager.AddStatusbarItemsByClass( + statusbarItems, statusbar=statusbar + ) + self.statusbarManager.AddStatusbarItem( + sb.SbRender(statusbar=statusbar, position=2) + ) + self.statusbarManager.Update() + return statusbar + + def AddStatusbarPane(self): + """Add statusbar as a pane""" + self._mgr.AddPane( + self.statusbar, + wx.aui.AuiPaneInfo() + .Bottom() + .MinSize(30, 30) + .Fixed() + .Name("statusbar") + .CloseButton(False) + .DestroyOnClose(True) + .ToolbarPane() + .Dockable(False) + .PaneBorder(False) + .Gripper(False), + ) + + def SetStatusText(self, *args): + """Overide wx.StatusBar method""" + self.statusbar.SetStatusText(*args) + + def ShowStatusbar(self, show): + """Show/hide statusbar and associated pane""" + self._mgr.GetPane("statusbar").Show(show) + self._mgr.Update() + + def IsStatusbarShown(self): + """Check if statusbar is shown""" + return self._mgr.GetPane("statusbar").IsShown() + + def StatusbarReposition(self): + """Reposition items in statusbar""" + if self.statusbarManager: + self.statusbarManager.Reposition() + + def StatusbarEnableLongHelp(self, enable=True): + """Enable/disable toolbars long help""" + for toolbar in six.itervalues(self.toolbars): + if toolbar: + toolbar.EnableLongHelp(enable) + + def ShowAllToolbars(self, show=True): + if not show: # hide + action = self.RemoveToolbar + else: + action = self.AddToolbar + for toolbar in self.GetToolbarNames(): + action(toolbar) + + def AreAllToolbarsShown(self): + return self.GetMapToolbar().IsShown() + + def GetToolbarNames(self): + """Return toolbar names""" + return list(self.toolbars.keys()) + + def AddToolbar(self): + """Add defined toolbar to the window""" + raise NotImplementedError("AddToolbar") + + def RemoveToolbar(self, name, destroy=False): + """Removes defined toolbar from the window + + :param name toolbar to remove + :param destroy True to destroy otherwise toolbar is only hidden + """ + self._mgr.DetachPane(self.toolbars[name]) + if destroy: + self._toolSwitcher.RemoveToolbarFromGroup("mouseUse", self.toolbars[name]) + self.toolbars[name].Destroy() + self.toolbars.pop(name) + else: + self.toolbars[name].Hide() + + self._mgr.Update() + + def IsPaneShown(self, name): + """Check if pane (toolbar, mapWindow ...) of given name is currently shown""" + if self._mgr.GetPane(name).IsOk(): + return self._mgr.GetPane(name).IsShown() + return False + + def OnRender(self, event): + """Re-render map composition (each map layer)""" + raise NotImplementedError("OnRender") + + def OnDraw(self, event): + """Re-display current map composition""" + self.MapWindow.UpdateMap(render=False) + + def OnErase(self, event): + """Erase the canvas""" + self.MapWindow.EraseMap() + + def OnZoomIn(self, event): + """Zoom in the map.""" + self.MapWindow.SetModeZoomIn() + + def OnZoomOut(self, event): + """Zoom out the map.""" + self.MapWindow.SetModeZoomOut() + + def _setUpMapWindow(self, mapWindow): + """Binds map windows' zoom history signals to map toolbar.""" + # enable or disable zoom history tool + if self.GetMapToolbar(): + mapWindow.zoomHistoryAvailable.connect( + lambda: self.GetMapToolbar().Enable("zoomBack", enable=True) + ) + mapWindow.zoomHistoryUnavailable.connect( + lambda: self.GetMapToolbar().Enable("zoomBack", enable=False) + ) + mapWindow.mouseMoving.connect(self.CoordinatesChanged) + + def OnPointer(self, event): + """Sets mouse mode to pointer.""" + self.MapWindow.SetModePointer() + + def OnPan(self, event): + """Panning, set mouse to drag""" + self.MapWindow.SetModePan() + + def OnZoomBack(self, event): + """Zoom last (previously stored position)""" + self.MapWindow.ZoomBack() + + def OnZoomToMap(self, event): + """ + Set display extents to match selected raster (including NULLs) + or vector map. + """ + self.MapWindow.ZoomToMap(layers=self.Map.GetListOfLayers()) + + def OnZoomToWind(self, event): + """Set display geometry to match computational region + settings (set with g.region) + """ + self.MapWindow.ZoomToWind() + + def OnZoomToDefault(self, event): + """Set display geometry to match default region settings""" + self.MapWindow.ZoomToDefault() + + +class SingleMapPanel(MapPanelBase): + """Panel with one map window. + + It is base class for panels which needs only one map. + + Derived class should have \c self.MapWindow or + it has to override GetWindow() methods. + + @note To access maps use getters only + (when using class or when writing class itself). + """ + + def __init__( + self, + parent=None, + giface=None, + id=wx.ID_ANY, + title="", + Map=None, + auimgr=None, + name="", + **kwargs, + ): + """ + + :param parent: gui parent + :param id: wx id + :param title: window title + :param map: instance of render.Map + :param name: panel name + :param kwargs: arguments passed to MapPanelBase + """ + + MapPanelBase.__init__( + self, + parent=parent, + id=id, + title=title, + auimgr=auimgr, + name=name, + **kwargs, + ) + + self.Map = Map # instance of render.Map + + # + # initialize region values + # + if self.Map: + self._initMap(Map=self.Map) + + def GetMap(self): + """Returns map (renderer) instance""" + return self.Map + + def GetWindow(self): + """Returns map window""" + return self.MapWindow + + def GetWindows(self): + """Returns list of map windows""" + return [self.MapWindow] + + def OnRender(self, event): + """Re-render map composition (each map layer)""" + self.GetWindow().UpdateMap(render=True, renderVector=True) + + # update statusbar + self.StatusbarUpdate() + + +class DoubleMapPanel(MapPanelBase): + """Panel with two map windows. + + It is base class for panels which needs two maps. + There is no primary and secondary map. Both maps are equal. + However, one map is current. + + It is expected that derived class will call _bindWindowsActivation() + when both map windows will be initialized. + + Drived class should have method GetMapToolbar() returns toolbar + which has methods SetActiveMap() and Enable(). + + @note To access maps use getters only + (when using class or when writing class itself). + + .. todo: + Use it in GCP manager (probably changes to both DoubleMapPanel + and GCP MapPanel will be necessary). + """ + + def __init__( + self, + parent=None, + id=wx.ID_ANY, + title=None, + firstMap=None, + secondMap=None, + auimgr=None, + name=None, + **kwargs, + ): + """ + + \a firstMap is set as active (by assign it to \c self.Map). + Derived class should assging to \c self.MapWindow to make one + map window current by dafault. + + :param parent: gui parent + :param id: wx id + :param title: window title + :param name: panel name + :param kwargs: arguments passed to MapPanelBase + """ + + MapPanelBase.__init__( + self, + parent=parent, + id=id, + title=title, + auimgr=auimgr, + name=name, + **kwargs, + ) + + self.firstMap = firstMap + self.secondMap = secondMap + self.Map = firstMap + + # + # initialize region values + # + self._initMap(Map=self.firstMap) + self._initMap(Map=self.secondMap) + self._bindRegions = False + + def _bindWindowsActivation(self): + self.GetFirstWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateFirstMap) + self.GetSecondWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateSecondMap) + + def _onToggleTool(self, id): + if self._toolSwitcher.IsToolInGroup(id, "mouseUse"): + self.GetFirstWindow().UnregisterAllHandlers() + self.GetSecondWindow().UnregisterAllHandlers() + + def GetFirstMap(self): + """Returns first Map instance""" + return self.firstMap + + def GetSecondMap(self): + """Returns second Map instance""" + return self.secondMap + + def GetFirstWindow(self): + """Get first map window""" + return self.firstMapWindow + + def GetSecondWindow(self): + """Get second map window""" + return self.secondMapWindow + + def GetMap(self): + """Returns current map (renderer) instance + + @note Use this method to access current map renderer. + (It is not guarented that current map will be stored in + \c self.Map in future versions.) + """ + return self.Map + + def GetWindow(self): + """Returns current map window + + :func:`GetMap()` + """ + return self.MapWindow + + def GetWindows(self): + """Return list of all windows""" + return [self.firstMapWindow, self.secondMapWindow] + + def ActivateFirstMap(self, event=None): + """Make first Map and MapWindow active and (un)bind regions of the two Maps.""" + if self.MapWindow == self.firstMapWindow: + return + + self.Map = self.firstMap + self.MapWindow = self.firstMapWindow + self.GetMapToolbar().SetActiveMap(0) + + # bind/unbind regions + if self._bindRegions: + self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap) + self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap) + + def ActivateSecondMap(self, event=None): + """Make second Map and MapWindow active and (un)bind regions of the two Maps.""" + if self.MapWindow == self.secondMapWindow: + return + + self.Map = self.secondMap + self.MapWindow = self.secondMapWindow + self.GetMapToolbar().SetActiveMap(1) + + if self._bindRegions: + self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap) + self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap) + + def SetBindRegions(self, on): + """Set or unset binding display regions.""" + self._bindRegions = on + if on: + if self.MapWindow == self.firstMapWindow: + self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap) + else: + self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap) + else: + if self.MapWindow == self.firstMapWindow: + self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap) + else: + self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap) + + def OnZoomChangedFirstMap(self): + """Display region of the first window (Map) changed. + + Synchronize the region of the second map and re-render it. + This is the default implementation which can be overridden. + """ + region = self.GetFirstMap().GetCurrentRegion() + self.GetSecondMap().region.update(region) + self.Render(mapToRender=self.GetSecondWindow()) + + def OnZoomChangedSecondMap(self): + """Display region of the second window (Map) changed. + + Synchronize the region of the second map and re-render it. + This is the default implementation which can be overridden. + """ + region = self.GetSecondMap().GetCurrentRegion() + self.GetFirstMap().region.update(region) + self.Render(mapToRender=self.GetFirstWindow()) + + def OnZoomIn(self, event): + """Zoom in the map.""" + self.GetFirstWindow().SetModeZoomIn() + self.GetSecondWindow().SetModeZoomIn() + + def OnZoomOut(self, event): + """Zoom out the map.""" + self.GetFirstWindow().SetModeZoomOut() + self.GetSecondWindow().SetModeZoomOut() + + def OnPan(self, event): + """Panning, set mouse to pan""" + self.GetFirstWindow().SetModePan() + self.GetSecondWindow().SetModePan() + + def OnPointer(self, event): + """Set pointer mode (dragging overlays)""" + self.GetFirstWindow().SetModePointer() + self.GetSecondWindow().SetModePointer() + + def OnQuery(self, event): + """Set query mode""" + self.GetFirstWindow().SetModeQuery() + self.GetSecondWindow().SetModeQuery() + + def OnRender(self, event): + """Re-render map composition (each map layer)""" + self.Render(mapToRender=self.GetFirstWindow()) + self.Render(mapToRender=self.GetSecondWindow()) + + def Render(self, mapToRender): + """Re-render map composition""" + mapToRender.UpdateMap( + render=True, renderVector=mapToRender == self.GetFirstWindow() + ) + + # update statusbar + self.StatusbarUpdate() + + def OnErase(self, event): + """Erase the canvas""" + self.Erase(mapToErase=self.GetFirstWindow()) + self.Erase(mapToErase=self.GetSecondWindow()) + + def Erase(self, mapToErase): + """Erase the canvas""" + mapToErase.EraseMap() + + def OnDraw(self, event): + """Re-display current map composition""" + self.Draw(mapToDraw=self.GetFirstWindow()) + self.Draw(mapToDraw=self.GetSecondWindow()) + + def Draw(self, mapToDraw): + """Re-display current map composition""" + mapToDraw.UpdateMap(render=False) + + +class FrameMixin: + """Mixin class for wx.Panel that provides methods standardly + used on wx.Frame widget""" + + def Show(self): + self.GetParent().Show() + + def SetTitle(self, name): + self.GetParent().SetTitle(name) + + def Raise(self): + self.GetParent().Raise() + + def SetFocus(self): + self.GetParent().SetFocus() + + def CenterOnScreen(self): + self.GetParent().CenterOnScreen() + + def CentreOnScreen(self): + self.GetParent().CentreOnScreen() + + def IsFullScreen(self): + return self.GetParent().IsFullScreen() + + def IsIconized(self): + self.GetParent().IsIconized() + + def Maximize(self): + self.GetParent().Maximize() + + def ShowFullScreen(self, show): + for toolbar in self.toolbars.keys(): + self._mgr.GetPane(self.toolbars[toolbar]).Show(self.IsFullScreen()) + if self.statusbar: + self._mgr.GetPane("statusbar").Show(self.IsFullScreen()) + self._mgr.Update() + + self.GetParent().ShowFullScreen(show) + + def OnFullScreen(self, event): + """!Switches frame to fullscreen mode, hides toolbars and statusbar""" + self.ShowFullScreen(not self.IsFullScreen()) + event.Skip() + + def BindToFrame(self, *args): + self.GetParent().Bind(*args) + + def Destroy(self): + self.GetParent().Destroy() diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index c3186078a98..018bd9fd0d0 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -75,19 +75,20 @@ def __init__(self, mapframe, statusbar): self.mapFrame = mapframe self.statusbar = statusbar - self.choice = wx.Choice(self.statusbar, wx.ID_ANY) - - self.choice.Bind(wx.EVT_CHOICE, self.OnToggleStatus) - self.statusbarItems = dict() self._postInitialized = False self._modeIndexSet = False + self._mode = 0 + self.shownWidgetInStatusbar = None self.progressbar = SbProgress(self.mapFrame, self.statusbar, self) self.progressbar.progressShown.connect(self._progressShown) self.progressbar.progressHidden.connect(self._progressHidden) + self.shownWidgetInStatusbarChanged = Signal("SbManager.shownWidgetInStatusbarChanged") + self.shownWidgetInStatusbarChanged.connect(self.ShowItem) + self._oldStatus = "" self._hiddenItems = {} @@ -126,8 +127,6 @@ def AddStatusbarItem(self, item): :func:`AddStatusbarItemsByClass` """ self.statusbarItems[item.name] = item - if item.GetPosition() == 0: - self.choice.Append(item.label, clientData=item) # attrError? def AddStatusbarItemsByClass(self, itemClasses, **kwargs): """Adds items to statusbar @@ -187,37 +186,41 @@ def ShowItem(self, itemName): :func:`Update` """ - if ( - self.statusbarItems[itemName].GetPosition() != 0 - or not self.progressbar.IsShown() - ): + for item in self.statusbarItems.values(): + if item.GetPosition() == 0: + if item.name != itemName and not self.progressbar.IsShown(): + item.Hide() + else: + item.Update() self.statusbarItems[itemName].Show() - - def _postInit(self): - """Post-initialization method - - It sets internal user settings, - set choice's selection (from user settings) and does reposition. - It needs choice filled by items. - it is called automatically. - """ - UserSettings.Set( - group="display", - key="statusbarMode", - subkey="choices", - value=self.choice.GetItems(), - settings_type="internal", - ) - - if not self._modeIndexSet: - self.choice.SetSelection( - UserSettings.Get( - group="display", key="statusbarMode", subkey="selection" - ) - ) - self.Reposition() - - self._postInitialized = True + self.shownWidgetInStatusbar = list(self.statusbarItems.keys()).index(itemName) + +# def _postInit(self): +# """Post-initialization method +# +# It sets internal user settings, +# set choice's selection (from user settings) and does reposition. +# It needs choice filled by items. +# it is called automatically. +# """ +# print(self.choice.GetItems()) +# UserSettings.Set( +# group="display", +# key="statusbarMode", +# subkey="choices", +# value=self.choice.GetItems(), +# settings_type="internal", +# ) +# +# if not self._modeIndexSet: +# self.choice.SetSelection( +# UserSettings.Get( +# group="display", key="statusbarMode", subkey="selection" +# ) +# ) +# self.Reposition() +# +# self._postInitialized = True def Update(self): """Updates statusbar @@ -226,20 +229,21 @@ def Update(self): """ self.progressbar.Update() - if not self._postInitialized: - self._postInit() +# if not self._postInitialized: +# self._postInit() for item in self.statusbarItems.values(): if item.GetPosition() == 0: if not self.progressbar.IsShown(): item.Hide() else: - item.Update() # mask, render + item.Update() # render - if self.progressbar.IsShown(): - pass - elif self.choice.GetCount() > 0: - item = self.choice.GetClientData(self.choice.GetSelection()) - item.Update() +# self.statusbarItems.values() +# if self.progressbar.IsShown(): +# pass +# elif self.choice.GetCount() > 0: +# item = self.choice.GetClientData(self.choice.GetSelection()) +# item.Update() def Reposition(self): """Reposition items in statusbar @@ -252,7 +256,6 @@ def Reposition(self): for item in self.statusbarItems.values(): widgets.append((item.GetPosition(), item.GetWidget())) - widgets.append((1, self.choice)) widgets.append((1, self.progressbar.GetWidget())) for idx, win in widgets: @@ -285,11 +288,11 @@ def GetProgressBar(self): def _progressShown(self): self._oldStatus = self.statusbar.GetStatusText(0) - self.choice.GetClientData(self.choice.GetSelection()).Hide() + #self.choice.GetClientData(self.choice.GetSelection()).Hide() def _progressHidden(self): self.statusbar.SetStatusText(self._oldStatus, 0) - self.choice.GetClientData(self.choice.GetSelection()).Show() + #self.choice.GetClientData(self.choice.GetSelection()).Show() def OnToggleStatus(self, event): """Toggle status text""" @@ -300,12 +303,11 @@ def SetMode(self, modeIndex): Mode is usually driven by user through choice. """ - self._modeIndexSet = True - self.choice.SetSelection(modeIndex) + self._mode = modeIndex def GetMode(self): """Returns current mode""" - return self.choice.GetSelection() + return self._mode def SetProgress(self, range, value, text): """Update progress.""" @@ -513,7 +515,7 @@ class SbGoTo(SbItem): def __init__(self, mapframe, statusbar, position=0): SbItem.__init__(self, mapframe, statusbar, position) self.name = "goto" - self.label = _("Go to") + self.label = _("Go to XY coordinates") self.widget = TextCtrl( parent=self.statusbar, @@ -822,7 +824,7 @@ class SbRegionExtent(SbTextItem): def __init__(self, mapframe, statusbar, position=0): SbTextItem.__init__(self, mapframe, statusbar, position) self.name = "displayRegion" - self.label = _("Extent") + self.label = _("Display extent") def Show(self): precision = int( diff --git a/gui/wxpython/mapdisp/statusbar_new.py b/gui/wxpython/mapdisp/statusbar_new.py new file mode 100644 index 00000000000..b797f1eb096 --- /dev/null +++ b/gui/wxpython/mapdisp/statusbar_new.py @@ -0,0 +1,745 @@ +""" +@package frame.statusbar + +@brief Classes for main window statusbar management + +Classes: + - statusbar::SbMapDisplay + - statusbar::SbException + - statusbar::SbItem + - statusbar::SbTextItem + - statusbar::SbCoordinates + +(C) 2022 by the GRASS Development Team + +This program is free software under the GNU General Public License +(>=v2). Read the file COPYING that comes with GRASS for details. + +@author Linda Kladivova +@author Anna Petrasova +@author Vaclav Petras +""" + +import wx + +from core import utils +from mapdisp.properties import ChBRender + + +class SbMapDisplay: + """Statusbar for map display window.""" + + def __init__(self, parent, giface): + self.parent = parent + self.giface = giface + self.statusbar = wx.StatusBar(self.parent, id=wx.ID_ANY) + self.statusbar.SetMinHeight(24) + self.statusbar.SetFieldsCount(3) + self.statusbar.SetStatusWidths([200, -1, 100]) + self._init_items() + self.statusbar.Bind(wx.EVT_SIZE, self.OnSize) + + self._repositionStatusbar() + + def _init_items(self): + """"Init all items that can be shown in statusbar.""" + self.coordinates = SbCoordinates(self.widget, self.giface) + self.render = ChBRender(self.widget, self.properties) + + def GetStatusbar(self): + return self.statusbar + + def _repositionStatusbar(self): + """Reposition widgets in main window statusbar""" + rect1 = self.GetStatusbar().GetFieldRect(1) + rect1.x += 1 + rect1.y += 1 + self.coordinates.GetItem().SetRect(rect1) + rect1.x += 1 + rect1.y += 1 + self.render.GetItem().SetRect(rect1) + + def OnSize(self, event): + """Adjust main window statusbar on changing size""" + self._repositionStatusbar() + + def SetStatusText(self, *args): + """Overide wx.StatusBar method""" + self.GetStatusbar().SetStatusText(*args) + + +class SbException(Exception): + """Exception class used in SbMapDisplay and SbItems""" + + def __init__(self, message): + self.message = message + + def __str__(self): + return self.message + + +class SbItem: + """Base class for statusbar items.""" + + def __init__(self, statusbar): + self.statusbar = statusbar + + def Show(self): + """Invokes showing of underlying item. + + In derived classes it can do what is appropriate for it, + e.g. showing text on statusbar (only). + """ + self.item.Show() + + def Hide(self): + self.item.Hide() + + def SetValue(self, value): + self.item.SetValue(value) + + def GetValue(self): + return self.item.GetValue() + + def GetItem(self): + """Returns underlying widget. + + :return: widget or None if doesn't exist + """ + return self.item + + def _update(self): + """Default implementation for Update method. + + :param longHelp: True to enable long help (help from toolbars) + """ + self.statusbar.SetStatusText("", 0) + self.Show() + + +class SbTextItem(SbItem): + """Base class for items without widgets. + + Only sets statusbar text. + """ + + def __init__(self, statusbar): + SbItem.__init__(self, statusbar) + + self.text = None + + def Show(self): + self.statusbar.SetStatusText(self.GetValue()) + + def Hide(self): + self.statusbar.SetStatusText("") + + def SetValue(self, value): + self.text = value + + def GetValue(self): + return self.text + + def GetWidget(self): + return None + + +class SbCoordinates(SbTextItem): + """Show map coordinates when mouse moves. + + Requires MapWindow.GetLastEN method.""" + + def __init__(self, statusbar, giface, mapDisplayProperties): + SbTextItem.__init__(self, statusbar) + self.name = "coordinates" + self.label = _("Coordinates") + self._properties = mapDisplayProperties + self._additionalInfo = None + self._basicValue = None + + def Show(self): + """Show the last map window coordinates. + + .. todo:: + remove last EN call and use coordinates coming from signal + """ + try: + e, n = self.giface.GetMapWindow().GetLastEN() + self._basicValue = self.ReprojectENFromMap(e, n) + if self._additionalInfo: + value = _("{coords} ({additionalInfo})").format( + coords=self._basicValue, additionalInfo=self._additionalInfo + ) + else: + value = self._basicValue + self.SetValue(value) + except SbException as e: + self.SetValue(e.message) + except TypeError: + self.SetValue("") + except AttributeError: + self.SetValue("") + SbTextItem.Show(self) + + def SetAdditionalInfo(self, text): + """Sets additional info to be shown together with coordinates. + + The format is translation dependent but the default is + "coordinates (additional info)" + + It does not show the changed text immediately, it waits for the Show() + method to be called. + + :param text: string to be shown + """ + self._additionalInfo = text + + def ReprojectENFromMap(self, e, n): + """Reproject east, north to user defined projection. + + :param e,n: coordinate + + @throws SbException if useDefinedProjection is True and projection is not defined in UserSettings + """ + useDefinedProjection = self._properties.useDefinedProjection + projectionSettings = self._properties.projectionSettings + + if useDefinedProjection: + if projectionSettings["proj4"]: + raise SbException(_("Projection not defined (check the settings)")) + else: + # reproject values + proj, coord = utils.ReprojectCoordinates( + coord=(e, n), projOut=projectionSettings["proj4"], flags="d" + ) + if coord: + e, n = coord + if proj in ("ll", "latlong", "longlat") and projectionSettings["format"] == "DMS": + return utils.Deg2DMS(e, n, precision=projectionSettings["precision"]) + else: + return "%.*f; %.*f" % (projectionSettings["precision"], e, projectionSettings["precision"], n) + else: + raise SbException(_("Error in projection (check the settings)")) + else: + if self.giface.GetMapDisplay().GetMap().projinfo["proj"] == "ll" and projectionSettings["format"] == "DMS": + return utils.Deg2DMS(e, n, precision=projectionSettings["precision"]) + else: + return "%.*f; %.*f" % (projectionSettings["precision"], e, projectionSettings["precision"], n) + + +#class SbProgress(SbItem): +# """General progress bar to show progress. +# +# Underlaying widget is wx.Gauge. +# """ +# +# def __init__(self, mapframe, statusbar, sbManager, position=0): +# self.progressShown = Signal("SbProgress.progressShown") +# self.progressHidden = Signal("SbProgress.progressHidden") +# SbItem.__init__(self, mapframe, statusbar, position) +# self.name = "progress" +# self.sbManager = sbManager +# # on-render gauge +# self.widget = wx.Gauge( +# parent=self.statusbar, id=wx.ID_ANY, range=0, style=wx.GA_HORIZONTAL +# ) +# self.Hide() +# +# self.progressShown.connect(self._progressShown) +# self.progressHidden.connect(self._progressHidden) +# +# def GetRange(self): +# """Returns progress range.""" +# return self.widget.GetRange() +# +# def SetRange(self, range): +# """Sets progress range.""" +# if range > 0: +# if self.GetRange() != range: +# self.widget.SetRange(range) +# self.Show() +# else: +# self.Hide() +# +# def Show(self): +# if not self.IsShown(): +# self.progressShown.emit() +# self.widget.Show() +# +# def Hide(self): +# if self.IsShown(): +# self.progressHidden.emit() +# self.widget.Hide() +# +# def IsShown(self): +# """Is progress bar shown""" +# return self.widget.IsShown() +# +# def SetValue(self, value): +# """Sets value of progressbar.""" +# if value > self.GetRange(): +# self.Hide() +# return +# +# self.widget.SetValue(value) +# if value == self.GetRange(): +# self.Hide() +# +# def GetWidget(self): +# """Returns underlaying winget. +# +# :return: widget or None if doesn't exist +# """ +# return self.widget +# +# def Update(self): +# pass +# +# def GetProgressBar(self): +# """Returns progress bar""" +# return self.progressbar +# +# def _progressShown(self): +# self._oldStatus = self.statusbar.GetStatusText(0) +# self.choice.GetClientData(self.choice.GetSelection()).Hide() +# +# def _progressHidden(self): +# self.statusbar.SetStatusText(self._oldStatus, 0) +# self.choice.GetClientData(self.choice.GetSelection()).Show() +# +# def SetProgress(self, range, value, text): +# """Update progress.""" +# self.progressbar.SetRange(range) +# self.progressbar.SetValue(value) +# if text: +# self.statusbar.SetStatusText(text) +# + + + + +#class SbMapScale(SbItem): +# """Editable combobox to get/set current map scale.""" +# +# def __init__(self, parent, mapWindowProperties, giface): +# SbItem.__init__(self, mapWindowProperties) +# self.name = "mapscale" +# self.widget = wx.ComboBox( +# parent=parent, +# id=wx.ID_ANY, +# label = _("Map scale"), +# style=wx.TE_PROCESS_ENTER, +# size=(150, -1), +# ) +# self.widget.SetItems( +# [ +# "1:1000", +# "1:5000", +# "1:10000", +# "1:25000", +# "1:50000", +# "1:100000", +# "1:1000000", +# ] +# ) +# self.widget.SetToolTip( +# wx.ToolTip( +# _( +# "As everyone's monitors and resolutions " +# "are set differently these values are not " +# "true map scales, but should get you into " +# "the right neighborhood." +# ) +# ) +# ) +# +# self.widget.Bind(wx.EVT_TEXT_ENTER, self.OnChangeMapScale) +# self.widget.Bind(wx.EVT_COMBOBOX, self.OnChangeMapScale) +# +# self.lastMapScale = None +# +# def Update(self): +# scale = self._properties.mapScale +# self.parent.SetStatusText("") +# try: +# self.SetValue("1:%ld" % (scale + 0.5)) +# except TypeError: +# pass # FIXME, why this should happen? +# +# self.lastMapScale = scale +# +# +# def OnChangeMapScale(self, event): +# """Map scale changed by user""" +# scale = event.GetString() +# +# try: +# if scale[:2] != "1:": +# raise ValueError +# value = int(scale[2:]) +# except ValueError: +# self.SetValue("1:%ld" % int(self._properties.mapScale)) +# return +# +# self._properties.mapScale = value +# +# # redraw map if auto-rendering is enabled +# if self._properties.autoRender: +# self.giface.updateMap.emit() + + +#class SbGoTo(SbItem): +# """Textctrl to set coordinates which to focus on. +# +# Requires MapFrame.GetWindow, MapWindow.GoTo method. +# """ +# +# def __init__(self, mapframe, statusbar, position=0): +# SbItem.__init__(self, mapframe, statusbar, position) +# self.name = "goto" +# self.label = _("Go to") +# +# self.widget = TextCtrl( +# parent=self.statusbar, +# id=wx.ID_ANY, +# value="", +# style=wx.TE_PROCESS_ENTER, +# size=(300, -1), +# ) +# +# self.widget.Hide() +# +# self.widget.Bind(wx.EVT_TEXT_ENTER, self.OnGoTo) +# +# def ReprojectENToMap(self, e, n, useDefinedProjection): +# """Reproject east, north from user defined projection +# +# :param e,n: coordinate (for DMS string, else float or string) +# :param useDefinedProjection: projection defined by user in settings dialog +# +# @throws SbException if useDefinedProjection is True and projection is not defined in UserSettings +# """ +# if useDefinedProjection: +# settings = UserSettings.Get( +# group="projection", key="statusbar", subkey="proj4" +# ) +# if not settings: +# raise SbException(_("Projection not defined (check the settings)")) +# else: +# # reproject values +# projIn = settings +# projOut = RunCommand("g.proj", flags="jf", read=True) +# proj = projIn.split(" ")[0].split("=")[1] +# if proj in ("ll", "latlong", "longlat"): +# e, n = utils.DMS2Deg(e, n) +# proj, coord1 = utils.ReprojectCoordinates( +# coord=(e, n), projIn=projIn, projOut=projOut, flags="d" +# ) +# e, n = coord1 +# else: +# e, n = float(e), float(n) +# proj, coord1 = utils.ReprojectCoordinates( +# coord=(e, n), projIn=projIn, projOut=projOut, flags="d" +# ) +# e, n = coord1 +# elif self.mapFrame.GetMap().projinfo["proj"] == "ll": +# e, n = utils.DMS2Deg(e, n) +# else: +# e, n = float(e), float(n) +# return e, n +# +# def OnGoTo(self, event): +# """Go to position""" +# try: +# e, n = self.GetValue().split(";") +# e, n = self.ReprojectENToMap(e, n, self.mapFrame.GetProperty("projection")) +# self.mapFrame.GetWindow().GoTo(e, n) +# self.widget.SetFocus() +# except ValueError: +# # FIXME: move this code to MapWindow/BufferedWindow/MapFrame +# region = self.mapFrame.GetMap().GetCurrentRegion() +# precision = int( +# UserSettings.Get(group="projection", key="format", subkey="precision") +# ) +# format = UserSettings.Get(group="projection", key="format", subkey="ll") +# if self.mapFrame.GetMap().projinfo["proj"] == "ll" and format == "DMS": +# self.SetValue( +# "%s" +# % utils.Deg2DMS( +# region["center_easting"], +# region["center_northing"], +# precision=precision, +# ) +# ) +# else: +# self.SetValue( +# "%.*f; %.*f" +# % ( +# precision, +# region["center_easting"], +# precision, +# region["center_northing"], +# ) +# ) +# except SbException as e: +# # FIXME: this may be useless since statusbar update checks user +# # defined projection and this exception raises when user def proj +# # does not exists +# self.statusbar.SetStatusText(str(e), 0) +# +# def GetCenterString(self, map): +# """Get current map center in appropriate format""" +# region = map.GetCurrentRegion() +# precision = int( +# UserSettings.Get(group="projection", key="format", subkey="precision") +# ) +# format = UserSettings.Get(group="projection", key="format", subkey="ll") +# projection = UserSettings.Get( +# group="projection", key="statusbar", subkey="proj4" +# ) +# +# if self.mapFrame.GetProperty("projection"): +# if not projection: +# raise SbException(_("Projection not defined (check the settings)")) +# else: +# proj, coord = utils.ReprojectCoordinates( +# coord=(region["center_easting"], region["center_northing"]), +# projOut=projection, +# flags="d", +# ) +# if coord: +# if proj in ("ll", "latlong", "longlat") and format == "DMS": +# return "%s" % utils.Deg2DMS( +# coord[0], coord[1], precision=precision +# ) +# else: +# return "%.*f; %.*f" % (precision, coord[0], precision, coord[1]) +# else: +# raise SbException(_("Error in projection (check the settings)")) +# else: +# if self.mapFrame.GetMap().projinfo["proj"] == "ll" and format == "DMS": +# return "%s" % utils.Deg2DMS( +# region["center_easting"], +# region["center_northing"], +# precision=precision, +# ) +# else: +# return "%.*f; %.*f" % ( +# precision, +# region["center_easting"], +# precision, +# region["center_northing"], +# ) +# +# def SetCenter(self): +# """Set current map center as item value""" +# center = self.GetCenterString(self.mapFrame.GetMap()) +# self.SetValue(center) +# +# def Update(self): +# self.statusbar.SetStatusText("") +# +# try: +# self.SetCenter() +# self.Show() +# except SbException as e: +# self.statusbar.SetStatusText(str(e), 0) +# +# # disable long help +# self.mapFrame.StatusbarEnableLongHelp(False) + +# +# +# +#class SbDisplayGeometry(SbTextItem): +# """Show current display resolution.""" +# +# def __init__(self, mapframe, statusbar, position=0): +# SbTextItem.__init__(self, mapframe, statusbar, position) +# self.name = "displayGeometry" +# self.label = _("Display geometry") +# +# def Show(self): +# region = copy.copy(self.mapFrame.GetMap().GetCurrentRegion()) +# if self.mapFrame.mapWindowProperties.resolution: +# compRegion = self.mapFrame.GetMap().GetRegion(add3d=False) +# region["rows"] = abs( +# int((region["n"] - region["s"]) / compRegion["nsres"]) + 0.5 +# ) +# region["cols"] = abs( +# int((region["e"] - region["w"]) / compRegion["ewres"]) + 0.5 +# ) +# region["nsres"] = compRegion["nsres"] +# region["ewres"] = compRegion["ewres"] +# self.SetValue( +# "rows=%d; cols=%d; nsres=%.2f; ewres=%.2f" +# % (region["rows"], region["cols"], region["nsres"], region["ewres"]) +# ) +# SbTextItem.Show(self) + + + + +#class SbRegionExtent(SbTextItem): +# """Shows current display region""" +# +# def __init__(self, mapframe, statusbar, position=0): +# SbTextItem.__init__(self, mapframe, statusbar, position) +# self.name = "displayRegion" +# self.label = _("Extent") +# +# def Show(self): +# precision = int( +# UserSettings.Get(group="projection", key="format", subkey="precision") +# ) +# format = UserSettings.Get(group="projection", key="format", subkey="ll") +# projection = self.mapFrame.GetProperty("projection") +# region = self._getRegion() +# try: +# regionReprojected = self.ReprojectRegionFromMap( +# region, projection, precision, format +# ) +# self.SetValue(regionReprojected) +# except SbException as e: +# self.SetValue(e.message) +# SbTextItem.Show(self) +# +# def _getRegion(self): +# """Get current display region""" +# return self.mapFrame.GetMap().GetCurrentRegion() # display region +# +# def _formatRegion(self, w, e, s, n, nsres, ewres, precision=None): +# """Format display region string for statusbar +# +# :param nsres,ewres: unused +# """ +# if precision is not None: +# return "%.*f - %.*f, %.*f - %.*f" % ( +# precision, +# w, +# precision, +# e, +# precision, +# s, +# precision, +# n, +# ) +# else: +# return "%s - %s, %s - %s" % (w, e, s, n) +# +# def ReprojectRegionFromMap(self, region, useDefinedProjection, precision, format): +# """Reproject region values +# +# .. todo:: +# reorganize this method to remove code useful only for derived class SbCompRegionExtent +# """ +# if useDefinedProjection: +# settings = UserSettings.Get( +# group="projection", key="statusbar", subkey="proj4" +# ) +# +# if not settings: +# raise SbException(_("Projection not defined (check the settings)")) +# else: +# projOut = settings +# proj, coord1 = utils.ReprojectCoordinates( +# coord=(region["w"], region["s"]), projOut=projOut, flags="d" +# ) +# proj, coord2 = utils.ReprojectCoordinates( +# coord=(region["e"], region["n"]), projOut=projOut, flags="d" +# ) +# # useless, used in derived class +# proj, coord3 = utils.ReprojectCoordinates( +# coord=(0.0, 0.0), projOut=projOut, flags="d" +# ) +# proj, coord4 = utils.ReprojectCoordinates( +# coord=(region["ewres"], region["nsres"]), projOut=projOut, flags="d" +# ) +# if coord1 and coord2: +# if proj in ("ll", "latlong", "longlat") and format == "DMS": +# w, s = utils.Deg2DMS( +# coord1[0], coord1[1], string=False, precision=precision +# ) +# e, n = utils.Deg2DMS( +# coord2[0], coord2[1], string=False, precision=precision +# ) +# ewres, nsres = utils.Deg2DMS( +# abs(coord3[0]) - abs(coord4[0]), +# abs(coord3[1]) - abs(coord4[1]), +# string=False, +# hemisphere=False, +# precision=precision, +# ) +# return self._formatRegion( +# w=w, s=s, e=e, n=n, ewres=ewres, nsres=nsres +# ) +# else: +# w, s = coord1 +# e, n = coord2 +# ewres, nsres = coord3 +# return self._formatRegion( +# w=w, +# s=s, +# e=e, +# n=n, +# ewres=ewres, +# nsres=nsres, +# precision=precision, +# ) +# else: +# raise SbException(_("Error in projection (check the settings)")) +# +# else: +# if self.mapFrame.GetMap().projinfo["proj"] == "ll" and format == "DMS": +# w, s = utils.Deg2DMS( +# region["w"], region["s"], string=False, precision=precision +# ) +# e, n = utils.Deg2DMS( +# region["e"], region["n"], string=False, precision=precision +# ) +# ewres, nsres = utils.Deg2DMS( +# region["ewres"], region["nsres"], string=False, precision=precision +# ) +# return self._formatRegion(w=w, s=s, e=e, n=n, ewres=ewres, nsres=nsres) +# else: +# w, s = region["w"], region["s"] +# e, n = region["e"], region["n"] +# ewres, nsres = region["ewres"], region["nsres"] +# return self._formatRegion( +# w=w, s=s, e=e, n=n, ewres=ewres, nsres=nsres, precision=precision +# ) +# +# +#class SbCompRegionExtent(SbRegionExtent): +# """Shows computational region.""" +# +# def __init__(self, mapframe, statusbar, position=0): +# SbRegionExtent.__init__(self, mapframe, statusbar, position) +# self.name = "computationalRegion" +# self.label = _("Computational region") +# +# def _formatRegion(self, w, e, s, n, ewres, nsres, precision=None): +# """Format computational region string for statusbar""" +# if precision is not None: +# return "%.*f - %.*f, %.*f - %.*f (%.*f, %.*f)" % ( +# precision, +# w, +# precision, +# e, +# precision, +# s, +# precision, +# n, +# precision, +# ewres, +# precision, +# nsres, +# ) +# else: +# return "%s - %s, %s - %s (%s, %s)" % (w, e, s, n, ewres, nsres) +# +# def _getRegion(self): +# """Returns computational region.""" +# return self.mapFrame.GetMap().GetRegion() # computational region + + diff --git a/gui/wxpython/mapdisp/untitled0.py b/gui/wxpython/mapdisp/untitled0.py new file mode 100644 index 00000000000..5ad3e96166e --- /dev/null +++ b/gui/wxpython/mapdisp/untitled0.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Wed Feb 9 08:12:34 2022 + +@author: linwe +""" + + +class Spam(object): + sausages = False + + @property + def eggs(self): + if self.sausages: + return 42 + raise AttributeError("No eggs without sausages") + + @property + def invalid(self): + return self.foobar + + +spam = Spam() +print(hasattr(Spam, 'eggs')) + +print(hasattr(spam, 'eggs')) + +spam.sausages = True +print(hasattr(spam, 'eggs')) + +print(hasattr(spam, 'invalid')) +print(getattr(spam, 'eggs')) \ No newline at end of file From bdc0fc8e61c26f6908a43d7924aedcc9686b1856 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Thu, 17 Feb 2022 10:11:41 -0600 Subject: [PATCH 02/26] remove files pushed by mistake --- gui/wxpython/mapdisp/refactoringPR/base.py | 459 ---------- gui/wxpython/mapdisp/refactoringPR/mapdisp.py | 838 ------------------ .../mapdisp/refactoringPR/mapdisp_guicore.py | 838 ------------------ gui/wxpython/mapdisp/statusbar_new.py | 745 ---------------- gui/wxpython/mapdisp/untitled0.py | 33 - 5 files changed, 2913 deletions(-) delete mode 100644 gui/wxpython/mapdisp/refactoringPR/base.py delete mode 100644 gui/wxpython/mapdisp/refactoringPR/mapdisp.py delete mode 100644 gui/wxpython/mapdisp/refactoringPR/mapdisp_guicore.py delete mode 100644 gui/wxpython/mapdisp/statusbar_new.py delete mode 100644 gui/wxpython/mapdisp/untitled0.py diff --git a/gui/wxpython/mapdisp/refactoringPR/base.py b/gui/wxpython/mapdisp/refactoringPR/base.py deleted file mode 100644 index 0c2caab3332..00000000000 --- a/gui/wxpython/mapdisp/refactoringPR/base.py +++ /dev/null @@ -1,459 +0,0 @@ -""" -@package mapwin.mapwindow - -@brief Map display canvas basic functionality - base class and properties. - -Classes: - - mapwindow::MapWindowProperties - - mapwindow::MapWindowBase - -(C) 2006-2012 by the GRASS Development Team - -This program is free software under the GNU General Public License -(>=v2). Read the file COPYING that comes with GRASS for details. - -@author Martin Landa -@author Michael Barton -@author Jachym Cepicky -@author Vaclav Petras (handlers support) -@author Stepan Turek (handlers support) -""" - -import wx -import six - -from core.settings import UserSettings -from core.gcmd import GError -from gui_core.wrap import StockCursor - -from grass.script import core as grass -from grass.pydispatch.signal import Signal - - -class MapWindowProperties(object): - def __init__(self): - self._resolution = None - self.resolutionChanged = Signal("MapWindowProperties.resolutionChanged") - self._autoRender = None - self.autoRenderChanged = Signal("MapWindowProperties.autoRenderChanged") - self._showRegion = None - self.showRegionChanged = Signal("MapWindowProperties.showRegionChanged") - self._alignExtent = None - self.alignExtentChanged = Signal("MapWindowProperties.alignExtentChanged") - self._useDefinedProjection = False - self.useDefinedProjectionChanged = Signal( - "MapWindowProperties.useDefinedProjectionChanged" - ) - - def setValuesFromUserSettings(self): - """Convenient function to get values from user settings into this object.""" - self._resolution = UserSettings.Get( - group="display", key="compResolution", subkey="enabled" - ) - self._autoRender = UserSettings.Get( - group="display", key="autoRendering", subkey="enabled" - ) - self._showRegion = False # in statusbar.py was not from settings - self._alignExtent = UserSettings.Get( - group="display", key="alignExtent", subkey="enabled" - ) - - @property - def resolution(self): - return self._resolution - - @resolution.setter - def resolution(self, value): - if value != self._resolution: - self._resolution = value - self.resolutionChanged.emit(value=value) - - @property - def autoRender(self): - return self._autoRender - - @autoRender.setter - def autoRender(self, value): - if value != self._autoRender: - self._autoRender = value - self.autoRenderChanged.emit(value=value) - - @property - def showRegion(self): - return self._showRegion - - @showRegion.setter - def showRegion(self, value): - if value != self._showRegion: - self._showRegion = value - self.showRegionChanged.emit(value=value) - - @property - def alignExtent(self): - return self._alignExtent - - @alignExtent.setter - def alignExtent(self, value): - if value != self._alignExtent: - self._alignExtent = value - self.alignExtentChanged.emit(value=value) - - @property - def useDefinedProjection(self): - return self._useDefinedProjection - - @useDefinedProjection.setter - def useDefinedProjection(self, value): - self._useDefinedProjection = value - - @property - def epsg(self): - return UserSettings.Get(group="projection", key="statusbar", subkey="epsg") - - @property - def precision(self): - return int( - UserSettings.Get(group="projection", key="format", subkey="precision") - ) - - @property - def latlong(self): - return UserSettings.Get(group="projection", key="format", subkey="ll") - - @property - def proj4(self): - return UserSettings.Get( - group="projection", key="statusbar", subkey="proj4" - ) - - -class MapWindowBase(object): - """Abstract map display window class - - Superclass for BufferedWindow class (2D display mode), and GLWindow - (3D display mode). - - Subclasses have to define - - _bindMouseEvents method which binds MouseEvent handlers - - Pixel2Cell - - Cell2Pixel (if it is possible) - """ - - def __init__(self, parent, giface, Map): - self.parent = parent - self.Map = Map - self._giface = giface - - # Emitted when someone registers as mouse event handler - self.mouseHandlerRegistered = Signal("MapWindow.mouseHandlerRegistered") - # Emitted when mouse event handler is unregistered - self.mouseHandlerUnregistered = Signal("MapWindow.mouseHandlerUnregistered") - # emitted after double click in pointer mode on legend, text, scalebar - self.overlayActivated = Signal("MapWindow.overlayActivated") - # emitted when overlay should be hidden - self.overlayRemoved = Signal("MapWindow.overlayRemoved") - - # mouse attributes -- position on the screen, begin and end of - # dragging, and type of drawing - self.mouse = { - "begin": [0, 0], # screen coordinates - "end": [0, 0], - "use": "pointer", - "box": "point", - } - # last east, north coordinates, changes on mouse motion - self.lastEN = None - - # stores overridden cursor - self._overriddenCursor = None - - # dictionary where event types are stored as keys and lists of - # handlers for these types as values - self.handlersContainer = { - wx.EVT_LEFT_DOWN: [], - wx.EVT_LEFT_UP: [], - wx.EVT_LEFT_DCLICK: [], - wx.EVT_MIDDLE_DOWN: [], - wx.EVT_MIDDLE_UP: [], - wx.EVT_MIDDLE_DCLICK: [], - wx.EVT_RIGHT_DOWN: [], - wx.EVT_RIGHT_UP: [], - wx.EVT_RIGHT_DCLICK: [], - wx.EVT_MOTION: [], - wx.EVT_ENTER_WINDOW: [], - wx.EVT_LEAVE_WINDOW: [], - wx.EVT_MOUSEWHEEL: [], - wx.EVT_MOUSE_EVENTS: [], - } - - # available cursors - self._cursors = { - "default": StockCursor(cursorId=wx.CURSOR_ARROW), - "cross": StockCursor(cursorId=wx.CURSOR_CROSS), - "hand": StockCursor(cursorId=wx.CURSOR_HAND), - "pencil": StockCursor(cursorId=wx.CURSOR_PENCIL), - "sizenwse": StockCursor(cursorId=wx.CURSOR_SIZENWSE), - } - - # default cursor for window is arrow (at least we rely on it here) - # but we need to define attribute here - # cannot call SetNamedCursor since it expects the instance - # to be a wx window, so setting only the attribute - self._cursor = "default" - - wx.CallAfter(self.InitBinding) - - def __del__(self): - self.UnregisterAllHandlers() - - def InitBinding(self): - """Binds helper functions, which calls all handlers - registered to events with the events - """ - for ev, handlers in six.iteritems(self.handlersContainer): - self.Bind(ev, self.EventTypeHandler(handlers)) - - def EventTypeHandler(self, evHandlers): - return lambda event: self.HandlersCaller(event, evHandlers) - - def HandlersCaller(self, event, handlers): - """Hepler function which calls all handlers registered for - event - """ - for handler in handlers: - try: - handler(event) - except: - handlers.remove(handler) - GError( - parent=self, - message=_( - "Error occurred during calling of handler: %s \n" - "Handler was unregistered." - ) - % handler.__name__, - ) - - event.Skip() - - def RegisterMouseEventHandler(self, event, handler, cursor=None): - """Binds event handler - - @deprecated This method is deprecated. Use Signals or drawing API - instead. Signals do not cover all events but new Signals can be added - when needed consider also adding generic signal. However, more - interesting and useful is higher level API to create objects, graphics etc. - - Call event.Skip() in handler to allow default processing in MapWindow. - - If any error occurs inside of handler, the handler is removed. - - Before handler is unregistered it is called with - string value "unregistered" of event parameter. - - :: - - # your class methods - def OnButton(self, event): - # current map display's map window - # expects LayerManager to be the parent - self.mapwin = self.parent.GetLayerTree().GetMapDisplay().GetWindow() - if self.mapwin.RegisterEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction, - 'cross'): - self.parent.GetLayerTree().GetMapDisplay().Raise() - else: - # handle that you cannot get coordinates - - def OnMouseAction(self, event): - # get real world coordinates of mouse click - coor = self.mapwin.Pixel2Cell(event.GetPositionTuple()[:]) - self.text.SetLabel('Coor: ' + str(coor)) - self.mapwin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction) - event.Skip() - - - Emits mouseHandlerRegistered signal before handler is registered. - - :param event: one of mouse events - :param handler: function to handle event - :param cursor: cursor which temporary overrides current cursor - - :return: True if successful - :return: False if event cannot be bind - """ - self.mouseHandlerRegistered.emit() - # inserts handler into list - for containerEv, handlers in six.iteritems(self.handlersContainer): - if event == containerEv: - handlers.append(handler) - - self.mouse["useBeforeGenericEvent"] = self.mouse["use"] - self.mouse["use"] = "genericEvent" - - if cursor: - self._overriddenCursor = self.GetNamedCursor() - self.SetNamedCursor(cursor) - - return True - - def UnregisterAllHandlers(self): - """Unregisters all registered handlers - - @deprecated This method is deprecated. Use Signals or drawing API instead. - - Before each handler is unregistered it is called with string - value "unregistered" of event parameter. - """ - for containerEv, handlers in six.iteritems(self.handlersContainer): - for handler in handlers: - try: - handler("unregistered") - handlers.remove(handler) - except: - GError( - parent=self, - message=_( - "Error occurred during unregistration of handler: %s \n \ - Handler was unregistered." - ) - % handler.__name__, - ) - handlers.remove(handler) - - def UnregisterMouseEventHandler(self, event, handler): - """Unbinds event handler for event - - @deprecated This method is deprecated. Use Signals or drawing API instead. - - Before handler is unregistered it is called with string value - "unregistered" of event parameter. - - Emits mouseHandlerUnregistered signal after handler is unregistered. - - :param handler: handler to unbind - :param event: event from which handler will be unbinded - - :return: True if successful - :return: False if event cannot be unbind - """ - # removes handler from list - for containerEv, handlers in six.iteritems(self.handlersContainer): - if event != containerEv: - continue - try: - handler("unregistered") - if handler in handlers: - handlers.remove(handler) - else: - grass.warning( - _("Handler: %s was not registered") % handler.__name__ - ) - except: - GError( - parent=self, - message=_( - "Error occurred during unregistration of handler: %s \n \ - Handler was unregistered" - ) - % handler.__name__, - ) - handlers.remove(handler) - - # restore mouse use (previous state) - self.mouse["use"] = self.mouse["useBeforeGenericEvent"] - - # restore overridden cursor - if self._overriddenCursor: - self.SetNamedCursor(self._overriddenCursor) - - self.mouseHandlerUnregistered.emit() - return True - - def Pixel2Cell(self, xyCoords): - raise NotImplementedError() - - def Cell2Pixel(self, enCoords): - raise NotImplementedError() - - def OnMotion(self, event): - """Tracks mouse motion and update statusbar - - .. todo:: - remove this method when lastEN is not used - - :func:`GetLastEN` - """ - try: - self.lastEN = self.Pixel2Cell(event.GetPosition()) - except (ValueError): - self.lastEN = None - - event.Skip() - - def GetLastEN(self): - """Returns last coordinates of mouse cursor. - - @deprecated This method is deprecated. Use Signal with coordinates as parameters. - - :func:`OnMotion` - """ - return self.lastEN - - def SetNamedCursor(self, cursorName): - """Sets cursor defined by name.""" - cursor = self._cursors[cursorName] - self.SetCursor(cursor) - self._cursor = cursorName - - def GetNamedCursor(self): - """Returns current cursor name.""" - return self._cursor - - cursor = property(fget=GetNamedCursor, fset=SetNamedCursor) - - def SetModePointer(self): - """Sets mouse mode to pointer.""" - self.mouse["use"] = "pointer" - self.mouse["box"] = "point" - self.SetNamedCursor("default") - - def SetModePan(self): - """Sets mouse mode to pan.""" - self.mouse["use"] = "pan" - self.mouse["box"] = "box" - self.zoomtype = 0 - self.SetNamedCursor("hand") - - def SetModeZoomIn(self): - self._setModeZoom(zoomType=1) - - def SetModeZoomOut(self): - self._setModeZoom(zoomType=-1) - - def _setModeZoom(self, zoomType): - self.zoomtype = zoomType - self.mouse["use"] = "zoom" - self.mouse["box"] = "box" - self.pen = wx.Pen(colour="Red", width=2, style=wx.SHORT_DASH) - self.SetNamedCursor("cross") - - def SetModeDrawRegion(self): - self.mouse["use"] = "drawRegion" - self.mouse["box"] = "box" - self.pen = wx.Pen(colour="Red", width=2, style=wx.SHORT_DASH) - self.SetNamedCursor("cross") - - def SetModeQuery(self): - """Query mode on""" - self.mouse["use"] = "query" - self.mouse["box"] = "point" - self.zoomtype = 0 - self.SetNamedCursor("cross") - - def DisactivateWin(self): - """Use when the class instance is hidden in MapFrame.""" - raise NotImplementedError() - - def ActivateWin(self): - """Used when the class instance is activated in MapFrame.""" - raise NotImplementedError() diff --git a/gui/wxpython/mapdisp/refactoringPR/mapdisp.py b/gui/wxpython/mapdisp/refactoringPR/mapdisp.py deleted file mode 100644 index 1b9f05ee778..00000000000 --- a/gui/wxpython/mapdisp/refactoringPR/mapdisp.py +++ /dev/null @@ -1,838 +0,0 @@ -""" -@package gui_core.mapdisp - -@brief Base classes for Map display window - -Classes: - - mapdisp::MapPanelBase - - mapdisp::SingleMapPanel - - mapdisp::DoubleMapPanel - -(C) 2009-2014 by the GRASS Development Team - -This program is free software under the GNU General Public License -(>=v2). Read the file COPYING that comes with GRASS for details. - -@author Martin Landa -@author Michael Barton -@author Vaclav Petras -@author Anna Kratochvilova -""" - -import sys -import six - -import wx - -from core.debug import Debug -from gui_core.toolbars import ToolSwitcher -from gui_core.wrap import NewId -from mapdisp import statusbar as sb - -from grass.script import core as grass - - -class MapPanelBase(wx.Panel): - """Base class for map display window - - Derived class must use (create and initialize) \c statusbarManager - or override - GetProperty(), SetProperty() and HasProperty() methods. - - Several methods has to be overridden or - \c NotImplementedError("MethodName") will be raised. - - If derived class enables and disables auto-rendering, - it should override IsAutoRendered method. - - It is expected that derived class will call _setUpMapWindow(). - - Derived class can has one or more map windows (and map renders) - but implementation of MapPanelBase expects that one window and - one map will be current. - Current instances of map window and map renderer should be returned - by methods GetWindow() and GetMap() respectively. - - AUI manager is stored in \c self._mgr. - """ - - def __init__( - self, - parent=None, - id=wx.ID_ANY, - title="", - auimgr=None, - name="", - **kwargs, - ): - """ - - .. warning:: - Use \a auimgr parameter only if you know what you are doing. - - :param parent: gui parent - :param id: wx id - :param title: window title - :param toolbars: array of activated toolbars, e.g. ['map', 'digit'] - :param auimgr: AUI manager (if \c None, wx.aui.AuiManager is used) - :param name: panel name - :param kwargs: arguments passed to \c wx.Panel - """ - - self.parent = parent - - wx.Panel.__init__(self, parent, id, name=name, **kwargs) - - # toolbars - self.toolbars = {} - self.iconsize = (16, 16) - - # - # Fancy gui - # - if auimgr is None: - from wx.aui import AuiManager - - self._mgr = AuiManager(self) - else: - self._mgr = auimgr - - # handles switching between tools in different toolbars - self._toolSwitcher = ToolSwitcher() - self._toolSwitcher.toggleToolChanged.connect(self._onToggleTool) - - # set accelerator table - self.shortcuts_table = [ - (self.OnCloseWindow, wx.ACCEL_CTRL, ord("W")), - (self.OnRender, wx.ACCEL_CTRL, ord("R")), - (self.OnRender, wx.ACCEL_NORMAL, wx.WXK_F5), - ] - - self._initShortcuts() - - def _initShortcuts(self): - """init shortcuts to acceleration table""" - accelTable = [] - for handler, entry, kdb in self.shortcuts_table: - wxId = NewId() - self.Bind(wx.EVT_MENU, handler, id=wxId) - accelTable.append((entry, kdb, wxId)) - self.SetAcceleratorTable(wx.AcceleratorTable(accelTable)) - - def _initMap(self, Map): - """Initialize map display, set dimensions and map region""" - if not grass.find_program("g.region", "--help"): - sys.exit( - _("GRASS module '%s' not found. Unable to start map " "display window.") - % "g.region" - ) - - Debug.msg(2, "MapPanel._initMap():") - Map.ChangeMapSize(self.GetClientSize()) - Map.region = Map.GetRegion() # g.region -upgc - # self.Map.SetRegion() # adjust region to match display window - - def _resize(self): - Debug.msg(1, "MapPanel_resize():") - wm, hw = self.MapWindow.GetClientSize() - wf, hf = self.GetSize() - dw = wf - wm - dh = hf - hw - self.SetSize((wf + dw, hf + dh)) - - def _onToggleTool(self, id): - if self._toolSwitcher.IsToolInGroup(id, "mouseUse"): - self.GetWindow().UnregisterAllHandlers() - - def OnSize(self, event): - """Adjust statusbar on changing size""" - # reposition checkbox in statusbar - self.StatusbarReposition() - - # update statusbar - self.StatusbarUpdate() - - def OnCloseWindow(self, event): - self.Destroy() - - def GetToolSwitcher(self): - return self._toolSwitcher - - def SetProperty(self, name, value): - """Sets property""" - if self.HasProperty("projection"): - self.statusbarManager.SetProperty(name, value) - else: - self.mapWindowProperties.useDefinedProjection = value - - def GetProperty(self, name): - """Returns property""" - if self.HasProperty("projection"): - return self.statusbarManager.GetProperty(name) - else: - return self.mapWindowProperties.useDefinedProjection - - def HasProperty(self, name): - """Checks whether object has property""" - return self.statusbarManager.HasProperty(name) - - def GetPPM(self): - """Get pixel per meter - - .. todo:: - now computed every time, is it necessary? - - .. todo:: - enable user to specify ppm (and store it in UserSettings) - """ - # TODO: need to be fixed... - # screen X region problem - # user should specify ppm - dc = wx.ScreenDC() - dpSizePx = wx.DisplaySize() # display size in pixels - dpSizeMM = wx.DisplaySizeMM() # display size in mm (system) - dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4) # inches - sysPpi = dc.GetPPI() - comPpi = (dpSizePx[0] / dpSizeIn[0], dpSizePx[1] / dpSizeIn[1]) - - ppi = comPpi # pixel per inch - ppm = ((ppi[0] / 2.54) * 100, (ppi[1] / 2.54) * 100) # pixel per meter - - Debug.msg( - 4, - "MapPanelBase.GetPPM(): size: px=%d,%d mm=%f,%f " - "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" - % ( - dpSizePx[0], - dpSizePx[1], - dpSizeMM[0], - dpSizeMM[1], - dpSizeIn[0], - dpSizeIn[1], - sysPpi[0], - sysPpi[1], - comPpi[0], - comPpi[1], - ppm[0], - ppm[1], - ), - ) - - return ppm - - def SetMapScale(self, value, map=None): - """Set current map scale - - :param value: scale value (n if scale is 1:n) - :param map: Map instance (if none self.Map is used) - """ - if not map: - map = self.Map - - region = self.Map.region - dEW = value * (region["cols"] / self.GetPPM()[0]) - dNS = value * (region["rows"] / self.GetPPM()[1]) - region["n"] = region["center_northing"] + dNS / 2.0 - region["s"] = region["center_northing"] - dNS / 2.0 - region["w"] = region["center_easting"] - dEW / 2.0 - region["e"] = region["center_easting"] + dEW / 2.0 - - # add to zoom history - self.GetWindow().ZoomHistory(region["n"], region["s"], region["e"], region["w"]) - - def GetMapScale(self, map=None): - """Get current map scale - - :param map: Map instance (if none self.Map is used) - """ - if not map: - map = self.GetMap() - - region = map.region - ppm = self.GetPPM() - - heightCm = region["rows"] / ppm[1] * 100 - widthCm = region["cols"] / ppm[0] * 100 - - Debug.msg( - 4, "MapPanel.GetMapScale(): width_cm=%f, height_cm=%f" % (widthCm, heightCm) - ) - - xscale = (region["e"] - region["w"]) / (region["cols"] / ppm[0]) - yscale = (region["n"] - region["s"]) / (region["rows"] / ppm[1]) - scale = (xscale + yscale) / 2.0 - - Debug.msg( - 3, - "MapPanel.GetMapScale(): xscale=%f, yscale=%f -> scale=%f" - % (xscale, yscale, scale), - ) - - return scale - - def GetProgressBar(self): - """Returns progress bar - - Progress bar can be used by other classes. - """ - return self.statusbarManager.GetProgressBar() - - def GetMap(self): - """Returns current map (renderer) instance""" - raise NotImplementedError("GetMap") - - def GetWindow(self): - """Returns current map window""" - raise NotImplementedError("GetWindow") - - def GetWindows(self): - """Returns list of map windows""" - raise NotImplementedError("GetWindows") - - def GetMapToolbar(self): - """Returns toolbar with zooming tools""" - raise NotImplementedError("GetMapToolbar") - - def GetToolbar(self, name): - """Returns toolbar if exists and is active, else None.""" - if name in self.toolbars and self.toolbars[name].IsShown(): - return self.toolbars[name] - - return None - - def StatusbarUpdate(self): - """Update statusbar content""" - if self.statusbarManager: - Debug.msg(5, "MapPanelBase.StatusbarUpdate()") - self.statusbarManager.Update() - - def IsAutoRendered(self): - """Check if auto-rendering is enabled""" - # TODO: this is now not the right place to access this attribute - # TODO: add mapWindowProperties to init parameters - # and pass the right object in the init of derived class? - # or do not use this method at all, let mapwindow decide - return self.mapWindowProperties.autoRender - - def CoordinatesChanged(self): - """Shows current coordinates on statusbar.""" - # assuming that the first mode is coordinates - # probably shold not be here but good solution is not available now - if self.statusbarManager: - if self.statusbarManager.GetMode() == 0: - self.statusbarManager.ShowItem("coordinates") - - def CreateStatusbar(self, statusbarItems): - """Create statusbar (default items).""" - # create statusbar and its manager - statusbar = wx.StatusBar(self, id=wx.ID_ANY) - statusbar.SetMinHeight(24) - statusbar.SetFieldsCount(3) - statusbar.SetStatusWidths([-6, -2, -1]) - self.statusbarManager = sb.SbManager(statusbar=statusbar, giface=self._giface, mapDisplayProperties=self._mapWindowProperties) - - # fill statusbar manager - self.statusbarManager.AddStatusbarItemsByClass( - statusbarItems, statusbar=statusbar - ) - self.statusbarManager.AddStatusbarItem( - sb.SbRender(statusbar=statusbar, position=2) - ) - self.statusbarManager.Update() - return statusbar - - def AddStatusbarPane(self): - """Add statusbar as a pane""" - self._mgr.AddPane( - self.statusbar, - wx.aui.AuiPaneInfo() - .Bottom() - .MinSize(30, 30) - .Fixed() - .Name("statusbar") - .CloseButton(False) - .DestroyOnClose(True) - .ToolbarPane() - .Dockable(False) - .PaneBorder(False) - .Gripper(False), - ) - - def SetStatusText(self, *args): - """Overide wx.StatusBar method""" - self.statusbar.SetStatusText(*args) - - def ShowStatusbar(self, show): - """Show/hide statusbar and associated pane""" - self._mgr.GetPane("statusbar").Show(show) - self._mgr.Update() - - def IsStatusbarShown(self): - """Check if statusbar is shown""" - return self._mgr.GetPane("statusbar").IsShown() - - def StatusbarReposition(self): - """Reposition items in statusbar""" - if self.statusbarManager: - self.statusbarManager.Reposition() - - def StatusbarEnableLongHelp(self, enable=True): - """Enable/disable toolbars long help""" - for toolbar in six.itervalues(self.toolbars): - if toolbar: - toolbar.EnableLongHelp(enable) - - def ShowAllToolbars(self, show=True): - if not show: # hide - action = self.RemoveToolbar - else: - action = self.AddToolbar - for toolbar in self.GetToolbarNames(): - action(toolbar) - - def AreAllToolbarsShown(self): - return self.GetMapToolbar().IsShown() - - def GetToolbarNames(self): - """Return toolbar names""" - return list(self.toolbars.keys()) - - def AddToolbar(self): - """Add defined toolbar to the window""" - raise NotImplementedError("AddToolbar") - - def RemoveToolbar(self, name, destroy=False): - """Removes defined toolbar from the window - - :param name toolbar to remove - :param destroy True to destroy otherwise toolbar is only hidden - """ - self._mgr.DetachPane(self.toolbars[name]) - if destroy: - self._toolSwitcher.RemoveToolbarFromGroup("mouseUse", self.toolbars[name]) - self.toolbars[name].Destroy() - self.toolbars.pop(name) - else: - self.toolbars[name].Hide() - - self._mgr.Update() - - def IsPaneShown(self, name): - """Check if pane (toolbar, mapWindow ...) of given name is currently shown""" - if self._mgr.GetPane(name).IsOk(): - return self._mgr.GetPane(name).IsShown() - return False - - def OnRender(self, event): - """Re-render map composition (each map layer)""" - raise NotImplementedError("OnRender") - - def OnDraw(self, event): - """Re-display current map composition""" - self.MapWindow.UpdateMap(render=False) - - def OnErase(self, event): - """Erase the canvas""" - self.MapWindow.EraseMap() - - def OnZoomIn(self, event): - """Zoom in the map.""" - self.MapWindow.SetModeZoomIn() - - def OnZoomOut(self, event): - """Zoom out the map.""" - self.MapWindow.SetModeZoomOut() - - def _setUpMapWindow(self, mapWindow): - """Binds map windows' zoom history signals to map toolbar.""" - # enable or disable zoom history tool - if self.GetMapToolbar(): - mapWindow.zoomHistoryAvailable.connect( - lambda: self.GetMapToolbar().Enable("zoomBack", enable=True) - ) - mapWindow.zoomHistoryUnavailable.connect( - lambda: self.GetMapToolbar().Enable("zoomBack", enable=False) - ) - mapWindow.mouseMoving.connect(self.CoordinatesChanged) - - def OnPointer(self, event): - """Sets mouse mode to pointer.""" - self.MapWindow.SetModePointer() - - def OnPan(self, event): - """Panning, set mouse to drag""" - self.MapWindow.SetModePan() - - def OnZoomBack(self, event): - """Zoom last (previously stored position)""" - self.MapWindow.ZoomBack() - - def OnZoomToMap(self, event): - """ - Set display extents to match selected raster (including NULLs) - or vector map. - """ - self.MapWindow.ZoomToMap(layers=self.Map.GetListOfLayers()) - - def OnZoomToWind(self, event): - """Set display geometry to match computational region - settings (set with g.region) - """ - self.MapWindow.ZoomToWind() - - def OnZoomToDefault(self, event): - """Set display geometry to match default region settings""" - self.MapWindow.ZoomToDefault() - - -class SingleMapPanel(MapPanelBase): - """Panel with one map window. - - It is base class for panels which needs only one map. - - Derived class should have \c self.MapWindow or - it has to override GetWindow() methods. - - @note To access maps use getters only - (when using class or when writing class itself). - """ - - def __init__( - self, - parent=None, - giface=None, - id=wx.ID_ANY, - title="", - Map=None, - auimgr=None, - name="", - **kwargs, - ): - """ - - :param parent: gui parent - :param id: wx id - :param title: window title - :param map: instance of render.Map - :param name: panel name - :param kwargs: arguments passed to MapPanelBase - """ - - MapPanelBase.__init__( - self, - parent=parent, - id=id, - title=title, - auimgr=auimgr, - name=name, - **kwargs, - ) - - self.Map = Map # instance of render.Map - - # - # initialize region values - # - if self.Map: - self._initMap(Map=self.Map) - - def GetMap(self): - """Returns map (renderer) instance""" - return self.Map - - def GetWindow(self): - """Returns map window""" - return self.MapWindow - - def GetWindows(self): - """Returns list of map windows""" - return [self.MapWindow] - - def OnRender(self, event): - """Re-render map composition (each map layer)""" - self.GetWindow().UpdateMap(render=True, renderVector=True) - - # update statusbar - self.StatusbarUpdate() - - -class DoubleMapPanel(MapPanelBase): - """Panel with two map windows. - - It is base class for panels which needs two maps. - There is no primary and secondary map. Both maps are equal. - However, one map is current. - - It is expected that derived class will call _bindWindowsActivation() - when both map windows will be initialized. - - Drived class should have method GetMapToolbar() returns toolbar - which has methods SetActiveMap() and Enable(). - - @note To access maps use getters only - (when using class or when writing class itself). - - .. todo: - Use it in GCP manager (probably changes to both DoubleMapPanel - and GCP MapPanel will be necessary). - """ - - def __init__( - self, - parent=None, - id=wx.ID_ANY, - title=None, - firstMap=None, - secondMap=None, - auimgr=None, - name=None, - **kwargs, - ): - """ - - \a firstMap is set as active (by assign it to \c self.Map). - Derived class should assging to \c self.MapWindow to make one - map window current by dafault. - - :param parent: gui parent - :param id: wx id - :param title: window title - :param name: panel name - :param kwargs: arguments passed to MapPanelBase - """ - - MapPanelBase.__init__( - self, - parent=parent, - id=id, - title=title, - auimgr=auimgr, - name=name, - **kwargs, - ) - - self.firstMap = firstMap - self.secondMap = secondMap - self.Map = firstMap - - # - # initialize region values - # - self._initMap(Map=self.firstMap) - self._initMap(Map=self.secondMap) - self._bindRegions = False - - def _bindWindowsActivation(self): - self.GetFirstWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateFirstMap) - self.GetSecondWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateSecondMap) - - def _onToggleTool(self, id): - if self._toolSwitcher.IsToolInGroup(id, "mouseUse"): - self.GetFirstWindow().UnregisterAllHandlers() - self.GetSecondWindow().UnregisterAllHandlers() - - def GetFirstMap(self): - """Returns first Map instance""" - return self.firstMap - - def GetSecondMap(self): - """Returns second Map instance""" - return self.secondMap - - def GetFirstWindow(self): - """Get first map window""" - return self.firstMapWindow - - def GetSecondWindow(self): - """Get second map window""" - return self.secondMapWindow - - def GetMap(self): - """Returns current map (renderer) instance - - @note Use this method to access current map renderer. - (It is not guarented that current map will be stored in - \c self.Map in future versions.) - """ - return self.Map - - def GetWindow(self): - """Returns current map window - - :func:`GetMap()` - """ - return self.MapWindow - - def GetWindows(self): - """Return list of all windows""" - return [self.firstMapWindow, self.secondMapWindow] - - def ActivateFirstMap(self, event=None): - """Make first Map and MapWindow active and (un)bind regions of the two Maps.""" - if self.MapWindow == self.firstMapWindow: - return - - self.Map = self.firstMap - self.MapWindow = self.firstMapWindow - self.GetMapToolbar().SetActiveMap(0) - - # bind/unbind regions - if self._bindRegions: - self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap) - self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap) - - def ActivateSecondMap(self, event=None): - """Make second Map and MapWindow active and (un)bind regions of the two Maps.""" - if self.MapWindow == self.secondMapWindow: - return - - self.Map = self.secondMap - self.MapWindow = self.secondMapWindow - self.GetMapToolbar().SetActiveMap(1) - - if self._bindRegions: - self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap) - self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap) - - def SetBindRegions(self, on): - """Set or unset binding display regions.""" - self._bindRegions = on - if on: - if self.MapWindow == self.firstMapWindow: - self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap) - else: - self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap) - else: - if self.MapWindow == self.firstMapWindow: - self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap) - else: - self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap) - - def OnZoomChangedFirstMap(self): - """Display region of the first window (Map) changed. - - Synchronize the region of the second map and re-render it. - This is the default implementation which can be overridden. - """ - region = self.GetFirstMap().GetCurrentRegion() - self.GetSecondMap().region.update(region) - self.Render(mapToRender=self.GetSecondWindow()) - - def OnZoomChangedSecondMap(self): - """Display region of the second window (Map) changed. - - Synchronize the region of the second map and re-render it. - This is the default implementation which can be overridden. - """ - region = self.GetSecondMap().GetCurrentRegion() - self.GetFirstMap().region.update(region) - self.Render(mapToRender=self.GetFirstWindow()) - - def OnZoomIn(self, event): - """Zoom in the map.""" - self.GetFirstWindow().SetModeZoomIn() - self.GetSecondWindow().SetModeZoomIn() - - def OnZoomOut(self, event): - """Zoom out the map.""" - self.GetFirstWindow().SetModeZoomOut() - self.GetSecondWindow().SetModeZoomOut() - - def OnPan(self, event): - """Panning, set mouse to pan""" - self.GetFirstWindow().SetModePan() - self.GetSecondWindow().SetModePan() - - def OnPointer(self, event): - """Set pointer mode (dragging overlays)""" - self.GetFirstWindow().SetModePointer() - self.GetSecondWindow().SetModePointer() - - def OnQuery(self, event): - """Set query mode""" - self.GetFirstWindow().SetModeQuery() - self.GetSecondWindow().SetModeQuery() - - def OnRender(self, event): - """Re-render map composition (each map layer)""" - self.Render(mapToRender=self.GetFirstWindow()) - self.Render(mapToRender=self.GetSecondWindow()) - - def Render(self, mapToRender): - """Re-render map composition""" - mapToRender.UpdateMap( - render=True, renderVector=mapToRender == self.GetFirstWindow() - ) - - # update statusbar - self.StatusbarUpdate() - - def OnErase(self, event): - """Erase the canvas""" - self.Erase(mapToErase=self.GetFirstWindow()) - self.Erase(mapToErase=self.GetSecondWindow()) - - def Erase(self, mapToErase): - """Erase the canvas""" - mapToErase.EraseMap() - - def OnDraw(self, event): - """Re-display current map composition""" - self.Draw(mapToDraw=self.GetFirstWindow()) - self.Draw(mapToDraw=self.GetSecondWindow()) - - def Draw(self, mapToDraw): - """Re-display current map composition""" - mapToDraw.UpdateMap(render=False) - - -class FrameMixin: - """Mixin class for wx.Panel that provides methods standardly - used on wx.Frame widget""" - - def Show(self): - self.GetParent().Show() - - def SetTitle(self, name): - self.GetParent().SetTitle(name) - - def Raise(self): - self.GetParent().Raise() - - def SetFocus(self): - self.GetParent().SetFocus() - - def CenterOnScreen(self): - self.GetParent().CenterOnScreen() - - def CentreOnScreen(self): - self.GetParent().CentreOnScreen() - - def IsFullScreen(self): - return self.GetParent().IsFullScreen() - - def IsIconized(self): - self.GetParent().IsIconized() - - def Maximize(self): - self.GetParent().Maximize() - - def ShowFullScreen(self, show): - for toolbar in self.toolbars.keys(): - self._mgr.GetPane(self.toolbars[toolbar]).Show(self.IsFullScreen()) - if self.statusbar: - self._mgr.GetPane("statusbar").Show(self.IsFullScreen()) - self._mgr.Update() - - self.GetParent().ShowFullScreen(show) - - def OnFullScreen(self, event): - """!Switches frame to fullscreen mode, hides toolbars and statusbar""" - self.ShowFullScreen(not self.IsFullScreen()) - event.Skip() - - def BindToFrame(self, *args): - self.GetParent().Bind(*args) - - def Destroy(self): - self.GetParent().Destroy() diff --git a/gui/wxpython/mapdisp/refactoringPR/mapdisp_guicore.py b/gui/wxpython/mapdisp/refactoringPR/mapdisp_guicore.py deleted file mode 100644 index 1b9f05ee778..00000000000 --- a/gui/wxpython/mapdisp/refactoringPR/mapdisp_guicore.py +++ /dev/null @@ -1,838 +0,0 @@ -""" -@package gui_core.mapdisp - -@brief Base classes for Map display window - -Classes: - - mapdisp::MapPanelBase - - mapdisp::SingleMapPanel - - mapdisp::DoubleMapPanel - -(C) 2009-2014 by the GRASS Development Team - -This program is free software under the GNU General Public License -(>=v2). Read the file COPYING that comes with GRASS for details. - -@author Martin Landa -@author Michael Barton -@author Vaclav Petras -@author Anna Kratochvilova -""" - -import sys -import six - -import wx - -from core.debug import Debug -from gui_core.toolbars import ToolSwitcher -from gui_core.wrap import NewId -from mapdisp import statusbar as sb - -from grass.script import core as grass - - -class MapPanelBase(wx.Panel): - """Base class for map display window - - Derived class must use (create and initialize) \c statusbarManager - or override - GetProperty(), SetProperty() and HasProperty() methods. - - Several methods has to be overridden or - \c NotImplementedError("MethodName") will be raised. - - If derived class enables and disables auto-rendering, - it should override IsAutoRendered method. - - It is expected that derived class will call _setUpMapWindow(). - - Derived class can has one or more map windows (and map renders) - but implementation of MapPanelBase expects that one window and - one map will be current. - Current instances of map window and map renderer should be returned - by methods GetWindow() and GetMap() respectively. - - AUI manager is stored in \c self._mgr. - """ - - def __init__( - self, - parent=None, - id=wx.ID_ANY, - title="", - auimgr=None, - name="", - **kwargs, - ): - """ - - .. warning:: - Use \a auimgr parameter only if you know what you are doing. - - :param parent: gui parent - :param id: wx id - :param title: window title - :param toolbars: array of activated toolbars, e.g. ['map', 'digit'] - :param auimgr: AUI manager (if \c None, wx.aui.AuiManager is used) - :param name: panel name - :param kwargs: arguments passed to \c wx.Panel - """ - - self.parent = parent - - wx.Panel.__init__(self, parent, id, name=name, **kwargs) - - # toolbars - self.toolbars = {} - self.iconsize = (16, 16) - - # - # Fancy gui - # - if auimgr is None: - from wx.aui import AuiManager - - self._mgr = AuiManager(self) - else: - self._mgr = auimgr - - # handles switching between tools in different toolbars - self._toolSwitcher = ToolSwitcher() - self._toolSwitcher.toggleToolChanged.connect(self._onToggleTool) - - # set accelerator table - self.shortcuts_table = [ - (self.OnCloseWindow, wx.ACCEL_CTRL, ord("W")), - (self.OnRender, wx.ACCEL_CTRL, ord("R")), - (self.OnRender, wx.ACCEL_NORMAL, wx.WXK_F5), - ] - - self._initShortcuts() - - def _initShortcuts(self): - """init shortcuts to acceleration table""" - accelTable = [] - for handler, entry, kdb in self.shortcuts_table: - wxId = NewId() - self.Bind(wx.EVT_MENU, handler, id=wxId) - accelTable.append((entry, kdb, wxId)) - self.SetAcceleratorTable(wx.AcceleratorTable(accelTable)) - - def _initMap(self, Map): - """Initialize map display, set dimensions and map region""" - if not grass.find_program("g.region", "--help"): - sys.exit( - _("GRASS module '%s' not found. Unable to start map " "display window.") - % "g.region" - ) - - Debug.msg(2, "MapPanel._initMap():") - Map.ChangeMapSize(self.GetClientSize()) - Map.region = Map.GetRegion() # g.region -upgc - # self.Map.SetRegion() # adjust region to match display window - - def _resize(self): - Debug.msg(1, "MapPanel_resize():") - wm, hw = self.MapWindow.GetClientSize() - wf, hf = self.GetSize() - dw = wf - wm - dh = hf - hw - self.SetSize((wf + dw, hf + dh)) - - def _onToggleTool(self, id): - if self._toolSwitcher.IsToolInGroup(id, "mouseUse"): - self.GetWindow().UnregisterAllHandlers() - - def OnSize(self, event): - """Adjust statusbar on changing size""" - # reposition checkbox in statusbar - self.StatusbarReposition() - - # update statusbar - self.StatusbarUpdate() - - def OnCloseWindow(self, event): - self.Destroy() - - def GetToolSwitcher(self): - return self._toolSwitcher - - def SetProperty(self, name, value): - """Sets property""" - if self.HasProperty("projection"): - self.statusbarManager.SetProperty(name, value) - else: - self.mapWindowProperties.useDefinedProjection = value - - def GetProperty(self, name): - """Returns property""" - if self.HasProperty("projection"): - return self.statusbarManager.GetProperty(name) - else: - return self.mapWindowProperties.useDefinedProjection - - def HasProperty(self, name): - """Checks whether object has property""" - return self.statusbarManager.HasProperty(name) - - def GetPPM(self): - """Get pixel per meter - - .. todo:: - now computed every time, is it necessary? - - .. todo:: - enable user to specify ppm (and store it in UserSettings) - """ - # TODO: need to be fixed... - # screen X region problem - # user should specify ppm - dc = wx.ScreenDC() - dpSizePx = wx.DisplaySize() # display size in pixels - dpSizeMM = wx.DisplaySizeMM() # display size in mm (system) - dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4) # inches - sysPpi = dc.GetPPI() - comPpi = (dpSizePx[0] / dpSizeIn[0], dpSizePx[1] / dpSizeIn[1]) - - ppi = comPpi # pixel per inch - ppm = ((ppi[0] / 2.54) * 100, (ppi[1] / 2.54) * 100) # pixel per meter - - Debug.msg( - 4, - "MapPanelBase.GetPPM(): size: px=%d,%d mm=%f,%f " - "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" - % ( - dpSizePx[0], - dpSizePx[1], - dpSizeMM[0], - dpSizeMM[1], - dpSizeIn[0], - dpSizeIn[1], - sysPpi[0], - sysPpi[1], - comPpi[0], - comPpi[1], - ppm[0], - ppm[1], - ), - ) - - return ppm - - def SetMapScale(self, value, map=None): - """Set current map scale - - :param value: scale value (n if scale is 1:n) - :param map: Map instance (if none self.Map is used) - """ - if not map: - map = self.Map - - region = self.Map.region - dEW = value * (region["cols"] / self.GetPPM()[0]) - dNS = value * (region["rows"] / self.GetPPM()[1]) - region["n"] = region["center_northing"] + dNS / 2.0 - region["s"] = region["center_northing"] - dNS / 2.0 - region["w"] = region["center_easting"] - dEW / 2.0 - region["e"] = region["center_easting"] + dEW / 2.0 - - # add to zoom history - self.GetWindow().ZoomHistory(region["n"], region["s"], region["e"], region["w"]) - - def GetMapScale(self, map=None): - """Get current map scale - - :param map: Map instance (if none self.Map is used) - """ - if not map: - map = self.GetMap() - - region = map.region - ppm = self.GetPPM() - - heightCm = region["rows"] / ppm[1] * 100 - widthCm = region["cols"] / ppm[0] * 100 - - Debug.msg( - 4, "MapPanel.GetMapScale(): width_cm=%f, height_cm=%f" % (widthCm, heightCm) - ) - - xscale = (region["e"] - region["w"]) / (region["cols"] / ppm[0]) - yscale = (region["n"] - region["s"]) / (region["rows"] / ppm[1]) - scale = (xscale + yscale) / 2.0 - - Debug.msg( - 3, - "MapPanel.GetMapScale(): xscale=%f, yscale=%f -> scale=%f" - % (xscale, yscale, scale), - ) - - return scale - - def GetProgressBar(self): - """Returns progress bar - - Progress bar can be used by other classes. - """ - return self.statusbarManager.GetProgressBar() - - def GetMap(self): - """Returns current map (renderer) instance""" - raise NotImplementedError("GetMap") - - def GetWindow(self): - """Returns current map window""" - raise NotImplementedError("GetWindow") - - def GetWindows(self): - """Returns list of map windows""" - raise NotImplementedError("GetWindows") - - def GetMapToolbar(self): - """Returns toolbar with zooming tools""" - raise NotImplementedError("GetMapToolbar") - - def GetToolbar(self, name): - """Returns toolbar if exists and is active, else None.""" - if name in self.toolbars and self.toolbars[name].IsShown(): - return self.toolbars[name] - - return None - - def StatusbarUpdate(self): - """Update statusbar content""" - if self.statusbarManager: - Debug.msg(5, "MapPanelBase.StatusbarUpdate()") - self.statusbarManager.Update() - - def IsAutoRendered(self): - """Check if auto-rendering is enabled""" - # TODO: this is now not the right place to access this attribute - # TODO: add mapWindowProperties to init parameters - # and pass the right object in the init of derived class? - # or do not use this method at all, let mapwindow decide - return self.mapWindowProperties.autoRender - - def CoordinatesChanged(self): - """Shows current coordinates on statusbar.""" - # assuming that the first mode is coordinates - # probably shold not be here but good solution is not available now - if self.statusbarManager: - if self.statusbarManager.GetMode() == 0: - self.statusbarManager.ShowItem("coordinates") - - def CreateStatusbar(self, statusbarItems): - """Create statusbar (default items).""" - # create statusbar and its manager - statusbar = wx.StatusBar(self, id=wx.ID_ANY) - statusbar.SetMinHeight(24) - statusbar.SetFieldsCount(3) - statusbar.SetStatusWidths([-6, -2, -1]) - self.statusbarManager = sb.SbManager(statusbar=statusbar, giface=self._giface, mapDisplayProperties=self._mapWindowProperties) - - # fill statusbar manager - self.statusbarManager.AddStatusbarItemsByClass( - statusbarItems, statusbar=statusbar - ) - self.statusbarManager.AddStatusbarItem( - sb.SbRender(statusbar=statusbar, position=2) - ) - self.statusbarManager.Update() - return statusbar - - def AddStatusbarPane(self): - """Add statusbar as a pane""" - self._mgr.AddPane( - self.statusbar, - wx.aui.AuiPaneInfo() - .Bottom() - .MinSize(30, 30) - .Fixed() - .Name("statusbar") - .CloseButton(False) - .DestroyOnClose(True) - .ToolbarPane() - .Dockable(False) - .PaneBorder(False) - .Gripper(False), - ) - - def SetStatusText(self, *args): - """Overide wx.StatusBar method""" - self.statusbar.SetStatusText(*args) - - def ShowStatusbar(self, show): - """Show/hide statusbar and associated pane""" - self._mgr.GetPane("statusbar").Show(show) - self._mgr.Update() - - def IsStatusbarShown(self): - """Check if statusbar is shown""" - return self._mgr.GetPane("statusbar").IsShown() - - def StatusbarReposition(self): - """Reposition items in statusbar""" - if self.statusbarManager: - self.statusbarManager.Reposition() - - def StatusbarEnableLongHelp(self, enable=True): - """Enable/disable toolbars long help""" - for toolbar in six.itervalues(self.toolbars): - if toolbar: - toolbar.EnableLongHelp(enable) - - def ShowAllToolbars(self, show=True): - if not show: # hide - action = self.RemoveToolbar - else: - action = self.AddToolbar - for toolbar in self.GetToolbarNames(): - action(toolbar) - - def AreAllToolbarsShown(self): - return self.GetMapToolbar().IsShown() - - def GetToolbarNames(self): - """Return toolbar names""" - return list(self.toolbars.keys()) - - def AddToolbar(self): - """Add defined toolbar to the window""" - raise NotImplementedError("AddToolbar") - - def RemoveToolbar(self, name, destroy=False): - """Removes defined toolbar from the window - - :param name toolbar to remove - :param destroy True to destroy otherwise toolbar is only hidden - """ - self._mgr.DetachPane(self.toolbars[name]) - if destroy: - self._toolSwitcher.RemoveToolbarFromGroup("mouseUse", self.toolbars[name]) - self.toolbars[name].Destroy() - self.toolbars.pop(name) - else: - self.toolbars[name].Hide() - - self._mgr.Update() - - def IsPaneShown(self, name): - """Check if pane (toolbar, mapWindow ...) of given name is currently shown""" - if self._mgr.GetPane(name).IsOk(): - return self._mgr.GetPane(name).IsShown() - return False - - def OnRender(self, event): - """Re-render map composition (each map layer)""" - raise NotImplementedError("OnRender") - - def OnDraw(self, event): - """Re-display current map composition""" - self.MapWindow.UpdateMap(render=False) - - def OnErase(self, event): - """Erase the canvas""" - self.MapWindow.EraseMap() - - def OnZoomIn(self, event): - """Zoom in the map.""" - self.MapWindow.SetModeZoomIn() - - def OnZoomOut(self, event): - """Zoom out the map.""" - self.MapWindow.SetModeZoomOut() - - def _setUpMapWindow(self, mapWindow): - """Binds map windows' zoom history signals to map toolbar.""" - # enable or disable zoom history tool - if self.GetMapToolbar(): - mapWindow.zoomHistoryAvailable.connect( - lambda: self.GetMapToolbar().Enable("zoomBack", enable=True) - ) - mapWindow.zoomHistoryUnavailable.connect( - lambda: self.GetMapToolbar().Enable("zoomBack", enable=False) - ) - mapWindow.mouseMoving.connect(self.CoordinatesChanged) - - def OnPointer(self, event): - """Sets mouse mode to pointer.""" - self.MapWindow.SetModePointer() - - def OnPan(self, event): - """Panning, set mouse to drag""" - self.MapWindow.SetModePan() - - def OnZoomBack(self, event): - """Zoom last (previously stored position)""" - self.MapWindow.ZoomBack() - - def OnZoomToMap(self, event): - """ - Set display extents to match selected raster (including NULLs) - or vector map. - """ - self.MapWindow.ZoomToMap(layers=self.Map.GetListOfLayers()) - - def OnZoomToWind(self, event): - """Set display geometry to match computational region - settings (set with g.region) - """ - self.MapWindow.ZoomToWind() - - def OnZoomToDefault(self, event): - """Set display geometry to match default region settings""" - self.MapWindow.ZoomToDefault() - - -class SingleMapPanel(MapPanelBase): - """Panel with one map window. - - It is base class for panels which needs only one map. - - Derived class should have \c self.MapWindow or - it has to override GetWindow() methods. - - @note To access maps use getters only - (when using class or when writing class itself). - """ - - def __init__( - self, - parent=None, - giface=None, - id=wx.ID_ANY, - title="", - Map=None, - auimgr=None, - name="", - **kwargs, - ): - """ - - :param parent: gui parent - :param id: wx id - :param title: window title - :param map: instance of render.Map - :param name: panel name - :param kwargs: arguments passed to MapPanelBase - """ - - MapPanelBase.__init__( - self, - parent=parent, - id=id, - title=title, - auimgr=auimgr, - name=name, - **kwargs, - ) - - self.Map = Map # instance of render.Map - - # - # initialize region values - # - if self.Map: - self._initMap(Map=self.Map) - - def GetMap(self): - """Returns map (renderer) instance""" - return self.Map - - def GetWindow(self): - """Returns map window""" - return self.MapWindow - - def GetWindows(self): - """Returns list of map windows""" - return [self.MapWindow] - - def OnRender(self, event): - """Re-render map composition (each map layer)""" - self.GetWindow().UpdateMap(render=True, renderVector=True) - - # update statusbar - self.StatusbarUpdate() - - -class DoubleMapPanel(MapPanelBase): - """Panel with two map windows. - - It is base class for panels which needs two maps. - There is no primary and secondary map. Both maps are equal. - However, one map is current. - - It is expected that derived class will call _bindWindowsActivation() - when both map windows will be initialized. - - Drived class should have method GetMapToolbar() returns toolbar - which has methods SetActiveMap() and Enable(). - - @note To access maps use getters only - (when using class or when writing class itself). - - .. todo: - Use it in GCP manager (probably changes to both DoubleMapPanel - and GCP MapPanel will be necessary). - """ - - def __init__( - self, - parent=None, - id=wx.ID_ANY, - title=None, - firstMap=None, - secondMap=None, - auimgr=None, - name=None, - **kwargs, - ): - """ - - \a firstMap is set as active (by assign it to \c self.Map). - Derived class should assging to \c self.MapWindow to make one - map window current by dafault. - - :param parent: gui parent - :param id: wx id - :param title: window title - :param name: panel name - :param kwargs: arguments passed to MapPanelBase - """ - - MapPanelBase.__init__( - self, - parent=parent, - id=id, - title=title, - auimgr=auimgr, - name=name, - **kwargs, - ) - - self.firstMap = firstMap - self.secondMap = secondMap - self.Map = firstMap - - # - # initialize region values - # - self._initMap(Map=self.firstMap) - self._initMap(Map=self.secondMap) - self._bindRegions = False - - def _bindWindowsActivation(self): - self.GetFirstWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateFirstMap) - self.GetSecondWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateSecondMap) - - def _onToggleTool(self, id): - if self._toolSwitcher.IsToolInGroup(id, "mouseUse"): - self.GetFirstWindow().UnregisterAllHandlers() - self.GetSecondWindow().UnregisterAllHandlers() - - def GetFirstMap(self): - """Returns first Map instance""" - return self.firstMap - - def GetSecondMap(self): - """Returns second Map instance""" - return self.secondMap - - def GetFirstWindow(self): - """Get first map window""" - return self.firstMapWindow - - def GetSecondWindow(self): - """Get second map window""" - return self.secondMapWindow - - def GetMap(self): - """Returns current map (renderer) instance - - @note Use this method to access current map renderer. - (It is not guarented that current map will be stored in - \c self.Map in future versions.) - """ - return self.Map - - def GetWindow(self): - """Returns current map window - - :func:`GetMap()` - """ - return self.MapWindow - - def GetWindows(self): - """Return list of all windows""" - return [self.firstMapWindow, self.secondMapWindow] - - def ActivateFirstMap(self, event=None): - """Make first Map and MapWindow active and (un)bind regions of the two Maps.""" - if self.MapWindow == self.firstMapWindow: - return - - self.Map = self.firstMap - self.MapWindow = self.firstMapWindow - self.GetMapToolbar().SetActiveMap(0) - - # bind/unbind regions - if self._bindRegions: - self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap) - self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap) - - def ActivateSecondMap(self, event=None): - """Make second Map and MapWindow active and (un)bind regions of the two Maps.""" - if self.MapWindow == self.secondMapWindow: - return - - self.Map = self.secondMap - self.MapWindow = self.secondMapWindow - self.GetMapToolbar().SetActiveMap(1) - - if self._bindRegions: - self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap) - self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap) - - def SetBindRegions(self, on): - """Set or unset binding display regions.""" - self._bindRegions = on - if on: - if self.MapWindow == self.firstMapWindow: - self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap) - else: - self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap) - else: - if self.MapWindow == self.firstMapWindow: - self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap) - else: - self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap) - - def OnZoomChangedFirstMap(self): - """Display region of the first window (Map) changed. - - Synchronize the region of the second map and re-render it. - This is the default implementation which can be overridden. - """ - region = self.GetFirstMap().GetCurrentRegion() - self.GetSecondMap().region.update(region) - self.Render(mapToRender=self.GetSecondWindow()) - - def OnZoomChangedSecondMap(self): - """Display region of the second window (Map) changed. - - Synchronize the region of the second map and re-render it. - This is the default implementation which can be overridden. - """ - region = self.GetSecondMap().GetCurrentRegion() - self.GetFirstMap().region.update(region) - self.Render(mapToRender=self.GetFirstWindow()) - - def OnZoomIn(self, event): - """Zoom in the map.""" - self.GetFirstWindow().SetModeZoomIn() - self.GetSecondWindow().SetModeZoomIn() - - def OnZoomOut(self, event): - """Zoom out the map.""" - self.GetFirstWindow().SetModeZoomOut() - self.GetSecondWindow().SetModeZoomOut() - - def OnPan(self, event): - """Panning, set mouse to pan""" - self.GetFirstWindow().SetModePan() - self.GetSecondWindow().SetModePan() - - def OnPointer(self, event): - """Set pointer mode (dragging overlays)""" - self.GetFirstWindow().SetModePointer() - self.GetSecondWindow().SetModePointer() - - def OnQuery(self, event): - """Set query mode""" - self.GetFirstWindow().SetModeQuery() - self.GetSecondWindow().SetModeQuery() - - def OnRender(self, event): - """Re-render map composition (each map layer)""" - self.Render(mapToRender=self.GetFirstWindow()) - self.Render(mapToRender=self.GetSecondWindow()) - - def Render(self, mapToRender): - """Re-render map composition""" - mapToRender.UpdateMap( - render=True, renderVector=mapToRender == self.GetFirstWindow() - ) - - # update statusbar - self.StatusbarUpdate() - - def OnErase(self, event): - """Erase the canvas""" - self.Erase(mapToErase=self.GetFirstWindow()) - self.Erase(mapToErase=self.GetSecondWindow()) - - def Erase(self, mapToErase): - """Erase the canvas""" - mapToErase.EraseMap() - - def OnDraw(self, event): - """Re-display current map composition""" - self.Draw(mapToDraw=self.GetFirstWindow()) - self.Draw(mapToDraw=self.GetSecondWindow()) - - def Draw(self, mapToDraw): - """Re-display current map composition""" - mapToDraw.UpdateMap(render=False) - - -class FrameMixin: - """Mixin class for wx.Panel that provides methods standardly - used on wx.Frame widget""" - - def Show(self): - self.GetParent().Show() - - def SetTitle(self, name): - self.GetParent().SetTitle(name) - - def Raise(self): - self.GetParent().Raise() - - def SetFocus(self): - self.GetParent().SetFocus() - - def CenterOnScreen(self): - self.GetParent().CenterOnScreen() - - def CentreOnScreen(self): - self.GetParent().CentreOnScreen() - - def IsFullScreen(self): - return self.GetParent().IsFullScreen() - - def IsIconized(self): - self.GetParent().IsIconized() - - def Maximize(self): - self.GetParent().Maximize() - - def ShowFullScreen(self, show): - for toolbar in self.toolbars.keys(): - self._mgr.GetPane(self.toolbars[toolbar]).Show(self.IsFullScreen()) - if self.statusbar: - self._mgr.GetPane("statusbar").Show(self.IsFullScreen()) - self._mgr.Update() - - self.GetParent().ShowFullScreen(show) - - def OnFullScreen(self, event): - """!Switches frame to fullscreen mode, hides toolbars and statusbar""" - self.ShowFullScreen(not self.IsFullScreen()) - event.Skip() - - def BindToFrame(self, *args): - self.GetParent().Bind(*args) - - def Destroy(self): - self.GetParent().Destroy() diff --git a/gui/wxpython/mapdisp/statusbar_new.py b/gui/wxpython/mapdisp/statusbar_new.py deleted file mode 100644 index b797f1eb096..00000000000 --- a/gui/wxpython/mapdisp/statusbar_new.py +++ /dev/null @@ -1,745 +0,0 @@ -""" -@package frame.statusbar - -@brief Classes for main window statusbar management - -Classes: - - statusbar::SbMapDisplay - - statusbar::SbException - - statusbar::SbItem - - statusbar::SbTextItem - - statusbar::SbCoordinates - -(C) 2022 by the GRASS Development Team - -This program is free software under the GNU General Public License -(>=v2). Read the file COPYING that comes with GRASS for details. - -@author Linda Kladivova -@author Anna Petrasova -@author Vaclav Petras -""" - -import wx - -from core import utils -from mapdisp.properties import ChBRender - - -class SbMapDisplay: - """Statusbar for map display window.""" - - def __init__(self, parent, giface): - self.parent = parent - self.giface = giface - self.statusbar = wx.StatusBar(self.parent, id=wx.ID_ANY) - self.statusbar.SetMinHeight(24) - self.statusbar.SetFieldsCount(3) - self.statusbar.SetStatusWidths([200, -1, 100]) - self._init_items() - self.statusbar.Bind(wx.EVT_SIZE, self.OnSize) - - self._repositionStatusbar() - - def _init_items(self): - """"Init all items that can be shown in statusbar.""" - self.coordinates = SbCoordinates(self.widget, self.giface) - self.render = ChBRender(self.widget, self.properties) - - def GetStatusbar(self): - return self.statusbar - - def _repositionStatusbar(self): - """Reposition widgets in main window statusbar""" - rect1 = self.GetStatusbar().GetFieldRect(1) - rect1.x += 1 - rect1.y += 1 - self.coordinates.GetItem().SetRect(rect1) - rect1.x += 1 - rect1.y += 1 - self.render.GetItem().SetRect(rect1) - - def OnSize(self, event): - """Adjust main window statusbar on changing size""" - self._repositionStatusbar() - - def SetStatusText(self, *args): - """Overide wx.StatusBar method""" - self.GetStatusbar().SetStatusText(*args) - - -class SbException(Exception): - """Exception class used in SbMapDisplay and SbItems""" - - def __init__(self, message): - self.message = message - - def __str__(self): - return self.message - - -class SbItem: - """Base class for statusbar items.""" - - def __init__(self, statusbar): - self.statusbar = statusbar - - def Show(self): - """Invokes showing of underlying item. - - In derived classes it can do what is appropriate for it, - e.g. showing text on statusbar (only). - """ - self.item.Show() - - def Hide(self): - self.item.Hide() - - def SetValue(self, value): - self.item.SetValue(value) - - def GetValue(self): - return self.item.GetValue() - - def GetItem(self): - """Returns underlying widget. - - :return: widget or None if doesn't exist - """ - return self.item - - def _update(self): - """Default implementation for Update method. - - :param longHelp: True to enable long help (help from toolbars) - """ - self.statusbar.SetStatusText("", 0) - self.Show() - - -class SbTextItem(SbItem): - """Base class for items without widgets. - - Only sets statusbar text. - """ - - def __init__(self, statusbar): - SbItem.__init__(self, statusbar) - - self.text = None - - def Show(self): - self.statusbar.SetStatusText(self.GetValue()) - - def Hide(self): - self.statusbar.SetStatusText("") - - def SetValue(self, value): - self.text = value - - def GetValue(self): - return self.text - - def GetWidget(self): - return None - - -class SbCoordinates(SbTextItem): - """Show map coordinates when mouse moves. - - Requires MapWindow.GetLastEN method.""" - - def __init__(self, statusbar, giface, mapDisplayProperties): - SbTextItem.__init__(self, statusbar) - self.name = "coordinates" - self.label = _("Coordinates") - self._properties = mapDisplayProperties - self._additionalInfo = None - self._basicValue = None - - def Show(self): - """Show the last map window coordinates. - - .. todo:: - remove last EN call and use coordinates coming from signal - """ - try: - e, n = self.giface.GetMapWindow().GetLastEN() - self._basicValue = self.ReprojectENFromMap(e, n) - if self._additionalInfo: - value = _("{coords} ({additionalInfo})").format( - coords=self._basicValue, additionalInfo=self._additionalInfo - ) - else: - value = self._basicValue - self.SetValue(value) - except SbException as e: - self.SetValue(e.message) - except TypeError: - self.SetValue("") - except AttributeError: - self.SetValue("") - SbTextItem.Show(self) - - def SetAdditionalInfo(self, text): - """Sets additional info to be shown together with coordinates. - - The format is translation dependent but the default is - "coordinates (additional info)" - - It does not show the changed text immediately, it waits for the Show() - method to be called. - - :param text: string to be shown - """ - self._additionalInfo = text - - def ReprojectENFromMap(self, e, n): - """Reproject east, north to user defined projection. - - :param e,n: coordinate - - @throws SbException if useDefinedProjection is True and projection is not defined in UserSettings - """ - useDefinedProjection = self._properties.useDefinedProjection - projectionSettings = self._properties.projectionSettings - - if useDefinedProjection: - if projectionSettings["proj4"]: - raise SbException(_("Projection not defined (check the settings)")) - else: - # reproject values - proj, coord = utils.ReprojectCoordinates( - coord=(e, n), projOut=projectionSettings["proj4"], flags="d" - ) - if coord: - e, n = coord - if proj in ("ll", "latlong", "longlat") and projectionSettings["format"] == "DMS": - return utils.Deg2DMS(e, n, precision=projectionSettings["precision"]) - else: - return "%.*f; %.*f" % (projectionSettings["precision"], e, projectionSettings["precision"], n) - else: - raise SbException(_("Error in projection (check the settings)")) - else: - if self.giface.GetMapDisplay().GetMap().projinfo["proj"] == "ll" and projectionSettings["format"] == "DMS": - return utils.Deg2DMS(e, n, precision=projectionSettings["precision"]) - else: - return "%.*f; %.*f" % (projectionSettings["precision"], e, projectionSettings["precision"], n) - - -#class SbProgress(SbItem): -# """General progress bar to show progress. -# -# Underlaying widget is wx.Gauge. -# """ -# -# def __init__(self, mapframe, statusbar, sbManager, position=0): -# self.progressShown = Signal("SbProgress.progressShown") -# self.progressHidden = Signal("SbProgress.progressHidden") -# SbItem.__init__(self, mapframe, statusbar, position) -# self.name = "progress" -# self.sbManager = sbManager -# # on-render gauge -# self.widget = wx.Gauge( -# parent=self.statusbar, id=wx.ID_ANY, range=0, style=wx.GA_HORIZONTAL -# ) -# self.Hide() -# -# self.progressShown.connect(self._progressShown) -# self.progressHidden.connect(self._progressHidden) -# -# def GetRange(self): -# """Returns progress range.""" -# return self.widget.GetRange() -# -# def SetRange(self, range): -# """Sets progress range.""" -# if range > 0: -# if self.GetRange() != range: -# self.widget.SetRange(range) -# self.Show() -# else: -# self.Hide() -# -# def Show(self): -# if not self.IsShown(): -# self.progressShown.emit() -# self.widget.Show() -# -# def Hide(self): -# if self.IsShown(): -# self.progressHidden.emit() -# self.widget.Hide() -# -# def IsShown(self): -# """Is progress bar shown""" -# return self.widget.IsShown() -# -# def SetValue(self, value): -# """Sets value of progressbar.""" -# if value > self.GetRange(): -# self.Hide() -# return -# -# self.widget.SetValue(value) -# if value == self.GetRange(): -# self.Hide() -# -# def GetWidget(self): -# """Returns underlaying winget. -# -# :return: widget or None if doesn't exist -# """ -# return self.widget -# -# def Update(self): -# pass -# -# def GetProgressBar(self): -# """Returns progress bar""" -# return self.progressbar -# -# def _progressShown(self): -# self._oldStatus = self.statusbar.GetStatusText(0) -# self.choice.GetClientData(self.choice.GetSelection()).Hide() -# -# def _progressHidden(self): -# self.statusbar.SetStatusText(self._oldStatus, 0) -# self.choice.GetClientData(self.choice.GetSelection()).Show() -# -# def SetProgress(self, range, value, text): -# """Update progress.""" -# self.progressbar.SetRange(range) -# self.progressbar.SetValue(value) -# if text: -# self.statusbar.SetStatusText(text) -# - - - - -#class SbMapScale(SbItem): -# """Editable combobox to get/set current map scale.""" -# -# def __init__(self, parent, mapWindowProperties, giface): -# SbItem.__init__(self, mapWindowProperties) -# self.name = "mapscale" -# self.widget = wx.ComboBox( -# parent=parent, -# id=wx.ID_ANY, -# label = _("Map scale"), -# style=wx.TE_PROCESS_ENTER, -# size=(150, -1), -# ) -# self.widget.SetItems( -# [ -# "1:1000", -# "1:5000", -# "1:10000", -# "1:25000", -# "1:50000", -# "1:100000", -# "1:1000000", -# ] -# ) -# self.widget.SetToolTip( -# wx.ToolTip( -# _( -# "As everyone's monitors and resolutions " -# "are set differently these values are not " -# "true map scales, but should get you into " -# "the right neighborhood." -# ) -# ) -# ) -# -# self.widget.Bind(wx.EVT_TEXT_ENTER, self.OnChangeMapScale) -# self.widget.Bind(wx.EVT_COMBOBOX, self.OnChangeMapScale) -# -# self.lastMapScale = None -# -# def Update(self): -# scale = self._properties.mapScale -# self.parent.SetStatusText("") -# try: -# self.SetValue("1:%ld" % (scale + 0.5)) -# except TypeError: -# pass # FIXME, why this should happen? -# -# self.lastMapScale = scale -# -# -# def OnChangeMapScale(self, event): -# """Map scale changed by user""" -# scale = event.GetString() -# -# try: -# if scale[:2] != "1:": -# raise ValueError -# value = int(scale[2:]) -# except ValueError: -# self.SetValue("1:%ld" % int(self._properties.mapScale)) -# return -# -# self._properties.mapScale = value -# -# # redraw map if auto-rendering is enabled -# if self._properties.autoRender: -# self.giface.updateMap.emit() - - -#class SbGoTo(SbItem): -# """Textctrl to set coordinates which to focus on. -# -# Requires MapFrame.GetWindow, MapWindow.GoTo method. -# """ -# -# def __init__(self, mapframe, statusbar, position=0): -# SbItem.__init__(self, mapframe, statusbar, position) -# self.name = "goto" -# self.label = _("Go to") -# -# self.widget = TextCtrl( -# parent=self.statusbar, -# id=wx.ID_ANY, -# value="", -# style=wx.TE_PROCESS_ENTER, -# size=(300, -1), -# ) -# -# self.widget.Hide() -# -# self.widget.Bind(wx.EVT_TEXT_ENTER, self.OnGoTo) -# -# def ReprojectENToMap(self, e, n, useDefinedProjection): -# """Reproject east, north from user defined projection -# -# :param e,n: coordinate (for DMS string, else float or string) -# :param useDefinedProjection: projection defined by user in settings dialog -# -# @throws SbException if useDefinedProjection is True and projection is not defined in UserSettings -# """ -# if useDefinedProjection: -# settings = UserSettings.Get( -# group="projection", key="statusbar", subkey="proj4" -# ) -# if not settings: -# raise SbException(_("Projection not defined (check the settings)")) -# else: -# # reproject values -# projIn = settings -# projOut = RunCommand("g.proj", flags="jf", read=True) -# proj = projIn.split(" ")[0].split("=")[1] -# if proj in ("ll", "latlong", "longlat"): -# e, n = utils.DMS2Deg(e, n) -# proj, coord1 = utils.ReprojectCoordinates( -# coord=(e, n), projIn=projIn, projOut=projOut, flags="d" -# ) -# e, n = coord1 -# else: -# e, n = float(e), float(n) -# proj, coord1 = utils.ReprojectCoordinates( -# coord=(e, n), projIn=projIn, projOut=projOut, flags="d" -# ) -# e, n = coord1 -# elif self.mapFrame.GetMap().projinfo["proj"] == "ll": -# e, n = utils.DMS2Deg(e, n) -# else: -# e, n = float(e), float(n) -# return e, n -# -# def OnGoTo(self, event): -# """Go to position""" -# try: -# e, n = self.GetValue().split(";") -# e, n = self.ReprojectENToMap(e, n, self.mapFrame.GetProperty("projection")) -# self.mapFrame.GetWindow().GoTo(e, n) -# self.widget.SetFocus() -# except ValueError: -# # FIXME: move this code to MapWindow/BufferedWindow/MapFrame -# region = self.mapFrame.GetMap().GetCurrentRegion() -# precision = int( -# UserSettings.Get(group="projection", key="format", subkey="precision") -# ) -# format = UserSettings.Get(group="projection", key="format", subkey="ll") -# if self.mapFrame.GetMap().projinfo["proj"] == "ll" and format == "DMS": -# self.SetValue( -# "%s" -# % utils.Deg2DMS( -# region["center_easting"], -# region["center_northing"], -# precision=precision, -# ) -# ) -# else: -# self.SetValue( -# "%.*f; %.*f" -# % ( -# precision, -# region["center_easting"], -# precision, -# region["center_northing"], -# ) -# ) -# except SbException as e: -# # FIXME: this may be useless since statusbar update checks user -# # defined projection and this exception raises when user def proj -# # does not exists -# self.statusbar.SetStatusText(str(e), 0) -# -# def GetCenterString(self, map): -# """Get current map center in appropriate format""" -# region = map.GetCurrentRegion() -# precision = int( -# UserSettings.Get(group="projection", key="format", subkey="precision") -# ) -# format = UserSettings.Get(group="projection", key="format", subkey="ll") -# projection = UserSettings.Get( -# group="projection", key="statusbar", subkey="proj4" -# ) -# -# if self.mapFrame.GetProperty("projection"): -# if not projection: -# raise SbException(_("Projection not defined (check the settings)")) -# else: -# proj, coord = utils.ReprojectCoordinates( -# coord=(region["center_easting"], region["center_northing"]), -# projOut=projection, -# flags="d", -# ) -# if coord: -# if proj in ("ll", "latlong", "longlat") and format == "DMS": -# return "%s" % utils.Deg2DMS( -# coord[0], coord[1], precision=precision -# ) -# else: -# return "%.*f; %.*f" % (precision, coord[0], precision, coord[1]) -# else: -# raise SbException(_("Error in projection (check the settings)")) -# else: -# if self.mapFrame.GetMap().projinfo["proj"] == "ll" and format == "DMS": -# return "%s" % utils.Deg2DMS( -# region["center_easting"], -# region["center_northing"], -# precision=precision, -# ) -# else: -# return "%.*f; %.*f" % ( -# precision, -# region["center_easting"], -# precision, -# region["center_northing"], -# ) -# -# def SetCenter(self): -# """Set current map center as item value""" -# center = self.GetCenterString(self.mapFrame.GetMap()) -# self.SetValue(center) -# -# def Update(self): -# self.statusbar.SetStatusText("") -# -# try: -# self.SetCenter() -# self.Show() -# except SbException as e: -# self.statusbar.SetStatusText(str(e), 0) -# -# # disable long help -# self.mapFrame.StatusbarEnableLongHelp(False) - -# -# -# -#class SbDisplayGeometry(SbTextItem): -# """Show current display resolution.""" -# -# def __init__(self, mapframe, statusbar, position=0): -# SbTextItem.__init__(self, mapframe, statusbar, position) -# self.name = "displayGeometry" -# self.label = _("Display geometry") -# -# def Show(self): -# region = copy.copy(self.mapFrame.GetMap().GetCurrentRegion()) -# if self.mapFrame.mapWindowProperties.resolution: -# compRegion = self.mapFrame.GetMap().GetRegion(add3d=False) -# region["rows"] = abs( -# int((region["n"] - region["s"]) / compRegion["nsres"]) + 0.5 -# ) -# region["cols"] = abs( -# int((region["e"] - region["w"]) / compRegion["ewres"]) + 0.5 -# ) -# region["nsres"] = compRegion["nsres"] -# region["ewres"] = compRegion["ewres"] -# self.SetValue( -# "rows=%d; cols=%d; nsres=%.2f; ewres=%.2f" -# % (region["rows"], region["cols"], region["nsres"], region["ewres"]) -# ) -# SbTextItem.Show(self) - - - - -#class SbRegionExtent(SbTextItem): -# """Shows current display region""" -# -# def __init__(self, mapframe, statusbar, position=0): -# SbTextItem.__init__(self, mapframe, statusbar, position) -# self.name = "displayRegion" -# self.label = _("Extent") -# -# def Show(self): -# precision = int( -# UserSettings.Get(group="projection", key="format", subkey="precision") -# ) -# format = UserSettings.Get(group="projection", key="format", subkey="ll") -# projection = self.mapFrame.GetProperty("projection") -# region = self._getRegion() -# try: -# regionReprojected = self.ReprojectRegionFromMap( -# region, projection, precision, format -# ) -# self.SetValue(regionReprojected) -# except SbException as e: -# self.SetValue(e.message) -# SbTextItem.Show(self) -# -# def _getRegion(self): -# """Get current display region""" -# return self.mapFrame.GetMap().GetCurrentRegion() # display region -# -# def _formatRegion(self, w, e, s, n, nsres, ewres, precision=None): -# """Format display region string for statusbar -# -# :param nsres,ewres: unused -# """ -# if precision is not None: -# return "%.*f - %.*f, %.*f - %.*f" % ( -# precision, -# w, -# precision, -# e, -# precision, -# s, -# precision, -# n, -# ) -# else: -# return "%s - %s, %s - %s" % (w, e, s, n) -# -# def ReprojectRegionFromMap(self, region, useDefinedProjection, precision, format): -# """Reproject region values -# -# .. todo:: -# reorganize this method to remove code useful only for derived class SbCompRegionExtent -# """ -# if useDefinedProjection: -# settings = UserSettings.Get( -# group="projection", key="statusbar", subkey="proj4" -# ) -# -# if not settings: -# raise SbException(_("Projection not defined (check the settings)")) -# else: -# projOut = settings -# proj, coord1 = utils.ReprojectCoordinates( -# coord=(region["w"], region["s"]), projOut=projOut, flags="d" -# ) -# proj, coord2 = utils.ReprojectCoordinates( -# coord=(region["e"], region["n"]), projOut=projOut, flags="d" -# ) -# # useless, used in derived class -# proj, coord3 = utils.ReprojectCoordinates( -# coord=(0.0, 0.0), projOut=projOut, flags="d" -# ) -# proj, coord4 = utils.ReprojectCoordinates( -# coord=(region["ewres"], region["nsres"]), projOut=projOut, flags="d" -# ) -# if coord1 and coord2: -# if proj in ("ll", "latlong", "longlat") and format == "DMS": -# w, s = utils.Deg2DMS( -# coord1[0], coord1[1], string=False, precision=precision -# ) -# e, n = utils.Deg2DMS( -# coord2[0], coord2[1], string=False, precision=precision -# ) -# ewres, nsres = utils.Deg2DMS( -# abs(coord3[0]) - abs(coord4[0]), -# abs(coord3[1]) - abs(coord4[1]), -# string=False, -# hemisphere=False, -# precision=precision, -# ) -# return self._formatRegion( -# w=w, s=s, e=e, n=n, ewres=ewres, nsres=nsres -# ) -# else: -# w, s = coord1 -# e, n = coord2 -# ewres, nsres = coord3 -# return self._formatRegion( -# w=w, -# s=s, -# e=e, -# n=n, -# ewres=ewres, -# nsres=nsres, -# precision=precision, -# ) -# else: -# raise SbException(_("Error in projection (check the settings)")) -# -# else: -# if self.mapFrame.GetMap().projinfo["proj"] == "ll" and format == "DMS": -# w, s = utils.Deg2DMS( -# region["w"], region["s"], string=False, precision=precision -# ) -# e, n = utils.Deg2DMS( -# region["e"], region["n"], string=False, precision=precision -# ) -# ewres, nsres = utils.Deg2DMS( -# region["ewres"], region["nsres"], string=False, precision=precision -# ) -# return self._formatRegion(w=w, s=s, e=e, n=n, ewres=ewres, nsres=nsres) -# else: -# w, s = region["w"], region["s"] -# e, n = region["e"], region["n"] -# ewres, nsres = region["ewres"], region["nsres"] -# return self._formatRegion( -# w=w, s=s, e=e, n=n, ewres=ewres, nsres=nsres, precision=precision -# ) -# -# -#class SbCompRegionExtent(SbRegionExtent): -# """Shows computational region.""" -# -# def __init__(self, mapframe, statusbar, position=0): -# SbRegionExtent.__init__(self, mapframe, statusbar, position) -# self.name = "computationalRegion" -# self.label = _("Computational region") -# -# def _formatRegion(self, w, e, s, n, ewres, nsres, precision=None): -# """Format computational region string for statusbar""" -# if precision is not None: -# return "%.*f - %.*f, %.*f - %.*f (%.*f, %.*f)" % ( -# precision, -# w, -# precision, -# e, -# precision, -# s, -# precision, -# n, -# precision, -# ewres, -# precision, -# nsres, -# ) -# else: -# return "%s - %s, %s - %s (%s, %s)" % (w, e, s, n, ewres, nsres) -# -# def _getRegion(self): -# """Returns computational region.""" -# return self.mapFrame.GetMap().GetRegion() # computational region - - diff --git a/gui/wxpython/mapdisp/untitled0.py b/gui/wxpython/mapdisp/untitled0.py deleted file mode 100644 index 5ad3e96166e..00000000000 --- a/gui/wxpython/mapdisp/untitled0.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -Created on Wed Feb 9 08:12:34 2022 - -@author: linwe -""" - - -class Spam(object): - sausages = False - - @property - def eggs(self): - if self.sausages: - return 42 - raise AttributeError("No eggs without sausages") - - @property - def invalid(self): - return self.foobar - - -spam = Spam() -print(hasattr(Spam, 'eggs')) - -print(hasattr(spam, 'eggs')) - -spam.sausages = True -print(hasattr(spam, 'eggs')) - -print(hasattr(spam, 'invalid')) -print(getattr(spam, 'eggs')) \ No newline at end of file From 1cd77e6497442add3a3d5c067a7ff3c990b8e844 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Fri, 18 Feb 2022 08:48:44 -0600 Subject: [PATCH 03/26] make label more readable --- gui/wxpython/image2target/ii2t_statusbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/wxpython/image2target/ii2t_statusbar.py b/gui/wxpython/image2target/ii2t_statusbar.py index dbcafa0b7a6..3ce738eb466 100644 --- a/gui/wxpython/image2target/ii2t_statusbar.py +++ b/gui/wxpython/image2target/ii2t_statusbar.py @@ -34,7 +34,7 @@ class SbGoToGCP(SbItem): def __init__(self, mapframe, statusbar, position=0): SbItem.__init__(self, mapframe, statusbar, position) self.name = "gotoGCP" - self.label = _("Go to GCP No.") + self.label = _("Go to GCP number") self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, value="", min=0) self.widget.Hide() From 8236966c550a726891094e055d293d9642c3cb8e Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Fri, 18 Feb 2022 10:41:06 -0600 Subject: [PATCH 04/26] signal is connected in RBShowInStatusbar --- gui/wxpython/mapdisp/properties.py | 16 ++++++++++++---- gui/wxpython/mapdisp/statusbar.py | 13 +++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index 26107916039..12c36f6483b 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -296,8 +296,9 @@ def __init__(self, parent, sbmanager): style=wx.RA_SPECIFY_COLS, ) self.names = self._getAttributes(attrType="name") - if self.statusbarManager.shownWidgetInStatusbar: - self._setValue(self.statusbarManager.shownWidgetInStatusbar) + if self.statusbarManager.shownWidgetInStatusbar in self.names: + value = [self.names.index(x) for x in self.names if x in self.statusbarManager.shownWidgetInStatusbar][0] + self._setValue(value) else: self._setValue(self.statusbarManager.GetMode()) @@ -326,9 +327,16 @@ def _getAttributes(self, attrType): attributes.append(value.name) return attributes + def _connect(self): + self.statusbarManager.shownWidgetInStatusbarChanged.connect(self._setValue) + + def _disconnect(self): + self.statusbarManager.shownWidgetInStatusbarChanged.disconnect(self._setValue) + def _onToggle(self, event): - name = self._getAttributes(attrType="name")[self.GetValue()] - self.statusbarManager.shownWidgetInStatusbarChanged.emit(itemName=name) + self._disconnect() + self.statusbarManager.shownWidgetInStatusbar = self.names[self.GetValue()] + self._connect() class MapDisplayPropertiesDialog(wx.Dialog): diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 018bd9fd0d0..eef93a8ec0c 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -80,7 +80,7 @@ def __init__(self, mapframe, statusbar): self._postInitialized = False self._modeIndexSet = False self._mode = 0 - self.shownWidgetInStatusbar = None + self._shownWidgetInStatusbar = None self.progressbar = SbProgress(self.mapFrame, self.statusbar, self) self.progressbar.progressShown.connect(self._progressShown) @@ -93,6 +93,16 @@ def __init__(self, mapframe, statusbar): self._hiddenItems = {} + @property + def shownWidgetInStatusbar(self): + return self._shownWidgetInStatusbar + + @shownWidgetInStatusbar.setter + def shownWidgetInStatusbar(self, name): + if name != self._shownWidgetInStatusbar: + self._shownWidgetInStatusbar = name + self.shownWidgetInStatusbarChanged.emit(itemName=name) + def SetProperty(self, name, value): """Sets property represented by one of contained SbItems @@ -193,7 +203,6 @@ def ShowItem(self, itemName): else: item.Update() self.statusbarItems[itemName].Show() - self.shownWidgetInStatusbar = list(self.statusbarItems.keys()).index(itemName) # def _postInit(self): # """Post-initialization method From a789e0af4a1c67b185f7497404f808dd6887502a Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Sun, 20 Feb 2022 09:52:08 -0600 Subject: [PATCH 05/26] edit label --- gui/wxpython/gcp/statusbar.py | 2 +- gui/wxpython/photo2image/ip2i_statusbar.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/wxpython/gcp/statusbar.py b/gui/wxpython/gcp/statusbar.py index dbcafa0b7a6..3ce738eb466 100644 --- a/gui/wxpython/gcp/statusbar.py +++ b/gui/wxpython/gcp/statusbar.py @@ -34,7 +34,7 @@ class SbGoToGCP(SbItem): def __init__(self, mapframe, statusbar, position=0): SbItem.__init__(self, mapframe, statusbar, position) self.name = "gotoGCP" - self.label = _("Go to GCP No.") + self.label = _("Go to GCP number") self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, value="", min=0) self.widget.Hide() diff --git a/gui/wxpython/photo2image/ip2i_statusbar.py b/gui/wxpython/photo2image/ip2i_statusbar.py index 8ada6068b8f..a7a818cdae6 100644 --- a/gui/wxpython/photo2image/ip2i_statusbar.py +++ b/gui/wxpython/photo2image/ip2i_statusbar.py @@ -34,7 +34,7 @@ class SbGoToGCP(SbItem): def __init__(self, mapframe, statusbar, position=0): SbItem.__init__(self, mapframe, statusbar, position) self.name = "gotoGCP" - self.label = _("Go to GCP No.") + self.label = _("Go to GCP number") self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, value="", min=0) self.widget.Hide() From f9ceef93c11f90ffc14e03052dca5110af0e1fb6 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Sun, 20 Feb 2022 11:08:02 -0600 Subject: [PATCH 06/26] switching statusbar modes through mapdisplay settings --- gui/wxpython/mapdisp/properties.py | 9 ++-- gui/wxpython/mapdisp/statusbar.py | 66 +++++++----------------------- 2 files changed, 17 insertions(+), 58 deletions(-) diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index 12c36f6483b..bea416564fb 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -296,13 +296,10 @@ def __init__(self, parent, sbmanager): style=wx.RA_SPECIFY_COLS, ) self.names = self._getAttributes(attrType="name") - if self.statusbarManager.shownWidgetInStatusbar in self.names: - value = [self.names.index(x) for x in self.names if x in self.statusbarManager.shownWidgetInStatusbar][0] - self._setValue(value) - else: - self._setValue(self.statusbarManager.GetMode()) + self._setValue(self.statusbarManager.GetMode()) self.widget.Bind(wx.EVT_RADIOBOX, self._onToggle) + self._connect() def _setValue(self, value): self.widget.SetSelection(value) @@ -335,7 +332,7 @@ def _disconnect(self): def _onToggle(self, event): self._disconnect() - self.statusbarManager.shownWidgetInStatusbar = self.names[self.GetValue()] + self.statusbarManager.SetMode(self.GetValue()) self._connect() diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index eef93a8ec0c..43b00ce7d19 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -80,29 +80,18 @@ def __init__(self, mapframe, statusbar): self._postInitialized = False self._modeIndexSet = False self._mode = 0 - self._shownWidgetInStatusbar = None self.progressbar = SbProgress(self.mapFrame, self.statusbar, self) self.progressbar.progressShown.connect(self._progressShown) self.progressbar.progressHidden.connect(self._progressHidden) self.shownWidgetInStatusbarChanged = Signal("SbManager.shownWidgetInStatusbarChanged") - self.shownWidgetInStatusbarChanged.connect(self.ShowItem) + self.shownWidgetInStatusbarChanged.connect(self.Update) self._oldStatus = "" self._hiddenItems = {} - @property - def shownWidgetInStatusbar(self): - return self._shownWidgetInStatusbar - - @shownWidgetInStatusbar.setter - def shownWidgetInStatusbar(self, name): - if name != self._shownWidgetInStatusbar: - self._shownWidgetInStatusbar = name - self.shownWidgetInStatusbarChanged.emit(itemName=name) - def SetProperty(self, name, value): """Sets property represented by one of contained SbItems @@ -204,32 +193,12 @@ def ShowItem(self, itemName): item.Update() self.statusbarItems[itemName].Show() -# def _postInit(self): -# """Post-initialization method -# -# It sets internal user settings, -# set choice's selection (from user settings) and does reposition. -# It needs choice filled by items. -# it is called automatically. -# """ -# print(self.choice.GetItems()) -# UserSettings.Set( -# group="display", -# key="statusbarMode", -# subkey="choices", -# value=self.choice.GetItems(), -# settings_type="internal", -# ) -# -# if not self._modeIndexSet: -# self.choice.SetSelection( -# UserSettings.Get( -# group="display", key="statusbarMode", subkey="selection" -# ) -# ) -# self.Reposition() -# -# self._postInitialized = True + def _postInit(self): + """Post-initialization method""" + + self.Reposition() + + self._postInitialized = True def Update(self): """Updates statusbar @@ -237,9 +206,10 @@ def Update(self): It always updates mask. """ self.progressbar.Update() + + if not self._postInitialized: + self._postInit() -# if not self._postInitialized: -# self._postInit() for item in self.statusbarItems.values(): if item.GetPosition() == 0: if not self.progressbar.IsShown(): @@ -247,12 +217,9 @@ def Update(self): else: item.Update() # render -# self.statusbarItems.values() -# if self.progressbar.IsShown(): -# pass -# elif self.choice.GetCount() > 0: -# item = self.choice.GetClientData(self.choice.GetSelection()) -# item.Update() + item = list(self.statusbarItems.values())[self.GetMode()] + item.Update() + def Reposition(self): """Reposition items in statusbar @@ -297,15 +264,9 @@ def GetProgressBar(self): def _progressShown(self): self._oldStatus = self.statusbar.GetStatusText(0) - #self.choice.GetClientData(self.choice.GetSelection()).Hide() def _progressHidden(self): self.statusbar.SetStatusText(self._oldStatus, 0) - #self.choice.GetClientData(self.choice.GetSelection()).Show() - - def OnToggleStatus(self, event): - """Toggle status text""" - self.Update() def SetMode(self, modeIndex): """Sets current mode @@ -313,6 +274,7 @@ def SetMode(self, modeIndex): Mode is usually driven by user through choice. """ self._mode = modeIndex + self.shownWidgetInStatusbarChanged.emit(value=modeIndex) def GetMode(self): """Returns current mode""" From f1fc70b17fc65163d59477605bf7fb462ad15792 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Sun, 20 Feb 2022 11:15:55 -0600 Subject: [PATCH 07/26] black and simplification --- gui/wxpython/gui_core/mapdisp.py | 5 ++++- gui/wxpython/mapdisp/properties.py | 17 ++++++++--------- gui/wxpython/mapdisp/statusbar.py | 11 ++++++----- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/gui/wxpython/gui_core/mapdisp.py b/gui/wxpython/gui_core/mapdisp.py index b4342d52b1b..9d05944c09f 100644 --- a/gui/wxpython/gui_core/mapdisp.py +++ b/gui/wxpython/gui_core/mapdisp.py @@ -498,7 +498,10 @@ def OnMapDisplayProperties(self, event): from mapdisp.properties import MapDisplayPropertiesDialog dlg = MapDisplayPropertiesDialog( - parent=self, mapframe=self, properties=self.mapWindowProperties, sbmanager=self.statusbarManager + parent=self, + mapframe=self, + properties=self.mapWindowProperties, + sbmanager=self.statusbarManager, ) dlg.CenterOnParent() dlg.Show() diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index bea416564fb..631436cc54e 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -286,7 +286,7 @@ def __init__(self, parent, sbmanager): self.name = "showInStatusbar" self.statusbarManager = sbmanager - choices = self._getAttributes(attrType="label") + choices = self._getChoices() self.widget = wx.RadioBox( parent=parent, id=wx.ID_ANY, @@ -295,7 +295,6 @@ def __init__(self, parent, sbmanager): majorDimension=1, style=wx.RA_SPECIFY_COLS, ) - self.names = self._getAttributes(attrType="name") self._setValue(self.statusbarManager.GetMode()) self.widget.Bind(wx.EVT_RADIOBOX, self._onToggle) @@ -314,14 +313,11 @@ def GetWidget(self): """ return self.widget - def _getAttributes(self, attrType): + def _getChoices(self): attributes = [] for value in self.statusbarManager.statusbarItems.values(): - if value.GetPosition()==0: - if attrType=="label": - attributes.append(value.label) - elif attrType=="name": - attributes.append(value.name) + if value.GetPosition() == 0: + attributes.append(value.label) return attributes def _connect(self): @@ -338,6 +334,7 @@ def _onToggle(self, event): class MapDisplayPropertiesDialog(wx.Dialog): """Map Display properties dialog.""" + def __init__( self, parent, @@ -444,7 +441,9 @@ def _createStatusBarPage(self, parent): sizer = wx.BoxSizer(wx.VERTICAL) - self.shownInStatusbar = RBShowInStatusbar(parent=panel, sbmanager=self.statusbarManager) + self.shownInStatusbar = RBShowInStatusbar( + parent=panel, sbmanager=self.statusbarManager + ) sizer.Add( self.shownInStatusbar.GetWidget(), proportion=0, diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 43b00ce7d19..f40364063a3 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -85,7 +85,9 @@ def __init__(self, mapframe, statusbar): self.progressbar.progressShown.connect(self._progressShown) self.progressbar.progressHidden.connect(self._progressHidden) - self.shownWidgetInStatusbarChanged = Signal("SbManager.shownWidgetInStatusbarChanged") + self.shownWidgetInStatusbarChanged = Signal( + "SbManager.shownWidgetInStatusbarChanged" + ) self.shownWidgetInStatusbarChanged.connect(self.Update) self._oldStatus = "" @@ -195,9 +197,9 @@ def ShowItem(self, itemName): def _postInit(self): """Post-initialization method""" - + self.Reposition() - + self._postInitialized = True def Update(self): @@ -206,7 +208,7 @@ def Update(self): It always updates mask. """ self.progressbar.Update() - + if not self._postInitialized: self._postInit() @@ -219,7 +221,6 @@ def Update(self): item = list(self.statusbarItems.values())[self.GetMode()] item.Update() - def Reposition(self): """Reposition items in statusbar From 2b0cf9828063feb24f7da51c274e58306fb9861a Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Sun, 20 Feb 2022 11:24:26 -0600 Subject: [PATCH 08/26] small edits --- gui/wxpython/mapdisp/properties.py | 2 +- gui/wxpython/mapdisp/statusbar.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index 631436cc54e..15b3a32e119 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -333,7 +333,7 @@ def _onToggle(self, event): class MapDisplayPropertiesDialog(wx.Dialog): - """Map Display properties dialog.""" + """Map Display properties dialog""" def __init__( self, diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index f40364063a3..94c9afe3a65 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -211,7 +211,6 @@ def Update(self): if not self._postInitialized: self._postInit() - for item in self.statusbarItems.values(): if item.GetPosition() == 0: if not self.progressbar.IsShown(): @@ -275,6 +274,7 @@ def SetMode(self, modeIndex): Mode is usually driven by user through choice. """ self._mode = modeIndex + self._modeIndexSet = True self.shownWidgetInStatusbarChanged.emit(value=modeIndex) def GetMode(self): From a2f9522ab82d200fb05073298ab9ddd1e7c84fcc Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Mon, 21 Feb 2022 13:40:30 -0600 Subject: [PATCH 09/26] keep original labels --- gui/wxpython/gcp/statusbar.py | 2 +- gui/wxpython/image2target/ii2t_statusbar.py | 2 +- gui/wxpython/photo2image/ip2i_statusbar.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/wxpython/gcp/statusbar.py b/gui/wxpython/gcp/statusbar.py index 3ce738eb466..dbcafa0b7a6 100644 --- a/gui/wxpython/gcp/statusbar.py +++ b/gui/wxpython/gcp/statusbar.py @@ -34,7 +34,7 @@ class SbGoToGCP(SbItem): def __init__(self, mapframe, statusbar, position=0): SbItem.__init__(self, mapframe, statusbar, position) self.name = "gotoGCP" - self.label = _("Go to GCP number") + self.label = _("Go to GCP No.") self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, value="", min=0) self.widget.Hide() diff --git a/gui/wxpython/image2target/ii2t_statusbar.py b/gui/wxpython/image2target/ii2t_statusbar.py index 3ce738eb466..dbcafa0b7a6 100644 --- a/gui/wxpython/image2target/ii2t_statusbar.py +++ b/gui/wxpython/image2target/ii2t_statusbar.py @@ -34,7 +34,7 @@ class SbGoToGCP(SbItem): def __init__(self, mapframe, statusbar, position=0): SbItem.__init__(self, mapframe, statusbar, position) self.name = "gotoGCP" - self.label = _("Go to GCP number") + self.label = _("Go to GCP No.") self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, value="", min=0) self.widget.Hide() diff --git a/gui/wxpython/photo2image/ip2i_statusbar.py b/gui/wxpython/photo2image/ip2i_statusbar.py index a7a818cdae6..8ada6068b8f 100644 --- a/gui/wxpython/photo2image/ip2i_statusbar.py +++ b/gui/wxpython/photo2image/ip2i_statusbar.py @@ -34,7 +34,7 @@ class SbGoToGCP(SbItem): def __init__(self, mapframe, statusbar, position=0): SbItem.__init__(self, mapframe, statusbar, position) self.name = "gotoGCP" - self.label = _("Go to GCP number") + self.label = _("Go to GCP No.") self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, value="", min=0) self.widget.Hide() From 4960fdad4f48ff7541b51637efca98cbd0c1888b Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Mon, 21 Feb 2022 13:42:40 -0600 Subject: [PATCH 10/26] onToggleCheckBox kept --- gui/wxpython/mapdisp/properties.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index 15b3a32e119..70832f0a7ca 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -65,7 +65,7 @@ def _connect(self): def _disconnect(self): self.mapWindowPropertyChanged().disconnect(self._setValue) - def _onToggle(self, event): + def _onToggleCheckBox(self, event): self._disconnect() self.mapWindowProperty = self.GetValue() self._connect() @@ -83,7 +83,7 @@ def __init__(self, parent, mapWindowProperties): self.widget.SetValue(self.mapWindowProperty) self.widget.SetToolTip(wx.ToolTip(_("Enable/disable auto-rendering"))) - self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle) + self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox) self._connect() @property @@ -124,7 +124,7 @@ def __init__(self, parent, mapWindowProperties): ) ) ) - self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle) + self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox) self._connect() @property @@ -162,7 +162,7 @@ def __init__(self, parent, mapframe, mapWindowProperties): ) ) ) - self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle) + self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox) self._connect() @property @@ -176,9 +176,9 @@ def mapWindowProperty(self, value): def mapWindowPropertyChanged(self): return self._properties.resolutionChanged - def _onToggle(self, event): + def _onToggleCheckBox(self, event): """Update display when toggle display mode""" - super()._onToggle(event) + super()._onToggleCheckBox(event) # redraw map if auto-rendering is enabled if self._properties.autoRender: @@ -208,7 +208,7 @@ def __init__(self, parent, mapframe, mapWindowProperties): ) ) ) - self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle) + self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox) self._connect() @property @@ -222,12 +222,12 @@ def mapWindowProperty(self, value): def mapWindowPropertyChanged(self): return self._properties.showRegionChanged - def _onToggle(self, event): + def _onToggleCheckBox(self, event): """Shows/Hides extent (comp. region) in map canvas. Shows or hides according to checkbox value. """ - super()._onToggle(event) + super()._onToggleCheckBox(event) # redraw map if auto-rendering is enabled if self._properties.autoRender: @@ -253,7 +253,7 @@ def __init__(self, parent, mapWindowProperties): ) ) ) - self.widget.Bind(wx.EVT_CHECKBOX, self._onToggle) + self.widget.Bind(wx.EVT_CHECKBOX, self._onToggleCheckBox) self._connect() @property @@ -267,8 +267,8 @@ def mapWindowProperty(self, value): def mapWindowPropertyChanged(self): return self._properties.useDefinedProjectionChanged - def _onToggle(self, event): - super()._onToggle(event) + def _onToggleCheckBox(self, event): + super()._onToggleCheckBox(event) epsg = self._properties.epsg if epsg: label = _("{label} (EPSG: {epsg})").format( @@ -297,7 +297,7 @@ def __init__(self, parent, sbmanager): ) self._setValue(self.statusbarManager.GetMode()) - self.widget.Bind(wx.EVT_RADIOBOX, self._onToggle) + self.widget.Bind(wx.EVT_RADIOBOX, self._onToggleRadioBox) self._connect() def _setValue(self, value): @@ -326,7 +326,7 @@ def _connect(self): def _disconnect(self): self.statusbarManager.shownWidgetInStatusbarChanged.disconnect(self._setValue) - def _onToggle(self, event): + def _onToggleRadioBox(self, event): self._disconnect() self.statusbarManager.SetMode(self.GetValue()) self._connect() From 1dbfe2a7cc0c75b42f404e37dbb8ac30d0b75c4e Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Mon, 21 Feb 2022 13:48:01 -0600 Subject: [PATCH 11/26] add GetItemLabels method to statusbar manager --- gui/wxpython/mapdisp/properties.py | 9 +-------- gui/wxpython/mapdisp/statusbar.py | 8 ++++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index 70832f0a7ca..74018511fef 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -286,7 +286,7 @@ def __init__(self, parent, sbmanager): self.name = "showInStatusbar" self.statusbarManager = sbmanager - choices = self._getChoices() + choices = self.statusbarManager.GetItemLabels() self.widget = wx.RadioBox( parent=parent, id=wx.ID_ANY, @@ -313,13 +313,6 @@ def GetWidget(self): """ return self.widget - def _getChoices(self): - attributes = [] - for value in self.statusbarManager.statusbarItems.values(): - if value.GetPosition() == 0: - attributes.append(value.label) - return attributes - def _connect(self): self.statusbarManager.shownWidgetInStatusbarChanged.connect(self._setValue) diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 94c9afe3a65..e4e583b4c70 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -182,6 +182,14 @@ def ShowStatusbarChoiceItemsByClass(self, itemClasses): if item.__class__ in itemClasses: self.choice.Insert(item.label, pos, item) + def GetItemLabels(self): + """Get list of item labels""" + attributes = [] + for value in self.statusbarItems.values(): + if value.GetPosition() == 0: + attributes.append(value.label) + return attributes + def ShowItem(self, itemName): """Invokes showing of particular item From 6192767d9de904d16813395c6c41253cb2cd7fc4 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Mon, 21 Feb 2022 13:49:08 -0600 Subject: [PATCH 12/26] make a dialog bigger --- gui/wxpython/mapdisp/properties.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index 74018511fef..0832e78e1b7 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -335,7 +335,7 @@ def __init__( properties, sbmanager, title=_("Map Display Settings"), - size=(-1, 250), + size=(-1, 300), style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, ): wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=title, style=style) From 542f89e88996cfaca9c182468cb254cb26608e31 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Mon, 21 Feb 2022 14:09:16 -0600 Subject: [PATCH 13/26] _postInit method preserved --- gui/wxpython/mapdisp/statusbar.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index e4e583b4c70..21bc9a51670 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -204,8 +204,25 @@ def ShowItem(self, itemName): self.statusbarItems[itemName].Show() def _postInit(self): - """Post-initialization method""" - + """Post-initialization method + + It sets internal user settings, + set selection (from map display settings) and does reposition. + It is called automatically. + """ + UserSettings.Set( + group="display", + key="statusbarMode", + subkey="choices", + value=self.statusbarItems.values(), + settings_type="internal" + ) + if not self._modeIndexSet: + self.SetMode( + UserSettings.Get( + group="display", key="statusbarMode", subkey="selection" + ) + ) self.Reposition() self._postInitialized = True From 6ec8c566d5983b3215b4b9803e46a69d82cd91f6 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Mon, 21 Feb 2022 14:11:00 -0600 Subject: [PATCH 14/26] black --- gui/wxpython/mapdisp/statusbar.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 21bc9a51670..ec2a128e3dd 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -205,7 +205,7 @@ def ShowItem(self, itemName): def _postInit(self): """Post-initialization method - + It sets internal user settings, set selection (from map display settings) and does reposition. It is called automatically. @@ -215,13 +215,13 @@ def _postInit(self): key="statusbarMode", subkey="choices", value=self.statusbarItems.values(), - settings_type="internal" + settings_type="internal", ) if not self._modeIndexSet: self.SetMode( - UserSettings.Get( - group="display", key="statusbarMode", subkey="selection" - ) + UserSettings.Get( + group="display", key="statusbarMode", subkey="selection" + ) ) self.Reposition() From f515c756168fb0ff6137278b17d61d2506e2ef7a Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Tue, 22 Feb 2022 14:59:53 -0600 Subject: [PATCH 15/26] signals removed, 2D/3D switching fixed --- gui/wxpython/mapdisp/frame.py | 6 ++--- gui/wxpython/mapdisp/properties.py | 15 +++++------ gui/wxpython/mapdisp/statusbar.py | 43 +++++++----------------------- 3 files changed, 18 insertions(+), 46 deletions(-) diff --git a/gui/wxpython/mapdisp/frame.py b/gui/wxpython/mapdisp/frame.py index cdc8b9a6531..0bda87cd6b0 100644 --- a/gui/wxpython/mapdisp/frame.py +++ b/gui/wxpython/mapdisp/frame.py @@ -448,7 +448,7 @@ def AddNviz(self): ) # update status bar - self.statusbarManager.HideStatusbarChoiceItemsByClass( + self.statusbarManager.HideStatusbarItemsByClass( self.statusbarItemsHiddenInNviz ) self.statusbarManager.SetMode(0) @@ -548,9 +548,7 @@ def RemoveNviz(self): pass # update status bar - self.statusbarManager.ShowStatusbarChoiceItemsByClass( - self.statusbarItemsHiddenInNviz - ) + self.statusbarManager.hiddenItems = [] self.statusbarManager.SetMode( UserSettings.Get(group="display", key="statusbarMode", subkey="selection") ) diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index 0832e78e1b7..ed2336767d5 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -296,9 +296,9 @@ def __init__(self, parent, sbmanager): style=wx.RA_SPECIFY_COLS, ) self._setValue(self.statusbarManager.GetMode()) + self._hideItems(self.statusbarManager.hiddenItems) self.widget.Bind(wx.EVT_RADIOBOX, self._onToggleRadioBox) - self._connect() def _setValue(self, value): self.widget.SetSelection(value) @@ -306,6 +306,11 @@ def _setValue(self, value): def GetValue(self): return self.widget.GetSelection() + def _hideItems(self, items, show=False): + """Shows or hides a radiobox options""" + for item in items: + self.widget.ShowItem(item=item, show=show) + def GetWidget(self): """Returns underlying widget. @@ -313,16 +318,8 @@ def GetWidget(self): """ return self.widget - def _connect(self): - self.statusbarManager.shownWidgetInStatusbarChanged.connect(self._setValue) - - def _disconnect(self): - self.statusbarManager.shownWidgetInStatusbarChanged.disconnect(self._setValue) - def _onToggleRadioBox(self, event): - self._disconnect() self.statusbarManager.SetMode(self.GetValue()) - self._connect() class MapDisplayPropertiesDialog(wx.Dialog): diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index ec2a128e3dd..5ab2cacc184 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -85,14 +85,13 @@ def __init__(self, mapframe, statusbar): self.progressbar.progressShown.connect(self._progressShown) self.progressbar.progressHidden.connect(self._progressHidden) - self.shownWidgetInStatusbarChanged = Signal( - "SbManager.shownWidgetInStatusbarChanged" + self.widgetsInStatusbarShown = Signal( + "SbManager.widgetsInStatusbarShown" ) - self.shownWidgetInStatusbarChanged.connect(self.Update) self._oldStatus = "" - self._hiddenItems = {} + self.hiddenItems = [] def SetProperty(self, name, value): """Sets property represented by one of contained SbItems @@ -141,7 +140,7 @@ def AddStatusbarItemsByClass(self, itemClasses, **kwargs): item = Item(**kwargs) self.AddStatusbarItem(item) - def HideStatusbarChoiceItemsByClass(self, itemClasses): + def HideStatusbarItemsByClass(self, itemClasses): """Hides items showed in choice Hides items with position 0 (items showed in choice) by removing @@ -154,33 +153,11 @@ def HideStatusbarChoiceItemsByClass(self, itemClasses): .. todo:: consider adding similar function which would take item names """ - index = [] for itemClass in itemClasses: - for i in range(0, self.choice.GetCount() - 1): - item = self.choice.GetClientData(i) + for i in range(0, len(self.statusbarItems.values())): + item = list(self.statusbarItems.values())[i] if item.__class__ == itemClass: - index.append(i) - self._hiddenItems[i] = item - # must be sorted in reverse order to be removed correctly - for i in sorted(index, reverse=True): - self.choice.Delete(i) - - def ShowStatusbarChoiceItemsByClass(self, itemClasses): - """Shows items showed in choice - - Shows items with position 0 (items showed in choice) by adding - them to choice. - Items are restored in their old positions. - - :param itemClasses list of classes of items to be showed - - :func:`HideStatusbarChoiceItemsByClass` - """ - # must be sorted to be inserted correctly - for pos in sorted(self._hiddenItems.keys()): - item = self._hiddenItems[pos] - if item.__class__ in itemClasses: - self.choice.Insert(item.label, pos, item) + self.hiddenItems.append(i) def GetItemLabels(self): """Get list of item labels""" @@ -273,7 +250,7 @@ def Reposition(self): # else: x, y = rect.x + 3, rect.y - 1 w, h = wWin, rect.height + 2 - else: # choice || auto-rendering + else: # auto-rendering x, y = rect.x, rect.y w, h = rect.width, rect.height + 1 if win == self.progressbar.GetWidget(): @@ -296,11 +273,11 @@ def _progressHidden(self): def SetMode(self, modeIndex): """Sets current mode - Mode is usually driven by user through choice. + Mode is usually driven by user through map display settings. """ self._mode = modeIndex self._modeIndexSet = True - self.shownWidgetInStatusbarChanged.emit(value=modeIndex) + self.Update() def GetMode(self): """Returns current mode""" From 6569b12a083b7d1ae4ccfb588b11e80e84b0d04b Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Tue, 22 Feb 2022 15:10:50 -0600 Subject: [PATCH 16/26] list comprehension --- gui/wxpython/mapdisp/statusbar.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 5ab2cacc184..3236dced6e9 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -161,11 +161,7 @@ def HideStatusbarItemsByClass(self, itemClasses): def GetItemLabels(self): """Get list of item labels""" - attributes = [] - for value in self.statusbarItems.values(): - if value.GetPosition() == 0: - attributes.append(value.label) - return attributes + return [value.label for value in self.statusbarItems.values() if value.GetPosition()==0] def ShowItem(self, itemName): """Invokes showing of particular item From 37bcf2bcddfecd23ea1d1d1de5f3f88c70911172 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Tue, 22 Feb 2022 15:35:06 -0600 Subject: [PATCH 17/26] black, signal removed --- gui/wxpython/mapdisp/frame.py | 4 +--- gui/wxpython/mapdisp/statusbar.py | 10 +++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/gui/wxpython/mapdisp/frame.py b/gui/wxpython/mapdisp/frame.py index 0bda87cd6b0..1749a75bf0d 100644 --- a/gui/wxpython/mapdisp/frame.py +++ b/gui/wxpython/mapdisp/frame.py @@ -448,9 +448,7 @@ def AddNviz(self): ) # update status bar - self.statusbarManager.HideStatusbarItemsByClass( - self.statusbarItemsHiddenInNviz - ) + self.statusbarManager.HideStatusbarItemsByClass(self.statusbarItemsHiddenInNviz) self.statusbarManager.SetMode(0) # erase map window diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 3236dced6e9..2ffc88dcd24 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -85,10 +85,6 @@ def __init__(self, mapframe, statusbar): self.progressbar.progressShown.connect(self._progressShown) self.progressbar.progressHidden.connect(self._progressHidden) - self.widgetsInStatusbarShown = Signal( - "SbManager.widgetsInStatusbarShown" - ) - self._oldStatus = "" self.hiddenItems = [] @@ -161,7 +157,11 @@ def HideStatusbarItemsByClass(self, itemClasses): def GetItemLabels(self): """Get list of item labels""" - return [value.label for value in self.statusbarItems.values() if value.GetPosition()==0] + return [ + value.label + for value in self.statusbarItems.values() + if value.GetPosition() == 0 + ] def ShowItem(self, itemName): """Invokes showing of particular item From 2cb5667e560f820c55bd1285508efb3fb7081529 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Wed, 23 Feb 2022 09:02:59 -0600 Subject: [PATCH 18/26] desc, problem with other map disp apps --- gui/wxpython/mapdisp/statusbar.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 2ffc88dcd24..42d5498f3b8 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -201,10 +201,7 @@ def _postInit(self): self._postInitialized = True def Update(self): - """Updates statusbar - - It always updates mask. - """ + """Updates statusbar""" self.progressbar.Update() if not self._postInitialized: @@ -216,8 +213,14 @@ def Update(self): else: item.Update() # render - item = list(self.statusbarItems.values())[self.GetMode()] - item.Update() + if self.progressbar.IsShown(): + pass + else: + item = list(self.statusbarItems.values())[self.GetMode()] + try: + item.Update() + except: + item.Show() def Reposition(self): """Reposition items in statusbar From d4ec49f67d07a0a755bd1223b6fbd0a9579e43b2 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Wed, 23 Feb 2022 09:23:47 -0600 Subject: [PATCH 19/26] Update statusbar from radiobox, SetMode just sets the mode --- gui/wxpython/mapdisp/properties.py | 1 + gui/wxpython/mapdisp/statusbar.py | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index ed2336767d5..37a0e86d315 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -320,6 +320,7 @@ def GetWidget(self): def _onToggleRadioBox(self, event): self.statusbarManager.SetMode(self.GetValue()) + self.statusbarManager.Update() class MapDisplayPropertiesDialog(wx.Dialog): diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 42d5498f3b8..e330bc883d4 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -217,10 +217,7 @@ def Update(self): pass else: item = list(self.statusbarItems.values())[self.GetMode()] - try: - item.Update() - except: - item.Show() + item.Update() def Reposition(self): """Reposition items in statusbar @@ -276,7 +273,6 @@ def SetMode(self, modeIndex): """ self._mode = modeIndex self._modeIndexSet = True - self.Update() def GetMode(self): """Returns current mode""" From 31cbdd49e936a1a51e040a85ac591f7b43401be3 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Wed, 23 Feb 2022 09:41:20 -0600 Subject: [PATCH 20/26] edit descriptions --- gui/wxpython/mapdisp/statusbar.py | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index e330bc883d4..622decc88b2 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -52,8 +52,8 @@ class SbManager: """Statusbar manager for wx.Statusbar and SbItems. Statusbar manager manages items added by AddStatusbarItem method. - Provides progress bar (SbProgress) and choice (wx.Choice). - Items with position 0 are shown according to choice selection. + Provides progress bar (SbProgress). + Items with position 0 are shown according to selection in Map Display settings dialog. Only one item of the same class is supposed to be in statusbar. Manager user have to create statusbar on his own, add items to manager and call Update method to show particular widgets. @@ -70,7 +70,7 @@ class SbManager: def __init__(self, mapframe, statusbar): """Connects manager to statusbar - Creates choice and progress bar. + Creates progress bar. """ self.mapFrame = mapframe self.statusbar = statusbar @@ -116,12 +116,7 @@ def HasProperty(self, name): return False def AddStatusbarItem(self, item): - """Adds item to statusbar - - If item position is 0, item is managed by choice. - - :func:`AddStatusbarItemsByClass` - """ + """Adds item to statusbar""" self.statusbarItems[item.name] = item def AddStatusbarItemsByClass(self, itemClasses, **kwargs): @@ -137,17 +132,9 @@ def AddStatusbarItemsByClass(self, itemClasses, **kwargs): self.AddStatusbarItem(item) def HideStatusbarItemsByClass(self, itemClasses): - """Hides items showed in choice - - Hides items with position 0 (items showed in choice) by removing - them from choice. + """Fill list of item indexes that are hidden. :param itemClasses list of classes of items to be hided - - :func:`ShowStatusbarChoiceItemsByClass` - - .. todo:: - consider adding similar function which would take item names """ for itemClass in itemClasses: for i in range(0, len(self.statusbarItems.values())): @@ -352,7 +339,7 @@ def _update(self, longHelp): self.mapFrame.StatusbarEnableLongHelp(longHelp) def Update(self): - """Called when statusbar action is activated (e.g. through wx.Choice).""" + """Called when statusbar action is activated (e.g. through Map Display settings).""" self._update(longHelp=False) From eb25021a184cebf3a767c1af7dc4f3a23eed8209 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Wed, 23 Feb 2022 09:54:44 -0600 Subject: [PATCH 21/26] fix combobox in preferences dialog --- gui/wxpython/mapdisp/statusbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 622decc88b2..1571ad81c83 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -174,7 +174,7 @@ def _postInit(self): group="display", key="statusbarMode", subkey="choices", - value=self.statusbarItems.values(), + value=self.GetItemLabels(), settings_type="internal", ) if not self._modeIndexSet: From dab55b6ad9a91e5e95f2f2f4edd4c2c47a78bdc3 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Thu, 24 Feb 2022 06:16:11 -0600 Subject: [PATCH 22/26] items disabled rather than hidden --- gui/wxpython/mapdisp/frame.py | 8 +++++--- gui/wxpython/mapdisp/properties.py | 10 +++++----- gui/wxpython/mapdisp/statusbar.py | 10 +++++----- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/gui/wxpython/mapdisp/frame.py b/gui/wxpython/mapdisp/frame.py index 1749a75bf0d..484a62c910c 100644 --- a/gui/wxpython/mapdisp/frame.py +++ b/gui/wxpython/mapdisp/frame.py @@ -150,7 +150,7 @@ def __init__( sb.SbMapScale, sb.SbGoTo, ] - self.statusbarItemsHiddenInNviz = ( + self.statusbarItemsDisabledInNviz = ( sb.SbDisplayGeometry, sb.SbMapScale, ) @@ -448,7 +448,7 @@ def AddNviz(self): ) # update status bar - self.statusbarManager.HideStatusbarItemsByClass(self.statusbarItemsHiddenInNviz) + self.statusbarManager.DisableStatusbarItemsByClass(self.statusbarItemsDisabledInNviz) self.statusbarManager.SetMode(0) # erase map window @@ -546,11 +546,13 @@ def RemoveNviz(self): pass # update status bar - self.statusbarManager.hiddenItems = [] + self.statusbarManager.disabledItems = {} self.statusbarManager.SetMode( 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( _("Switching back to 2D view mode..."), diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index 37a0e86d315..1adb0b6bbb1 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -296,7 +296,7 @@ def __init__(self, parent, sbmanager): style=wx.RA_SPECIFY_COLS, ) self._setValue(self.statusbarManager.GetMode()) - self._hideItems(self.statusbarManager.hiddenItems) + self._disableItems() self.widget.Bind(wx.EVT_RADIOBOX, self._onToggleRadioBox) @@ -306,10 +306,10 @@ def _setValue(self, value): def GetValue(self): return self.widget.GetSelection() - def _hideItems(self, items, show=False): - """Shows or hides a radiobox options""" - for item in items: - self.widget.ShowItem(item=item, show=show) + def _disableItems(self): + """Disables a radiobox options""" + for item in self.statusbarManager.disabledItems.keys(): + self.widget.EnableItem(n=item, enable=False) def GetWidget(self): """Returns underlying widget. diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 1571ad81c83..ef85b08386e 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -87,7 +87,7 @@ def __init__(self, mapframe, statusbar): self._oldStatus = "" - self.hiddenItems = [] + self.disabledItems = {} def SetProperty(self, name, value): """Sets property represented by one of contained SbItems @@ -131,16 +131,16 @@ def AddStatusbarItemsByClass(self, itemClasses, **kwargs): item = Item(**kwargs) self.AddStatusbarItem(item) - def HideStatusbarItemsByClass(self, itemClasses): - """Fill list of item indexes that are hidden. + def DisableStatusbarItemsByClass(self, itemClasses): + """Fill list of item indexes that are disabled. - :param itemClasses list of classes of items to be hided + :param itemClasses list of classes of items to be disabled """ for itemClass in itemClasses: for i in range(0, len(self.statusbarItems.values())): item = list(self.statusbarItems.values())[i] if item.__class__ == itemClass: - self.hiddenItems.append(i) + self.disabledItems[i] = item def GetItemLabels(self): """Get list of item labels""" From 0b18dab0fb34c3cac74c37bbf87ee39cd6bbfd63 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Thu, 24 Feb 2022 06:17:58 -0600 Subject: [PATCH 23/26] black --- gui/wxpython/mapdisp/frame.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gui/wxpython/mapdisp/frame.py b/gui/wxpython/mapdisp/frame.py index 484a62c910c..9bece75b0ab 100644 --- a/gui/wxpython/mapdisp/frame.py +++ b/gui/wxpython/mapdisp/frame.py @@ -448,7 +448,9 @@ def AddNviz(self): ) # update status bar - self.statusbarManager.DisableStatusbarItemsByClass(self.statusbarItemsDisabledInNviz) + self.statusbarManager.DisableStatusbarItemsByClass( + self.statusbarItemsDisabledInNviz + ) self.statusbarManager.SetMode(0) # erase map window From 4db0b457cae83cb2cd6f2b005e031bf6a9f3d783 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Tue, 1 Mar 2022 12:23:53 -0600 Subject: [PATCH 24/26] keep the previous code for Show() method --- gui/wxpython/mapdisp/statusbar.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index ef85b08386e..d99d9963d33 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -155,12 +155,10 @@ def ShowItem(self, itemName): :func:`Update` """ - for item in self.statusbarItems.values(): - if item.GetPosition() == 0: - if item.name != itemName and not self.progressbar.IsShown(): - item.Hide() - else: - item.Update() + if ( + self.statusbarItems[itemName].GetPosition() != 0 + or not self.progressbar.IsShown() + ): self.statusbarItems[itemName].Show() def _postInit(self): From 60fc78eca280e1fe2eb727222edead6c6b859d99 Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Tue, 1 Mar 2022 12:43:30 -0600 Subject: [PATCH 25/26] GCP labels changed --- gui/wxpython/gcp/statusbar.py | 2 +- gui/wxpython/image2target/ii2t_statusbar.py | 2 +- gui/wxpython/photo2image/ip2i_statusbar.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/wxpython/gcp/statusbar.py b/gui/wxpython/gcp/statusbar.py index dbcafa0b7a6..1d10ad0b9b4 100644 --- a/gui/wxpython/gcp/statusbar.py +++ b/gui/wxpython/gcp/statusbar.py @@ -34,7 +34,7 @@ class SbGoToGCP(SbItem): def __init__(self, mapframe, statusbar, position=0): SbItem.__init__(self, mapframe, statusbar, position) self.name = "gotoGCP" - self.label = _("Go to GCP No.") + self.label = _("Pan to GCP by number") self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, value="", min=0) self.widget.Hide() diff --git a/gui/wxpython/image2target/ii2t_statusbar.py b/gui/wxpython/image2target/ii2t_statusbar.py index dbcafa0b7a6..1d10ad0b9b4 100644 --- a/gui/wxpython/image2target/ii2t_statusbar.py +++ b/gui/wxpython/image2target/ii2t_statusbar.py @@ -34,7 +34,7 @@ class SbGoToGCP(SbItem): def __init__(self, mapframe, statusbar, position=0): SbItem.__init__(self, mapframe, statusbar, position) self.name = "gotoGCP" - self.label = _("Go to GCP No.") + self.label = _("Pan to GCP by number") self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, value="", min=0) self.widget.Hide() diff --git a/gui/wxpython/photo2image/ip2i_statusbar.py b/gui/wxpython/photo2image/ip2i_statusbar.py index 8ada6068b8f..c1fcf9a9907 100644 --- a/gui/wxpython/photo2image/ip2i_statusbar.py +++ b/gui/wxpython/photo2image/ip2i_statusbar.py @@ -34,7 +34,7 @@ class SbGoToGCP(SbItem): def __init__(self, mapframe, statusbar, position=0): SbItem.__init__(self, mapframe, statusbar, position) self.name = "gotoGCP" - self.label = _("Go to GCP No.") + self.label = _("Pan to GCP by number") self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, value="", min=0) self.widget.Hide() From 61da223883d12768a9ac6cee5401bac01003011e Mon Sep 17 00:00:00 2001 From: lindakladivova Date: Tue, 1 Mar 2022 12:53:53 -0600 Subject: [PATCH 26/26] parameter names changed --- gui/wxpython/mapdisp/properties.py | 4 ++-- gui/wxpython/mapdisp/statusbar.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gui/wxpython/mapdisp/properties.py b/gui/wxpython/mapdisp/properties.py index 1adb0b6bbb1..b1c95034b4f 100644 --- a/gui/wxpython/mapdisp/properties.py +++ b/gui/wxpython/mapdisp/properties.py @@ -300,8 +300,8 @@ def __init__(self, parent, sbmanager): self.widget.Bind(wx.EVT_RADIOBOX, self._onToggleRadioBox) - def _setValue(self, value): - self.widget.SetSelection(value) + def _setValue(self, mode): + self.widget.SetSelection(mode) def GetValue(self): return self.widget.GetSelection() diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index d99d9963d33..5c0693a05a3 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -251,12 +251,12 @@ def _progressShown(self): def _progressHidden(self): self.statusbar.SetStatusText(self._oldStatus, 0) - def SetMode(self, modeIndex): + def SetMode(self, mode): """Sets current mode Mode is usually driven by user through map display settings. """ - self._mode = modeIndex + self._mode = mode self._modeIndexSet = True def GetMode(self):