/[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 6 by bh, Tue Aug 28 15:41:52 2001 UTC revision 383 by jonathan, Tue Jan 28 18:38:03 2003 UTC
# Line 1  Line 1 
1  #! /usr/bin/python  #! /usr/bin/python
2  # Copyright (c) 2001 by Intevation GmbH  # Copyright (c) 2001, 2002 by Intevation GmbH
3  # Authors:  # Authors:
4  # Jan-Oliver Wagner <[email protected]>  # Jan-Oliver Wagner <[email protected]>
5  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
# Line 9  Line 9 
9    
10  __version__ = "$Revision$"  __version__ = "$Revision$"
11    
12    from types import StringType, UnicodeType
13    
14  from wxPython.wx import *  from wxPython.wx import *
15    
16  from Thuban.Model.messages import MAPS_CHANGED, MAP_PROJECTION_CHANGED, \  from Thuban import _
17       LAYERS_CHANGED, LAYER_LEGEND_CHANGED, LAYER_VISIBILITY_CHANGED  
18  from Thuban.Model.layer import Layer, shapetype_names  from Thuban.Model.color import Color
19    
20    from Thuban.Model.messages import CHANGED
21    from Thuban.Model.layer import Layer
22  from Thuban.Model.map import Map  from Thuban.Model.map import Map
 import view  
23    
24    from dialogs import NonModalDialog
25  from messages import SESSION_CHANGED, SELECTED_LAYER  from messages import SESSION_CHANGED, SELECTED_LAYER
26    
27  def color_string(color):  BMP_SIZE = 15
28      if color is None:  
29          return "None"  class SessionTreeCtrl(wxTreeCtrl):
30      return "(%.3f, %.3f, %.3f)" % (color.red, color.green, color.blue)  
31        """Widget to display a tree view of the session.
32    
33        The tree view is created recursively from the session object. The
34        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  class myTreeCtrlPanel(wxPanel):      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, app):
52    
     def __init__(self, parent, 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          wxPanel.__init__(self, parent, -1, style=wxWANTS_CHARS)          wxTreeCtrl.__init__(self, parent, ID)
55    
56          self.app = app          self.app = app
57            # boolean to indicate that we manipulate the selection ourselves
58            # so that we can ignore the selection events generated
59            self.changing_selection = 0
60    
61          EVT_SIZE(self, self.OnSize)          # Dictionary mapping layer id's to tree items
62          self.tree = wxTreeCtrl(self, -1)          self.layer_to_item = {}
63    
64          self.app.Subscribe(SESSION_CHANGED, self.session_changed)          self.app.Subscribe(SESSION_CHANGED, self.session_changed)
65          self.app.interactor.Subscribe(SELECTED_LAYER, self.layer_selected)          self.app.interactor.Subscribe(SELECTED_LAYER, self.layer_selected)
66    
67            # the session currently displayed in the tree
68            self.session = None
69    
70            self.image_list = wxImageList(BMP_SIZE, BMP_SIZE)
71            self.AssignImageList(self.image_list)
72    
73          # pretend the session has changed to build the initial tree          # pretend the session has changed to build the initial tree
74          self.session_changed()          self.session_changed()
75    
76          EVT_TREE_SEL_CHANGED(self, self.tree.GetId(), self.OnSelChanged)          EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
77    
78        def unsubscribe_all(self):
79            if self.session is not None:
80                self.session.Unsubscribe(CHANGED, self.update_tree)
81                self.session = None
82            self.app.Unsubscribe(SESSION_CHANGED, self.session_changed)
83            self.app.interactor.Unsubscribe(SELECTED_LAYER, self.layer_selected)
84    
85      def update_tree(self, *args):      def update_tree(self, *args):
86          """Clear and rebuild the tree"""          """Clear and rebuild the tree"""
87          self.tree.DeleteAllItems()          self.DeleteAllItems()
88            self.layer_to_item.clear()
89    
90          session = self.app.session          session = self.app.session
91          root = self.tree.AddRoot("Session: %s" % session.title)          info = session.TreeInfo()
92          for map in session.Maps():          root = self.AddRoot(info[0])
93              mapitem = self.tree.AppendItem(root, "Map: %s" % map.title)          self.add_items(root, info[1])
94              self.tree.SetPyData(mapitem, map)          self.Expand(root)
95              if map.projection and len(map.projection.params) > 0:          # select the selected layer
96                  projectionitem = self.tree.AppendItem(mapitem, "Projection")          selected_layer = self.app.interactor.selected_layer
97                  for param in map.projection.params:          if selected_layer is not None:
98                      parameteritem = self.tree.AppendItem(projectionitem,              # One would expect that the selected_layer's id is in
99                                                           str(param))              # layer_to_item at this point as we've just rebuilt that
100                  self.tree.Expand(projectionitem)              # mapping completely. However, when a new session is loaded
101                # for instance, it can happen that the tree view is updated
102              layers = map.Layers()              # before the interactor in which case selected_layer may be
103              for layer_index in range(len(layers) - 1, -1, -1):              # a layer of the old session.
104                  layer = layers[layer_index]              item = self.layer_to_item.get(id(selected_layer))
105                  idata = wxTreeItemData()              if item is not None:
106                  idata.SetData(layer)                  self.SelectItem(item)
107                  layeritem = self.tree.AppendItem(mapitem,  
108                                                   "Layer '%s'" % layer.Title(),      def add_items(self, parent, items):
109                                                   data = idata)          # print "\n---\n", items
110                  if layer is self.app.interactor.selected_layer:  
111                      self.tree.SelectItem(layeritem)          if items is None: return
112                  if isinstance(layer, Layer):  
113                      if layer.Visible():          for item in items:
114                          text = "Shown"              if hasattr(item, "TreeInfo"):
115                      else:                  # Supports the TreeInfo protocol
116                          text = "Hidden"                  info = item.TreeInfo()
117                      self.tree.AppendItem(layeritem, text)                  treeitem = self.AppendItem(parent, info[0])
118                      self.tree.AppendItem(layeritem,                  self.SetPyData(treeitem, item)
119                                           "Shapes: %d" % layer.NumShapes())                  self.add_items(treeitem, info[1])
120                      self.tree.AppendItem(layeritem,                  self.Expand(treeitem)
121                                           ("Extents: (%g, %g, %g, %g)"                  if isinstance(item, Layer):
122                                            % layer.LatLongBoundingBox()))                      self.layer_to_item[id(item)] = treeitem
123                      self.tree.AppendItem(layeritem,              elif isinstance(item, StringType) or \
124                                           "Shapetype: %s" %                   isinstance(item, UnicodeType):
125                                           shapetype_names[layer.ShapeType()])                  # it's a string
126                      self.tree.AppendItem(layeritem,                  self.AppendItem(parent, item)
127                                           "Fill: " + color_string(layer.fill))              else:
128                      self.tree.AppendItem(layeritem,                  # assume its a sequence (title, items)
129                                        "Outline: " + color_string(layer.stroke))                  if isinstance(item[1], Color):
130                  self.tree.Expand(layeritem)                      treeitem = self.AppendItem(parent, _("(%s)") % item[0])
131              self.tree.Expand(mapitem)  
132          self.tree.Expand(root)                      bmp = wxEmptyBitmap(BMP_SIZE, BMP_SIZE)
133                        brush = wxBrush(wxColour(item[1].red * 255,
134                                                 item[1].green * 255,
135                                                 item[1].blue * 255),
136                                        wxSOLID)
137                        dc = wxMemoryDC()
138                        dc.SelectObject(bmp)
139                        dc.SetBrush(brush)
140                        dc.Clear()
141                        dc.DrawRoundedRectangle(0, 0,
142                                                bmp.GetWidth(), bmp.GetHeight(),
143                                                4)
144                        dc.SelectObject(wxNullBitmap)
145    
146                        i = self.image_list.Add(bmp)
147                        self.SetItemImage(treeitem, i)
148                    else:
149                        treeitem = self.AppendItem(parent, item[0])
150                        self.add_items(treeitem, item[1])
151                    self.Expand(treeitem)
152    
153      def session_changed(self, *args):      def session_changed(self, *args):
154          for channel in (MAPS_CHANGED,          new_session = self.app.session
155                          MAP_PROJECTION_CHANGED,          # if the session has changed subscribe/unsubscribe
156                          LAYERS_CHANGED,          if self.session is not new_session:
157                          LAYER_LEGEND_CHANGED,              if self.session is not None:
158                          LAYER_VISIBILITY_CHANGED):                  self.session.Unsubscribe(CHANGED, self.update_tree)
159              self.app.session.Subscribe(channel, self.update_tree)              if new_session is not None:
160                    new_session.Subscribe(CHANGED, self.update_tree)
161                self.session = new_session
162          self.update_tree()          self.update_tree()
163    
     def OnSize(self, event):  
         w,h = self.GetClientSizeTuple()  
         self.tree.SetDimensions(0, 0, w, h)  
   
164      def normalize_selection(self):      def normalize_selection(self):
165          """Select the layer or map containing currently selected item"""          """Select the layer or map containing currently selected item"""
166          tree = self.tree          item = self.GetSelection()
         item = self.tree.GetSelection()  
167          while item.IsOk():          while item.IsOk():
168              object = tree.GetPyData(item)              object = self.GetPyData(item)
169              if isinstance(object, Layer) or isinstance(object, Map):              if isinstance(object, Layer) or isinstance(object, Map):
170                  break                  break
171              item = tree.GetItemParent(item)              item = self.GetItemParent(item)
172            else:
173          self.tree.SelectItem(item)              # No layer or map was found in the chain of parents, so
174                # there's nothing we can do.
175                return
176    
177            self.changing_selection = 1
178            try:
179                self.SelectItem(item)
180            finally:
181                self.changing_selection = 0
182    
183      def SelectedLayer(self):      def SelectedLayer(self):
184          """Return the layer object currently selected in the tree.          """Return the layer object currently selected in the tree.
185          Return None if no layer is selected"""          Return None if no layer is selected"""
186          tree = self.tree          layer = self.GetPyData(self.GetSelection())
         layer = tree.GetPyData(tree.GetSelection())  
187          if isinstance(layer, Layer):          if isinstance(layer, Layer):
188              return layer              return layer
189          return None          return None
190    
191      def OnSelChanged(self, event):      def OnSelChanged(self, event):
192            if self.changing_selection:
193                # we're changing the selection ourselves (probably through
194                # self.normalize_selection(). ignore the event.
195                return
196          self.normalize_selection()          self.normalize_selection()
197          layer = self.SelectedLayer()          # SelectedLayer returns None if no layer is selected. Since
198          if layer is not None:          # passing None to interactor.SelectLayer deselects the layer we
199              self.app.interactor.SelectLayer(layer)          # can simply pass the result of SelectedLayer on in all cases
200            self.app.interactor.SelectLayer(self.SelectedLayer())
201    
202      def layer_selected(self, layer):      def layer_selected(self, layer):
203          pass          item = self.layer_to_item.get(id(layer))
204            if item is not None and item != self.GetSelection():
205                self.SelectItem(item)
206    
207    
208    class SessionTreeView(NonModalDialog):
209    
210        """Non modal dialog showing the session as a tree"""
211    
212        def __init__(self, parent, app, name):
213            NonModalDialog.__init__(self, parent, app.interactor, name,
214                                    _("Session"))
215            self.tree = SessionTreeCtrl(self, -1, app)
216    
217        def OnClose(self, event):
218            #self.interactor.Unsubscribe(SELECTED_SHAPE, self.select_shape)
219            NonModalDialog.OnClose(self, event)
220    
221            # if there were a way to get notified when the tree control
222            # itself is destroyed we could use that to unsubscribe instead
223            # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at
224            # all)
225            self.tree.unsubscribe_all()

Legend:
Removed from v.6  
changed lines
  Added in v.383

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26