/[thuban]/trunk/thuban/Thuban/UI/classifier.py
ViewVC logotype

Diff of /trunk/thuban/Thuban/UI/classifier.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 473 by jonathan, Wed Mar 5 18:39:45 2003 UTC revision 606 by jonathan, Fri Apr 4 12:16:39 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001 by Intevation GmbH  # Copyright (c) 2001, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jonathan Coles <[email protected]>  # Jonathan Coles <[email protected]>
4  #  #
# Line 27  from Thuban.Model.color import Color Line 27  from Thuban.Model.color import Color
27    
28  from Thuban.Model.layer import Layer, SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT  from Thuban.Model.layer import Layer, SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT
29    
30    from Thuban.UI.classgen import ClassGenDialog, ClassGenerator
31    
32    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
# Line 34  ID_CLASS_TABLE = 40011 Line 38  ID_CLASS_TABLE = 40011
38  ID_CLASSIFY_OK = 4001  ID_CLASSIFY_OK = 4001
39  ID_CLASSIFY_CANCEL = 4002  ID_CLASSIFY_CANCEL = 4002
40  ID_CLASSIFY_ADD = 4003  ID_CLASSIFY_ADD = 4003
41  ID_CLASSIFY_GENRANGE = 4004  ID_CLASSIFY_GENCLASS = 4004
42  ID_CLASSIFY_REMOVE = 4005  ID_CLASSIFY_REMOVE = 4005
43  ID_CLASSIFY_MOVEUP = 4006  ID_CLASSIFY_MOVEUP = 4006
44  ID_CLASSIFY_MOVEDOWN = 4007  ID_CLASSIFY_MOVEDOWN = 4007
45    ID_CLASSIFY_APPLY = 4008
46    ID_CLASSIFY_EDITPROPS = 4009
47    
48  # table columns  # table columns
49  COL_SYMBOL = 0  COL_SYMBOL = 0
# Line 56  FIELD_NAME = 2 Line 62  FIELD_NAME = 2
62  import weakref  import weakref
63  class ClassGrid(wxGrid):  class ClassGrid(wxGrid):
64    
65      def __init__(self, parent):  
66        def __init__(self, parent, classifier):
67          """Constructor.          """Constructor.
68    
69          parent -- the parent window          parent -- the parent window
# Line 65  class ClassGrid(wxGrid): Line 72  class ClassGrid(wxGrid):
72                   use for display.                   use for display.
73          """          """
74    
75          wxGrid.__init__(self, parent, ID_CLASS_TABLE, size = (340, 160))          #wxGrid.__init__(self, parent, ID_CLASS_TABLE, size = (340, 160))
76          #self.SetTable(ClassTable(fieldData, layer.ShapeType(), self), true)          wxGrid.__init__(self, parent, ID_CLASS_TABLE)
77          self.SetSelectionMode(wxGrid.wxGridSelectRows)          #self.SetTable(ClassTable(fieldData, layer.ShapeType(), self), True)
78    
79            self.classifier = classifier
80    
81            self.currentSelection = []
82    
83          EVT_GRID_CELL_LEFT_DCLICK(self, self._OnCellDClick)          EVT_GRID_CELL_LEFT_DCLICK(self, self._OnCellDClick)
84          EVT_GRID_RANGE_SELECT(self, self._OnSelectedRange)          EVT_GRID_RANGE_SELECT(self, self._OnSelectedRange)
85          EVT_GRID_SELECT_CELL(self, self._OnSelectedCell)          EVT_GRID_SELECT_CELL(self, self._OnSelectedCell)
86            EVT_GRID_COL_SIZE(self, self._OnCellResize)
87            EVT_GRID_ROW_SIZE(self, self._OnCellResize)
88    
89          self.currentSelection = []          #print "123123123: ", ('Show' in dir(self))
90    
91      def CreateTable(self, clazz, shapeType):      #def Show(self):
92            #print "SHOW!"
93    
94          assert(isinstance(clazz, Classification))      #def Refresh(self):
95            #self.Show()
96        #def Update(self):
97            #self.Show()
98    
99        def CreateTable(self, clazz, shapeType, group = None):
100    
101            assert isinstance(clazz, Classification)
102    
         self.shapeType = shapeType  
103          table = self.GetTable()          table = self.GetTable()
104          if table is None:          if table is None:
105              self.SetTable(ClassTable(clazz, self.shapeType, self), true)              w = self.GetDefaultColSize() * 3 + self.GetDefaultRowLabelSize()
106          else:              h = self.GetDefaultRowSize() * 4 + self.GetDefaultColLabelSize()
107              table.Reset(clazz, self.shapeType)              self.SetDimensions(-1, -1, w, h)
108                self.SetSizeHints(w, h, -1, -1)
109                table = ClassTable(self)
110                self.SetTable(table, True)
111    
112    
113            self.SetSelectionMode(wxGrid.wxGridSelectRows)
114          self.ClearSelection()          self.ClearSelection()
115    
116            #print "8------------------"
117            table.Reset(clazz, shapeType, group)
118            #print "9------------------"
119    
120    #   def Show(self, show = True):
121    #       print "SHOW!"
122    #       wxGrid.Show(self, show)
123    
124    #       sel = self.GetCurrentSelection()
125    
126    #       print "( 1"
127    #       if len(sel) == 1:
128    #           print "( 2"
129    #           self.MakeCellVisible(sel[0], 0)
130    
131      def GetCurrentSelection(self):      def GetCurrentSelection(self):
132          """Return the currently highlighted rows as an increasing list          """Return the currently highlighted rows as an increasing list
133             of row numbers."""             of row numbers."""
134            #print "@@ ", self.currentSelection
135          sel = copy.copy(self.currentSelection)          sel = copy.copy(self.currentSelection)
136          sel.sort()          sel.sort()
137          return sel          return sel
138    
139        def GetSelectedRows(self):
140            return self.GetCurrentSelection()
141    
142      def SetCellRenderer(self, row, col):      def SetCellRenderer(self, row, col):
143          raise ValueError(_("Must not allow setting of renderer in ClassGrid!"))          raise ValueError(_("Must not allow setting of renderer in ClassGrid!"))
144    
# Line 128  class ClassGrid(wxGrid): Line 172  class ClassGrid(wxGrid):
172          # if only one thing is selected check if it is the default          # if only one thing is selected check if it is the default
173          # data row, because we can't remove that          # data row, because we can't remove that
174          if len(sel) == 1:          if len(sel) == 1:
175              group = self.GetTable().GetValueAsCustom(sel[0], COL_SYMBOL, None)              #group = self.GetTable().GetValueAsCustom(sel[0], COL_SYMBOL, None)
176                group = self.GetTable().GetClassGroup(sel[0])
177              if isinstance(group, ClassGroupDefault):              if isinstance(group, ClassGroupDefault):
178                  wxMessageDialog(self,                  wxMessageDialog(self,
179                                  "The Default group cannot be removed.",                                  "The Default group cannot be removed.",
# Line 160  class ClassGrid(wxGrid): Line 205  class ClassGrid(wxGrid):
205                  r = self.GetNumberRows() - 1                  r = self.GetNumberRows() - 1
206              self.SelectRow(r)              self.SelectRow(r)
207                    
208    
209        def SelectGroup(self, group, makeVisible = True):
210            if group is None: return
211    
212            assert isinstance(group, ClassGroup)
213    
214            table = self.GetTable()
215    
216            assert table is not None
217    
218    
219            #print "-- ", group
220            for i in range(table.GetNumberRows()):
221                g = table.GetClassGroup(i)
222                #print "1", g
223                if g is group:
224                    #print "2"
225                    self.SelectRow(i)
226                    if makeVisible:
227                        #print "3"
228                        self.MakeCellVisible(i, 0)
229                    break
230    
231            
232    
233  #  #
234  # 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!
235  #  #
# Line 177  class ClassGrid(wxGrid): Line 247  class ClassGrid(wxGrid):
247          r = event.GetRow()          r = event.GetRow()
248          c = event.GetCol()          c = event.GetCol()
249          if c == COL_SYMBOL:          if c == COL_SYMBOL:
250              group = self.GetTable().GetValueAsCustom(r, c, None)              self.classifier.EditGroupProperties(r)
             prop = group.GetProperties()  
251    
             # get a new ClassGroupProperties object and copy the  
             # values over to our current object  
             propDlg = SelectPropertiesDialog(NULL, prop, self.shapeType)  
             if propDlg.ShowModal() == wxID_OK:  
                 new_prop = propDlg.GetClassGroupProperties()  
                 prop.SetProperties(new_prop)  
                 self.Refresh()  
             propDlg.Destroy()  
252    
253      #      #
254      # _OnSelectedRange() and _OnSelectedCell() were borrowed      # _OnSelectedRange() and _OnSelectedCell() were borrowed
# Line 199  class ClassGrid(wxGrid): Line 260  class ClassGrid(wxGrid):
260          if event.Selecting():          if event.Selecting():
261              for index in range( event.GetTopRow(), event.GetBottomRow()+1):              for index in range( event.GetTopRow(), event.GetBottomRow()+1):
262                  if index not in self.currentSelection:                  if index not in self.currentSelection:
263                        #print "    ", index
264                      self.currentSelection.append( index )                      self.currentSelection.append( index )
265          else:          else:
266              for index in range( event.GetTopRow(), event.GetBottomRow()+1):              for index in range( event.GetTopRow(), event.GetBottomRow()+1):
267                  while index in self.currentSelection:                  while index in self.currentSelection:
268                        #print "    ", index
269                      self.currentSelection.remove( index )                      self.currentSelection.remove( index )
270          #self.ConfigureForSelection()          #self.ConfigureForSelection()
271    
272            #print self.GetCurrentSelection()
273          event.Skip()          event.Skip()
274    
275      def _OnSelectedCell( self, event ):      def _OnSelectedCell( self, event ):
276          """Internal update to the selection tracking list"""          """Internal update to the selection tracking list"""
277            #print "selecting cell: ", event.GetRow()
278          self.currentSelection = [ event.GetRow() ]          self.currentSelection = [ event.GetRow() ]
279          #self.ConfigureForSelection()          #self.ConfigureForSelection()
280          event.Skip()          event.Skip()
281    
282        def _OnCellResize(self, event):
283            self.FitInside()
284    
285  class ClassTable(wxPyGridTableBase):  class ClassTable(wxPyGridTableBase):
286      """Represents the underlying data structure for the grid."""      """Represents the underlying data structure for the grid."""
287    
# Line 221  class ClassTable(wxPyGridTableBase): Line 289  class ClassTable(wxPyGridTableBase):
289    
290      __col_labels = [_("Symbol"), _("Value"), _("Label")]      __col_labels = [_("Symbol"), _("Value"), _("Label")]
291    
292      def __init__(self, clazz, shapeType, view = None):  
293        def __init__(self, view = None):
294        #def __init__(self, clazz, shapeType, view = None):
295          """Constructor.          """Constructor.
296    
297          shapeType -- the type of shape that the layer uses          shapeType -- the type of shape that the layer uses
# Line 230  class ClassTable(wxPyGridTableBase): Line 300  class ClassTable(wxPyGridTableBase):
300          """          """
301    
302          wxPyGridTableBase.__init__(self)          wxPyGridTableBase.__init__(self)
303    
304          self.SetView(view)          self.SetView(view)
305          self.tdata = []          self.tdata = []
306    
307          self.Reset(clazz, shapeType)          #self.Reset(clazz, shapeType)
308    
309      def Reset(self, clazz, shapeType):      def Reset(self, clazz, shapeType, group = None):
310          """Reset the table with the given data.          """Reset the table with the given data.
311    
312          This is necessary because wxWindows does not allow a grid's          This is necessary because wxWindows does not allow a grid's
# Line 249  class ClassTable(wxPyGridTableBase): Line 320  class ClassTable(wxPyGridTableBase):
320          shapeType -- the type of shape that the layer uses          shapeType -- the type of shape that the layer uses
321          """          """
322    
323          assert(isinstance(clazz, Classification))          assert isinstance(clazz, Classification)
324    
325          self.GetView().BeginBatch()          self.GetView().BeginBatch()
326    
327          self.clazz = clazz          self.fieldType = clazz.GetFieldType()
328          self.shapeType = shapeType          self.shapeType = shapeType
         self.renderer = ClassRenderer(self.shapeType)  
329    
330          old_len = len(self.tdata)          self.SetClassification(clazz, group)
331            self.__Modified(-1)
332            #print "11------------------"
333    
334            self.GetView().EndBatch()
335            self.GetView().FitInside()
336    
337        def SetClassification(self, clazz, group = None):
338    
339            self.GetView().BeginBatch()
340    
341            old_len = self.GetNumberRows()
342          self.tdata = []          self.tdata = []
343    
344            #print "9------------------"
345          #          #
346          # copy the data out of the classification and into our          # copy the data out of the classification and into our
347          # array          # array
348          #          #
349          for p in self.clazz:          row = -1
350              np = copy.copy(p)          for g in clazz:
351              self.__SetRow(-1, np)              ng = copy.deepcopy(g)
352                self.__SetRow(None, ng)
353                if g is group:
354                    row = self.GetNumberRows() - 1
355                    #print "selecting row..."
356    
357            #print "10------------------"
358    
359          self.__Modified(False)          self.__NotifyRowChanges(old_len, self.GetNumberRows())
360    
361            if row > -1:
362                self.GetView().ClearSelection()
363                self.GetView().SelectRow(row)
364                self.GetView().MakeCellVisible(row, 0)
365    
         self.__NotifyRowChanges(old_len, len(self.tdata))  
366          self.GetView().EndBatch()          self.GetView().EndBatch()
367            self.GetView().FitInside()
368    
369      def __NotifyRowChanges(self, curRows, newRows):      def __NotifyRowChanges(self, curRows, newRows):
370          #          #
# Line 285  class ClassTable(wxPyGridTableBase): Line 376  class ClassTable(wxPyGridTableBase):
376                          wxGRIDTABLE_NOTIFY_ROWS_APPENDED,                          wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
377                          newRows - curRows)    # how many                          newRows - curRows)    # how many
378              self.GetView().ProcessTableMessage(msg)              self.GetView().ProcessTableMessage(msg)
379                self.GetView().FitInside()
380          elif newRows < curRows:          elif newRows < curRows:
381              msg = wxGridTableMessage(self,              msg = wxGridTableMessage(self,
382                          wxGRIDTABLE_NOTIFY_ROWS_DELETED,                          wxGRIDTABLE_NOTIFY_ROWS_DELETED,
383                          curRows - newRows,    # position                          curRows,              # position
384                          curRows - newRows)    # how many                          curRows - newRows)    # how many
385              self.GetView().ProcessTableMessage(msg)              self.GetView().ProcessTableMessage(msg)
386                self.GetView().FitInside()
387    
388      def __SetRow(self, row, group):      def __SetRow(self, row, group):
389          """Set a row's data to that of the group.          """Set a row's data to that of the group.
390    
391          row -- if row is -1 or greater than the current number of rows          The table is considered modified after this operation.
392                 then group is appended to the end.  
393            row -- if row is < 0 'group' is inserted at the top of the table
394                   if row is >= GetNumberRows() or None 'group' is append to
395                        the end of the table.
396                   otherwise 'group' replaces row 'row'
397          """          """
398    
399          # either append or replace          # either append or replace
400          if row == -1 or row >= self.GetNumberRows():          if row is None or row >= self.GetNumberRows():
401              self.tdata.append(group)              self.tdata.append(group)
402            elif row < 0:
403                self.tdata.insert(0, group)
404          else:          else:
405              self.tdata[row] = group              self.tdata[row] = group
406    
# Line 320  class ClassTable(wxPyGridTableBase): Line 419  class ClassTable(wxPyGridTableBase):
419          if isinstance(group, ClassGroupRange):     return _("Range")          if isinstance(group, ClassGroupRange):     return _("Range")
420          if isinstance(group, ClassGroupMap):       return _("Map")          if isinstance(group, ClassGroupMap):       return _("Map")
421    
422          assert(False) # shouldn't get here          assert False # shouldn't get here
423          return _("")          return _("")
424    
425      def GetNumberRows(self):      def GetNumberRows(self):
# Line 359  class ClassTable(wxPyGridTableBase): Line 458  class ClassTable(wxPyGridTableBase):
458          group = self.tdata[row]          group = self.tdata[row]
459    
460          if col == COL_SYMBOL:          if col == COL_SYMBOL:
461              return group              return group.GetProperties()
462    
463          if col == COL_LABEL:          if col == COL_LABEL:
464              return group.GetLabel()              return group.GetLabel()
465    
466          # col must be COL_VALUE          # col must be COL_VALUE
467          assert(col == COL_VALUE)          assert col == COL_VALUE
468    
469          if isinstance(group, ClassGroupDefault):          if isinstance(group, ClassGroupDefault):
470              return _("DEFAULT")              return _("DEFAULT")
# Line 374  class ClassTable(wxPyGridTableBase): Line 473  class ClassTable(wxPyGridTableBase):
473          elif isinstance(group, ClassGroupRange):          elif isinstance(group, ClassGroupRange):
474              return _("%s - %s") % (group.GetMin(), group.GetMax())              return _("%s - %s") % (group.GetMin(), group.GetMax())
475    
476          assert(False) # shouldn't get here          assert False  # shouldn't get here
477          return None          return None
478    
479      def __ParseInput(self, value):      def __ParseInput(self, value):
# Line 385  class ClassTable(wxPyGridTableBase): Line 484  class ClassTable(wxPyGridTableBase):
484          value, or of length two if it is a range.          value, or of length two if it is a range.
485          """          """
486    
487          type = self.clazz.GetFieldType()          type = self.fieldType
488    
489          if type == FIELDTYPE_STRING:          if type == FIELDTYPE_STRING:
490              return (value,)              return (value,)
# Line 414  class ClassTable(wxPyGridTableBase): Line 513  class ClassTable(wxPyGridTableBase):
513    
514                  return (conv(Str2Num(value[:i])), conv(Str2Num(value[i+1:])))                  return (conv(Str2Num(value[:i])), conv(Str2Num(value[i+1:])))
515    
516          assert(False) # shouldn't get here          assert False  # shouldn't get here
517            return (0,)
518                            
519    
520      def SetValueAsCustom(self, row, col, typeName, value):      def SetValueAsCustom(self, row, col, typeName, value):
# Line 429  class ClassTable(wxPyGridTableBase): Line 529  class ClassTable(wxPyGridTableBase):
529          typeName -- unused, but needed to overload wxPyGridTableBase          typeName -- unused, but needed to overload wxPyGridTableBase
530          """          """
531    
532          assert(col >= 0 and col < self.GetNumberCols())          assert col >= 0 and col < self.GetNumberCols()
533          assert(row >= 0 and row < self.GetNumberRows())          assert row >= 0 and row < self.GetNumberRows()
534    
535          group = self.tdata[row]          group = self.tdata[row]
536    
537          mod = False          mod = True # assume the data will change
538    
539          if col == COL_SYMBOL:          if col == COL_SYMBOL:
540              self.__SetRow(row, value)              group.SetProperties(value)
541              mod = True          elif col == COL_LABEL:
542                group.SetLabel(value)
543          elif col == COL_VALUE:          elif col == COL_VALUE:
544              if isinstance(group, ClassGroupDefault):              if isinstance(group, ClassGroupDefault):
545                  # not allowed to modify the default value                  # not allowed to modify the default value
# Line 451  class ClassTable(wxPyGridTableBase): Line 552  class ClassTable(wxPyGridTableBase):
552                      dataInfo = self.__ParseInput(value)                      dataInfo = self.__ParseInput(value)
553                  except ValueError:                  except ValueError:
554                      # bad input, ignore the request                      # bad input, ignore the request
555                      pass                      mod = False
556                  else:                  else:
557    
558                        changed = False
559                      ngroup = group                      ngroup = group
560                      props = group.GetProperties()                      props = group.GetProperties()
561    
# Line 465  class ClassTable(wxPyGridTableBase): Line 567  class ClassTable(wxPyGridTableBase):
567                      if len(dataInfo) == 1:                      if len(dataInfo) == 1:
568                          if not isinstance(group, ClassGroupSingleton):                          if not isinstance(group, ClassGroupSingleton):
569                              ngroup = ClassGroupSingleton(prop = props)                              ngroup = ClassGroupSingleton(prop = props)
570                                changed = True
571                          ngroup.SetValue(dataInfo[0])                          ngroup.SetValue(dataInfo[0])
572                      elif len(dataInfo) == 2:                      elif len(dataInfo) == 2:
573                          if not isinstance(group, ClassGroupRange):                          if not isinstance(group, ClassGroupRange):
574                              ngroup = ClassGroupRange(prop = props)                              ngroup = ClassGroupRange(prop = props)
575                                changed = True
576                          ngroup.SetRange(dataInfo[0], dataInfo[1])                          ngroup.SetRange(dataInfo[0], dataInfo[1])
577                      else:                      else:
578                          assert(False)                          assert False
579                            pass
580    
581                      ngroup.SetLabel(group.GetLabel())                      if changed:
582                            ngroup.SetLabel(group.GetLabel())
583                      self.__SetRow(row, ngroup)                          self.SetClassGroup(row, ngroup)
584            else:
585                      mod = True              assert False # shouldn't be here
586                pass
   
         elif col == COL_LABEL:  
             group.SetLabel(value)  
             mod = True  
587    
588          if mod:          if mod:
589              self.__Modified()              self.__Modified()
590              self.GetView().Refresh()              self.GetView().Refresh()
591    
# Line 495  class ClassTable(wxPyGridTableBase): Line 596  class ClassTable(wxPyGridTableBase):
596          #attr = wxPyGridTableBase.GetAttr(self, row, col, someExtraParameter)          #attr = wxPyGridTableBase.GetAttr(self, row, col, someExtraParameter)
597    
598          if col == COL_SYMBOL:          if col == COL_SYMBOL:
599                # we need to create a new renderer each time, because
600                # SetRenderer takes control of the parameter
601              attr.SetRenderer(ClassRenderer(self.shapeType))              attr.SetRenderer(ClassRenderer(self.shapeType))
602              attr.SetReadOnly()              attr.SetReadOnly()
603    
# Line 503  class ClassTable(wxPyGridTableBase): Line 606  class ClassTable(wxPyGridTableBase):
606      def GetClassGroup(self, row):      def GetClassGroup(self, row):
607          """Return the ClassGroup object representing row 'row'."""          """Return the ClassGroup object representing row 'row'."""
608    
609          return self.GetValueAsCustom(row, COL_SYMBOL, None)          return self.tdata[row] # self.GetValueAsCustom(row, COL_SYMBOL, None)
610    
611      def SetClassGroup(self, row, group):      def SetClassGroup(self, row, group):
612          self.SetValueAsCustom(row, COL_SYMBOL, None, group)          self.__SetRow(row, group)
613            self.GetView().Refresh()
614    
615      def __Modified(self, mod = True):      def __Modified(self, mod = True):
616          """Set the modified flag."""          """Adjust the modified flag.
617          self.modified = mod  
618            mod -- if -1 set the modified flag to False, otherwise perform
619                   an 'or' operation with the current value of the flag and
620                   'mod'
621            """
622    
623            if mod == -1:
624                self.modified = False
625            else:
626                self.modified = mod or self.modified
627    
628      def IsModified(self):      def IsModified(self):
629          """True if this table is considered modified."""          """True if this table is considered modified."""
630          return self.modified          return self.modified
631    
632      def DeleteRows(self, pos, numRows = 1):      def DeleteRows(self, pos, numRows = 1):
633          """Deletes 'numRows' beginning at row 'pos'.          """Deletes 'numRows' beginning at row 'pos'.
634    
635          The table is considered modified after this operation.          The row representing the default group is not removed.
636    
637            The table is considered modified if any rows are removed.
638          """          """
639    
640          assert(pos >= 0)          assert pos >= 0
641          old_len = len(self.tdata)          old_len = len(self.tdata)
642          for row in range(pos, pos - numRows, -1):          for row in range(pos, pos - numRows, -1):
643              group = self.GetValueAsCustom(row, COL_SYMBOL, None)              group = self.GetClassGroup(row)
644              if not isinstance(group, ClassGroupDefault):              if not isinstance(group, ClassGroupDefault):
645                  self.tdata.pop(row)                  self.tdata.pop(row)
646                  self.__Modified()                  self.__Modified()
# Line 534  class ClassTable(wxPyGridTableBase): Line 649  class ClassTable(wxPyGridTableBase):
649              self.__NotifyRowChanges(old_len, len(self.tdata))              self.__NotifyRowChanges(old_len, len(self.tdata))
650    
651      def AppendRows(self, numRows = 1):      def AppendRows(self, numRows = 1):
652          """Append 'numRows' empty rows to the end of the table."""          """Append 'numRows' empty rows to the end of the table.
653    
654            The table is considered modified if any rows are appended.
655            """
656    
657          old_len = len(self.tdata)          old_len = len(self.tdata)
658          for i in range(numRows):          for i in range(numRows):
659              np = ClassGroupSingleton()              np = ClassGroupSingleton()
660              self.__SetRow(-1, np)              self.__SetRow(None, np)
             #self.tdata.append([np, np.GetValue(), np.GetLabel()])  
             self.__Modified()  
661    
662          if self.IsModified():          if self.IsModified():
663              self.__NotifyRowChanges(old_len, len(self.tdata))              self.__NotifyRowChanges(old_len, len(self.tdata))
664    
665    
666  class Classifier(wxDialog):  class Classifier(NonModalDialog):
       
     def __init__(self, parent, layer):  
         wxDialog.__init__(self, parent, -1, _("Classify"),  
                           style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)  
667    
668        def __init__(self, parent, name, layer, group = None):
669            NonModalDialog.__init__(self, parent, name,
670                                    _("Classifier: %s") % layer.Title())
671    
672            panel = wxPanel(self, -1, size=(100, 100))
673    
674          self.layer = layer          self.layer = layer
675    
676            self.originalClass = self.layer.GetClassification()
677            field = self.originalClass.GetField()
678            fieldType = self.originalClass.GetFieldType()
679    
680          topBox = wxBoxSizer(wxVERTICAL)          topBox = wxBoxSizer(wxVERTICAL)
681            panelBox = wxBoxSizer(wxVERTICAL)
682    
683          topBox.Add(wxStaticText(self, -1, _("Layer: %s") % layer.Title()),          #panelBox.Add(wxStaticText(panel, -1, _("Layer: %s") % layer.Title()),
684              0, wxALIGN_LEFT | wxALL, 4)              #0, wxALIGN_LEFT | wxALL, 4)
685          topBox.Add(wxStaticText(self, -1, _("Type: %s") % layer.ShapeType()),          panelBox.Add(wxStaticText(panel, -1,
686                                    _("Layer Type: %s") % layer.ShapeType()),
687              0, wxALIGN_LEFT | wxALL, 4)              0, wxALIGN_LEFT | wxALL, 4)
688    
         propertyBox = wxBoxSizer(wxHORIZONTAL)  
         propertyBox.Add(wxStaticText(self, -1, _("Field: ")),  
             0, wxALIGN_CENTER | wxALL, 4)  
689    
690          self.fields = wxComboBox(self, ID_PROPERTY_SELECT, "",          #
691            # make field combo box
692            #
693            self.fields = wxComboBox(panel, ID_PROPERTY_SELECT, "",
694                                       style = wxCB_READONLY)                                       style = wxCB_READONLY)
695    
696          self.num_cols = layer.table.field_count()          self.num_cols = layer.table.field_count()
697          # just assume the first field in case one hasn't been          # just assume the first field in case one hasn't been
698          # specified in the file.          # specified in the file.
699          self.__cur_field = 0          self.__cur_field = 0
         clazz = layer.GetClassification()  
         field = clazz.GetField()  
700    
701          self.fields.Append("<None>")          self.fields.Append("<None>")
702          self.fields.SetClientData(0, None)          self.fields.SetClientData(0, None)
# Line 586  class Classifier(wxDialog): Line 707  class Classifier(wxDialog):
707    
708              if name == field:              if name == field:
709                  self.__cur_field = i + 1                  self.__cur_field = i + 1
710                  self.fields.SetClientData(i + 1, clazz)                  self.fields.SetClientData(i + 1, self.originalClass)
711              else:              else:
712                  self.fields.SetClientData(i + 1, None)                  self.fields.SetClientData(i + 1, None)
713    
         self.fields.SetSelection(self.__cur_field)  
714    
715            ###########
716    
717            self.fieldTypeText = wxStaticText(panel, -1, "")
718            panelBox.Add(self.fieldTypeText, 0,
719                         wxGROW | wxALIGN_LEFT | wxALL | wxADJUST_MINSIZE, 4)
720    
721            propertyBox = wxBoxSizer(wxHORIZONTAL)
722            propertyBox.Add(wxStaticText(panel, -1, _("Field: ")),
723                0, wxALIGN_LEFT | wxALL, 4)
724          propertyBox.Add(self.fields, 1, wxGROW|wxALL, 4)          propertyBox.Add(self.fields, 1, wxGROW|wxALL, 4)
725          EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self._OnFieldSelect)          EVT_COMBOBOX(self, ID_PROPERTY_SELECT, self._OnFieldSelect)
726    
727          topBox.Add(propertyBox, 0, wxGROW, 4)          panelBox.Add(propertyBox, 0, wxGROW, 4)
728    
729    
730            #
731            # Control Box
732            #
733            controlBox = wxBoxSizer(wxHORIZONTAL)
734    
735    
736            ###########
737            #
738            # Control buttons:
739            #
740            self.controlButtons = []
741    
742            controlButtonBox = wxBoxSizer(wxVERTICAL)
743    
744            button = wxButton(panel, ID_CLASSIFY_ADD, _("Add"))
745            controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
746            self.controlButtons.append(button)
747    
748            button = wxButton(panel, ID_CLASSIFY_EDITPROPS, _("Edit Properties"))
749            controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
750            self.controlButtons.append(button)
751    
752            button = wxButton(panel, ID_CLASSIFY_GENCLASS, _("Generate Class"))
753            controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
754            self.controlButtons.append(button)
755    
756            button = wxButton(panel, ID_CLASSIFY_MOVEUP, _("Move Up"))
757            controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
758            self.controlButtons.append(button)
759    
760            button = wxButton(panel, ID_CLASSIFY_MOVEDOWN, _("Move Down"))
761            controlButtonBox.Add(button, 0, wxGROW | wxALL, 4)
762            self.controlButtons.append(button)
763    
764            controlButtonBox.Add(60, 20, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
765    
766            button = wxButton(panel, ID_CLASSIFY_REMOVE, _("Remove"))
767            controlButtonBox.Add(button, 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)
768            self.controlButtons.append(button)
769    
770    
771            ###########
772          #          #
773          # Classification data table          # Classification data table
774          #          #
775    
776          controlBox = wxBoxSizer(wxHORIZONTAL)          self.classGrid = ClassGrid(panel, self)
777          self.classGrid = ClassGrid(self)          #self.__SetGridTable(self.__cur_field, group)
778            #self.fields.SetSelection(self.__cur_field)
779    
780            # calling __SelectField after creating the classGrid fills in the
781            # grid with the correct information
782            #print "2------------------"
783            self.__SelectField(self.__cur_field, group = group)
784    
785          self.__SetGridTable(self.__cur_field)          #self.classGrid.SelectGroup(group)
786    
787          controlBox.Add(self.classGrid, 1, wxGROW, 0)          controlBox.Add(self.classGrid, 1, wxGROW, 0)
788    
         controlButtonBox = wxBoxSizer(wxVERTICAL)  
         controlButtonBox.Add(wxButton(self, ID_CLASSIFY_ADD,  
             _("Add")), 0, wxGROW | wxALL, 4)  
         controlButtonBox.Add(wxButton(self, ID_CLASSIFY_GENRANGE,  
             _("Generate Ranges")), 0, wxGROW | wxALL, 4)  
   
         controlButtonBox.Add(wxButton(self, ID_CLASSIFY_MOVEUP,  
             _("Move Up")), 0, wxGROW | wxALL, 4)  
         controlButtonBox.Add(wxButton(self, ID_CLASSIFY_MOVEDOWN,  
             _("Move Down")), 0, wxGROW | wxALL, 4)  
789    
         controlButtonBox.Add(wxButton(self, ID_CLASSIFY_REMOVE,  
             _("Remove")), 0, wxGROW | wxALL | wxALIGN_BOTTOM, 4)  
790    
791          controlBox.Add(controlButtonBox, 0, wxGROW, 10)          controlBox.Add(controlButtonBox, 0, wxGROW, 10)
792          topBox.Add(controlBox, 1, wxGROW, 10)          panelBox.Add(controlBox, 1, wxGROW, 10)
793    
794          EVT_BUTTON(self, ID_CLASSIFY_ADD, self._OnAdd)          EVT_BUTTON(self, ID_CLASSIFY_ADD, self._OnAdd)
795            EVT_BUTTON(self, ID_CLASSIFY_EDITPROPS, self._OnEditGroupProperties)
796          EVT_BUTTON(self, ID_CLASSIFY_REMOVE, self._OnRemove)          EVT_BUTTON(self, ID_CLASSIFY_REMOVE, self._OnRemove)
797          EVT_BUTTON(self, ID_CLASSIFY_GENRANGE, self._OnGenRange)          EVT_BUTTON(self, ID_CLASSIFY_GENCLASS, self._OnGenClass)
798          EVT_BUTTON(self, ID_CLASSIFY_MOVEUP, self._OnMoveUp)          EVT_BUTTON(self, ID_CLASSIFY_MOVEUP, self._OnMoveUp)
799          EVT_BUTTON(self, ID_CLASSIFY_MOVEDOWN, self._OnMoveDown)          EVT_BUTTON(self, ID_CLASSIFY_MOVEDOWN, self._OnMoveDown)
800    
801          #          ###########
802          # Control buttons:  
         #  
803          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
804          buttonBox.Add(wxButton(self, ID_CLASSIFY_OK, _("OK")),          buttonBox.Add(wxButton(panel, ID_CLASSIFY_OK, _("OK")),
805                        0, wxALL, 4)                        0, wxALL, 4)
806          buttonBox.Add(wxButton(self, ID_CLASSIFY_CANCEL, _("Cancel")),          buttonBox.Add(60, 20, 0, wxALL, 4)
807            buttonBox.Add(wxButton(panel, ID_CLASSIFY_APPLY, _("Apply")),
808                        0, wxALL, 4)                        0, wxALL, 4)
809          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)          buttonBox.Add(60, 20, 0, wxALL, 4)
810            buttonBox.Add(wxButton(panel, ID_CLASSIFY_CANCEL, _("Cancel")),
811                          0, wxALL, 4)
812            panelBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 0)
813    
814          EVT_BUTTON(self, ID_CLASSIFY_OK, self._OnOK)          EVT_BUTTON(self, ID_CLASSIFY_OK, self._OnOK)
815            EVT_BUTTON(self, ID_CLASSIFY_APPLY, self._OnApply)
816          EVT_BUTTON(self, ID_CLASSIFY_CANCEL, self._OnCancel)          EVT_BUTTON(self, ID_CLASSIFY_CANCEL, self._OnCancel)
817    
818            ###########
819    
820    
821            panel.SetAutoLayout(True)
822            panel.SetSizer(panelBox)
823            panelBox.SetSizeHints(panel)
824    
825          self.SetAutoLayout(true)          topBox.Add(panel, 1, wxGROW, 0)
826            panelBox.SetSizeHints(self)
827            self.SetAutoLayout(True)
828          self.SetSizer(topBox)          self.SetSizer(topBox)
829          topBox.Fit(self)  
830          topBox.SetSizeHints(self)          #print "1------------------"
831            #self.Fit()
832            ######################
833    
834            self.haveApplied = False
835    
836        def EditGroupProperties(self, row):
837            table = self.classGrid.GetTable()
838            prop = table.GetValueAsCustom(row, COL_SYMBOL, None)
839    
840            # get a new ClassGroupProperties object and copy the
841            # values over to our current object
842            propDlg = SelectPropertiesDialog(NULL, prop, self.layer.ShapeType())
843            if propDlg.ShowModal() == wxID_OK:
844                new_prop = propDlg.GetClassGroupProperties()
845                table.SetValueAsCustom(row, COL_SYMBOL, None, new_prop)
846            propDlg.Destroy()
847            
848    
849      def __BuildClassification(self, fieldIndex):      def __BuildClassification(self, fieldIndex):
850    
851            numRows = self.classGrid.GetNumberRows()
852            assert numRows > 0  # there should always be a default row
853    
854          clazz = Classification()          clazz = Classification()
855          fieldName = self.fields.GetString(fieldIndex)          if fieldIndex == 0:
856          fieldType = self.layer.GetFieldType(fieldName)              fieldName = None
857                fieldType = None
858            else:
859                fieldName = self.fields.GetString(fieldIndex)
860                fieldType = self.layer.GetFieldType(fieldName)
861    
862          clazz.SetField(fieldName)          clazz.SetField(fieldName)
863          clazz.SetFieldType(fieldType)          clazz.SetFieldType(fieldType)
864    
         numRows = self.classGrid.GetNumberRows()  
   
         assert(numRows > 0) # there should always be a default row  
865    
866          table = self.classGrid.GetTable()          table = self.classGrid.GetTable()
867          clazz.SetDefaultGroup(table.GetClassGroup(0))          clazz.SetDefaultGroup(table.GetClassGroup(0))
# Line 672  class Classifier(wxDialog): Line 871  class Classifier(wxDialog):
871    
872          return clazz          return clazz
873    
874      def __SetGridTable(self, fieldIndex):      def __SetGridTable(self, fieldIndex, group = None):
875    
876          clazz = self.fields.GetClientData(fieldIndex)          clazz = self.fields.GetClientData(fieldIndex)
877    
# Line 680  class Classifier(wxDialog): Line 879  class Classifier(wxDialog):
879              clazz = Classification()              clazz = Classification()
880              clazz.SetDefaultGroup(              clazz.SetDefaultGroup(
881                  ClassGroupDefault(                  ClassGroupDefault(
882                      self.layer.GetClassification().GetDefaultGroup().GetProperties()))                      self.layer.GetClassification().
883                                   GetDefaultGroup().GetProperties()))
884    
885              fieldName = self.fields.GetString(fieldIndex)              fieldName = self.fields.GetString(fieldIndex)
886              fieldType = self.layer.GetFieldType(fieldName)              fieldType = self.layer.GetFieldType(fieldName)
887              clazz.SetFieldType(fieldType)              clazz.SetFieldType(fieldType)
888                                    
889          self.classGrid.CreateTable(clazz, self.layer.ShapeType())          #print "6------------------"
890            self.classGrid.CreateTable(clazz, self.layer.ShapeType(), group)
891            #print "7------------------"
892    
     def _OnFieldSelect(self, event):  
         clazz = self.__BuildClassification(self.__cur_field)  
         self.fields.SetClientData(self.__cur_field, clazz)  
893    
         self.__cur_field = self.fields.GetSelection()  
         self.__SetGridTable(self.__cur_field)  
894    
895      def _OnOK(self, event):      type2string = {None:             _("None"),
896                       FIELDTYPE_STRING: _("Text"),
897                       FIELDTYPE_INT:    _("Integer"),
898                       FIELDTYPE_DOUBLE: _("Decimal")}
899    
900        def __SetFieldTypeText(self, fieldIndex):
901            fieldName = self.fields.GetString(fieldIndex)
902            fieldType = self.layer.GetFieldType(fieldName)
903    
904            assert Classifier.type2string.has_key(fieldType)
905    
906            text = Classifier.type2string[fieldType]
907    
908            self.fieldTypeText.SetLabel(_("Field Type: %s") % text)
909    
910        def __SelectField(self, newIndex, oldIndex = -1, group = None):
911    
912            #print "3------------------"
913    
914            assert oldIndex >= -1
915    
916            self.fields.SetSelection(newIndex)
917    
918            if oldIndex != -1:
919                clazz = self.__BuildClassification(oldIndex)
920                self.fields.SetClientData(oldIndex, clazz)
921    
922            #print "4------------------"
923            self.__SetGridTable(newIndex, group)
924            #print "5------------------"
925    
926            enabled = newIndex != 0
927    
928            for b in self.controlButtons:
929                b.Enable(enabled)
930    
931            self.__SetFieldTypeText(newIndex)
932    
933    
934        def _OnEditGroupProperties(self, event):
935            sel = self.classGrid.GetCurrentSelection()
936    
937            if len(sel) == 1:
938                self.EditGroupProperties(sel[0])
939    
940        def _OnFieldSelect(self, event):
941            index = self.fields.GetSelection()
942            self.__SelectField(index, self.__cur_field)
943            self.__cur_field = index
944    
945        def _OnApply(self, event):
946          """Put the data from the table into a new Classification and hand          """Put the data from the table into a new Classification and hand
947             it to the layer.             it to the layer.
948          """          """
# Line 709  class Classifier(wxDialog): Line 956  class Classifier(wxDialog):
956          if clazz is None or self.classGrid.GetTable().IsModified():          if clazz is None or self.classGrid.GetTable().IsModified():
957              clazz = self.__BuildClassification(self.__cur_field)              clazz = self.__BuildClassification(self.__cur_field)
958    
         clazz.SetLayer(self.layer)  
   
959          self.layer.SetClassification(clazz)          self.layer.SetClassification(clazz)
960    
961          self.EndModal(wxID_OK)          self.haveApplied = True
962    
963        def _OnOK(self, event):
964            self._OnApply(event)
965            self.OnClose(event)
966    
967      def _OnCancel(self, event):      def _OnCancel(self, event):
968          """Do nothing. The layer's current classification stays the same."""          """The layer's current classification stays the same."""
969          self.EndModal(wxID_CANCEL)          if self.haveApplied:
970                self.layer.SetClassification(self.originalClass)
971    
972            self.OnClose(event)
973    
974      def _OnAdd(self, event):      def _OnAdd(self, event):
975          self.classGrid.AppendRows()          self.classGrid.AppendRows()
# Line 725  class Classifier(wxDialog): Line 977  class Classifier(wxDialog):
977      def _OnRemove(self, event):      def _OnRemove(self, event):
978          self.classGrid.DeleteSelectedRows()          self.classGrid.DeleteSelectedRows()
979    
980      def _OnGenRange(self, event):      def _OnGenClass(self, event):
981          print "Classifier._OnGenRange()"  
982            genDlg = ClassGenDialog(self,
983                                    self.layer.table,
984                                    self.fields.GetString(self.__cur_field))
985    
986            if genDlg.ShowModal() == wxID_OK:
987                clazz = genDlg.GetClassification()
988                self.fields.SetClientData(self.__cur_field, clazz)
989                self.classGrid.GetTable().SetClassification(clazz)
990            genDlg.Destroy()
991    
992      def _OnMoveUp(self, event):      def _OnMoveUp(self, event):
993          sel = self.classGrid.GetCurrentSelection()          sel = self.classGrid.GetCurrentSelection()
994    
995            #print "sel: ", sel
996    
997          if len(sel) == 1:          if len(sel) == 1:
998              i = sel[0]              i = sel[0]
999              if i > 1:              if i > 1:
# Line 741  class Classifier(wxDialog): Line 1004  class Classifier(wxDialog):
1004                  table.SetClassGroup(i, x)                  table.SetClassGroup(i, x)
1005                  self.classGrid.ClearSelection()                  self.classGrid.ClearSelection()
1006                  self.classGrid.SelectRow(i - 1)                  self.classGrid.SelectRow(i - 1)
1007                    self.classGrid.MakeCellVisible(i - 1, 0)
1008    
1009      def _OnMoveDown(self, event):      def _OnMoveDown(self, event):
1010          sel = self.classGrid.GetCurrentSelection()          sel = self.classGrid.GetCurrentSelection()
# Line 755  class Classifier(wxDialog): Line 1019  class Classifier(wxDialog):
1019                  table.SetClassGroup(i + 1, x)                  table.SetClassGroup(i + 1, x)
1020                  self.classGrid.ClearSelection()                  self.classGrid.ClearSelection()
1021                  self.classGrid.SelectRow(i + 1)                  self.classGrid.SelectRow(i + 1)
1022                    self.classGrid.MakeCellVisible(i + 1, 0)
1023    
1024    
1025  ID_SELPROP_OK = 4001  ID_SELPROP_OK = 4001
# Line 763  ID_SELPROP_SPINCTRL = 4002 Line 1028  ID_SELPROP_SPINCTRL = 4002
1028  ID_SELPROP_PREVIEW = 4003  ID_SELPROP_PREVIEW = 4003
1029  ID_SELPROP_STROKECLR = 4004  ID_SELPROP_STROKECLR = 4004
1030  ID_SELPROP_FILLCLR = 4005  ID_SELPROP_FILLCLR = 4005
1031    ID_SELPROP_STROKECLRTRANS = 4006
1032    ID_SELPROP_FILLCLRTRANS = 4007
1033    
1034  class SelectPropertiesDialog(wxDialog):  class SelectPropertiesDialog(wxDialog):
1035    
1036      def __init__(self, parent, prop, shapeType):      def __init__(self, parent, prop, shapeType):
1037          wxDialog.__init__(self, parent, -1, _("Select Properties"),          wxDialog.__init__(self, parent, -1, _("Select Properties"),
1038                            style = wxRESIZE_BORDER)                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
1039    
1040          self.prop = ClassGroupProperties(prop)          self.prop = ClassGroupProperties(prop)
1041    
# Line 780  class SelectPropertiesDialog(wxDialog): Line 1047  class SelectPropertiesDialog(wxDialog):
1047          previewBox = wxBoxSizer(wxVERTICAL)          previewBox = wxBoxSizer(wxVERTICAL)
1048          previewBox.Add(wxStaticText(self, -1, _("Preview:")),          previewBox.Add(wxStaticText(self, -1, _("Preview:")),
1049              0, wxALIGN_LEFT | wxALL, 4)              0, wxALIGN_LEFT | wxALL, 4)
1050          self.previewer = ClassDataPreviewer(None, self.prop, shapeType,          self.previewWin = ClassDataPreviewWindow(None, self.prop, shapeType,
1051                                              self, ID_SELPROP_PREVIEW, (40, 40))                                              self, ID_SELPROP_PREVIEW, (40, 40))
1052          previewBox.Add(self.previewer, 1, wxGROW, 15)          previewBox.Add(self.previewWin, 1, wxGROW, 15)
1053    
1054          itemBox.Add(previewBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)          itemBox.Add(previewBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)
1055    
1056          # control box          # control box
1057          ctrlBox = wxBoxSizer(wxVERTICAL)          ctrlBox = wxBoxSizer(wxVERTICAL)
1058          ctrlBox.Add(  
1059              wxButton(self, ID_SELPROP_STROKECLR, "Change Line Color"),          lineColorBox = wxBoxSizer(wxHORIZONTAL)
1060              0, wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)          lineColorBox.Add(
1061                wxButton(self, ID_SELPROP_STROKECLR, _("Change Line Color")),
1062                1, wxALL | wxGROW, 4)
1063          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)
1064    
1065            lineColorBox.Add(
1066                wxButton(self, ID_SELPROP_STROKECLRTRANS, _("Transparent")),
1067                1, wxALL | wxGROW, 4)
1068            EVT_BUTTON(self, ID_SELPROP_STROKECLRTRANS,
1069                       self._OnChangeLineColorTrans)
1070    
1071            ctrlBox.Add(lineColorBox, 0,
1072                        wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)
1073    
1074          if shapeType != SHAPETYPE_ARC:          if shapeType != SHAPETYPE_ARC:
1075              ctrlBox.Add(              fillColorBox = wxBoxSizer(wxHORIZONTAL)
1076                  wxButton(self, ID_SELPROP_FILLCLR, "Change Fill Color"),              fillColorBox.Add(
1077                  0, wxALIGN_LEFT | wxALL | wxGROW, 4)                  wxButton(self, ID_SELPROP_FILLCLR, _("Change Fill Color")),
1078                    1, wxALL | wxGROW, 4)
1079              EVT_BUTTON(self, ID_SELPROP_FILLCLR, self._OnChangeFillColor)              EVT_BUTTON(self, ID_SELPROP_FILLCLR, self._OnChangeFillColor)
1080                fillColorBox.Add(
1081                    wxButton(self, ID_SELPROP_FILLCLRTRANS, _("Transparent")),
1082                    1, wxALL | wxGROW, 4)
1083                EVT_BUTTON(self, ID_SELPROP_FILLCLRTRANS,
1084                           self._OnChangeFillColorTrans)
1085                ctrlBox.Add(fillColorBox, 0,
1086                            wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)
1087    
1088          spinBox = wxBoxSizer(wxHORIZONTAL)          spinBox = wxBoxSizer(wxHORIZONTAL)
1089          spinBox.Add(wxStaticText(self, -1, _("Line Width: ")),          spinBox.Add(wxStaticText(self, -1, _("Line Width: ")),
# Line 815  class SelectPropertiesDialog(wxDialog): Line 1101  class SelectPropertiesDialog(wxDialog):
1101          itemBox.Add(ctrlBox, 0, wxALIGN_RIGHT | wxALL | wxGROW, 0)          itemBox.Add(ctrlBox, 0, wxALIGN_RIGHT | wxALL | wxGROW, 0)
1102          topBox.Add(itemBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)          topBox.Add(itemBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)
1103    
   
1104          #          #
1105          # Control buttons:          # Control buttons:
1106          #          #
1107          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wxBoxSizer(wxHORIZONTAL)
1108          buttonBox.Add(wxButton(self, ID_CLASSIFY_OK, _("OK")),          buttonBox.Add(wxButton(self, ID_SELPROP_OK, _("OK")),
1109                        0, wxALL, 4)                        0, wxALL, 4)
1110          buttonBox.Add(wxButton(self, ID_CLASSIFY_CANCEL, _("Cancel")),          buttonBox.Add(wxButton(self, ID_SELPROP_CANCEL, _("Cancel")),
1111                        0, wxALL, 4)                        0, wxALL, 4)
1112          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)          topBox.Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 10)
1113                                                                                                                                                                    
1114          EVT_BUTTON(self, ID_SELPROP_OK, self._OnOK)          EVT_BUTTON(self, ID_SELPROP_OK, self._OnOK)
1115          EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)          EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)
1116                                                                                                                                                                    
1117          self.SetAutoLayout(true)          self.SetAutoLayout(True)
1118          self.SetSizer(topBox)          self.SetSizer(topBox)
1119          topBox.Fit(self)          topBox.Fit(self)
1120          topBox.SetSizeHints(self)          topBox.SetSizeHints(self)
# Line 842  class SelectPropertiesDialog(wxDialog): Line 1127  class SelectPropertiesDialog(wxDialog):
1127    
1128      def _OnSpin(self, event):      def _OnSpin(self, event):
1129          self.prop.SetLineWidth(self.spinCtrl.GetValue())          self.prop.SetLineWidth(self.spinCtrl.GetValue())
1130          self.previewer.Refresh()          self.previewWin.Refresh()
1131    
1132      def __GetColor(self, cur):      def __GetColor(self, cur):
1133          dialog = wxColourDialog(self)          dialog = wxColourDialog(self)
1134          dialog.GetColourData().SetColour(Color2wxColour(cur))          if cur is not Color.None:
1135                dialog.GetColourData().SetColour(Color2wxColour(cur))
1136    
1137          ret = None          ret = None
1138          if dialog.ShowModal() == wxID_OK:          if dialog.ShowModal() == wxID_OK:
1139              ret = wxColour2Color(dialog.GetColourData().GetColour())              ret = wxColour2Color(dialog.GetColourData().GetColour())
# Line 859  class SelectPropertiesDialog(wxDialog): Line 1146  class SelectPropertiesDialog(wxDialog):
1146          clr = self.__GetColor(self.prop.GetLineColor())          clr = self.__GetColor(self.prop.GetLineColor())
1147          if clr is not None:          if clr is not None:
1148              self.prop.SetLineColor(clr)              self.prop.SetLineColor(clr)
1149          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1150    
1151        def _OnChangeLineColorTrans(self, event):
1152            self.prop.SetLineColor(Color.None)
1153            self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1154            
1155      def _OnChangeFillColor(self, event):      def _OnChangeFillColor(self, event):
1156          clr = self.__GetColor(self.prop.GetFill())          clr = self.__GetColor(self.prop.GetFill())
1157          if clr is not None:          if clr is not None:
1158              self.prop.SetFill(clr)              self.prop.SetFill(clr)
1159          self.previewer.Refresh() # XXX: work around, see ClassDataPreviewer          self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1160    
1161        def _OnChangeFillColorTrans(self, event):
1162            self.prop.SetFill(Color.None)
1163            self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
1164    
1165      def GetClassGroupProperties(self):      def GetClassGroupProperties(self):
1166          return self.prop          return self.prop
1167    
1168    
1169  class ClassDataPreviewer(wxWindow):  class ClassDataPreviewWindow(wxWindow):
1170    
1171      def __init__(self, rect, prop, shapeType,      def __init__(self, rect, prop, shapeType,
1172                         parent = None, id = -1, size = wxDefaultSize):                         parent = None, id = -1, size = wxDefaultSize):
1173          if parent is not None:          if parent is not None:
1174              wxWindow.__init__(self, parent, id, size=size)              wxWindow.__init__(self, parent, id, (0, 0), size)
1175              EVT_PAINT(self, self._OnPaint)              EVT_PAINT(self, self._OnPaint)
1176    
1177          self.rect = rect          self.rect = rect
1178    
1179          self.prop = prop          self.prop = prop
1180          self.shapeType = shapeType          self.shapeType = shapeType
1181            self.previewer = ClassDataPreviewer()
1182    
1183      def _OnPaint(self, event):      def _OnPaint(self, event):
1184          dc = wxPaintDC(self)          dc = wxPaintDC(self)
# Line 889  class ClassDataPreviewer(wxWindow): Line 1186  class ClassDataPreviewer(wxWindow):
1186          # XXX: this doesn't seem to be having an effect:          # XXX: this doesn't seem to be having an effect:
1187          dc.DestroyClippingRegion()          dc.DestroyClippingRegion()
1188    
1189          self.Draw(dc, None)          if self.rect is None:
1190                w, h = self.GetSize()
1191                rect = wxRect(0, 0, w, h)
1192            else:
1193                rect = self.rect
1194    
1195            self.previewer.Draw(dc, rect, self.prop, self.shapeType)
1196    
1197    class ClassDataPreviewer:
1198    
1199      def Draw(self, dc, rect, prop = None, shapeType = None):      def Draw(self, dc, rect, prop, shapeType):
1200    
1201          if prop is None: prop = self.prop          assert dc is not None
1202          if shapeType is None: shapeType = self.shapeType          assert isinstance(prop, ClassGroupProperties)
1203    
1204          if rect is None:          if rect is None:
1205              x = y = 0              x = 0
1206              w, h = self.GetClientSizeTuple()              y = 0
1207                w, h = dc.GetSize()
1208          else:          else:
1209              x = rect.GetX()              x = rect.GetX()
1210              y = rect.GetY()              y = rect.GetY()
# Line 928  class ClassDataPreviewer(wxWindow): Line 1234  class ClassDataPreviewer(wxWindow):
1234                             wxPoint(x + w/2, y + h/4*3),                             wxPoint(x + w/2, y + h/4*3),
1235                             wxPoint(x + w, y)])                             wxPoint(x + w, y)])
1236    
1237          elif shapeType == SHAPETYPE_POINT or \          elif shapeType == SHAPETYPE_POINT:
              shapeType == SHAPETYPE_POLYGON:  
1238    
1239              dc.DrawCircle(x + w/2, y + h/2,              dc.DrawCircle(x + w/2, y + h/2,
1240                            (min(w, h) - prop.GetLineWidth())/2)                            (min(w, h) - prop.GetLineWidth())/2)
1241    
1242            elif shapeType == SHAPETYPE_POLYGON:
1243                dc.DrawRectangle(x, y, w, h)
1244    
1245  class ClassRenderer(wxPyGridCellRenderer):  class ClassRenderer(wxPyGridCellRenderer):
1246    
1247      def __init__(self, shapeType):      def __init__(self, shapeType):
1248          wxPyGridCellRenderer.__init__(self)          wxPyGridCellRenderer.__init__(self)
1249          self.previewer = ClassDataPreviewer(None, None, shapeType)          self.shapeType = shapeType
1250            self.previewer = ClassDataPreviewer()
1251    
1252      def Draw(self, grid, attr, dc, rect, row, col, isSelected):      def Draw(self, grid, attr, dc, rect, row, col, isSelected):
1253          data = grid.GetTable().GetValueAsCustom(row, col, None)          data = grid.GetTable().GetClassGroup(row)
1254    
1255          dc.SetClippingRegion(rect.GetX(), rect.GetY(),          dc.SetClippingRegion(rect.GetX(), rect.GetY(),
1256                               rect.GetWidth(), rect.GetHeight())                               rect.GetWidth(), rect.GetHeight())
# Line 951  class ClassRenderer(wxPyGridCellRenderer Line 1260  class ClassRenderer(wxPyGridCellRenderer
1260                           rect.GetWidth(), rect.GetHeight())                           rect.GetWidth(), rect.GetHeight())
1261    
1262          if not isinstance(data, ClassGroupMap):          if not isinstance(data, ClassGroupMap):
1263              self.previewer.Draw(dc, rect, data.GetProperties())              self.previewer.Draw(dc, rect, data.GetProperties(), self.shapeType)
1264    
1265          if isSelected:          if isSelected:
1266              dc.SetPen(wxPen(wxColour(0 * 255, 0 * 255, 0 * 255),              dc.SetPen(wxPen(wxColour(0 * 255, 0 * 255, 0 * 255),

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26