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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26