/[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 496 by jonathan, Mon Mar 10 10:54:50 2003 UTC revision 671 by bh, Tue Apr 15 18:09:47 2003 UTC
# 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 Thuban.UI.classgen import ClassGenDialog, ClassGenerator
31    
32  from dialogs import NonModalDialog  from dialogs import NonModalDialog
33    
 # widget id's  
 ID_PROPERTY_SELECT = 4010  
34  ID_CLASS_TABLE = 40011  ID_CLASS_TABLE = 40011
35    
 ID_CLASSIFY_OK = 4001  
 ID_CLASSIFY_CANCEL = 4002  
 ID_CLASSIFY_ADD = 4003  
 ID_CLASSIFY_GENRANGE = 4004  
 ID_CLASSIFY_REMOVE = 4005  
 ID_CLASSIFY_MOVEUP = 4006  
 ID_CLASSIFY_MOVEDOWN = 4007  
 ID_CLASSIFY_APPLY = 4008  
36    
37  # table columns  # table columns
38  COL_SYMBOL = 0  COL_VISIBLE = 0
39  COL_VALUE  = 1  COL_SYMBOL  = 1
40  COL_LABEL  = 2  COL_VALUE   = 2
41    COL_LABEL   = 3
42    NUM_COLS    = 4
43    
44  # indices into the client data lists in Classifier.fields  # indices into the client data lists in Classifier.fields
45  FIELD_CLASS = 0  FIELD_CLASS = 0
# Line 59  FIELD_NAME = 2 Line 53  FIELD_NAME = 2
53  import weakref  import weakref
54  class ClassGrid(wxGrid):  class ClassGrid(wxGrid):
55    
56      def __init__(self, parent):  
57        def __init__(self, parent, classifier):
58          """Constructor.          """Constructor.
59    
60          parent -- the parent window          parent -- the parent window
# Line 68  class ClassGrid(wxGrid): Line 63  class ClassGrid(wxGrid):
63                   use for display.                   use for display.
64          """          """
65    
         #wxGrid.__init__(self, parent, ID_CLASS_TABLE, size = (340, 160))  
66          wxGrid.__init__(self, parent, ID_CLASS_TABLE)          wxGrid.__init__(self, parent, ID_CLASS_TABLE)
67          #self.SetTable(ClassTable(fieldData, layer.ShapeType(), self), true)  
68            self.classifier = classifier
69    
70            self.currentSelection = []
71    
72          EVT_GRID_CELL_LEFT_DCLICK(self, self._OnCellDClick)          EVT_GRID_CELL_LEFT_DCLICK(self, self._OnCellDClick)
73          EVT_GRID_RANGE_SELECT(self, self._OnSelectedRange)          EVT_GRID_RANGE_SELECT(self, self._OnSelectedRange)
74          EVT_GRID_SELECT_CELL(self, self._OnSelectedCell)          EVT_GRID_SELECT_CELL(self, self._OnSelectedCell)
75            EVT_GRID_COL_SIZE(self, self._OnCellResize)
76            EVT_GRID_ROW_SIZE(self, self._OnCellResize)
77    
78          self.currentSelection = []      #def GetCellAttr(self, row, col):
79            #print "GetCellAttr ", row, col
80            #wxGrid.GetCellAttr(self, row, col)
81    
82      def CreateTable(self, clazz, shapeType):      def CreateTable(self, clazz, shapeType, group = None):
83    
84          assert(isinstance(clazz, Classification))          assert isinstance(clazz, Classification)
85    
         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() * NUM_COLS \
89          else:                  + self.GetDefaultRowLabelSize()
90              table.Reset(clazz, self.shapeType)              h = self.GetDefaultRowSize() * 4 \
91                    + self.GetDefaultColLabelSize()
92    
93                self.SetDimensions(-1, -1, w, h)
94                self.SetSizeHints(w, h, -1, -1)
95                table = ClassTable(self)
96                self.SetTable(table, True)
97    
98    
99          self.SetSelectionMode(wxGrid.wxGridSelectRows)          self.SetSelectionMode(wxGrid.wxGridSelectRows)
100          self.ClearSelection()          self.ClearSelection()
101    
102            table.Reset(clazz, shapeType, group)
103    
104      def GetCurrentSelection(self):      def GetCurrentSelection(self):
105          """Return the currently highlighted rows as an increasing list          """Return the currently highlighted rows as an increasing list
106             of row numbers."""             of row numbers."""
# Line 99  class ClassGrid(wxGrid): Line 108  class ClassGrid(wxGrid):
108          sel.sort()          sel.sort()
109          return sel          return sel
110    
111      def SetCellRenderer(self, row, col):      def GetSelectedRows(self):
112          raise ValueError(_("Must not allow setting of renderer in ClassGrid!"))          return self.GetCurrentSelection()
113    
114        #def SetCellRenderer(self, row, col, renderer):
115            #raise ValueError(_("Must not allow setting of renderer in ClassGrid!"))
116    
117      #      #
118      # [Set|Get]Table is taken from http://wiki.wxpython.org      # [Set|Get]Table is taken from http://wiki.wxpython.org
# Line 165  class ClassGrid(wxGrid): Line 177  class ClassGrid(wxGrid):
177                  r = self.GetNumberRows() - 1                  r = self.GetNumberRows() - 1
178              self.SelectRow(r)              self.SelectRow(r)
179                    
180    
181        def SelectGroup(self, group, makeVisible = True):
182            if group is None: return
183    
184            assert isinstance(group, ClassGroup)
185    
186            table = self.GetTable()
187    
188            assert table is not None
189    
190            for i in range(table.GetNumberRows()):
191                g = table.GetClassGroup(i)
192                if g is group:
193                    self.SelectRow(i)
194                    if makeVisible:
195                        self.MakeCellVisible(i, 0)
196                    break
197    
198  #  #
199  # XXX: This isn't working, and there is no way to deselect rows wxPython!  # XXX: This isn't working, and there is no way to deselect rows wxPython!
200  #  #
# Line 177  class ClassGrid(wxGrid): Line 207  class ClassGrid(wxGrid):
207  #                                  sel = False))  #                                  sel = False))
208    
209      def _OnCellDClick(self, event):      def _OnCellDClick(self, event):
210          """Handle a double on a cell."""          """Handle a double click on a cell."""
211    
212          r = event.GetRow()          r = event.GetRow()
213          c = event.GetCol()          c = event.GetCol()
         if c == COL_SYMBOL:  
             prop = self.GetTable().GetValueAsCustom(r, c, None)  
             #prop = group.GetProperties()  
214    
215              # get a new ClassGroupProperties object and copy the          if c == COL_SYMBOL:
216              # values over to our current object              self.classifier.EditSymbol(r)
217              propDlg = SelectPropertiesDialog(NULL, prop, self.shapeType)          else:
218              if propDlg.ShowModal() == wxID_OK:              event.Skip()
                 new_prop = propDlg.GetClassGroupProperties()  
                 #prop.SetProperties(new_prop)  
                 self.GetTable().SetValueAsCustom(r, c, None, new_prop)  
             propDlg.Destroy()  
219    
220      #      #
221      # _OnSelectedRange() and _OnSelectedCell() were borrowed      # _OnSelectedRange() and _OnSelectedCell() were borrowed
# Line 219  class ClassGrid(wxGrid): Line 242  class ClassGrid(wxGrid):
242          #self.ConfigureForSelection()          #self.ConfigureForSelection()
243          event.Skip()          event.Skip()
244    
245        def _OnCellResize(self, event):
246            self.FitInside()
247    
248  class ClassTable(wxPyGridTableBase):  class ClassTable(wxPyGridTableBase):
249      """Represents the underlying data structure for the grid."""      """Represents the underlying data structure for the grid."""
250    
251      NUM_COLS = 3      __col_labels = [_("Visible"), _("Symbol"), _("Value"), _("Label")]
252    
     __col_labels = [_("Symbol"), _("Value"), _("Label")]  
253    
254      def __init__(self, clazz, shapeType, view = None):      def __init__(self, view = None):
255        #def __init__(self, clazz, shapeType, view = None):
256          """Constructor.          """Constructor.
257    
258          shapeType -- the type of shape that the layer uses          shapeType -- the type of shape that the layer uses
# Line 236  class ClassTable(wxPyGridTableBase): Line 262  class ClassTable(wxPyGridTableBase):
262    
263          wxPyGridTableBase.__init__(self)          wxPyGridTableBase.__init__(self)
264    
265          self.SetView(view)          assert len(ClassTable.__col_labels) == NUM_COLS
         self.tdata = []  
266    
267          self.Reset(clazz, shapeType)          self.clazz = None
268            self.__colAttr = {}
269    
270      def Reset(self, clazz, shapeType):          self.SetView(view)
271    
272        def Reset(self, clazz, shapeType, group = None):
273          """Reset the table with the given data.          """Reset the table with the given data.
274    
275          This is necessary because wxWindows does not allow a grid's          This is necessary because wxWindows does not allow a grid's
# Line 255  class ClassTable(wxPyGridTableBase): Line 283  class ClassTable(wxPyGridTableBase):
283          shapeType -- the type of shape that the layer uses          shapeType -- the type of shape that the layer uses
284          """          """
285    
286          assert(isinstance(clazz, Classification))          assert isinstance(clazz, Classification)
287    
288          self.GetView().BeginBatch()          self.GetView().BeginBatch()
289    
290          self.fieldType = clazz.GetFieldType()          self.fieldType = clazz.GetFieldType()
291          self.shapeType = shapeType          self.shapeType = shapeType
292    
293          old_len = len(self.tdata)          self.SetClassification(clazz, group)
294            self.__Modified(-1)
295    
296            self.__colAttr = {}
297    
298            attr = wxGridCellAttr()
299            attr.SetEditor(wxGridCellBoolEditor())
300            attr.SetRenderer(wxGridCellBoolRenderer())
301            attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER)
302            self.__colAttr[COL_VISIBLE] = attr
303    
304            attr = wxGridCellAttr()
305            attr.SetRenderer(ClassRenderer(self.shapeType))
306            attr.SetReadOnly()
307            self.__colAttr[COL_SYMBOL] = attr
308    
309            self.GetView().EndBatch()
310            self.GetView().FitInside()
311    
312        def GetClassification(self):
313            return self.clazz
314    
315          self.tdata = []      def SetClassification(self, clazz, group = None):
316    
317            self.GetView().BeginBatch()
318    
319            old_len = self.GetNumberRows()
320    
321            row = -1
322            self.clazz = clazz
323    
324            self.__NotifyRowChanges(old_len, self.GetNumberRows())
325    
326          #          #
327          # copy the data out of the classification and into our          # XXX: this is dead code at the moment
         # array  
328          #          #
329          for p in clazz:          if row > -1:
330              np = copy.deepcopy(p)              self.GetView().ClearSelection()
331              self.__SetRow(-1, np)              self.GetView().SelectRow(row)
332                self.GetView().MakeCellVisible(row, 0)
333    
334            self.__Modified()
         self.__Modified(-1)  
335    
         self.__NotifyRowChanges(old_len, len(self.tdata))  
336    
         view = self.GetView()  
         w = view.GetDefaultColSize() * 3 + view.GetDefaultRowLabelSize()  
         h = view.GetDefaultRowSize() * 4 + view.GetDefaultColLabelSize()  
         view.SetDimensions(-1, -1, w, h)  
         view.SetSizeHints(w, h, -1, -1)  
               
337          self.GetView().EndBatch()          self.GetView().EndBatch()
338            self.GetView().FitInside()
339    
340      def __NotifyRowChanges(self, curRows, newRows):      def __NotifyRowChanges(self, curRows, newRows):
341          #          #
# Line 297  class ClassTable(wxPyGridTableBase): Line 347  class ClassTable(wxPyGridTableBase):
347                          wxGRIDTABLE_NOTIFY_ROWS_APPENDED,                          wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
348                          newRows - curRows)    # how many                          newRows - curRows)    # how many
349              self.GetView().ProcessTableMessage(msg)              self.GetView().ProcessTableMessage(msg)
350                self.GetView().FitInside()
351          elif newRows < curRows:          elif newRows < curRows:
352              msg = wxGridTableMessage(self,              msg = wxGridTableMessage(self,
353                          wxGRIDTABLE_NOTIFY_ROWS_DELETED,                          wxGRIDTABLE_NOTIFY_ROWS_DELETED,
354                          curRows - newRows,    # position                          curRows,              # position
355                          curRows - newRows)    # how many                          curRows - newRows)    # how many
356              self.GetView().ProcessTableMessage(msg)              self.GetView().ProcessTableMessage(msg)
357                self.GetView().FitInside()
358    
359    
360      def __SetRow(self, row, group):      def __SetRow(self, row, group):
361          """Set a row's data to that of the group.          """Set a row's data to that of the group.
362    
363          The table is considered modified after this operation.          The table is considered modified after this operation.
364    
365          row -- if row is -1 or greater than the current number of rows          row -- if row is < 0 'group' is inserted at the top of the table
366                 then group is appended to the end.                 if row is >= GetNumberRows() or None 'group' is append to
367                        the end of the table.
368                   otherwise 'group' replaces row 'row'
369          """          """
370    
371          # either append or replace          # either append or replace
372          if row == -1 or row >= self.GetNumberRows():          if row is None or row >= self.GetNumberRows():
373              self.tdata.append(group)              self.clazz.AppendGroup(group)
374            elif row < 0:
375                self.clazz.InsertGroup(0, group)
376          else:          else:
377              self.tdata[row] = group              if row == 0:
378                    self.clazz.SetDefaultGroup(group)
379                else:
380                    self.clazz.ReplaceGroup(row - 1, group)
381    
382          self.__Modified()          self.__Modified()
383    
# Line 328  class ClassTable(wxPyGridTableBase): Line 388  class ClassTable(wxPyGridTableBase):
388      def GetRowLabelValue(self, row):      def GetRowLabelValue(self, row):
389          """Return the label for the given row."""          """Return the label for the given row."""
390    
391          group = self.tdata[row]          if row == 0:
392          if isinstance(group, ClassGroupDefault):   return _("Default")              return _("Default")
393          if isinstance(group, ClassGroupSingleton): return _("Singleton")          else:
394          if isinstance(group, ClassGroupRange):     return _("Range")              group = self.clazz.GetGroup(row - 1)
395          if isinstance(group, ClassGroupMap):       return _("Map")              if isinstance(group, ClassGroupDefault):   return _("Default")
396                if isinstance(group, ClassGroupSingleton): return _("Singleton")
397                if isinstance(group, ClassGroupRange):     return _("Range")
398                if isinstance(group, ClassGroupMap):       return _("Map")
399    
400          assert(False) # shouldn't get here          assert False # shouldn't get here
401          return _("")          return ""
402    
403      def GetNumberRows(self):      def GetNumberRows(self):
404          """Return the number of rows."""          """Return the number of rows."""
405          return len(self.tdata)          if self.clazz is None:
406                return 0
407    
408            return self.clazz.GetNumGroups() + 1 # +1 for default group
409    
410      def GetNumberCols(self):      def GetNumberCols(self):
411          """Return the number of columns."""          """Return the number of columns."""
412          return self.NUM_COLS          return NUM_COLS
413    
414      def IsEmptyCell(self, row, col):      def IsEmptyCell(self, row, col):
415          """Determine if a cell is empty. This is always false."""          """Determine if a cell is empty. This is always false."""
# Line 361  class ClassTable(wxPyGridTableBase): Line 427  class ClassTable(wxPyGridTableBase):
427          """          """
428    
429          self.SetValueAsCustom(row, col, None, value)          self.SetValueAsCustom(row, col, None, value)
         self.__Modified()  
430                
431      def GetValueAsCustom(self, row, col, typeName):      def GetValueAsCustom(self, row, col, typeName):
432          """Return the object that is used to represent the given          """Return the object that is used to represent the given
# Line 370  class ClassTable(wxPyGridTableBase): Line 435  class ClassTable(wxPyGridTableBase):
435          typeName -- unused, but needed to overload wxPyGridTableBase          typeName -- unused, but needed to overload wxPyGridTableBase
436          """          """
437    
438          group = self.tdata[row]          if row == 0:
439                group = self.clazz.GetDefaultGroup()
440            else:
441                group = self.clazz.GetGroup(row - 1)
442    
443    
444            if col == COL_VISIBLE:
445                return group.IsVisible()
446    
447          if col == COL_SYMBOL:          if col == COL_SYMBOL:
448              return group.GetProperties()              return group.GetProperties()
# Line 379  class ClassTable(wxPyGridTableBase): Line 451  class ClassTable(wxPyGridTableBase):
451              return group.GetLabel()              return group.GetLabel()
452    
453          # col must be COL_VALUE          # col must be COL_VALUE
454          assert(col == COL_VALUE)          assert col == COL_VALUE
455    
456          if isinstance(group, ClassGroupDefault):          if isinstance(group, ClassGroupDefault):
457              return _("DEFAULT")              return _("DEFAULT")
# Line 403  class ClassTable(wxPyGridTableBase): Line 475  class ClassTable(wxPyGridTableBase):
475    
476          if type == FIELDTYPE_STRING:          if type == FIELDTYPE_STRING:
477              return (value,)              return (value,)
478          elif type == FIELDTYPE_INT or type == FIELDTYPE_DOUBLE:          elif type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
479    
480              if type == FIELDTYPE_INT:              if type == FIELDTYPE_INT:
481                  conv = lambda p: int(float(p))                  conv = lambda p: int(float(p))
# Line 428  class ClassTable(wxPyGridTableBase): Line 500  class ClassTable(wxPyGridTableBase):
500    
501                  return (conv(Str2Num(value[:i])), conv(Str2Num(value[i+1:])))                  return (conv(Str2Num(value[:i])), conv(Str2Num(value[i+1:])))
502    
503          assert(False) # shouldn't get here          assert False  # shouldn't get here
504          return (0,)          return (0,)
505                            
506    
# Line 444  class ClassTable(wxPyGridTableBase): Line 516  class ClassTable(wxPyGridTableBase):
516          typeName -- unused, but needed to overload wxPyGridTableBase          typeName -- unused, but needed to overload wxPyGridTableBase
517          """          """
518    
519          assert(col >= 0 and col < self.GetNumberCols())          assert 0 <= col < self.GetNumberCols()
520          assert(row >= 0 and row < self.GetNumberRows())          assert 0 <= row < self.GetNumberRows()
521    
522          group = self.tdata[row]          if row == 0:
523                group = self.clazz.GetDefaultGroup()
524            else:
525                group = self.clazz.GetGroup(row - 1)
526    
527          mod = True # assume the data will change          mod = True # assume the data will change
528    
529          if col == COL_SYMBOL:          if col == COL_VISIBLE:
530                group.SetVisible(value)
531            elif col == COL_SYMBOL:
532              group.SetProperties(value)              group.SetProperties(value)
533          elif col == COL_LABEL:          elif col == COL_LABEL:
534              group.SetLabel(value)              group.SetLabel(value)
# Line 490  class ClassTable(wxPyGridTableBase): Line 567  class ClassTable(wxPyGridTableBase):
567                              changed = True                              changed = True
568                          ngroup.SetRange(dataInfo[0], dataInfo[1])                          ngroup.SetRange(dataInfo[0], dataInfo[1])
569                      else:                      else:
570                          assert(False)                          assert False
571                          pass                          pass
572    
573                      if changed:                      if changed:
574                          ngroup.SetLabel(group.GetLabel())                          ngroup.SetLabel(group.GetLabel())
575                          self.SetClassGroup(row, ngroup)                          self.SetClassGroup(row, ngroup)
576          else:          else:
577              assert(False) # shouldn't be here              assert False # shouldn't be here
578              pass              pass
579    
580          if mod:          if mod:
# Line 507  class ClassTable(wxPyGridTableBase): Line 584  class ClassTable(wxPyGridTableBase):
584      def GetAttr(self, row, col, someExtraParameter):      def GetAttr(self, row, col, someExtraParameter):
585          """Returns the cell attributes"""          """Returns the cell attributes"""
586    
587          attr = wxGridCellAttr()          return self.__colAttr.get(col, wxGridCellAttr()).Clone()
         #attr = wxPyGridTableBase.GetAttr(self, row, col, someExtraParameter)  
   
         if col == COL_SYMBOL:  
             # we need to create a new renderer each time, because  
             # SetRenderer takes control of the parameter  
             attr.SetRenderer(ClassRenderer(self.shapeType))  
             attr.SetReadOnly()  
   
         return attr  
588    
589      def GetClassGroup(self, row):      def GetClassGroup(self, row):
590          """Return the ClassGroup object representing row 'row'."""          """Return the ClassGroup object representing row 'row'."""
591    
592          return self.tdata[row] # self.GetValueAsCustom(row, COL_SYMBOL, None)          #return self.GetValueAsCustom(row, COL_SYMBOL, None)
593            if row == 0:
594                return self.clazz.GetDefaultGroup()
595            else:
596                return self.clazz.GetGroup(row - 1)
597    
598      def SetClassGroup(self, row, group):      def SetClassGroup(self, row, group):
599          self.__SetRow(row, group)          self.__SetRow(row, group)
# Line 552  class ClassTable(wxPyGridTableBase): Line 624  class ClassTable(wxPyGridTableBase):
624          The table is considered modified if any rows are removed.          The table is considered modified if any rows are removed.
625          """          """
626    
627          assert(pos >= 0)          assert pos >= 0
628          old_len = len(self.tdata)          old_len = self.GetNumberRows()
629          for row in range(pos, pos - numRows, -1):          for row in range(pos, pos - numRows, -1):
630              group = self.GetClassGroup(row)              group = self.GetClassGroup(row)
631              if not isinstance(group, ClassGroupDefault):              if row != 0:
632                  self.tdata.pop(row)                  self.clazz.RemoveGroup(row - 1)
633                  self.__Modified()                  self.__Modified()
634            
635          if self.IsModified():          if self.IsModified():
636              self.__NotifyRowChanges(old_len, len(self.tdata))              self.__NotifyRowChanges(old_len, self.GetNumberRows())
637    
638      def AppendRows(self, numRows = 1):      def AppendRows(self, numRows = 1):
639          """Append 'numRows' empty rows to the end of the table.          """Append 'numRows' empty rows to the end of the table.
# Line 569  class ClassTable(wxPyGridTableBase): Line 641  class ClassTable(wxPyGridTableBase):
641          The table is considered modified if any rows are appended.          The table is considered modified if any rows are appended.
642          """          """
643    
644          old_len = len(self.tdata)          old_len = self.GetNumberRows()
645          for i in range(numRows):          for i in range(numRows):
646              np = ClassGroupSingleton()              np = ClassGroupSingleton()
647              self.__SetRow(-1, np)              self.__SetRow(None, np)
648    
649          if self.IsModified():          if self.IsModified():
650              self.__NotifyRowChanges(old_len, len(self.tdata))              self.__NotifyRowChanges(old_len, self.GetNumberRows())
651    
652    
653    ID_PROPERTY_OK = 4001
654    ID_PROPERTY_REVERT = 4002
655    ID_PROPERTY_ADD = 4003
656    ID_PROPERTY_GENCLASS = 4004
657    ID_PROPERTY_REMOVE = 4005
658    ID_PROPERTY_MOVEUP = 4006
659    ID_PROPERTY_MOVEDOWN = 4007
660    ID_PROPERTY_TRY = 4008
661    ID_PROPERTY_EDITSYM = 4009
662    ID_PROPERTY_CLOSE = 4010
663    ID_PROPERTY_SELECT = 4011
664    ID_PROPERTY_TITLE = 4012
665    ID_PROPERTY_FIELDTEXT = 4013
666    
667    BTN_ADD = 0
668    BTN_EDIT = 1
669    BTN_GEN = 2
670    BTN_UP = 3
671    BTN_DOWN = 4
672    BTN_RM = 5
673    
674    EB_LAYER_TITLE = 0
675    EB_SELECT_FIELD = 1
676    EB_GEN_CLASS = 2
677    
678  class Classifier(NonModalDialog):  class Classifier(NonModalDialog):
679        
680      def __init__(self, parent, interactor, name, layer):      type2string = {None:             _("None"),
681          NonModalDialog.__init__(self, parent, interactor, name,                     FIELDTYPE_STRING: _("Text"),
682                                  _("Classifier: %s") % layer.Title())                     FIELDTYPE_INT:    _("Integer"),
683                       FIELDTYPE_DOUBLE: _("Decimal")}
684    
685        def __init__(self, parent, name, layer, group = None):
686            NonModalDialog.__init__(self, parent, name, "")
687    
688            self.__SetTitle(layer.Title())
689    
690          self.layer = layer          self.layer = layer
691    
# Line 590  class Classifier(NonModalDialog): Line 693  class Classifier(NonModalDialog):
693          field = self.originalClass.GetField()          field = self.originalClass.GetField()
694          fieldType = self.originalClass.GetFieldType()          fieldType = self.originalClass.GetFieldType()
695    
696            self.genDlg = None
697    
698          topBox = wxBoxSizer(wxVERTICAL)          topBox = wxBoxSizer(wxVERTICAL)
699    
700          #topBox.Add(wxStaticText(self, -1, _("Layer: %s") % layer.Title()),          panel = wxPanel(self, -1, size=(100, 100))
701              #0, wxALIGN_LEFT | wxALL, 4)  
702          topBox.Add(wxStaticText(self, -1,          panelBox = wxBoxSizer(wxVERTICAL)
703                                  _("Layer Type: %s") % layer.ShapeType()),  
704            sizer = wxBoxSizer(wxHORIZONTAL)
705            sizer.Add(wxStaticText(panel, -1, _("Title: ")),
706                0, wxALIGN_LEFT | wxALL | wxALIGN_CENTER_VERTICAL, 4)
707            sizer.Add(wxTextCtrl(panel, ID_PROPERTY_TITLE, layer.Title()),
708                      1, wxGROW | wxALL, 4)
709            EVT_TEXT(self, ID_PROPERTY_TITLE, self._OnTitleChanged)
710    
711            panelBox.Add(sizer, 0, wxGROW, 4)
712    
713            panelBox.Add(wxStaticText(panel, -1,
714                                    _("Type: %s") % layer.ShapeType()),
715              0, wxALIGN_LEFT | wxALL, 4)              0, wxALIGN_LEFT | wxALL, 4)
716    
717    
718            #####################
719    
720            #panelBox = wxBoxSizer(wxVERTICAL)
721            classBox = wxStaticBoxSizer(
722                        wxStaticBox(panel, -1, _("Classification")), wxVERTICAL)
723    
724    
725          #          #
726          # make field combo box          # make field combo box
727          #          #
728          self.fields = wxComboBox(self, ID_PROPERTY_SELECT, "",          self.fields = wxComboBox(panel, ID_PROPERTY_SELECT, "",
729                                       style = wxCB_READONLY)                                       style = wxCB_READONLY)
730    
731          self.num_cols = layer.table.field_count()          self.num_cols = layer.table.field_count()
# Line 611  class Classifier(NonModalDialog): Line 734  class Classifier(NonModalDialog):
734          self.__cur_field = 0          self.__cur_field = 0
735    
736          self.fields.Append("<None>")          self.fields.Append("<None>")
737          self.fields.SetClientData(0, None)  
738            if self.originalClass.GetFieldType() is None:
739                self.fields.SetClientData(0, copy.deepcopy(self.originalClass))
740            else:
741                self.fields.SetClientData(0, None)
742    
743          for i in range(self.num_cols):          for i in range(self.num_cols):
744              type, name, len, decc = layer.table.field_info(i)              type, name, len, decc = layer.table.field_info(i)
# Line 619  class Classifier(NonModalDialog): Line 746  class Classifier(NonModalDialog):
746    
747              if name == field:              if name == field:
748                  self.__cur_field = i + 1                  self.__cur_field = i + 1
749                  self.fields.SetClientData(i + 1, self.originalClass)                  self.fields.SetClientData(i + 1,
750                                              copy.deepcopy(self.originalClass))
751              else:              else:
752                  self.fields.SetClientData(i + 1, None)                  self.fields.SetClientData(i + 1, None)
753    
754    
755          #          ###########
         #  
         #  
756    
         self.fieldTypeText = wxStaticText(self, -1, "")  
         self.__SetFieldTypeText(self.__cur_field)  
757    
758          topBox.Add(self.fieldTypeText, 0, wxALIGN_LEFT | wxALL, 4)          sizer = wxBoxSizer(wxHORIZONTAL)
759          #self.fieldTypeText.SetLabel("asdfadsfs")          sizer.Add(wxStaticText(panel, ID_PROPERTY_FIELDTEXT, _("Field: ")),
760                0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 4)
761          propertyBox = wxBoxSizer(wxHORIZONTAL)          sizer.Add(self.fields, 1, wxGROW | wxALL, 4)
         propertyBox.Add(wxStaticText(self, -1, _("Field: ")),  
             0, wxALIGN_CENTER | wxALL, 4)  
         propertyBox.Add(self.fields, 1, wxGROW|wxALL, 4)  
762          EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self._OnFieldSelect)          EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self._OnFieldSelect)
763    
764          topBox.Add(propertyBox, 0, wxGROW, 4)          classBox.Add(sizer, 0, wxGROW, 4)
765    
766            self.fieldTypeText = wxStaticText(panel, -1, "")
767            classBox.Add(self.fieldTypeText, 0,
768                         wxGROW | wxALIGN_LEFT | wxALL | wxADJUST_MINSIZE, 4)
769    
770    
771          #          #
772          # Classification data table          # Control Box
773          #          #
   
774          controlBox = wxBoxSizer(wxHORIZONTAL)          controlBox = wxBoxSizer(wxHORIZONTAL)
775    
         self.classGrid = ClassGrid(self)  
         self.__SetGridTable(self.__cur_field)  
   
         controlBox.Add(self.classGrid, 1, wxGROW, 0)  
   
         controlButtonBox = wxBoxSizer(wxVERTICAL)  
776    
777            ###########
778          #          #
779          # Control buttons:          # Control buttons:
780          #          #
781          self.controlButtons = []          controlButtonBox = wxBoxSizer(wxVERTICAL)
782    
783          button = wxButton(self, ID_CLASSIFY_ADD, _("Add"))          button = wxButton(panel, ID_PROPERTY_GENCLASS, _("Generate Class"))
784          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
         self.controlButtons.append(button)  
785    
786          #button = wxButton(self, ID_CLASSIFY_GENRANGE, _("Generate Ranges"))          button = wxButton(panel, ID_PROPERTY_ADD, _("Add"))
787          #controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
         #self.controlButtons.append(button)  
788    
789          button = wxButton(self, ID_CLASSIFY_MOVEUP, _("Move Up"))          button = wxButton(panel, ID_PROPERTY_MOVEUP, _("Move Up"))
790          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
         self.controlButtons.append(button)  
791    
792          button = wxButton(self, ID_CLASSIFY_MOVEDOWN, _("Move Down"))          button = wxButton(panel, ID_PROPERTY_MOVEDOWN, _("Move Down"))
793            controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
794    
795            button = wxButton(panel, ID_PROPERTY_EDITSYM, _("Edit Symbol"))
796          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)          controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
         self.controlButtons.append(button)  
797    
798          controlButtonBox.Add(60, 20, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)          controlButtonBox.Add(60, 20, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
799    
800          button = wxButton(self, ID_CLASSIFY_REMOVE, _("Remove"))          button = wxButton(panel, ID_PROPERTY_REMOVE, _("Remove"))
801          controlButtonBox.Add(button, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)          controlButtonBox.Add(button, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
         self.controlButtons.append(button)  
802    
803    
804            ###########
805            #
806            # Classification data table
807            #
808    
809            self.classGrid = ClassGrid(panel, self)
810    
811            # calling __SelectField after creating the classGrid fills in the
812            # grid with the correct information
813            self.fields.SetSelection(self.__cur_field)
814            self.__SelectField(self.__cur_field, group = group)
815    
816            controlBox.Add(self.classGrid, 1, wxGROW, 0)
817          controlBox.Add(controlButtonBox, 0, wxGROW, 10)          controlBox.Add(controlButtonBox, 0, wxGROW, 10)
         topBox.Add(controlBox, 1, wxGROW, 10)  
818    
819          EVT_BUTTON(self, ID_CLASSIFY_ADD, self._OnAdd)          classBox.Add(controlBox, 1, wxGROW, 10)
820          EVT_BUTTON(self, ID_CLASSIFY_REMOVE, self._OnRemove)          panelBox.Add(classBox, 1, wxGROW, 0)
821          EVT_BUTTON(self, ID_CLASSIFY_GENRANGE, self._OnGenRange)  
822          EVT_BUTTON(self, ID_CLASSIFY_MOVEUP, self._OnMoveUp)          EVT_BUTTON(self, ID_PROPERTY_ADD, self._OnAdd)
823          EVT_BUTTON(self, ID_CLASSIFY_MOVEDOWN, self._OnMoveDown)          EVT_BUTTON(self, ID_PROPERTY_EDITSYM, self._OnEditSymbol)
824            EVT_BUTTON(self, ID_PROPERTY_REMOVE, self._OnRemove)
825            EVT_BUTTON(self, ID_PROPERTY_GENCLASS, self._OnGenClass)
826            EVT_BUTTON(self, ID_PROPERTY_MOVEUP, self._OnMoveUp)
827            EVT_BUTTON(self, ID_PROPERTY_MOVEDOWN, self._OnMoveDown)
828    
829            ###########
830    
831    
832            panel.SetAutoLayout(True)
833            panel.SetSizer(panelBox)
834            panelBox.SetSizeHints(panel)
835    
836            topBox.Add(panel, 1, wxGROW | wxALL, 4)
837    
838            ###########
839    
840          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
841          buttonBox.Add(wxButton(self, ID_CLASSIFY_OK, _("OK")),          buttonBox.Add(wxButton(self, ID_PROPERTY_TRY, _("Try")),
842                        0, wxALL, 4)                        0, wxALL, 4)
843          buttonBox.Add(60, 20, 0, wxALL, 4)          buttonBox.Add(60, 20, 0, wxALL, 4)
844          buttonBox.Add(wxButton(self, ID_CLASSIFY_APPLY, _("Apply")),          buttonBox.Add(wxButton(self, ID_PROPERTY_REVERT, _("Revert")),
845                        0, wxALL, 4)                        0, wxALL, 4)
846          buttonBox.Add(60, 20, 0, wxALL, 4)          buttonBox.Add(60, 20, 0, wxALL, 4)
847          buttonBox.Add(wxButton(self, ID_CLASSIFY_CANCEL, _("Cancel")),          buttonBox.Add(wxButton(self, ID_PROPERTY_OK, _("OK")),
848                        0, wxALL, 4)                        0, wxALL, 4)
849          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)          buttonBox.Add(60, 20, 0, wxALL, 4)
850            buttonBox.Add(wxButton(self, ID_PROPERTY_CLOSE, _("Close")),
851                          0, wxALL, 4)
852            topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 0)
853    
854          EVT_BUTTON(self, ID_CLASSIFY_OK, self._OnOK)          EVT_BUTTON(self, ID_PROPERTY_OK, self._OnOK)
855          EVT_BUTTON(self, ID_CLASSIFY_APPLY, self._OnApply)          EVT_BUTTON(self, ID_PROPERTY_TRY, self._OnTry)
856          EVT_BUTTON(self, ID_CLASSIFY_CANCEL, self._OnCancel)          EVT_BUTTON(self, ID_PROPERTY_CLOSE, self._OnCloseBtn)
857            EVT_BUTTON(self, ID_PROPERTY_REVERT, self._OnRevert)
858    
859          self.fields.SetSelection(self.__cur_field)          ###########
         self.__SelectField(self.__cur_field)  
860    
861          self.SetAutoLayout(true)          topBox.SetSizeHints(self)
862            self.SetAutoLayout(True)
863          self.SetSizer(topBox)          self.SetSizer(topBox)
         topBox.Fit(self)  
         topBox.SetSizeHints(self)  
864    
865            #self.Fit()
866            ######################
867    
868            self.haveApplied = False
869    
870        def EditSymbol(self, row):
871            table = self.classGrid.GetTable()
872            prop = table.GetValueAsCustom(row, COL_SYMBOL, None)
873    
874            # get a new ClassGroupProperties object and copy the
875            # values over to our current object
876            propDlg = SelectPropertiesDialog(NULL, prop, self.layer.ShapeType())
877    
878            self.Enable(False)
879            if propDlg.ShowModal() == wxID_OK:
880                new_prop = propDlg.GetClassGroupProperties()
881                table.SetValueAsCustom(row, COL_SYMBOL, None, new_prop)
882            self.Enable(True)
883            propDlg.Destroy()
884            
885        def _SetClassification(self, clazz):
886            
887            self.fields.SetClientData(self.__cur_field, clazz)
888            self.classGrid.GetTable().SetClassification(clazz)
889    
890      def __BuildClassification(self, fieldIndex):      def __BuildClassification(self, fieldIndex, copyClass = False):
891    
892          numRows = self.classGrid.GetNumberRows()  #       numRows = self.classGrid.GetNumberRows()
893          assert(numRows > 0) # there should always be a default row  #       assert numRows > 0  # there should always be a default row
894    
895          clazz = Classification()  #       clazz = Classification()
896          if fieldIndex == 0:          if fieldIndex == 0:
897              fieldName = None              fieldName = None
898              fieldType = None              fieldType = None
# Line 728  class Classifier(NonModalDialog): Line 900  class Classifier(NonModalDialog):
900              fieldName = self.fields.GetString(fieldIndex)              fieldName = self.fields.GetString(fieldIndex)
901              fieldType = self.layer.GetFieldType(fieldName)              fieldType = self.layer.GetFieldType(fieldName)
902    
903            clazz = self.classGrid.GetTable().GetClassification()
904    
905            if copyClass:
906                clazz = copy.deepcopy(clazz)
907    
908          clazz.SetField(fieldName)          clazz.SetField(fieldName)
909          clazz.SetFieldType(fieldType)          clazz.SetFieldType(fieldType)
910    
911    
912          table = self.classGrid.GetTable()  #       table = self.classGrid.GetTable()
913          clazz.SetDefaultGroup(table.GetClassGroup(0))  #       clazz.SetDefaultGroup(table.GetClassGroup(0))
914    
915          for i in range(1, numRows):  #       for i in range(1, numRows):
916              clazz.AddGroup(table.GetClassGroup(i))  #           clazz.AppendGroup(table.GetClassGroup(i))
917    
918          return clazz          return clazz
919    
920      def __SetGridTable(self, fieldIndex):      def __SetGridTable(self, fieldIndex, group = None):
921    
922          clazz = self.fields.GetClientData(fieldIndex)          clazz = self.fields.GetClientData(fieldIndex)
923    
# Line 755  class Classifier(NonModalDialog): Line 932  class Classifier(NonModalDialog):
932              fieldType = self.layer.GetFieldType(fieldName)              fieldType = self.layer.GetFieldType(fieldName)
933              clazz.SetFieldType(fieldType)              clazz.SetFieldType(fieldType)
934                                    
935          self.classGrid.CreateTable(clazz, self.layer.ShapeType())          self.classGrid.CreateTable(clazz, self.layer.ShapeType(), group)
   
   
   
     type2string = {None:             "None",  
                    FIELDTYPE_STRING: "Text",  
                    FIELDTYPE_INT:    "Integer",  
                    FIELDTYPE_DOUBLE: "Decimal"}  
936    
937      def __SetFieldTypeText(self, fieldIndex):      def __SetFieldTypeText(self, fieldIndex):
938          fieldName = self.fields.GetString(fieldIndex)          fieldName = self.fields.GetString(fieldIndex)
939          fieldType = self.layer.GetFieldType(fieldName)          fieldType = self.layer.GetFieldType(fieldName)
940    
941          assert(Classifier.type2string.has_key(fieldType))          assert Classifier.type2string.has_key(fieldType)
942    
943          text = Classifier.type2string[fieldType]          text = Classifier.type2string[fieldType]
944    
945          self.fieldTypeText.SetLabel(_("Field Type: %s") % text)          self.fieldTypeText.SetLabel(_("Data Type: %s") % text)
946    
947        def __SelectField(self, newIndex, oldIndex = -1, group = None):
948            """This method assumes that the current selection for the
949            combo has already been set by a call to SetSelection().
950            """
951    
952            assert oldIndex >= -1
953    
954      def __SelectField(self, fieldIndex):          if oldIndex != -1:
955          clazz = self.__BuildClassification(fieldIndex)              clazz = self.__BuildClassification(oldIndex)
956          self.fields.SetClientData(fieldIndex, clazz)              self.fields.SetClientData(oldIndex, clazz)
957    
958          self.__cur_field = self.fields.GetSelection()          self.__SetGridTable(newIndex, group)
         self.__SetGridTable(fieldIndex)  
959    
960          enabled = fieldIndex != 0          self.__EnableButtons(EB_SELECT_FIELD, newIndex != 0)
961    
962          for b in self.controlButtons:          self.__SetFieldTypeText(newIndex)
             b.Enable(enabled)  
963    
964          self.__SetFieldTypeText(fieldIndex)      def __SetTitle(self, title):
965            if title != "":
966                title = ": " + title
967    
968            self.SetTitle(_("Layer Properties") + title)
969    
970        def _OnEditSymbol(self, event):
971            sel = self.classGrid.GetCurrentSelection()
972    
973            if len(sel) == 1:
974                self.EditSymbol(sel[0])
975    
976      def _OnFieldSelect(self, event):      def _OnFieldSelect(self, event):
977          self.__SelectField(self.__cur_field)          index = self.fields.GetSelection()
978            self.__SelectField(index, self.__cur_field)
979            self.__cur_field = index
980    
981      def _OnApply(self, event):      def _OnTry(self, event):
982          """Put the data from the table into a new Classification and hand          """Put the data from the table into a new Classification and hand
983             it to the layer.             it to the layer.
984          """          """
# Line 804  class Classifier(NonModalDialog): Line 990  class Classifier(NonModalDialog):
990          # to begin with or it has been modified          # to begin with or it has been modified
991          #          #
992          if clazz is None or self.classGrid.GetTable().IsModified():          if clazz is None or self.classGrid.GetTable().IsModified():
993              clazz = self.__BuildClassification(self.__cur_field)              clazz = self.__BuildClassification(self.__cur_field, True)
994    
995          self.layer.SetClassification(clazz)          self.layer.SetClassification(clazz)
996    
997            self.haveApplied = True
998    
999      def _OnOK(self, event):      def _OnOK(self, event):
1000          self._OnApply(event)          self._OnTry(event)
1001          self.OnClose(event)          self.Close()
1002    
1003      def _OnCancel(self, event):      def _OnCloseBtn(self, event):
1004            """Close is similar to Cancel except that any changes that were
1005            made and applied remain applied, but the currently displayed
1006            classification is discarded.
1007            """
1008    
1009            self.Close()
1010    
1011        def _OnRevert(self, event):
1012          """The layer's current classification stays the same."""          """The layer's current classification stays the same."""
1013          self.layer.SetClassification(self.originalClass)          if self.haveApplied:
1014          self.OnClose(event)              self.layer.SetClassification(self.originalClass)
1015    
1016            #self.Close()
1017    
1018      def _OnAdd(self, event):      def _OnAdd(self, event):
1019          self.classGrid.AppendRows()          self.classGrid.AppendRows()
# Line 823  class Classifier(NonModalDialog): Line 1021  class Classifier(NonModalDialog):
1021      def _OnRemove(self, event):      def _OnRemove(self, event):
1022          self.classGrid.DeleteSelectedRows()          self.classGrid.DeleteSelectedRows()
1023    
1024      def _OnGenRange(self, event):      def _OnGenClass(self, event):
1025          print "Classifier._OnGenRange()"  
1026            self.genDlg = ClassGenDialog(self, self.layer,
1027                              self.fields.GetString(self.__cur_field))
1028    
1029            EVT_CLOSE(self.genDlg, self._OnGenDialogClose)
1030    
1031            self.__EnableButtons(EB_GEN_CLASS, False)
1032    
1033            self.genDlg.Show()
1034    
1035        def _OnGenDialogClose(self, event):
1036            self.genDlg.Destroy()
1037            self.__EnableButtons(EB_GEN_CLASS, True)
1038    
1039      def _OnMoveUp(self, event):      def _OnMoveUp(self, event):
1040          sel = self.classGrid.GetCurrentSelection()          sel = self.classGrid.GetCurrentSelection()
# Line 839  class Classifier(NonModalDialog): Line 1049  class Classifier(NonModalDialog):
1049                  table.SetClassGroup(i, x)                  table.SetClassGroup(i, x)
1050                  self.classGrid.ClearSelection()                  self.classGrid.ClearSelection()
1051                  self.classGrid.SelectRow(i - 1)                  self.classGrid.SelectRow(i - 1)
1052                    self.classGrid.MakeCellVisible(i - 1, 0)
1053    
1054      def _OnMoveDown(self, event):      def _OnMoveDown(self, event):
1055          sel = self.classGrid.GetCurrentSelection()          sel = self.classGrid.GetCurrentSelection()
# Line 853  class Classifier(NonModalDialog): Line 1064  class Classifier(NonModalDialog):
1064                  table.SetClassGroup(i + 1, x)                  table.SetClassGroup(i + 1, x)
1065                  self.classGrid.ClearSelection()                  self.classGrid.ClearSelection()
1066                  self.classGrid.SelectRow(i + 1)                  self.classGrid.SelectRow(i + 1)
1067                    self.classGrid.MakeCellVisible(i + 1, 0)
1068    
1069        def _OnTitleChanged(self, event):
1070            obj = event.GetEventObject()
1071    
1072            self.layer.SetTitle(obj.GetValue())
1073            self.__SetTitle(self.layer.Title())
1074    
1075            self.__EnableButtons(EB_LAYER_TITLE, self.layer.Title() != "")
1076    
1077        def __EnableButtons(self, case, enable):
1078    
1079            if case == EB_LAYER_TITLE:  
1080                list = (ID_PROPERTY_OK,
1081                        ID_PROPERTY_CLOSE)
1082    
1083            elif case == EB_SELECT_FIELD:
1084                list = (ID_PROPERTY_GENCLASS,
1085                        ID_PROPERTY_ADD,
1086                        ID_PROPERTY_MOVEUP,
1087                        ID_PROPERTY_MOVEDOWN,
1088                        ID_PROPERTY_EDITSYM,
1089                        ID_PROPERTY_REMOVE)
1090    
1091            elif case == EB_GEN_CLASS:
1092                list = (ID_PROPERTY_SELECT,
1093                        ID_PROPERTY_FIELDTEXT,
1094                        ID_PROPERTY_GENCLASS,
1095                        ID_PROPERTY_EDITSYM)
1096    
1097            for id in list:
1098                self.FindWindowById(id).Enable(enable)
1099    
1100  ID_SELPROP_OK = 4001  ID_SELPROP_OK = 4001
1101  ID_SELPROP_CANCEL = 4002  ID_SELPROP_CANCEL = 4002
# Line 868  class SelectPropertiesDialog(wxDialog): Line 1110  class SelectPropertiesDialog(wxDialog):
1110    
1111      def __init__(self, parent, prop, shapeType):      def __init__(self, parent, prop, shapeType):
1112          wxDialog.__init__(self, parent, -1, _("Select Properties"),          wxDialog.__init__(self, parent, -1, _("Select Properties"),
1113                            style = wxRESIZE_BORDER)                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
1114    
1115          self.prop = ClassGroupProperties(prop)          self.prop = ClassGroupProperties(prop)
1116    
# Line 880  class SelectPropertiesDialog(wxDialog): Line 1122  class SelectPropertiesDialog(wxDialog):
1122          previewBox = wxBoxSizer(wxVERTICAL)          previewBox = wxBoxSizer(wxVERTICAL)
1123          previewBox.Add(wxStaticText(self, -1, _("Preview:")),          previewBox.Add(wxStaticText(self, -1, _("Preview:")),
1124              0, wxALIGN_LEFT | wxALL, 4)              0, wxALIGN_LEFT | wxALL, 4)
1125          self.previewer = ClassDataPreviewer(None, self.prop, shapeType,  
1126                                              self, ID_SELPROP_PREVIEW, (40, 40))          self.previewWin = ClassGroupPropertiesCtrl(
1127          previewBox.Add(self.previewer, 1, wxGROW, 15)              self, ID_SELPROP_PREVIEW, self.prop, shapeType,
1128                (40, 40), wxSIMPLE_BORDER)
1129    
1130            self.previewWin.AllowEdit(False)
1131    
1132            previewBox.Add(self.previewWin, 1, wxGROW | wxALL, 4)
1133    
1134          itemBox.Add(previewBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)          itemBox.Add(previewBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)
1135    
# Line 891  class SelectPropertiesDialog(wxDialog): Line 1138  class SelectPropertiesDialog(wxDialog):
1138    
1139          lineColorBox = wxBoxSizer(wxHORIZONTAL)          lineColorBox = wxBoxSizer(wxHORIZONTAL)
1140          lineColorBox.Add(          lineColorBox.Add(
1141              wxButton(self, ID_SELPROP_STROKECLR, "Change Line Color"),              wxButton(self, ID_SELPROP_STROKECLR, _("Change Line Color")),
1142              1, wxALL | wxGROW, 4)              1, wxALL | wxGROW, 4)
1143          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)
1144    
1145          lineColorBox.Add(          lineColorBox.Add(
1146              wxButton(self, ID_SELPROP_STROKECLRTRANS, "Transparent"),              wxButton(self, ID_SELPROP_STROKECLRTRANS, _("Transparent")),
1147              1, wxALL | wxGROW, 4)              1, wxALL | wxGROW, 4)
1148          EVT_BUTTON(self, ID_SELPROP_STROKECLRTRANS,          EVT_BUTTON(self, ID_SELPROP_STROKECLRTRANS,
1149                     self._OnChangeLineColorTrans)                     self._OnChangeLineColorTrans)
# Line 907  class SelectPropertiesDialog(wxDialog): Line 1154  class SelectPropertiesDialog(wxDialog):
1154          if shapeType != SHAPETYPE_ARC:          if shapeType != SHAPETYPE_ARC:
1155              fillColorBox = wxBoxSizer(wxHORIZONTAL)              fillColorBox = wxBoxSizer(wxHORIZONTAL)
1156              fillColorBox.Add(              fillColorBox.Add(
1157                  wxButton(self, ID_SELPROP_FILLCLR, "Change Fill Color"),                  wxButton(self, ID_SELPROP_FILLCLR, _("Change Fill Color")),
1158                  1, wxALL | wxGROW, 4)                  1, wxALL | wxGROW, 4)
1159              EVT_BUTTON(self, ID_SELPROP_FILLCLR, self._OnChangeFillColor)              EVT_BUTTON(self, ID_SELPROP_FILLCLR, self._OnChangeFillColor)
1160              fillColorBox.Add(              fillColorBox.Add(
1161                  wxButton(self, ID_SELPROP_FILLCLRTRANS, "Transparent"),                  wxButton(self, ID_SELPROP_FILLCLRTRANS, _("Transparent")),
1162                  1, wxALL | wxGROW, 4)                  1, wxALL | wxGROW, 4)
1163              EVT_BUTTON(self, ID_SELPROP_FILLCLRTRANS,              EVT_BUTTON(self, ID_SELPROP_FILLCLRTRANS,
1164                         self._OnChangeFillColorTrans)                         self._OnChangeFillColorTrans)
# Line 947  class SelectPropertiesDialog(wxDialog): Line 1194  class SelectPropertiesDialog(wxDialog):
1194          EVT_BUTTON(self, ID_SELPROP_OK, self._OnOK)          EVT_BUTTON(self, ID_SELPROP_OK, self._OnOK)
1195          EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)          EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)
1196                                                                                                                                                                    
1197          self.SetAutoLayout(true)          self.SetAutoLayout(True)
1198          self.SetSizer(topBox)          self.SetSizer(topBox)
1199          topBox.Fit(self)          topBox.Fit(self)
1200          topBox.SetSizeHints(self)          topBox.SetSizeHints(self)
# Line 960  class SelectPropertiesDialog(wxDialog): Line 1207  class SelectPropertiesDialog(wxDialog):
1207    
1208      def _OnSpin(self, event):      def _OnSpin(self, event):
1209          self.prop.SetLineWidth(self.spinCtrl.GetValue())          self.prop.SetLineWidth(self.spinCtrl.GetValue())
1210          self.previewer.Refresh()          self.previewWin.Refresh()
1211    
1212      def __GetColor(self, cur):      def __GetColor(self, cur):
1213          dialog = wxColourDialog(self)          dialog = wxColourDialog(self)
1214          dialog.GetColourData().SetColour(Color2wxColour(cur))          if cur is not Color.Transparent:
1215                dialog.GetColourData().SetColour(Color2wxColour(cur))
1216    
1217          ret = None          ret = None
1218          if dialog.ShowModal() == wxID_OK:          if dialog.ShowModal() == wxID_OK:
1219              ret = wxColour2Color(dialog.GetColourData().GetColour())              ret = wxColour2Color(dialog.GetColourData().GetColour())
# Line 977  class SelectPropertiesDialog(wxDialog): Line 1226  class SelectPropertiesDialog(wxDialog):
1226          clr = self.__GetColor(self.prop.GetLineColor())          clr = self.__GetColor(self.prop.GetLineColor())
1227          if clr is not None:          if clr is not None:
1228              self.prop.SetLineColor(clr)              self.prop.SetLineColor(clr)
1229          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1230    
1231      def _OnChangeLineColorTrans(self, event):      def _OnChangeLineColorTrans(self, event):
1232          self.prop.SetLineColor(Color.None)          self.prop.SetLineColor(Color.Transparent)
1233          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1234                    
1235      def _OnChangeFillColor(self, event):      def _OnChangeFillColor(self, event):
1236          clr = self.__GetColor(self.prop.GetFill())          clr = self.__GetColor(self.prop.GetFill())
1237          if clr is not None:          if clr is not None:
1238              self.prop.SetFill(clr)              self.prop.SetFill(clr)
1239          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1240    
1241      def _OnChangeFillColorTrans(self, event):      def _OnChangeFillColorTrans(self, event):
1242          self.prop.SetFill(Color.None)          self.prop.SetFill(Color.Transparent)
1243          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1244    
1245      def GetClassGroupProperties(self):      def GetClassGroupProperties(self):
1246          return self.prop          return self.prop
1247    
1248    
1249  class ClassDataPreviewer(wxWindow):  class ClassDataPreviewWindow(wxWindow):
1250    
1251      def __init__(self, rect, prop, shapeType,      def __init__(self, rect, prop, shapeType,
1252                         parent = None, id = -1, size = wxDefaultSize):                         parent = None, id = -1, size = wxDefaultSize):
1253          if parent is not None:          if parent is not None:
1254              wxWindow.__init__(self, parent, id, size=size)              wxWindow.__init__(self, parent, id, (0, 0), size)
1255              EVT_PAINT(self, self._OnPaint)              EVT_PAINT(self, self._OnPaint)
1256    
1257          self.rect = rect          self.rect = rect
1258    
1259          self.prop = prop          self.prop = prop
1260          self.shapeType = shapeType          self.shapeType = shapeType
1261            self.previewer = ClassDataPreviewer()
1262    
1263        def GetProperties():
1264            return self.prop
1265    
1266      def _OnPaint(self, event):      def _OnPaint(self, event):
1267          dc = wxPaintDC(self)          dc = wxPaintDC(self)
# Line 1015  class ClassDataPreviewer(wxWindow): Line 1269  class ClassDataPreviewer(wxWindow):
1269          # XXX: this doesn't seem to be having an effect:          # XXX: this doesn't seem to be having an effect:
1270          dc.DestroyClippingRegion()          dc.DestroyClippingRegion()
1271    
1272          self.Draw(dc, None)          if self.rect is None:
1273                w, h = self.GetSize()
1274                rect = wxRect(0, 0, w, h)
1275            else:
1276                rect = self.rect
1277    
1278            self.previewer.Draw(dc, rect, self.prop, self.shapeType)
1279    
1280    class ClassDataPreviewer:
1281    
1282      def Draw(self, dc, rect, prop = None, shapeType = None):      def Draw(self, dc, rect, prop, shapeType):
1283    
1284          if prop is None: prop = self.prop          assert dc is not None
1285          if shapeType is None: shapeType = self.shapeType          assert isinstance(prop, ClassGroupProperties)
1286    
1287          if rect is None:          if rect is None:
1288              x = y = 0              x = 0
1289              w, h = self.GetClientSizeTuple()              y = 0
1290                w, h = dc.GetSize()
1291          else:          else:
1292              x = rect.GetX()              x = rect.GetX()
1293              y = rect.GetY()              y = rect.GetY()
# Line 1032  class ClassDataPreviewer(wxWindow): Line 1295  class ClassDataPreviewer(wxWindow):
1295              h = rect.GetHeight()              h = rect.GetHeight()
1296    
1297          stroke = prop.GetLineColor()          stroke = prop.GetLineColor()
1298          if stroke is Color.None:          if stroke is Color.Transparent:
1299              pen = wxTRANSPARENT_PEN              pen = wxTRANSPARENT_PEN
1300          else:          else:
1301              pen = wxPen(Color2wxColour(stroke),              pen = wxPen(Color2wxColour(stroke),
# Line 1040  class ClassDataPreviewer(wxWindow): Line 1303  class ClassDataPreviewer(wxWindow):
1303                          wxSOLID)                          wxSOLID)
1304    
1305          stroke = prop.GetFill()          stroke = prop.GetFill()
1306          if stroke is Color.None:          if stroke is Color.Transparent:
1307              brush = wxTRANSPARENT_BRUSH              brush = wxTRANSPARENT_BRUSH
1308          else:          else:
1309              brush = wxBrush(Color2wxColour(stroke), wxSOLID)              brush = wxBrush(Color2wxColour(stroke), wxSOLID)
# Line 1054  class ClassDataPreviewer(wxWindow): Line 1317  class ClassDataPreviewer(wxWindow):
1317                             wxPoint(x + w/2, y + h/4*3),                             wxPoint(x + w/2, y + h/4*3),
1318                             wxPoint(x + w, y)])                             wxPoint(x + w, y)])
1319    
1320          elif shapeType == SHAPETYPE_POINT or \          elif shapeType == SHAPETYPE_POINT:
              shapeType == SHAPETYPE_POLYGON:  
1321    
1322              dc.DrawCircle(x + w/2, y + h/2,              dc.DrawCircle(x + w/2, y + h/2,
1323                            (min(w, h) - prop.GetLineWidth())/2)                            (min(w, h) - prop.GetLineWidth())/2)
1324    
1325            elif shapeType == SHAPETYPE_POLYGON:
1326                dc.DrawRectangle(x, y, w, h)
1327    
1328  class ClassRenderer(wxPyGridCellRenderer):  class ClassRenderer(wxPyGridCellRenderer):
1329    
1330      def __init__(self, shapeType):      def __init__(self, shapeType):
1331          wxPyGridCellRenderer.__init__(self)          wxPyGridCellRenderer.__init__(self)
1332          self.previewer = ClassDataPreviewer(None, None, shapeType)          self.shapeType = shapeType
1333            self.previewer = ClassDataPreviewer()
1334    
1335      def Draw(self, grid, attr, dc, rect, row, col, isSelected):      def Draw(self, grid, attr, dc, rect, row, col, isSelected):
1336          data = grid.GetTable().GetClassGroup(row)          data = grid.GetTable().GetClassGroup(row)
# Line 1077  class ClassRenderer(wxPyGridCellRenderer Line 1343  class ClassRenderer(wxPyGridCellRenderer
1343                           rect.GetWidth(), rect.GetHeight())                           rect.GetWidth(), rect.GetHeight())
1344    
1345          if not isinstance(data, ClassGroupMap):          if not isinstance(data, ClassGroupMap):
1346              self.previewer.Draw(dc, rect, data.GetProperties())              self.previewer.Draw(dc, rect, data.GetProperties(), self.shapeType)
1347    
1348          if isSelected:          if isSelected:
1349              dc.SetPen(wxPen(wxColour(0 * 255, 0 * 255, 0 * 255),              dc.SetPen(wxPen(wxBLACK, 1, wxSOLID))
                       4, wxSOLID))  
1350              dc.SetBrush(wxTRANSPARENT_BRUSH)              dc.SetBrush(wxTRANSPARENT_BRUSH)
1351    
1352              dc.DrawRectangle(rect.GetX(), rect.GetY(),              dc.DrawRectangle(rect.GetX(), rect.GetY(),
1353                               rect.GetWidth(), rect.GetHeight())                               rect.GetWidth(), rect.GetHeight())
1354    
1355          dc.DestroyClippingRegion()          dc.DestroyClippingRegion()
1356    
1357    
1358    class ClassGroupPropertiesCtrl(wxWindow, wxControl):
1359    
1360        def __init__(self, parent, id, props, shapeType,
1361                     size = wxDefaultSize, style = 0):
1362    
1363            wxWindow.__init__(self, parent, id, size = size, style = style)
1364    
1365            self.SetProperties(props)
1366            self.SetShapeType(shapeType)
1367            self.AllowEdit(True)
1368    
1369            EVT_PAINT(self, self._OnPaint)
1370            EVT_LEFT_DCLICK(self, self._OnLeftDClick)
1371    
1372            self.previewer = ClassDataPreviewer()
1373    
1374        def _OnPaint(self, event):
1375            dc = wxPaintDC(self)
1376    
1377            # XXX: this doesn't seem to be having an effect:
1378            dc.DestroyClippingRegion()
1379    
1380            w, h = self.GetClientSize()
1381    
1382            self.previewer.Draw(dc,
1383                                wxRect(0, 0, w, h),
1384                                self.GetProperties(),
1385                                self.GetShapeType())
1386    
1387    
1388        def GetProperties(self):
1389            return self.props
1390    
1391        def SetProperties(self, props):
1392            self.props = props
1393            self.Refresh()
1394    
1395        def GetShapeType(self):
1396            return self.shapeType
1397    
1398        def SetShapeType(self, shapeType):
1399            self.shapeType = shapeType
1400            self.Refresh()
1401    
1402        def AllowEdit(self, allow):
1403            self.allowEdit = allow
1404    
1405        def DoEdit(self):
1406            if not self.allowEdit: return
1407    
1408            propDlg = SelectPropertiesDialog(NULL,
1409                                             self.GetProperties(),
1410                                             self.GetShapeType())
1411    
1412            if propDlg.ShowModal() == wxID_OK:
1413                new_prop = propDlg.GetClassGroupProperties()
1414                self.SetProperties(new_prop)
1415                self.Refresh()
1416    
1417            propDlg.Destroy()
1418    
1419        def _OnLeftDClick(self, event):
1420            self.DoEdit()

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26