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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26