/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/classification.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/Model/classification.py

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

revision 1336 by jonathan, Tue Jul 1 16:09:26 2003 UTC revision 1426 by jonathan, Wed Jul 16 13:22:20 2003 UTC
# Line 27  from Thuban import _ Line 27  from Thuban import _
27  from messages import \  from messages import \
28      LAYER_PROJECTION_CHANGED, \      LAYER_PROJECTION_CHANGED, \
29      LAYER_LEGEND_CHANGED, \      LAYER_LEGEND_CHANGED, \
30      LAYER_VISIBILITY_CHANGED      LAYER_VISIBILITY_CHANGED,\
31        CLASS_CHANGED
32    
33  from Thuban.Model.color import Color, Transparent, Black  from Thuban.Model.color import Color, Transparent, Black
34  from Thuban.Model.range import Range  from Thuban.Model.range import Range
35    
36  import Thuban.Model.layer  import Thuban.Model.layer
37    
38  class Classification:  from Thuban.Lib.connector import Publisher
39    
40    class Classification(Publisher):
41      """Encapsulates the classification of layer.      """Encapsulates the classification of layer.
42            
43      The Classification divides some kind of data into Groups which      The Classification divides some kind of data into Groups which
# Line 42  class Classification: Line 45  class Classification:
45      retrieved by matching data values to the appropriate group.      retrieved by matching data values to the appropriate group.
46      """      """
47    
48      def __init__(self, layer = None, field = None):      def __init__(self):
49          """Initialize a classification.          """Initialize a classification."""
   
         layer -- the Layer object who owns this classification  
   
         field -- the name of the data table field that  
                  is to be used to classify layer properties  
         """  
50    
         self.layer = None  
         self.field = None  
         self.fieldType = None  
51          self.__groups = []          self.__groups = []
52    
         self.__setLayerLock = False  
   
53          self.SetDefaultGroup(ClassGroupDefault())          self.SetDefaultGroup(ClassGroupDefault())
54    
         self.SetFieldInfo(field, None)  
   
         self._set_layer(layer)  
   
55      def __iter__(self):      def __iter__(self):
56          return ClassIterator(self.__groups)          return ClassIterator(self.__groups)
57    
58      def __deepcopy__(self, memo):      def __deepcopy__(self, memo):
59          clazz = Classification()          clazz = Classification()
60    
         # note: the only thing that isn't copied is the layer reference  
         clazz.field = self.field  
         clazz.fieldType = self.fieldType  
61          clazz.__groups[0] = copy.deepcopy(self.__groups[0])          clazz.__groups[0] = copy.deepcopy(self.__groups[0])
62    
63          for i in range(1, len(self.__groups)):          for i in range(1, len(self.__groups)):
# Line 82  class Classification: Line 67  class Classification:
67    
68      def __SendNotification(self):      def __SendNotification(self):
69          """Notify the layer that this class has changed."""          """Notify the layer that this class has changed."""
70          if self.layer is not None:          self.issue(CLASS_CHANGED)
             self.layer.ClassChanged()  
71            
     def GetField(self):  
         """Return the name of the field."""  
         return self.field  
   
     def GetFieldType(self):  
         """Return the field type."""  
         return self.fieldType  
   
     def SetFieldInfo(self, name, type):  
         """Set the classified field name to 'name' and it's field  
         type to 'type'  
   
         If this classification has an owning layer a ValueError  
         exception will be thrown either the field or field type  
         mismatch the information in the layer's table.  
   
         If the field info is successful set and the class has  
         an owning layer, the layer will be informed that the  
         classification has changed.  
         """  
   
         if name == "":  
             name = None  
   
         if self.layer is None:  
             self.field = name  
             self.fieldType = type  
         elif name is None:  
             self.field = None  
             self.fieldType = None  
         else:  
             #  
             # verify that the field exists in the layer and that  
             # the type is correct.  
             #  
             fieldType = self.layer.GetFieldType(name)  
             if fieldType is None:  
                 raise ValueError("'%s' was not found in the layer's table."  
                                  % self.field)  
             elif type is not None and fieldType != type:  
                 raise ValueError("type doesn't match layer's field type for %s"  
                                  % self.field)  
   
             self.field = name  
             self.fieldType = fieldType  
   
         self.__SendNotification()  
   
     def _set_layer(self, layer):  
         """Internal: Set the owning Layer of this classification.  
   
         A ValueError exception will be thrown either the field or  
         field type mismatch the information in the layer's table.  
   
         If the layer is successful set, the layer will be informed  
         that the classification has changed.  
         """  
   
         if layer is None:  
             self.layer = None  
         else:  
             old_layer = self.layer  
             self.layer = layer  
   
             try:  
                 # this sync's the fieldType  
                 # and sends a notification to the layer  
                 self.SetFieldInfo(self.GetField(), None)  
             except ValueError:  
                 self.layer = old_layer  
                 raise ValueError  
   
     def GetLayer(self):  
         """Return the parent layer."""  
         return self.layer  
   
72      #      #
73      # these SetDefault* methods are really only provided for      # these SetDefault* methods are really only provided for
74      # some backward compatibility. they should be considered      # some backward compatibility. they should be considered
# Line 238  class Classification: Line 146  class Classification:
146          self.InsertGroup(self.GetNumGroups(), item)          self.InsertGroup(self.GetNumGroups(), item)
147    
148      def InsertGroup(self, index, group):      def InsertGroup(self, index, group):
           
149          assert isinstance(group, ClassGroup)          assert isinstance(group, ClassGroup)
   
150          self.__groups.insert(index + 1, group)          self.__groups.insert(index + 1, group)
   
151          self.__SendNotification()          self.__SendNotification()
152    
153      def RemoveGroup(self, index):      def RemoveGroup(self, index):
# Line 250  class Classification: Line 155  class Classification:
155    
156      def ReplaceGroup(self, index, group):      def ReplaceGroup(self, index, group):
157          assert isinstance(group, ClassGroup)          assert isinstance(group, ClassGroup)
   
158          self.__groups[index + 1] = group          self.__groups[index + 1] = group
   
159          self.__SendNotification()          self.__SendNotification()
160    
161      def GetGroup(self, index):      def GetGroup(self, index):
# Line 262  class Classification: Line 165  class Classification:
165          """Return the number of non-default groups in the classification."""          """Return the number of non-default groups in the classification."""
166          return len(self.__groups) - 1          return len(self.__groups) - 1
167    
   
168      def FindGroup(self, value):      def FindGroup(self, value):
169          """Return the associated group, or the default group.          """Return the associated group, or the default group.
170    
# Line 274  class Classification: Line 176  class Classification:
176                   return the default properties                   return the default properties
177          """          """
178    
179          if self.GetField() is not None and value is not None:          if value is not None:
   
180              for i in range(1, len(self.__groups)):              for i in range(1, len(self.__groups)):
181                  group = self.__groups[i]                  group = self.__groups[i]
182                  if group.Matches(value):                  if group.Matches(value):
# Line 328  class Classification: Line 229  class Classification:
229          for p in self:          for p in self:
230              items.append(build_item(p, p.GetDisplayText()))              items.append(build_item(p, p.GetDisplayText()))
231    
 #           if isinstance(p, ClassGroupDefault):  
 #               items.append(build_item(self.GetDefaultGroup(), _("'DEFAULT'")))  
 #           elif isinstance(p, ClassGroupSingleton):  
 #               items.append(build_item(p, str(p.GetValue())))  
 #           elif isinstance(p, ClassGroupRange):  
 #               items.append(build_item(p, "%s - %s" %  
 #                                          (p.GetMin(), p.GetMax())))  
   
232          return (_("Classification"), items)          return (_("Classification"), items)
233    
234  class ClassIterator:  class ClassIterator:
# Line 357  class ClassIterator: Line 250  class ClassIterator:
250          maps -- a list of map groups          maps -- a list of map groups
251          """          """
252    
253          self.data = data #[default, points, ranges, maps]          self.data = data
254          self.data_index = 0          self.data_index = 0
         #self.data_iter = iter(self.data)  
         #self.iter = None  
255    
256      def __iter__(self):      def __iter__(self):
257          return self          return self
# Line 375  class ClassIterator: Line 266  class ClassIterator:
266              self.data_index += 1              self.data_index += 1
267              return d              return d
268                    
 #       if self.iter is None:  
 #           try:  
 #               self.data_item = self.data_iter.next()  
 #               self.iter = iter(self.data_item)  
 #           except TypeError:  
 #               return self.data_item  
   
 #       try:  
 #           return self.iter.next()  
 #       except StopIteration:  
 #           self.iter = None  
 #           return self.next()  
         
269  class ClassGroupProperties:  class ClassGroupProperties:
270      """Represents the properties of a single Classification Group.      """Represents the properties of a single Classification Group.
271        
# Line 402  class ClassGroupProperties: Line 280  class ClassGroupProperties:
280                   and fill color = Transparent                   and fill color = Transparent
281          """          """
282    
         #self.stroke = None  
         #self.strokeWidth = 0  
         #self.fill = None  
   
283          if props is not None:          if props is not None:
284              self.SetProperties(props)              self.SetProperties(props)
285          else:          else:
# Line 661  class ClassGroupRange(ClassGroup): Line 535  class ClassGroupRange(ClassGroup):
535      """A Group that represents a range of values that map to the same      """A Group that represents a range of values that map to the same
536         set of properties."""         set of properties."""
537    
538      def __init__(self, min = 0, max = 1, props = None, label = "", group=None):      def __init__(self, _range = (0,1), props = None, label = "", group=None):
539          """Constructor.          """Constructor.
540    
541          The minumum value must be strictly less than the maximum.          The minumum value must be strictly less than the maximum.
542    
543          min -- the minimum range value          _range -- either a tuple (min, max) where min < max or
544                      a Range object
         max -- the maximum range value  
545    
546          prop -- a ClassGroupProperites object. If prop is None a default          prop -- a ClassGroupProperites object. If prop is None a default
547                   set of properties is created.                   set of properties is created.
# Line 677  class ClassGroupRange(ClassGroup): Line 550  class ClassGroupRange(ClassGroup):
550          """          """
551    
552          ClassGroup.__init__(self, label, props, group)          ClassGroup.__init__(self, label, props, group)
553            self.SetRange(_range)
         #self.__min = self.__max = 0  
         #self.__range = Range("[" + repr(float(min)) + ";" +  
                                    #repr(float(max)) + "[")  
         self.SetRange(min, max)  
554    
555      def __copy__(self):      def __copy__(self):
556          return ClassGroupRange(min = self.__range,          return ClassGroupRange(self.__range,
                                max = None,  
557                                 props = self.GetProperties(),                                 props = self.GetProperties(),
558                                 label = self.GetLabel())                                 label = self.GetLabel())
559    
560      def __deepcopy__(self, memo):      def __deepcopy__(self, memo):
561          return ClassGroupRange(min = copy.copy(self.__range),          return ClassGroupRange(copy.copy(self.__range),
                                max = copy.copy(self.GetMax()),  
562                                 group = self)                                 group = self)
563    
564      def GetMin(self):      def GetMin(self):
# Line 705  class ClassGroupRange(ClassGroup): Line 572  class ClassGroupRange(ClassGroup):
572                 maximum value. Use SetRange() to change both min and max values.                 maximum value. Use SetRange() to change both min and max values.
573          """          """
574            
575          self.SetRange(min, self.__range.GetRange()[2])          self.SetRange((min, self.__range.GetRange()[2]))
576    
577      def GetMax(self):      def GetMax(self):
578          """Return the range's maximum value."""          """Return the range's maximum value."""
# Line 717  class ClassGroupRange(ClassGroup): Line 584  class ClassGroupRange(ClassGroup):
584          max -- the new maximum. Note that this must be greater than the current          max -- the new maximum. Note that this must be greater than the current
585                 minimum value. Use SetRange() to change both min and max values.                 minimum value. Use SetRange() to change both min and max values.
586          """          """
587          self.SetRange(self.__range.GetRange()[1], max)          self.SetRange((self.__range.GetRange()[1], max))
588    
589      def SetRange(self, min, max = None):      def SetRange(self, _range):
590          """Set a new range.          """Set a new range.
591    
592          Note that min must be strictly less than max.          _range -- Either a tuple (min, max) where min < max or
593                      a Range object.
594    
595          min -- the new minimum value          Raises ValueError on error.
         min -- the new maximum value  
596          """          """
597    
598          if isinstance(min, Range):          if isinstance(_range, Range):
599              self.__range = min              self.__range = _range
600            elif isinstance(_range, types.TupleType) and len(_range) == 2:
601                self.__range = Range(("[", _range[0], _range[1], "["))
602          else:          else:
603              if max is None:              raise ValueError()
                 raise ValueError()  
   
             self.__range = Range(("[", min, max, "["))  
604    
605      def GetRange(self):      def GetRange(self):
606          """Return the range as a string"""          """Return the range as a string"""
         #return (self.__min, self.__max)  
607          return self.__range.string(self.__range.GetRange())          return self.__range.string(self.__range.GetRange())
608    
609      def Matches(self, value):      def Matches(self, value):
# Line 748  class ClassGroupRange(ClassGroup): Line 613  class ClassGroupRange(ClassGroup):
613          """          """
614    
615          return operator.contains(self.__range, value)          return operator.contains(self.__range, value)
         #return self.__min <= value < self.__max  
616    
617      def GetDisplayText(self):      def GetDisplayText(self):
618          label = self.GetLabel()          label = self.GetLabel()
619    
620          if label != "": return label          if label != "": return label
621    
         #return _("%s - %s") % (self.GetMin(), self.GetMax())  
         #return repr(self.__range)  
622          return self.__range.string(self.__range.GetRange())          return self.__range.string(self.__range.GetRange())
623    
624      def __eq__(self, other):      def __eq__(self, other):
625          return ClassGroup.__eq__(self, other) \          return ClassGroup.__eq__(self, other) \
626              and isinstance(other, ClassGroupRange) \              and isinstance(other, ClassGroupRange) \
627              and self.__range == other.__range              and self.__range == other.__range
             #and self.__min == other.__min \  
             #and self.__max == other.__max  
628    
629      def __repr__(self):      def __repr__(self):
630          return "(" + str(self.__range) + ClassGroup.__repr__(self) + ")"          return "(" + str(self.__range) + ClassGroup.__repr__(self) + ")"
         #return "(" + repr(self.__min) + ", " + repr(self.__max) + ", " + \  
                #ClassGroup.__repr__(self) + ")"  
631    
632  class ClassGroupMap(ClassGroup):  class ClassGroupMap(ClassGroup):
633      """Currently, this class is not used."""      """Currently, this class is not used."""

Legend:
Removed from v.1336  
changed lines
  Added in v.1426

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26