/[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 671 by bh, Tue Apr 15 18:09:47 2003 UTC revision 1464 by bh, Fri Jul 18 18:20:40 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.common import *  from Thuban.UI.common import Color2wxColour, wxColour2Color
 from Thuban.UI.common import *  
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 Transparent
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    from messages import MAP_REPLACED
39    
40  ID_CLASS_TABLE = 40011  ID_CLASS_TABLE = 40011
41    
# Line 63  class ClassGrid(wxGrid): Line 69  class ClassGrid(wxGrid):
69                   use for display.                   use for display.
70          """          """
71    
72          wxGrid.__init__(self, parent, ID_CLASS_TABLE)          wxGrid.__init__(self, parent, ID_CLASS_TABLE, style = 0)
73    
74          self.classifier = classifier          self.classifier = classifier
75    
# Line 79  class ClassGrid(wxGrid): Line 85  class ClassGrid(wxGrid):
85          #print "GetCellAttr ", row, col          #print "GetCellAttr ", row, col
86          #wxGrid.GetCellAttr(self, row, col)          #wxGrid.GetCellAttr(self, row, col)
87    
88      def CreateTable(self, clazz, shapeType, group = None):      def CreateTable(self, clazz, fieldType, shapeType, group = None):
89    
90          assert isinstance(clazz, Classification)          assert isinstance(clazz, Classification)
91    
# Line 99  class ClassGrid(wxGrid): Line 105  class ClassGrid(wxGrid):
105          self.SetSelectionMode(wxGrid.wxGridSelectRows)          self.SetSelectionMode(wxGrid.wxGridSelectRows)
106          self.ClearSelection()          self.ClearSelection()
107    
108          table.Reset(clazz, shapeType, group)          table.Reset(clazz, fieldType, shapeType, group)
109    
110      def GetCurrentSelection(self):      def GetCurrentSelection(self):
111          """Return the currently highlighted rows as an increasing list          """Return the currently highlighted rows as an increasing list
# Line 244  class ClassGrid(wxGrid): Line 250  class ClassGrid(wxGrid):
250    
251      def _OnCellResize(self, event):      def _OnCellResize(self, event):
252          self.FitInside()          self.FitInside()
253            event.Skip()
254    
255  class ClassTable(wxPyGridTableBase):  class ClassTable(wxPyGridTableBase):
256      """Represents the underlying data structure for the grid."""      """Represents the underlying data structure for the grid."""
# Line 252  class ClassTable(wxPyGridTableBase): Line 259  class ClassTable(wxPyGridTableBase):
259    
260    
261      def __init__(self, view = None):      def __init__(self, view = None):
     #def __init__(self, clazz, shapeType, view = None):  
262          """Constructor.          """Constructor.
263    
264          shapeType -- the type of shape that the layer uses          shapeType -- the type of shape that the layer uses
# Line 269  class ClassTable(wxPyGridTableBase): Line 275  class ClassTable(wxPyGridTableBase):
275    
276          self.SetView(view)          self.SetView(view)
277    
278      def Reset(self, clazz, shapeType, group = None):      def Reset(self, clazz, fieldType, shapeType, group = None):
279          """Reset the table with the given data.          """Reset the table with the given data.
280    
281          This is necessary because wxWindows does not allow a grid's          This is necessary because wxWindows does not allow a grid's
# Line 287  class ClassTable(wxPyGridTableBase): Line 293  class ClassTable(wxPyGridTableBase):
293    
294          self.GetView().BeginBatch()          self.GetView().BeginBatch()
295    
296          self.fieldType = clazz.GetFieldType()          self.fieldType = fieldType
297          self.shapeType = shapeType          self.shapeType = shapeType
298    
299          self.SetClassification(clazz, group)          self.SetClassification(clazz, group)
# Line 458  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
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(Str2Num(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(Str2Num(value[:i])), conv(Str2Num(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(prop = 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(prop = 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 650  class ClassTable(wxPyGridTableBase): Line 648  class ClassTable(wxPyGridTableBase):
648              self.__NotifyRowChanges(old_len, self.GetNumberRows())              self.__NotifyRowChanges(old_len, self.GetNumberRows())
649    
650    
 ID_PROPERTY_OK = 4001  
651  ID_PROPERTY_REVERT = 4002  ID_PROPERTY_REVERT = 4002
652  ID_PROPERTY_ADD = 4003  ID_PROPERTY_ADD = 4003
653  ID_PROPERTY_GENCLASS = 4004  ID_PROPERTY_GENCLASS = 4004
# Line 659  ID_PROPERTY_MOVEUP = 4006 Line 656  ID_PROPERTY_MOVEUP = 4006
656  ID_PROPERTY_MOVEDOWN = 4007  ID_PROPERTY_MOVEDOWN = 4007
657  ID_PROPERTY_TRY = 4008  ID_PROPERTY_TRY = 4008
658  ID_PROPERTY_EDITSYM = 4009  ID_PROPERTY_EDITSYM = 4009
 ID_PROPERTY_CLOSE = 4010  
659  ID_PROPERTY_SELECT = 4011  ID_PROPERTY_SELECT = 4011
660  ID_PROPERTY_TITLE = 4012  ID_PROPERTY_TITLE = 4012
661  ID_PROPERTY_FIELDTEXT = 4013  ID_PROPERTY_FIELDTEXT = 4013
# Line 675  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.parent.Subscribe(MAP_REPLACED, self.map_replaced)
687          self.layer = layer          self.layer = layer
688            self.map = map
689    
690          self.originalClass = self.layer.GetClassification()          self.map.Subscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)
691          field = self.originalClass.GetField()          self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
692          fieldType = self.originalClass.GetFieldType()                               self.layer_shapestore_replaced)
693    
694          self.genDlg = None          self.genDlg = None
695    
696          topBox = wxBoxSizer(wxVERTICAL)          ############################
697            # Create the controls
698            #
699    
700          panel = wxPanel(self, -1, size=(100, 100))          panel = wxPanel(self, -1)
701    
702          panelBox = wxBoxSizer(wxVERTICAL)          text_title = wxTextCtrl(panel, ID_PROPERTY_TITLE, layer.Title())
703            self.fieldTypeText = wxStaticText(panel, -1, "")
704    
705          sizer = wxBoxSizer(wxHORIZONTAL)          if layer.HasClassification():
706          sizer.Add(wxStaticText(panel, -1, _("Title: ")),              self.originalClass = self.layer.GetClassification()
707              0, wxALIGN_LEFT | wxALL | wxALIGN_CENTER_VERTICAL, 4)              self.originalClassField = self.layer.GetClassificationColumn()
708          sizer.Add(wxTextCtrl(panel, ID_PROPERTY_TITLE, layer.Title()),              field = self.originalClassField
709                    1, wxGROW | wxALL, 4)              fieldType = self.layer.GetFieldType(field)
         EVT_TEXT(self, ID_PROPERTY_TITLE, self._OnTitleChanged)  
710    
711          panelBox.Add(sizer, 0, wxGROW, 4)              table = layer.ShapeStore().Table()
712                #
713                # make field choice box
714                #
715                self.fields = wxChoice(panel, ID_PROPERTY_SELECT,)
716    
717          panelBox.Add(wxStaticText(panel, -1,              self.num_cols = table.NumColumns()
718                                  _("Type: %s") % layer.ShapeType()),              # just assume the first field in case one hasn't been
719              0, wxALIGN_LEFT | wxALL, 4)              # specified in the file.
720                self.__cur_field = 0
721    
722                self.fields.Append("<None>")
723    
724          #####################              if fieldType is None:
725                    self.fields.SetClientData(0, copy.deepcopy(self.originalClass))
726                else:
727                    self.fields.SetClientData(0, None)
728    
729          #panelBox = wxBoxSizer(wxVERTICAL)              for i in range(self.num_cols):
730          classBox = wxStaticBoxSizer(                  name = table.Column(i).name
731                      wxStaticBox(panel, -1, _("Classification")), wxVERTICAL)                  self.fields.Append(name)
732    
733                    if name == field:
734                        self.__cur_field = i + 1
735                        self.fields.SetClientData(i + 1,
736                                                  copy.deepcopy(self.originalClass))
737                    else:
738                        self.fields.SetClientData(i + 1, None)
739    
740                button_gen = wxButton(panel, ID_PROPERTY_GENCLASS,
741                    _("Generate Class"))
742                button_add = wxButton(panel, ID_PROPERTY_ADD,
743                    _("Add"))
744                button_moveup = wxButton(panel, ID_PROPERTY_MOVEUP,
745                    _("Move Up"))
746                button_movedown = wxButton(panel, ID_PROPERTY_MOVEDOWN,
747                    _("Move Down"))
748                button_edit = wxButton(panel, ID_PROPERTY_EDITSYM,
749                    _("Edit Symbol"))
750                button_remove = wxButton(panel, ID_PROPERTY_REMOVE,
751                    _("Remove"))
752    
753                self.classGrid = ClassGrid(panel, self)
754    
755                # calling __SelectField after creating the classGrid fills in the
756                # grid with the correct information
757                self.fields.SetSelection(self.__cur_field)
758                self.__SelectField(self.__cur_field, group = group)
759    
760            button_try = wxButton(self, ID_PROPERTY_TRY, _("Try"))
761            button_revert = wxButton(self, ID_PROPERTY_REVERT, _("Revert"))
762            button_ok = wxButton(self, wxID_OK, _("OK"))
763            button_close = wxButton(self, wxID_CANCEL, _("Close"))
764            button_ok.SetDefault()
765    
766            ############################
767            # Layout the controls
768          #          #
         # make field combo box  
         #  
         self.fields = wxComboBox(panel, ID_PROPERTY_SELECT, "",  
                                      style = wxCB_READONLY)  
   
         self.num_cols = layer.table.field_count()  
         # just assume the first field in case one hasn't been  
         # specified in the file.  
         self.__cur_field = 0  
   
         self.fields.Append("<None>")  
769    
770          if self.originalClass.GetFieldType() is None:          topBox = wxBoxSizer(wxVERTICAL)
771              self.fields.SetClientData(0, copy.deepcopy(self.originalClass))          panelBox = wxBoxSizer(wxVERTICAL)
         else:  
             self.fields.SetClientData(0, None)  
772    
773          for i in range(self.num_cols):          sizer = wxBoxSizer(wxHORIZONTAL)
774              type, name, len, decc = layer.table.field_info(i)          sizer.Add(wxStaticText(panel, -1, _("Title: ")),
775              self.fields.Append(name)              0, wxALIGN_LEFT | wxALL | wxALIGN_CENTER_VERTICAL, 4)
776            sizer.Add(text_title, 1, wxGROW, 0)
             if name == field:  
                 self.__cur_field = i + 1  
                 self.fields.SetClientData(i + 1,  
                                           copy.deepcopy(self.originalClass))  
             else:  
                 self.fields.SetClientData(i + 1, None)  
777    
778            panelBox.Add(sizer, 0, wxGROW, 4)
779    
780          ###########          if isinstance(layer, RasterLayer):
781                type = "Image"
782            else:
783                type = layer.ShapeType()
784    
785            panelBox.Add(wxStaticText(panel, -1, _("Type: %s") % type),
786                0, wxALIGN_LEFT | wxALL, 4)
787    
788          sizer = wxBoxSizer(wxHORIZONTAL)          if layer.HasClassification():
         sizer.Add(wxStaticText(panel, ID_PROPERTY_FIELDTEXT, _("Field: ")),  
             0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 4)  
         sizer.Add(self.fields, 1, wxGROW | wxALL, 4)  
         EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self._OnFieldSelect)  
789    
790          classBox.Add(sizer, 0, wxGROW, 4)              classBox = wxStaticBoxSizer(
791                            wxStaticBox(panel, -1, _("Classification")), wxVERTICAL)
792    
         self.fieldTypeText = wxStaticText(panel, -1, "")  
         classBox.Add(self.fieldTypeText, 0,  
                      wxGROW | wxALIGN_LEFT | wxALL | wxADJUST_MINSIZE, 4)  
793    
794                sizer = wxBoxSizer(wxHORIZONTAL)
795                sizer.Add(wxStaticText(panel, ID_PROPERTY_FIELDTEXT, _("Field: ")),
796                    0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 4)
797                sizer.Add(self.fields, 1, wxGROW | wxALL, 4)
798    
799          #              classBox.Add(sizer, 0, wxGROW, 4)
         # Control Box  
         #  
         controlBox = wxBoxSizer(wxHORIZONTAL)  
800    
801                classBox.Add(self.fieldTypeText, 0,
802                            wxGROW | wxALIGN_LEFT | wxALL | wxADJUST_MINSIZE, 4)
803    
804          ###########              controlBox = wxBoxSizer(wxHORIZONTAL)
805          #              controlButtonBox = wxBoxSizer(wxVERTICAL)
         # Control buttons:  
         #  
         controlButtonBox = wxBoxSizer(wxVERTICAL)  
806    
807          button = wxButton(panel, ID_PROPERTY_GENCLASS, _("Generate Class"))              controlButtonBox.Add(button_gen, 0, wxGROW|wxALL, 4)
808          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)              controlButtonBox.Add(button_add, 0, wxGROW|wxALL, 4)
809                controlButtonBox.Add(button_moveup, 0, wxGROW|wxALL, 4)
810                controlButtonBox.Add(button_movedown, 0, wxGROW|wxALL, 4)
811                controlButtonBox.Add(button_edit, 0, wxGROW|wxALL, 4)
812                controlButtonBox.Add(60, 20, 0, wxGROW|wxALL|wxALIGN_BOTTOM, 4)
813                controlButtonBox.Add(button_remove, 0,
814                                     wxGROW|wxALL|wxALIGN_BOTTOM, 4)
815    
816          button = wxButton(panel, ID_PROPERTY_ADD, _("Add"))              controlBox.Add(self.classGrid, 1, wxGROW, 0)
817          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)              controlBox.Add(controlButtonBox, 0, wxGROW, 10)
818    
819          button = wxButton(panel, ID_PROPERTY_MOVEUP, _("Move Up"))              classBox.Add(controlBox, 1, wxGROW, 10)
820          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)              panelBox.Add(classBox, 1, wxGROW, 0)
821    
         button = wxButton(panel, ID_PROPERTY_MOVEDOWN, _("Move Down"))  
         controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)  
822    
823          button = wxButton(panel, ID_PROPERTY_EDITSYM, _("Edit Symbol"))          buttonBox = wxBoxSizer(wxHORIZONTAL)
824          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)          buttonBox.Add(button_try, 0, wxRIGHT|wxEXPAND, 10)
825            buttonBox.Add(button_revert, 0, wxRIGHT|wxEXPAND, 10)
826            buttonBox.Add(button_ok, 0, wxRIGHT|wxEXPAND, 10)
827            buttonBox.Add(button_close, 0, wxRIGHT|wxEXPAND, 10)
828    
829          controlButtonBox.Add(60, 20, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)          panel.SetAutoLayout(True)
830            panel.SetSizer(panelBox)
831            panelBox.Fit(panel)
832            panelBox.SetSizeHints(panel)
833    
834          button = wxButton(panel, ID_PROPERTY_REMOVE, _("Remove"))          topBox.Add(panel, 1, wxGROW | wxALL, 4)
835          controlButtonBox.Add(button, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)          topBox.Add(buttonBox, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)
836    
837            self.SetAutoLayout(True)
838            self.SetSizer(topBox)
839            topBox.Fit(self)
840            topBox.SetSizeHints(self)
841            self.Layout()
842    
843          ###########          ###########
         #  
         # Classification data table  
         #  
   
         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)  
844    
845          controlBox.Add(self.classGrid, 1, wxGROW, 0)          EVT_CHOICE(self, ID_PROPERTY_SELECT, self._OnFieldSelect)
846          controlBox.Add(controlButtonBox, 0, wxGROW, 10)          EVT_TEXT(self, ID_PROPERTY_TITLE, self._OnTitleChanged)
847            EVT_BUTTON(self, wxID_OK, self._OnOK)
848          classBox.Add(controlBox, 1, wxGROW, 10)          EVT_BUTTON(self, ID_PROPERTY_TRY, self._OnTry)
849          panelBox.Add(classBox, 1, wxGROW, 0)          EVT_BUTTON(self, wxID_CANCEL, self._OnCloseBtn)
850            EVT_BUTTON(self, ID_PROPERTY_REVERT, self._OnRevert)
851    
852          EVT_BUTTON(self, ID_PROPERTY_ADD, self._OnAdd)          EVT_BUTTON(self, ID_PROPERTY_ADD, self._OnAdd)
853          EVT_BUTTON(self, ID_PROPERTY_EDITSYM, self._OnEditSymbol)          EVT_BUTTON(self, ID_PROPERTY_EDITSYM, self._OnEditSymbol)
# Line 826  class Classifier(NonModalDialog): Line 856  class Classifier(NonModalDialog):
856          EVT_BUTTON(self, ID_PROPERTY_MOVEUP, self._OnMoveUp)          EVT_BUTTON(self, ID_PROPERTY_MOVEUP, self._OnMoveUp)
857          EVT_BUTTON(self, ID_PROPERTY_MOVEDOWN, self._OnMoveDown)          EVT_BUTTON(self, ID_PROPERTY_MOVEDOWN, self._OnMoveDown)
858    
859          ###########          ######################
   
   
         panel.SetAutoLayout(True)  
         panel.SetSizer(panelBox)  
         panelBox.SetSizeHints(panel)  
   
         topBox.Add(panel, 1, wxGROW | wxALL, 4)  
   
         ###########  
860    
861          buttonBox = wxBoxSizer(wxHORIZONTAL)          text_title.SetFocus()
862          buttonBox.Add(wxButton(self, ID_PROPERTY_TRY, _("Try")),          self.haveApplied = False
                       0, wxALL, 4)  
         buttonBox.Add(60, 20, 0, wxALL, 4)  
         buttonBox.Add(wxButton(self, ID_PROPERTY_REVERT, _("Revert")),  
                       0, wxALL, 4)  
         buttonBox.Add(60, 20, 0, wxALL, 4)  
         buttonBox.Add(wxButton(self, ID_PROPERTY_OK, _("OK")),  
                       0, wxALL, 4)  
         buttonBox.Add(60, 20, 0, wxALL, 4)  
         buttonBox.Add(wxButton(self, ID_PROPERTY_CLOSE, _("Close")),  
                       0, wxALL, 4)  
         topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 0)  
863    
864          EVT_BUTTON(self, ID_PROPERTY_OK, self._OnOK)      def unsubscribe_messages(self):
865          EVT_BUTTON(self, ID_PROPERTY_TRY, self._OnTry)          self.parent.Unsubscribe(MAP_REPLACED, self.map_replaced)
866          EVT_BUTTON(self, ID_PROPERTY_CLOSE, self._OnCloseBtn)          self.map.Unsubscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)
867          EVT_BUTTON(self, ID_PROPERTY_REVERT, self._OnRevert)          self.layer.Unsubscribe(LAYER_SHAPESTORE_REPLACED,
868                                   self.layer_shapestore_replaced)
869    
870        def map_layers_removed(self, map):
871            if self.layer not in self.map.Layers():
872                self.Close()
873    
874          ###########      def layer_shapestore_replaced(self, *args):
875            """Subscribed to the map's LAYER_SHAPESTORE_REPLACED message.
876    
877          topBox.SetSizeHints(self)          Close self.
878          self.SetAutoLayout(True)          """
879          self.SetSizer(topBox)          self.Close()
   
         #self.Fit()  
         ######################  
880    
881          self.haveApplied = False      def map_replaced(self, *args):
882            """Subscribed to the mainwindow's MAP_REPLACED message. Close self."""
883            self.Close()
884    
885      def EditSymbol(self, row):      def EditSymbol(self, row):
886          table = self.classGrid.GetTable()          table = self.classGrid.GetTable()
# Line 873  class Classifier(NonModalDialog): Line 888  class Classifier(NonModalDialog):
888    
889          # get a new ClassGroupProperties object and copy the          # get a new ClassGroupProperties object and copy the
890          # values over to our current object          # values over to our current object
891          propDlg = SelectPropertiesDialog(NULL, prop, self.layer.ShapeType())          propDlg = SelectPropertiesDialog(self, prop, self.layer.ShapeType())
892    
893          self.Enable(False)          self.Enable(False)
894          if propDlg.ShowModal() == wxID_OK:          if propDlg.ShowModal() == wxID_OK:
# Line 887  class Classifier(NonModalDialog): Line 902  class Classifier(NonModalDialog):
902          self.fields.SetClientData(self.__cur_field, clazz)          self.fields.SetClientData(self.__cur_field, clazz)
903          self.classGrid.GetTable().SetClassification(clazz)          self.classGrid.GetTable().SetClassification(clazz)
904    
905      def __BuildClassification(self, fieldIndex, copyClass = False):      def __BuildClassification(self, fieldIndex, copyClass=False, force=False):
906    
907  #       numRows = self.classGrid.GetNumberRows()  #       numRows = self.classGrid.GetNumberRows()
908  #       assert numRows > 0  # there should always be a default row  #       assert numRows > 0  # there should always be a default row
909    
 #       clazz = Classification()  
910          if fieldIndex == 0:          if fieldIndex == 0:
911              fieldName = None              fieldName = None
912              fieldType = None              fieldType = None
# Line 900  class Classifier(NonModalDialog): Line 914  class Classifier(NonModalDialog):
914              fieldName = self.fields.GetString(fieldIndex)              fieldName = self.fields.GetString(fieldIndex)
915              fieldType = self.layer.GetFieldType(fieldName)              fieldType = self.layer.GetFieldType(fieldName)
916    
917          clazz = self.classGrid.GetTable().GetClassification()          clazz = self.fields.GetClientData(fieldIndex)
918            if clazz is None or self.classGrid.GetTable().IsModified() or force:
919          if copyClass:              clazz = self.classGrid.GetTable().GetClassification()
920              clazz = copy.deepcopy(clazz)              if copyClass:
921                    clazz = copy.deepcopy(clazz)
         clazz.SetField(fieldName)  
         clazz.SetFieldType(fieldType)  
   
   
 #       table = self.classGrid.GetTable()  
 #       clazz.SetDefaultGroup(table.GetClassGroup(0))  
   
 #       for i in range(1, numRows):  
 #           clazz.AppendGroup(table.GetClassGroup(i))  
922    
923          return clazz          return clazz, fieldName
924    
925      def __SetGridTable(self, fieldIndex, group = None):      def __SetGridTable(self, fieldIndex, group = None):
926    
# Line 928  class Classifier(NonModalDialog): Line 933  class Classifier(NonModalDialog):
933                      self.layer.GetClassification().                      self.layer.GetClassification().
934                                 GetDefaultGroup().GetProperties()))                                 GetDefaultGroup().GetProperties()))
935    
936              fieldName = self.fields.GetString(fieldIndex)          fieldName = self.fields.GetString(fieldIndex)
937              fieldType = self.layer.GetFieldType(fieldName)          fieldType = self.layer.GetFieldType(fieldName)
             clazz.SetFieldType(fieldType)  
938                                    
939          self.classGrid.CreateTable(clazz, self.layer.ShapeType(), group)          self.classGrid.CreateTable(clazz, fieldType,
940                                       self.layer.ShapeType(), group)
941    
942      def __SetFieldTypeText(self, fieldIndex):      def __SetFieldTypeText(self, fieldIndex):
943          fieldName = self.fields.GetString(fieldIndex)          fieldName = self.fields.GetString(fieldIndex)
# Line 952  class Classifier(NonModalDialog): Line 957  class Classifier(NonModalDialog):
957          assert oldIndex >= -1          assert oldIndex >= -1
958    
959          if oldIndex != -1:          if oldIndex != -1:
960              clazz = self.__BuildClassification(oldIndex)              clazz, name = self.__BuildClassification(oldIndex, force = True)
961              self.fields.SetClientData(oldIndex, clazz)              self.fields.SetClientData(oldIndex, clazz)
962    
963          self.__SetGridTable(newIndex, group)          self.__SetGridTable(newIndex, group)
964    
965          self.__EnableButtons(EB_SELECT_FIELD, newIndex != 0)          self.__EnableButtons(EB_SELECT_FIELD)
966    
967          self.__SetFieldTypeText(newIndex)          self.__SetFieldTypeText(newIndex)
968    
# Line 983  class Classifier(NonModalDialog): Line 988  class Classifier(NonModalDialog):
988             it to the layer.             it to the layer.
989          """          """
990    
991          clazz = self.fields.GetClientData(self.__cur_field)          if self.layer.HasClassification():
992                clazz = self.fields.GetClientData(self.__cur_field)
993    
994          #              #
995          # only build the classification if there wasn't one to              # only build the classification if there wasn't one to
996          # to begin with or it has been modified              # to begin with or it has been modified
997          #              #
998          if clazz is None or self.classGrid.GetTable().IsModified():              self.classGrid.SaveEditControlValue()
999              clazz = self.__BuildClassification(self.__cur_field, True)              clazz, name = self.__BuildClassification(self.__cur_field, True)
1000    
1001          self.layer.SetClassification(clazz)              self.layer.SetClassificationColumn(name)
1002                self.layer.SetClassification(clazz)
1003    
1004          self.haveApplied = True          self.haveApplied = True
1005    
# Line 1000  class Classifier(NonModalDialog): Line 1007  class Classifier(NonModalDialog):
1007          self._OnTry(event)          self._OnTry(event)
1008          self.Close()          self.Close()
1009    
1010        def OnClose(self, event):
1011            self.unsubscribe_messages()
1012            NonModalNonParentDialog.OnClose(self, event)
1013    
1014      def _OnCloseBtn(self, event):      def _OnCloseBtn(self, event):
1015          """Close is similar to Cancel except that any changes that were          """Close is similar to Cancel except that any changes that were
1016          made and applied remain applied, but the currently displayed          made and applied remain applied, but the currently displayed
# Line 1011  class Classifier(NonModalDialog): Line 1022  class Classifier(NonModalDialog):
1022      def _OnRevert(self, event):      def _OnRevert(self, event):
1023          """The layer's current classification stays the same."""          """The layer's current classification stays the same."""
1024          if self.haveApplied:          if self.haveApplied:
1025                self.layer.SetClassificationColumn(self.originalClassField)
1026              self.layer.SetClassification(self.originalClass)              self.layer.SetClassification(self.originalClass)
1027    
1028          #self.Close()          #self.Close()
# Line 1028  class Classifier(NonModalDialog): Line 1040  class Classifier(NonModalDialog):
1040    
1041          EVT_CLOSE(self.genDlg, self._OnGenDialogClose)          EVT_CLOSE(self.genDlg, self._OnGenDialogClose)
1042    
1043          self.__EnableButtons(EB_GEN_CLASS, False)          self.__EnableButtons(EB_GEN_CLASS)
1044    
1045          self.genDlg.Show()          self.genDlg.Show()
1046    
1047      def _OnGenDialogClose(self, event):      def _OnGenDialogClose(self, event):
1048          self.genDlg.Destroy()          self.genDlg.Destroy()
1049          self.__EnableButtons(EB_GEN_CLASS, True)          self.genDlg = None
1050            self.__EnableButtons(EB_GEN_CLASS)
1051    
1052      def _OnMoveUp(self, event):      def _OnMoveUp(self, event):
1053          sel = self.classGrid.GetCurrentSelection()          sel = self.classGrid.GetCurrentSelection()
# Line 1072  class Classifier(NonModalDialog): Line 1085  class Classifier(NonModalDialog):
1085          self.layer.SetTitle(obj.GetValue())          self.layer.SetTitle(obj.GetValue())
1086          self.__SetTitle(self.layer.Title())          self.__SetTitle(self.layer.Title())
1087    
1088          self.__EnableButtons(EB_LAYER_TITLE, self.layer.Title() != "")          self.__EnableButtons(EB_LAYER_TITLE)
1089    
1090        def __EnableButtons(self, case):
1091    
1092      def __EnableButtons(self, case, enable):          list = {wxID_OK                 : True,
1093                    wxID_CANCEL             : True,
1094                    ID_PROPERTY_ADD         : True,
1095                    ID_PROPERTY_MOVEUP      : True,
1096                    ID_PROPERTY_MOVEDOWN    : True,
1097                    ID_PROPERTY_REMOVE      : True,
1098                    ID_PROPERTY_SELECT      : True,
1099                    ID_PROPERTY_FIELDTEXT   : True,
1100                    ID_PROPERTY_GENCLASS    : True,
1101                    ID_PROPERTY_EDITSYM     : True}
1102    
1103          if case == EB_LAYER_TITLE:            if case == EB_LAYER_TITLE:  
1104              list = (ID_PROPERTY_OK,              if self.layer.Title() == "":
1105                      ID_PROPERTY_CLOSE)                  list[wxID_OK] = False
1106                    list[wxID_CANCEL] = False
1107    
1108          elif case == EB_SELECT_FIELD:          elif case == EB_SELECT_FIELD:
1109              list = (ID_PROPERTY_GENCLASS,              if self.fields.GetSelection() == 0:
1110                      ID_PROPERTY_ADD,                  list[ID_PROPERTY_GENCLASS] = False
1111                      ID_PROPERTY_MOVEUP,                  list[ID_PROPERTY_ADD] = False
1112                      ID_PROPERTY_MOVEDOWN,                  list[ID_PROPERTY_MOVEUP] = False
1113                      ID_PROPERTY_EDITSYM,                  list[ID_PROPERTY_MOVEDOWN] = False
1114                      ID_PROPERTY_REMOVE)                  list[ID_PROPERTY_REMOVE] = False
1115    
1116          elif case == EB_GEN_CLASS:          elif case == EB_GEN_CLASS:
1117              list = (ID_PROPERTY_SELECT,              if self.genDlg is not None:
1118                      ID_PROPERTY_FIELDTEXT,                  list[ID_PROPERTY_SELECT] = False
1119                      ID_PROPERTY_GENCLASS,                  list[ID_PROPERTY_FIELDTEXT] = False
1120                      ID_PROPERTY_EDITSYM)                  list[ID_PROPERTY_GENCLASS] = False
1121    
1122            for id, enable in list.items():
1123                win = self.FindWindowById(id)
1124                if win:
1125                    win.Enable(enable)
1126    
         for id in list:  
             self.FindWindowById(id).Enable(enable)  
   
 ID_SELPROP_OK = 4001  
 ID_SELPROP_CANCEL = 4002  
1127  ID_SELPROP_SPINCTRL = 4002  ID_SELPROP_SPINCTRL = 4002
1128  ID_SELPROP_PREVIEW = 4003  ID_SELPROP_PREVIEW = 4003
1129  ID_SELPROP_STROKECLR = 4004  ID_SELPROP_STROKECLR = 4004
# Line 1137  class SelectPropertiesDialog(wxDialog): Line 1162  class SelectPropertiesDialog(wxDialog):
1162          ctrlBox = wxBoxSizer(wxVERTICAL)          ctrlBox = wxBoxSizer(wxVERTICAL)
1163    
1164          lineColorBox = wxBoxSizer(wxHORIZONTAL)          lineColorBox = wxBoxSizer(wxHORIZONTAL)
1165          lineColorBox.Add(          button = wxButton(self, ID_SELPROP_STROKECLR, _("Change Line Color"))
1166              wxButton(self, ID_SELPROP_STROKECLR, _("Change Line Color")),          button.SetFocus()
1167              1, wxALL | wxGROW, 4)          lineColorBox.Add(button, 1, wxALL | wxGROW, 4)
1168          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)
1169    
1170          lineColorBox.Add(          lineColorBox.Add(
# Line 1185  class SelectPropertiesDialog(wxDialog): Line 1210  class SelectPropertiesDialog(wxDialog):
1210          # Control buttons:          # Control buttons:
1211          #          #
1212          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
1213          buttonBox.Add(wxButton(self, ID_SELPROP_OK, _("OK")),          button_ok = wxButton(self, wxID_OK, _("OK"))
1214                        0, wxALL, 4)          buttonBox.Add(button_ok, 0, wxRIGHT|wxEXPAND, 10)
1215          buttonBox.Add(wxButton(self, ID_SELPROP_CANCEL, _("Cancel")),          buttonBox.Add(wxButton(self, wxID_CANCEL, _("Cancel")),
1216                        0, wxALL, 4)                        0, wxRIGHT|wxEXPAND, 10)
1217          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)          topBox.Add(buttonBox, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)
1218    
1219            button_ok.SetDefault()
1220                                                                                                                                                                    
1221          EVT_BUTTON(self, ID_SELPROP_OK, self._OnOK)          #EVT_BUTTON(self, wxID_OK, self._OnOK)
1222          EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)          #EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)
1223                                                                                                                                                                    
1224          self.SetAutoLayout(True)          self.SetAutoLayout(True)
1225          self.SetSizer(topBox)          self.SetSizer(topBox)
1226          topBox.Fit(self)          topBox.Fit(self)
1227          topBox.SetSizeHints(self)          topBox.SetSizeHints(self)
1228    
1229      def _OnOK(self, event):      def OnOK(self, event):
1230          self.EndModal(wxID_OK)          self.EndModal(wxID_OK)
1231    
1232      def _OnCancel(self, event):      def OnCancel(self, event):
1233          self.EndModal(wxID_CANCEL)          self.EndModal(wxID_CANCEL)
1234    
1235      def _OnSpin(self, event):      def _OnSpin(self, event):
# Line 1211  class SelectPropertiesDialog(wxDialog): Line 1238  class SelectPropertiesDialog(wxDialog):
1238    
1239      def __GetColor(self, cur):      def __GetColor(self, cur):
1240          dialog = wxColourDialog(self)          dialog = wxColourDialog(self)
1241          if cur is not Color.Transparent:          if cur is not Transparent:
1242              dialog.GetColourData().SetColour(Color2wxColour(cur))              dialog.GetColourData().SetColour(Color2wxColour(cur))
1243    
1244          ret = None          ret = None
# Line 1229  class SelectPropertiesDialog(wxDialog): Line 1256  class SelectPropertiesDialog(wxDialog):
1256          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1257    
1258      def _OnChangeLineColorTrans(self, event):      def _OnChangeLineColorTrans(self, event):
1259          self.prop.SetLineColor(Color.Transparent)          self.prop.SetLineColor(Transparent)
1260          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1261                    
1262      def _OnChangeFillColor(self, event):      def _OnChangeFillColor(self, event):
# Line 1239  class SelectPropertiesDialog(wxDialog): Line 1266  class SelectPropertiesDialog(wxDialog):
1266          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1267    
1268      def _OnChangeFillColorTrans(self, event):      def _OnChangeFillColorTrans(self, event):
1269          self.prop.SetFill(Color.Transparent)          self.prop.SetFill(Transparent)
1270          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1271    
1272      def GetClassGroupProperties(self):      def GetClassGroupProperties(self):
# Line 1295  class ClassDataPreviewer: Line 1322  class ClassDataPreviewer:
1322              h = rect.GetHeight()              h = rect.GetHeight()
1323    
1324          stroke = prop.GetLineColor()          stroke = prop.GetLineColor()
1325          if stroke is Color.Transparent:          if stroke is Transparent:
1326              pen = wxTRANSPARENT_PEN              pen = wxTRANSPARENT_PEN
1327          else:          else:
1328              pen = wxPen(Color2wxColour(stroke),              pen = wxPen(Color2wxColour(stroke),
# Line 1303  class ClassDataPreviewer: Line 1330  class ClassDataPreviewer:
1330                          wxSOLID)                          wxSOLID)
1331    
1332          stroke = prop.GetFill()          stroke = prop.GetFill()
1333          if stroke is Color.Transparent:          if stroke is Transparent:
1334              brush = wxTRANSPARENT_BRUSH              brush = wxTRANSPARENT_BRUSH
1335          else:          else:
1336              brush = wxBrush(Color2wxColour(stroke), wxSOLID)              brush = wxBrush(Color2wxColour(stroke), wxSOLID)
# Line 1362  class ClassGroupPropertiesCtrl(wxWindow, Line 1389  class ClassGroupPropertiesCtrl(wxWindow,
1389    
1390          wxWindow.__init__(self, parent, id, size = size, style = style)          wxWindow.__init__(self, parent, id, size = size, style = style)
1391    
1392            self.parent = parent
1393    
1394          self.SetProperties(props)          self.SetProperties(props)
1395          self.SetShapeType(shapeType)          self.SetShapeType(shapeType)
1396          self.AllowEdit(True)          self.AllowEdit(True)
# Line 1405  class ClassGroupPropertiesCtrl(wxWindow, Line 1434  class ClassGroupPropertiesCtrl(wxWindow,
1434      def DoEdit(self):      def DoEdit(self):
1435          if not self.allowEdit: return          if not self.allowEdit: return
1436    
1437          propDlg = SelectPropertiesDialog(NULL,          propDlg = SelectPropertiesDialog(self.parent,
1438                                           self.GetProperties(),                                           self.GetProperties(),
1439                                           self.GetShapeType())                                           self.GetShapeType())
1440    

Legend:
Removed from v.671  
changed lines
  Added in v.1464

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26