/[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 2386 by jan, Thu Oct 7 14:43:45 2004 UTC revision 2700 by dpinte, Mon Sep 18 14:27:02 2006 UTC
# Line 1  Line 1 
1  # Copyright (c) 2003-2004 by Intevation GmbH  # Copyright (c) 2003-2005 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jan-Oliver Wagner <[email protected]> (2003-2004)  # Jan-Oliver Wagner <[email protected]> (2003-2004)
4  # Martin Schulze <[email protected]> (2004)  # Martin Schulze <[email protected]> (2004)
5  # Frank Koormann <[email protected]> (2003)  # Frank Koormann <[email protected]> (2003, 2006)
6  # Bernhard Herzog <[email protected]> (2003)  # Bernhard Herzog <[email protected]> (2003)
7  # Jonathan Coles <[email protected]> (2003)  # Jonathan Coles <[email protected]> (2003)
8  #  #
# Line 16  __version__ = "$Revision$" Line 16  __version__ = "$Revision$"
16  # $Id$  # $Id$
17    
18  import copy  import copy
19    import re
20    
21  from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \  from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
22       FIELDTYPE_STRING       FIELDTYPE_STRING
23    
24  from wxPython.wx import *  import wx
25  from wxPython.grid import *  from wx import grid
26    
27  from Thuban import _  from Thuban import _
28  from Thuban.UI.common import Color2wxColour, wxColour2Color  from Thuban.UI.common import Color2wxColour, wxColour2Color
# Line 30  from Thuban.Model.messages import MAP_LA Line 31  from Thuban.Model.messages import MAP_LA
31  from Thuban.Model.range import Range  from Thuban.Model.range import Range
32  from Thuban.Model.classification import \  from Thuban.Model.classification import \
33      Classification, ClassGroupDefault, \      Classification, ClassGroupDefault, \
34      ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \      ClassGroupSingleton, ClassGroupPattern, ClassGroupRange, ClassGroupMap, \
35      ClassGroupProperties      ClassGroupProperties
36    
37  from Thuban.Model.color import Transparent  from Thuban.Model.color import Transparent
38    
39  from Thuban.Model.layer import Layer, RasterLayer  from Thuban.Model.layer import Layer
40  from Thuban.Model.data import SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT  from Thuban.Model.data import SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT
41    
42  from Thuban.UI.classgen import ClassGenDialog  from Thuban.UI.classgen import ClassGenDialog
43  from Thuban.UI.colordialog import ColorDialog  from Thuban.UI.colordialog import ColorDialog
44    
45  from dialogs import NonModalNonParentDialog  from Thuban.UI.layerproperties import LayerProperties
46  from messages import MAP_REPLACED  from messages import MAP_REPLACED
47    
 ID_CLASS_TABLE = 40011  
   
48    
49  # table columns  # table columns
50  COL_VISIBLE = 0  COL_VISIBLE = 0
# Line 64  FIELD_NAME = 2 Line 63  FIELD_NAME = 2
63  # passed into SetTable is the same that is returned by GetTable  # passed into SetTable is the same that is returned by GetTable
64  #  #
65  import weakref  import weakref
66  class ClassGrid(wxGrid):  class ClassGrid(grid.Grid):
67    
68    
69      def __init__(self, parent, classifier):      def __init__(self, parent, classifier):
# Line 75  class ClassGrid(wxGrid): Line 74  class ClassGrid(wxGrid):
74          clazz -- the working classification that this grid should          clazz -- the working classification that this grid should
75                   use for display.                   use for display.
76          """          """
77            grid.Grid.__init__(self, parent, -1, style = 0)
         wxGrid.__init__(self, parent, ID_CLASS_TABLE, style = 0)  
78    
79          self.classifier = classifier          self.classifier = classifier
80    
81          self.currentSelection = []          self.currentSelection = []
82    
83          EVT_GRID_CELL_LEFT_DCLICK(self, self._OnCellDClick)          self.Bind(grid.EVT_GRID_CELL_LEFT_DCLICK, self._OnCellDClick)
84          EVT_GRID_RANGE_SELECT(self, self._OnSelectedRange)          self.Bind(grid.EVT_GRID_RANGE_SELECT, self._OnSelectedRange)
85          EVT_GRID_SELECT_CELL(self, self._OnSelectedCell)          self.Bind(grid.EVT_GRID_SELECT_CELL, self._OnSelectedCell)
86          EVT_GRID_COL_SIZE(self, self._OnCellResize)          self.Bind(grid.EVT_GRID_COL_SIZE, self._OnCellResize)
87          EVT_GRID_ROW_SIZE(self, self._OnCellResize)          self.Bind(grid.EVT_GRID_ROW_SIZE, self._OnCellResize)
88            self.Bind(grid.EVT_GRID_LABEL_RIGHT_CLICK, self._OnLabelRightClicked)
89    
90    
91      #def GetCellAttr(self, row, col):      #def GetCellAttr(self, row, col):
92          #print "GetCellAttr ", row, col          #print "GetCellAttr ", row, col
93          #wxGrid.GetCellAttr(self, row, col)          #Grid.GetCellAttr(self, row, col)
94    
95      def CreateTable(self, clazz, fieldType, shapeType, group = None):      def CreateTable(self, clazz, fieldType, shapeType, group = None):
96    
# Line 99  class ClassGrid(wxGrid): Line 99  class ClassGrid(wxGrid):
99          table = self.GetTable()          table = self.GetTable()
100          if table is None:          if table is None:
101              w = self.GetDefaultColSize() * NUM_COLS \              w = self.GetDefaultColSize() * NUM_COLS \
102                  + self.GetDefaultRowLabelSize()                  + self.GetDefaultRowLabelSize()
103              h = self.GetDefaultRowSize() * 4 \              h = self.GetDefaultRowSize() * 4 \
104                  + self.GetDefaultColLabelSize()                  + self.GetDefaultColLabelSize()
105    
# Line 109  class ClassGrid(wxGrid): Line 109  class ClassGrid(wxGrid):
109              self.SetTable(table, True)              self.SetTable(table, True)
110    
111    
112          self.SetSelectionMode(wxGrid.wxGridSelectRows)          self.SetSelectionMode(grid.Grid.wxGridSelectRows)
113          self.ClearSelection()          self.ClearSelection()
114    
115          table.Reset(clazz, fieldType, shapeType, group)          table.Reset(clazz, fieldType, shapeType, group)
# Line 135  class ClassGrid(wxGrid): Line 135  class ClassGrid(wxGrid):
135      #      #
136      def SetTable(self, object, *attributes):      def SetTable(self, object, *attributes):
137          self.tableRef = weakref.ref(object)          self.tableRef = weakref.ref(object)
138          return wxGrid.SetTable(self, object, *attributes)          return grid.Grid.SetTable(self, object, *attributes)
139    
140      def GetTable(self):      def GetTable(self):
141          try:          try:
# Line 145  class ClassGrid(wxGrid): Line 145  class ClassGrid(wxGrid):
145    
146      def DeleteSelectedRows(self):      def DeleteSelectedRows(self):
147          """Deletes all highlighted rows.          """Deletes all highlighted rows.
148      
149          If only one row is highlighted then after it is deleted the          If only one row is highlighted then after it is deleted the
150          row that was below the deleted row is highlighted."""          row that was below the deleted row is highlighted."""
151    
152          sel = self.GetCurrentSelection()          sel = self.GetCurrentSelection()
153    
154          # nothing to do          # nothing to do
155          if len(sel) == 0: return          if len(sel) == 0: return
156    
157          # if only one thing is selected check if it is the default          # if only one thing is selected check if it is the default
158          # data row, because we can't remove that          # data row, because we can't remove that
# Line 160  class ClassGrid(wxGrid): Line 160  class ClassGrid(wxGrid):
160              #group = self.GetTable().GetValueAsCustom(sel[0], COL_SYMBOL, None)              #group = self.GetTable().GetValueAsCustom(sel[0], COL_SYMBOL, None)
161              group = self.GetTable().GetClassGroup(sel[0])              group = self.GetTable().GetClassGroup(sel[0])
162              if isinstance(group, ClassGroupDefault):              if isinstance(group, ClassGroupDefault):
163                  wxMessageDialog(self,                  wx.MessageDialog(self,
164                                  "The Default group cannot be removed.",                                  _("The Default group cannot be removed."),
165                                  style = wxOK | wxICON_EXCLAMATION).ShowModal()                                  style = wx.OK | wx.ICON_EXCLAMATION).ShowModal()
166                  return                  return
167            
168    
169          self.ClearSelection()          self.ClearSelection()
170    
# Line 189  class ClassGrid(wxGrid): Line 189  class ClassGrid(wxGrid):
189              if r > self.GetNumberRows() - 1:              if r > self.GetNumberRows() - 1:
190                  r = self.GetNumberRows() - 1                  r = self.GetNumberRows() - 1
191              self.SelectRow(r)              self.SelectRow(r)
192            
193    
194      def SelectGroup(self, group, makeVisible = True):      def SelectGroup(self, group, makeVisible = True):
195          if group is None: return          if group is None: return
196    
197          assert isinstance(group, ClassGroup)          assert isinstance(group, ClassGroup)
198    
199          table = self.GetTable()          table = self.GetTable()
200    
201          assert table is not None          assert table is not None
202    
203          for i in range(table.GetNumberRows()):          for i in range(table.GetNumberRows()):
204              g = table.GetClassGroup(i)              g = table.GetClassGroup(i)
# Line 213  class ClassGrid(wxGrid): Line 213  class ClassGrid(wxGrid):
213  #  #
214  #   def DeselectRow(self, row):  #   def DeselectRow(self, row):
215  #       self.ProcessEvent(  #       self.ProcessEvent(
216  #           wxGridRangeSelectEvent(-1,  #           GridRangeSelectEvent(-1,
217  #                                  wxEVT_GRID_RANGE_SELECT,  #                                  wxEVT_GRID_RANGE_SELECT,
218  #                                  self,  #                                  self,
219  #                                  (row, row), (row, row),  #                                  (row, row), (row, row),
# Line 235  class ClassGrid(wxGrid): Line 235  class ClassGrid(wxGrid):
235      # from http://wiki.wxpython.org to keep track of which      # from http://wiki.wxpython.org to keep track of which
236      # cells are currently highlighted      # cells are currently highlighted
237      #      #
238      def _OnSelectedRange(self, event):      def _OnSelectedRange(self, event):
239          """Internal update to the selection tracking list"""          """Internal update to the selection tracking list"""
240          if event.Selecting():          if event.Selecting():
241              for index in range( event.GetTopRow(), event.GetBottomRow()+1):              for index in range( event.GetTopRow(), event.GetBottomRow()+1):
242                  if index not in self.currentSelection:                  if index not in self.currentSelection:
243                      self.currentSelection.append( index )                      self.currentSelection.append( index )
244          else:          else:
245              for index in range( event.GetTopRow(), event.GetBottomRow()+1):              for index in range( event.GetTopRow(), event.GetBottomRow()+1):
246                  while index in self.currentSelection:                  while index in self.currentSelection:
247                      self.currentSelection.remove( index )                      self.currentSelection.remove( index )
248          #self.ConfigureForSelection()          #self.ConfigureForSelection()
249    
250          event.Skip()          event.Skip()
251    
252      def _OnSelectedCell( self, event ):      def _OnSelectedCell( self, event ):
253          """Internal update to the selection tracking list"""          """Internal update to the selection tracking list"""
254          self.currentSelection = [ event.GetRow() ]          self.currentSelection = [ event.GetRow() ]
255          #self.ConfigureForSelection()          #self.ConfigureForSelection()
256          event.Skip()          event.Skip()
257    
258      def _OnCellResize(self, event):      def _OnCellResize(self, event):
259          self.FitInside()          self.FitInside()
260          event.Skip()          event.Skip()
261    
262  class ClassTable(wxPyGridTableBase):      def _OnLabelRightClicked(self, event):
263            """Process right click on label, raise popup for row labels."""
264            row, col = event.GetRow(), event.GetCol()
265            if col == -1:
266                self.labelPopup(event, row)
267    
268        def labelPopup(self, event, row):
269            """Raise grid label popup."""
270            # check if row label is Pattern or Singleton
271            label = self.GetRowLabelValue(row)
272            if (label == _("Pattern") or label == _("Singleton")):
273                xe,ye = event.GetPosition()
274                x=self.GetRowSize(row)/2
275                menu = wx.Menu()
276                patternID = wx.NewId()
277                singletonID = wx.NewId()
278    
279                def _SetSingleton(event, self=self, row=row):
280                    table = self.GetTable()
281                    group = table.clazz.GetGroup(row - 1)
282                    if not isinstance(group, ClassGroupSingleton):
283                        ngroup = ClassGroupSingleton(
284                                    group.GetPattern(),
285                                    group.GetProperties(),
286                                    group.GetLabel()
287                                    )
288                        table.SetClassGroup(row, ngroup)
289    
290                def _SetPattern(event, self=self, row=row):
291                    table = self.GetTable()
292                    group = table.clazz.GetGroup(row - 1)
293                    if not isinstance(group, ClassGroupPattern):
294                        try:
295                            re.compile(group.GetValue())
296                        except:
297                            pass
298                        else:
299                            ngroup = ClassGroupPattern(
300                                    group.GetValue(),
301                                    group.GetProperties(),
302                                    group.GetLabel()
303                                    )
304                            table.SetClassGroup(row, ngroup)
305    
306                menu.Append(singletonID, _("Singleton"))
307                self.Bind(wx.EVT_MENU, _SetSingleton, id=singletonID)
308                if self.GetTable().fieldType == FIELDTYPE_STRING:
309                    menu.Append(patternID, _("Pattern"))
310                    self.Bind(wx.EVT_MENU, _SetPattern, id=patternID)
311                self.PopupMenu(menu, wx.Point(x,ye))
312                menu.Destroy()
313    
314    class ClassTable(grid.PyGridTableBase):
315      """Represents the underlying data structure for the grid."""      """Represents the underlying data structure for the grid."""
316    
317      __col_labels = [_("Visible"), _("Symbol"), _("Value"), _("Label")]      __col_labels = [_("Visible"), _("Symbol"), _("Value"), _("Label")]
# Line 270  class ClassTable(wxPyGridTableBase): Line 322  class ClassTable(wxPyGridTableBase):
322    
323          shapeType -- the type of shape that the layer uses          shapeType -- the type of shape that the layer uses
324    
325          view -- a wxGrid object that uses this class for its table          view -- a Grid object that uses this class for its table
326          """          """
327    
328          wxPyGridTableBase.__init__(self)          grid.PyGridTableBase.__init__(self)
329    
330          assert len(ClassTable.__col_labels) == NUM_COLS          assert len(ClassTable.__col_labels) == NUM_COLS
331    
# Line 296  class ClassTable(wxPyGridTableBase): Line 348  class ClassTable(wxPyGridTableBase):
348          shapeType -- the type of shape that the layer uses          shapeType -- the type of shape that the layer uses
349          """          """
350    
351          assert isinstance(clazz, Classification)          assert isinstance(clazz, Classification)
352    
353          self.GetView().BeginBatch()          self.GetView().BeginBatch()
354    
# Line 308  class ClassTable(wxPyGridTableBase): Line 360  class ClassTable(wxPyGridTableBase):
360    
361          self.__colAttr = {}          self.__colAttr = {}
362    
363          attr = wxGridCellAttr()          attr = grid.GridCellAttr()
364          attr.SetEditor(wxGridCellBoolEditor())          attr.SetEditor(grid.GridCellBoolEditor())
365          attr.SetRenderer(wxGridCellBoolRenderer())          attr.SetRenderer(grid.GridCellBoolRenderer())
366          attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER)          attr.SetAlignment(wx.ALIGN_CENTER, wx.ALIGN_CENTER)
367          self.__colAttr[COL_VISIBLE] = attr          self.__colAttr[COL_VISIBLE] = attr
368    
369          attr = wxGridCellAttr()          attr = grid.GridCellAttr()
370          attr.SetRenderer(ClassRenderer(self.shapeType))          attr.SetRenderer(ClassRenderer(self.shapeType))
371          attr.SetReadOnly()          attr.SetReadOnly()
372          self.__colAttr[COL_SYMBOL] = attr          self.__colAttr[COL_SYMBOL] = attr
# Line 362  class ClassTable(wxPyGridTableBase): Line 414  class ClassTable(wxPyGridTableBase):
414          # rows and columns          # rows and columns
415          #          #
416          if newRows > curRows:          if newRows > curRows:
417              msg = wxGridTableMessage(self,              msg = grid.GridTableMessage(self,
418                          wxGRIDTABLE_NOTIFY_ROWS_APPENDED,                          grid.GRIDTABLE_NOTIFY_ROWS_APPENDED,
419                          newRows - curRows)    # how many                          newRows - curRows)    # how many
420              self.GetView().ProcessTableMessage(msg)              self.GetView().ProcessTableMessage(msg)
421              self.GetView().FitInside()              self.GetView().FitInside()
422          elif newRows < curRows:          elif newRows < curRows:
423              msg = wxGridTableMessage(self,              msg = grid.GridTableMessage(self,
424                          wxGRIDTABLE_NOTIFY_ROWS_DELETED,                          grid.GRIDTABLE_NOTIFY_ROWS_DELETED,
425                          curRows,              # position                          curRows,              # position
426                          curRows - newRows)    # how many                          curRows - newRows)    # how many
427              self.GetView().ProcessTableMessage(msg)              self.GetView().ProcessTableMessage(msg)
# Line 412  class ClassTable(wxPyGridTableBase): Line 464  class ClassTable(wxPyGridTableBase):
464              group = self.clazz.GetGroup(row - 1)              group = self.clazz.GetGroup(row - 1)
465              if isinstance(group, ClassGroupDefault):   return _("Default")              if isinstance(group, ClassGroupDefault):   return _("Default")
466              if isinstance(group, ClassGroupSingleton): return _("Singleton")              if isinstance(group, ClassGroupSingleton): return _("Singleton")
467                if isinstance(group, ClassGroupPattern):   return _("Pattern")
468              if isinstance(group, ClassGroupRange):     return _("Range")              if isinstance(group, ClassGroupRange):     return _("Range")
469              if isinstance(group, ClassGroupMap):       return _("Map")              if isinstance(group, ClassGroupMap):       return _("Map")
470    
# Line 469  class ClassTable(wxPyGridTableBase): Line 522  class ClassTable(wxPyGridTableBase):
522              return group.GetLabel()              return group.GetLabel()
523    
524          # col must be COL_VALUE          # col must be COL_VALUE
525          assert col == COL_VALUE          assert col == COL_VALUE
526    
527          if isinstance(group, ClassGroupDefault):          if isinstance(group, ClassGroupDefault):
528              return _("DEFAULT")              return _("DEFAULT")
529          elif isinstance(group, ClassGroupSingleton):          elif isinstance(group, ClassGroupSingleton):
530              return group.GetValue()              return group.GetValue()
531            elif isinstance(group, ClassGroupPattern):
532                return group.GetPattern()
533          elif isinstance(group, ClassGroupRange):          elif isinstance(group, ClassGroupRange):
534              return group.GetRange()              return group.GetRange()
535    
# Line 486  class ClassTable(wxPyGridTableBase): Line 541  class ClassTable(wxPyGridTableBase):
541             (string, number, or range)             (string, number, or range)
542    
543          Returns a tuple (type, data) where type is 0 if data is          Returns a tuple (type, data) where type is 0 if data is
544          a singleton value, or 1 if is a range          a singleton value, 1 if is a range or 2 if it is a pattern.
545          """          """
546    
547          type = self.fieldType          type = self.fieldType
548    
549          if type == FIELDTYPE_STRING:          if type == FIELDTYPE_STRING:
550              return (0, value)              # Approach: if we can compile the value as an expression,
551                # make it a pattern, else a singleton.
552                # This is quite crude, however I don't have a better idea:
553                # How to distinct the singleton "Thuban" from the pattern "Thuban"?
554                try:
555                    re.compile(value)
556                except:
557                    return (0, value)
558                else:
559                    return (2, value)
560          elif type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):          elif type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
561              if type == FIELDTYPE_INT:              if type == FIELDTYPE_INT:
562                  # the float call allows the user to enter 1.0 for 1                  # the float call allows the user to enter 1.0 for 1
# Line 526  class ClassTable(wxPyGridTableBase): Line 590  class ClassTable(wxPyGridTableBase):
590          typeName -- unused, but needed to overload wxPyGridTableBase          typeName -- unused, but needed to overload wxPyGridTableBase
591          """          """
592    
593          assert 0 <= col < self.GetNumberCols()          assert 0 <= col < self.GetNumberCols()
594          assert 0 <= row < self.GetNumberRows()          assert 0 <= row < self.GetNumberRows()
595    
596          if row == 0:          if row == 0:
597              group = self.clazz.GetDefaultGroup()              group = self.clazz.GetDefaultGroup()
# Line 576  class ClassTable(wxPyGridTableBase): Line 640  class ClassTable(wxPyGridTableBase):
640                              ngroup = ClassGroupRange(props = props)                              ngroup = ClassGroupRange(props = props)
641                              changed = True                              changed = True
642                          ngroup.SetRange(dataInfo[1])                          ngroup.SetRange(dataInfo[1])
643                        elif dataInfo[0] == 2:
644                            if not isinstance(group, ClassGroupPattern):
645                                ngroup = ClassGroupPattern(props = props)
646                                changed = True
647                            ngroup.SetPattern(dataInfo[1])
648                      else:                      else:
649                          assert False                          assert False
650                          pass                          pass
# Line 594  class ClassTable(wxPyGridTableBase): Line 663  class ClassTable(wxPyGridTableBase):
663      def GetAttr(self, row, col, someExtraParameter):      def GetAttr(self, row, col, someExtraParameter):
664          """Returns the cell attributes"""          """Returns the cell attributes"""
665    
666          return self.__colAttr.get(col, wxGridCellAttr()).Clone()          return self.__colAttr.get(col, grid.GridCellAttr()).Clone()
667    
668      def GetClassGroup(self, row):      def GetClassGroup(self, row):
669          """Return the ClassGroup object representing row 'row'."""          """Return the ClassGroup object representing row 'row'."""
# Line 635  class ClassTable(wxPyGridTableBase): Line 704  class ClassTable(wxPyGridTableBase):
704          The table is considered modified if any rows are removed.          The table is considered modified if any rows are removed.
705          """          """
706    
707          assert pos >= 0          assert pos >= 0
708          old_len = self.GetNumberRows()          old_len = self.GetNumberRows()
709          for row in range(pos, pos - numRows, -1):          for row in range(pos, pos - numRows, -1):
710              group = self.GetClassGroup(row)              group = self.GetClassGroup(row)
711              if row != 0:              if row != 0:
712                  self.clazz.RemoveGroup(row - 1)                  self.clazz.RemoveGroup(row - 1)
713                  self.__Modified()                  self.__Modified()
714        
715          if self.IsModified():          if self.IsModified():
716              self.__NotifyRowChanges(old_len, self.GetNumberRows())              self.__NotifyRowChanges(old_len, self.GetNumberRows())
717    
# Line 684  EB_LAYER_TITLE = 0 Line 753  EB_LAYER_TITLE = 0
753  EB_SELECT_FIELD = 1  EB_SELECT_FIELD = 1
754  EB_GEN_CLASS = 2  EB_GEN_CLASS = 2
755    
756  class Classifier(NonModalNonParentDialog):  class Classifier(LayerProperties):
757    
758      type2string = {None:             _("None"),      type2string = {None:             _("None"),
759                     FIELDTYPE_STRING: _("Text"),                     FIELDTYPE_STRING: _("Text"),
# Line 697  class Classifier(NonModalNonParentDialog Line 766  class Classifier(NonModalNonParentDialog
766          group in the classification table.          group in the classification table.
767          """          """
768    
769          NonModalNonParentDialog.__init__(self, parent, name, "")          LayerProperties.__init__(self, parent, name, layer)
   
         self.__SetTitle(layer.Title())  
   
         self.parent.Subscribe(MAP_REPLACED, self.map_replaced)  
         self.layer = layer  
         self.map = parent.Map()  
770    
         self.map.Subscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)  
771          self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,          self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
772                               self.layer_shapestore_replaced)                               self.layer_shapestore_replaced)
773    
774          self.genDlg = None          self.genDlg = None
775            self.group = group
776    
777          ############################          LayerProperties.dialog_layout(self)
778          # Create the controls  
779          #      def dialog_layout(self, panel, panelBox):
780    
781          panel = wxPanel(self, -1)          if self.layer.HasClassification():
782    
783          text_title = wxTextCtrl(panel, ID_PROPERTY_TITLE, layer.Title())              self.fieldTypeText = wx.StaticText(panel, -1, "")
         self.fieldTypeText = wxStaticText(panel, -1, "")  
784    
         if layer.HasClassification():  
785              self.originalClass = self.layer.GetClassification()              self.originalClass = self.layer.GetClassification()
786              self.originalClassField = self.layer.GetClassificationColumn()              self.originalClassField = self.layer.GetClassificationColumn()
787              field = self.originalClassField              field = self.originalClassField
788              fieldType = self.layer.GetFieldType(field)              fieldType = self.layer.GetFieldType(field)
789    
790              table = layer.ShapeStore().Table()              table = self.layer.ShapeStore().Table()
791              #              #
792              # make field choice box              # make field choice box
793              #              #
794              self.fields = wxChoice(panel, ID_PROPERTY_SELECT,)              self.fields = wx.Choice(panel, ID_PROPERTY_SELECT,)
795    
796              self.num_cols = table.NumColumns()              self.num_cols = table.NumColumns()
797              # just assume the first field in case one hasn't been              # just assume the first field in case one hasn't been
798              # specified in the file.              # specified in the file.
799              self.__cur_field = 0              self.__cur_field = 0
800    
801              self.fields.Append("<None>")              self.fields.Append("<None>")
802    
# Line 750  class Classifier(NonModalNonParentDialog Line 811  class Classifier(NonModalNonParentDialog
811    
812                  if name == field:                  if name == field:
813                      self.__cur_field = i + 1                      self.__cur_field = i + 1
814                      self.fields.SetClientData(i + 1,                      self.fields.SetClientData(i + 1,
815                                                copy.deepcopy(self.originalClass))                                                copy.deepcopy(self.originalClass))
816                  else:                  else:
817                      self.fields.SetClientData(i + 1, None)                      self.fields.SetClientData(i + 1, None)
818    
819              button_gen = wxButton(panel, ID_PROPERTY_GENCLASS,              button_gen = wx.Button(panel, ID_PROPERTY_GENCLASS,
820                  _("Generate Class"))                  _("Generate Class"))
821              button_add = wxButton(panel, ID_PROPERTY_ADD,              button_add = wx.Button(panel, ID_PROPERTY_ADD,
822                  _("Add"))                  _("Add"))
823              button_moveup = wxButton(panel, ID_PROPERTY_MOVEUP,              button_moveup = wx.Button(panel, ID_PROPERTY_MOVEUP,
824                  _("Move Up"))                  _("Move Up"))
825              button_movedown = wxButton(panel, ID_PROPERTY_MOVEDOWN,              button_movedown = wx.Button(panel, ID_PROPERTY_MOVEDOWN,
826                  _("Move Down"))                  _("Move Down"))
827              button_edit = wxButton(panel, ID_PROPERTY_EDITSYM,              button_edit = wx.Button(panel, ID_PROPERTY_EDITSYM,
828                  _("Edit Symbol"))                  _("Edit Symbol"))
829              button_remove = wxButton(panel, ID_PROPERTY_REMOVE,              button_remove = wx.Button(panel, ID_PROPERTY_REMOVE,
830                  _("Remove"))                  _("Remove"))
831    
832              self.classGrid = ClassGrid(panel, self)              self.classGrid = ClassGrid(panel, self)
# Line 773  class Classifier(NonModalNonParentDialog Line 834  class Classifier(NonModalNonParentDialog
834              # calling __SelectField after creating the classGrid fills in the              # calling __SelectField after creating the classGrid fills in the
835              # grid with the correct information              # grid with the correct information
836              self.fields.SetSelection(self.__cur_field)              self.fields.SetSelection(self.__cur_field)
837              self.__SelectField(self.__cur_field, group = group)              self.__SelectField(self.__cur_field, group = self.group)
838    
         button_try = wxButton(self, ID_PROPERTY_TRY, _("Try"))  
         button_revert = wxButton(self, ID_PROPERTY_REVERT, _("Revert"))  
         button_ok = wxButton(self, wxID_OK, _("OK"))  
         button_close = wxButton(self, wxID_CANCEL, _("Close"))  
         button_ok.SetDefault()  
   
         ############################  
         # Layout the controls  
         #  
   
         topBox = wxBoxSizer(wxVERTICAL)  
         panelBox = wxBoxSizer(wxVERTICAL)  
   
         sizer = wxBoxSizer(wxHORIZONTAL)  
         sizer.Add(wxStaticText(panel, -1, _("Title: ")),  
             0, wxALIGN_LEFT | wxALL | wxALIGN_CENTER_VERTICAL, 4)  
         sizer.Add(text_title, 1, wxGROW, 0)  
   
         panelBox.Add(sizer, 0, wxGROW, 4)  
   
         if isinstance(layer, RasterLayer):  
             type = "Image"  
         else:  
             type = layer.ShapeType()  
839    
840          panelBox.Add(wxStaticText(panel, -1, _("Type: %s") % type),              classBox = wx.StaticBoxSizer(
841              0, wxALIGN_LEFT | wxALL, 4)                          wx.StaticBox(panel, -1, _("Classification")), wx.VERTICAL)
842    
         if layer.HasClassification():  
843    
844              classBox = wxStaticBoxSizer(              sizer = wx.BoxSizer(wx.HORIZONTAL)
845                          wxStaticBox(panel, -1, _("Classification")), wxVERTICAL)              sizer.Add(wx.StaticText(panel, ID_PROPERTY_FIELDTEXT, _("Field: ")),
846                    0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 4)
847                sizer.Add(self.fields, 1, wx.GROW | wx.ALL, 4)
848    
849                classBox.Add(sizer, 0, wx.GROW, 4)
850    
851              sizer = wxBoxSizer(wxHORIZONTAL)              classBox.Add(self.fieldTypeText, 0,
852              sizer.Add(wxStaticText(panel, ID_PROPERTY_FIELDTEXT, _("Field: ")),                          wx.GROW | wx.ALIGN_LEFT | wx.ALL | wx.ADJUST_MINSIZE, 4)
                 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 4)  
             sizer.Add(self.fields, 1, wxGROW | wxALL, 4)  
853    
854              classBox.Add(sizer, 0, wxGROW, 4)              controlBox = wx.BoxSizer(wx.HORIZONTAL)
855                controlButtonBox = wx.BoxSizer(wx.VERTICAL)
856    
857              classBox.Add(self.fieldTypeText, 0,              controlButtonBox.Add(button_gen, 0, wx.GROW|wx.ALL, 4)
858                          wxGROW | wxALIGN_LEFT | wxALL | wxADJUST_MINSIZE, 4)              controlButtonBox.Add(button_add, 0, wx.GROW|wx.ALL, 4)
859                controlButtonBox.Add(button_moveup, 0, wx.GROW|wx.ALL, 4)
860                controlButtonBox.Add(button_movedown, 0, wx.GROW|wx.ALL, 4)
861                controlButtonBox.Add(button_edit, 0, wx.GROW|wx.ALL, 4)
862                controlButtonBox.Add( (60, 20), 0, wx.GROW|wx.ALL|wx.ALIGN_BOTTOM, 4)
863                controlButtonBox.Add(button_remove, 0,
864                                     wx.GROW|wx.ALL|wx.ALIGN_BOTTOM, 4)
865    
866              controlBox = wxBoxSizer(wxHORIZONTAL)              controlBox.Add(self.classGrid, 1, wx.GROW, 0)
867              controlButtonBox = wxBoxSizer(wxVERTICAL)              controlBox.Add(controlButtonBox, 0, wx.GROW, 10)
868    
869              controlButtonBox.Add(button_gen, 0, wxGROW|wxALL, 4)              classBox.Add(controlBox, 1, wx.GROW, 10)
870              controlButtonBox.Add(button_add, 0, wxGROW|wxALL, 4)              panelBox.Add(classBox, 1, wx.GROW, 0)
             controlButtonBox.Add(button_moveup, 0, wxGROW|wxALL, 4)  
             controlButtonBox.Add(button_movedown, 0, wxGROW|wxALL, 4)  
             controlButtonBox.Add(button_edit, 0, wxGROW|wxALL, 4)  
             controlButtonBox.Add(60, 20, 0, wxGROW|wxALL|wxALIGN_BOTTOM, 4)  
             controlButtonBox.Add(button_remove, 0,  
                                  wxGROW|wxALL|wxALIGN_BOTTOM, 4)  
871    
             controlBox.Add(self.classGrid, 1, wxGROW, 0)  
             controlBox.Add(controlButtonBox, 0, wxGROW, 10)  
872    
873              classBox.Add(controlBox, 1, wxGROW, 10)          self.Bind(wx.EVT_CHOICE, self._OnFieldSelect, id=ID_PROPERTY_SELECT)
874              panelBox.Add(classBox, 1, wxGROW, 0)          self.Bind(wx.EVT_BUTTON, self._OnAdd, id=ID_PROPERTY_ADD)
875            self.Bind(wx.EVT_BUTTON, self._OnEditSymbol, id=ID_PROPERTY_EDITSYM)
876            self.Bind(wx.EVT_BUTTON, self._OnRemove, id=ID_PROPERTY_REMOVE)
877          buttonBox = wxBoxSizer(wxHORIZONTAL)          self.Bind(wx.EVT_BUTTON, self._OnGenClass, id=ID_PROPERTY_GENCLASS)
878          buttonBox.Add(button_try, 0, wxRIGHT|wxEXPAND, 10)          self.Bind(wx.EVT_BUTTON, self._OnMoveUp, id=ID_PROPERTY_MOVEUP)
879          buttonBox.Add(button_revert, 0, wxRIGHT|wxEXPAND, 10)          self.Bind(wx.EVT_BUTTON, self._OnMoveDown, id=ID_PROPERTY_MOVEDOWN)
         buttonBox.Add(button_ok, 0, wxRIGHT|wxEXPAND, 10)  
         buttonBox.Add(button_close, 0, wxRIGHT|wxEXPAND, 10)  
   
         panel.SetAutoLayout(True)  
         panel.SetSizer(panelBox)  
         panelBox.Fit(panel)  
         panelBox.SetSizeHints(panel)  
   
         topBox.Add(panel, 1, wxGROW | wxALL, 4)  
         topBox.Add(buttonBox, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)  
   
         self.SetAutoLayout(True)  
         self.SetSizer(topBox)  
         topBox.Fit(self)  
         topBox.SetSizeHints(self)  
         self.Layout()  
   
         ###########  
   
         EVT_CHOICE(self, ID_PROPERTY_SELECT, self._OnFieldSelect)  
         EVT_TEXT(self, ID_PROPERTY_TITLE, self._OnTitleChanged)  
         EVT_BUTTON(self, wxID_OK, self._OnOK)  
         EVT_BUTTON(self, ID_PROPERTY_TRY, self._OnTry)  
         EVT_BUTTON(self, wxID_CANCEL, self._OnCloseBtn)  
         EVT_BUTTON(self, ID_PROPERTY_REVERT, self._OnRevert)  
   
         EVT_BUTTON(self, ID_PROPERTY_ADD, self._OnAdd)  
         EVT_BUTTON(self, ID_PROPERTY_EDITSYM, self._OnEditSymbol)  
         EVT_BUTTON(self, ID_PROPERTY_REMOVE, self._OnRemove)  
         EVT_BUTTON(self, ID_PROPERTY_GENCLASS, self._OnGenClass)  
         EVT_BUTTON(self, ID_PROPERTY_MOVEUP, self._OnMoveUp)  
         EVT_BUTTON(self, ID_PROPERTY_MOVEDOWN, self._OnMoveDown)  
   
         ######################  
   
         text_title.SetFocus()  
         self.haveApplied = False  
880    
881      def unsubscribe_messages(self):      def unsubscribe_messages(self):
882          """Unsubscribe from all messages."""          """Unsubscribe from all messages."""
883          self.parent.Unsubscribe(MAP_REPLACED, self.map_replaced)          LayerProperties.unsubscribe_messages(self)
         self.map.Unsubscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)  
884          self.layer.Unsubscribe(LAYER_SHAPESTORE_REPLACED,          self.layer.Unsubscribe(LAYER_SHAPESTORE_REPLACED,
885                                 self.layer_shapestore_replaced)                                 self.layer_shapestore_replaced)
886    
     def map_layers_removed(self, map):  
         """Subscribed to MAP_LAYERS_REMOVED. If this layer was removed,  
         Close self.  
         """  
         if self.layer not in self.map.Layers():  
             self.Close()  
   
887      def layer_shapestore_replaced(self, *args):      def layer_shapestore_replaced(self, *args):
888          """Subscribed to the map's LAYER_SHAPESTORE_REPLACED message.          """Subscribed to the map's LAYER_SHAPESTORE_REPLACED message.
   
889          Close self.          Close self.
890          """          """
891          self.Close()          self.Close()
892    
     def map_replaced(self, *args):  
         """Subscribed to the mainwindow's MAP_REPLACED message. Close self."""  
         self.Close()  
   
893      def EditSymbol(self, row):      def EditSymbol(self, row):
894          """Open up a dialog where the user can select the properties          """Open up a dialog where the user can select the properties
895          for a group.          for a group.
# Line 916  class Classifier(NonModalNonParentDialog Line 902  class Classifier(NonModalNonParentDialog
902          propDlg = SelectPropertiesDialog(self, prop, self.layer.ShapeType())          propDlg = SelectPropertiesDialog(self, prop, self.layer.ShapeType())
903    
904          self.Enable(False)          self.Enable(False)
905          if propDlg.ShowModal() == wxID_OK:          if propDlg.ShowModal() == wx.ID_OK:
906              new_prop = propDlg.GetClassGroupProperties()              new_prop = propDlg.GetClassGroupProperties()
907              table.SetValueAsCustom(row, COL_SYMBOL, None, new_prop)              table.SetValueAsCustom(row, COL_SYMBOL, None, new_prop)
908          self.Enable(True)          self.Enable(True)
# Line 972  class Classifier(NonModalNonParentDialog Line 958  class Classifier(NonModalNonParentDialog
958    
959          fieldName = self.fields.GetString(fieldIndex)          fieldName = self.fields.GetString(fieldIndex)
960          fieldType = self.layer.GetFieldType(fieldName)          fieldType = self.layer.GetFieldType(fieldName)
961                    
962          self.classGrid.CreateTable(clazz, fieldType,          self.classGrid.CreateTable(clazz, fieldType,
963                                     self.layer.ShapeType(), group)                                     self.layer.ShapeType(), group)
964    
965      def __SetFieldTypeText(self, fieldIndex):      def __SetFieldTypeText(self, fieldIndex):
# Line 983  class Classifier(NonModalNonParentDialog Line 969  class Classifier(NonModalNonParentDialog
969          fieldName = self.fields.GetString(fieldIndex)          fieldName = self.fields.GetString(fieldIndex)
970          fieldType = self.layer.GetFieldType(fieldName)          fieldType = self.layer.GetFieldType(fieldName)
971    
972          assert Classifier.type2string.has_key(fieldType)          assert Classifier.type2string.has_key(fieldType)
973    
974          text = Classifier.type2string[fieldType]          text = Classifier.type2string[fieldType]
975    
# Line 1012  class Classifier(NonModalNonParentDialog Line 998  class Classifier(NonModalNonParentDialog
998              title = ": " + title              title = ": " + title
999    
1000          self.SetTitle(_("Layer Properties") + title)          self.SetTitle(_("Layer Properties") + title)
1001    
1002      def _OnEditSymbol(self, event):      def _OnEditSymbol(self, event):
1003          """Open up a dialog for the user to select group properties."""          """Open up a dialog for the user to select group properties."""
1004          sel = self.classGrid.GetCurrentSelection()          sel = self.classGrid.GetCurrentSelection()
# Line 1020  class Classifier(NonModalNonParentDialog Line 1006  class Classifier(NonModalNonParentDialog
1006          if len(sel) == 1:          if len(sel) == 1:
1007              self.EditSymbol(sel[0])              self.EditSymbol(sel[0])
1008    
1009      def _OnFieldSelect(self, event):      def _OnFieldSelect(self, event):
1010          index = self.fields.GetSelection()          index = self.fields.GetSelection()
1011          self.__SelectField(index, self.__cur_field)          self.__SelectField(index, self.__cur_field)
1012          self.__cur_field = index          self.__cur_field = index
1013    
1014      def _OnTry(self, event):      def OnTry(self, event):
1015          """Put the data from the table into a new Classification and hand          """Put the data from the table into a new Classification and hand
1016             it to the layer.             it to the layer.
1017          """          """
# Line 1045  class Classifier(NonModalNonParentDialog Line 1031  class Classifier(NonModalNonParentDialog
1031    
1032          self.haveApplied = True          self.haveApplied = True
1033    
1034      def _OnOK(self, event):      def OnOK(self, event):
1035          self._OnTry(event)          self.OnTry(event)
         self.Close()  
   
     def OnClose(self, event):  
         self.unsubscribe_messages()  
         NonModalNonParentDialog.OnClose(self, event)  
   
     def _OnCloseBtn(self, event):  
         """Close is similar to Cancel except that any changes that were  
         made and applied remain applied, but the currently displayed  
         classification is discarded.  
         """  
   
1036          self.Close()          self.Close()
1037    
1038      def _OnRevert(self, event):      def OnRevert(self, event):
1039          """The layer's current classification stays the same."""          """The layer's current classification stays the same."""
1040          if self.haveApplied:          if self.haveApplied and self.layer.HasClassification():
1041              self.layer.SetClassificationColumn(self.originalClassField)              self.layer.SetClassificationColumn(self.originalClassField)
1042              self.layer.SetClassification(self.originalClass)              self.layer.SetClassification(self.originalClass)
1043    
1044          #self.Close()          #self.Close()
1045    
1046      def _OnAdd(self, event):      def _OnAdd(self, event):
1047          self.classGrid.AppendRows()          self.classGrid.AppendRows()
1048    
1049      def _OnRemove(self, event):      def _OnRemove(self, event):
# Line 1081  class Classifier(NonModalNonParentDialog Line 1055  class Classifier(NonModalNonParentDialog
1055          self.genDlg = ClassGenDialog(self, self.layer,          self.genDlg = ClassGenDialog(self, self.layer,
1056                            self.fields.GetString(self.__cur_field))                            self.fields.GetString(self.__cur_field))
1057    
1058          EVT_CLOSE(self.genDlg, self._OnGenDialogClose)          self.Bind(wx.EVT_CLOSE, self._OnGenDialogClose, self.genDlg)
1059    
1060          self.__EnableButtons(EB_GEN_CLASS)          self.__EnableButtons(EB_GEN_CLASS)
1061    
# Line 1141  class Classifier(NonModalNonParentDialog Line 1115  class Classifier(NonModalNonParentDialog
1115          based on the case provided. Cases are constants beginning with EB_.          based on the case provided. Cases are constants beginning with EB_.
1116          """          """
1117    
1118          list = {wxID_OK                 : True,          list = {wx.ID_OK                 : True,
1119                  wxID_CANCEL             : True,                  wx.ID_CANCEL             : True,
1120                  ID_PROPERTY_ADD         : True,                  ID_PROPERTY_ADD         : True,
1121                  ID_PROPERTY_MOVEUP      : True,                  ID_PROPERTY_MOVEUP      : True,
1122                  ID_PROPERTY_MOVEDOWN    : True,                  ID_PROPERTY_MOVEDOWN    : True,
1123                  ID_PROPERTY_REMOVE      : True,                  ID_PROPERTY_REMOVE      : True,
1124                  ID_PROPERTY_SELECT      : True,                  ID_PROPERTY_SELECT      : True,
1125                  ID_PROPERTY_FIELDTEXT   : True,                  ID_PROPERTY_FIELDTEXT   : True,
1126                  ID_PROPERTY_GENCLASS    : True,                  ID_PROPERTY_GENCLASS    : True,
1127                  ID_PROPERTY_EDITSYM     : True}                  ID_PROPERTY_EDITSYM     : True}
1128    
1129          if case == EB_LAYER_TITLE:            if case == EB_LAYER_TITLE:
1130              if self.layer.Title() == "":              if self.layer.Title() == "":
1131                  list[wxID_OK] = False                  list[wxID_OK] = False
1132                  list[wxID_CANCEL] = False                  list[wxID_CANCEL] = False
# Line 1167  class Classifier(NonModalNonParentDialog Line 1141  class Classifier(NonModalNonParentDialog
1141    
1142          elif case == EB_GEN_CLASS:          elif case == EB_GEN_CLASS:
1143              if self.genDlg is not None:              if self.genDlg is not None:
1144                  list[ID_PROPERTY_SELECT] = False                  list[ID_PROPERTY_SELECT] = False
1145                  list[ID_PROPERTY_FIELDTEXT] = False                  list[ID_PROPERTY_FIELDTEXT] = False
1146                  list[ID_PROPERTY_GENCLASS] = False                  list[ID_PROPERTY_GENCLASS] = False
1147    
1148          for id, enable in list.items():          for id, enable in list.items():
1149              win = self.FindWindowById(id)              win = self.FindWindowById(id)
# Line 1184  ID_SELPROP_STROKECLRTRANS = 4006 Line 1158  ID_SELPROP_STROKECLRTRANS = 4006
1158  ID_SELPROP_FILLCLRTRANS = 4007  ID_SELPROP_FILLCLRTRANS = 4007
1159  ID_SELPROP_SPINCTRL_SIZE = 4008  ID_SELPROP_SPINCTRL_SIZE = 4008
1160    
1161  class SelectPropertiesDialog(wxDialog):  class SelectPropertiesDialog(wx.Dialog):
1162      """Dialog that allows the user to select group properties."""      """Dialog that allows the user to select group properties."""
1163    
1164      def __init__(self, parent, prop, shapeType):      def __init__(self, parent, prop, shapeType):
1165          """Open the dialog with the initial prop properties and shapeType."""          """Open the dialog with the initial prop properties and shapeType."""
1166    
1167          wxDialog.__init__(self, parent, -1, _("Select Properties"),          wx.Dialog.__init__(self, parent, -1, _("Select Properties"),
1168                            style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)                            style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
1169    
1170          self.prop = ClassGroupProperties(prop)          self.prop = ClassGroupProperties(prop)
1171    
1172          topBox = wxBoxSizer(wxVERTICAL)          topBox = wx.BoxSizer(wx.VERTICAL)
1173    
1174          itemBox = wxBoxSizer(wxHORIZONTAL)          itemBox = wx.BoxSizer(wx.HORIZONTAL)
1175    
1176          # preview box          # preview box
1177          previewBox = wxBoxSizer(wxVERTICAL)          previewBox = wx.BoxSizer(wx.VERTICAL)
1178          previewBox.Add(wxStaticText(self, -1, _("Preview:")),          previewBox.Add(wx.StaticText(self, -1, _("Preview:")),
1179              0, wxALIGN_LEFT | wxALL, 4)              0, wx.ALIGN_LEFT | wx.ALL, 4)
1180    
1181          self.previewWin = ClassGroupPropertiesCtrl(          self.previewWin = ClassGroupPropertiesCtrl(
1182              self, ID_SELPROP_PREVIEW, self.prop, shapeType,              self, ID_SELPROP_PREVIEW, self.prop, shapeType,
1183              (40, 40), wxSIMPLE_BORDER)              (40, 40), wx.SIMPLE_BORDER)
1184    
1185          self.previewWin.AllowEdit(False)          self.previewWin.AllowEdit(False)
1186    
1187          previewBox.Add(self.previewWin, 1, wxGROW | wxALL, 4)          previewBox.Add(self.previewWin, 1, wx.GROW | wx.ALL, 4)
1188    
1189          itemBox.Add(previewBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)          itemBox.Add(previewBox, 1, wx.ALIGN_LEFT | wx.ALL | wx.GROW, 0)
1190    
1191          # control box          # control box
1192          ctrlBox = wxBoxSizer(wxVERTICAL)          ctrlBox = wx.BoxSizer(wx.VERTICAL)
1193    
1194          lineColorBox = wxBoxSizer(wxHORIZONTAL)          lineColorBox = wx.BoxSizer(wx.HORIZONTAL)
1195          button = wxButton(self, ID_SELPROP_STROKECLR, _("Change Line Color"))          button = wx.Button(self, ID_SELPROP_STROKECLR, _("Change Line Color"))
1196          button.SetFocus()          button.SetFocus()
1197          lineColorBox.Add(button, 1, wxALL | wxGROW, 4)          lineColorBox.Add(button, 1, wx.ALL | wx.GROW, 4)
1198          EVT_BUTTON(self, ID_SELPROP_STROKECLR, self._OnChangeLineColor)          self.Bind(wx.EVT_BUTTON, self._OnChangeLineColor, id=ID_SELPROP_STROKECLR)
1199    
1200          lineColorBox.Add(          lineColorBox.Add(
1201              wxButton(self, ID_SELPROP_STROKECLRTRANS, _("Transparent")),              wx.Button(self, ID_SELPROP_STROKECLRTRANS, _("Transparent")),
1202              1, wxALL | wxGROW, 4)              1, wx.ALL | wx.GROW, 4)
1203          EVT_BUTTON(self, ID_SELPROP_STROKECLRTRANS,          self.Bind(wx.EVT_BUTTON, self._OnChangeLineColorTrans, \
1204                     self._OnChangeLineColorTrans)                                     id=ID_SELPROP_STROKECLRTRANS)
1205    
1206          ctrlBox.Add(lineColorBox, 0,          ctrlBox.Add(lineColorBox, 0,
1207                      wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)                      wx.ALIGN_CENTER_HORIZONTAL | wx.ALL | wx.GROW, 4)
1208    
1209          if shapeType != SHAPETYPE_ARC:          if shapeType != SHAPETYPE_ARC:
1210              fillColorBox = wxBoxSizer(wxHORIZONTAL)              fillColorBox = wx.BoxSizer(wx.HORIZONTAL)
1211              fillColorBox.Add(              fillColorBox.Add(
1212                  wxButton(self, ID_SELPROP_FILLCLR, _("Change Fill Color")),                  wx.Button(self, ID_SELPROP_FILLCLR, _("Change Fill Color")),
1213                  1, wxALL | wxGROW, 4)                  1, wx.ALL | wx.GROW, 4)
1214              EVT_BUTTON(self, ID_SELPROP_FILLCLR, self._OnChangeFillColor)              self.Bind(wx.EVT_BUTTON, self._OnChangeFillColor, id=ID_SELPROP_FILLCLR)
1215              fillColorBox.Add(              fillColorBox.Add(
1216                  wxButton(self, ID_SELPROP_FILLCLRTRANS, _("Transparent")),                  wx.Button(self, ID_SELPROP_FILLCLRTRANS, _("Transparent")),
1217                  1, wxALL | wxGROW, 4)                  1, wx.ALL | wx.GROW, 4)
1218              EVT_BUTTON(self, ID_SELPROP_FILLCLRTRANS,              self.Bind(wx.EVT_BUTTON, self._OnChangeFillColorTrans,\
1219                         self._OnChangeFillColorTrans)                                          id=ID_SELPROP_FILLCLRTRANS)
1220              ctrlBox.Add(fillColorBox, 0,              ctrlBox.Add(fillColorBox, 0,
1221                          wxALIGN_CENTER_HORIZONTAL | wxALL | wxGROW, 4)                          wx.ALIGN_CENTER_HORIZONTAL | wx.ALL | wx.GROW, 4)
1222    
1223          # Line width selection          # Line width selection
1224          spinBox = wxBoxSizer(wxHORIZONTAL)          spinBox = wx.BoxSizer(wx.HORIZONTAL)
1225          spinBox.Add(wxStaticText(self, -1, _("Line Width: ")),          spinBox.Add(wx.StaticText(self, -1, _("Line Width: ")),
1226                  0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 4)                  0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 4)
1227          self.spinCtrl_linewidth = wxSpinCtrl(self,          self.spinCtrl_linewidth = wx.SpinCtrl(self,
1228                                               ID_SELPROP_SPINCTRL_LINEWIDTH,                                               ID_SELPROP_SPINCTRL_LINEWIDTH,
1229                                               min=1, max=10,                                               min=1, max=10,
1230                                               value=str(prop.GetLineWidth()),                                               value=str(prop.GetLineWidth()),
1231                                               initial=prop.GetLineWidth())                                               initial=prop.GetLineWidth())
1232    
1233          EVT_SPINCTRL(self, ID_SELPROP_SPINCTRL_LINEWIDTH,          self.Bind(wx.EVT_SPINCTRL, self._OnSpinLineWidth, \
1234                       self._OnSpinLineWidth)                      id=ID_SELPROP_SPINCTRL_LINEWIDTH)
1235    
1236          spinBox.Add(self.spinCtrl_linewidth, 0, wxALIGN_LEFT | wxALL, 4)          spinBox.Add(self.spinCtrl_linewidth, 0, wx.ALIGN_LEFT | wx.ALL, 4)
1237          ctrlBox.Add(spinBox, 0, wxALIGN_RIGHT | wxALL, 0)          ctrlBox.Add(spinBox, 0, wx.ALIGN_RIGHT | wx.ALL, 0)
1238    
1239          # Size selection          # Size selection
1240          if shapeType == SHAPETYPE_POINT:          if shapeType == SHAPETYPE_POINT:
1241              spinBox = wxBoxSizer(wxHORIZONTAL)              spinBox = wx.BoxSizer(wx.HORIZONTAL)
1242              spinBox.Add(wxStaticText(self, -1, _("Size: ")),              spinBox.Add(wx.StaticText(self, -1, _("Size: ")),
1243                          0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 4)                          0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 4)
1244              self.spinCtrl_size = wxSpinCtrl(self, ID_SELPROP_SPINCTRL_SIZE,              self.spinCtrl_size = wx.SpinCtrl(self, ID_SELPROP_SPINCTRL_SIZE,
1245                                              min=1, max=100,                                              min=1, max=100,
1246                                              value=str(prop.GetSize()),                                              value=str(prop.GetSize()),
1247                                              initial=prop.GetSize())                                              initial=prop.GetSize())
1248    
1249              EVT_SPINCTRL(self, ID_SELPROP_SPINCTRL_SIZE, self._OnSpinSize)              self.Bind(wx.EVT_SPINCTRL, self._OnSpinSize, id=ID_SELPROP_SPINCTRL_SIZE)
1250    
1251              spinBox.Add(self.spinCtrl_size, 0, wxALIGN_LEFT | wxALL, 4)              spinBox.Add(self.spinCtrl_size, 0, wx.ALIGN_LEFT | wx.ALL, 4)
1252              ctrlBox.Add(spinBox, 0, wxALIGN_RIGHT | wxALL, 0)              ctrlBox.Add(spinBox, 0, wx.ALIGN_RIGHT | wx.ALL, 0)
1253    
1254    
1255          itemBox.Add(ctrlBox, 0, wxALIGN_RIGHT | wxALL | wxGROW, 0)          itemBox.Add(ctrlBox, 0, wx.ALIGN_RIGHT | wx.ALL | wx.GROW, 0)
1256          topBox.Add(itemBox, 1, wxALIGN_LEFT | wxALL | wxGROW, 0)          topBox.Add(itemBox, 1, wx.ALIGN_LEFT | wx.ALL | wx.GROW, 0)
1257    
1258          #          #
1259          # Control buttons:          # Control buttons:
1260          #          #
1261          buttonBox = wxBoxSizer(wxHORIZONTAL)          buttonBox = wx.BoxSizer(wx.HORIZONTAL)
1262          button_ok = wxButton(self, wxID_OK, _("OK"))          button_ok = wx.Button(self, wx.ID_OK, _("OK"))
1263          buttonBox.Add(button_ok, 0, wxRIGHT|wxEXPAND, 10)          buttonBox.Add(button_ok, 0, wx.RIGHT|wx.EXPAND, 10)
1264          buttonBox.Add(wxButton(self, wxID_CANCEL, _("Cancel")),          buttonBox.Add(wx.Button(self, wx.ID_CANCEL, _("Cancel")),
1265                        0, wxRIGHT|wxEXPAND, 10)                        0, wx.RIGHT|wx.EXPAND, 10)
1266          topBox.Add(buttonBox, 0, wxALIGN_RIGHT|wxBOTTOM|wxTOP, 10)          topBox.Add(buttonBox, 0, wx.ALIGN_RIGHT|wx.BOTTOM|wx.TOP, 10)
1267    
1268          button_ok.SetDefault()          button_ok.SetDefault()
1269    
# Line 1302  class SelectPropertiesDialog(wxDialog): Line 1276  class SelectPropertiesDialog(wxDialog):
1276          topBox.SetSizeHints(self)          topBox.SetSizeHints(self)
1277    
1278      def OnOK(self, event):      def OnOK(self, event):
1279          self.EndModal(wxID_OK)          self.EndModal(wx.ID_OK)
1280    
1281      def OnCancel(self, event):      def OnCancel(self, event):
1282          self.EndModal(wxID_CANCEL)          self.EndModal(wx.ID_CANCEL)
1283    
1284      def _OnSpinLineWidth(self, event):      def _OnSpinLineWidth(self, event):
1285          self.prop.SetLineWidth(self.spinCtrl_linewidth.GetValue())          self.prop.SetLineWidth(self.spinCtrl_linewidth.GetValue())
# Line 1320  class SelectPropertiesDialog(wxDialog): Line 1294  class SelectPropertiesDialog(wxDialog):
1294          dialog.SetColor(cur)          dialog.SetColor(cur)
1295    
1296          ret = None          ret = None
1297          if dialog.ShowModal() == wxID_OK:          if dialog.ShowModal() == wx.ID_OK:
1298              ret = dialog.GetColor()              ret = dialog.GetColor()
1299    
1300          dialog.Destroy()          dialog.Destroy()
# Line 1351  class SelectPropertiesDialog(wxDialog): Line 1325  class SelectPropertiesDialog(wxDialog):
1325          return self.prop          return self.prop
1326    
1327    
1328  class ClassDataPreviewWindow(wxWindow):  class ClassDataPreviewWindow(wx.Window):
1329      """A custom window that draws group properties using the correct shape."""      """A custom window that draws group properties using the correct shape."""
1330    
1331      def __init__(self, rect, prop, shapeType,      def __init__(self, rect, prop, shapeType,
1332                         parent = None, id = -1, size = wxDefaultSize):                         parent = None, id = -1, size = wx.DefaultSize):
1333          """Draws the appropriate shape as specified with shapeType using          """Draws the appropriate shape as specified with shapeType using
1334          prop properities.          prop properities.
1335          """          """
1336          if parent is not None:          if parent is not None:
1337              wxWindow.__init__(self, parent, id, (0, 0), size)              wx.Window.__init__(self, parent, id, (0, 0), size)
1338              EVT_PAINT(self, self._OnPaint)              self.Bind(wx.EVT_PAINT, self._OnPaint)
1339    
1340          self.rect = rect          self.rect = rect
1341    
# Line 1373  class ClassDataPreviewWindow(wxWindow): Line 1347  class ClassDataPreviewWindow(wxWindow):
1347          return self.prop          return self.prop
1348    
1349      def _OnPaint(self, event):      def _OnPaint(self, event):
1350          dc = wxPaintDC(self)          dc = wx.PaintDC(self)
1351    
1352          # XXX: this doesn't seem to be having an effect:          # XXX: this doesn't seem to be having an effect:
1353          dc.DestroyClippingRegion()          dc.DestroyClippingRegion()
1354    
1355          if self.rect is None:          if self.rect is None:
1356              w, h = self.GetSize()              w, h = self.GetSize()
1357              rect = wxRect(0, 0, w, h)              rect = wx.Rect(0, 0, w, h)
1358          else:          else:
1359              rect = self.rect              rect = self.rect
1360    
# Line 1413  class ClassDataPreviewer: Line 1387  class ClassDataPreviewer:
1387    
1388          stroke = prop.GetLineColor()          stroke = prop.GetLineColor()
1389          if stroke is Transparent:          if stroke is Transparent:
1390              pen = wxTRANSPARENT_PEN              pen = wx.TRANSPARENT_PEN
1391          else:          else:
1392              pen = wxPen(Color2wxColour(stroke),              pen = wx.Pen(Color2wxColour(stroke),
1393                          prop.GetLineWidth(),                          prop.GetLineWidth(),
1394                          wxSOLID)                          wx.SOLID)
1395    
1396          stroke = prop.GetFill()          stroke = prop.GetFill()
1397          if stroke is Transparent:          if stroke is Transparent:
1398              brush = wxTRANSPARENT_BRUSH              brush = wx.TRANSPARENT_BRUSH
1399          else:          else:
1400              brush = wxBrush(Color2wxColour(stroke), wxSOLID)              brush = wx.Brush(Color2wxColour(stroke), wx.SOLID)
1401    
1402          dc.SetPen(pen)          dc.SetPen(pen)
1403          dc.SetBrush(brush)          dc.SetBrush(brush)
1404    
1405          if shapeType == SHAPETYPE_ARC:          if shapeType == SHAPETYPE_ARC:
1406              dc.DrawSpline([wxPoint(x, y + h),              dc.DrawSpline([wx.Point(x, y + h),
1407                             wxPoint(x + w/2, y + h/4),                             wx.Point(x + w/2, y + h/4),
1408                             wxPoint(x + w/2, y + h/4*3),                             wx.Point(x + w/2, y + h/4*3),
1409                             wxPoint(x + w, y)])                             wx.Point(x + w, y)])
1410    
1411          elif shapeType == SHAPETYPE_POINT:          elif shapeType == SHAPETYPE_POINT:
1412    
# Line 1450  class ClassDataPreviewer: Line 1424  class ClassDataPreviewer:
1424    
1425          return None          return None
1426    
1427  class ClassRenderer(wxPyGridCellRenderer):  class ClassRenderer(grid.PyGridCellRenderer):
1428      """A wrapper class that can be used to draw group properties in a      """A wrapper class that can be used to draw group properties in a
1429      grid table.      grid table.
1430      """      """
1431    
1432      def __init__(self, shapeType):      def __init__(self, shapeType):
1433          wxPyGridCellRenderer.__init__(self)          grid.PyGridCellRenderer.__init__(self)
1434          self.shapeType = shapeType          self.shapeType = shapeType
1435          self.previewer = ClassDataPreviewer()          self.previewer = ClassDataPreviewer()
1436    
1437      def Draw(self, grid, attr, dc, rect, row, col, isSelected):      def Draw(self, grid, attr, dc, rect, row, col, isSelected):
1438          data = grid.GetTable().GetClassGroup(row)          data = grid.GetTable().GetClassGroup(row)
1439    
1440          dc.SetClippingRegion(rect.GetX(), rect.GetY(),          dc.SetClippingRegion(rect.GetX(), rect.GetY(),
1441                               rect.GetWidth(), rect.GetHeight())                               rect.GetWidth(), rect.GetHeight())
1442          dc.SetPen(wxPen(wxLIGHT_GREY))          dc.SetPen(wx.Pen(wx.LIGHT_GREY))
1443          dc.SetBrush(wxBrush(wxLIGHT_GREY, wxSOLID))          dc.SetBrush(wx.Brush(wx.LIGHT_GREY, wx.SOLID))
1444          dc.DrawRectangle(rect.GetX(), rect.GetY(),          dc.DrawRectangle(rect.GetX(), rect.GetY(),
1445                           rect.GetWidth(), rect.GetHeight())                           rect.GetWidth(), rect.GetHeight())
1446    
1447          if not isinstance(data, ClassGroupMap):          if not isinstance(data, ClassGroupMap):
# Line 1483  class ClassRenderer(wxPyGridCellRenderer Line 1457  class ClassRenderer(wxPyGridCellRenderer
1457                  rect.SetHeight(new_h)                  rect.SetHeight(new_h)
1458                  rect.SetWidth(new_w)                  rect.SetWidth(new_w)
1459                  dc.DestroyClippingRegion()                  dc.DestroyClippingRegion()
1460                  dc.SetClippingRegion(rect.GetX(), rect.GetY(),                  dc.SetClippingRegion(rect.GetX(), rect.GetY(),
1461                                       rect.GetWidth(), rect.GetHeight())                                       rect.GetWidth(), rect.GetHeight())
1462                  dc.SetPen(wxPen(wxLIGHT_GREY))                  dc.SetPen(wx.Pen(wx.LIGHT_GREY))
1463                  dc.SetBrush(wxBrush(wxLIGHT_GREY, wxSOLID))                  dc.SetBrush(wx.Brush(wx.LIGHT_GREY, wx.SOLID))
1464                  dc.DrawRectangle(rect.GetX(), rect.GetY(),                  dc.DrawRectangle(rect.GetX(), rect.GetY(),
1465                                   rect.GetWidth(), rect.GetHeight())                                   rect.GetWidth(), rect.GetHeight())
1466                  self.previewer.Draw(dc, rect, data.GetProperties(),                  self.previewer.Draw(dc, rect, data.GetProperties(),
1467                                      self.shapeType)                                      self.shapeType)
1468    
1469          if isSelected:          if isSelected:
1470              dc.SetPen(wxPen(wxBLACK, 1, wxSOLID))              dc.SetPen(wx.Pen(wx.BLACK, 1, wx.SOLID))
1471              dc.SetBrush(wxTRANSPARENT_BRUSH)              dc.SetBrush(wx.TRANSPARENT_BRUSH)
1472    
1473              dc.DrawRectangle(rect.GetX(), rect.GetY(),              dc.DrawRectangle(rect.GetX(), rect.GetY(),
1474                               rect.GetWidth(), rect.GetHeight())                               rect.GetWidth(), rect.GetHeight())
1475    
1476          dc.DestroyClippingRegion()          dc.DestroyClippingRegion()
1477    
1478    
1479  class ClassGroupPropertiesCtrl(wxWindow, wxControl):  class ClassGroupPropertiesCtrl(wx.Control):
1480      """A custom window and control that draw a preview of group properties      """A custom window and control that draw a preview of group properties
1481      and can open a dialog to modify the properties if the user double-clicks      and can open a dialog to modify the properties if the user double-clicks
1482      it.      it.
1483      """      """
1484    
1485      def __init__(self, parent, id, props, shapeType,      def __init__(self, parent, id, props, shapeType,
1486                   size = wxDefaultSize, style = 0):                   size = wx.DefaultSize, style = 0):
1487            wx.Control.__init__(self, parent, id, size = size, style = style)
         wxWindow.__init__(self, parent, id, size = size, style = style)  
1488    
1489          self.parent = parent          self.parent = parent
1490    
# Line 1519  class ClassGroupPropertiesCtrl(wxWindow, Line 1492  class ClassGroupPropertiesCtrl(wxWindow,
1492          self.SetShapeType(shapeType)          self.SetShapeType(shapeType)
1493          self.AllowEdit(True)          self.AllowEdit(True)
1494    
1495          EVT_PAINT(self, self._OnPaint)          self.Bind(wx.EVT_PAINT, self._OnPaint)
1496          EVT_LEFT_DCLICK(self, self._OnLeftDClick)          self.Bind(wx.EVT_LEFT_DCLICK, self._OnLeftDClick)
1497    
1498          self.previewer = ClassDataPreviewer()          self.previewer = ClassDataPreviewer()
1499    
1500      def _OnPaint(self, event):      def _OnPaint(self, event):
1501          dc = wxPaintDC(self)          dc = wx.PaintDC(self)
1502    
1503          # XXX: this doesn't seem to be having an effect:          # XXX: this doesn't seem to be having an effect:
1504          dc.DestroyClippingRegion()          dc.DestroyClippingRegion()
1505    
1506          w, h = self.GetClientSize()          w, h = self.GetClientSize()
1507    
1508          self.previewer.Draw(dc,          self.previewer.Draw(dc,
1509                              wxRect(0, 0, w, h),                              wx.Rect(0, 0, w, h),
1510                              self.GetProperties(),                              self.GetProperties(),
1511                              self.GetShapeType())                              self.GetShapeType())
1512    
1513    
# Line 1561  class ClassGroupPropertiesCtrl(wxWindow, Line 1534  class ClassGroupPropertiesCtrl(wxWindow,
1534    
1535          if not self.allowEdit: return          if not self.allowEdit: return
1536    
1537          propDlg = SelectPropertiesDialog(self.parent,          propDlg = SelectPropertiesDialog(self.parent,
1538                                           self.GetProperties(),                                           self.GetProperties(),
1539                                           self.GetShapeType())                                           self.GetShapeType())
1540    
1541          if propDlg.ShowModal() == wxID_OK:          if propDlg.ShowModal() == wx.ID_OK:
1542              new_prop = propDlg.GetClassGroupProperties()              new_prop = propDlg.GetClassGroupProperties()
1543              self.SetProperties(new_prop)              self.SetProperties(new_prop)
1544              self.Refresh()              self.Refresh()
# Line 1575  class ClassGroupPropertiesCtrl(wxWindow, Line 1548  class ClassGroupPropertiesCtrl(wxWindow,
1548      def _OnLeftDClick(self, event):      def _OnLeftDClick(self, event):
1549          self.DoEdit()          self.DoEdit()
1550    
 from Thuban.UI.mainwindow import layer_properties_dialogs  
 layer_properties_dialogs.add(Layer, Classifier)  
 layer_properties_dialogs.add(RasterLayer, Classifier)  

Legend:
Removed from v.2386  
changed lines
  Added in v.2700

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26