/[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 217 by bh, Wed Jul 17 10:50:40 2002 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
13    
14  from wxPython.wx import *  from wxPython.wx import *
15    
16  from Thuban.Model.messages import MAPS_CHANGED, MAP_PROJECTION_CHANGED, \  from Thuban.Model.messages import MAPS_CHANGED, MAP_PROJECTION_CHANGED, \
17       LAYERS_CHANGED, LAYER_LEGEND_CHANGED, LAYER_VISIBILITY_CHANGED       LAYERS_CHANGED, LAYER_LEGEND_CHANGED, LAYER_VISIBILITY_CHANGED, \
18         EXTENSIONS_CHANGED, EXTENSION_OBJECTS_CHANGED
19  from Thuban.Model.layer import Layer, shapetype_names  from Thuban.Model.layer import Layer, shapetype_names
20  from Thuban.Model.map import Map  from Thuban.Model.map import Map
 import view  
21    
22    from dialogs import NonModalDialog
23  from messages import SESSION_CHANGED, SELECTED_LAYER  from messages import SESSION_CHANGED, SELECTED_LAYER
24    
 def color_string(color):  
     if color is None:  
         return "None"  
     return "(%.3f, %.3f, %.3f)" % (color.red, color.green, color.blue)  
25    
26  class myTreeCtrlPanel(wxPanel):  class SessionTreeCtrl(wxTreeCtrl):
27    
28        """Widget to display a tree view of the session.
29    
30        The tree view is created recursively from the session object. The
31        tree view calls the session's TreeInfo method which should return a
32        pair (<title>, <item>) where <title> ist the title of the session
33        item in the tree view and <items> is a list of objects to use as the
34        children of the session in the tree view.
35    
36        The items list can contain three types of items:
37    
38           1. a string. The string is used as the title for a leaf item in
39              the tree view.
40    
41      def __init__(self, parent, app):         2. an object with a TreeInfo method. This method is called and
42              should return a pair just like the session's TreeInfo method.
43    
44           3. a pair (<title>, <item>) which is treated like the return
45              value of TreeInfo.
46        """
47    
48        # the session channels to subscribe to update the tree
49        session_channels = (MAPS_CHANGED, MAP_PROJECTION_CHANGED,
50                            LAYERS_CHANGED, LAYER_LEGEND_CHANGED,
51                            LAYER_VISIBILITY_CHANGED, EXTENSIONS_CHANGED,
52                            EXTENSION_OBJECTS_CHANGED)
53    
54        def __init__(self, parent, ID, app):
55          # 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.
56          wxPanel.__init__(self, parent, -1, style=wxWANTS_CHARS)          wxTreeCtrl.__init__(self, parent, ID)
57    
58          self.app = app          self.app = app
59            # boolean to indicate that we manipulate the selection ourselves
60            # so that we can ignore the selection events generated
61            self.changing_selection = 0
62    
63          EVT_SIZE(self, self.OnSize)          # Dictionary mapping layer id's to tree items
64          self.tree = wxTreeCtrl(self, -1)          self.layer_to_item = {}
65    
66          self.app.Subscribe(SESSION_CHANGED, self.session_changed)          self.app.Subscribe(SESSION_CHANGED, self.session_changed)
67          self.app.interactor.Subscribe(SELECTED_LAYER, self.layer_selected)          self.app.interactor.Subscribe(SELECTED_LAYER, self.layer_selected)
68    
69            # the session currently displayed in the tree
70            self.session = None
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                for channel in self.session_channels:
80                    self.session.Unsubscribe(channel, 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,              self.SelectItem(self.layer_to_item[id(selected_layer)])
99                                                           str(param))  
100                  self.tree.Expand(projectionitem)      def add_items(self, parent, items):
101            for item in items:
102              layers = map.Layers()              if hasattr(item, "TreeInfo"):
103              for layer_index in range(len(layers) - 1, -1, -1):                  # Supports the TreeInfo protocol
104                  layer = layers[layer_index]                  info = item.TreeInfo()
105                  idata = wxTreeItemData()                  treeitem = self.AppendItem(parent, info[0])
106                  idata.SetData(layer)                  self.SetPyData(treeitem, item)
107                  layeritem = self.tree.AppendItem(mapitem,                  self.add_items(treeitem, info[1])
108                                                   "Layer '%s'" % layer.Title(),                  self.Expand(treeitem)
109                                                   data = idata)                  if isinstance(item, Layer):
110                  if layer is self.app.interactor.selected_layer:                      self.layer_to_item[id(item)] = treeitem
111                      self.tree.SelectItem(layeritem)              elif isinstance(item, StringType):
112                  if isinstance(layer, Layer):                  # it's a string
113                      if layer.Visible():                  # FIXME: What to do about UNICODE
114                          text = "Shown"                  self.AppendItem(parent, item)
115                      else:              else:
116                          text = "Hidden"                  # assume its a sequence (title, items)
117                      self.tree.AppendItem(layeritem, text)                  treeitem = self.AppendItem(parent, item[0])
118                      self.tree.AppendItem(layeritem,                  self.add_items(treeitem, item[1])
119                                           "Shapes: %d" % layer.NumShapes())                  self.Expand(treeitem)
                     self.tree.AppendItem(layeritem,  
                                          ("Extents: (%g, %g, %g, %g)"  
                                           % layer.LatLongBoundingBox()))  
                     self.tree.AppendItem(layeritem,  
                                          "Shapetype: %s" %  
                                          shapetype_names[layer.ShapeType()])  
                     self.tree.AppendItem(layeritem,  
                                          "Fill: " + color_string(layer.fill))  
                     self.tree.AppendItem(layeritem,  
                                       "Outline: " + color_string(layer.stroke))  
                 self.tree.Expand(layeritem)  
             self.tree.Expand(mapitem)  
         self.tree.Expand(root)  
120    
121      def session_changed(self, *args):      def session_changed(self, *args):
122          for channel in (MAPS_CHANGED,          new_session = self.app.session
123                          MAP_PROJECTION_CHANGED,          # if the session has changed subscribe/unsubscribe
124                          LAYERS_CHANGED,          if self.session is not new_session:
125                          LAYER_LEGEND_CHANGED,              if self.session is not None:
126                          LAYER_VISIBILITY_CHANGED):                  for channel in self.session_channels:
127              self.app.session.Subscribe(channel, self.update_tree)                      self.session.Unsubscribe(channel, self.update_tree)
128                if new_session is not None:
129                    for channel in self.session_channels:
130                        new_session.Subscribe(channel, self.update_tree)
131                self.session = new_session
132          self.update_tree()          self.update_tree()
133    
     def OnSize(self, event):  
         w,h = self.GetClientSizeTuple()  
         self.tree.SetDimensions(0, 0, w, h)  
   
134      def normalize_selection(self):      def normalize_selection(self):
135          """Select the layer or map containing currently selected item"""          """Select the layer or map containing currently selected item"""
136          tree = self.tree          item = self.GetSelection()
         item = self.tree.GetSelection()  
137          while item.IsOk():          while item.IsOk():
138              object = tree.GetPyData(item)              object = self.GetPyData(item)
139              if isinstance(object, Layer) or isinstance(object, Map):              if isinstance(object, Layer) or isinstance(object, Map):
140                  break                  break
141              item = tree.GetItemParent(item)              item = self.GetItemParent(item)
142    
143          self.tree.SelectItem(item)          self.changing_selection = 1
144            try:
145                self.SelectItem(item)
146            finally:
147                self.changing_selection = 0
148    
149      def SelectedLayer(self):      def SelectedLayer(self):
150          """Return the layer object currently selected in the tree.          """Return the layer object currently selected in the tree.
151          Return None if no layer is selected"""          Return None if no layer is selected"""
152          tree = self.tree          layer = self.GetPyData(self.GetSelection())
         layer = tree.GetPyData(tree.GetSelection())  
153          if isinstance(layer, Layer):          if isinstance(layer, Layer):
154              return layer              return layer
155          return None          return None
156    
157      def OnSelChanged(self, event):      def OnSelChanged(self, event):
158            if self.changing_selection:
159                # we're changing the selection ourselves (probably through
160                # self.normalize_selection(). ignore the event.
161                return
162          self.normalize_selection()          self.normalize_selection()
163          layer = self.SelectedLayer()          # SelectedLayer returns None if no layer is selected. Since
164          if layer is not None:          # passing None to interactor.SelectLayer deselects the layer we
165              self.app.interactor.SelectLayer(layer)          # can simply pass the result of SelectedLayer on in all cases
166            self.app.interactor.SelectLayer(self.SelectedLayer())
167    
168      def layer_selected(self, layer):      def layer_selected(self, layer):
169          pass          item = self.layer_to_item.get(id(layer))
170            if item is not None and item != self.GetSelection():
171                self.SelectItem(item)
172    
173    
174    class SessionTreeView(NonModalDialog):
175    
176        """Non modal dialog showing the session as a tree"""
177    
178        def __init__(self, parent, app, name):
179            NonModalDialog.__init__(self, parent, app.interactor, name, "Session")
180            self.tree = SessionTreeCtrl(self, -1, app)
181    
182        def OnClose(self, event):
183            #self.interactor.Unsubscribe(SELECTED_SHAPE, self.select_shape)
184            NonModalDialog.OnClose(self, event)
185    
186            # if there were a way to get notified when the tree control
187            # itself is destroyed we could use that to unsubscribe instead
188            # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at
189            # all)
190            self.tree.unsubscribe_all()

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26