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

Legend:
Removed from v.498  
changed lines
  Added in v.638

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26