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

Legend:
Removed from v.428  
changed lines
  Added in v.609

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26