/[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 453 by bh, Tue Mar 4 11:31:39 2003 UTC revision 613 by jonathan, Mon Apr 7 08:55:55 2003 UTC
# Line 16  an input value falls with a range that d Line 16  an input value falls with a range that d
16  If no mapping can be found then default data will  If no mapping can be found then default data will
17  be returned. Input values must be hashable objects  be returned. Input values must be hashable objects
18    
19  See the description of GetGroup() for more information  See the description of FindGroup() for more information
20  on the mapping algorithm.  on the mapping algorithm.
21  """  """
22        
23  # fix for people using python2.1  # fix for people using python2.1
24  from __future__ import nested_scopes  from __future__ import nested_scopes
25    
26    import copy
27    
28    from Thuban import _
29    
30  from types import *  from types import *
31    
32  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \  from messages import \
33       LAYER_VISIBILITY_CHANGED      LAYER_PROJECTION_CHANGED, \
34        LAYER_LEGEND_CHANGED, \
35        LAYER_VISIBILITY_CHANGED
36    
 from Thuban import _  
37  from Thuban.Model.color import Color  from Thuban.Model.color import Color
38    
39  import Thuban.Model.layer  import Thuban.Model.layer
40    
   
 # constants  
 RANGE_MIN  = 0  
 RANGE_MAX  = 1  
 RANGE_DATA = 2  
   
41  class Classification:  class Classification:
42        """Encapsulates the classification of layer.
43        
44        The Classification divides some kind of data into Groups which
45        are associated with properties. Later the properties can be
46        retrieved by matching data values to the appropriate group.
47        """
48    
49      def __init__(self, layer = None, field = None):      def __init__(self, layer = None, field = None):
50          """Initialize a classification.          """Initialize a classification.
51    
52             layer -- the layer object who owns this classification          layer -- the Layer object who owns this classification
53    
54             field -- the name of the data table field that          field -- the name of the data table field that
55                      is to be used to classify layer properties                   is to be used to classify layer properties
56          """          """
57    
58          self.layer = None # stop message sending          self.layer = None
59            self.field = None
60            self.fieldType = None
61            self.__groups = []
62    
63            self.__setLayerLock = False
64    
65          self.SetDefaultGroup(ClassGroupDefault())          self.SetDefaultGroup(ClassGroupDefault())
         self.SetField(field)  
66    
67          self.layer = layer          self.SetLayer(layer)
68          self.points = []          self.SetField(field)
         self.ranges = []  
         self.maps   = []  
69    
70      def __iter__(self):      def __iter__(self):
71          return ClassIterator(self.DefaultGroup,          return ClassIterator(self.__groups)
72                               self.points,  
73                               self.ranges,      def __deepcopy__(self, memo):
74                               self.maps)          clazz = Classification()
75    
76            clazz.__groups[0] = copy.deepcopy(self.__groups[0])
77    
78            for i in range(1, len(self.__groups)):
79                clazz.__groups.append(copy.deepcopy(self.__groups[i]))
80    
81      def __SendMessage(self, message):          print "Classification.__deepcopy__"
82            return clazz
83    
84        def __SendNotification(self):
85            """Notify the layer that this class has changed."""
86          if self.layer is not None:          if self.layer is not None:
87              self.layer.changed(message, self.layer)              self.layer.ClassChanged()
88            
89      def SetField(self, field):      def SetField(self, field):
90          """Set the name of the data table field to use.          """Set the name of the data table field to use.
91                    
92             field -- if None then all values map to the default data          If there is no layer then the field type is set to None,
93            otherwise the layer is queried to find the type of the
94            field data
95    
96            field -- if None then all values map to the default data
97          """          """
98    
99          if field == "":          if field == "":
100              field = None              field = None
101    
102    
103            if field is None:
104                if self.layer is not None:
105                    self.fieldType = None
106            else:
107                if self.layer is not None:
108                    fieldType = self.layer.GetFieldType(field)
109                    if fieldType is None:
110                        raise ValueError("'%s' was not found in the layer's table."
111                                         % self.field)
112    
113                    #
114                    # unfortunately we cannot call SetFieldType() because it
115                    # requires the layer to be None
116                    #
117                    self.fieldType = fieldType
118                    #self.SetFieldType(fieldType)
119    
120          self.field = field          self.field = field
121          self.__SendMessage(LAYER_LEGEND_CHANGED)  
122            self.__SendNotification()
123    
124      def GetField(self):      def GetField(self):
125            """Return the name of the field."""
126          return self.field          return self.field
127    
128      def SetLayer(self, layer):      def GetFieldType(self):
129          assert(isinstance(layer, Thuban.Model.layer.Layer))          """Return the field type."""
130          self.layer = layer          return self.fieldType
         self.__SendMessage(LAYER_LEGEND_CHANGED)  
131    
132      def GetLayer(self):      def SetFieldType(self, type):
133          return layer.self          """Set the type of the field used by this classification.
134    
135      def SetDefaultGroup(self, group):          A ValueError is raised if the owning layer is not None and
136          """Set the group to be used when a value can't be classified.          'type' is different from the current field type.
137            """
138    
139             group -- group that the value maps to. See class description.          if type != self.fieldType:
140                if self.layer is not None:
141                    raise ValueError()
142                else:
143                    self.fieldType = type
144                    self.__SendNotification()
145    
146        def SetLayer(self, layer):
147            """Set the owning Layer of this classification.
148    
149            A ValueError exception will be thrown either the field or
150            field type mismatch the information in the layer's table.
151          """          """
152    
153          assert(isinstance(group, ClassGroupDefault))          # prevent infinite recursion when calling SetClassification()
154          self.DefaultGroup = group          if self.__setLayerLock: return
155    
156            self.__setLayerLock = True
157    
158            if layer is None:
159                if self.layer is not None:
160                    l = self.layer
161                    self.layer = None
162                    l.SetClassification(None)
163            else:
164                assert isinstance(layer, Thuban.Model.layer.Layer)
165    
166                old_layer = self.layer
167    
168                self.layer = layer
169    
170                try:
171                    self.SetField(self.GetField()) # this sync's the fieldType
172                except ValueError:
173                    self.layer = old_layer
174                    self.__setLayerLock = False
175                    raise ValueError
176                else:
177                    self.layer.SetClassification(self)
178    
179            self.__setLayerLock = False
180    
181        def GetLayer(self):
182            """Return the parent layer."""
183            return self.layer
184    
     def GetDefaultGroup(self):  
         return self.DefaultGroup  
185    
186      #      #
187      # these SetDefault* methods are really only provided for      # these SetDefault* methods are really only provided for
# Line 112  class Classification: Line 190  class Classification:
190      #      #
191    
192      def SetDefaultFill(self, fill):      def SetDefaultFill(self, fill):
193          assert(isinstance(fill, Color))          """Set the default fill color.
194          self.DefaultGroup.GetProperties().SetFill(fill)  
195          self.__SendMessage(LAYER_LEGEND_CHANGED)          fill -- a Color object.
196            """
197            assert isinstance(fill, Color)
198            self.GetDefaultGroup().GetProperties().SetFill(fill)
199            self.__SendNotification()
200                    
201      def GetDefaultFill(self):      def GetDefaultFill(self):
202          return self.DefaultGroup.GetProperties().GetFill()          """Return the default fill color."""
203            return self.GetDefaultGroup().GetProperties().GetFill()
204                    
205      def SetDefaultStroke(self, stroke):      def SetDefaultLineColor(self, color):
206          assert(isinstance(stroke, Color))          """Set the default line color.
207          self.DefaultGroup.GetProperties().SetStroke(stroke)  
208          self.__SendMessage(LAYER_LEGEND_CHANGED)          color -- a Color object.
209            """
210            assert isinstance(color, Color)
211            self.GetDefaultGroup().GetProperties().SetLineColor(color)
212            self.__SendNotification()
213                    
214      def GetDefaultStroke(self):      def GetDefaultLineColor(self):
215          return self.DefaultGroup.GetProperties().GetStroke()          """Return the default line color."""
216            return self.GetDefaultGroup().GetProperties().GetLineColor()
217                    
218      def SetDefaultStrokeWidth(self, strokeWidth):      def SetDefaultLineWidth(self, lineWidth):
219          assert(isinstance(strokeWidth, IntType))          """Set the default line width.
220          self.DefaultGroup.GetProperties().SetStrokeWidth(strokeWidth)  
221          self.__SendMessage(LAYER_LEGEND_CHANGED)          lineWidth -- an integer > 0.
222            """
223            assert isinstance(lineWidth, IntType)
224            self.GetDefaultGroup().GetProperties().SetLineWidth(lineWidth)
225            self.__SendNotification()
226                    
227      def GetDefaultStrokeWidth(self):      def GetDefaultLineWidth(self):
228          return self.DefaultGroup.GetProperties().GetStrokeWidth()          """Return the default line width."""
229            return self.GetDefaultGroup().GetProperties().GetLineWidth()
230                    
     def AddGroup(self, item):  
         assert(isinstance(item, ClassGroup))  
231    
232          if isinstance(item, ClassGroupDefault):      #
233              self.SetDefaultGroup(item)      # The methods that manipulate self.__groups have to be kept in
234          elif isinstance(item, ClassGroupSingleton):      # sync. We store the default group in index 0 to make it
235              self.points.append(item)      # convienent to iterate over the classification's groups, but
236          elif isinstance(item, ClassGroupRange):      # from the user's perspective the first (non-default) group is
237              self.ranges.append(item)      # at index 0 and the DefaultGroup is a special entity.
238          elif isinstance(item, ClassGroupMap):      #
239              self.maps.append(item)  
240        def SetDefaultGroup(self, group):
241            """Set the group to be used when a value can't be classified.
242    
243            group -- group that the value maps to.
244            """
245    
246            assert isinstance(group, ClassGroupDefault)
247            if len(self.__groups) > 0:
248                self.__groups[0] = group
249          else:          else:
250              raise ValueError(_("Unrecognized ClassGroup"))              self.__groups.append(group)
251    
252        def GetDefaultGroup(self):
253            """Return the default group."""
254            return self.__groups[0]
255    
256        def AppendGroup(self, item):
257            """Append a new ClassGroup item to the classification.
258    
259            item -- this must be a valid ClassGroup object
260            """
261    
262            self.InsertGroup(self.GetNumGroups(), item)
263    
264        def InsertGroup(self, index, group):
265            
266            assert isinstance(group, ClassGroup)
267    
268          self.__SendMessage(LAYER_LEGEND_CHANGED)          self.__groups.insert(index + 1, group)
269    
270            self.__SendNotification()
271    
272        def RemoveGroup(self, index):
273            return self.__groups.pop(index + 1)
274    
275        def ReplaceGroup(self, index, group):
276            assert isinstance(group, ClassGroup)
277    
278            self.__groups[index + 1] = group
279    
280            self.__SendNotification()
281    
282        def GetGroup(self, index):
283            return self.__groups[index + 1]
284    
285        def GetNumGroups(self):
286            """Return the number of non-default groups in the classification."""
287            return len(self.__groups) - 1
288    
289    
290        def FindGroup(self, value):
291            """Return the associated group, or the default group.
292    
293            Groups are checked in the order the were added to the
294            Classification.
295    
296            value -- the value to classify. If there is no mapping,
297                     the field is None or value is None,
298                     return the default properties
299            """
300    
301      def GetGroup(self, value):          if self.GetField() is not None and value is not None:
         """Return the associated data, or the default data.  
302    
303             The following search technique is used:              for i in range(1, len(self.__groups)):
304                 (1) if the field is None, return the default data                  group = self.__groups[i]
305                 (2) check if the value exists as a single value                  if group.Matches(value):
306                 (3) check if the value falls within a range. Ranges                      return group
                    are checked in the order they were added to  
                    the classification.  
   
            value -- the value to classify. If there is no mapping,  
                     or value is None, return the default properties  
         """  
   
         if self.field is not None and value is not None:  
   
             for p in self:  
                 if p.Matches(value):  
                     return p  
 #           #  
 #           # check the discrete values  
 #           #  
 #           if self.points.has_key(value):  
 #               return self.points[value]  
 #           #for p in self.points:  
 #               #if p.Value  
   
 #           #  
 #           # check the ranges  
 #           #  
 #           for p in self.ranges:  
 #               if p.InRange(value):  
 #                   return p  
   
 #           #  
 #           # check the maps  
 #           #  
 #           for p in self.maps:  
 #               try:  
 #                   return p.Map(value)  
 #               except: pass  
307    
308          return self.DefaultGroup          return self.GetDefaultGroup()
309    
310      def GetProperties(self, value):      def GetProperties(self, value):
311          return self.GetGroup(value).GetProperties()          """Return the properties associated with the given value.
312          
313            Use this function rather than Classification.FindGroup().GetProperties()
314            since the returned group may be a ClassGroupMap which doesn't support
315            a call to GetProperties().
316            """
317    
318            group = self.FindGroup(value)
319            if isinstance(group, ClassGroupMap):
320                return group.GetPropertiesFromValue(value)
321            else:
322                return group.GetProperties()
323    
324      def TreeInfo(self):      def TreeInfo(self):
325          items = []          items = []
326    
327          def build_color_item(text, color):          def build_color_item(text, color):
328              if color is Color.None:              if color is Color.Transparent:
329                  return ("%s: %s" % (text, _("None")), None)                  return ("%s: %s" % (text, _("None")), None)
330    
331              return ("%s: (%.3f, %.3f, %.3f)" %              return ("%s: (%.3f, %.3f, %.3f)" %
# Line 218  class Classification: Line 341  class Classification:
341    
342              props = group.GetProperties()              props = group.GetProperties()
343              i = []              i = []
344              v = props.GetStroke()              v = props.GetLineColor()
345              i.append(build_color_item(_("Stroke"), v))              i.append(build_color_item(_("Line Color"), v))
346              v = props.GetStrokeWidth()              v = props.GetLineWidth()
347              i.append(_("Stroke Width: %s") % v)              i.append(_("Line Width: %s") % v)
348              v = props.GetFill()              v = props.GetFill()
349              i.append(build_color_item(_("Fill"), v))              i.append(build_color_item(_("Fill"), v))
350              return (label, i)              return (label, i)
351    
352          for p in self:          for p in self:
353              if isinstance(p, ClassGroupDefault):              items.append(build_item(p, p.GetDisplayText()))
                 items.append(build_item(self.DefaultGroup, _("'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())))  
354    
355  #       for p in self.points.values():  #           if isinstance(p, ClassGroupDefault):
356  #           items.append(build_item(p, str(p.GetValue())))  #               items.append(build_item(self.GetDefaultGroup(), _("'DEFAULT'")))
357    #           elif isinstance(p, ClassGroupSingleton):
358  #       for p in self.ranges:  #               items.append(build_item(p, str(p.GetValue())))
359  #           items.append(build_item(p, "%s - %s" % (p.GetMin(), p.GetMax())))  #           elif isinstance(p, ClassGroupRange):
360    #               items.append(build_item(p, "%s - %s" %
361    #                                          (p.GetMin(), p.GetMax())))
362    
363          return (_("Classification"), items)          return (_("Classification"), items)
364    
365  class ClassIterator:  class ClassIterator:
366        """Allows the Groups in a Classifcation to be interated over.
367    
368        The items are returned in the following order:
369            default data, singletons, ranges, maps
370        """
371    
372        def __init__(self, data): #default, points, ranges, maps):
373            """Constructor.
374    
375      def __init__(self, default, points, ranges, maps):          default -- the default group
376          self.data = [default, points, ranges, maps]  
377          self.data_iter = iter(self.data)          points -- a list of singleton groups
378          self.iter = None  
379            ranges -- a list of range groups
380    
381            maps -- a list of map groups
382            """
383    
384            self.data = data #[default, points, ranges, maps]
385            self.data_index = 0
386            #self.data_iter = iter(self.data)
387            #self.iter = None
388    
389      def __iter__(self):      def __iter__(self):
390          return self          return self
391    
392      def next(self):      def next(self):
393          if self.iter is None:          """Return the next item."""
394              try:  
395                  self.data_item = self.data_iter.next()          if self.data_index >= len(self.data):
396                  self.iter = iter(self.data_item)              raise StopIteration
397              except TypeError:          else:
398                  return self.data_item              d = self.data[self.data_index]
399                self.data_index += 1
400          try:              return d
401              return self.iter.next()          
402          except StopIteration:  #       if self.iter is None:
403              self.iter = None  #           try:
404              return self.next()  #               self.data_item = self.data_iter.next()
405    #               self.iter = iter(self.data_item)
406    #           except TypeError:
407    #               return self.data_item
408    
409    #       try:
410    #           return self.iter.next()
411    #       except StopIteration:
412    #           self.iter = None
413    #           return self.next()
414                
415  class ClassGroupProperties:  class ClassGroupProperties:
416        """Represents the properties of a single Classification Group.
417      
418        These are used when rendering a layer."""
419    
420      def __init__(self, prop = None):      def __init__(self, props = None):
421            """Constructor.
422    
423          if prop is not None:          props -- a ClassGroupProperties object. The class is copied if
424              self.SetStroke(prop.GetStroke())                   prop is not None. Otherwise, a default set of properties
425              self.SetStrokeWidth(prop.GetStrokeWidth())                   is created such that: line color = Color.Black, line width = 1,
426              self.SetFill(prop.GetFill())                   and fill color = Color.Transparent
427          else:          """
             self.SetStroke(Color.None)  
             self.SetStrokeWidth(1)  
             self.SetFill(Color.None)  
428    
429      def GetStroke(self):          self.stroke = None
430            self.strokeWidth = 0
431            self.fill = None
432    
433            if props is not None:
434                self.SetProperties(props)
435            else:
436                self.SetLineColor(Color.Black)
437                self.SetLineWidth(1)
438                self.SetFill(Color.Transparent)
439    
440        def SetProperties(self, props):
441            """Set this class's properties to those in class props."""
442    
443            assert isinstance(props, ClassGroupProperties)
444            self.SetLineColor(props.GetLineColor())
445            self.SetLineWidth(props.GetLineWidth())
446            self.SetFill(props.GetFill())
447            
448        def GetLineColor(self):
449            """Return the line color as a Color object."""
450          return self.stroke          return self.stroke
451    
452      def SetStroke(self, stroke):      def SetLineColor(self, color):
453          assert(isinstance(stroke, Color))          """Set the line color.
454          self.stroke = stroke  
455            color -- the color of the line. This must be a Color object.
456      def GetStrokeWidth(self):          """
457          return self.stroke_width  
458            assert isinstance(color, Color)
459      def SetStrokeWidth(self, stroke_width):          self.stroke = color
         assert(isinstance(stroke_width, IntType))  
         if (stroke_width < 1):  
             raise ValueError(_("stroke_width < 1"))  
460    
461          self.stroke_width = stroke_width      def GetLineWidth(self):
462            """Return the line width."""
463            return self.strokeWidth
464    
465        def SetLineWidth(self, lineWidth):
466            """Set the line width.
467    
468            lineWidth -- the new line width. This must be > 0.
469            """
470            assert isinstance(lineWidth, IntType)
471            if (lineWidth < 1):
472                raise ValueError(_("lineWidth < 1"))
473    
474            self.strokeWidth = lineWidth
475    
476      def GetFill(self):      def GetFill(self):
477            """Return the fill color as a Color object."""
478          return self.fill          return self.fill
479    
480      def SetFill(self, fill):      def SetFill(self, fill):
481          assert(isinstance(fill, Color))          """Set the fill color.
482    
483            fill -- the color of the fill. This must be a Color object.
484            """
485    
486            assert isinstance(fill, Color)
487          self.fill = fill          self.fill = fill
488    
489        def __eq__(self, other):
490            """Return true if 'props' has the same attributes as this class"""
491    
492            return isinstance(other, ClassGroupProperties)   \
493                and self.stroke      == other.GetLineColor() \
494                and self.strokeWidth == other.GetLineWidth() \
495                and self.fill        == other.GetFill()
496    
497        def __ne__(self, other):
498            return not self.__eq__(other)
499    
500        def __copy__(self):
501            return ClassGroupProperties(self)
502    
503        def __deepcopy__(self):
504            return ClassGroupProperties(self)
505    
506  class ClassGroup:  class ClassGroup:
507        """A base class for all Groups within a Classification"""
508    
509      def __init__(self, label = ""):      def __init__(self, label = ""):
510          self.label = label          """Constructor.
511    
512            label -- A string representing the Group's label
513            """
514    
515            self.label = None
516    
517            self.SetLabel(label)
518    
519      def GetLabel(self):      def GetLabel(self):
520            """Return the Group's label."""
521          return self.label          return self.label
522    
523      def SetLabel(self, label):      def SetLabel(self, label):
524            """Set the Group's label.
525    
526            label -- a string representing the Group's label. This must
527                     not be None.
528            """
529            assert isinstance(label, StringType)
530          self.label = label          self.label = label
531    
532        def GetDisplayText(self):
533            assert False, "GetDisplay must be overridden by subclass!"
534            return ""
535    
536      def Matches(self, value):      def Matches(self, value):
537          """This needs to be implemented by all subclasses."""          """Determines if this Group is associated with the given value.
         pass  
538    
539      def GetProperties(self, value):          Returns False. This needs to be overridden by all subclasses.
540          """This needs to be implemented by all subclasses."""          """
541          pass          assert False, "GetMatches must be overridden by subclass!"
542            return False
543    
544        def GetProperties(self):
545            """Return the properties associated with the given value.
546    
547            Returns None. This needs to be overridden by all subclasses.
548            """
549            assert False, "GetProperties must be overridden by subclass!"
550            return None
551    
552            
553  class ClassGroupSingleton(ClassGroup):  class ClassGroupSingleton(ClassGroup):
554        """A Group that is associated with a single value."""
555    
556      def __init__(self, value = 0, prop = None, label = ""):      def __init__(self, value = 0, prop = None, label = ""):
557            """Constructor.
558    
559            value -- the associated value.
560    
561            prop -- a ClassGroupProperites object. If prop is None a default
562                     set of properties is created.
563    
564            label -- a label for this group.
565            """
566          ClassGroup.__init__(self, label)          ClassGroup.__init__(self, label)
567    
568            self.prop = None
569            self.value = None
570    
571          self.SetValue(value)          self.SetValue(value)
572          self.SetProperties(prop)          self.SetProperties(prop)
573    
574      def __copy__(self):      def __copy__(self):
575          return ClassGroupSingleton(self.value, self.prop, self.label)          return ClassGroupSingleton(self.GetValue(),
576                                       self.GetProperties(),
577                                       self.GetLabel())
578    
579        def __deepcopy__(self, memo):
580            return ClassGroupSingleton(copy.copy(self.GetValue()),
581                                       copy.copy(self.GetProperties()),
582                                       copy.copy(self.GetLabel()))
583    
584      def GetValue(self):      def GetValue(self):
585            """Return the associated value."""
586          return self.value          return self.value
587    
588      def SetValue(self, value):      def SetValue(self, value):
589            """Associate this Group with the given value."""
590          self.value = value          self.value = value
591    
592      def Matches(self, value):      def Matches(self, value):
593            """Determine if the given value matches the associated Group value."""
594    
595            """Returns True if the value matches, False otherwise."""
596    
597          return self.value == value          return self.value == value
598    
599      def GetProperties(self, value = None):      def GetProperties(self):
600          if value is None: return self.prop          """Return the Properties associated with this Group."""
601    
602          if self.Matches(value):          return self.prop
             return self.prop  
         else:  
             return None  
603    
604      def SetProperties(self, prop):      def SetProperties(self, prop):
605            """Set the properties associated with this Group.
606    
607            prop -- a ClassGroupProperties object. if prop is None,
608                    a default set of properties is created.
609            """
610    
611          if prop is None: prop = ClassGroupProperties()          if prop is None: prop = ClassGroupProperties()
612          assert(isinstance(prop, ClassGroupProperties))          assert isinstance(prop, ClassGroupProperties)
613          self.prop = prop          self.prop = prop
614    
615        def GetDisplayText(self):
616            label = self.GetLabel()
617    
618            if label != "": return label
619    
620            return str(self.GetValue())
621    
622        def __eq__(self, other):
623            return isinstance(other, ClassGroupSingleton) \
624                and self.GetProperties() == other.GetProperties() \
625                and self.GetValue() == other.GetValue()
626    
627        def __ne__(self, other):
628            return not self.__eq__(other)
629    
630    class ClassGroupDefault(ClassGroup):
631        """The default Group. When values do not match any other
632           Group within a Classification, the properties from this
633           class are used."""
634    
 class ClassGroupDefault(ClassGroupSingleton):  
635      def __init__(self, prop = None, label = ""):      def __init__(self, prop = None, label = ""):
636          ClassGroupSingleton.__init__(self, 0, prop, label)          """Constructor.
637    
638            prop -- a ClassGroupProperites object. If prop is None a default
639                     set of properties is created.
640    
641            label -- a label for this group.
642            """
643    
644            ClassGroup.__init__(self, label)
645            self.SetProperties(prop)
646    
647      def __copy__(self):      def __copy__(self):
648          return ClassGroupDefault(self.prop, self.label)          return ClassGroupDefault(self.GetProperties(), self.GetLabel())
649    
650        def __deepcopy__(self, memo):
651            return ClassGroupDefault(copy.copy(self.GetProperties()),
652                                     copy.copy(self.GetLabel()))
653    
654        def Matches(self, value):
655            return True
656    
657      def GetProperties(self, value = None):      def GetProperties(self):
658            """Return the Properties associated with this Group."""
659          return self.prop          return self.prop
660    
661        def SetProperties(self, prop):
662            """Set the properties associated with this Group.
663    
664            prop -- a ClassGroupProperties object. if prop is None,
665                    a default set of properties is created.
666            """
667    
668            if prop is None: prop = ClassGroupProperties()
669            assert isinstance(prop, ClassGroupProperties)
670            self.prop = prop
671    
672        def GetDisplayText(self):
673            label = self.GetLabel()
674    
675            if label != "": return label
676    
677            return _("DEFAULT")
678    
679        def __eq__(self, other):
680            return isinstance(other, ClassGroupDefault) \
681                and self.GetProperties() == other.GetProperties()
682    
683        def __ne__(self, other):
684            return not self.__eq__(other)
685    
686  class ClassGroupRange(ClassGroup):  class ClassGroupRange(ClassGroup):
687        """A Group that represents a range of values that map to the same
688           set of properties."""
689    
690      def __init__(self, min = 0, max = 1, prop = None, label = ""):      def __init__(self, min = 0, max = 1, prop = None, label = ""):
691            """Constructor.
692    
693            The minumum value must be strictly less than the maximum.
694    
695            min -- the minimum range value
696    
697            max -- the maximum range value
698    
699            prop -- a ClassGroupProperites object. If prop is None a default
700                     set of properties is created.
701    
702            label -- a label for this group.
703            """
704    
705          ClassGroup.__init__(self, label)          ClassGroup.__init__(self, label)
706    
707            self.min = self.max = 0
708            self.prop = None
709    
710          self.SetRange(min, max)          self.SetRange(min, max)
711          self.SetProperties(prop)          self.SetProperties(prop)
712    
713      def __copy__(self):      def __copy__(self):
714          return ClassGroupRange(self.min, self.max, self.prop, self.label)          return ClassGroupRange(self.GetMin(),
715                                   self.GetMax(),
716                                   self.GetProperties(),
717                                   self.GetLabel())
718    
719        def __deepcopy__(self, memo):
720            return ClassGroupRange(copy.copy(self.GetMin()),
721                                   copy.copy(self.GetMax()),
722                                   copy.copy(self.GetProperties()),
723                                   copy.copy(self.GetLabel()))
724    
725      def GetMin(self):      def GetMin(self):
726            """Return the range's minimum value."""
727          return self.min          return self.min
728    
729      def SetMin(self, min):      def SetMin(self, min):
730            """Set the range's minimum value.
731        
732            min -- the new minimum. Note that this must be less than the current
733                   maximum value. Use SetRange() to change both min and max values.
734            """
735        
736          self.SetRange(min, self.max)          self.SetRange(min, self.max)
737    
738      def GetMax(self):      def GetMax(self):
739            """Return the range's maximum value."""
740          return self.max          return self.max
741    
742      def SetMax(self, max):      def SetMax(self, max):
743            """Set the range's maximum value.
744        
745            max -- the new maximum. Note that this must be greater than the current
746                   minimum value. Use SetRange() to change both min and max values.
747            """
748          self.SetRange(self.min, max)          self.SetRange(self.min, max)
749    
750      def SetRange(self, min, max):      def SetRange(self, min, max):
751            """Set a new range.
752    
753            Note that min must be strictly less than max.
754    
755            min -- the new minimum value
756            min -- the new maximum value
757            """
758    
759          if min >= max:          if min >= max:
760              raise ValueError(_("ClassGroupRange: %i(min) >= %i(max)!") %              raise ValueError(_("ClassGroupRange: %i(min) >= %i(max)!") %
761                               (min, max))                               (min, max))
# Line 400  class ClassGroupRange(ClassGroup): Line 763  class ClassGroupRange(ClassGroup):
763          self.max = max          self.max = max
764    
765      def GetRange(self):      def GetRange(self):
766            """Return the range as a tuple (min, max)"""
767          return (self.min, self.max)          return (self.min, self.max)
768    
769      def Matches(self, value):      def Matches(self, value):
770          return self.min <= value < self.max          """Determine if the given value lies with the current range.
771    
772      def GetProperties(self, value = None):          The following check is used: min <= value < max.
773          if value is None: return self.prop          """
774    
775          if self.Matches(value):          return self.min <= value < self.max
776              return self.prop  
777          else:      def GetProperties(self):
778              return None          """Return the Properties associated with this Group."""
779            return self.prop
780    
781      def SetProperties(self, prop):      def SetProperties(self, prop):
782            """Set the properties associated with this Group.
783    
784            prop -- a ClassGroupProperties object. if prop is None,
785                    a default set of properties is created.
786            """
787          if prop is None: prop = ClassGroupProperties()          if prop is None: prop = ClassGroupProperties()
788          assert(isinstance(prop, ClassGroupProperties))          assert isinstance(prop, ClassGroupProperties)
789          self.prop = prop          self.prop = prop
790    
791        def GetDisplayText(self):
792            label = self.GetLabel()
793    
794            if label != "": return label
795    
796            return _("%s - %s") % (self.GetMin(), self.GetMax())
797    
798        def __eq__(self, other):
799            return isinstance(other, ClassGroupRange) \
800                and self.GetProperties() == other.GetProperties() \
801                and self.GetRange() == other.GetRange()
802    
803        def __ne__(self, other):
804            return not self.__eq__(other)
805    
806  class ClassGroupMap(ClassGroup):  class ClassGroupMap(ClassGroup):
807        """Currently, this class is not used."""
808    
809      FUNC_ID = "id"      FUNC_ID = "id"
810    
811      def __init__(self, map_type = FUNC_ID, func = None, prop = None, label=""):      def __init__(self, map_type = FUNC_ID, func = None, prop = None, label=""):
812          ClassGroup.__init__(self, prop)          ClassGroup.__init__(self, label)
813    
814          self.map_type = map_type          self.map_type = map_type
815          self.func = func          self.func = func
# Line 434  class ClassGroupMap(ClassGroup): Line 820  class ClassGroupMap(ClassGroup):
820      def Map(self, value):      def Map(self, value):
821          return self.func(value)          return self.func(value)
822    
823        def GetProperties(self):
824            return None
825    
826        def GetPropertiesFromValue(self, value):
827            pass
828    
829        def GetDisplayText(self):
830            return "Map: " + self.map_type
831    
832      #      #
833      # built-in mappings      # built-in mappings
834      #      #

Legend:
Removed from v.453  
changed lines
  Added in v.613

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26