/[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 397 by jonathan, Tue Feb 11 14:23:32 2003 UTC revision 679 by jonathan, Tue Apr 15 19:46:37 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001 by Intevation GmbH  # Copyright (c) 2001, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jonathan Coles <[email protected]>  # Jonathan Coles <[email protected]>
4  #  #
# Line 16  an input value falls with a range that d Line 16  an input value falls with a range that d
16  If no mapping can be found then default data will  If no mapping can be found then default data will
17  be returned. Input values must be hashable objects  be returned. Input values must be hashable objects
18    
19  See the description of getProperties() for more information  See the description of FindGroup() for more information
20  on the mapping algorithm.  on the mapping algorithm.
21  """  """
22        
23  # fix for people using python2.1  # fix for people using python2.1
24  from __future__ import nested_scopes  from __future__ import nested_scopes
25    
26  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \  import copy
      LAYER_VISIBILITY_CHANGED  
27    
28  from Thuban import _  from Thuban import _
 from Thuban.Model.color import Color  
29    
30  from wxPython.wx import *  from types import *
31    
32    from messages import \
33        LAYER_PROJECTION_CHANGED, \
34        LAYER_LEGEND_CHANGED, \
35        LAYER_VISIBILITY_CHANGED
36    
37    from Thuban.Model.color import Color
38    
39  # constants  import Thuban.Model.layer
 RANGE_MIN  = 0  
 RANGE_MAX  = 1  
 RANGE_DATA = 2  
40    
41  class Classification:  class Classification:
42        """Encapsulates the classification of layer.
43        
44        The Classification divides some kind of data into Groups which
45        are associated with properties. Later the properties can be
46        retrieved by matching data values to the appropriate group.
47        """
48    
49      def __init__(self, layer, field = None):      def __init__(self, layer = None, field = None):
50          """Initialize a classification.          """Initialize a classification.
51    
52             layer -- the layer object who owns this classification          layer -- the Layer object who owns this classification
53    
54             field -- the name of the data table field that          field -- the name of the data table field that
55                      is to be used to classify layer properties                   is to be used to classify layer properties
56          """          """
57    
58          self.layer = layer          self.layer = None
59          self.points = {}          self.field = None
60          self.ranges = []          self.fieldType = None
61          self.DefaultData = ClassData()          self.__groups = []
62          self.field = field  
63          #self.SetField(field)          self.__setLayerLock = False
64    
65            self.SetDefaultGroup(ClassGroupDefault())
66    
67            self.SetLayer(layer)
68            self.SetField(field)
69    
70        def __iter__(self):
71            return ClassIterator(self.__groups)
72    
73        def __deepcopy__(self, memo):
74            clazz = Classification()
75    
76            # 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):      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 the default data          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          self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)  
124            self.__SendNotification()
125    
126      def GetField(self):      def GetField(self):
127            """Return the name of the field."""
128          return self.field          return self.field
129    
130      def SetDefaultData(self, data):      def GetFieldType(self):
131          """Set the data to be used when a value can't be classified.          """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            A ValueError is raised if the owning layer is not None and
138            'type' is different from the current field type.
139            """
140    
141            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             data -- data that the value maps to. See class description.      def SetLayer(self, layer):
149            """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          self.DefaultData = data          # prevent infinite recursion when calling SetClassification()
156            if self.__setLayerLock: return
157    
158      def GetDefaultData(self):          self.__setLayerLock = True
159          return self.DefaultData  
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                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            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):      def SetDefaultFill(self, fill):
195          self.DefaultData.SetFill(fill)          """Set the default fill color.
196          self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)  
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):      def GetDefaultFill(self):
204          return self.DefaultData.GetFill()          """Return the default fill color."""
205            return self.GetDefaultGroup().GetProperties().GetFill()
206                    
207      def SetDefaultStroke(self, stroke):      def SetDefaultLineColor(self, color):
208          self.DefaultData.SetStroke(stroke)          """Set the default line color.
209          self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)  
210            color -- a Color object.
211            """
212            assert isinstance(color, Color)
213            self.GetDefaultGroup().GetProperties().SetLineColor(color)
214            self.__SendNotification()
215                    
216      def GetDefaultStroke(self):      def GetDefaultLineColor(self):
217          return self.DefaultData.GetStroke()          """Return the default line color."""
218            return self.GetDefaultGroup().GetProperties().GetLineColor()
219                    
220      def SetDefaultStrokeWidth(self, strokeWidth):      def SetDefaultLineWidth(self, lineWidth):
221          self.DefaultData.SetStrokeWidth(strokeWidth)          """Set the default line width.
222          self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)  
223            lineWidth -- an integer > 0.
224            """
225            assert isinstance(lineWidth, IntType)
226            self.GetDefaultGroup().GetProperties().SetLineWidth(lineWidth)
227            self.__SendNotification()
228                    
229      def GetDefaultStrokeWidth(self):      def GetDefaultLineWidth(self):
230          return self.DefaultData.GetStrokeWidth()          """Return the default line width."""
231            return self.GetDefaultGroup().GetProperties().GetLineWidth()
232                    
     def AddRange(self, min, max, data):  
         """Add a new range to the classification.  
233    
234             A range allows a value to be classified if it falls between      #
235             min and max. Specifically, min <= value < max      # 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             min -- the lower bound.      # 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             max -- the upper bound.      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          if min >= max:          assert isinstance(group, ClassGroupDefault)
249              raise ValueError(_("Range minimum >= maximum!"))          if len(self.__groups) > 0:
250          self.ranges.append([min, max, data])              self.__groups[0] = group
251          self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)          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            item -- this must be a valid ClassGroup object
262            """
263    
264            self.InsertGroup(self.GetNumGroups(), item)
265    
266        def InsertGroup(self, index, group):
267            
268            assert isinstance(group, ClassGroup)
269    
270            self.__groups.insert(index + 1, group)
271    
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      def AddPoint(self, value, data):          self.__groups[index + 1] = group
         """Associate a single value with data.  
281    
282             When this value is to be classified data will be returned.          self.__SendNotification()
283    
284             value -- classification value.      def GetGroup(self, index):
285            return self.__groups[index + 1]
286    
287             data  -- data that the value maps to. See class description.      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          self.points[value] = data          if self.GetField() is not None and value is not None:
         self.layer.changed(LAYER_LEGEND_CHANGED, self.layer)  
304    
305      def GetProperties(self, value):              for i in range(1, len(self.__groups)):
306          """Return the associated data, or the default data.                  group = self.__groups[i]
307                    if group.Matches(value):
308                        return group
309    
310             The following search technique is used:          return self.GetDefaultGroup()
                (1) if the field is None, return the default data  
                (2) check if the value exists as a single value  
                (3) check if the value falls within a range. Ranges  
                    are checked in the order they were added to  
                    the classification.  
   
            value -- the value to classify. If there is no mapping,  
                     or value is None, return the default data  
                     (which may be None)  
         """  
   
         if self.field is not None and value is not None:  
             #  
             # first check the discrete values  
             #  
             if self.points.has_key(value):  
                 return self.points[value]  
   
             #  
             # now check the ranges  
             #  
             for p in self.ranges:  
                 if (p[RANGE_MIN] <= value) and (value < p[RANGE_MAX]):  
                     return p[RANGE_DATA]  
311    
312        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          return self.DefaultData          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          # XXX: shouldn't print anything if there are no classifications              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          def color_string(color):  #       if self.iter is None:
405              if color is None:  #           try:
406                  return "None"  #               self.data_item = self.data_iter.next()
407              return "(%.3f, %.3f, %.3f)" % (color.red, color.green, color.blue)  #               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 build_item(data):      def __init__(self, props = None):
423              i = []          """Constructor.
424    
425              v = data.GetStroke()          props -- a ClassGroupProperties object. The class is copied if
426              i.append((_("Stroke: %s") % color_string(v), v))                   prop is not None. Otherwise, a default set of properties
427              v = data.GetStrokeWidth()                   is created such that: line color = Color.Black, line width = 1,
428              i.append((_("Stroke Width: %s") % v))                   and fill color = Color.Transparent
429              v = data.GetFill()          """
430              i.append((_("Fill: %s") % color_string(v), v))  
431              return i          #self.stroke = None
432            #self.strokeWidth = 0
433          items.append((_("'DEFAULT'"), build_item(self.DefaultData)))          #self.fill = None
434    
435          for name, data in self.points.items():          if props is not None:
436              items.append((_("%s") % name, build_item(data)))              self.SetProperties(props)
437            else:
438          for p in self.ranges:              self.SetLineColor(Color.Black)
439              data = p[RANGE_DATA]              self.SetLineWidth(1)
440              items.append((_("%s-%s") % (p[RANGE_MIN], p[RANGE_MAX])),              self.SetFill(Color.Transparent)
441                           build_item(data))  
442        def SetProperties(self, props):
443          return (_("Classifications"), items)          """Set this class's properties to those in class props."""
444    
445            assert isinstance(props, ClassGroupProperties)
446  class ClassData:          self.SetLineColor(props.GetLineColor())
447            self.SetLineWidth(props.GetLineWidth())
448      def __init__(self):          self.SetFill(props.GetFill())
449          self.stroke = None          
450          self.stroke_width = 0      def GetLineColor(self):
451          self.fill = None          """Return the line color as a Color object."""
452          self.label = ""          return self.__stroke
453        
454      def GetStroke(self):      def SetLineColor(self, color):
455          return self.stroke          """Set the line color.
456    
457      def SetStroke(self, stroke):          color -- the color of the line. This must be a Color object.
458          self.stroke = stroke          """
459    
460      def GetStrokeWidth(self):          assert isinstance(color, Color)
461          return self.stroke_width          self.__stroke = color
462    
463      def SetStrokeWidth(self, stroke_width):      def GetLineWidth(self):
464          self.stroke_width = stroke_width          """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):      def GetFill(self):
479          return self.fill          """Return the fill color as a Color object."""
480            return self.__fill
481    
482      def SetFill(self, fill):      def SetFill(self, fill):
483          self.fill = fill          """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            # 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            return not self.__eq__(other)
507    
508        def __copy__(self):
509            return ClassGroupProperties(self)
510    
511        def __deepcopy__(self):
512            return ClassGroupProperties(self)
513    
514    class ClassGroup:
515        """A base class for all Groups within a Classification"""
516    
517        def __init__(self, label = "", props = None, group = None):
518            """Constructor.
519    
520            label -- A string representing the Group's label
521            """
522    
523            if group is not None:
524                self.SetLabel(copy.copy(group.GetLabel()))
525                self.SetProperties(copy.copy(group.GetProperties()))
526                self.SetVisible(group.IsVisible())
527            else:
528                self.SetLabel(label)
529                self.SetProperties(props)
530                self.SetVisible(True)
531    
532      def GetLabel(self):      def GetLabel(self):
533            """Return the Group's label."""
534          return self.label          return self.label
535    
536      def SetLabel(self, label):      def SetLabel(self, label):
537            """Set the Group's label.
538    
539            label -- a string representing the Group's label. This must
540                     not be None.
541            """
542            assert isinstance(label, StringType)
543          self.label = label          self.label = label
544    
545        def GetDisplayText(self):
546            assert False, "GetDisplay must be overridden by subclass!"
547            return ""
548    
549        def Matches(self, value):
550            """Determines if this Group is associated with the given value.
551    
552            Returns False. This needs to be overridden by all subclasses.
553            """
554            assert False, "GetMatches must be overridden by subclass!"
555            return False
556    
557        def GetProperties(self):
558            """Return the properties associated with the given value."""
559    
560            return self.prop
561    
562        def SetProperties(self, prop):
563            """Set the properties associated with this Group.
564    
565            prop -- a ClassGroupProperties object. if prop is None,
566                    a default set of properties is created.
567            """
568    
569            if prop is None: prop = ClassGroupProperties()
570            assert isinstance(prop, ClassGroupProperties)
571            self.prop = prop
572    
573        def IsVisible(self):
574            return self.visible
575    
576        def SetVisible(self, visible):
577            self.visible = visible
578    
579        def __eq__(self, other):
580            return isinstance(other, ClassGroup) \
581                and self.GetProperties() == other.GetProperties()
582    
583        def __ne__(self, other):
584            return not self.__eq__(other)
585    
586        
587    class ClassGroupSingleton(ClassGroup):
588        """A Group that is associated with a single value."""
589    
590        def __init__(self, value = 0, props = None, label = "", group = None):
591            """Constructor.
592    
593            value -- the associated value.
594    
595            prop -- a ClassGroupProperites object. If prop is None a default
596                     set of properties is created.
597    
598            label -- a label for this group.
599            """
600            ClassGroup.__init__(self, label, props, group)
601    
602            self.SetValue(value)
603    
604        def __copy__(self):
605            return ClassGroupSingleton(self.GetValue(),
606                                       self.GetProperties(),
607                                       self.GetLabel())
608    
609        def __deepcopy__(self, memo):
610            return ClassGroupSingleton(self.GetValue(), group = self)
611    
612        def GetValue(self):
613            """Return the associated value."""
614            return self.__value
615    
616        def SetValue(self, value):
617            """Associate this Group with the given value."""
618            self.__value = value
619    
620        def Matches(self, value):
621            """Determine if the given value matches the associated Group value."""
622    
623            """Returns True if the value matches, False otherwise."""
624    
625            return self.__value == value
626    
627        def GetDisplayText(self):
628            label = self.GetLabel()
629    
630            if label != "": return label
631    
632            return str(self.GetValue())
633    
634        def __eq__(self, other):
635            return ClassGroup.__eq__(self, other) \
636                and isinstance(other, ClassGroupSingleton) \
637                and self.__value == other.__value
638    
639    class ClassGroupDefault(ClassGroup):
640        """The default Group. When values do not match any other
641           Group within a Classification, the properties from this
642           class are used."""
643    
644        def __init__(self, props = None, label = "", group = None):
645            """Constructor.
646    
647            prop -- a ClassGroupProperites object. If prop is None a default
648                     set of properties is created.
649    
650            label -- a label for this group.
651            """
652    
653            ClassGroup.__init__(self, label, props, group)
654    
655        def __copy__(self):
656            return ClassGroupDefault(self.GetProperties(), self.GetLabel())
657    
658        def __deepcopy__(self, memo):
659            return ClassGroupDefault(label = self.GetLabel(), group = self)
660    
661        def Matches(self, value):
662            return True
663    
664        def GetDisplayText(self):
665            label = self.GetLabel()
666    
667            if label != "": return label
668    
669            return _("DEFAULT")
670    
671        def __eq__(self, other):
672            return ClassGroup.__eq__(self, other) \
673                and isinstance(other, ClassGroupDefault) \
674                and self.GetProperties() == other.GetProperties()
675    
676    class ClassGroupRange(ClassGroup):
677        """A Group that represents a range of values that map to the same
678           set of properties."""
679    
680        def __init__(self, min = 0, max = 1, props = None, label = "", group=None):
681            """Constructor.
682    
683            The minumum value must be strictly less than the maximum.
684    
685            min -- the minimum range value
686    
687            max -- the maximum range value
688    
689            prop -- a ClassGroupProperites object. If prop is None a default
690                     set of properties is created.
691    
692            label -- a label for this group.
693            """
694    
695            ClassGroup.__init__(self, label, props, group)
696    
697            self.__min = self.__max = 0
698    
699            self.SetRange(min, max)
700    
701        def __copy__(self):
702            return ClassGroupRange(self.GetMin(),
703                                   self.GetMax(),
704                                   self.GetProperties(),
705                                   self.GetLabel())
706    
707        def __deepcopy__(self, memo):
708            return ClassGroupRange(copy.copy(self.GetMin()),
709                                   copy.copy(self.GetMax()),
710                                   group = self)
711    
712        def GetMin(self):
713            """Return the range's minimum value."""
714            return self.__min
715    
716        def SetMin(self, min):
717            """Set the range's minimum value.
718        
719            min -- the new minimum. Note that this must be less than the current
720                   maximum value. Use SetRange() to change both min and max values.
721            """
722        
723            self.SetRange(min, self.__max)
724    
725        def GetMax(self):
726            """Return the range's maximum value."""
727            return self.__max
728    
729        def SetMax(self, max):
730            """Set the range's maximum value.
731        
732            max -- the new maximum. Note that this must be greater than the current
733                   minimum value. Use SetRange() to change both min and max values.
734            """
735            self.SetRange(self.__min, max)
736    
737        def SetRange(self, min, max):
738            """Set a new range.
739    
740            Note that min must be strictly less than max.
741    
742            min -- the new minimum value
743            min -- the new maximum value
744            """
745    
746            if min >= max:
747                raise ValueError(_("ClassGroupRange: %i(min) >= %i(max)!") %
748                                 (min, max))
749            self.__min = min
750            self.__max = max
751    
752        def GetRange(self):
753            """Return the range as a tuple (min, max)"""
754            return (self.__min, self.__max)
755    
756        def Matches(self, value):
757            """Determine if the given value lies with the current range.
758    
759            The following check is used: min <= value < max.
760            """
761    
762            return self.__min <= value < self.__max
763    
764        def GetDisplayText(self):
765            label = self.GetLabel()
766    
767            if label != "": return label
768    
769            return _("%s - %s") % (self.GetMin(), self.GetMax())
770    
771        def __eq__(self, other):
772            return ClassGroup.__eq__(self, other) \
773                and isinstance(other, ClassGroupRange) \
774                and self.__min == other.__min \
775                and self.__max == other.__max
776    
777    class ClassGroupMap(ClassGroup):
778        """Currently, this class is not used."""
779    
780        FUNC_ID = "id"
781    
782        def __init__(self, map_type = FUNC_ID, func = None, prop = None, label=""):
783            ClassGroup.__init__(self, label)
784    
785            self.map_type = map_type
786            self.func = func
787    
788            if self.func is None:
789                self.func = func_id
790    
791        def Map(self, value):
792            return self.func(value)
793    
794        def GetProperties(self):
795            return None
796    
797        def GetPropertiesFromValue(self, value):
798            pass
799    
800        def GetDisplayText(self):
801            return "Map: " + self.map_type
802    
803        #
804        # built-in mappings
805        #
806        def func_id(value):
807            return value
808    

Legend:
Removed from v.397  
changed lines
  Added in v.679

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26