/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/tableview.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/Thuban/UI/tableview.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 808 - (show annotations)
Mon May 5 10:33:47 2003 UTC (21 years, 10 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/tableview.py
File MIME type: text/x-python
File size: 8080 byte(s)
(TableGrid.disallow_messages)
(TableGrid.allow_messages): New methods to make it possible to
inhibit message sending.
(TableGrid.issue): Only send the message if not inhibited.
(LayerTableGrid.select_shape): Use the new methods to make sure
that no ROW_SELECTED message is sent while we're updating the
selected rows to match the selected shapes.

1 # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2 # Authors:
3 # Bernhard Herzog <[email protected]>
4 #
5 # This program is free software under the GPL (>=v2)
6 # Read the file COPYING coming with Thuban for details.
7
8 __version__ = "$Revision$"
9
10 from wxPython.wx import *
11 from wxPython.grid import *
12
13 from Thuban.Lib.connector import Publisher
14 from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
15 FIELDTYPE_STRING
16 import view
17 from dialogs import NonModalDialog
18 from messages import SHAPES_SELECTED
19
20 wx_value_type_map = {FIELDTYPE_INT: wxGRID_VALUE_NUMBER,
21 FIELDTYPE_DOUBLE: wxGRID_VALUE_FLOAT,
22 FIELDTYPE_STRING: wxGRID_VALUE_STRING}
23
24 ROW_SELECTED = "ROW_SELECTED"
25
26
27 class DataTable(wxPyGridTableBase):
28
29 """Wrapper around a Thuban table object suitable for a wxGrid"""
30
31 def __init__(self, table = None):
32 wxPyGridTableBase.__init__(self)
33 self.num_cols = 0
34 self.num_rows = 0
35 self.columns = []
36 self.table = None
37 self.SetTable(table)
38
39 def SetTable(self, table):
40 self.table = table
41 self.num_cols = table.field_count()
42 self.num_rows = table.record_count()
43
44 self.columns = []
45 for i in range(self.num_cols):
46 type, name, len, decc = table.field_info(i)
47 self.columns.append((name, wx_value_type_map[type], len, decc))
48
49 #
50 # required methods for the wxPyGridTableBase interface
51 #
52
53 def GetNumberRows(self):
54 return self.num_rows
55
56 def GetNumberCols(self):
57 return self.num_cols
58
59 def IsEmptyCell(self, row, col):
60 return 0
61
62 # Get/Set values in the table. The Python version of these
63 # methods can handle any data-type, (as long as the Editor and
64 # Renderer understands the type too,) not just strings as in the
65 # C++ version.
66 def GetValue(self, row, col):
67 record = self.table.read_record(row)
68 return record[self.columns[col][0]]
69
70 def SetValue(self, row, col, value):
71 pass
72
73 #
74 # Some optional methods
75 #
76
77 # Called when the grid needs to display labels
78 def GetColLabelValue(self, col):
79 return self.columns[col][0]
80
81 # Called to determine the kind of editor/renderer to use by
82 # default, doesn't necessarily have to be the same type used
83 # nativly by the editor/renderer if they know how to convert.
84 def GetTypeName(self, row, col):
85 return self.columns[col][1]
86
87 # Called to determine how the data can be fetched and stored by the
88 # editor and renderer. This allows you to enforce some type-safety
89 # in the grid.
90 def CanGetValueAs(self, row, col, typeName):
91 # perhaps we should allow conversion int->double?
92 return self.GetTypeName(row, col) == typeName
93
94 def CanSetValueAs(self, row, col, typeName):
95 return self.CanGetValueAs(row, col, typeName)
96
97
98 class TableGrid(wxGrid, Publisher):
99
100 """A grid view for a Thuban table
101
102 When rows are selected by the user the table issues ROW_SELECTED
103 messages. wx sends selection events even when the selection is
104 manipulated by code (instead of by the user) which usually lead to
105 ROW_SELECTED messages being sent in turn. Therefore sending messages
106 can be switched on and off with the allow_messages and
107 disallow_messages methods.
108 """
109
110 def __init__(self, parent, table = None):
111 wxGrid.__init__(self, parent, -1)
112
113 self.allow_messages_count = 0
114
115 self.table = DataTable(table)
116
117 # The second parameter means that the grid is to take ownership
118 # of the table and will destroy it when done. Otherwise you
119 # would need to keep a reference to it and call its Destroy
120 # method later.
121 self.SetTable(self.table, true)
122
123 #self.SetMargins(0,0)
124
125 # AutoSizeColumns would allow us to make the grid have optimal
126 # column widths automatically but it would cause a traversal of
127 # the entire table which for large .dbf files can take a very
128 # long time.
129 #self.AutoSizeColumns(false)
130
131 self.SetSelectionMode(wxGrid.wxGridSelectRows)
132
133 EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)
134 EVT_GRID_SELECT_CELL(self, self.OnSelectCell)
135
136 def SetTableObject(self, table):
137 self.table.SetTable(table)
138
139 def OnRangeSelect(self, event):
140 if event.Selecting():
141 self.issue(ROW_SELECTED, event.GetTopLeftCoords().GetRow())
142
143 def OnSelectCell(self, event):
144 self.issue(ROW_SELECTED, event.GetRow())
145
146 def disallow_messages(self):
147 """Disallow messages to be send.
148
149 This method only increases a counter so that calls to
150 disallow_messages and allow_messages can be nested. Only the
151 outermost calls will actually switch message sending on and off.
152 """
153 self.allow_messages_count += 1
154
155 def allow_messages(self):
156 """Allow messages to be send.
157
158 This method only decreases a counter so that calls to
159 disallow_messages and allow_messages can be nested. Only the
160 outermost calls will actually switch message sending on and off.
161 """
162 self.allow_messages_count -= 1
163
164 def issue(self, *args):
165 """Issue a message unless disallowed.
166
167 See the allow_messages and disallow_messages methods.
168 """
169 if self.allow_messages_count == 0:
170 Publisher.issue(self, *args)
171
172
173 class LayerTableGrid(TableGrid):
174
175 """Table grid for the layer tables.
176
177 The LayerTableGrid is basically the same as a TableGrid but it's
178 selection is usually coupled to the selected object in the map.
179 """
180
181 def select_shape(self, layer, shape):
182 """Select the row corresponding to the specified shape and layer
183
184 If layer is not the layer the table is associated with do
185 nothing. If shape or layer is None also do nothing.
186 """
187 if layer is not None and layer.table is self.table.table \
188 and shape is not None:
189 self.disallow_messages()
190 try:
191 self.SelectRow(shape)
192 self.SetGridCursor(shape, 0)
193 self.MakeCellVisible(shape, 0)
194 finally:
195 self.allow_messages()
196
197
198 class TableFrame(NonModalDialog):
199
200 """Frame that displays a Thuban table in a grid view"""
201
202 def __init__(self, parent, name, title, table):
203 NonModalDialog.__init__(self, parent, name, title)
204 self.table = table
205 self.grid = self.make_grid(self.table)
206
207 def make_grid(self, table):
208 """Return the table grid to use in the frame.
209
210 The default implementation returns a TableGrid instance.
211 Override in derived classes to use different grid classes.
212 """
213 return TableGrid(self, table)
214
215
216 class LayerTableFrame(TableFrame):
217
218 """Frame that displays a layer table in a grid view
219
220 A LayerTableFrame is TableFrame whose selection is connected to the
221 selected object in a map.
222 """
223
224 def __init__(self, parent, name, title, layer, table):
225 TableFrame.__init__(self, parent, name, title, table)
226 self.layer = layer
227 self.grid.Subscribe(ROW_SELECTED, self.row_selected)
228 self.parent.Subscribe(SHAPES_SELECTED, self.select_shape)
229
230 def make_grid(self, table):
231 """Override the derived method to return a LayerTableGrid.
232 """
233 return LayerTableGrid(self, table)
234
235 def OnClose(self, event):
236 self.parent.Unsubscribe(SHAPES_SELECTED, self.select_shape)
237 TableFrame.OnClose(self, event)
238
239 def select_shape(self, layer, shapes):
240 """Subscribed to the SHAPES_SELECTED message.
241
242 If shapes contains exactly one shape id, select that shape in
243 the grid. Otherwise deselect all.
244 """
245 if len(shapes):
246 shape = shapes[0]
247 else:
248 shape = None
249 self.grid.select_shape(layer, shape)
250
251 def row_selected(self, row):
252 if self.layer is not None:
253 self.parent.SelectShapes(self.layer, [row])

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26