bh: thuban/Thuban/UI viewport.py, 1.19, 1.20 mainwindow.py, 1.140, 1.141

cvs@intevation.de cvs at intevation.de
Mon Jan 24 12:19:55 CET 2005


Author: bh

Update of /thubanrepository/thuban/Thuban/UI
In directory doto:/tmp/cvs-serv12794/Thuban/UI

Modified Files:
	viewport.py mainwindow.py 
Log Message:
Rework the status bar updates a bit to make sure the message about
the projections is produced at the right times.

* Thuban/UI/mainwindow.py (MainWindow.update_status_bar_messages):
New class variable with messages that may require a status bar
update.
(MainWindow.view_position_changed)
(MainWindow.update_status_bar): Rename from view_position_changed
to update_status_bar.  It's meaning has changed now that it may
also generate messages about problems with projection settings.
(MainWindow.__init__): Use the new update_status_bar_messages
class variable to subscribe update_status_bar
(MainWindow.set_position_text): Update doc-string.  This method
has to be renamed at some point.  See doc-string and comments.
(MainWindow.OnClose): Unsubscribe update_status_bar from all
messages in update_status_bar_messages

* Thuban/UI/viewport.py (ViewPort.forwarded_map_messages): New
class attribute.  map messages to be forwarded by the viewport.
(ViewPort._subscribe_map, ViewPort._unsubscribe_map): (un)subscribe
the messages in forwarded_map_messages


Index: viewport.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/UI/viewport.py,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- viewport.py	18 Nov 2004 20:17:43 -0000	1.19
+++ viewport.py	24 Jan 2005 11:19:53 -0000	1.20
@@ -1,4 +1,4 @@
-# Copyright (c) 2003-2004 by Intevation GmbH
+# Copyright (c) 2003-2005 by Intevation GmbH
 # Authors:
 # Bernhard Herzog <bh at intevation.de> (2003, 2004)
 # Jonathan Coles <jonathan at intevation.de> (2003)
@@ -20,7 +20,8 @@
 from wxproj import point_in_polygon_shape, shape_centroid
 
 from Thuban.Model.messages import MAP_PROJECTION_CHANGED, \
-     LAYER_PROJECTION_CHANGED, TITLE_CHANGED
+     LAYER_PROJECTION_CHANGED, TITLE_CHANGED, \
+     MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED
 from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
      SHAPETYPE_POINT, RAW_SHAPEFILE
 from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
@@ -31,7 +32,7 @@
 from selection import Selection
 
 from messages import LAYER_SELECTED, SHAPES_SELECTED, VIEW_POSITION, \
-                     SCALE_CHANGED, MAP_REPLACED
+     SCALE_CHANGED, MAP_REPLACED
 
 import hittest
 
@@ -226,6 +227,13 @@
                          "HasSelectedShapes": "selection",
                          "SelectedShapes": "selection"}
 
+    # Some messages are forwarded from the currently shown map.  This is
+    # simply a list of the channels to forward.  The _subscribe_map and
+    # _unsubscribe_map methods use this to handle the forwarding.
+    forwarded_map_messages = (LAYER_PROJECTION_CHANGED, TITLE_CHANGED,
+                              MAP_PROJECTION_CHANGED,
+                              MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED)
+
     def __init__(self, size = (400, 300)):
 
         self.size = size
@@ -311,14 +319,16 @@
                           self.layer_projection_changed)
             map.Subscribe(MAP_PROJECTION_CHANGED,
                           self.map_projection_changed)
-            self.subscribe_forwarding(TITLE_CHANGED, map)
+            for channel in self.forwarded_map_messages:
+                self.subscribe_forwarding(channel, map)
 
     def _unsubscribe_map(self, map):
         """
         Internal: Unsubscribe from the messages subscribed to in _subscribe_map
         """
         if map is not None:
-            self.unsubscribe_forwarding(TITLE_CHANGED, map)
+            for channel in self.forwarded_map_messages:
+                self.unsubscribe_forwarding(channel, map)
             map.Unsubscribe(MAP_PROJECTION_CHANGED,
                             self.map_projection_changed)
             map.Unsubscribe(LAYER_PROJECTION_CHANGED,

Index: mainwindow.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/UI/mainwindow.py,v
retrieving revision 1.140
retrieving revision 1.141
diff -u -d -r1.140 -r1.141
--- mainwindow.py	21 Jan 2005 08:31:16 -0000	1.140
+++ mainwindow.py	24 Jan 2005 11:19:53 -0000	1.141
@@ -1,4 +1,4 @@
-# Copyright (C) 2001, 2002, 2003, 2004 by Intevation GmbH
+# Copyright (C) 2001, 2002, 2003, 2004, 2005 by Intevation GmbH
 # Authors:
 # Jan-Oliver Wagner <jan at intevation.de>
 # Bernhard Herzog <bh at intevation.de>
@@ -23,7 +23,9 @@
 import Thuban
 
 from Thuban import _
-from Thuban.Model.messages import TITLE_CHANGED
+from Thuban.Model.messages import TITLE_CHANGED, LAYER_PROJECTION_CHANGED, \
+     MAP_PROJECTION_CHANGED, MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED
+
 from Thuban.Model.session import create_empty_session
 from Thuban.Model.layer import Layer, RasterLayer
 from Thuban.Model.postgisdb import PostGISShapeStore, has_postgis_support
@@ -75,6 +77,12 @@
                          "SelectedShapes": "canvas",
                          }
 
+    # Messages from the canvas that may require a status bar update.
+    # The update_status_bar method will be subscribed to these messages.
+    update_status_bar_messages = (VIEW_POSITION, LAYER_PROJECTION_CHANGED,
+                                  MAP_PROJECTION_CHANGED, MAP_LAYERS_ADDED,
+                                  MAP_LAYERS_REMOVED)
+
     def __init__(self, parent, ID, title, application, interactor,
                  initial_message = None, size = wxSize(-1, -1)):
         DockFrame.__init__(self, parent, ID, title, wxDefaultPosition, size)
@@ -101,11 +109,13 @@
 
         # Create the map canvas
         canvas = view.MapCanvas(self, -1)
-        canvas.Subscribe(VIEW_POSITION, self.view_position_changed)
         canvas.Subscribe(SHAPES_SELECTED, self.identify_view_on_demand)
         self.canvas = canvas
         self.canvas.Subscribe(TITLE_CHANGED, self.title_changed)
 
+        for channel in self.update_status_bar_messages:
+            self.canvas.Subscribe(channel, self.update_status_bar)
+
         self.SetMainWindow(self.canvas)
 
         self.SetAutoLayout(True)
@@ -334,40 +344,52 @@
     def get_open_dialog(self, name):
         return self.dialogs.get(name)
 
-    def view_position_changed(self):
-        """Put current position in status bar after a mouse move."""
+    def update_status_bar(self, *args):
+        """Handler for a bunch of messages that may require a status bar update
+
+        Currently this handles the canvas' VIEW_POSITION_CHANGED
+        messages as well as several messages about changes in the map
+        which may affect whether and how projections are used.
+
+        These messages affect the text in the status bar in the following way:
+
+        When VIEW_POSITION_CHANGED messages are sent and the mouse is
+        actually in the canvas window, display the current mouse
+        coordinates as defined by the canvas' CurrentPosition method.
+
+        If there is no current position to show, check whether there is
+        a potential problem with the map and layer projections and
+        display a message about it.  Otherwise the status bar will
+        become empty.
+
+        The text is displayed in the status bar using the
+        set_position_text method.
+        """
+        # Implementation note: We do not really have to know which
+        # message was sent.  We can simply call the canvas'
+        # CurrentPosition method and if that returns a tuple, it was a
+        # VIEW_POSITION_CHANGED message and we have to display it.
+        # Otherwise it was a VIEW_POSITION_CHANGED message where the
+        # mouse has left the canvas or it was a message about a change
+        # to the map, in which case we check the projections.
+        #
+        # When changing this method, keep in mind that the
+        # VIEW_POSITION_CHANGED message are sent for every mouse move in
+        # the canvas window, that is they happen very often, so the path
+        # taken in that case has to be fast.
+        text = ""
         pos = self.canvas.CurrentPosition()
         if pos is not None:
             text = "(%10.10g, %10.10g)" % pos
         else:
-            text = ""
-            # XXX This is a hack until we find a better place for this code.
-            # (BER 20050120)
-            # BH wrote (20050120):
-            # this branch is only executed when the mouse
-            # leaves the canvas window, so it's not that often [..]
-            # [Here] not the right place to put this code.  
-            # I don't have a better solution at hand, 
-            # but the view_position_changed is only there to update 
-            # the current position.  If other information is to
-            # be shown in the status bar it should 
-            # be handled in a different way and
-            # by other methods.
-            #
-            # The status bar widget supports some kind of stack of texts.
-            # maybe that can be used to distinguis 
-            # between short-lived information such as the mouse position 
-            # and more permanent information such as the hint 
-            # about the projections.
-            map = self.canvas.Map()
-            for layer in map.layers:
+            for layer in self.canvas.Map().Layers():
                 bbox = layer.LatLongBoundingBox()
                 if bbox:
                     left, bottom, right, top = bbox
                     if not (-180 <= left <= 180 and
-                        -180 <= right <= 180 and
-                        -90 <= top <= 90 and
-                        -90 <= bottom <= 90):
+                            -180 <= right <= 180 and
+                            -90 <= top <= 90 and
+                            -90 <= bottom <= 90):
                         text = _("Select layer '%s' and pick a projection "
                                  "using Layer/Projection...") % layer.title
                         break
@@ -375,12 +397,20 @@
         self.set_position_text(text)
 
     def set_position_text(self, text):
-        """Set the statusbar text showing the current position.
+        """Set the statusbar text to that created by update_status_bar
 
         By default the text is shown in field 0 of the status bar.
         Override this method in derived classes to put it into a
         different field of the statusbar.
+
+        For historical reasons this method is called set_position_text
+        because at first the text was always either the current position
+        or the empty string.  Now it can contain other messages as well.
+        The method will be renamed at one point.
         """
+        # Note: If this method is renamed we should perhaps think about
+        # some backwards compatibility measures for projects like
+        # GREAT-ER which override this method.
         self.SetStatusText(text)
 
     def OpenOrRaiseDialog(self, name, dialog_class, *args, **kw):
@@ -472,7 +502,9 @@
             # FIXME: it would be better to tie the unsubscription to
             # wx's destroy event, but that isn't implemented for wxGTK
             # yet.
-            self.canvas.Unsubscribe(VIEW_POSITION, self.view_position_changed)
+            for channel in self.update_status_bar_messages:
+                self.canvas.Unsubscribe(channel, self.update_status_bar)
+
             DockFrame.OnClose(self, event)
             for dlg in self.dialogs.values():
                 dlg.Destroy()





More information about the Thuban-devel mailing list

This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)