/[thuban]/trunk/thuban/Thuban/UI/classifier.py
ViewVC logotype

Annotation of /trunk/thuban/Thuban/UI/classifier.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 570 - (hide annotations)
Fri Mar 28 17:06:26 2003 UTC (21 years, 11 months ago) by jonathan
File MIME type: text/x-python
File size: 39125 byte(s)
Support for highlighting a specific
        group within the grid when the classification dialog is opened.
        Also contains a lot of debugging printouts which will later
        be removed.

1 bh 476 # Copyright (c) 2001, 2003 by Intevation GmbH
2 jonathan 372 # Authors:
3     # Jonathan Coles <[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     """Dialog for classifying how layers are displayed"""
9    
10     __version__ = "$Revision$"
11    
12 jonathan 376 import copy
13    
14 jonathan 473 from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
15     FIELDTYPE_STRING
16    
17 jonathan 372 from wxPython.wx import *
18     from wxPython.grid import *
19    
20 jan 374 from Thuban import _
21 jonathan 415 from Thuban.common import *
22 jonathan 441 from Thuban.UI.common import *
23 jan 374
24 jonathan 451 from Thuban.Model.classification import *
25 jonathan 392
26 jonathan 415 from Thuban.Model.color import Color
27    
28 jonathan 460 from Thuban.Model.layer import Layer, SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT
29 jonathan 392
30 jonathan 485 from dialogs import NonModalDialog
31    
32 jonathan 460 # widget id's
33 jonathan 372 ID_PROPERTY_SELECT = 4010
34     ID_CLASS_TABLE = 40011
35    
36     ID_CLASSIFY_OK = 4001
37     ID_CLASSIFY_CANCEL = 4002
38 jonathan 415 ID_CLASSIFY_ADD = 4003
39     ID_CLASSIFY_GENRANGE = 4004
40 jonathan 451 ID_CLASSIFY_REMOVE = 4005
41 jonathan 460 ID_CLASSIFY_MOVEUP = 4006
42     ID_CLASSIFY_MOVEDOWN = 4007
43 jonathan 485 ID_CLASSIFY_APPLY = 4008
44 jonathan 372
45 jonathan 460 # table columns
46     COL_SYMBOL = 0
47 jonathan 415 COL_VALUE = 1
48     COL_LABEL = 2
49    
50 jonathan 460 # indices into the client data lists in Classifier.fields
51 jonathan 451 FIELD_CLASS = 0
52     FIELD_TYPE = 1
53     FIELD_NAME = 2
54    
55 jonathan 415 #
56     # this is a silly work around to ensure that the table that is
57     # passed into SetTable is the same that is returned by GetTable
58     #
59     import weakref
60     class ClassGrid(wxGrid):
61    
62 jonathan 570
63 jonathan 460 def __init__(self, parent):
64     """Constructor.
65    
66     parent -- the parent window
67    
68     clazz -- the working classification that this grid should
69     use for display.
70     """
71    
72 jonathan 485 #wxGrid.__init__(self, parent, ID_CLASS_TABLE, size = (340, 160))
73     wxGrid.__init__(self, parent, ID_CLASS_TABLE)
74 jonathan 509 #self.SetTable(ClassTable(fieldData, layer.ShapeType(), self), True)
75 jonathan 415
76 jonathan 570 self.currentSelection = []
77    
78 jonathan 460 EVT_GRID_CELL_LEFT_DCLICK(self, self._OnCellDClick)
79 jonathan 451 EVT_GRID_RANGE_SELECT(self, self._OnSelectedRange)
80     EVT_GRID_SELECT_CELL(self, self._OnSelectedCell)
81    
82 jonathan 570 print "123123123: ", ('Show' in dir(self))
83 jonathan 451
84 jonathan 570 def Show(self):
85     print "SHOW!"
86 jonathan 460
87 jonathan 570 def Refresh(self):
88     self.Show()
89     def Update(self):
90     self.Show()
91    
92     def CreateTable(self, clazz, shapeType, group = None):
93    
94 jonathan 460 assert(isinstance(clazz, Classification))
95    
96     self.shapeType = shapeType
97     table = self.GetTable()
98     if table is None:
99 jonathan 500 w = self.GetDefaultColSize() * 3 + self.GetDefaultRowLabelSize()
100     h = self.GetDefaultRowSize() * 4 + self.GetDefaultColLabelSize()
101     self.SetDimensions(-1, -1, w, h)
102     self.SetSizeHints(w, h, -1, -1)
103 jonathan 570 table = ClassTable(self)
104     self.SetTable(table, True)
105 jonathan 460
106 jonathan 570
107 bh 476 self.SetSelectionMode(wxGrid.wxGridSelectRows)
108 jonathan 460 self.ClearSelection()
109    
110 jonathan 570 print "8------------------"
111     table.Reset(clazz, self.shapeType, group)
112     print "9------------------"
113    
114     # def Show(self, show = True):
115     # print "SHOW!"
116     # wxGrid.Show(self, show)
117    
118     # sel = self.GetCurrentSelection()
119    
120     # print "( 1"
121     # if len(sel) == 1:
122     # print "( 2"
123     # self.MakeCellVisible(sel[0], 0)
124    
125 jonathan 451 def GetCurrentSelection(self):
126 jonathan 460 """Return the currently highlighted rows as an increasing list
127     of row numbers."""
128 jonathan 570 print "@@ ", self.currentSelection
129 jonathan 451 sel = copy.copy(self.currentSelection)
130     sel.sort()
131     return sel
132    
133 jonathan 570 def GetSelectedRows(self):
134     return self.GetCurrentSelection()
135    
136 jonathan 415 def SetCellRenderer(self, row, col):
137     raise ValueError(_("Must not allow setting of renderer in ClassGrid!"))
138    
139 jonathan 460 #
140     # [Set|Get]Table is taken from http://wiki.wxpython.org
141     # they are needed as a work around to ensure that the table
142     # that is passed to SetTable is the one that is returned
143     # by GetTable.
144     #
145 jonathan 415 def SetTable(self, object, *attributes):
146     self.tableRef = weakref.ref(object)
147     return wxGrid.SetTable(self, object, *attributes)
148    
149     def GetTable(self):
150 jonathan 460 try:
151     return self.tableRef()
152     except:
153     return None
154 jonathan 415
155 jonathan 451 def DeleteSelectedRows(self):
156 jonathan 460 """Deletes all highlighted rows.
157    
158     If only one row is highlighted then after it is deleted the
159     row that was below the deleted row is highlighted."""
160    
161 jonathan 451 sel = self.GetCurrentSelection()
162 jonathan 415
163 jonathan 460 # nothing to do
164     if len(sel) == 0: return
165    
166     # if only one thing is selected check if it is the default
167     # data row, because we can't remove that
168 jonathan 451 if len(sel) == 1:
169 jonathan 485 #group = self.GetTable().GetValueAsCustom(sel[0], COL_SYMBOL, None)
170     group = self.GetTable().GetClassGroup(sel[0])
171 jonathan 451 if isinstance(group, ClassGroupDefault):
172     wxMessageDialog(self,
173     "The Default group cannot be removed.",
174     style = wxOK | wxICON_EXCLAMATION).ShowModal()
175     return
176    
177 jonathan 460
178 jonathan 451 self.ClearSelection()
179    
180 jonathan 460 # we need to remove things from the bottom up so we don't
181     # change the indexes of rows that will be deleted next
182 jonathan 451 sel.reverse()
183 jonathan 460
184     #
185     # actually remove the rows
186     #
187 jonathan 451 table = self.GetTable()
188     for row in sel:
189     table.DeleteRows(row)
190    
191 jonathan 460 #
192     # if there was only one row selected highlight the row
193     # that was directly below it, or move up one if the
194     # deleted row was the last row.
195     #
196 jonathan 451 if len(sel) == 1:
197     r = sel[0]
198     if r > self.GetNumberRows() - 1:
199     r = self.GetNumberRows() - 1
200     self.SelectRow(r)
201    
202 jonathan 570
203     def SelectGroup(self, group, makeVisible = True):
204     if group is None: return
205    
206     assert(isinstance(group, ClassGroup))
207    
208     table = self.GetTable()
209    
210     assert(table is not None)
211    
212    
213     print "-- ", group
214     for i in range(table.GetNumberRows()):
215     g = table.GetClassGroup(i)
216     print "1", g
217     if g is group:
218     print "2"
219     self.SelectRow(i)
220     if makeVisible:
221     print "3"
222     self.MakeCellVisible(i, 0)
223     break
224    
225    
226    
227 jonathan 451 #
228     # XXX: This isn't working, and there is no way to deselect rows wxPython!
229     #
230     # def DeselectRow(self, row):
231     # self.ProcessEvent(
232     # wxGridRangeSelectEvent(-1,
233     # wxEVT_GRID_RANGE_SELECT,
234     # self,
235     # (row, row), (row, row),
236     # sel = False))
237    
238 jonathan 460 def _OnCellDClick(self, event):
239     """Handle a double on a cell."""
240    
241 jonathan 451 r = event.GetRow()
242     c = event.GetCol()
243 jonathan 460 if c == COL_SYMBOL:
244 jonathan 485 prop = self.GetTable().GetValueAsCustom(r, c, None)
245     #prop = group.GetProperties()
246 jonathan 460
247     # get a new ClassGroupProperties object and copy the
248     # values over to our current object
249     propDlg = SelectPropertiesDialog(NULL, prop, self.shapeType)
250 jonathan 451 if propDlg.ShowModal() == wxID_OK:
251     new_prop = propDlg.GetClassGroupProperties()
252 jonathan 485 #prop.SetProperties(new_prop)
253     self.GetTable().SetValueAsCustom(r, c, None, new_prop)
254 jonathan 451 propDlg.Destroy()
255    
256     #
257     # _OnSelectedRange() and _OnSelectedCell() were borrowed
258 jonathan 460 # from http://wiki.wxpython.org to keep track of which
259     # cells are currently highlighted
260 jonathan 451 #
261     def _OnSelectedRange(self, event):
262     """Internal update to the selection tracking list"""
263     if event.Selecting():
264     for index in range( event.GetTopRow(), event.GetBottomRow()+1):
265     if index not in self.currentSelection:
266 jonathan 570 print " ", index
267 jonathan 451 self.currentSelection.append( index )
268     else:
269     for index in range( event.GetTopRow(), event.GetBottomRow()+1):
270     while index in self.currentSelection:
271 jonathan 570 print " ", index
272 jonathan 451 self.currentSelection.remove( index )
273     #self.ConfigureForSelection()
274    
275 jonathan 570 print self.GetCurrentSelection()
276 jonathan 451 event.Skip()
277    
278     def _OnSelectedCell( self, event ):
279     """Internal update to the selection tracking list"""
280 jonathan 570 print "selecting cell: ", event.GetRow()
281 jonathan 451 self.currentSelection = [ event.GetRow() ]
282     #self.ConfigureForSelection()
283     event.Skip()
284    
285 jonathan 376 class ClassTable(wxPyGridTableBase):
286 jonathan 460 """Represents the underlying data structure for the grid."""
287 jonathan 376
288 jonathan 415 NUM_COLS = 3
289    
290 jonathan 451 __col_labels = [_("Symbol"), _("Value"), _("Label")]
291 jonathan 415
292 jonathan 570
293     def __init__(self, view = None):
294     #def __init__(self, clazz, shapeType, view = None):
295 jonathan 460 """Constructor.
296    
297     shapeType -- the type of shape that the layer uses
298    
299     view -- a wxGrid object that uses this class for its table
300     """
301    
302 jonathan 376 wxPyGridTableBase.__init__(self)
303 jonathan 485
304 jonathan 415 self.SetView(view)
305     self.tdata = []
306 jonathan 376
307 jonathan 570 #self.Reset(clazz, shapeType)
308 jonathan 415
309 jonathan 570 def Reset(self, clazz, shapeType, group = None):
310 jonathan 460 """Reset the table with the given data.
311 jonathan 415
312 jonathan 460 This is necessary because wxWindows does not allow a grid's
313     table to change once it has been intially set and so we
314     need a way of modifying the data.
315    
316     clazz -- the working classification that this table should
317     use for display. This may be different from the
318     classification in the layer.
319    
320     shapeType -- the type of shape that the layer uses
321     """
322    
323     assert(isinstance(clazz, Classification))
324    
325 jonathan 415 self.GetView().BeginBatch()
326    
327 jonathan 485 self.fieldType = clazz.GetFieldType()
328 jonathan 415 self.shapeType = shapeType
329    
330 jonathan 451 old_len = len(self.tdata)
331 jonathan 415
332 jonathan 376 self.tdata = []
333    
334 jonathan 570 print "9------------------"
335 jonathan 460 #
336     # copy the data out of the classification and into our
337     # array
338     #
339 jonathan 570 row = -1
340     for g in clazz:
341     ng = copy.deepcopy(g)
342     self.__SetRow(-1, ng)
343     if g is group:
344     row = self.GetNumberRows() - 1
345     print "selecting row..."
346 jonathan 441
347 jonathan 570 print "10------------------"
348 jonathan 441
349 jonathan 485 self.__Modified(-1)
350 jonathan 415
351 jonathan 451 self.__NotifyRowChanges(old_len, len(self.tdata))
352 jonathan 570 print "11------------------"
353 jonathan 485
354 jonathan 570 if row > -1:
355     self.GetView().ClearSelection()
356     self.GetView().SelectRow(row)
357     self.GetView().MakeCellVisible(row, 0)
358 jonathan 485
359 jonathan 451 self.GetView().EndBatch()
360    
361     def __NotifyRowChanges(self, curRows, newRows):
362 jonathan 415 #
363     # silly message processing for updates to the number of
364     # rows and columns
365     #
366     if newRows > curRows:
367     msg = wxGridTableMessage(self,
368     wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
369     newRows - curRows) # how many
370     self.GetView().ProcessTableMessage(msg)
371 jonathan 519 self.GetView().FitInside()
372 jonathan 415 elif newRows < curRows:
373     msg = wxGridTableMessage(self,
374     wxGRIDTABLE_NOTIFY_ROWS_DELETED,
375     curRows - newRows, # position
376     curRows - newRows) # how many
377     self.GetView().ProcessTableMessage(msg)
378 jonathan 519 self.GetView().FitInside()
379 jonathan 415
380 jonathan 441 def __SetRow(self, row, group):
381 jonathan 460 """Set a row's data to that of the group.
382 jonathan 441
383 jonathan 485 The table is considered modified after this operation.
384    
385 jonathan 460 row -- if row is -1 or greater than the current number of rows
386     then group is appended to the end.
387     """
388 jonathan 441
389 jonathan 460 # either append or replace
390     if row == -1 or row >= self.GetNumberRows():
391     self.tdata.append(group)
392 jonathan 441 else:
393 jonathan 460 self.tdata[row] = group
394 jonathan 441
395 jonathan 460 self.__Modified()
396    
397 jonathan 415 def GetColLabelValue(self, col):
398 jonathan 460 """Return the label for the given column."""
399 jonathan 415 return self.__col_labels[col]
400    
401     def GetRowLabelValue(self, row):
402 jonathan 460 """Return the label for the given row."""
403 jonathan 415
404 jonathan 460 group = self.tdata[row]
405     if isinstance(group, ClassGroupDefault): return _("Default")
406     if isinstance(group, ClassGroupSingleton): return _("Singleton")
407     if isinstance(group, ClassGroupRange): return _("Range")
408     if isinstance(group, ClassGroupMap): return _("Map")
409    
410     assert(False) # shouldn't get here
411     return _("")
412    
413 jonathan 376 def GetNumberRows(self):
414 jonathan 460 """Return the number of rows."""
415 jonathan 376 return len(self.tdata)
416    
417     def GetNumberCols(self):
418 jonathan 460 """Return the number of columns."""
419 jonathan 415 return self.NUM_COLS
420 jonathan 376
421     def IsEmptyCell(self, row, col):
422 jonathan 460 """Determine if a cell is empty. This is always false."""
423     return False
424 jonathan 376
425     def GetValue(self, row, col):
426 jonathan 460 """Return the object that is used to represent the given
427     cell coordinates. This may not be a string."""
428     return self.GetValueAsCustom(row, col, None)
429 jonathan 376
430     def SetValue(self, row, col, value):
431 jonathan 460 """Assign 'value' to the cell specified by 'row' and 'col'.
432    
433     The table is considered modified after this operation.
434     """
435    
436     self.SetValueAsCustom(row, col, None, value)
437 jonathan 415 self.__Modified()
438    
439 jonathan 392 def GetValueAsCustom(self, row, col, typeName):
440 jonathan 460 """Return the object that is used to represent the given
441     cell coordinates. This may not be a string.
442    
443     typeName -- unused, but needed to overload wxPyGridTableBase
444     """
445 jonathan 376
446 jonathan 460 group = self.tdata[row]
447    
448     if col == COL_SYMBOL:
449 jonathan 485 return group.GetProperties()
450 jonathan 460
451     if col == COL_LABEL:
452     return group.GetLabel()
453    
454     # col must be COL_VALUE
455     assert(col == COL_VALUE)
456    
457     if isinstance(group, ClassGroupDefault):
458     return _("DEFAULT")
459     elif isinstance(group, ClassGroupSingleton):
460     return group.GetValue()
461     elif isinstance(group, ClassGroupRange):
462     return _("%s - %s") % (group.GetMin(), group.GetMax())
463    
464     assert(False) # shouldn't get here
465     return None
466    
467 jonathan 415 def __ParseInput(self, value):
468     """Try to determine what kind of input value is
469 jonathan 460 (string, number, or range)
470    
471     Returns a tuple of length one if there is a single
472     value, or of length two if it is a range.
473 jonathan 415 """
474 jonathan 392
475 jonathan 485 type = self.fieldType
476 jonathan 415
477 jonathan 460 if type == FIELDTYPE_STRING:
478 jonathan 451 return (value,)
479 jonathan 460 elif type == FIELDTYPE_INT or type == FIELDTYPE_DOUBLE:
480 jonathan 451
481 jonathan 460 if type == FIELDTYPE_INT:
482     conv = lambda p: int(float(p))
483     else:
484     conv = lambda p: p
485    
486 jonathan 451 #
487     # first try to take the input as a single number
488     # if there's an exception try to break it into
489     # a range seperated by a '-'. take care to ignore
490     # a leading '-' as that could be for a negative number.
491     # then try to parse the individual parts. if there
492     # is an exception here, let it pass up to the calling
493     # function.
494     #
495     try:
496 jonathan 460 return (conv(Str2Num(value)),)
497     except ValueError:
498 jonathan 451 i = value.find('-')
499     if i == 0:
500     i = value.find('-', 1)
501    
502 jonathan 460 return (conv(Str2Num(value[:i])), conv(Str2Num(value[i+1:])))
503    
504     assert(False) # shouldn't get here
505 jonathan 485 return (0,)
506 jonathan 415
507    
508     def SetValueAsCustom(self, row, col, typeName, value):
509 jonathan 460 """Set the cell specified by 'row' and 'col' to 'value'.
510 jonathan 415
511 jonathan 460 If column represents the value column, the input is parsed
512     to determine if a string, number, or range was entered.
513     A new ClassGroup may be created if the type of data changes.
514    
515     The table is considered modified after this operation.
516    
517     typeName -- unused, but needed to overload wxPyGridTableBase
518     """
519    
520     assert(col >= 0 and col < self.GetNumberCols())
521     assert(row >= 0 and row < self.GetNumberRows())
522    
523     group = self.tdata[row]
524    
525 jonathan 485 mod = True # assume the data will change
526 jonathan 460
527     if col == COL_SYMBOL:
528 jonathan 485 group.SetProperties(value)
529     elif col == COL_LABEL:
530     group.SetLabel(value)
531 jonathan 415 elif col == COL_VALUE:
532 jonathan 451 if isinstance(group, ClassGroupDefault):
533     # not allowed to modify the default value
534     pass
535     elif isinstance(group, ClassGroupMap):
536     # something special
537     pass
538     else: # SINGLETON, RANGE
539     try:
540     dataInfo = self.__ParseInput(value)
541 jonathan 460 except ValueError:
542 jonathan 451 # bad input, ignore the request
543 jonathan 485 mod = False
544 jonathan 451 else:
545 jonathan 415
546 jonathan 485 changed = False
547 jonathan 451 ngroup = group
548     props = group.GetProperties()
549 jonathan 460
550     #
551     # try to update the values, which may include
552     # changing the underlying group type if the
553     # group was a singleton and a range was entered
554     #
555 jonathan 451 if len(dataInfo) == 1:
556     if not isinstance(group, ClassGroupSingleton):
557     ngroup = ClassGroupSingleton(prop = props)
558 jonathan 485 changed = True
559 jonathan 451 ngroup.SetValue(dataInfo[0])
560     elif len(dataInfo) == 2:
561     if not isinstance(group, ClassGroupRange):
562     ngroup = ClassGroupRange(prop = props)
563 jonathan 485 changed = True
564 jonathan 451 ngroup.SetRange(dataInfo[0], dataInfo[1])
565 jonathan 415 else:
566 jonathan 451 assert(False)
567 jonathan 485 pass
568 jonathan 415
569 jonathan 485 if changed:
570     ngroup.SetLabel(group.GetLabel())
571     self.SetClassGroup(row, ngroup)
572     else:
573     assert(False) # shouldn't be here
574     pass
575 jonathan 460
576 jonathan 485 if mod:
577 jonathan 460 self.__Modified()
578     self.GetView().Refresh()
579 jonathan 415
580     def GetAttr(self, row, col, someExtraParameter):
581 jonathan 460 """Returns the cell attributes"""
582    
583 jonathan 415 attr = wxGridCellAttr()
584     #attr = wxPyGridTableBase.GetAttr(self, row, col, someExtraParameter)
585    
586 jonathan 460 if col == COL_SYMBOL:
587 jonathan 485 # we need to create a new renderer each time, because
588     # SetRenderer takes control of the parameter
589 jonathan 415 attr.SetRenderer(ClassRenderer(self.shapeType))
590     attr.SetReadOnly()
591    
592     return attr
593    
594 jonathan 441 def GetClassGroup(self, row):
595 jonathan 460 """Return the ClassGroup object representing row 'row'."""
596 jonathan 415
597 jonathan 485 return self.tdata[row] # self.GetValueAsCustom(row, COL_SYMBOL, None)
598 jonathan 415
599 jonathan 460 def SetClassGroup(self, row, group):
600 jonathan 485 self.__SetRow(row, group)
601     self.GetView().Refresh()
602 jonathan 460
603     def __Modified(self, mod = True):
604 jonathan 485 """Adjust the modified flag.
605 jonathan 460
606 jonathan 485 mod -- if -1 set the modified flag to False, otherwise perform
607     an 'or' operation with the current value of the flag and
608     'mod'
609     """
610    
611     if mod == -1:
612     self.modified = False
613     else:
614     self.modified = mod or self.modified
615    
616 jonathan 415 def IsModified(self):
617 jonathan 460 """True if this table is considered modified."""
618 jonathan 415 return self.modified
619    
620 jonathan 451 def DeleteRows(self, pos, numRows = 1):
621 jonathan 485 """Deletes 'numRows' beginning at row 'pos'.
622 jonathan 460
623 jonathan 485 The row representing the default group is not removed.
624    
625     The table is considered modified if any rows are removed.
626 jonathan 460 """
627    
628 jonathan 451 assert(pos >= 0)
629     old_len = len(self.tdata)
630     for row in range(pos, pos - numRows, -1):
631 jonathan 485 group = self.GetClassGroup(row)
632 jonathan 451 if not isinstance(group, ClassGroupDefault):
633     self.tdata.pop(row)
634     self.__Modified()
635    
636     if self.IsModified():
637     self.__NotifyRowChanges(old_len, len(self.tdata))
638 jonathan 415
639 jonathan 451 def AppendRows(self, numRows = 1):
640 jonathan 485 """Append 'numRows' empty rows to the end of the table.
641 jonathan 460
642 jonathan 485 The table is considered modified if any rows are appended.
643     """
644    
645 jonathan 451 old_len = len(self.tdata)
646     for i in range(numRows):
647     np = ClassGroupSingleton()
648 jonathan 460 self.__SetRow(-1, np)
649 jonathan 451
650     if self.IsModified():
651     self.__NotifyRowChanges(old_len, len(self.tdata))
652    
653    
654 jonathan 485 class Classifier(NonModalDialog):
655 bh 535
656 jonathan 570 def __init__(self, parent, name, layer, group = None):
657 bh 535 NonModalDialog.__init__(self, parent, name,
658 jonathan 485 _("Classifier: %s") % layer.Title())
659 jonathan 372
660 jonathan 511 panel = wxPanel(self, -1, size=(100, 100))
661 jonathan 509
662 jonathan 415 self.layer = layer
663    
664 jonathan 485 self.originalClass = self.layer.GetClassification()
665     field = self.originalClass.GetField()
666     fieldType = self.originalClass.GetFieldType()
667    
668 jonathan 372 topBox = wxBoxSizer(wxVERTICAL)
669 jonathan 511 panelBox = wxBoxSizer(wxVERTICAL)
670 jonathan 372
671 jonathan 511 #panelBox.Add(wxStaticText(panel, -1, _("Layer: %s") % layer.Title()),
672 jonathan 485 #0, wxALIGN_LEFT | wxALL, 4)
673 jonathan 511 panelBox.Add(wxStaticText(panel, -1,
674 jonathan 485 _("Layer Type: %s") % layer.ShapeType()),
675 jonathan 451 0, wxALIGN_LEFT | wxALL, 4)
676 jonathan 415
677 jonathan 372
678 jonathan 485 #
679     # make field combo box
680     #
681 jonathan 509 self.fields = wxComboBox(panel, ID_PROPERTY_SELECT, "",
682 jonathan 372 style = wxCB_READONLY)
683    
684     self.num_cols = layer.table.field_count()
685 jonathan 441 # just assume the first field in case one hasn't been
686     # specified in the file.
687 jonathan 451 self.__cur_field = 0
688 jonathan 460
689     self.fields.Append("<None>")
690     self.fields.SetClientData(0, None)
691    
692 jonathan 372 for i in range(self.num_cols):
693     type, name, len, decc = layer.table.field_info(i)
694 jonathan 451 self.fields.Append(name)
695    
696 jonathan 415 if name == field:
697 jonathan 460 self.__cur_field = i + 1
698 jonathan 485 self.fields.SetClientData(i + 1, self.originalClass)
699 jonathan 451 else:
700 jonathan 460 self.fields.SetClientData(i + 1, None)
701 jonathan 372
702    
703 jonathan 509 ###########
704 jonathan 485
705 jonathan 509 self.fieldTypeText = wxStaticText(panel, -1, "")
706 jonathan 560 panelBox.Add(self.fieldTypeText, 0,
707     wxGROW | wxALIGN_LEFT | wxALL | wxADJUST_MINSIZE, 4)
708 jonathan 485
709     propertyBox = wxBoxSizer(wxHORIZONTAL)
710 jonathan 509 propertyBox.Add(wxStaticText(panel, -1, _("Field: ")),
711 jonathan 506 0, wxALIGN_LEFT | wxALL, 4)
712 jonathan 451 propertyBox.Add(self.fields, 1, wxGROW|wxALL, 4)
713 jonathan 460 EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self._OnFieldSelect)
714 jonathan 451
715 jonathan 511 panelBox.Add(propertyBox, 0, wxGROW, 4)
716 jonathan 372
717 jonathan 570
718 jonathan 372 #
719 jonathan 570 # Control Box
720 jonathan 372 #
721 jonathan 415 controlBox = wxBoxSizer(wxHORIZONTAL)
722 jonathan 485
723 jonathan 460
724 jonathan 509 ###########
725 jonathan 485 #
726     # Control buttons:
727     #
728     self.controlButtons = []
729 jonathan 460
730 jonathan 509 controlButtonBox = wxBoxSizer(wxVERTICAL)
731    
732     button = wxButton(panel, ID_CLASSIFY_ADD, _("Add"))
733 jonathan 485 controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
734     self.controlButtons.append(button)
735 jonathan 451
736 jonathan 570 button = wxButton(panel, ID_CLASSIFY_GENRANGE, _("Generate Ranges"))
737     controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
738     self.controlButtons.append(button)
739 jonathan 485
740 jonathan 509 button = wxButton(panel, ID_CLASSIFY_MOVEUP, _("Move Up"))
741 jonathan 485 controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
742     self.controlButtons.append(button)
743    
744 jonathan 509 button = wxButton(panel, ID_CLASSIFY_MOVEDOWN, _("Move Down"))
745 jonathan 485 controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
746     self.controlButtons.append(button)
747    
748     controlButtonBox.Add(60, 20, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
749    
750 jonathan 509 button = wxButton(panel, ID_CLASSIFY_REMOVE, _("Remove"))
751 jonathan 485 controlButtonBox.Add(button, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
752     self.controlButtons.append(button)
753    
754 jonathan 570
755     ###########
756     #
757     # Classification data table
758     #
759    
760     self.classGrid = ClassGrid(panel)
761     #self.__SetGridTable(self.__cur_field, group)
762     #self.fields.SetSelection(self.__cur_field)
763    
764     # calling __SelectField after creating the classGrid fills in the
765     # grid with the correct information
766     print "2------------------"
767     self.__SelectField(self.__cur_field, group = group)
768    
769     #self.classGrid.SelectGroup(group)
770    
771     controlBox.Add(self.classGrid, 1, wxGROW, 0)
772    
773    
774    
775 jonathan 415 controlBox.Add(controlButtonBox, 0, wxGROW, 10)
776 jonathan 511 panelBox.Add(controlBox, 1, wxGROW, 10)
777 jonathan 415
778 jonathan 460 EVT_BUTTON(self, ID_CLASSIFY_ADD, self._OnAdd)
779     EVT_BUTTON(self, ID_CLASSIFY_REMOVE, self._OnRemove)
780     EVT_BUTTON(self, ID_CLASSIFY_GENRANGE, self._OnGenRange)
781     EVT_BUTTON(self, ID_CLASSIFY_MOVEUP, self._OnMoveUp)
782     EVT_BUTTON(self, ID_CLASSIFY_MOVEDOWN, self._OnMoveDown)
783 jonathan 415
784 jonathan 509 ###########
785    
786 jonathan 372 buttonBox = wxBoxSizer(wxHORIZONTAL)
787 jonathan 509 buttonBox.Add(wxButton(panel, ID_CLASSIFY_OK, _("OK")),
788 jonathan 372 0, wxALL, 4)
789 jonathan 485 buttonBox.Add(60, 20, 0, wxALL, 4)
790 jonathan 509 buttonBox.Add(wxButton(panel, ID_CLASSIFY_APPLY, _("Apply")),
791 jonathan 485 0, wxALL, 4)
792     buttonBox.Add(60, 20, 0, wxALL, 4)
793 jonathan 509 buttonBox.Add(wxButton(panel, ID_CLASSIFY_CANCEL, _("Cancel")),
794 jonathan 372 0, wxALL, 4)
795 jonathan 511 panelBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 0)
796 jonathan 372
797 jonathan 460 EVT_BUTTON(self, ID_CLASSIFY_OK, self._OnOK)
798 jonathan 485 EVT_BUTTON(self, ID_CLASSIFY_APPLY, self._OnApply)
799 jonathan 460 EVT_BUTTON(self, ID_CLASSIFY_CANCEL, self._OnCancel)
800 jonathan 372
801 jonathan 509 ###########
802    
803 jonathan 496
804 jonathan 509 panel.SetAutoLayout(True)
805 jonathan 511 panel.SetSizer(panelBox)
806     panelBox.SetSizeHints(panel)
807 jonathan 372
808 jonathan 511 topBox.Add(panel, 1, wxGROW, 0)
809     panelBox.SetSizeHints(self)
810 jonathan 509 self.SetAutoLayout(True)
811 jonathan 511 self.SetSizer(topBox)
812 jonathan 509
813 jonathan 570 print "1------------------"
814     #self.Fit()
815 jonathan 549 ######################
816    
817     self.haveApplied = False
818    
819 jonathan 460 def __BuildClassification(self, fieldIndex):
820 jonathan 415
821 jonathan 496 numRows = self.classGrid.GetNumberRows()
822     assert(numRows > 0) # there should always be a default row
823    
824 jonathan 415 clazz = Classification()
825 jonathan 496 if fieldIndex == 0:
826     fieldName = None
827     fieldType = None
828     else:
829     fieldName = self.fields.GetString(fieldIndex)
830     fieldType = self.layer.GetFieldType(fieldName)
831 jonathan 415
832 jonathan 460 clazz.SetField(fieldName)
833     clazz.SetFieldType(fieldType)
834    
835 jonathan 415
836 jonathan 460 table = self.classGrid.GetTable()
837     clazz.SetDefaultGroup(table.GetClassGroup(0))
838 jonathan 415
839 jonathan 460 for i in range(1, numRows):
840     clazz.AddGroup(table.GetClassGroup(i))
841    
842 jonathan 415 return clazz
843    
844 jonathan 570 def __SetGridTable(self, fieldIndex, group = None):
845 jonathan 415
846 jonathan 460 clazz = self.fields.GetClientData(fieldIndex)
847 jonathan 415
848 jonathan 460 if clazz is None:
849     clazz = Classification()
850     clazz.SetDefaultGroup(
851     ClassGroupDefault(
852 jonathan 485 self.layer.GetClassification().
853     GetDefaultGroup().GetProperties()))
854 jonathan 460
855     fieldName = self.fields.GetString(fieldIndex)
856     fieldType = self.layer.GetFieldType(fieldName)
857     clazz.SetFieldType(fieldType)
858    
859 jonathan 570 print "6------------------"
860     self.classGrid.CreateTable(clazz, self.layer.ShapeType(), group)
861     print "7------------------"
862 jonathan 460
863 jonathan 496
864    
865 jonathan 500 type2string = {None: _("None"),
866     FIELDTYPE_STRING: _("Text"),
867     FIELDTYPE_INT: _("Integer"),
868     FIELDTYPE_DOUBLE: _("Decimal")}
869 jonathan 496
870 jonathan 485 def __SetFieldTypeText(self, fieldIndex):
871     fieldName = self.fields.GetString(fieldIndex)
872     fieldType = self.layer.GetFieldType(fieldName)
873    
874 jonathan 496 assert(Classifier.type2string.has_key(fieldType))
875 jonathan 485
876 jonathan 496 text = Classifier.type2string[fieldType]
877    
878 jonathan 485 self.fieldTypeText.SetLabel(_("Field Type: %s") % text)
879    
880 jonathan 570 def __SelectField(self, newIndex, oldIndex = -1, group = None):
881 jonathan 460
882 jonathan 570 print "3------------------"
883    
884 jonathan 498 assert(oldIndex >= -1)
885 jonathan 415
886 jonathan 570 self.fields.SetSelection(newIndex)
887    
888 jonathan 498 if oldIndex != -1:
889     clazz = self.__BuildClassification(oldIndex)
890     self.fields.SetClientData(oldIndex, clazz)
891 jonathan 485
892 jonathan 570 print "4------------------"
893     self.__SetGridTable(newIndex, group)
894     print "5------------------"
895 jonathan 498
896     enabled = newIndex != 0
897    
898 jonathan 485 for b in self.controlButtons:
899     b.Enable(enabled)
900    
901 jonathan 498 self.__SetFieldTypeText(newIndex)
902 jonathan 485
903 jonathan 496
904     def _OnFieldSelect(self, event):
905 jonathan 498 index = self.fields.GetSelection()
906     self.__SelectField(index, self.__cur_field)
907     self.__cur_field = index
908 jonathan 485
909     def _OnApply(self, event):
910 jonathan 415 """Put the data from the table into a new Classification and hand
911     it to the layer.
912     """
913    
914 jonathan 460 clazz = self.fields.GetClientData(self.__cur_field)
915 jonathan 415
916     #
917     # only build the classification if there wasn't one to
918     # to begin with or it has been modified
919     #
920     if clazz is None or self.classGrid.GetTable().IsModified():
921 jonathan 451 clazz = self.__BuildClassification(self.__cur_field)
922 jonathan 415
923     self.layer.SetClassification(clazz)
924    
925 jonathan 549 self.haveApplied = True
926    
927 jonathan 485 def _OnOK(self, event):
928     self._OnApply(event)
929     self.OnClose(event)
930 jonathan 415
931 jonathan 460 def _OnCancel(self, event):
932 jonathan 485 """The layer's current classification stays the same."""
933 jonathan 549 if self.haveApplied:
934     self.layer.SetClassification(self.originalClass)
935    
936 jonathan 485 self.OnClose(event)
937 jonathan 415
938 jonathan 460 def _OnAdd(self, event):
939 jonathan 451 self.classGrid.AppendRows()
940 jonathan 415
941 jonathan 460 def _OnRemove(self, event):
942 jonathan 451 self.classGrid.DeleteSelectedRows()
943    
944 jonathan 460 def _OnGenRange(self, event):
945     print "Classifier._OnGenRange()"
946 jonathan 415
947 jonathan 460 def _OnMoveUp(self, event):
948     sel = self.classGrid.GetCurrentSelection()
949 jonathan 415
950 jonathan 570 print "sel: ", sel
951    
952 jonathan 460 if len(sel) == 1:
953     i = sel[0]
954     if i > 1:
955     table = self.classGrid.GetTable()
956     x = table.GetClassGroup(i - 1)
957     y = table.GetClassGroup(i)
958     table.SetClassGroup(i - 1, y)
959     table.SetClassGroup(i, x)
960     self.classGrid.ClearSelection()
961     self.classGrid.SelectRow(i - 1)
962 jonathan 570 self.classGrid.MakeCellVisible(i - 1, 0)
963 jonathan 460
964     def _OnMoveDown(self, event):
965     sel = self.classGrid.GetCurrentSelection()
966    
967     if len(sel) == 1:
968     i = sel[0]
969     table = self.classGrid.GetTable()
970     if 0 < i < table.GetNumberRows() - 1:
971     x = table.GetClassGroup(i)
972     y = table.GetClassGroup(i + 1)
973     table.SetClassGroup(i, y)
974     table.SetClassGroup(i + 1, x)
975     self.classGrid.ClearSelection()
976     self.classGrid.SelectRow(i + 1)
977 jonathan 570 self.classGrid.MakeCellVisible(i + 1, 0)
978 jonathan 460
979    
980 jonathan 415 ID_SELPROP_OK = 4001
981     ID_SELPROP_CANCEL = 4002
982     ID_SELPROP_SPINCTRL = 4002
983 jonathan 430 ID_SELPROP_PREVIEW = 4003
984     ID_SELPROP_STROKECLR = 4004
985     ID_SELPROP_FILLCLR = 4005
986 jonathan 485 ID_SELPROP_STROKECLRTRANS = 4006
987     ID_SELPROP_FILLCLRTRANS = 4007
988 jonathan 415
989     class SelectPropertiesDialog(wxDialog):
990    
991     def __init__(self, parent, prop, shapeType):
992     wxDialog.__init__(self, parent, -1, _("Select Properties"),
993 jonathan 507 style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
994 jonathan 415
995 jonathan 441 self.prop = ClassGroupProperties(prop)
996 jonathan 415
997 jonathan 430 topBox = wxBoxSizer(wxVERTICAL)
998 jonathan 415
999 jonathan 430 itemBox = wxBoxSizer(wxHORIZONTAL)
1000    
1001     # preview box
1002     previewBox = wxBoxSizer(wxVERTICAL)
1003     previewBox.Add(wxStaticText(self, -1, _("Preview:")),
1004     0, wxALIGN_LEFT | wxALL, 4)
1005 jonathan 549 self.previewWin = ClassDataPreviewWindow(None, self.prop, shapeType,
1006 jonathan 430 self, ID_SELPROP_PREVIEW, (40, 40))
1007 jonathan 549 previewBox.Add(self.previewWin, 1, wxGROW, 15)
1008 jonathan 430
1009     itemBox.Add(previewBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)
1010    
1011     # control box
1012     ctrlBox = wxBoxSizer(wxVERTICAL)
1013 jonathan 485
1014     lineColorBox = wxBoxSizer(wxHORIZONTAL)
1015     lineColorBox.Add(
1016 jonathan 500 wxButton(self, ID_SELPROP_STROKECLR, _("Change Line Color")),
1017 jonathan 485 1, wxALL | wxGROW, 4)
1018 jonathan 460 EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)
1019 jonathan 430
1020 jonathan 485 lineColorBox.Add(
1021 jonathan 500 wxButton(self, ID_SELPROP_STROKECLRTRANS, _("Transparent")),
1022 jonathan 485 1, wxALL | wxGROW, 4)
1023     EVT_BUTTON(self, ID_SELPROP_STROKECLRTRANS,
1024     self._OnChangeLineColorTrans)
1025    
1026     ctrlBox.Add(lineColorBox, 0,
1027     wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)
1028    
1029 jonathan 430 if shapeType != SHAPETYPE_ARC:
1030 jonathan 485 fillColorBox = wxBoxSizer(wxHORIZONTAL)
1031     fillColorBox.Add(
1032 jonathan 500 wxButton(self, ID_SELPROP_FILLCLR, _("Change Fill Color")),
1033 jonathan 485 1, wxALL | wxGROW, 4)
1034 jonathan 460 EVT_BUTTON(self, ID_SELPROP_FILLCLR, self._OnChangeFillColor)
1035 jonathan 485 fillColorBox.Add(
1036 jonathan 500 wxButton(self, ID_SELPROP_FILLCLRTRANS, _("Transparent")),
1037 jonathan 485 1, wxALL | wxGROW, 4)
1038     EVT_BUTTON(self, ID_SELPROP_FILLCLRTRANS,
1039     self._OnChangeFillColorTrans)
1040     ctrlBox.Add(fillColorBox, 0,
1041     wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)
1042 jonathan 430
1043 jonathan 415 spinBox = wxBoxSizer(wxHORIZONTAL)
1044 jonathan 460 spinBox.Add(wxStaticText(self, -1, _("Line Width: ")),
1045 jonathan 430 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 4)
1046 jonathan 415 self.spinCtrl = wxSpinCtrl(self, ID_SELPROP_SPINCTRL,
1047     min=1, max=10,
1048 jonathan 460 value=str(prop.GetLineWidth()),
1049     initial=prop.GetLineWidth())
1050 jonathan 415
1051 jonathan 460 EVT_SPINCTRL(self, ID_SELPROP_SPINCTRL, self._OnSpin)
1052 jonathan 415
1053     spinBox.Add(self.spinCtrl, 0, wxALIGN_LEFT | wxALL, 4)
1054    
1055 jonathan 430 ctrlBox.Add(spinBox, 0, wxALIGN_RIGHT | wxALL, 0)
1056     itemBox.Add(ctrlBox, 0, wxALIGN_RIGHT | wxALL | wxGROW, 0)
1057     topBox.Add(itemBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)
1058 jonathan 415
1059     #
1060     # Control buttons:
1061     #
1062     buttonBox = wxBoxSizer(wxHORIZONTAL)
1063 jonathan 485 buttonBox.Add(wxButton(self, ID_SELPROP_OK, _("OK")),
1064 jonathan 415 0, wxALL, 4)
1065 jonathan 485 buttonBox.Add(wxButton(self, ID_SELPROP_CANCEL, _("Cancel")),
1066 jonathan 415 0, wxALL, 4)
1067     topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)
1068    
1069 jonathan 460 EVT_BUTTON(self, ID_SELPROP_OK, self._OnOK)
1070     EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)
1071 jonathan 415
1072 jonathan 509 self.SetAutoLayout(True)
1073 jonathan 415 self.SetSizer(topBox)
1074     topBox.Fit(self)
1075     topBox.SetSizeHints(self)
1076    
1077 jonathan 460 def _OnOK(self, event):
1078 jonathan 372 self.EndModal(wxID_OK)
1079    
1080 jonathan 460 def _OnCancel(self, event):
1081 jonathan 372 self.EndModal(wxID_CANCEL)
1082    
1083 jonathan 460 def _OnSpin(self, event):
1084     self.prop.SetLineWidth(self.spinCtrl.GetValue())
1085 jonathan 549 self.previewWin.Refresh()
1086 jonathan 392
1087 jonathan 430 def __GetColor(self, cur):
1088     dialog = wxColourDialog(self)
1089     dialog.GetColourData().SetColour(Color2wxColour(cur))
1090     ret = None
1091     if dialog.ShowModal() == wxID_OK:
1092     ret = wxColour2Color(dialog.GetColourData().GetColour())
1093    
1094     dialog.Destroy()
1095    
1096     return ret
1097    
1098 jonathan 460 def _OnChangeLineColor(self, event):
1099     clr = self.__GetColor(self.prop.GetLineColor())
1100 jonathan 430 if clr is not None:
1101 jonathan 460 self.prop.SetLineColor(clr)
1102 jonathan 549 self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1103 jonathan 430
1104 jonathan 485 def _OnChangeLineColorTrans(self, event):
1105     self.prop.SetLineColor(Color.None)
1106 jonathan 549 self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1107 jonathan 485
1108 jonathan 460 def _OnChangeFillColor(self, event):
1109 jonathan 430 clr = self.__GetColor(self.prop.GetFill())
1110     if clr is not None:
1111     self.prop.SetFill(clr)
1112 jonathan 549 self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1113 jonathan 430
1114 jonathan 485 def _OnChangeFillColorTrans(self, event):
1115     self.prop.SetFill(Color.None)
1116 jonathan 549 self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1117 jonathan 485
1118 jonathan 441 def GetClassGroupProperties(self):
1119 jonathan 415 return self.prop
1120 jonathan 392
1121    
1122 jonathan 549 class ClassDataPreviewWindow(wxWindow):
1123 jonathan 415
1124 jonathan 441 def __init__(self, rect, prop, shapeType,
1125 jonathan 430 parent = None, id = -1, size = wxDefaultSize):
1126     if parent is not None:
1127 jonathan 549 wxWindow.__init__(self, parent, id, (0, 0), size)
1128 jonathan 460 EVT_PAINT(self, self._OnPaint)
1129 jonathan 415
1130 jonathan 430 self.rect = rect
1131 jonathan 549
1132 jonathan 441 self.prop = prop
1133 jonathan 430 self.shapeType = shapeType
1134 jonathan 549 self.previewer = ClassDataPreviewer()
1135 jonathan 430
1136 jonathan 460 def _OnPaint(self, event):
1137 jonathan 430 dc = wxPaintDC(self)
1138    
1139     # XXX: this doesn't seem to be having an effect:
1140     dc.DestroyClippingRegion()
1141    
1142 jonathan 549 if self.rect is None:
1143     w, h = self.GetSize()
1144     rect = wxRect(0, 0, w, h)
1145     else:
1146     rect = self.rect
1147 jonathan 430
1148 jonathan 549 self.previewer.Draw(dc, rect, self.prop, self.shapeType)
1149 jonathan 430
1150 jonathan 549 class ClassDataPreviewer:
1151 jonathan 430
1152 jonathan 549 def Draw(self, dc, rect, prop, shapeType):
1153    
1154     assert(dc is not None)
1155     assert(isinstance(prop, ClassGroupProperties))
1156    
1157 jonathan 430 if rect is None:
1158 jonathan 549 x = 0
1159     y = 0
1160     w, h = dc.GetSize()
1161 jonathan 430 else:
1162     x = rect.GetX()
1163     y = rect.GetY()
1164     w = rect.GetWidth()
1165     h = rect.GetHeight()
1166    
1167 jonathan 460 stroke = prop.GetLineColor()
1168 jonathan 415 if stroke is Color.None:
1169 jonathan 392 pen = wxTRANSPARENT_PEN
1170     else:
1171 jonathan 430 pen = wxPen(Color2wxColour(stroke),
1172 jonathan 460 prop.GetLineWidth(),
1173 jonathan 392 wxSOLID)
1174    
1175 jonathan 441 stroke = prop.GetFill()
1176 jonathan 415 if stroke is Color.None:
1177 jonathan 392 brush = wxTRANSPARENT_BRUSH
1178     else:
1179 jonathan 430 brush = wxBrush(Color2wxColour(stroke), wxSOLID)
1180 jonathan 392
1181     dc.SetPen(pen)
1182     dc.SetBrush(brush)
1183    
1184 jonathan 415 if shapeType == SHAPETYPE_ARC:
1185 jonathan 430 dc.DrawSpline([wxPoint(x, y + h),
1186     wxPoint(x + w/2, y + h/4),
1187     wxPoint(x + w/2, y + h/4*3),
1188     wxPoint(x + w, y)])
1189 jonathan 392
1190 jonathan 415 elif shapeType == SHAPETYPE_POINT or \
1191     shapeType == SHAPETYPE_POLYGON:
1192    
1193 jonathan 430 dc.DrawCircle(x + w/2, y + h/2,
1194 jonathan 460 (min(w, h) - prop.GetLineWidth())/2)
1195 jonathan 392
1196 jonathan 415 class ClassRenderer(wxPyGridCellRenderer):
1197    
1198     def __init__(self, shapeType):
1199     wxPyGridCellRenderer.__init__(self)
1200 jonathan 549 self.shapeType = shapeType
1201     self.previewer = ClassDataPreviewer()
1202 jonathan 415
1203     def Draw(self, grid, attr, dc, rect, row, col, isSelected):
1204 jonathan 485 data = grid.GetTable().GetClassGroup(row)
1205 jonathan 415
1206     dc.SetClippingRegion(rect.GetX(), rect.GetY(),
1207     rect.GetWidth(), rect.GetHeight())
1208     dc.SetPen(wxPen(wxLIGHT_GREY))
1209     dc.SetBrush(wxBrush(wxLIGHT_GREY, wxSOLID))
1210     dc.DrawRectangle(rect.GetX(), rect.GetY(),
1211     rect.GetWidth(), rect.GetHeight())
1212    
1213 jonathan 441 if not isinstance(data, ClassGroupMap):
1214 jonathan 549 self.previewer.Draw(dc, rect, data.GetProperties(), self.shapeType)
1215 jonathan 415
1216     if isSelected:
1217     dc.SetPen(wxPen(wxColour(0 * 255, 0 * 255, 0 * 255),
1218     4, wxSOLID))
1219     dc.SetBrush(wxTRANSPARENT_BRUSH)
1220     dc.DrawRectangle(rect.GetX(), rect.GetY(),
1221     rect.GetWidth(), rect.GetHeight())
1222    
1223 jonathan 392 dc.DestroyClippingRegion()
1224    

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26