/[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 460 by jonathan, Wed Mar 5 18:16:28 2003 UTC revision 560 by jonathan, Wed Mar 26 11:05:47 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001 by Intevation GmbH  # Copyright (c) 2001, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jonathan Coles <[email protected]>  # Jonathan Coles <[email protected]>
4  #  #
# Line 11  __version__ = "$Revision$" Line 11  __version__ = "$Revision$"
11    
12  import copy  import copy
13    
14    from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
15         FIELDTYPE_STRING
16    
17  from wxPython.wx import *  from wxPython.wx import *
18  from wxPython.grid import *  from wxPython.grid import *
19    
# Line 24  from Thuban.Model.color import Color Line 27  from Thuban.Model.color import Color
27    
28  from Thuban.Model.layer import Layer, SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT  from Thuban.Model.layer import Layer, SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT
29    
30    from dialogs import NonModalDialog
31    
32  # widget id's  # widget id's
33  ID_PROPERTY_SELECT = 4010  ID_PROPERTY_SELECT = 4010
34  ID_CLASS_TABLE = 40011  ID_CLASS_TABLE = 40011
# Line 35  ID_CLASSIFY_GENRANGE = 4004 Line 40  ID_CLASSIFY_GENRANGE = 4004
40  ID_CLASSIFY_REMOVE = 4005  ID_CLASSIFY_REMOVE = 4005
41  ID_CLASSIFY_MOVEUP = 4006  ID_CLASSIFY_MOVEUP = 4006
42  ID_CLASSIFY_MOVEDOWN = 4007  ID_CLASSIFY_MOVEDOWN = 4007
43    ID_CLASSIFY_APPLY = 4008
44    
45  # table columns  # table columns
46  COL_SYMBOL = 0  COL_SYMBOL = 0
# Line 62  class ClassGrid(wxGrid): Line 68  class ClassGrid(wxGrid):
68                   use for display.                   use for display.
69          """          """
70    
71          wxGrid.__init__(self, parent, ID_CLASS_TABLE, size = (340, 160))          #wxGrid.__init__(self, parent, ID_CLASS_TABLE, size = (340, 160))
72          self.SetTable(ClassTable(fieldData, layer.ShapeType(), self), true)          wxGrid.__init__(self, parent, ID_CLASS_TABLE)
73          self.SetSelectionMode(wxGrid.wxGridSelectRows)          #self.SetTable(ClassTable(fieldData, layer.ShapeType(), self), True)
74    
75          EVT_GRID_CELL_LEFT_DCLICK(self, self._OnCellDClick)          EVT_GRID_CELL_LEFT_DCLICK(self, self._OnCellDClick)
76          EVT_GRID_RANGE_SELECT(self, self._OnSelectedRange)          EVT_GRID_RANGE_SELECT(self, self._OnSelectedRange)
# Line 79  class ClassGrid(wxGrid): Line 85  class ClassGrid(wxGrid):
85          self.shapeType = shapeType          self.shapeType = shapeType
86          table = self.GetTable()          table = self.GetTable()
87          if table is None:          if table is None:
88              self.SetTable(ClassTable(clazz, self.shapeType, self), true)              w = self.GetDefaultColSize() * 3 + self.GetDefaultRowLabelSize()
89                h = self.GetDefaultRowSize() * 4 + self.GetDefaultColLabelSize()
90                self.SetDimensions(-1, -1, w, h)
91                self.SetSizeHints(w, h, -1, -1)
92                self.SetTable(ClassTable(clazz, self.shapeType, self), True)
93          else:          else:
94              table.Reset(clazz, self.shapeType)              table.Reset(clazz, self.shapeType)
95    
96            self.SetSelectionMode(wxGrid.wxGridSelectRows)
97          self.ClearSelection()          self.ClearSelection()
98    
99      def GetCurrentSelection(self):      def GetCurrentSelection(self):
# Line 125  class ClassGrid(wxGrid): Line 136  class ClassGrid(wxGrid):
136          # if only one thing is selected check if it is the default          # if only one thing is selected check if it is the default
137          # data row, because we can't remove that          # data row, because we can't remove that
138          if len(sel) == 1:          if len(sel) == 1:
139              group = self.GetTable().GetValueAsCustom(sel[0], COL_SYMBOL, None)              #group = self.GetTable().GetValueAsCustom(sel[0], COL_SYMBOL, None)
140                group = self.GetTable().GetClassGroup(sel[0])
141              if isinstance(group, ClassGroupDefault):              if isinstance(group, ClassGroupDefault):
142                  wxMessageDialog(self,                  wxMessageDialog(self,
143                                  "The Default group cannot be removed.",                                  "The Default group cannot be removed.",
# Line 174  class ClassGrid(wxGrid): Line 186  class ClassGrid(wxGrid):
186          r = event.GetRow()          r = event.GetRow()
187          c = event.GetCol()          c = event.GetCol()
188          if c == COL_SYMBOL:          if c == COL_SYMBOL:
189              group = self.GetTable().GetValueAsCustom(r, c, None)              prop = self.GetTable().GetValueAsCustom(r, c, None)
190              prop = group.GetProperties()              #prop = group.GetProperties()
191    
192              # get a new ClassGroupProperties object and copy the              # get a new ClassGroupProperties object and copy the
193              # values over to our current object              # values over to our current object
194              propDlg = SelectPropertiesDialog(NULL, prop, self.shapeType)              propDlg = SelectPropertiesDialog(NULL, prop, self.shapeType)
195              if propDlg.ShowModal() == wxID_OK:              if propDlg.ShowModal() == wxID_OK:
196                  new_prop = propDlg.GetClassGroupProperties()                  new_prop = propDlg.GetClassGroupProperties()
197                  prop.SetProperties(new_prop)                  #prop.SetProperties(new_prop)
198                  self.Refresh()                  self.GetTable().SetValueAsCustom(r, c, None, new_prop)
199              propDlg.Destroy()              propDlg.Destroy()
200    
201      #      #
# Line 227  class ClassTable(wxPyGridTableBase): Line 239  class ClassTable(wxPyGridTableBase):
239          """          """
240    
241          wxPyGridTableBase.__init__(self)          wxPyGridTableBase.__init__(self)
242    
243          self.SetView(view)          self.SetView(view)
244          self.tdata = []          self.tdata = []
245    
# Line 250  class ClassTable(wxPyGridTableBase): Line 263  class ClassTable(wxPyGridTableBase):
263    
264          self.GetView().BeginBatch()          self.GetView().BeginBatch()
265    
266          self.clazz = clazz          self.fieldType = clazz.GetFieldType()
267          self.shapeType = shapeType          self.shapeType = shapeType
         self.renderer = ClassRenderer(self.shapeType)  
268    
269          old_len = len(self.tdata)          old_len = len(self.tdata)
270    
# Line 262  class ClassTable(wxPyGridTableBase): Line 274  class ClassTable(wxPyGridTableBase):
274          # copy the data out of the classification and into our          # copy the data out of the classification and into our
275          # array          # array
276          #          #
277          for p in self.clazz:          for p in clazz:
278              np = copy.copy(p)              np = copy.deepcopy(p)
279              self.__SetRow(-1, np)              self.__SetRow(-1, np)
280    
281    
282          self.__Modified(False)          self.__Modified(-1)
283    
284          self.__NotifyRowChanges(old_len, len(self.tdata))          self.__NotifyRowChanges(old_len, len(self.tdata))
285    
286                
287          self.GetView().EndBatch()          self.GetView().EndBatch()
288    
289      def __NotifyRowChanges(self, curRows, newRows):      def __NotifyRowChanges(self, curRows, newRows):
# Line 282  class ClassTable(wxPyGridTableBase): Line 296  class ClassTable(wxPyGridTableBase):
296                          wxGRIDTABLE_NOTIFY_ROWS_APPENDED,                          wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
297                          newRows - curRows)    # how many                          newRows - curRows)    # how many
298              self.GetView().ProcessTableMessage(msg)              self.GetView().ProcessTableMessage(msg)
299                self.GetView().FitInside()
300          elif newRows < curRows:          elif newRows < curRows:
301              msg = wxGridTableMessage(self,              msg = wxGridTableMessage(self,
302                          wxGRIDTABLE_NOTIFY_ROWS_DELETED,                          wxGRIDTABLE_NOTIFY_ROWS_DELETED,
303                          curRows - newRows,    # position                          curRows - newRows,    # position
304                          curRows - newRows)    # how many                          curRows - newRows)    # how many
305              self.GetView().ProcessTableMessage(msg)              self.GetView().ProcessTableMessage(msg)
306                self.GetView().FitInside()
307    
308      def __SetRow(self, row, group):      def __SetRow(self, row, group):
309          """Set a row's data to that of the group.          """Set a row's data to that of the group.
310    
311            The table is considered modified after this operation.
312    
313          row -- if row is -1 or greater than the current number of rows          row -- if row is -1 or greater than the current number of rows
314                 then group is appended to the end.                 then group is appended to the end.
315          """          """
# Line 356  class ClassTable(wxPyGridTableBase): Line 374  class ClassTable(wxPyGridTableBase):
374          group = self.tdata[row]          group = self.tdata[row]
375    
376          if col == COL_SYMBOL:          if col == COL_SYMBOL:
377              return group              return group.GetProperties()
378    
379          if col == COL_LABEL:          if col == COL_LABEL:
380              return group.GetLabel()              return group.GetLabel()
# Line 382  class ClassTable(wxPyGridTableBase): Line 400  class ClassTable(wxPyGridTableBase):
400          value, or of length two if it is a range.          value, or of length two if it is a range.
401          """          """
402    
403          type = self.clazz.GetFieldType()          type = self.fieldType
404    
405          if type == FIELDTYPE_STRING:          if type == FIELDTYPE_STRING:
406              return (value,)              return (value,)
# Line 412  class ClassTable(wxPyGridTableBase): Line 430  class ClassTable(wxPyGridTableBase):
430                  return (conv(Str2Num(value[:i])), conv(Str2Num(value[i+1:])))                  return (conv(Str2Num(value[:i])), conv(Str2Num(value[i+1:])))
431    
432          assert(False) # shouldn't get here          assert(False) # shouldn't get here
433            return (0,)
434                            
435    
436      def SetValueAsCustom(self, row, col, typeName, value):      def SetValueAsCustom(self, row, col, typeName, value):
# Line 431  class ClassTable(wxPyGridTableBase): Line 450  class ClassTable(wxPyGridTableBase):
450    
451          group = self.tdata[row]          group = self.tdata[row]
452    
453          mod = False          mod = True # assume the data will change
454    
455          if col == COL_SYMBOL:          if col == COL_SYMBOL:
456              self.__SetRow(row, value)              group.SetProperties(value)
457              mod = True          elif col == COL_LABEL:
458                group.SetLabel(value)
459          elif col == COL_VALUE:          elif col == COL_VALUE:
460              if isinstance(group, ClassGroupDefault):              if isinstance(group, ClassGroupDefault):
461                  # not allowed to modify the default value                  # not allowed to modify the default value
# Line 448  class ClassTable(wxPyGridTableBase): Line 468  class ClassTable(wxPyGridTableBase):
468                      dataInfo = self.__ParseInput(value)                      dataInfo = self.__ParseInput(value)
469                  except ValueError:                  except ValueError:
470                      # bad input, ignore the request                      # bad input, ignore the request
471                      pass                      mod = False
472                  else:                  else:
473    
474                        changed = False
475                      ngroup = group                      ngroup = group
476                      props = group.GetProperties()                      props = group.GetProperties()
477    
# Line 462  class ClassTable(wxPyGridTableBase): Line 483  class ClassTable(wxPyGridTableBase):
483                      if len(dataInfo) == 1:                      if len(dataInfo) == 1:
484                          if not isinstance(group, ClassGroupSingleton):                          if not isinstance(group, ClassGroupSingleton):
485                              ngroup = ClassGroupSingleton(prop = props)                              ngroup = ClassGroupSingleton(prop = props)
486                                changed = True
487                          ngroup.SetValue(dataInfo[0])                          ngroup.SetValue(dataInfo[0])
488                      elif len(dataInfo) == 2:                      elif len(dataInfo) == 2:
489                          if not isinstance(group, ClassGroupRange):                          if not isinstance(group, ClassGroupRange):
490                              ngroup = ClassGroupRange(prop = props)                              ngroup = ClassGroupRange(prop = props)
491                                changed = True
492                          ngroup.SetRange(dataInfo[0], dataInfo[1])                          ngroup.SetRange(dataInfo[0], dataInfo[1])
493                      else:                      else:
494                          assert(False)                          assert(False)
495                            pass
496    
497                      ngroup.SetLabel(group.GetLabel())                      if changed:
498                            ngroup.SetLabel(group.GetLabel())
499                      self.__SetRow(row, ngroup)                          self.SetClassGroup(row, ngroup)
500            else:
501                      mod = True              assert(False) # shouldn't be here
502                pass
   
         elif col == COL_LABEL:  
             group.SetLabel(value)  
             mod = True  
503    
504          if mod:          if mod:
505              self.__Modified()              self.__Modified()
506              self.GetView().Refresh()              self.GetView().Refresh()
507    
# Line 492  class ClassTable(wxPyGridTableBase): Line 512  class ClassTable(wxPyGridTableBase):
512          #attr = wxPyGridTableBase.GetAttr(self, row, col, someExtraParameter)          #attr = wxPyGridTableBase.GetAttr(self, row, col, someExtraParameter)
513    
514          if col == COL_SYMBOL:          if col == COL_SYMBOL:
515                # we need to create a new renderer each time, because
516                # SetRenderer takes control of the parameter
517              attr.SetRenderer(ClassRenderer(self.shapeType))              attr.SetRenderer(ClassRenderer(self.shapeType))
518              attr.SetReadOnly()              attr.SetReadOnly()
519    
# Line 500  class ClassTable(wxPyGridTableBase): Line 522  class ClassTable(wxPyGridTableBase):
522      def GetClassGroup(self, row):      def GetClassGroup(self, row):
523          """Return the ClassGroup object representing row 'row'."""          """Return the ClassGroup object representing row 'row'."""
524    
525          return self.GetValueAsCustom(row, COL_SYMBOL, None)          return self.tdata[row] # self.GetValueAsCustom(row, COL_SYMBOL, None)
526    
527      def SetClassGroup(self, row, group):      def SetClassGroup(self, row, group):
528          self.SetValueAsCustom(row, COL_SYMBOL, None, group)          self.__SetRow(row, group)
529            self.GetView().Refresh()
530    
531      def __Modified(self, mod = True):      def __Modified(self, mod = True):
532          """Set the modified flag."""          """Adjust the modified flag.
533          self.modified = mod  
534            mod -- if -1 set the modified flag to False, otherwise perform
535                   an 'or' operation with the current value of the flag and
536                   'mod'
537            """
538    
539            if mod == -1:
540                self.modified = False
541            else:
542                self.modified = mod or self.modified
543    
544      def IsModified(self):      def IsModified(self):
545          """True if this table is considered modified."""          """True if this table is considered modified."""
546          return self.modified          return self.modified
547    
548      def DeleteRows(self, pos, numRows = 1):      def DeleteRows(self, pos, numRows = 1):
549          """Deletes 'numRows' beginning at row 'pos'.          """Deletes 'numRows' beginning at row 'pos'.
550    
551          The table is considered modified after this operation.          The row representing the default group is not removed.
552    
553            The table is considered modified if any rows are removed.
554          """          """
555    
556          assert(pos >= 0)          assert(pos >= 0)
557          old_len = len(self.tdata)          old_len = len(self.tdata)
558          for row in range(pos, pos - numRows, -1):          for row in range(pos, pos - numRows, -1):
559              group = self.GetValueAsCustom(row, COL_SYMBOL, None)              group = self.GetClassGroup(row)
560              if not isinstance(group, ClassGroupDefault):              if not isinstance(group, ClassGroupDefault):
561                  self.tdata.pop(row)                  self.tdata.pop(row)
562                  self.__Modified()                  self.__Modified()
# Line 531  class ClassTable(wxPyGridTableBase): Line 565  class ClassTable(wxPyGridTableBase):
565              self.__NotifyRowChanges(old_len, len(self.tdata))              self.__NotifyRowChanges(old_len, len(self.tdata))
566    
567      def AppendRows(self, numRows = 1):      def AppendRows(self, numRows = 1):
568          """Append 'numRows' empty rows to the end of the table."""          """Append 'numRows' empty rows to the end of the table.
569    
570            The table is considered modified if any rows are appended.
571            """
572    
573          old_len = len(self.tdata)          old_len = len(self.tdata)
574          for i in range(numRows):          for i in range(numRows):
575              np = ClassGroupSingleton()              np = ClassGroupSingleton()
576              self.__SetRow(-1, np)              self.__SetRow(-1, np)
             #self.tdata.append([np, np.GetValue(), np.GetLabel()])  
             self.__Modified()  
577    
578          if self.IsModified():          if self.IsModified():
579              self.__NotifyRowChanges(old_len, len(self.tdata))              self.__NotifyRowChanges(old_len, len(self.tdata))
580    
581    
582  class Classifier(wxDialog):  class Classifier(NonModalDialog):
583        
584      def __init__(self, parent, layer):      def __init__(self, parent, name, layer):
585          wxDialog.__init__(self, parent, -1, _("Classify"),          NonModalDialog.__init__(self, parent, name,
586                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)                                  _("Classifier: %s") % layer.Title())
587    
588            panel = wxPanel(self, -1, size=(100, 100))
589    
590          self.layer = layer          self.layer = layer
591    
592            self.originalClass = self.layer.GetClassification()
593            field = self.originalClass.GetField()
594            fieldType = self.originalClass.GetFieldType()
595    
596          topBox = wxBoxSizer(wxVERTICAL)          topBox = wxBoxSizer(wxVERTICAL)
597            panelBox = wxBoxSizer(wxVERTICAL)
598    
599          topBox.Add(wxStaticText(self, -1, _("Layer: %s") % layer.Title()),          #panelBox.Add(wxStaticText(panel, -1, _("Layer: %s") % layer.Title()),
600              0, wxALIGN_LEFT | wxALL, 4)              #0, wxALIGN_LEFT | wxALL, 4)
601          topBox.Add(wxStaticText(self, -1, _("Type: %s") % layer.ShapeType()),          panelBox.Add(wxStaticText(panel, -1,
602                                    _("Layer Type: %s") % layer.ShapeType()),
603              0, wxALIGN_LEFT | wxALL, 4)              0, wxALIGN_LEFT | wxALL, 4)
604    
         propertyBox = wxBoxSizer(wxHORIZONTAL)  
         propertyBox.Add(wxStaticText(self, -1, _("Field: ")),  
             0, wxALIGN_CENTER | wxALL, 4)  
605    
606          self.fields = wxComboBox(self, ID_PROPERTY_SELECT, "",          #
607            # make field combo box
608            #
609            self.fields = wxComboBox(panel, ID_PROPERTY_SELECT, "",
610                                       style = wxCB_READONLY)                                       style = wxCB_READONLY)
611    
612          self.num_cols = layer.table.field_count()          self.num_cols = layer.table.field_count()
613          # just assume the first field in case one hasn't been          # just assume the first field in case one hasn't been
614          # specified in the file.          # specified in the file.
615          self.__cur_field = 0          self.__cur_field = 0
         clazz = layer.GetClassification()  
         field = clazz.GetField()  
616    
617          self.fields.Append("<None>")          self.fields.Append("<None>")
618          self.fields.SetClientData(0, None)          self.fields.SetClientData(0, None)
# Line 583  class Classifier(wxDialog): Line 623  class Classifier(wxDialog):
623    
624              if name == field:              if name == field:
625                  self.__cur_field = i + 1                  self.__cur_field = i + 1
626                  self.fields.SetClientData(i + 1, clazz)                  self.fields.SetClientData(i + 1, self.originalClass)
627              else:              else:
628                  self.fields.SetClientData(i + 1, None)                  self.fields.SetClientData(i + 1, None)
629    
         self.fields.SetSelection(self.__cur_field)  
630    
631            ###########
632    
633            self.fieldTypeText = wxStaticText(panel, -1, "")
634            panelBox.Add(self.fieldTypeText, 0,
635                         wxGROW | wxALIGN_LEFT | wxALL | wxADJUST_MINSIZE, 4)
636    
637            propertyBox = wxBoxSizer(wxHORIZONTAL)
638            propertyBox.Add(wxStaticText(panel, -1, _("Field: ")),
639                0, wxALIGN_LEFT | wxALL, 4)
640          propertyBox.Add(self.fields, 1, wxGROW|wxALL, 4)          propertyBox.Add(self.fields, 1, wxGROW|wxALL, 4)
641          EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self._OnFieldSelect)          EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self._OnFieldSelect)
642    
643          topBox.Add(propertyBox, 0, wxGROW, 4)          panelBox.Add(propertyBox, 0, wxGROW, 4)
644    
645            ###########
646          #          #
647          # Classification data table          # Classification data table
648          #          #
649    
650          controlBox = wxBoxSizer(wxHORIZONTAL)          controlBox = wxBoxSizer(wxHORIZONTAL)
         self.classGrid = ClassGrid(self)  
651    
652            self.classGrid = ClassGrid(panel)
653          self.__SetGridTable(self.__cur_field)          self.__SetGridTable(self.__cur_field)
654    
655          controlBox.Add(self.classGrid, 1, wxGROW, 0)          controlBox.Add(self.classGrid, 1, wxGROW, 0)
656    
657            ###########
658            #
659            # Control buttons:
660            #
661            self.controlButtons = []
662    
663          controlButtonBox = wxBoxSizer(wxVERTICAL)          controlButtonBox = wxBoxSizer(wxVERTICAL)
         controlButtonBox.Add(wxButton(self, ID_CLASSIFY_ADD,  
             _("Add")), 0, wxGROW | wxALL, 4)  
         controlButtonBox.Add(wxButton(self, ID_CLASSIFY_GENRANGE,  
             _("Generate Ranges")), 0, wxGROW | wxALL, 4)  
   
         controlButtonBox.Add(wxButton(self, ID_CLASSIFY_MOVEUP,  
             _("Move Up")), 0, wxGROW | wxALL, 4)  
         controlButtonBox.Add(wxButton(self, ID_CLASSIFY_MOVEDOWN,  
             _("Move Down")), 0, wxGROW | wxALL, 4)  
664    
665          controlButtonBox.Add(wxButton(self, ID_CLASSIFY_REMOVE,          button = wxButton(panel, ID_CLASSIFY_ADD, _("Add"))
666              _("Remove")), 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
667            self.controlButtons.append(button)
668    
669            #button = wxButton(panel, ID_CLASSIFY_GENRANGE, _("Generate Ranges"))
670            #controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
671            #self.controlButtons.append(button)
672    
673            button = wxButton(panel, ID_CLASSIFY_MOVEUP, _("Move Up"))
674            controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
675            self.controlButtons.append(button)
676    
677            button = wxButton(panel, ID_CLASSIFY_MOVEDOWN, _("Move Down"))
678            controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
679            self.controlButtons.append(button)
680    
681            controlButtonBox.Add(60, 20, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
682    
683            button = wxButton(panel, ID_CLASSIFY_REMOVE, _("Remove"))
684            controlButtonBox.Add(button, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
685            self.controlButtons.append(button)
686    
687          controlBox.Add(controlButtonBox, 0, wxGROW, 10)          controlBox.Add(controlButtonBox, 0, wxGROW, 10)
688          topBox.Add(controlBox, 1, wxGROW, 10)          panelBox.Add(controlBox, 1, wxGROW, 10)
689    
690          EVT_BUTTON(self, ID_CLASSIFY_ADD, self._OnAdd)          EVT_BUTTON(self, ID_CLASSIFY_ADD, self._OnAdd)
691          EVT_BUTTON(self, ID_CLASSIFY_REMOVE, self._OnRemove)          EVT_BUTTON(self, ID_CLASSIFY_REMOVE, self._OnRemove)
# Line 628  class Classifier(wxDialog): Line 693  class Classifier(wxDialog):
693          EVT_BUTTON(self, ID_CLASSIFY_MOVEUP, self._OnMoveUp)          EVT_BUTTON(self, ID_CLASSIFY_MOVEUP, self._OnMoveUp)
694          EVT_BUTTON(self, ID_CLASSIFY_MOVEDOWN, self._OnMoveDown)          EVT_BUTTON(self, ID_CLASSIFY_MOVEDOWN, self._OnMoveDown)
695    
696          #          ###########
697          # Control buttons:  
         #  
698          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
699          buttonBox.Add(wxButton(self, ID_CLASSIFY_OK, _("OK")),          buttonBox.Add(wxButton(panel, ID_CLASSIFY_OK, _("OK")),
700                        0, wxALL, 4)                        0, wxALL, 4)
701          buttonBox.Add(wxButton(self, ID_CLASSIFY_CANCEL, _("Cancel")),          buttonBox.Add(60, 20, 0, wxALL, 4)
702            buttonBox.Add(wxButton(panel, ID_CLASSIFY_APPLY, _("Apply")),
703                        0, wxALL, 4)                        0, wxALL, 4)
704          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)          buttonBox.Add(60, 20, 0, wxALL, 4)
705            buttonBox.Add(wxButton(panel, ID_CLASSIFY_CANCEL, _("Cancel")),
706                          0, wxALL, 4)
707            panelBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 0)
708    
709          EVT_BUTTON(self, ID_CLASSIFY_OK, self._OnOK)          EVT_BUTTON(self, ID_CLASSIFY_OK, self._OnOK)
710            EVT_BUTTON(self, ID_CLASSIFY_APPLY, self._OnApply)
711          EVT_BUTTON(self, ID_CLASSIFY_CANCEL, self._OnCancel)          EVT_BUTTON(self, ID_CLASSIFY_CANCEL, self._OnCancel)
712    
713            ###########
714    
715            self.fields.SetSelection(self.__cur_field)
716            self.__SelectField(self.__cur_field)
717    
718          self.SetAutoLayout(true)          panel.SetAutoLayout(True)
719            panel.SetSizer(panelBox)
720            panelBox.SetSizeHints(panel)
721    
722            topBox.Add(panel, 1, wxGROW, 0)
723            panelBox.SetSizeHints(self)
724            self.SetAutoLayout(True)
725          self.SetSizer(topBox)          self.SetSizer(topBox)
726          topBox.Fit(self)  
727          topBox.SetSizeHints(self)          ######################
728    
729            self.haveApplied = False
730    
731      def __BuildClassification(self, fieldIndex):      def __BuildClassification(self, fieldIndex):
732    
733            numRows = self.classGrid.GetNumberRows()
734            assert(numRows > 0) # there should always be a default row
735    
736          clazz = Classification()          clazz = Classification()
737          fieldName = self.fields.GetString(fieldIndex)          if fieldIndex == 0:
738          fieldType = self.layer.GetFieldType(fieldName)              fieldName = None
739                fieldType = None
740            else:
741                fieldName = self.fields.GetString(fieldIndex)
742                fieldType = self.layer.GetFieldType(fieldName)
743    
744          clazz.SetField(fieldName)          clazz.SetField(fieldName)
745          clazz.SetFieldType(fieldType)          clazz.SetFieldType(fieldType)
746    
         numRows = self.classGrid.GetNumberRows()  
   
         assert(numRows > 0) # there should always be a default row  
747    
748          table = self.classGrid.GetTable()          table = self.classGrid.GetTable()
749          clazz.SetDefaultGroup(table.GetClassGroup(0))          clazz.SetDefaultGroup(table.GetClassGroup(0))
# Line 677  class Classifier(wxDialog): Line 761  class Classifier(wxDialog):
761              clazz = Classification()              clazz = Classification()
762              clazz.SetDefaultGroup(              clazz.SetDefaultGroup(
763                  ClassGroupDefault(                  ClassGroupDefault(
764                      self.layer.GetClassification().GetDefaultGroup().GetProperties()))                      self.layer.GetClassification().
765                                   GetDefaultGroup().GetProperties()))
766    
767              fieldName = self.fields.GetString(fieldIndex)              fieldName = self.fields.GetString(fieldIndex)
768              fieldType = self.layer.GetFieldType(fieldName)              fieldType = self.layer.GetFieldType(fieldName)
# Line 685  class Classifier(wxDialog): Line 770  class Classifier(wxDialog):
770                                    
771          self.classGrid.CreateTable(clazz, self.layer.ShapeType())          self.classGrid.CreateTable(clazz, self.layer.ShapeType())
772    
     def _OnFieldSelect(self, event):  
         clazz = self.__BuildClassification(self.__cur_field)  
         self.fields.SetClientData(self.__cur_field, clazz)  
773    
         self.__cur_field = self.fields.GetSelection()  
         self.__SetGridTable(self.__cur_field)  
774    
775      def _OnOK(self, event):      type2string = {None:             _("None"),
776                       FIELDTYPE_STRING: _("Text"),
777                       FIELDTYPE_INT:    _("Integer"),
778                       FIELDTYPE_DOUBLE: _("Decimal")}
779    
780        def __SetFieldTypeText(self, fieldIndex):
781            fieldName = self.fields.GetString(fieldIndex)
782            fieldType = self.layer.GetFieldType(fieldName)
783    
784            assert(Classifier.type2string.has_key(fieldType))
785    
786            text = Classifier.type2string[fieldType]
787    
788            self.fieldTypeText.SetLabel(_("Field Type: %s") % text)
789    
790        def __SelectField(self, newIndex, oldIndex = -1):
791    
792            assert(oldIndex >= -1)
793    
794            if oldIndex != -1:
795                clazz = self.__BuildClassification(oldIndex)
796                self.fields.SetClientData(oldIndex, clazz)
797    
798            self.__SetGridTable(newIndex)
799    
800            enabled = newIndex != 0
801    
802            for b in self.controlButtons:
803                b.Enable(enabled)
804    
805            self.__SetFieldTypeText(newIndex)
806    
807    
808        def _OnFieldSelect(self, event):
809            index = self.fields.GetSelection()
810            self.__SelectField(index, self.__cur_field)
811            self.__cur_field = index
812    
813        def _OnApply(self, event):
814          """Put the data from the table into a new Classification and hand          """Put the data from the table into a new Classification and hand
815             it to the layer.             it to the layer.
816          """          """
# Line 706  class Classifier(wxDialog): Line 824  class Classifier(wxDialog):
824          if clazz is None or self.classGrid.GetTable().IsModified():          if clazz is None or self.classGrid.GetTable().IsModified():
825              clazz = self.__BuildClassification(self.__cur_field)              clazz = self.__BuildClassification(self.__cur_field)
826    
         clazz.SetLayer(self.layer)  
   
827          self.layer.SetClassification(clazz)          self.layer.SetClassification(clazz)
828    
829          self.EndModal(wxID_OK)          self.haveApplied = True
830    
831        def _OnOK(self, event):
832            self._OnApply(event)
833            self.OnClose(event)
834    
835      def _OnCancel(self, event):      def _OnCancel(self, event):
836          """Do nothing. The layer's current classification stays the same."""          """The layer's current classification stays the same."""
837          self.EndModal(wxID_CANCEL)          if self.haveApplied:
838                self.layer.SetClassification(self.originalClass)
839    
840            self.OnClose(event)
841    
842      def _OnAdd(self, event):      def _OnAdd(self, event):
843          self.classGrid.AppendRows()          self.classGrid.AppendRows()
# Line 760  ID_SELPROP_SPINCTRL = 4002 Line 883  ID_SELPROP_SPINCTRL = 4002
883  ID_SELPROP_PREVIEW = 4003  ID_SELPROP_PREVIEW = 4003
884  ID_SELPROP_STROKECLR = 4004  ID_SELPROP_STROKECLR = 4004
885  ID_SELPROP_FILLCLR = 4005  ID_SELPROP_FILLCLR = 4005
886    ID_SELPROP_STROKECLRTRANS = 4006
887    ID_SELPROP_FILLCLRTRANS = 4007
888    
889  class SelectPropertiesDialog(wxDialog):  class SelectPropertiesDialog(wxDialog):
890    
891      def __init__(self, parent, prop, shapeType):      def __init__(self, parent, prop, shapeType):
892          wxDialog.__init__(self, parent, -1, _("Select Properties"),          wxDialog.__init__(self, parent, -1, _("Select Properties"),
893                            style = wxRESIZE_BORDER)                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
894    
895          self.prop = ClassGroupProperties(prop)          self.prop = ClassGroupProperties(prop)
896    
# Line 777  class SelectPropertiesDialog(wxDialog): Line 902  class SelectPropertiesDialog(wxDialog):
902          previewBox = wxBoxSizer(wxVERTICAL)          previewBox = wxBoxSizer(wxVERTICAL)
903          previewBox.Add(wxStaticText(self, -1, _("Preview:")),          previewBox.Add(wxStaticText(self, -1, _("Preview:")),
904              0, wxALIGN_LEFT | wxALL, 4)              0, wxALIGN_LEFT | wxALL, 4)
905          self.previewer = ClassDataPreviewer(None, self.prop, shapeType,          self.previewWin = ClassDataPreviewWindow(None, self.prop, shapeType,
906                                              self, ID_SELPROP_PREVIEW, (40, 40))                                              self, ID_SELPROP_PREVIEW, (40, 40))
907          previewBox.Add(self.previewer, 1, wxGROW, 15)          previewBox.Add(self.previewWin, 1, wxGROW, 15)
908    
909          itemBox.Add(previewBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)          itemBox.Add(previewBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)
910    
911          # control box          # control box
912          ctrlBox = wxBoxSizer(wxVERTICAL)          ctrlBox = wxBoxSizer(wxVERTICAL)
913          ctrlBox.Add(  
914              wxButton(self, ID_SELPROP_STROKECLR, "Change Line Color"),          lineColorBox = wxBoxSizer(wxHORIZONTAL)
915              0, wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)          lineColorBox.Add(
916                wxButton(self, ID_SELPROP_STROKECLR, _("Change Line Color")),
917                1, wxALL | wxGROW, 4)
918          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)
919    
920            lineColorBox.Add(
921                wxButton(self, ID_SELPROP_STROKECLRTRANS, _("Transparent")),
922                1, wxALL | wxGROW, 4)
923            EVT_BUTTON(self, ID_SELPROP_STROKECLRTRANS,
924                       self._OnChangeLineColorTrans)
925    
926            ctrlBox.Add(lineColorBox, 0,
927                        wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)
928    
929          if shapeType != SHAPETYPE_ARC:          if shapeType != SHAPETYPE_ARC:
930              ctrlBox.Add(              fillColorBox = wxBoxSizer(wxHORIZONTAL)
931                  wxButton(self, ID_SELPROP_FILLCLR, "Change Fill Color"),              fillColorBox.Add(
932                  0, wxALIGN_LEFT | wxALL | wxGROW, 4)                  wxButton(self, ID_SELPROP_FILLCLR, _("Change Fill Color")),
933                    1, wxALL | wxGROW, 4)
934              EVT_BUTTON(self, ID_SELPROP_FILLCLR, self._OnChangeFillColor)              EVT_BUTTON(self, ID_SELPROP_FILLCLR, self._OnChangeFillColor)
935                fillColorBox.Add(
936                    wxButton(self, ID_SELPROP_FILLCLRTRANS, _("Transparent")),
937                    1, wxALL | wxGROW, 4)
938                EVT_BUTTON(self, ID_SELPROP_FILLCLRTRANS,
939                           self._OnChangeFillColorTrans)
940                ctrlBox.Add(fillColorBox, 0,
941                            wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)
942    
943          spinBox = wxBoxSizer(wxHORIZONTAL)          spinBox = wxBoxSizer(wxHORIZONTAL)
944          spinBox.Add(wxStaticText(self, -1, _("Line Width: ")),          spinBox.Add(wxStaticText(self, -1, _("Line Width: ")),
# Line 812  class SelectPropertiesDialog(wxDialog): Line 956  class SelectPropertiesDialog(wxDialog):
956          itemBox.Add(ctrlBox, 0, wxALIGN_RIGHT | wxALL | wxGROW, 0)          itemBox.Add(ctrlBox, 0, wxALIGN_RIGHT | wxALL | wxGROW, 0)
957          topBox.Add(itemBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)          topBox.Add(itemBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)
958    
   
959          #          #
960          # Control buttons:          # Control buttons:
961          #          #
962          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
963          buttonBox.Add(wxButton(self, ID_CLASSIFY_OK, _("OK")),          buttonBox.Add(wxButton(self, ID_SELPROP_OK, _("OK")),
964                        0, wxALL, 4)                        0, wxALL, 4)
965          buttonBox.Add(wxButton(self, ID_CLASSIFY_CANCEL, _("Cancel")),          buttonBox.Add(wxButton(self, ID_SELPROP_CANCEL, _("Cancel")),
966                        0, wxALL, 4)                        0, wxALL, 4)
967          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)
968                                                                                                                                                                    
969          EVT_BUTTON(self, ID_SELPROP_OK, self._OnOK)          EVT_BUTTON(self, ID_SELPROP_OK, self._OnOK)
970          EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)          EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)
971                                                                                                                                                                    
972          self.SetAutoLayout(true)          self.SetAutoLayout(True)
973          self.SetSizer(topBox)          self.SetSizer(topBox)
974          topBox.Fit(self)          topBox.Fit(self)
975          topBox.SetSizeHints(self)          topBox.SetSizeHints(self)
# Line 839  class SelectPropertiesDialog(wxDialog): Line 982  class SelectPropertiesDialog(wxDialog):
982    
983      def _OnSpin(self, event):      def _OnSpin(self, event):
984          self.prop.SetLineWidth(self.spinCtrl.GetValue())          self.prop.SetLineWidth(self.spinCtrl.GetValue())
985          self.previewer.Refresh()          self.previewWin.Refresh()
986    
987      def __GetColor(self, cur):      def __GetColor(self, cur):
988          dialog = wxColourDialog(self)          dialog = wxColourDialog(self)
# Line 856  class SelectPropertiesDialog(wxDialog): Line 999  class SelectPropertiesDialog(wxDialog):
999          clr = self.__GetColor(self.prop.GetLineColor())          clr = self.__GetColor(self.prop.GetLineColor())
1000          if clr is not None:          if clr is not None:
1001              self.prop.SetLineColor(clr)              self.prop.SetLineColor(clr)
1002          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1003    
1004        def _OnChangeLineColorTrans(self, event):
1005            self.prop.SetLineColor(Color.None)
1006            self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1007            
1008      def _OnChangeFillColor(self, event):      def _OnChangeFillColor(self, event):
1009          clr = self.__GetColor(self.prop.GetFill())          clr = self.__GetColor(self.prop.GetFill())
1010          if clr is not None:          if clr is not None:
1011              self.prop.SetFill(clr)              self.prop.SetFill(clr)
1012          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1013    
1014        def _OnChangeFillColorTrans(self, event):
1015            self.prop.SetFill(Color.None)
1016            self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1017    
1018      def GetClassGroupProperties(self):      def GetClassGroupProperties(self):
1019          return self.prop          return self.prop
1020    
1021    
1022  class ClassDataPreviewer(wxWindow):  class ClassDataPreviewWindow(wxWindow):
1023    
1024      def __init__(self, rect, prop, shapeType,      def __init__(self, rect, prop, shapeType,
1025                         parent = None, id = -1, size = wxDefaultSize):                         parent = None, id = -1, size = wxDefaultSize):
1026          if parent is not None:          if parent is not None:
1027              wxWindow.__init__(self, parent, id, size=size)              wxWindow.__init__(self, parent, id, (0, 0), size)
1028              EVT_PAINT(self, self._OnPaint)              EVT_PAINT(self, self._OnPaint)
1029    
1030          self.rect = rect          self.rect = rect
1031    
1032          self.prop = prop          self.prop = prop
1033          self.shapeType = shapeType          self.shapeType = shapeType
1034            self.previewer = ClassDataPreviewer()
1035    
1036      def _OnPaint(self, event):      def _OnPaint(self, event):
1037          dc = wxPaintDC(self)          dc = wxPaintDC(self)
# Line 886  class ClassDataPreviewer(wxWindow): Line 1039  class ClassDataPreviewer(wxWindow):
1039          # XXX: this doesn't seem to be having an effect:          # XXX: this doesn't seem to be having an effect:
1040          dc.DestroyClippingRegion()          dc.DestroyClippingRegion()
1041    
1042          self.Draw(dc, None)          if self.rect is None:
1043                w, h = self.GetSize()
1044                rect = wxRect(0, 0, w, h)
1045            else:
1046                rect = self.rect
1047    
1048            self.previewer.Draw(dc, rect, self.prop, self.shapeType)
1049    
1050    class ClassDataPreviewer:
1051    
1052      def Draw(self, dc, rect, prop = None, shapeType = None):      def Draw(self, dc, rect, prop, shapeType):
1053    
1054          if prop is None: prop = self.prop          assert(dc is not None)
1055          if shapeType is None: shapeType = self.shapeType          assert(isinstance(prop, ClassGroupProperties))
1056    
1057          if rect is None:          if rect is None:
1058              x = y = 0              x = 0
1059              w, h = self.GetClientSizeTuple()              y = 0
1060                w, h = dc.GetSize()
1061          else:          else:
1062              x = rect.GetX()              x = rect.GetX()
1063              y = rect.GetY()              y = rect.GetY()
# Line 935  class ClassRenderer(wxPyGridCellRenderer Line 1097  class ClassRenderer(wxPyGridCellRenderer
1097    
1098      def __init__(self, shapeType):      def __init__(self, shapeType):
1099          wxPyGridCellRenderer.__init__(self)          wxPyGridCellRenderer.__init__(self)
1100          self.previewer = ClassDataPreviewer(None, None, shapeType)          self.shapeType = shapeType
1101            self.previewer = ClassDataPreviewer()
1102    
1103      def Draw(self, grid, attr, dc, rect, row, col, isSelected):      def Draw(self, grid, attr, dc, rect, row, col, isSelected):
1104          data = grid.GetTable().GetValueAsCustom(row, col, None)          data = grid.GetTable().GetClassGroup(row)
1105    
1106          dc.SetClippingRegion(rect.GetX(), rect.GetY(),          dc.SetClippingRegion(rect.GetX(), rect.GetY(),
1107                               rect.GetWidth(), rect.GetHeight())                               rect.GetWidth(), rect.GetHeight())
# Line 948  class ClassRenderer(wxPyGridCellRenderer Line 1111  class ClassRenderer(wxPyGridCellRenderer
1111                           rect.GetWidth(), rect.GetHeight())                           rect.GetWidth(), rect.GetHeight())
1112    
1113          if not isinstance(data, ClassGroupMap):          if not isinstance(data, ClassGroupMap):
1114              self.previewer.Draw(dc, rect, data.GetProperties())              self.previewer.Draw(dc, rect, data.GetProperties(), self.shapeType)
1115    
1116          if isSelected:          if isSelected:
1117              dc.SetPen(wxPen(wxColour(0 * 255, 0 * 255, 0 * 255),              dc.SetPen(wxPen(wxColour(0 * 255, 0 * 255, 0 * 255),

Legend:
Removed from v.460  
changed lines
  Added in v.560

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26