/[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 41 by bh, Thu Sep 6 18:58:46 2001 UTC revision 488 by jonathan, Fri Mar 7 18:21:25 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
24    
25  from dialogs import NonModalDialog  from dialogs import NonModalDialog
26  from messages import SESSION_CHANGED, SELECTED_LAYER  from messages import SESSION_CHANGED, SELECTED_LAYER
27    
28  def color_string(color):  BMP_SIZE = 15
     if color is None:  
         return "None"  
     return "(%.3f, %.3f, %.3f)" % (color.red, color.green, color.blue)  
   
29    
30  class SessionTreeCtrl(wxTreeCtrl):  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        The items list can contain three types of items:
41    
42           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):      def __init__(self, parent, ID, app):
53    
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          wxTreeCtrl.__init__(self, parent, ID)          wxTreeCtrl.__init__(self, parent, ID)
56    
# Line 41  class SessionTreeCtrl(wxTreeCtrl): Line 64  class SessionTreeCtrl(wxTreeCtrl):
64    
65          self.app.Subscribe(SESSION_CHANGED, self.session_changed)          self.app.Subscribe(SESSION_CHANGED, 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            self.image_list = wxImageList(BMP_SIZE, BMP_SIZE)
72            self.AssignImageList(self.image_list)
73    
74          # pretend the session has changed to build the initial tree          # pretend the session has changed to build the initial tree
75          self.session_changed()          self.session_changed()
76    
77          EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)          EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
78    
79        def unsubscribe_all(self):
80            if self.session is not None:
81                self.session.Unsubscribe(CHANGED, self.update_tree)
82                self.session = None
83            self.app.Unsubscribe(SESSION_CHANGED, self.session_changed)
84            self.app.interactor.Unsubscribe(SELECTED_LAYER, self.layer_selected)
85    
86      def update_tree(self, *args):      def update_tree(self, *args):
87          """Clear and rebuild the tree"""          """Clear and rebuild the tree"""
88          self.DeleteAllItems()          self.DeleteAllItems()
         session = self.app.session  
         root = self.AddRoot("Session: %s" % session.title)  
89          self.layer_to_item.clear()          self.layer_to_item.clear()
90          for map in session.Maps():  
91              mapitem = self.AppendItem(root, "Map: %s" % map.title)          session = self.app.session
92              self.SetPyData(mapitem, map)          info = session.TreeInfo()
93              if map.projection and len(map.projection.params) > 0:          root = self.AddRoot(info[0])
94                  projectionitem = self.AppendItem(mapitem, "Projection")          self.add_items(root, info[1])
                 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())  
                     self.AppendItem(layeritem, ("Extents: (%g, %g, %g, %g)"  
                                                 % layer.LatLongBoundingBox()))  
                     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)  
95          self.Expand(root)          self.Expand(root)
96            # select the selected layer
97            selected_layer = self.app.interactor.selected_layer
98            if selected_layer is not None:
99                # One would expect that the selected_layer's id is in
100                # layer_to_item at this point as we've just rebuilt that
101                # mapping completely. However, when a new session is loaded
102                # for instance, it can happen that the tree view is updated
103                # before the interactor in which case selected_layer may be
104                # a layer of the old session.
105                item = self.layer_to_item.get(id(selected_layer))
106                if item is not None:
107                    self.SelectItem(item)
108    
109        def add_items(self, parent, items):
110    
111            if items is None: return
112    
113            for item in items:
114                if hasattr(item, "TreeInfo"):
115                    # Supports the TreeInfo protocol
116                    info = item.TreeInfo()
117                    treeitem = self.AppendItem(parent, info[0])
118                    self.SetPyData(treeitem, item)
119                    self.add_items(treeitem, info[1])
120                    self.Expand(treeitem)
121                    if isinstance(item, Layer):
122                        self.layer_to_item[id(item)] = treeitem
123                elif isinstance(item, StringType) or \
124                     isinstance(item, UnicodeType):
125                    # it's a string
126                    self.AppendItem(parent, item)
127                else:
128                    # assume its a sequence (title, items)
129                    if isinstance(item[1], Color):
130    
131                        treeitem = self.AppendItem(parent, "(%s)" % item[0])
132    
133                        bmp = wxEmptyBitmap(BMP_SIZE, BMP_SIZE)
134                        brush = wxBrush(Color2wxColour(item[1]), wxSOLID)
135                        dc = wxMemoryDC()
136                        dc.SelectObject(bmp)
137                        dc.SetBrush(brush)
138                        dc.Clear()
139                        dc.DrawRoundedRectangle(0, 0,
140                                                bmp.GetWidth(), bmp.GetHeight(),
141                                                4)
142                        dc.SelectObject(wxNullBitmap)
143    
144                        i = self.image_list.Add(bmp)
145                        self.SetItemImage(treeitem, i)
146                    else:
147                        treeitem = self.AppendItem(parent, item[0])
148                        self.add_items(treeitem, item[1])
149                    self.Expand(treeitem)
150    
151      def session_changed(self, *args):      def session_changed(self, *args):
152          for channel in (MAPS_CHANGED,          new_session = self.app.session
153                          MAP_PROJECTION_CHANGED,          # if the session has changed subscribe/unsubscribe
154                          LAYERS_CHANGED,          if self.session is not new_session:
155                          LAYER_LEGEND_CHANGED,              if self.session is not None:
156                          LAYER_VISIBILITY_CHANGED):                  self.session.Unsubscribe(CHANGED, self.update_tree)
157              self.app.session.Subscribe(channel, self.update_tree)              if new_session is not None:
158                    new_session.Subscribe(CHANGED, self.update_tree)
159                self.session = new_session
160          self.update_tree()          self.update_tree()
161    
162      def normalize_selection(self):      def normalize_selection(self):
# Line 109  class SessionTreeCtrl(wxTreeCtrl): Line 167  class SessionTreeCtrl(wxTreeCtrl):
167              if isinstance(object, Layer) or isinstance(object, Map):              if isinstance(object, Layer) or isinstance(object, Map):
168                  break                  break
169              item = self.GetItemParent(item)              item = self.GetItemParent(item)
170            else:
171                # No layer or map was found in the chain of parents, so
172                # there's nothing we can do.
173                return
174    
175          self.changing_selection = 1          self.changing_selection = 1
176          try:          try:
# Line 130  class SessionTreeCtrl(wxTreeCtrl): Line 192  class SessionTreeCtrl(wxTreeCtrl):
192              # self.normalize_selection(). ignore the event.              # self.normalize_selection(). ignore the event.
193              return              return
194          self.normalize_selection()          self.normalize_selection()
195          layer = self.SelectedLayer()          # SelectedLayer returns None if no layer is selected. Since
196          if layer is not None:          # passing None to interactor.SelectLayer deselects the layer we
197              self.app.interactor.SelectLayer(layer)          # can simply pass the result of SelectedLayer on in all cases
198            self.app.interactor.SelectLayer(self.SelectedLayer())
199    
200      def layer_selected(self, layer):      def layer_selected(self, layer):
201          item = self.layer_to_item.get(id(layer))          item = self.layer_to_item.get(id(layer))
# Line 145  class SessionTreeView(NonModalDialog): Line 208  class SessionTreeView(NonModalDialog):
208      """Non modal dialog showing the session as a tree"""      """Non modal dialog showing the session as a tree"""
209    
210      def __init__(self, parent, app, name):      def __init__(self, parent, app, name):
211          NonModalDialog.__init__(self, parent, app.interactor, name, "Session")          NonModalDialog.__init__(self, parent, app.interactor, name,
212                                    _("Session"))
213          self.tree = SessionTreeCtrl(self, -1, app)          self.tree = SessionTreeCtrl(self, -1, app)
214    
215      def OnClose(self, event):      def Shutdown(self):
216          #self.interactor.Unsubscribe(SELECTED_SHAPE, self.select_shape)          # if there were a way to get notified when the tree control
217          NonModalDialog.OnClose(self, event)          # itself is destroyed we could use that to unsubscribe instead
218            # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at
219            # all)
220            self.tree.unsubscribe_all()
221    
222            # this needs to come last because Destroy will be called
223            NonModalDialog.Shutdown(self)
224    

Legend:
Removed from v.41  
changed lines
  Added in v.488

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26