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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 430 by jonathan, Mon Feb 24 18:47:06 2003 UTC revision 455 by bh, Tue Mar 4 11:32:20 2003 UTC
# Line 16  from wxPython.grid import * Line 16  from wxPython.grid import *
16    
17  from Thuban import _  from Thuban import _
18  from Thuban.common import *  from Thuban.common import *
19    from Thuban.UI.common import *
20    
21  from Thuban.Model.classification import * #Classification, ClassData  from Thuban.Model.classification import *
22    
23  from Thuban.Model.color import Color  from Thuban.Model.color import Color
24    
# Line 30  ID_CLASSIFY_OK = 4001 Line 31  ID_CLASSIFY_OK = 4001
31  ID_CLASSIFY_CANCEL = 4002  ID_CLASSIFY_CANCEL = 4002
32  ID_CLASSIFY_ADD = 4003  ID_CLASSIFY_ADD = 4003
33  ID_CLASSIFY_GENRANGE = 4004  ID_CLASSIFY_GENRANGE = 4004
34    ID_CLASSIFY_REMOVE = 4005
35    
36  COL_VISUAL = 0  COL_VISUAL = 0
37  COL_VALUE  = 1  COL_VALUE  = 1
38  COL_LABEL  = 2  COL_LABEL  = 2
39    
40    FIELD_CLASS = 0
41    FIELD_TYPE = 1
42    FIELD_NAME = 2
43    
44    FIELD_TYPE_STRING = "string"
45    FIELD_TYPE_INT = "int"
46    FIELD_TYPE_DOUBLE = "double"
47    
48  #  #
49  # this is a silly work around to ensure that the table that is  # this is a silly work around to ensure that the table that is
50  # passed into SetTable is the same that is returned by GetTable  # passed into SetTable is the same that is returned by GetTable
# Line 42  COL_LABEL  = 2 Line 52  COL_LABEL  = 2
52  import weakref  import weakref
53  class ClassGrid(wxGrid):  class ClassGrid(wxGrid):
54    
55      def __init__(self, parent, layer):      def __init__(self, parent, layer, fieldData):
56          wxGrid.__init__(self, parent, ID_CLASS_TABLE, size = (300, 150))          wxGrid.__init__(self, parent, ID_CLASS_TABLE, size = (340, 160))
57          self.SetTable(          self.SetTable(ClassTable(fieldData, layer.ShapeType(), self), true)
58              ClassTable(layer.GetClassification(), layer.ShapeType(), self),          self.SetSelectionMode(wxGrid.wxGridSelectRows)
59              true)          EVT_GRID_CELL_LEFT_DCLICK(self, self.OnCellDClick)
60    
61            EVT_GRID_RANGE_SELECT(self, self._OnSelectedRange)
62            EVT_GRID_SELECT_CELL(self, self._OnSelectedCell)
63    
64            self.layer = layer
65            self.currentSelection = []
66    
67        def GetCurrentSelection(self):
68            sel = copy.copy(self.currentSelection)
69            sel.sort()
70            return sel
71    
72      def SetCellRenderer(self, row, col):      def SetCellRenderer(self, row, col):
73          raise ValueError(_("Must not allow setting of renderer in ClassGrid!"))          raise ValueError(_("Must not allow setting of renderer in ClassGrid!"))
# Line 58  class ClassGrid(wxGrid): Line 79  class ClassGrid(wxGrid):
79      def GetTable(self):      def GetTable(self):
80          return self.tableRef()          return self.tableRef()
81    
82        def DeleteSelectedRows(self):
83            sel = self.GetCurrentSelection()
84    
85            if len(sel) == 0: return
86            if len(sel) == 1:
87                group = self.GetTable().GetValueAsCustom(sel[0], COL_VISUAL, None)
88                if isinstance(group, ClassGroupDefault):
89                    wxMessageDialog(self,
90                                    "The Default group cannot be removed.",
91                                    style = wxOK | wxICON_EXCLAMATION).ShowModal()
92                    return
93            
94            self.ClearSelection()
95    
96            sel.reverse()
97            table = self.GetTable()
98            for row in sel:
99                table.DeleteRows(row)
100    
101            if len(sel) == 1:
102                r = sel[0]
103                if r > self.GetNumberRows() - 1:
104                    r = self.GetNumberRows() - 1
105                self.SelectRow(r)
106            
107    #
108    # XXX: This isn't working, and there is no way to deselect rows wxPython!
109    #
110    #   def DeselectRow(self, row):
111    #       self.ProcessEvent(
112    #           wxGridRangeSelectEvent(-1,
113    #                                  wxEVT_GRID_RANGE_SELECT,
114    #                                  self,
115    #                                  (row, row), (row, row),
116    #                                  sel = False))
117    
118        def OnCellDClick(self, event):
119            r = event.GetRow()
120            c = event.GetCol()
121            if c == COL_VISUAL:
122                # XXX: getting the properties is only possible with non-Maps!!!
123                group = self.GetTable().GetValueAsCustom(r, c, None)
124                prop = group.GetProperties()
125                propDlg = SelectPropertiesDialog(NULL, prop, self.layer.ShapeType())
126                if propDlg.ShowModal() == wxID_OK:
127                    new_prop = propDlg.GetClassGroupProperties()
128                    prop.SetStroke(new_prop.GetStroke())
129                    prop.SetStrokeWidth(new_prop.GetStrokeWidth())
130                    prop.SetFill(new_prop.GetFill())
131                    self.Refresh()
132                propDlg.Destroy()
133    
134        #
135        # _OnSelectedRange() and _OnSelectedCell() were borrowed
136        # from http://wiki.wxpython.org
137        #
138        def _OnSelectedRange(self, event):
139            """Internal update to the selection tracking list"""
140            if event.Selecting():
141                for index in range( event.GetTopRow(), event.GetBottomRow()+1):
142                    if index not in self.currentSelection:
143                        self.currentSelection.append( index )
144            else:
145                for index in range( event.GetTopRow(), event.GetBottomRow()+1):
146                    while index in self.currentSelection:
147                        self.currentSelection.remove( index )
148            #self.ConfigureForSelection()
149    
150            event.Skip()
151    
152        def _OnSelectedCell( self, event ):
153            """Internal update to the selection tracking list"""
154            self.currentSelection = [ event.GetRow() ]
155            #self.ConfigureForSelection()
156            event.Skip()
157    
158  class ClassTable(wxPyGridTableBase):  class ClassTable(wxPyGridTableBase):
159    
160      NUM_COLS = 3      NUM_COLS = 3
161    
162      __col_labels = [_("Visual"), _("Value"), _("Label")]      __col_labels = [_("Symbol"), _("Value"), _("Label")]
   
     # this is tied to the values of classification.ClassData  
     __row_labels = [_("Default"), _("Point"), _("Range"), _("Map")]  
163    
164      def __init__(self, clazz, shapeType, view = None):      def __init__(self, fieldData, shapeType, view = None):
165          wxPyGridTableBase.__init__(self)          wxPyGridTableBase.__init__(self)
166          self.SetView(view)          self.SetView(view)
167          self.tdata = []          self.tdata = []
168    
169          self.Reset(clazz, shapeType)          self.Reset(fieldData, shapeType)
170    
171      def Reset(self, clazz, shapeType):      def Reset(self, fieldData, shapeType):
172    
173          self.GetView().BeginBatch()          self.GetView().BeginBatch()
174    
175            self.fieldData = fieldData
176          self.shapeType = shapeType          self.shapeType = shapeType
177          self.renderer = ClassRenderer(self.shapeType)          self.renderer = ClassRenderer(self.shapeType)
178    
179          old_tdata = self.tdata          old_len = len(self.tdata)
180    
181          self.tdata = []          self.tdata = []
182    
183            clazz = fieldData[FIELD_CLASS]
184          if clazz is None:          if clazz is None:
185              clazz = Classification()              clazz = Classification()
186    
187          p = clazz.GetDefaultData()  #       p = clazz.GetDefaultGroup()
188          np = ClassDataDefault(classData = p)  #       np = ClassDataDefault(classData = p)
189          self.tdata.append([np, 'DEFAULT', np.GetLabel()])  #       self.tdata.append([np, 'DEFAULT', np.GetLabel()])
190    
191          for p in clazz.points.values():  #       for p in clazz.points.values():
192              np = ClassDataPoint(p.GetValue(), classData = p)  #           np = ClassDataPoint(p.GetValue(), classData = p)
193              self.tdata.append([np, np.GetValue(), np.GetLabel()])  #           self.tdata.append([np, np.GetValue(), np.GetLabel()])
194    
195          for p in clazz.ranges:  #       for p in clazz.ranges:
196              np = ClassDataRange(p.GetMin(), p.GetMax(), classData = p)  #           np = ClassDataRange(p.GetMin(), p.GetMax(), classData = p)
197              self.tdata.append([np,  #           self.tdata.append([np,
198                                 '%s - %s' % (np.GetMin(), np.GetMax()),  #                              '%s - %s' % (np.GetMin(), np.GetMax()),
199                                 np.GetLabel()])  #                              np.GetLabel()])
200    
201            i = 0
202            for p in clazz:
203                np = copy.copy(p)
204                self.__SetRow(i, np)
205                i += 1
206    
207    
208          self.modified = 0          self.modified = 0
209    
210            self.__NotifyRowChanges(old_len, len(self.tdata))
211            self.GetView().EndBatch()
212    
213        def __NotifyRowChanges(self, curRows, newRows):
214          #          #
215          # silly message processing for updates to the number of          # silly message processing for updates to the number of
216          # rows and columns          # rows and columns
217          #          #
         curRows = len(old_tdata)  
         newRows = len(self.tdata)  
218          if newRows > curRows:          if newRows > curRows:
219              msg = wxGridTableMessage(self,              msg = wxGridTableMessage(self,
220                          wxGRIDTABLE_NOTIFY_ROWS_APPENDED,                          wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
# Line 123  class ClassTable(wxPyGridTableBase): Line 227  class ClassTable(wxPyGridTableBase):
227                          curRows - newRows)    # how many                          curRows - newRows)    # how many
228              self.GetView().ProcessTableMessage(msg)              self.GetView().ProcessTableMessage(msg)
229    
230          self.GetView().EndBatch()  
231        def __SetRow(self, row, group):
232    
233            if isinstance(group, ClassGroupDefault):
234                data = [group, _('DEFAULT'), group.GetLabel()]
235            elif isinstance(group, ClassGroupSingleton):
236                data = [group, group.GetValue(), group.GetLabel()]
237            elif isinstance(group, ClassGroupRange):
238                data = [group,
239                        _('%s - %s') % (group.GetMin(), group.GetMax()),
240                        group.GetLabel()]
241    
242            if row >= len(self.tdata):
243                self.tdata.append(data)
244            else:
245                self.tdata[row] = data
246    
247      def GetColLabelValue(self, col):      def GetColLabelValue(self, col):
248          return self.__col_labels[col]          return self.__col_labels[col]
249    
250      def GetRowLabelValue(self, row):      def GetRowLabelValue(self, row):
251          data = self.tdata[row][COL_VISUAL]          data = self.tdata[row][COL_VISUAL]
252          type = data.GetType()          if isinstance(data, ClassGroupDefault):   return _("Default")
253          return self.__row_labels[type]          if isinstance(data, ClassGroupSingleton): return _("Singleton")
254            if isinstance(data, ClassGroupRange):     return _("Range")
255            if isinstance(data, ClassGroupMap):       return _("Map")
256    
257      def GetNumberRows(self):      def GetNumberRows(self):
258          return len(self.tdata)          return len(self.tdata)
# Line 157  class ClassTable(wxPyGridTableBase): Line 278  class ClassTable(wxPyGridTableBase):
278             (a single number or a range)             (a single number or a range)
279          """          """
280    
281          #          type = self.fieldData[FIELD_TYPE]
282          # first try to take the input as a single number  
283          # if there's an exception try to break it into          if type == FIELD_TYPE_STRING:
284          # a range seperated by a '-'. take care to ignore              return (value,)
285          # a leading '-' as that could be for a negative number.          elif type == FIELD_TYPE_INT or type == FIELD_TYPE_DOUBLE:
286          # then try to parse the individual parts. if there  
287          # is an exception here, let it pass up to the calling              #
288          # function.              # first try to take the input as a single number
289          #              # if there's an exception try to break it into
290          try:              # a range seperated by a '-'. take care to ignore
291              return (ClassData.POINT, Str2Num(value))              # a leading '-' as that could be for a negative number.
292          except:              # then try to parse the individual parts. if there
293              i = value.find('-')              # is an exception here, let it pass up to the calling
294              if i == 0:              # function.
295                  i = value.find('-', 1)              #
296                try:
297              return (ClassData.RANGE,                  return (Str2Num(value),)
298                      Str2Num(value[:i]),              except:
299                      Str2Num(value[i+1:]))                  i = value.find('-')
300                    if i == 0:
301                        i = value.find('-', 1)
302    
303                    return (Str2Num(value[:i]), Str2Num(value[i+1:]))
304                            
305    
306      def SetValueAsCustom(self, row, col, typeName, value):      def SetValueAsCustom(self, row, col, typeName, value):
307          data = self.tdata[row][COL_VISUAL]          group = self.tdata[row][COL_VISUAL]
308    
309          if col == COL_VISUAL:          if col == COL_VISUAL:
310              self.tdata[row][COL_VISUAL] = value              self.tdata[row][COL_VISUAL] = value
311          elif col == COL_VALUE:          elif col == COL_VALUE:
312              if row != 0: # DefaultData row              if isinstance(group, ClassGroupDefault):
313                  type = data.GetType()                  # not allowed to modify the default value
314                    pass
315                  if type == ClassData.MAP:              elif isinstance(group, ClassGroupMap):
316                      # something special                  # something special
317                    pass
318                else: # SINGLETON, RANGE
319                    try:
320                        dataInfo = self.__ParseInput(value)
321                    except:
322                        # bad input, ignore the request
323                      pass                      pass
324                  else: # POINT, RANGE                  else:
                     try:  
                         dataInfo = self.__ParseInput(value)  
                     except: pass  
                         # bad input, ignore the request  
                     else:  
325    
326                          if dataInfo[0] == ClassData.POINT:                      ngroup = group
327                              if type != ClassData.POINT:                      props = group.GetProperties()
328                                  data = ClassDataPoint(classData = data)                      if len(dataInfo) == 1:
329                              data.SetValue(dataInfo[1])                          if not isinstance(group, ClassGroupSingleton):
330                              self.tdata[row][COL_VALUE] = data.GetValue()                              ngroup = ClassGroupSingleton(prop = props)
331                          elif dataInfo[0] == ClassData.RANGE:                          ngroup.SetValue(dataInfo[0])
332                              if type != ClassData.RANGE:                      elif len(dataInfo) == 2:
333                                  data = ClassDataRange(classData = data)                          if not isinstance(group, ClassGroupRange):
334                              data.SetRange(dataInfo[1], dataInfo[2])                              ngroup = ClassGroupRange(prop = props)
335                              self.tdata[row][COL_VALUE] = \                          ngroup.SetRange(dataInfo[0], dataInfo[1])
336                                  "%s - %s" % (data.GetMin(), data.GetMax())                      else:
337                            assert(False)
338    
339                          self.tdata[row][COL_VISUAL] = data                      ngroup.SetLabel(group.GetLabel())
340                        self.__SetRow(row, ngroup)
341    
342                          self.GetView().Refresh()                      self.GetView().Refresh()
343    
344          elif col == COL_LABEL:          elif col == COL_LABEL:
345              data.SetLabel(value)              group.SetLabel(value)
346              self.tdata[row][COL_LABEL] = data.GetLabel()              self.tdata[row][COL_LABEL] = group.GetLabel()
347          else:          else:
348              raise ValueError(_("Invalid column request"))              raise ValueError(_("Invalid column request"))
349    
# Line 231  class ClassTable(wxPyGridTableBase): Line 359  class ClassTable(wxPyGridTableBase):
359    
360          return attr          return attr
361    
362      def GetClassData(self, row):      def GetClassGroup(self, row):
363          return self.tdata[row][COL_VISUAL]          return self.tdata[row][COL_VISUAL]
364    
365      def __Modified(self):      def __Modified(self):
# Line 240  class ClassTable(wxPyGridTableBase): Line 368  class ClassTable(wxPyGridTableBase):
368      def IsModified(self):      def IsModified(self):
369          return self.modified          return self.modified
370    
371      def AddNewDataRow(self):      def DeleteRows(self, pos, numRows = 1):
372          np = ClassDataPoint()          assert(pos >= 0)
373          self.tdata.append([np, np.GetValue(), np.GetLabel()])          old_len = len(self.tdata)
374          msg = wxGridTableMessage(self, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1)          for row in range(pos, pos - numRows, -1):
375          self.GetView().ProcessTableMessage(msg)              group = self.GetValueAsCustom(row, COL_VISUAL, None)
376          self.GetView().Refresh()              if not isinstance(group, ClassGroupDefault):
377                    self.tdata.pop(row)
378                    self.__Modified()
379        
380            if self.IsModified():
381                self.__NotifyRowChanges(old_len, len(self.tdata))
382    
383        def AppendRows(self, numRows = 1):
384            old_len = len(self.tdata)
385            for i in range(numRows):
386                np = ClassGroupSingleton()
387                self.tdata.append([np, np.GetValue(), np.GetLabel()])
388                self.__Modified()
389    
390            if self.IsModified():
391                self.__NotifyRowChanges(old_len, len(self.tdata))
392    
393    
394  class Classifier(wxDialog):  class Classifier(wxDialog):
395            
396      def __init__(self, parent, layer):      def __init__(self, parent, layer):
397          wxDialog.__init__(self, parent, -1, _("Classify"),          wxDialog.__init__(self, parent, -1, _("Classify"),
398                            style = wxRESIZE_BORDER)                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
399    
400    
401          self.layer = layer          self.layer = layer
402    
403          topBox = wxBoxSizer(wxVERTICAL)          topBox = wxBoxSizer(wxVERTICAL)
404    
405          topBox.Add(wxStaticText(self, -1, _("Layer: %s") % layer.Title()),          topBox.Add(wxStaticText(self, -1, _("Layer: %s") % layer.Title()),
406              0, wxALIGN_LEFT | wxBOTTOM, 4)              0, wxALIGN_LEFT | wxALL, 4)
407          topBox.Add(wxStaticText(self, -1, _("Type: %s") % layer.ShapeType()),          topBox.Add(wxStaticText(self, -1, _("Type: %s") % layer.ShapeType()),
408              0, wxALIGN_LEFT | wxBOTTOM, 4)              0, wxALIGN_LEFT | wxALL, 4)
409    
410          propertyBox = wxBoxSizer(wxHORIZONTAL)          propertyBox = wxBoxSizer(wxHORIZONTAL)
411          propertyBox.Add(wxStaticText(self, -1, _("Property: ")),          propertyBox.Add(wxStaticText(self, -1, _("Field: ")),
412              0, wxALIGN_CENTER | wxALL, 4)              0, wxALIGN_CENTER | wxALL, 4)
413    
414          self.properties = wxComboBox(self, ID_PROPERTY_SELECT, "",          self.fields = wxComboBox(self, ID_PROPERTY_SELECT, "",
415                                       style = wxCB_READONLY)                                       style = wxCB_READONLY)
416    
417          self.num_cols = layer.table.field_count()          self.num_cols = layer.table.field_count()
418          self.__cur_prop = -1          # just assume the first field in case one hasn't been
419          field = layer.GetClassification().GetField()          # specified in the file.
420            self.__cur_field = 0
421            clazz = layer.GetClassification()
422            field = clazz.GetField()
423          for i in range(self.num_cols):          for i in range(self.num_cols):
424              type, name, len, decc = layer.table.field_info(i)              type, name, len, decc = layer.table.field_info(i)
425                self.fields.Append(name)
426    
427              if name == field:              if name == field:
428                  self.__cur_prop = i                  self.__cur_field = i
429              self.properties.Append(name)                  self.fields.SetClientData(i, [clazz, type, name, len, decc])
430              self.properties.SetClientData(i, None)              else:
431                    self.fields.SetClientData(i, [None, type, name, len, decc])
432          self.properties.SetSelection(self.__cur_prop)  
433          propertyBox.Add(self.properties, 1, wxGROW|wxALL, 0)          self.fields.SetSelection(self.__cur_field)
434          EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self.OnPropertySelect)  
435            propertyBox.Add(self.fields, 1, wxGROW|wxALL, 4)
436            EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self.OnFieldSelect)
437    
438          topBox.Add(propertyBox, 0, wxGROW, 4)          topBox.Add(propertyBox, 0, wxGROW, 4)
439    
# Line 290  class Classifier(wxDialog): Line 442  class Classifier(wxDialog):
442          #          #
443    
444          controlBox = wxBoxSizer(wxHORIZONTAL)          controlBox = wxBoxSizer(wxHORIZONTAL)
445          self.classGrid = ClassGrid(self, layer)          self.classGrid = ClassGrid(self,
446                                       layer,
447                                       self.fields.GetClientData(self.__cur_field))
448    
449          controlBox.Add(self.classGrid, 1, wxGROW, 0)          controlBox.Add(self.classGrid, 1, wxGROW, 0)
450    
# Line 300  class Classifier(wxDialog): Line 454  class Classifier(wxDialog):
454          controlButtonBox.Add(wxButton(self, ID_CLASSIFY_GENRANGE,          controlButtonBox.Add(wxButton(self, ID_CLASSIFY_GENRANGE,
455              _("Generate Ranges")), 0, wxGROW | wxALL, 4)              _("Generate Ranges")), 0, wxGROW | wxALL, 4)
456    
457            controlButtonBox.Add(wxButton(self, ID_CLASSIFY_REMOVE,
458                _("Remove")), 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
459    
460          controlBox.Add(controlButtonBox, 0, wxGROW, 10)          controlBox.Add(controlButtonBox, 0, wxGROW, 10)
461          topBox.Add(controlBox, 1, wxGROW, 10)          topBox.Add(controlBox, 1, wxGROW, 10)
462    
463          EVT_BUTTON(self, ID_CLASSIFY_ADD, self.OnAdd)          EVT_BUTTON(self, ID_CLASSIFY_ADD, self.OnAdd)
464            EVT_BUTTON(self, ID_CLASSIFY_REMOVE, self.OnRemove)
465          EVT_BUTTON(self, ID_CLASSIFY_GENRANGE, self.OnGenRange)          EVT_BUTTON(self, ID_CLASSIFY_GENRANGE, self.OnGenRange)
         EVT_GRID_CELL_LEFT_DCLICK(self.classGrid, self.OnCellDClick)  
466    
467          #          #
468          # Control buttons:          # Control buttons:
# Line 320  class Classifier(wxDialog): Line 477  class Classifier(wxDialog):
477          EVT_BUTTON(self, ID_CLASSIFY_OK, self.OnOK)          EVT_BUTTON(self, ID_CLASSIFY_OK, self.OnOK)
478          EVT_BUTTON(self, ID_CLASSIFY_CANCEL, self.OnCancel)          EVT_BUTTON(self, ID_CLASSIFY_CANCEL, self.OnCancel)
479    
480    
481    
482          self.SetAutoLayout(true)          self.SetAutoLayout(true)
483          self.SetSizer(topBox)          self.SetSizer(topBox)
484          topBox.Fit(self)          topBox.Fit(self)
# Line 328  class Classifier(wxDialog): Line 487  class Classifier(wxDialog):
487      def __BuildClassification(self, prop):      def __BuildClassification(self, prop):
488    
489          clazz = Classification()          clazz = Classification()
490          clazz.SetField(self.properties.GetStringSelection())          clazz.SetField(self.fields.GetString(prop))
491    
492          numRows = self.classGrid.GetNumberRows()          numRows = self.classGrid.GetNumberRows()
493    
494          if numRows > 0:          if numRows > 0:
495              table = self.classGrid.GetTable()              table = self.classGrid.GetTable()
496              clazz.SetDefaultData(table.GetClassData(0))              clazz.SetDefaultGroup(table.GetClassGroup(0))
497    
498              for i in range(1, numRows):              for i in range(1, numRows):
499                  clazz.AddClassData(table.GetClassData(i))                  clazz.AddGroup(table.GetClassGroup(i))
500    
501          return clazz          return clazz
502    
503      def OnPropertySelect(self, event):      def OnFieldSelect(self, event):
504          self.properties.SetClientData(          data = self.fields.GetClientData(self.__cur_field)
505              self.__cur_prop, self.__BuildClassification(self.__cur_prop))          data[FIELD_CLASS] = self.__BuildClassification(self.__cur_field)
506    
507          self.__cur_prop = self.properties.GetSelection()          self.fields.SetClientData(self.__cur_field, data)
508          clazz = self.properties.GetClientData(self.__cur_prop)  
509          table = self.classGrid.GetTable()          self.__cur_field = self.fields.GetSelection()
510            fieldData = self.fields.GetClientData(self.__cur_field)
511          table.Reset(clazz, self.layer.ShapeType())          self.classGrid.GetTable().Reset(fieldData, self.layer.ShapeType())
512    
513      def OnOK(self, event):      def OnOK(self, event):
514          """Put the data from the table into a new Classification and hand          """Put the data from the table into a new Classification and hand
515             it to the layer.             it to the layer.
516          """          """
517    
518          clazz = self.properties.GetClientData(self.__cur_prop)          clazz = self.fields.GetClientData(self.__cur_field)[FIELD_CLASS]
519    
520          #          #
521          # only build the classification if there wasn't one to          # only build the classification if there wasn't one to
522          # to begin with or it has been modified          # to begin with or it has been modified
523          #          #
524          if clazz is None or self.classGrid.GetTable().IsModified():          if clazz is None or self.classGrid.GetTable().IsModified():
525              clazz = self.__BuildClassification(self.__cur_prop)              clazz = self.__BuildClassification(self.__cur_field)
526    
527          clazz.SetLayer(self.layer)          clazz.SetLayer(self.layer)
528    
# Line 375  class Classifier(wxDialog): Line 534  class Classifier(wxDialog):
534          """Do nothing. The layer's current classification stays the same."""          """Do nothing. The layer's current classification stays the same."""
535          self.EndModal(wxID_CANCEL)          self.EndModal(wxID_CANCEL)
536    
   
537      def OnAdd(self, event):      def OnAdd(self, event):
538          self.classGrid.GetTable().AddNewDataRow()          self.classGrid.AppendRows()
539          print "Classifier.OnAdd()"  
540        def OnRemove(self, event):
541            self.classGrid.DeleteSelectedRows()
542    
543      def OnGenRange(self, event):      def OnGenRange(self, event):
544          print "Classifier.OnGenRange()"          print "Classifier.OnGenRange()"
545    
     def OnCellDClick(self, event):  
         r = event.GetRow()  
         c = event.GetCol()  
         if c == COL_VISUAL:  
             prop = self.classGrid.GetTable().GetValueAsCustom(r, c, None)  
             propDlg = SelectPropertiesDialog(NULL, prop, self.layer.ShapeType())  
             if propDlg.ShowModal() == wxID_OK:  
                 new_prop = propDlg.GetClassData()  
                 prop.SetStroke(new_prop.GetStroke())  
                 prop.SetStrokeWidth(new_prop.GetStrokeWidth())  
                 prop.SetFill(new_prop.GetFill())  
                 self.classGrid.Refresh()  
             propDlg.Destroy()  
   
546    
547  ID_SELPROP_OK = 4001  ID_SELPROP_OK = 4001
548  ID_SELPROP_CANCEL = 4002  ID_SELPROP_CANCEL = 4002
# Line 411  class SelectPropertiesDialog(wxDialog): Line 557  class SelectPropertiesDialog(wxDialog):
557          wxDialog.__init__(self, parent, -1, _("Select Properties"),          wxDialog.__init__(self, parent, -1, _("Select Properties"),
558                            style = wxRESIZE_BORDER)                            style = wxRESIZE_BORDER)
559    
560          self.prop = ClassData(classData = prop)          self.prop = ClassGroupProperties(prop)
561    
562          topBox = wxBoxSizer(wxVERTICAL)          topBox = wxBoxSizer(wxVERTICAL)
563    
# Line 431  class SelectPropertiesDialog(wxDialog): Line 577  class SelectPropertiesDialog(wxDialog):
577          ctrlBox = wxBoxSizer(wxVERTICAL)          ctrlBox = wxBoxSizer(wxVERTICAL)
578          ctrlBox.Add(          ctrlBox.Add(
579              wxButton(self, ID_SELPROP_STROKECLR, "Change Stroke Color"),              wxButton(self, ID_SELPROP_STROKECLR, "Change Stroke Color"),
580              0, wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)              1, wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)
581          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self.OnChangeStrokeColor)          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self.OnChangeStrokeColor)
582    
583          if shapeType != SHAPETYPE_ARC:          if shapeType != SHAPETYPE_ARC:
# Line 508  class SelectPropertiesDialog(wxDialog): Line 654  class SelectPropertiesDialog(wxDialog):
654              self.prop.SetFill(clr)              self.prop.SetFill(clr)
655          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer
656    
657      def GetClassData(self):      def GetClassGroupProperties(self):
658          return self.prop          return self.prop
659    
660    
661  class ClassDataPreviewer(wxWindow):  class ClassDataPreviewer(wxWindow):
662    
663      def __init__(self, rect, data, shapeType,      def __init__(self, rect, prop, shapeType,
664                         parent = None, id = -1, size = wxDefaultSize):                         parent = None, id = -1, size = wxDefaultSize):
665          if parent is not None:          if parent is not None:
666              wxWindow.__init__(self, parent, id, size=size)              wxWindow.__init__(self, parent, id, size=size)
667              EVT_PAINT(self, self.OnPaint)              EVT_PAINT(self, self.OnPaint)
668    
669          self.rect = rect          self.rect = rect
670          self.data = data          self.prop = prop
671          self.shapeType = shapeType          self.shapeType = shapeType
672    
673      def OnPaint(self, event):      def OnPaint(self, event):
# Line 532  class ClassDataPreviewer(wxWindow): Line 678  class ClassDataPreviewer(wxWindow):
678    
679          self.Draw(dc, None)          self.Draw(dc, None)
680    
681      def Draw(self, dc, rect, data = None, shapeType = None):      def Draw(self, dc, rect, prop = None, shapeType = None):
682    
683          if data is None: data = self.data          if prop is None: prop = self.prop
684          if shapeType is None: shapeType = self.shapeType          if shapeType is None: shapeType = self.shapeType
685    
686          if rect is None:          if rect is None:
# Line 546  class ClassDataPreviewer(wxWindow): Line 692  class ClassDataPreviewer(wxWindow):
692              w = rect.GetWidth()              w = rect.GetWidth()
693              h = rect.GetHeight()              h = rect.GetHeight()
694    
695          stroke = data.GetStroke()          stroke = prop.GetStroke()
696          if stroke is Color.None:          if stroke is Color.None:
697              pen = wxTRANSPARENT_PEN              pen = wxTRANSPARENT_PEN
698          else:          else:
699              pen = wxPen(Color2wxColour(stroke),              pen = wxPen(Color2wxColour(stroke),
700                          data.GetStrokeWidth(),                          prop.GetStrokeWidth(),
701                          wxSOLID)                          wxSOLID)
702    
703          stroke = data.GetFill()          stroke = prop.GetFill()
704          if stroke is Color.None:          if stroke is Color.None:
705              brush = wxTRANSPARENT_BRUSH              brush = wxTRANSPARENT_BRUSH
706          else:          else:
# Line 573  class ClassDataPreviewer(wxWindow): Line 719  class ClassDataPreviewer(wxWindow):
719               shapeType == SHAPETYPE_POLYGON:               shapeType == SHAPETYPE_POLYGON:
720    
721              dc.DrawCircle(x + w/2, y + h/2,              dc.DrawCircle(x + w/2, y + h/2,
722                            (min(w, h) - data.GetStrokeWidth())/2)                            (min(w, h) - prop.GetStrokeWidth())/2)
723    
724  class ClassRenderer(wxPyGridCellRenderer):  class ClassRenderer(wxPyGridCellRenderer):
725    
# Line 582  class ClassRenderer(wxPyGridCellRenderer Line 728  class ClassRenderer(wxPyGridCellRenderer
728          self.previewer = ClassDataPreviewer(None, None, shapeType)          self.previewer = ClassDataPreviewer(None, None, shapeType)
729    
730      def Draw(self, grid, attr, dc, rect, row, col, isSelected):      def Draw(self, grid, attr, dc, rect, row, col, isSelected):
731          data = grid.GetTable().GetValueAsCustom(row, col, "")          data = grid.GetTable().GetValueAsCustom(row, col, None)
   
732    
733          dc.SetClippingRegion(rect.GetX(), rect.GetY(),          dc.SetClippingRegion(rect.GetX(), rect.GetY(),
734                               rect.GetWidth(), rect.GetHeight())                               rect.GetWidth(), rect.GetHeight())
# Line 592  class ClassRenderer(wxPyGridCellRenderer Line 737  class ClassRenderer(wxPyGridCellRenderer
737          dc.DrawRectangle(rect.GetX(), rect.GetY(),          dc.DrawRectangle(rect.GetX(), rect.GetY(),
738                           rect.GetWidth(), rect.GetHeight())                           rect.GetWidth(), rect.GetHeight())
739    
740          self.previewer.Draw(dc, rect, data)          if not isinstance(data, ClassGroupMap):
741                self.previewer.Draw(dc, rect, data.GetProperties())
742    
743          if isSelected:          if isSelected:
744              dc.SetPen(wxPen(wxColour(0 * 255, 0 * 255, 0 * 255),              dc.SetPen(wxPen(wxColour(0 * 255, 0 * 255, 0 * 255),

Legend:
Removed from v.430  
changed lines
  Added in v.455

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26