/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/tree.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/UI/tree.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 177 by bh, Wed May 15 14:02:09 2002 UTC revision 1766 by jan, Wed Oct 1 09:52:28 2003 UTC
# Line 1  Line 1 
1  #! /usr/bin/python  # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
 # Copyright (c) 2001, 2002 by Intevation GmbH  
2  # Authors:  # Authors:
3  # Jan-Oliver Wagner <[email protected]>  # Jan-Oliver Wagner <[email protected]>
4  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
# Line 9  Line 8 
8    
9  __version__ = "$Revision$"  __version__ = "$Revision$"
10    
11    from types import StringType, UnicodeType
12    
13  from wxPython.wx import *  from wxPython.wx import *
14    
15  from Thuban.Model.messages import MAPS_CHANGED, MAP_PROJECTION_CHANGED, \  from Thuban import _
16       LAYERS_CHANGED, LAYER_LEGEND_CHANGED, LAYER_VISIBILITY_CHANGED  from Thuban.UI.common import Color2wxColour
17  from Thuban.Model.layer import Layer, shapetype_names  
18  from Thuban.Model.map import Map  from Thuban.Model.color import Color
19    
20  from dialogs import NonModalDialog  from Thuban.Model.messages import CHANGED
21  from messages import SESSION_CHANGED, SELECTED_LAYER  from Thuban.Model.layer import Layer
22    from Thuban.Model.map import Map
23    
24  def color_string(color):  from dialogs import NonModalNonParentDialog
25      if color is None:  from messages import SESSION_REPLACED, LAYER_SELECTED
         return "None"  
     return "(%.3f, %.3f, %.3f)" % (color.red, color.green, color.blue)  
26    
27    BMP_SIZE = 15
28    
29  class SessionTreeCtrl(wxTreeCtrl):  class SessionTreeCtrl(wxTreeCtrl):
30    
31      # the session channels to subscribe to to update the tree      """Widget to display a tree view of the session.
32      session_channels = (MAPS_CHANGED, MAP_PROJECTION_CHANGED,  
33                          LAYERS_CHANGED, LAYER_LEGEND_CHANGED,      The tree view is created recursively from the session object. The
34                          LAYER_VISIBILITY_CHANGED)      tree view calls the session's TreeInfo method which should return a
35        pair (<title>, <item>) where <title> ist the title of the session
36        item in the tree view and <items> is a list of objects to use as the
37        children of the session in the tree view.
38    
39        The items list can contain three types of items:
40    
41           1. a string. The string is used as the title for a leaf item in
42              the tree view.
43    
44           2. an object with a TreeInfo method. This method is called and
45              should return a pair just like the session's TreeInfo method.
46    
47           3. a pair (<title>, <item>) which is treated like the return
48              value of TreeInfo.
49        """
50    
51        def __init__(self, parent, ID, mainwindow, app):
52    
     def __init__(self, parent, ID, app):  
53          # Use the WANTS_CHARS style so the panel doesn't eat the Return key.          # Use the WANTS_CHARS style so the panel doesn't eat the Return key.
54          wxTreeCtrl.__init__(self, parent, ID)          wxTreeCtrl.__init__(self, parent, ID)
55    
56            self.mainwindow = mainwindow
57          self.app = app          self.app = app
58          # boolean to indicate that we manipulate the selection ourselves          # boolean to indicate that we manipulate the selection ourselves
59          # so that we can ignore the selection events generated          # so that we can ignore the selection events generated
# Line 44  class SessionTreeCtrl(wxTreeCtrl): Line 62  class SessionTreeCtrl(wxTreeCtrl):
62          # Dictionary mapping layer id's to tree items          # Dictionary mapping layer id's to tree items
63          self.layer_to_item = {}          self.layer_to_item = {}
64    
65          self.app.Subscribe(SESSION_CHANGED, self.session_changed)          self.app.Subscribe(SESSION_REPLACED, self.session_changed)
66          self.app.interactor.Subscribe(SELECTED_LAYER, self.layer_selected)          self.mainwindow.Subscribe(LAYER_SELECTED, self.layer_selected)
67    
68          # the session currently displayed in the tree          # the session currently displayed in the tree
69          self.session = None          self.session = None
70    
71    
72          # pretend the session has changed to build the initial tree          # pretend the session has changed to build the initial tree
73          self.session_changed()          self.session_changed()
74    
# Line 57  class SessionTreeCtrl(wxTreeCtrl): Line 76  class SessionTreeCtrl(wxTreeCtrl):
76    
77      def unsubscribe_all(self):      def unsubscribe_all(self):
78          if self.session is not None:          if self.session is not None:
79              for channel in self.session_channels:              self.session.Unsubscribe(CHANGED, self.update_tree)
                 self.session.Unsubscribe(channel, self.update_tree)  
80              self.session = None              self.session = None
81          self.app.Unsubscribe(SESSION_CHANGED, self.session_changed)          self.app.Unsubscribe(SESSION_REPLACED, self.session_changed)
82          self.app.interactor.Unsubscribe(SELECTED_LAYER, self.layer_selected)          self.mainwindow.Unsubscribe(LAYER_SELECTED, self.layer_selected)
83    
84      def update_tree(self, *args):      def update_tree(self, *args):
85          """Clear and rebuild the tree"""          """Clear and rebuild the tree"""
86          self.DeleteAllItems()          self.DeleteAllItems()
         session = self.app.session  
         root = self.AddRoot("Session: %s" % session.title)  
87          self.layer_to_item.clear()          self.layer_to_item.clear()
88          if session.filename == None:          self.image_list = wxImageList(BMP_SIZE, BMP_SIZE, False, 0)
89              self.AppendItem(root, "Filename:")  
90          else:          bmp = wxEmptyBitmap(BMP_SIZE, BMP_SIZE)
91              self.AppendItem(root, "Filename: %s" % session.filename)          dc = wxMemoryDC()
92          if session.WasModified():          dc.SelectObject(bmp)
93              self.AppendItem(root, "Modified: yes")          dc.SetBrush(wxBLACK_BRUSH)
94          else:          dc.Clear()
95              self.AppendItem(root, "Modified: no")          dc.SelectObject(wxNullBitmap)
96    
97            self.emptyImageIndex = \
98                self.image_list.AddWithColourMask(bmp, wxColour(0, 0, 0))
99    
100          for map in session.Maps():          self.AssignImageList(self.image_list)
101              mapitem = self.AppendItem(root, "Map: %s" % map.title)  
102              self.SetPyData(mapitem, map)          session = self.app.session
103              if map.BoundingBox() != None:          info = session.TreeInfo()
104                  self.AppendItem(mapitem, ("Extent (lat-lon): (%g, %g, %g, %g)"          root = self.AddRoot(info[0], -1, -1, None)
105                                            % map.BoundingBox()))          self.SetItemImage(root, self.emptyImageIndex)
106              if map.projection and len(map.projection.params) > 0:          self.add_items(root, info[1])
                 self.AppendItem(mapitem,  
                                 ("Extent (projected): (%g, %g, %g, %g)"  
                                  % map.ProjectedBoundingBox()))  
                 projectionitem = self.AppendItem(mapitem, "Projection")  
                 for param in map.projection.params:  
                     parameteritem = self.AppendItem(projectionitem, str(param))  
                 self.Expand(projectionitem)  
   
             layers = map.Layers()  
             for layer_index in range(len(layers) - 1, -1, -1):  
                 layer = layers[layer_index]  
                 idata = wxTreeItemData()  
                 idata.SetData(layer)  
                 layeritem = self.AppendItem(mapitem,  
                                             "Layer '%s'" % layer.Title(),  
                                             data = idata)  
                 self.layer_to_item[id(layer)] = layeritem  
                 if layer is self.app.interactor.selected_layer:  
                     self.SelectItem(layeritem)  
                 if isinstance(layer, Layer):  
                     if layer.Visible():  
                         text = "Shown"  
                     else:  
                         text = "Hidden"  
                     self.AppendItem(layeritem, text)  
                     self.AppendItem(layeritem, "Shapes: %d" %layer.NumShapes())  
                     bbox = layer.LatLongBoundingBox()  
                     if bbox is not None:  
                         self.AppendItem(layeritem,  
                                         ("Extent (lat-lon): (%g, %g, %g, %g)"  
                                          % bbox))  
                     else:  
                         self.AppendItem(layeritem, ("Extent (lat-lon):"))  
                     self.AppendItem(layeritem,  
                                     "Shapetype: %s"  
                                     % shapetype_names[layer.ShapeType()])  
                     self.AppendItem(layeritem,  
                                     "Fill: " + color_string(layer.fill))  
                     self.AppendItem(layeritem,  
                                     "Outline: " + color_string(layer.stroke))  
                 self.Expand(layeritem)  
             self.Expand(mapitem)  
107          self.Expand(root)          self.Expand(root)
108            # select the selected layer
109            selected_layer = self.mainwindow.current_layer()
110            if selected_layer is not None:
111                # One would expect that the selected_layer's id is in
112                # layer_to_item at this point as we've just rebuilt that
113                # mapping completely. However, when a new session is loaded
114                # for instance, it can happen that the tree view is updated
115                # before the canvas's selection in which case selected_layer
116                # may be a layer of the old session.
117                item = self.layer_to_item.get(id(selected_layer))
118                if item is not None:
119                    self.SelectItem(item)
120    
121        def add_items(self, parent, items):
122    
123            if items is None: return
124    
125            for item in items:
126                if hasattr(item, "TreeInfo"):
127                    # Supports the TreeInfo protocol
128                    info = item.TreeInfo()
129                    treeitem = self.AppendItem(parent, info[0], -1, -1, None)
130                    self.SetItemImage(treeitem, self.emptyImageIndex)
131                    self.SetPyData(treeitem, item)
132                    self.add_items(treeitem, info[1])
133                    self.Expand(treeitem)
134                    if isinstance(item, Layer):
135                        self.layer_to_item[id(item)] = treeitem
136                elif isinstance(item, StringType) or \
137                     isinstance(item, UnicodeType):
138                    # it's a string
139                    treeitem = self.AppendItem(parent, item, -1, -1, None)
140                    self.SetItemImage(treeitem, self.emptyImageIndex)
141                else:
142                    # assume its a sequence (title, items)
143                    if isinstance(item[1], Color):
144    
145                        treeitem = self.AppendItem(parent, "(%s)" % item[0])
146    
147                        bmp = wxEmptyBitmap(BMP_SIZE, BMP_SIZE)
148                        brush = wxBrush(Color2wxColour(item[1]), wxSOLID)
149                        dc = wxMemoryDC()
150                        dc.SelectObject(bmp)
151                        dc.SetBrush(brush)
152                        dc.Clear()
153                        dc.DrawRoundedRectangle(0, 0,
154                                                bmp.GetWidth(), bmp.GetHeight(),
155                                                4)
156                        dc.SelectObject(wxNullBitmap)
157    
158                        i = self.image_list.Add(bmp)
159                        self.SetItemImage(treeitem, i)
160                    else:
161                        treeitem = self.AppendItem(parent, item[0], -1, -1, None)
162                        self.SetItemImage(treeitem, self.emptyImageIndex)
163                        self.add_items(treeitem, item[1])
164                    self.Expand(treeitem)
165    
166      def session_changed(self, *args):      def session_changed(self, *args):
167          new_session = self.app.session          new_session = self.app.session
168          # if the session has changed subscribe/unsubscribe          # if the session has changed subscribe/unsubscribe
169          if self.session is not new_session:          if self.session is not new_session:
170              if self.session is not None:              if self.session is not None:
171                  for channel in self.session_channels:                  self.session.Unsubscribe(CHANGED, self.update_tree)
                     self.session.Unsubscribe(channel, self.update_tree)  
172              if new_session is not None:              if new_session is not None:
173                  for channel in self.session_channels:                  new_session.Subscribe(CHANGED, self.update_tree)
                     new_session.Subscribe(channel, self.update_tree)  
174              self.session = new_session              self.session = new_session
175          self.update_tree()          self.update_tree()
176    
# Line 150  class SessionTreeCtrl(wxTreeCtrl): Line 182  class SessionTreeCtrl(wxTreeCtrl):
182              if isinstance(object, Layer) or isinstance(object, Map):              if isinstance(object, Layer) or isinstance(object, Map):
183                  break                  break
184              item = self.GetItemParent(item)              item = self.GetItemParent(item)
185            else:
186                # No layer or map was found in the chain of parents, so
187                # there's nothing we can do.
188                return
189    
190          self.changing_selection = 1          self.changing_selection = 1
191          try:          try:
# Line 172  class SessionTreeCtrl(wxTreeCtrl): Line 208  class SessionTreeCtrl(wxTreeCtrl):
208              return              return
209          self.normalize_selection()          self.normalize_selection()
210          # SelectedLayer returns None if no layer is selected. Since          # SelectedLayer returns None if no layer is selected. Since
211          # passing None to interactor.SelectLayer deselects the layer we          # passing None to SelectLayer deselects the layer we can simply
212          # can simply pass the result of SelectedLayer on in all cases          # pass the result of SelectedLayer on in all cases
213          self.app.interactor.SelectLayer(self.SelectedLayer())          self.mainwindow.SelectLayer(self.SelectedLayer())
214    
215      def layer_selected(self, layer):      def layer_selected(self, layer):
216          item = self.layer_to_item.get(id(layer))          item = self.layer_to_item.get(id(layer))
# Line 182  class SessionTreeCtrl(wxTreeCtrl): Line 218  class SessionTreeCtrl(wxTreeCtrl):
218              self.SelectItem(item)              self.SelectItem(item)
219    
220    
221  class SessionTreeView(NonModalDialog):  class SessionTreeView(NonModalNonParentDialog):
222    
223      """Non modal dialog showing the session as a tree"""      """Non modal dialog showing the session as a tree"""
224    
225      def __init__(self, parent, app, name):      def __init__(self, parent, app, name):
226          NonModalDialog.__init__(self, parent, app.interactor, name, "Session")          NonModalNonParentDialog.__init__(self, parent, name, _("Session"))
227          self.tree = SessionTreeCtrl(self, -1, app)          self.tree = SessionTreeCtrl(self, -1, parent, app)
228    
229      def OnClose(self, event):      def OnClose(self, event):
230          #self.interactor.Unsubscribe(SELECTED_SHAPE, self.select_shape)          NonModalNonParentDialog.OnClose(self, event)
         NonModalDialog.OnClose(self, event)  
231    
232          # if there were a way to get notified when the tree control          # if there were a way to get notified when the tree control
233          # itself is destroyed we could use that to unsubscribe instead          # itself is destroyed we could use that to unsubscribe instead
234          # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at          # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at
235          # all)          # all)
236          self.tree.unsubscribe_all()          self.tree.unsubscribe_all()
237    

Legend:
Removed from v.177  
changed lines
  Added in v.1766

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26