/[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 473 by jonathan, Wed Mar 5 18:39:45 2003 UTC revision 549 by jonathan, Thu Mar 20 09:45:07 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 27  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 38  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 65  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 82  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 128  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 177  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 230  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 253  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 265  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 285  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 359  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 385  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 415  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 434  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 451  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 465  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 495  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 503  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 534  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):
       
     def __init__(self, parent, layer):  
         wxDialog.__init__(self, parent, -1, _("Classify"),  
                           style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)  
583    
584        def __init__(self, parent, name, layer):
585            NonModalDialog.__init__(self, parent, name,
586                                    _("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 586  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, wxGROW | wxALIGN_LEFT | wxALL, 4)
635    
636            propertyBox = wxBoxSizer(wxHORIZONTAL)
637            propertyBox.Add(wxStaticText(panel, -1, _("Field: ")),
638                0, wxALIGN_LEFT | wxALL, 4)
639          propertyBox.Add(self.fields, 1, wxGROW|wxALL, 4)          propertyBox.Add(self.fields, 1, wxGROW|wxALL, 4)
640          EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self._OnFieldSelect)          EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self._OnFieldSelect)
641    
642          topBox.Add(propertyBox, 0, wxGROW, 4)          panelBox.Add(propertyBox, 0, wxGROW, 4)
643    
644            ###########
645          #          #
646          # Classification data table          # Classification data table
647          #          #
648    
649          controlBox = wxBoxSizer(wxHORIZONTAL)          controlBox = wxBoxSizer(wxHORIZONTAL)
         self.classGrid = ClassGrid(self)  
650    
651            self.classGrid = ClassGrid(panel)
652          self.__SetGridTable(self.__cur_field)          self.__SetGridTable(self.__cur_field)
653    
654          controlBox.Add(self.classGrid, 1, wxGROW, 0)          controlBox.Add(self.classGrid, 1, wxGROW, 0)
655    
656            ###########
657            #
658            # Control buttons:
659            #
660            self.controlButtons = []
661    
662          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)  
663    
664          controlButtonBox.Add(wxButton(self, ID_CLASSIFY_REMOVE,          button = wxButton(panel, ID_CLASSIFY_ADD, _("Add"))
665              _("Remove")), 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
666            self.controlButtons.append(button)
667    
668            #button = wxButton(panel, ID_CLASSIFY_GENRANGE, _("Generate Ranges"))
669            #controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
670            #self.controlButtons.append(button)
671    
672            button = wxButton(panel, ID_CLASSIFY_MOVEUP, _("Move Up"))
673            controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
674            self.controlButtons.append(button)
675    
676            button = wxButton(panel, ID_CLASSIFY_MOVEDOWN, _("Move Down"))
677            controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
678            self.controlButtons.append(button)
679    
680            controlButtonBox.Add(60, 20, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
681    
682            button = wxButton(panel, ID_CLASSIFY_REMOVE, _("Remove"))
683            controlButtonBox.Add(button, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
684            self.controlButtons.append(button)
685    
686          controlBox.Add(controlButtonBox, 0, wxGROW, 10)          controlBox.Add(controlButtonBox, 0, wxGROW, 10)
687          topBox.Add(controlBox, 1, wxGROW, 10)          panelBox.Add(controlBox, 1, wxGROW, 10)
688    
689          EVT_BUTTON(self, ID_CLASSIFY_ADD, self._OnAdd)          EVT_BUTTON(self, ID_CLASSIFY_ADD, self._OnAdd)
690          EVT_BUTTON(self, ID_CLASSIFY_REMOVE, self._OnRemove)          EVT_BUTTON(self, ID_CLASSIFY_REMOVE, self._OnRemove)
# Line 631  class Classifier(wxDialog): Line 692  class Classifier(wxDialog):
692          EVT_BUTTON(self, ID_CLASSIFY_MOVEUP, self._OnMoveUp)          EVT_BUTTON(self, ID_CLASSIFY_MOVEUP, self._OnMoveUp)
693          EVT_BUTTON(self, ID_CLASSIFY_MOVEDOWN, self._OnMoveDown)          EVT_BUTTON(self, ID_CLASSIFY_MOVEDOWN, self._OnMoveDown)
694    
695          #          ###########
696          # Control buttons:  
         #  
697          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
698          buttonBox.Add(wxButton(self, ID_CLASSIFY_OK, _("OK")),          buttonBox.Add(wxButton(panel, ID_CLASSIFY_OK, _("OK")),
699                        0, wxALL, 4)                        0, wxALL, 4)
700          buttonBox.Add(wxButton(self, ID_CLASSIFY_CANCEL, _("Cancel")),          buttonBox.Add(60, 20, 0, wxALL, 4)
701            buttonBox.Add(wxButton(panel, ID_CLASSIFY_APPLY, _("Apply")),
702                        0, wxALL, 4)                        0, wxALL, 4)
703          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)          buttonBox.Add(60, 20, 0, wxALL, 4)
704            buttonBox.Add(wxButton(panel, ID_CLASSIFY_CANCEL, _("Cancel")),
705                          0, wxALL, 4)
706            panelBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 0)
707    
708          EVT_BUTTON(self, ID_CLASSIFY_OK, self._OnOK)          EVT_BUTTON(self, ID_CLASSIFY_OK, self._OnOK)
709            EVT_BUTTON(self, ID_CLASSIFY_APPLY, self._OnApply)
710          EVT_BUTTON(self, ID_CLASSIFY_CANCEL, self._OnCancel)          EVT_BUTTON(self, ID_CLASSIFY_CANCEL, self._OnCancel)
711    
712            ###########
713    
714            self.fields.SetSelection(self.__cur_field)
715            self.__SelectField(self.__cur_field)
716    
717          self.SetAutoLayout(true)          panel.SetAutoLayout(True)
718            panel.SetSizer(panelBox)
719            panelBox.SetSizeHints(panel)
720    
721            topBox.Add(panel, 1, wxGROW, 0)
722            panelBox.SetSizeHints(self)
723            self.SetAutoLayout(True)
724          self.SetSizer(topBox)          self.SetSizer(topBox)
725          topBox.Fit(self)  
726          topBox.SetSizeHints(self)          ######################
727    
728            self.haveApplied = False
729    
730      def __BuildClassification(self, fieldIndex):      def __BuildClassification(self, fieldIndex):
731    
732            numRows = self.classGrid.GetNumberRows()
733            assert(numRows > 0) # there should always be a default row
734    
735          clazz = Classification()          clazz = Classification()
736          fieldName = self.fields.GetString(fieldIndex)          if fieldIndex == 0:
737          fieldType = self.layer.GetFieldType(fieldName)              fieldName = None
738                fieldType = None
739            else:
740                fieldName = self.fields.GetString(fieldIndex)
741                fieldType = self.layer.GetFieldType(fieldName)
742    
743          clazz.SetField(fieldName)          clazz.SetField(fieldName)
744          clazz.SetFieldType(fieldType)          clazz.SetFieldType(fieldType)
745    
         numRows = self.classGrid.GetNumberRows()  
   
         assert(numRows > 0) # there should always be a default row  
746    
747          table = self.classGrid.GetTable()          table = self.classGrid.GetTable()
748          clazz.SetDefaultGroup(table.GetClassGroup(0))          clazz.SetDefaultGroup(table.GetClassGroup(0))
# Line 680  class Classifier(wxDialog): Line 760  class Classifier(wxDialog):
760              clazz = Classification()              clazz = Classification()
761              clazz.SetDefaultGroup(              clazz.SetDefaultGroup(
762                  ClassGroupDefault(                  ClassGroupDefault(
763                      self.layer.GetClassification().GetDefaultGroup().GetProperties()))                      self.layer.GetClassification().
764                                   GetDefaultGroup().GetProperties()))
765    
766              fieldName = self.fields.GetString(fieldIndex)              fieldName = self.fields.GetString(fieldIndex)
767              fieldType = self.layer.GetFieldType(fieldName)              fieldType = self.layer.GetFieldType(fieldName)
# Line 688  class Classifier(wxDialog): Line 769  class Classifier(wxDialog):
769                                    
770          self.classGrid.CreateTable(clazz, self.layer.ShapeType())          self.classGrid.CreateTable(clazz, self.layer.ShapeType())
771    
     def _OnFieldSelect(self, event):  
         clazz = self.__BuildClassification(self.__cur_field)  
         self.fields.SetClientData(self.__cur_field, clazz)  
772    
         self.__cur_field = self.fields.GetSelection()  
         self.__SetGridTable(self.__cur_field)  
773    
774      def _OnOK(self, event):      type2string = {None:             _("None"),
775                       FIELDTYPE_STRING: _("Text"),
776                       FIELDTYPE_INT:    _("Integer"),
777                       FIELDTYPE_DOUBLE: _("Decimal")}
778    
779        def __SetFieldTypeText(self, fieldIndex):
780            fieldName = self.fields.GetString(fieldIndex)
781            fieldType = self.layer.GetFieldType(fieldName)
782    
783            assert(Classifier.type2string.has_key(fieldType))
784    
785            text = Classifier.type2string[fieldType]
786    
787            self.fieldTypeText.SetLabel(_("Field Type: %s") % text)
788    
789        def __SelectField(self, newIndex, oldIndex = -1):
790    
791            assert(oldIndex >= -1)
792    
793            if oldIndex != -1:
794                clazz = self.__BuildClassification(oldIndex)
795                self.fields.SetClientData(oldIndex, clazz)
796    
797            self.__SetGridTable(newIndex)
798    
799            enabled = newIndex != 0
800    
801            for b in self.controlButtons:
802                b.Enable(enabled)
803    
804            self.__SetFieldTypeText(newIndex)
805    
806    
807        def _OnFieldSelect(self, event):
808            index = self.fields.GetSelection()
809            self.__SelectField(index, self.__cur_field)
810            self.__cur_field = index
811    
812        def _OnApply(self, event):
813          """Put the data from the table into a new Classification and hand          """Put the data from the table into a new Classification and hand
814             it to the layer.             it to the layer.
815          """          """
# Line 709  class Classifier(wxDialog): Line 823  class Classifier(wxDialog):
823          if clazz is None or self.classGrid.GetTable().IsModified():          if clazz is None or self.classGrid.GetTable().IsModified():
824              clazz = self.__BuildClassification(self.__cur_field)              clazz = self.__BuildClassification(self.__cur_field)
825    
         clazz.SetLayer(self.layer)  
   
826          self.layer.SetClassification(clazz)          self.layer.SetClassification(clazz)
827    
828          self.EndModal(wxID_OK)          self.haveApplied = True
829    
830        def _OnOK(self, event):
831            self._OnApply(event)
832            self.OnClose(event)
833    
834      def _OnCancel(self, event):      def _OnCancel(self, event):
835          """Do nothing. The layer's current classification stays the same."""          """The layer's current classification stays the same."""
836          self.EndModal(wxID_CANCEL)          if self.haveApplied:
837                self.layer.SetClassification(self.originalClass)
838    
839            self.OnClose(event)
840    
841      def _OnAdd(self, event):      def _OnAdd(self, event):
842          self.classGrid.AppendRows()          self.classGrid.AppendRows()
# Line 763  ID_SELPROP_SPINCTRL = 4002 Line 882  ID_SELPROP_SPINCTRL = 4002
882  ID_SELPROP_PREVIEW = 4003  ID_SELPROP_PREVIEW = 4003
883  ID_SELPROP_STROKECLR = 4004  ID_SELPROP_STROKECLR = 4004
884  ID_SELPROP_FILLCLR = 4005  ID_SELPROP_FILLCLR = 4005
885    ID_SELPROP_STROKECLRTRANS = 4006
886    ID_SELPROP_FILLCLRTRANS = 4007
887    
888  class SelectPropertiesDialog(wxDialog):  class SelectPropertiesDialog(wxDialog):
889    
890      def __init__(self, parent, prop, shapeType):      def __init__(self, parent, prop, shapeType):
891          wxDialog.__init__(self, parent, -1, _("Select Properties"),          wxDialog.__init__(self, parent, -1, _("Select Properties"),
892                            style = wxRESIZE_BORDER)                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
893    
894          self.prop = ClassGroupProperties(prop)          self.prop = ClassGroupProperties(prop)
895    
# Line 780  class SelectPropertiesDialog(wxDialog): Line 901  class SelectPropertiesDialog(wxDialog):
901          previewBox = wxBoxSizer(wxVERTICAL)          previewBox = wxBoxSizer(wxVERTICAL)
902          previewBox.Add(wxStaticText(self, -1, _("Preview:")),          previewBox.Add(wxStaticText(self, -1, _("Preview:")),
903              0, wxALIGN_LEFT | wxALL, 4)              0, wxALIGN_LEFT | wxALL, 4)
904          self.previewer = ClassDataPreviewer(None, self.prop, shapeType,          self.previewWin = ClassDataPreviewWindow(None, self.prop, shapeType,
905                                              self, ID_SELPROP_PREVIEW, (40, 40))                                              self, ID_SELPROP_PREVIEW, (40, 40))
906          previewBox.Add(self.previewer, 1, wxGROW, 15)          previewBox.Add(self.previewWin, 1, wxGROW, 15)
907    
908          itemBox.Add(previewBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)          itemBox.Add(previewBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)
909    
910          # control box          # control box
911          ctrlBox = wxBoxSizer(wxVERTICAL)          ctrlBox = wxBoxSizer(wxVERTICAL)
912          ctrlBox.Add(  
913              wxButton(self, ID_SELPROP_STROKECLR, "Change Line Color"),          lineColorBox = wxBoxSizer(wxHORIZONTAL)
914              0, wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)          lineColorBox.Add(
915                wxButton(self, ID_SELPROP_STROKECLR, _("Change Line Color")),
916                1, wxALL | wxGROW, 4)
917          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)
918    
919            lineColorBox.Add(
920                wxButton(self, ID_SELPROP_STROKECLRTRANS, _("Transparent")),
921                1, wxALL | wxGROW, 4)
922            EVT_BUTTON(self, ID_SELPROP_STROKECLRTRANS,
923                       self._OnChangeLineColorTrans)
924    
925            ctrlBox.Add(lineColorBox, 0,
926                        wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)
927    
928          if shapeType != SHAPETYPE_ARC:          if shapeType != SHAPETYPE_ARC:
929              ctrlBox.Add(              fillColorBox = wxBoxSizer(wxHORIZONTAL)
930                  wxButton(self, ID_SELPROP_FILLCLR, "Change Fill Color"),              fillColorBox.Add(
931                  0, wxALIGN_LEFT | wxALL | wxGROW, 4)                  wxButton(self, ID_SELPROP_FILLCLR, _("Change Fill Color")),
932                    1, wxALL | wxGROW, 4)
933              EVT_BUTTON(self, ID_SELPROP_FILLCLR, self._OnChangeFillColor)              EVT_BUTTON(self, ID_SELPROP_FILLCLR, self._OnChangeFillColor)
934                fillColorBox.Add(
935                    wxButton(self, ID_SELPROP_FILLCLRTRANS, _("Transparent")),
936                    1, wxALL | wxGROW, 4)
937                EVT_BUTTON(self, ID_SELPROP_FILLCLRTRANS,
938                           self._OnChangeFillColorTrans)
939                ctrlBox.Add(fillColorBox, 0,
940                            wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)
941    
942          spinBox = wxBoxSizer(wxHORIZONTAL)          spinBox = wxBoxSizer(wxHORIZONTAL)
943          spinBox.Add(wxStaticText(self, -1, _("Line Width: ")),          spinBox.Add(wxStaticText(self, -1, _("Line Width: ")),
# Line 815  class SelectPropertiesDialog(wxDialog): Line 955  class SelectPropertiesDialog(wxDialog):
955          itemBox.Add(ctrlBox, 0, wxALIGN_RIGHT | wxALL | wxGROW, 0)          itemBox.Add(ctrlBox, 0, wxALIGN_RIGHT | wxALL | wxGROW, 0)
956          topBox.Add(itemBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)          topBox.Add(itemBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)
957    
   
958          #          #
959          # Control buttons:          # Control buttons:
960          #          #
961          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
962          buttonBox.Add(wxButton(self, ID_CLASSIFY_OK, _("OK")),          buttonBox.Add(wxButton(self, ID_SELPROP_OK, _("OK")),
963                        0, wxALL, 4)                        0, wxALL, 4)
964          buttonBox.Add(wxButton(self, ID_CLASSIFY_CANCEL, _("Cancel")),          buttonBox.Add(wxButton(self, ID_SELPROP_CANCEL, _("Cancel")),
965                        0, wxALL, 4)                        0, wxALL, 4)
966          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)
967                                                                                                                                                                    
968          EVT_BUTTON(self, ID_SELPROP_OK, self._OnOK)          EVT_BUTTON(self, ID_SELPROP_OK, self._OnOK)
969          EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)          EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)
970                                                                                                                                                                    
971          self.SetAutoLayout(true)          self.SetAutoLayout(True)
972          self.SetSizer(topBox)          self.SetSizer(topBox)
973          topBox.Fit(self)          topBox.Fit(self)
974          topBox.SetSizeHints(self)          topBox.SetSizeHints(self)
# Line 842  class SelectPropertiesDialog(wxDialog): Line 981  class SelectPropertiesDialog(wxDialog):
981    
982      def _OnSpin(self, event):      def _OnSpin(self, event):
983          self.prop.SetLineWidth(self.spinCtrl.GetValue())          self.prop.SetLineWidth(self.spinCtrl.GetValue())
984          self.previewer.Refresh()          self.previewWin.Refresh()
985    
986      def __GetColor(self, cur):      def __GetColor(self, cur):
987          dialog = wxColourDialog(self)          dialog = wxColourDialog(self)
# Line 859  class SelectPropertiesDialog(wxDialog): Line 998  class SelectPropertiesDialog(wxDialog):
998          clr = self.__GetColor(self.prop.GetLineColor())          clr = self.__GetColor(self.prop.GetLineColor())
999          if clr is not None:          if clr is not None:
1000              self.prop.SetLineColor(clr)              self.prop.SetLineColor(clr)
1001          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1002    
1003        def _OnChangeLineColorTrans(self, event):
1004            self.prop.SetLineColor(Color.None)
1005            self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1006            
1007      def _OnChangeFillColor(self, event):      def _OnChangeFillColor(self, event):
1008          clr = self.__GetColor(self.prop.GetFill())          clr = self.__GetColor(self.prop.GetFill())
1009          if clr is not None:          if clr is not None:
1010              self.prop.SetFill(clr)              self.prop.SetFill(clr)
1011          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1012    
1013        def _OnChangeFillColorTrans(self, event):
1014            self.prop.SetFill(Color.None)
1015            self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1016    
1017      def GetClassGroupProperties(self):      def GetClassGroupProperties(self):
1018          return self.prop          return self.prop
1019    
1020    
1021  class ClassDataPreviewer(wxWindow):  class ClassDataPreviewWindow(wxWindow):
1022    
1023      def __init__(self, rect, prop, shapeType,      def __init__(self, rect, prop, shapeType,
1024                         parent = None, id = -1, size = wxDefaultSize):                         parent = None, id = -1, size = wxDefaultSize):
1025          if parent is not None:          if parent is not None:
1026              wxWindow.__init__(self, parent, id, size=size)              wxWindow.__init__(self, parent, id, (0, 0), size)
1027              EVT_PAINT(self, self._OnPaint)              EVT_PAINT(self, self._OnPaint)
1028    
1029          self.rect = rect          self.rect = rect
1030    
1031          self.prop = prop          self.prop = prop
1032          self.shapeType = shapeType          self.shapeType = shapeType
1033            self.previewer = ClassDataPreviewer()
1034    
1035      def _OnPaint(self, event):      def _OnPaint(self, event):
1036          dc = wxPaintDC(self)          dc = wxPaintDC(self)
# Line 889  class ClassDataPreviewer(wxWindow): Line 1038  class ClassDataPreviewer(wxWindow):
1038          # XXX: this doesn't seem to be having an effect:          # XXX: this doesn't seem to be having an effect:
1039          dc.DestroyClippingRegion()          dc.DestroyClippingRegion()
1040    
1041          self.Draw(dc, None)          if self.rect is None:
1042                w, h = self.GetSize()
1043                rect = wxRect(0, 0, w, h)
1044            else:
1045                rect = self.rect
1046    
1047            self.previewer.Draw(dc, rect, self.prop, self.shapeType)
1048    
1049    class ClassDataPreviewer:
1050    
1051      def Draw(self, dc, rect, prop = None, shapeType = None):      def Draw(self, dc, rect, prop, shapeType):
1052    
1053          if prop is None: prop = self.prop          assert(dc is not None)
1054          if shapeType is None: shapeType = self.shapeType          assert(isinstance(prop, ClassGroupProperties))
1055    
1056          if rect is None:          if rect is None:
1057              x = y = 0              x = 0
1058              w, h = self.GetClientSizeTuple()              y = 0
1059                w, h = dc.GetSize()
1060          else:          else:
1061              x = rect.GetX()              x = rect.GetX()
1062              y = rect.GetY()              y = rect.GetY()
# Line 938  class ClassRenderer(wxPyGridCellRenderer Line 1096  class ClassRenderer(wxPyGridCellRenderer
1096    
1097      def __init__(self, shapeType):      def __init__(self, shapeType):
1098          wxPyGridCellRenderer.__init__(self)          wxPyGridCellRenderer.__init__(self)
1099          self.previewer = ClassDataPreviewer(None, None, shapeType)          self.shapeType = shapeType
1100            self.previewer = ClassDataPreviewer()
1101    
1102      def Draw(self, grid, attr, dc, rect, row, col, isSelected):      def Draw(self, grid, attr, dc, rect, row, col, isSelected):
1103          data = grid.GetTable().GetValueAsCustom(row, col, None)          data = grid.GetTable().GetClassGroup(row)
1104    
1105          dc.SetClippingRegion(rect.GetX(), rect.GetY(),          dc.SetClippingRegion(rect.GetX(), rect.GetY(),
1106                               rect.GetWidth(), rect.GetHeight())                               rect.GetWidth(), rect.GetHeight())
# Line 951  class ClassRenderer(wxPyGridCellRenderer Line 1110  class ClassRenderer(wxPyGridCellRenderer
1110                           rect.GetWidth(), rect.GetHeight())                           rect.GetWidth(), rect.GetHeight())
1111    
1112          if not isinstance(data, ClassGroupMap):          if not isinstance(data, ClassGroupMap):
1113              self.previewer.Draw(dc, rect, data.GetProperties())              self.previewer.Draw(dc, rect, data.GetProperties(), self.shapeType)
1114    
1115          if isSelected:          if isSelected:
1116              dc.SetPen(wxPen(wxColour(0 * 255, 0 * 255, 0 * 255),              dc.SetPen(wxPen(wxColour(0 * 255, 0 * 255, 0 * 255),

Legend:
Removed from v.473  
changed lines
  Added in v.549

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26