/[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 388 by jonathan, Mon Feb 10 15:25:05 2003 UTC revision 613 by jonathan, Mon Apr 7 08:55:55 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001 by Intevation GmbH  # Copyright (c) 2001, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jonathan Coles <[email protected]>  # Jonathan Coles <[email protected]>
4  #  #
# Line 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 getProperties() for more information  See the description of FindGroup() for more information
20  on the mapping algorithm.  on the mapping algorithm.
21  """  """
22        
23  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \  # fix for people using python2.1
24       LAYER_VISIBILITY_CHANGED  from __future__ import nested_scopes
25    
26    import copy
27    
28  from Thuban import _  from Thuban import _
 from Thuban.Model.color import Color  
29    
30  from wxPython.wx import *  from types import *
31    
32    from messages import \
33        LAYER_PROJECTION_CHANGED, \
34        LAYER_LEGEND_CHANGED, \
35        LAYER_VISIBILITY_CHANGED
36    
37  # constants  from Thuban.Model.color import Color
38  RANGE_MIN  = 0  
39  RANGE_MAX  = 1  import Thuban.Model.layer
 RANGE_DATA = 2  
40    
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, 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 = layer          self.layer = None
59          self.points = {}          self.field = None
60          self.ranges = []          self.fieldType = None
61          self.DefaultData = ClassData()          self.__groups = []
62          self.field = field  
63          #self.SetField(field)          self.__setLayerLock = False
64    
65            self.SetDefaultGroup(ClassGroupDefault())
66    
67            self.SetLayer(layer)
68            self.SetField(field)
69    
70        def __iter__(self):
71            return ClassIterator(self.__groups)
72    
73        def __deepcopy__(self, memo):
74            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            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:
87                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 == "":
100                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.layer.changed(LAYER_LEGEND_CHANGED, self.layer)  
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 SetDefaultData(self, data):      def GetFieldType(self):
129          """Set the data to be used when a value can't be classified.          """Return the field type."""
130            return self.fieldType
131    
132        def SetFieldType(self, type):
133            """Set the type of the field used by this classification.
134    
135            A ValueError is raised if the owning layer is not None and
136            'type' is different from the current field type.
137            """
138    
139            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             data -- data that the value maps to. See class description.      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          self.DefaultData = data          # prevent infinite recursion when calling SetClassification()
154            if self.__setLayerLock: return
155    
156      def GetDefaultData(self):          self.__setLayerLock = True
157          return self.DefaultData  
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    
185    
186        #
187        # these SetDefault* methods are really only provided for
188        # some backward compatibility. they should be considered
189        # for removal once all the classification code is finished.
190        #
191    
192      def SetDefaultFill(self, fill):      def SetDefaultFill(self, fill):
193          self.DefaultData.SetFill(fill)          """Set the default fill color.
194          self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)  
195            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.DefaultData.GetFill()          """Return the default fill color."""
203            return self.GetDefaultGroup().GetProperties().GetFill()
204                    
205      def SetDefaultStroke(self, stroke):      def SetDefaultLineColor(self, color):
206          self.DefaultData.SetStroke(stroke)          """Set the default line color.
207          self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)  
208            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.DefaultData.GetStroke()          """Return the default line color."""
216            return self.GetDefaultGroup().GetProperties().GetLineColor()
217                    
218      def SetDefaultStrokeWidth(self, strokeWidth):      def SetDefaultLineWidth(self, lineWidth):
219          self.DefaultData.SetStrokeWidth(strokeWidth)          """Set the default line width.
220          self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)  
221            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.DefaultData.GetStrokeWidth()          """Return the default line width."""
229            return self.GetDefaultGroup().GetProperties().GetLineWidth()
230                    
     def AddRange(self, min, max, data):  
         """Add a new range to the classification.  
231    
232             A range allows a value to be classified if it falls between      #
233             min and max. Specifically, min <= value < max      # The methods that manipulate self.__groups have to be kept in
234                # sync. We store the default group in index 0 to make it
235             min -- the lower bound.      # convienent to iterate over the classification's groups, but
236        # from the user's perspective the first (non-default) group is
237        # at index 0 and the DefaultGroup is a special entity.
238        #
239    
240             max -- the upper bound.      def SetDefaultGroup(self, group):
241            """Set the group to be used when a value can't be classified.
242    
243             data -- data that the value maps to. See class description.          group -- group that the value maps to.
244          """          """
245    
246          if min >= max:          assert isinstance(group, ClassGroupDefault)
247              raise ValueError(_("Range minimum >= maximum!"))          if len(self.__groups) > 0:
248          self.ranges.append([min, max, data])              self.__groups[0] = group
249          self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)          else:
250                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.__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      def AddPoint(self, value, data):          self.__SendNotification()
         """Associate a single value with data.  
281    
282             When this value is to be classified data will be returned.      def GetGroup(self, index):
283            return self.__groups[index + 1]
284    
285             value -- classification value.      def GetNumGroups(self):
286            """Return the number of non-default groups in the classification."""
287            return len(self.__groups) - 1
288    
289             data  -- data that the value maps to. See class description.  
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          self.points[value] = data          if self.GetField() is not None and value is not None:
         self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)  
302    
303      def GetProperties(self, value):              for i in range(1, len(self.__groups)):
304          """Return the associated data, or the default data.                  group = self.__groups[i]
305                    if group.Matches(value):
306                        return group
307    
308             The following search technique is used:          return self.GetDefaultGroup()
                (1) if the field is None, return the default data  
                (2) check if the value exists as a single value  
                (3) check if the value falls within a range. Ranges  
                    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 data  
                     (which may be None)  
         """  
   
         if self.field is not None and value is not None:  
             #  
             # first check the discrete values  
             #  
             if self.points.has_key(value):  
                 return self.points[value]  
   
             #  
             # now check the ranges  
             #  
             for p in self.ranges:  
                 if (p[RANGE_MIN] <= value) and (value < p[RANGE_MAX]):  
                     return p[RANGE_DATA]  
309    
310        def GetProperties(self, value):
311            """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          return self.DefaultData          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):
328          # XXX: shouldn't print anything if there are no classifications              if color is Color.Transparent:
329          #                  return ("%s: %s" % (text, _("None")), None)
330    
331                return ("%s: (%.3f, %.3f, %.3f)" %
332                        (text, color.red, color.green, color.blue),
333                        color)
334    
335            def build_item(group, string):
336                label = group.GetLabel()
337                if label == "":
338                    label = string
339                else:
340                    label += " (%s)" % string
341    
342                        props = group.GetProperties()
         def color_string(color):  
             if color is None:  
                 return "None"  
             return "(%.3f, %.3f, %.3f)" % (color.red, color.green, color.blue)  
   
         def build_item(data):  
343              i = []              i = []
344                v = props.GetLineColor()
345                i.append(build_color_item(_("Line Color"), v))
346                v = props.GetLineWidth()
347                i.append(_("Line Width: %s") % v)
348                v = props.GetFill()
349                i.append(build_color_item(_("Fill"), v))
350                return (label, i)
351    
352            for p in self:
353                items.append(build_item(p, p.GetDisplayText()))
354    
355    #           if isinstance(p, ClassGroupDefault):
356    #               items.append(build_item(self.GetDefaultGroup(), _("'DEFAULT'")))
357    #           elif isinstance(p, ClassGroupSingleton):
358    #               items.append(build_item(p, str(p.GetValue())))
359    #           elif isinstance(p, ClassGroupRange):
360    #               items.append(build_item(p, "%s - %s" %
361    #                                          (p.GetMin(), p.GetMax())))
362    
363              v = data.GetStroke()          return (_("Classification"), items)
364              i.append((_("Stroke: %s") % color_string(v), v))  
365              v = data.GetStrokeWidth()  class ClassIterator:
366              i.append((_("Stroke Width: %s") % v))      """Allows the Groups in a Classifcation to be interated over.
             v = data.GetFill()  
             i.append((_("Fill: %s") % color_string(v), v))  
             return i  
367    
368          items.append((_("'DEFAULT'"), build_item(self.DefaultData)))      The items are returned in the following order:
369            default data, singletons, ranges, maps
370        """
371    
372          for name, data in self.points.items():      def __init__(self, data): #default, points, ranges, maps):
373              items.append((_("%s") % name, build_item(data)))          """Constructor.
374    
375          for p in self.ranges:          default -- the default group
376              data = p[RANGE_DATA]  
377              items.append((_("%s-%s") % (p[RANGE_MIN], p[RANGE_MAX])),          points -- a list of singleton groups
                          build_item(data))  
378    
379          return (_("Classifications"), items)          ranges -- a list of range groups
380    
381            maps -- a list of map groups
382            """
383    
384  class ClassData:          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):
390            return self
391    
392        def next(self):
393            """Return the next item."""
394    
395            if self.data_index >= len(self.data):
396                raise StopIteration
397            else:
398                d = self.data[self.data_index]
399                self.data_index += 1
400                return d
401            
402    #       if self.iter is None:
403    #           try:
404    #               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:
416        """Represents the properties of a single Classification Group.
417      
418        These are used when rendering a layer."""
419    
420        def __init__(self, props = None):
421            """Constructor.
422    
423            props -- a ClassGroupProperties object. The class is copied if
424                     prop is not None. Otherwise, a default set of properties
425                     is created such that: line color = Color.Black, line width = 1,
426                     and fill color = Color.Transparent
427            """
428    
     def __init__(self):  
429          self.stroke = None          self.stroke = None
430          self.stroke_width = 0          self.strokeWidth = 0
431          self.fill = None          self.fill = None
432          self.label = ""  
433                if props is not None:
434      def GetStroke(self):              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          self.stroke = stroke          """Set the line color.
454    
455            color -- the color of the line. This must be a Color object.
456            """
457    
458            assert isinstance(color, Color)
459            self.stroke = color
460    
461        def GetLineWidth(self):
462            """Return the line width."""
463            return self.strokeWidth
464    
465      def GetStrokeWidth(self):      def SetLineWidth(self, lineWidth):
466          return self.stroke_width          """Set the line width.
467    
468      def SetStrokeWidth(self, stroke_width):          lineWidth -- the new line width. This must be > 0.
469          self.stroke_width = stroke_width          """
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            """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:
507        """A base class for all Groups within a Classification"""
508    
509        def __init__(self, label = ""):
510            """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):
537            """Determines if this Group is associated with the given value.
538    
539            Returns False. This needs to be overridden by all subclasses.
540            """
541            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):
554        """A Group that is associated with a single value."""
555    
556        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)
567    
568            self.prop = None
569            self.value = None
570    
571            self.SetValue(value)
572            self.SetProperties(prop)
573    
574        def __copy__(self):
575            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):
585            """Return the associated value."""
586            return self.value
587    
588        def SetValue(self, value):
589            """Associate this Group with the given value."""
590            self.value = value
591    
592        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
598    
599        def GetProperties(self):
600            """Return the Properties associated with this Group."""
601    
602            return self.prop
603    
604        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()
612            assert isinstance(prop, ClassGroupProperties)
613            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    
635        def __init__(self, prop = None, label = ""):
636            """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):
648            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):
658            """Return the Properties associated with this Group."""
659            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):
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 = ""):
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)
706    
707            self.min = self.max = 0
708            self.prop = None
709    
710            self.SetRange(min, max)
711            self.SetProperties(prop)
712    
713        def __copy__(self):
714            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):
726            """Return the range's minimum value."""
727            return self.min
728    
729        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)
737    
738        def GetMax(self):
739            """Return the range's maximum value."""
740            return self.max
741    
742        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)
749    
750        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:
760                raise ValueError(_("ClassGroupRange: %i(min) >= %i(max)!") %
761                                 (min, max))
762            self.min = min
763            self.max = max
764    
765        def GetRange(self):
766            """Return the range as a tuple (min, max)"""
767            return (self.min, self.max)
768    
769        def Matches(self, value):
770            """Determine if the given value lies with the current range.
771    
772            The following check is used: min <= value < max.
773            """
774    
775            return self.min <= value < self.max
776    
777        def GetProperties(self):
778            """Return the Properties associated with this Group."""
779            return self.prop
780    
781        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()
788            assert isinstance(prop, ClassGroupProperties)
789            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):
807        """Currently, this class is not used."""
808    
809        FUNC_ID = "id"
810    
811        def __init__(self, map_type = FUNC_ID, func = None, prop = None, label=""):
812            ClassGroup.__init__(self, label)
813    
814            self.map_type = map_type
815            self.func = func
816    
817            if self.func is None:
818                self.func = func_id
819    
820        def Map(self, value):
821            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
834        #
835        def func_id(value):
836            return value
837    

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26