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

Legend:
Removed from v.385  
changed lines
  Added in v.1351

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26