/[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 835 by bh, Tue May 6 15:52:41 2003 UTC revision 1207 by bh, Fri Jun 13 18:16:10 2003 UTC
# Line 18  from wxPython.wx import * Line 18  from wxPython.wx import *
18  from wxPython.grid import *  from wxPython.grid import *
19    
20  from Thuban import _  from Thuban import _
21  from Thuban.UI.common import *  from Thuban.UI.common import Color2wxColour, wxColour2Color
22    
23  from Thuban.Model.classification import *  from Thuban.Model.messages import MAP_LAYERS_REMOVED, LAYER_SHAPESTORE_REPLACED
24    from Thuban.Model.range import Range
25    from Thuban.Model.classification import \
26        Classification, ClassGroupDefault, \
27        ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \
28        ClassGroupProperties
29    
30  from Thuban.Model.color import Color  from Thuban.Model.color import Color
31    
32  from Thuban.Model.layer import Layer, SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT  from Thuban.Model.layer import Layer, RasterLayer, \
33        SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT
34    
35  from Thuban.UI.classgen import ClassGenDialog, ClassGenerator  from Thuban.UI.classgen import ClassGenDialog
36    
37  from dialogs import NonModalDialog  from dialogs import NonModalNonParentDialog
38    
39  ID_CLASS_TABLE = 40011  ID_CLASS_TABLE = 40011
40    
# Line 243  class ClassGrid(wxGrid): Line 249  class ClassGrid(wxGrid):
249    
250      def _OnCellResize(self, event):      def _OnCellResize(self, event):
251          self.FitInside()          self.FitInside()
252            event.Skip()
253    
254  class ClassTable(wxPyGridTableBase):  class ClassTable(wxPyGridTableBase):
255      """Represents the underlying data structure for the grid."""      """Represents the underlying data structure for the grid."""
# Line 457  class ClassTable(wxPyGridTableBase): Line 464  class ClassTable(wxPyGridTableBase):
464          elif isinstance(group, ClassGroupSingleton):          elif isinstance(group, ClassGroupSingleton):
465              return group.GetValue()              return group.GetValue()
466          elif isinstance(group, ClassGroupRange):          elif isinstance(group, ClassGroupRange):
467              return _("%s - %s") % (group.GetMin(), group.GetMax())              return group.GetRange()
468    
469          assert(False) # shouldn't get here          assert False # shouldn't get here
470          return None          return None
471    
472      def __ParseInput(self, value):      def __ParseInput(self, value):
473          """Try to determine what kind of input value is          """Try to determine what kind of input value is
474             (string, number, or range)             (string, number, or range)
475    
476          Returns a tuple of length one if there is a single          Returns a tuple (type, data) where type is 0 if data is
477          value, or of length two if it is a range.          a singleton value, or 1 if is a range
478          """          """
479    
480          type = self.fieldType          type = self.fieldType
481    
482          if type == FIELDTYPE_STRING:          if type == FIELDTYPE_STRING:
483              return (value,)              return (0, value)
484          elif type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):          elif type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
   
485              if type == FIELDTYPE_INT:              if type == FIELDTYPE_INT:
486                  # the float call allows the user to enter 1.0 for 1                  # the float call allows the user to enter 1.0 for 1
487                  conv = lambda p: int(float(p))                  conv = lambda p: int(float(p))
488              else:              else:
489                  conv = lambda p: p                  conv = float
490    
491              #              #
492              # first try to take the input as a single number              # first try to take the input as a single number
493              # if there's an exception try to break it into              # if there's an exception try to break it into
494              # a range seperated by a '-'. take care to ignore              # a range. if there is an exception here, let it
495              # a leading '-' as that could be for a negative number.              # pass up to the calling function.
             # then try to parse the individual parts. if there  
             # is an exception here, let it pass up to the calling  
             # function.  
496              #              #
497              try:              try:
498                  return (conv(value),)                  return (0, conv(value))
499              except ValueError:              except ValueError:
500                  i = value.find('-')                  return (1, Range(value))
                 if i == 0:  
                     i = value.find('-', 1)  
   
                 return (conv(value[:i]), conv(value[i+1:]))  
501    
502          assert False  # shouldn't get here          assert False  # shouldn't get here
503          return (0,)          return (0,None)
               
504    
505      def SetValueAsCustom(self, row, col, typeName, value):      def SetValueAsCustom(self, row, col, typeName, value):
506          """Set the cell specified by 'row' and 'col' to 'value'.          """Set the cell specified by 'row' and 'col' to 'value'.
# Line 556  class ClassTable(wxPyGridTableBase): Line 554  class ClassTable(wxPyGridTableBase):
554                      # changing the underlying group type if the                      # changing the underlying group type if the
555                      # group was a singleton and a range was entered                      # group was a singleton and a range was entered
556                      #                      #
557                      if len(dataInfo) == 1:                      if dataInfo[0] == 0:
558                          if not isinstance(group, ClassGroupSingleton):                          if not isinstance(group, ClassGroupSingleton):
559                              ngroup = ClassGroupSingleton(props = props)                              ngroup = ClassGroupSingleton(props = props)
560                              changed = True                              changed = True
561                          ngroup.SetValue(dataInfo[0])                          ngroup.SetValue(dataInfo[1])
562                      elif len(dataInfo) == 2:                      elif dataInfo[0] == 1:
563                          if not isinstance(group, ClassGroupRange):                          if not isinstance(group, ClassGroupRange):
564                              ngroup = ClassGroupRange(props = props)                              ngroup = ClassGroupRange(props = props)
565                              changed = True                              changed = True
566                          ngroup.SetRange(dataInfo[0], dataInfo[1])                          ngroup.SetRange(dataInfo[1])
567                      else:                      else:
568                          assert False                          assert False
569                          pass                          pass
# Line 673  EB_LAYER_TITLE = 0 Line 671  EB_LAYER_TITLE = 0
671  EB_SELECT_FIELD = 1  EB_SELECT_FIELD = 1
672  EB_GEN_CLASS = 2  EB_GEN_CLASS = 2
673    
674  class Classifier(NonModalDialog):  class Classifier(NonModalNonParentDialog):
675    
676      type2string = {None:             _("None"),      type2string = {None:             _("None"),
677                     FIELDTYPE_STRING: _("Text"),                     FIELDTYPE_STRING: _("Text"),
678                     FIELDTYPE_INT:    _("Integer"),                     FIELDTYPE_INT:    _("Integer"),
679                     FIELDTYPE_DOUBLE: _("Decimal")}                     FIELDTYPE_DOUBLE: _("Decimal")}
680    
681      def __init__(self, parent, name, layer, group = None):      def __init__(self, parent, name, map, layer, group = None):
682          NonModalDialog.__init__(self, parent, name, "")          NonModalNonParentDialog.__init__(self, parent, name, "")
683    
684          self.__SetTitle(layer.Title())          self.__SetTitle(layer.Title())
685    
686          self.layer = layer          self.layer = layer
687            self.map = map
688    
689          self.originalClass = self.layer.GetClassification()          self.map.Subscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)
690          field = self.originalClass.GetField()          self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
691          fieldType = self.originalClass.GetFieldType()                               self.layer_shapestore_replaced)
692    
693          self.genDlg = None          self.genDlg = None
694    
# Line 700  class Classifier(NonModalDialog): Line 699  class Classifier(NonModalDialog):
699          panel = wxPanel(self, -1)          panel = wxPanel(self, -1)
700    
701          text_title = wxTextCtrl(panel, ID_PROPERTY_TITLE, layer.Title())          text_title = wxTextCtrl(panel, ID_PROPERTY_TITLE, layer.Title())
702          #          self.fieldTypeText = wxStaticText(panel, -1, "")
         # make field choice box  
         #  
         self.fields = wxChoice(panel, ID_PROPERTY_SELECT,)  
   
         self.num_cols = layer.table.NumColumns()  
         # just assume the first field in case one hasn't been  
         # specified in the file.  
         self.__cur_field = 0  
   
         self.fields.Append("<None>")  
703    
704          if self.originalClass.GetFieldType() is None:          if layer.HasClassification():
705              self.fields.SetClientData(0, copy.deepcopy(self.originalClass))              self.originalClass = self.layer.GetClassification()
706          else:              field = self.originalClass.GetField()
707              self.fields.SetClientData(0, None)              fieldType = self.originalClass.GetFieldType()
708    
709          for i in range(self.num_cols):              #
710              name = layer.table.Column(i).name              # make field choice box
711              self.fields.Append(name)              #
712                self.fields = wxChoice(panel, ID_PROPERTY_SELECT,)
             if name == field:  
                 self.__cur_field = i + 1  
                 self.fields.SetClientData(i + 1,  
                                           copy.deepcopy(self.originalClass))  
             else:  
                 self.fields.SetClientData(i + 1, None)  
713    
714                self.num_cols = layer.table.NumColumns()
715                # just assume the first field in case one hasn't been
716                # specified in the file.
717                self.__cur_field = 0
718    
719          self.fieldTypeText = wxStaticText(panel, -1, "")              self.fields.Append("<None>")
720    
721          button_gen = wxButton(panel, ID_PROPERTY_GENCLASS, _("Generate Class"))              if self.originalClass.GetFieldType() is None:
722                    self.fields.SetClientData(0, copy.deepcopy(self.originalClass))
723                else:
724                    self.fields.SetClientData(0, None)
725    
726          button_add = wxButton(panel, ID_PROPERTY_ADD, _("Add"))              for i in range(self.num_cols):
727          button_moveup = wxButton(panel, ID_PROPERTY_MOVEUP, _("Move Up"))                  name = layer.table.Column(i).name
728          button_movedown = wxButton(panel, ID_PROPERTY_MOVEDOWN, _("Move Down"))                  self.fields.Append(name)
729          button_edit = wxButton(panel, ID_PROPERTY_EDITSYM, _("Edit Symbol"))  
730          button_remove = wxButton(panel, ID_PROPERTY_REMOVE, _("Remove"))                  if name == field:
731                        self.__cur_field = i + 1
732                        self.fields.SetClientData(i + 1,
733                                                copy.deepcopy(self.originalClass))
734                    else:
735                        self.fields.SetClientData(i + 1, None)
736    
737                button_gen = wxButton(panel, ID_PROPERTY_GENCLASS,
738                    _("Generate Class"))
739                button_add = wxButton(panel, ID_PROPERTY_ADD,
740                    _("Add"))
741                button_moveup = wxButton(panel, ID_PROPERTY_MOVEUP,
742                    _("Move Up"))
743                button_movedown = wxButton(panel, ID_PROPERTY_MOVEDOWN,
744                    _("Move Down"))
745                button_edit = wxButton(panel, ID_PROPERTY_EDITSYM,
746                    _("Edit Symbol"))
747                button_remove = wxButton(panel, ID_PROPERTY_REMOVE,
748                    _("Remove"))
749    
750                self.classGrid = ClassGrid(panel, self)
751    
752                # calling __SelectField after creating the classGrid fills in the
753                # grid with the correct information
754                self.fields.SetSelection(self.__cur_field)
755                self.__SelectField(self.__cur_field, group = group)
756    
757          button_try = wxButton(panel, ID_PROPERTY_TRY, _("Try"))          button_try = wxButton(self, ID_PROPERTY_TRY, _("Try"))
758          button_revert = wxButton(panel, ID_PROPERTY_REVERT, _("Revert"))          button_revert = wxButton(self, ID_PROPERTY_REVERT, _("Revert"))
759          button_ok = wxButton(panel, wxID_OK, _("OK"))          button_ok = wxButton(self, wxID_OK, _("OK"))
760          button_ok.SetDefault()          button_ok.SetDefault()
761          button_close = wxButton(panel, wxID_CANCEL, _("Close"))          button_close = wxButton(self, wxID_CANCEL, _("Close"))
   
         self.classGrid = ClassGrid(panel, self)  
   
         # calling __SelectField after creating the classGrid fills in the  
         # grid with the correct information  
         self.fields.SetSelection(self.__cur_field)  
         self.__SelectField(self.__cur_field, group = group)  
762    
763          ############################          ############################
764          # Layout the controls          # Layout the controls
# Line 767  class Classifier(NonModalDialog): Line 774  class Classifier(NonModalDialog):
774    
775          panelBox.Add(sizer, 0, wxGROW, 4)          panelBox.Add(sizer, 0, wxGROW, 4)
776    
777          panelBox.Add(wxStaticText(panel, -1,          if isinstance(layer, RasterLayer):
778                                  _("Type: %s") % layer.ShapeType()),              type = "Image"
779            else:
780                type = layer.ShapeType()
781    
782            panelBox.Add(wxStaticText(panel, -1, _("Type: %s") % type),
783              0, wxALIGN_LEFT | wxALL, 4)              0, wxALIGN_LEFT | wxALL, 4)
784    
785          classBox = wxStaticBoxSizer(          if layer.HasClassification():
                     wxStaticBox(panel, -1, _("Classification")), wxVERTICAL)  
786    
787                classBox = wxStaticBoxSizer(
788                            wxStaticBox(panel, -1, _("Classification")), wxVERTICAL)
789    
         sizer = wxBoxSizer(wxHORIZONTAL)  
         sizer.Add(wxStaticText(panel, ID_PROPERTY_FIELDTEXT, _("Field: ")),  
             0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 4)  
         sizer.Add(self.fields, 1, wxGROW | wxALL, 4)  
   
         classBox.Add(sizer, 0, wxGROW, 4)  
   
         classBox.Add(self.fieldTypeText, 0,  
                      wxGROW | wxALIGN_LEFT | wxALL | wxADJUST_MINSIZE, 4)  
   
         controlBox = wxBoxSizer(wxHORIZONTAL)  
         controlButtonBox = wxBoxSizer(wxVERTICAL)  
   
         controlButtonBox.Add(button_gen, 0, wxGROW|wxALL, 4)  
         controlButtonBox.Add(button_add, 0, wxGROW|wxALL, 4)  
         controlButtonBox.Add(button_moveup, 0, wxGROW|wxALL, 4)  
         controlButtonBox.Add(button_movedown, 0, wxGROW|wxALL, 4)  
         controlButtonBox.Add(button_edit, 0, wxGROW|wxALL, 4)  
         controlButtonBox.Add(60, 20, 0, wxGROW|wxALL|wxALIGN_BOTTOM, 4)  
         controlButtonBox.Add(button_remove, 0, wxGROW|wxALL|wxALIGN_BOTTOM, 4)  
790    
791          controlBox.Add(self.classGrid, 1, wxGROW, 0)              sizer = wxBoxSizer(wxHORIZONTAL)
792          controlBox.Add(controlButtonBox, 0, wxGROW, 10)              sizer.Add(wxStaticText(panel, ID_PROPERTY_FIELDTEXT, _("Field: ")),
793                    0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 4)
794                sizer.Add(self.fields, 1, wxGROW | wxALL, 4)
795    
796                classBox.Add(sizer, 0, wxGROW, 4)
797    
798                classBox.Add(self.fieldTypeText, 0,
799                            wxGROW | wxALIGN_LEFT | wxALL | wxADJUST_MINSIZE, 4)
800    
801                controlBox = wxBoxSizer(wxHORIZONTAL)
802                controlButtonBox = wxBoxSizer(wxVERTICAL)
803    
804                controlButtonBox.Add(button_gen, 0, wxGROW|wxALL, 4)
805                controlButtonBox.Add(button_add, 0, wxGROW|wxALL, 4)
806                controlButtonBox.Add(button_moveup, 0, wxGROW|wxALL, 4)
807                controlButtonBox.Add(button_movedown, 0, wxGROW|wxALL, 4)
808                controlButtonBox.Add(button_edit, 0, wxGROW|wxALL, 4)
809                controlButtonBox.Add(60, 20, 0, wxGROW|wxALL|wxALIGN_BOTTOM, 4)
810                controlButtonBox.Add(button_remove, 0,
811                                     wxGROW|wxALL|wxALIGN_BOTTOM, 4)
812    
813          classBox.Add(controlBox, 1, wxGROW, 10)              controlBox.Add(self.classGrid, 1, wxGROW, 0)
814          panelBox.Add(classBox, 1, wxGROW, 0)              controlBox.Add(controlButtonBox, 0, wxGROW, 10)
815    
816                classBox.Add(controlBox, 1, wxGROW, 10)
817                panelBox.Add(classBox, 1, wxGROW, 0)
818    
819    
820          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
821          buttonBox.Add(button_try, 0, wxALL, 4)          buttonBox.Add(button_try, 0, wxRIGHT|wxEXPAND, 10)
822          buttonBox.Add(60, 20, 0, wxALL, 4)          buttonBox.Add(button_revert, 0, wxRIGHT|wxEXPAND, 10)
823          buttonBox.Add(button_revert, 0, wxALL, 4)          buttonBox.Add(button_ok, 0, wxRIGHT|wxEXPAND, 10)
824          buttonBox.Add(60, 20, 0, wxALL, 4)          buttonBox.Add(button_close, 0, wxRIGHT|wxEXPAND, 10)
         buttonBox.Add(button_ok, 0, wxALL, 4)  
         buttonBox.Add(60, 20, 0, wxALL, 4)  
         buttonBox.Add(button_close, 0, wxALL, 4)  
         panelBox.Add(buttonBox, 0,  
             wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 0)  
825    
826          panel.SetAutoLayout(True)          panel.SetAutoLayout(True)
827          panel.SetSizer(panelBox)          panel.SetSizer(panelBox)
# Line 820  class Classifier(NonModalDialog): Line 829  class Classifier(NonModalDialog):
829          panelBox.SetSizeHints(panel)          panelBox.SetSizeHints(panel)
830    
831          topBox.Add(panel, 1, wxGROW | wxALL, 4)          topBox.Add(panel, 1, wxGROW | wxALL, 4)
832            topBox.Add(buttonBox, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)
833    
834          self.SetAutoLayout(True)          self.SetAutoLayout(True)
835          self.SetSizer(topBox)          self.SetSizer(topBox)
# Line 845  class Classifier(NonModalDialog): Line 855  class Classifier(NonModalDialog):
855    
856          ######################          ######################
857    
858          self.fields.SetFocus()          text_title.SetFocus()
859          self.haveApplied = False          self.haveApplied = False
860    
861        def unsubscribe_messages(self):
862            self.map.Unsubscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)
863            self.layer.Unsubscribe(LAYER_SHAPESTORE_REPLACED,
864                                   self.layer_shapestore_replaced)
865    
866        def map_layers_removed(self, map):
867            if self.layer not in self.map.Layers():
868                self.Close()
869    
870        def layer_shapestore_replaced(self, *args):
871            self.Close()
872    
873      def EditSymbol(self, row):      def EditSymbol(self, row):
874          table = self.classGrid.GetTable()          table = self.classGrid.GetTable()
875          prop = table.GetValueAsCustom(row, COL_SYMBOL, None)          prop = table.GetValueAsCustom(row, COL_SYMBOL, None)
# Line 964  class Classifier(NonModalDialog): Line 986  class Classifier(NonModalDialog):
986             it to the layer.             it to the layer.
987          """          """
988    
989          clazz = self.fields.GetClientData(self.__cur_field)          if self.layer.HasClassification():
990                clazz = self.fields.GetClientData(self.__cur_field)
991    
992          #              #
993          # only build the classification if there wasn't one to              # only build the classification if there wasn't one to
994          # to begin with or it has been modified              # to begin with or it has been modified
995          #              #
996          if clazz is None or self.classGrid.GetTable().IsModified():              self.classGrid.SaveEditControlValue()
997              clazz = self.__BuildClassification(self.__cur_field, True)              if clazz is None or self.classGrid.GetTable().IsModified():
998                    clazz = self.__BuildClassification(self.__cur_field, True)
999    
1000          self.layer.SetClassification(clazz)              self.layer.SetClassification(clazz)
1001    
1002          self.haveApplied = True          self.haveApplied = True
1003    
# Line 982  class Classifier(NonModalDialog): Line 1006  class Classifier(NonModalDialog):
1006          self.Close()          self.Close()
1007    
1008      def OnClose(self, event):      def OnClose(self, event):
1009          NonModalDialog.OnClose(self, event)          self.unsubscribe_messages()
1010            NonModalNonParentDialog.OnClose(self, event)
1011    
1012      def _OnCloseBtn(self, event):      def _OnCloseBtn(self, event):
1013          """Close is similar to Cancel except that any changes that were          """Close is similar to Cancel except that any changes that were
# Line 1169  class SelectPropertiesDialog(wxDialog): Line 1194  class SelectPropertiesDialog(wxDialog):
1194          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
1195          button_ok = wxButton(self, wxID_OK, _("OK"))          button_ok = wxButton(self, wxID_OK, _("OK"))
1196          button_ok.SetDefault()          button_ok.SetDefault()
1197          buttonBox.Add(button_ok, 0, wxALL, 4)          buttonBox.Add(button_ok, 0, wxRIGHT|wxEXPAND, 10)
1198          buttonBox.Add(wxButton(self, wxID_CANCEL, _("Cancel")),          buttonBox.Add(wxButton(self, wxID_CANCEL, _("Cancel")),
1199                        0, wxALL, 4)                        0, wxRIGHT|wxEXPAND, 10)
1200          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)          topBox.Add(buttonBox, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)
1201                                                                                                                                                                    
1202          #EVT_BUTTON(self, wxID_OK, self._OnOK)          #EVT_BUTTON(self, wxID_OK, self._OnOK)
1203          #EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)          #EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)

Legend:
Removed from v.835  
changed lines
  Added in v.1207

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26