/[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 1058 by frank, Tue May 27 11:30:29 2003 UTC
# Line 1  Line 1 
1  #! /usr/bin/python  #! /usr/bin/python
2  # Copyright (c) 2001 by Intevation GmbH  # Copyright (c) 2001, 2002, 2003 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 Color2wxColour
18  from Thuban.Model.layer import Layer, shapetype_names  
19  from Thuban.Model.map import Map  from Thuban.Model.color import Color
20    
21  from dialogs import NonModalDialog  from Thuban.Model.messages import CHANGED
22  from messages import SESSION_CHANGED, SELECTED_LAYER  from Thuban.Model.layer import Layer
23    from Thuban.Model.map import Map
24    
25  def color_string(color):  from dialogs import NonModalNonParentDialog
26      if color is None:  from messages import SESSION_REPLACED, LAYER_SELECTED
         return "None"  
     return "(%.3f, %.3f, %.3f)" % (color.red, color.green, color.blue)  
27    
28    BMP_SIZE = 15
29    
30  class SessionTreeCtrl(wxTreeCtrl):  class SessionTreeCtrl(wxTreeCtrl):
31    
32      def __init__(self, parent, ID, app):      """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, mainwindow, 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    
57            self.mainwindow = mainwindow
58          self.app = app          self.app = app
59          # boolean to indicate that we manipulate the selection ourselves          # boolean to indicate that we manipulate the selection ourselves
60          # so that we can ignore the selection events generated          # so that we can ignore the selection events generated
# Line 39  class SessionTreeCtrl(wxTreeCtrl): Line 63  class SessionTreeCtrl(wxTreeCtrl):
63          # Dictionary mapping layer id's to tree items          # Dictionary mapping layer id's to tree items
64          self.layer_to_item = {}          self.layer_to_item = {}
65    
66          self.app.Subscribe(SESSION_CHANGED, self.session_changed)          self.app.Subscribe(SESSION_REPLACED, self.session_changed)
67          self.app.interactor.Subscribe(SELECTED_LAYER, self.layer_selected)          self.mainwindow.Subscribe(LAYER_SELECTED, self.layer_selected)
68    
69            # the session currently displayed in the tree
70            self.session = None
71    
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.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_REPLACED, self.session_changed)
83            self.mainwindow.Unsubscribe(LAYER_SELECTED, 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.DeleteAllItems()          self.DeleteAllItems()
         session = self.app.session  
         root = self.AddRoot("Session: %s" % session.title)  
88          self.layer_to_item.clear()          self.layer_to_item.clear()
89          for map in session.Maps():          self.image_list = wxImageList(BMP_SIZE, BMP_SIZE, False, 0)
90              mapitem = self.AppendItem(root, "Map: %s" % map.title)  
91              self.SetPyData(mapitem, map)          bmp = wxEmptyBitmap(BMP_SIZE, BMP_SIZE)
92              if map.projection and len(map.projection.params) > 0:          dc = wxMemoryDC()
93                  projectionitem = self.AppendItem(mapitem, "Projection")          dc.SelectObject(bmp)
94                  for param in map.projection.params:          dc.SetBrush(wxBLACK_BRUSH)
95                      parameteritem = self.AppendItem(projectionitem, str(param))          dc.Clear()
96                  self.Expand(projectionitem)          dc.SelectObject(wxNullBitmap)
97    
98              layers = map.Layers()          self.emptyImageIndex = \
99              for layer_index in range(len(layers) - 1, -1, -1):              self.image_list.AddWithColourMask(bmp, wxColour(0, 0, 0))
100                  layer = layers[layer_index]  
101                  idata = wxTreeItemData()          self.AssignImageList(self.image_list)
102                  idata.SetData(layer)  
103                  layeritem = self.AppendItem(mapitem,          session = self.app.session
104                                              "Layer '%s'" % layer.Title(),          info = session.TreeInfo()
105                                              data = idata)          root = self.AddRoot(info[0], -1, -1, None)
106                  self.layer_to_item[id(layer)] = layeritem          self.SetItemImage(root, self.emptyImageIndex)
107                  if layer is self.app.interactor.selected_layer:          self.add_items(root, info[1])
                     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)  
108          self.Expand(root)          self.Expand(root)
109            # select the selected layer
110            selected_layer = self.mainwindow.current_layer()
111            if selected_layer is not None:
112                # One would expect that the selected_layer's id is in
113                # layer_to_item at this point as we've just rebuilt that
114                # mapping completely. However, when a new session is loaded
115                # for instance, it can happen that the tree view is updated
116                # before the canvas's selection in which case selected_layer
117                # may be a layer of the old session.
118                item = self.layer_to_item.get(id(selected_layer))
119                if item is not None:
120                    self.SelectItem(item)
121    
122        def add_items(self, parent, items):
123    
124            if items is None: return
125    
126            for item in items:
127                if hasattr(item, "TreeInfo"):
128                    # Supports the TreeInfo protocol
129                    info = item.TreeInfo()
130                    treeitem = self.AppendItem(parent, info[0], -1, -1, None)
131                    self.SetItemImage(treeitem, self.emptyImageIndex)
132                    self.SetPyData(treeitem, item)
133                    self.add_items(treeitem, info[1])
134                    self.Expand(treeitem)
135                    if isinstance(item, Layer):
136                        self.layer_to_item[id(item)] = treeitem
137                elif isinstance(item, StringType) or \
138                     isinstance(item, UnicodeType):
139                    # it's a string
140                    treeitem = self.AppendItem(parent, item, -1, -1, None)
141                    self.SetItemImage(treeitem, self.emptyImageIndex)
142                else:
143                    # assume its a sequence (title, items)
144                    if isinstance(item[1], Color):
145    
146                        treeitem = self.AppendItem(parent, "(%s)" % item[0])
147    
148                        bmp = wxEmptyBitmap(BMP_SIZE, BMP_SIZE)
149                        brush = wxBrush(Color2wxColour(item[1]), wxSOLID)
150                        dc = wxMemoryDC()
151                        dc.SelectObject(bmp)
152                        dc.SetBrush(brush)
153                        dc.Clear()
154                        dc.DrawRoundedRectangle(0, 0,
155                                                bmp.GetWidth(), bmp.GetHeight(),
156                                                4)
157                        dc.SelectObject(wxNullBitmap)
158    
159                        i = self.image_list.Add(bmp)
160                        self.SetItemImage(treeitem, i)
161                    else:
162                        treeitem = self.AppendItem(parent, item[0], -1, -1, None)
163                        self.SetItemImage(treeitem, self.emptyImageIndex)
164                        self.add_items(treeitem, item[1])
165                    self.Expand(treeitem)
166    
167      def session_changed(self, *args):      def session_changed(self, *args):
168          for channel in (MAPS_CHANGED,          new_session = self.app.session
169                          MAP_PROJECTION_CHANGED,          # if the session has changed subscribe/unsubscribe
170                          LAYERS_CHANGED,          if self.session is not new_session:
171                          LAYER_LEGEND_CHANGED,              if self.session is not None:
172                          LAYER_VISIBILITY_CHANGED):                  self.session.Unsubscribe(CHANGED, self.update_tree)
173              self.app.session.Subscribe(channel, self.update_tree)              if new_session is not None:
174                    new_session.Subscribe(CHANGED, self.update_tree)
175                self.session = new_session
176          self.update_tree()          self.update_tree()
177    
178      def normalize_selection(self):      def normalize_selection(self):
# Line 109  class SessionTreeCtrl(wxTreeCtrl): Line 183  class SessionTreeCtrl(wxTreeCtrl):
183              if isinstance(object, Layer) or isinstance(object, Map):              if isinstance(object, Layer) or isinstance(object, Map):
184                  break                  break
185              item = self.GetItemParent(item)              item = self.GetItemParent(item)
186            else:
187                # No layer or map was found in the chain of parents, so
188                # there's nothing we can do.
189                return
190    
191          self.changing_selection = 1          self.changing_selection = 1
192          try:          try:
# Line 130  class SessionTreeCtrl(wxTreeCtrl): Line 208  class SessionTreeCtrl(wxTreeCtrl):
208              # self.normalize_selection(). ignore the event.              # self.normalize_selection(). ignore the event.
209              return              return
210          self.normalize_selection()          self.normalize_selection()
211          layer = self.SelectedLayer()          # SelectedLayer returns None if no layer is selected. Since
212          if layer is not None:          # passing None to SelectLayer deselects the layer we can simply
213              self.app.interactor.SelectLayer(layer)          # pass the result of SelectedLayer on in all cases
214            self.mainwindow.SelectLayer(self.SelectedLayer())
215    
216      def layer_selected(self, layer):      def layer_selected(self, layer):
217          item = self.layer_to_item.get(id(layer))          item = self.layer_to_item.get(id(layer))
# Line 140  class SessionTreeCtrl(wxTreeCtrl): Line 219  class SessionTreeCtrl(wxTreeCtrl):
219              self.SelectItem(item)              self.SelectItem(item)
220    
221    
222  class SessionTreeView(NonModalDialog):  class SessionTreeView(NonModalNonParentDialog):
223    
224      """Non modal dialog showing the session as a tree"""      """Non modal dialog showing the session as a tree"""
225    
226      def __init__(self, parent, app, name):      def __init__(self, parent, app, name):
227          NonModalDialog.__init__(self, parent, app.interactor, name, "Session")          NonModalNonParentDialog.__init__(self, parent, name, _("Session"))
228          self.tree = SessionTreeCtrl(self, -1, app)          self.tree = SessionTreeCtrl(self, -1, parent, app)
229    
230      def OnClose(self, event):      def OnClose(self, event):
231          #self.interactor.Unsubscribe(SELECTED_SHAPE, self.select_shape)          NonModalNonParentDialog.OnClose(self, event)
232          NonModalDialog.OnClose(self, event)  
233            # if there were a way to get notified when the tree control
234            # itself is destroyed we could use that to unsubscribe instead
235            # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at
236            # all)
237            self.tree.unsubscribe_all()
238    

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26