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

Legend:
Removed from v.381  
changed lines
  Added in v.960

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26