/[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 453 by bh, Tue Mar 4 11:31:39 2003 UTC revision 643 by jonathan, Thu Apr 10 17:55:57 2003 UTC
# 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 GetGroup() 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    import copy
27    
28    from Thuban import _
29    
30  from types import *  from types import *
31    
32  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \  from messages import \
33       LAYER_VISIBILITY_CHANGED      LAYER_PROJECTION_CHANGED, \
34        LAYER_LEGEND_CHANGED, \
35        LAYER_VISIBILITY_CHANGED
36    
 from Thuban import _  
37  from Thuban.Model.color import Color  from Thuban.Model.color import Color
38    
39  import Thuban.Model.layer  import Thuban.Model.layer
40    
   
 # constants  
 RANGE_MIN  = 0  
 RANGE_MAX  = 1  
 RANGE_DATA = 2  
   
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 = 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 = None # stop message sending          self.layer = None
59            self.field = None
60            self.fieldType = None
61            self.__groups = []
62    
63            self.__setLayerLock = False
64    
65          self.SetDefaultGroup(ClassGroupDefault())          self.SetDefaultGroup(ClassGroupDefault())
         self.SetField(field)  
66    
67          self.layer = layer          self.SetLayer(layer)
68          self.points = []          self.SetField(field)
         self.ranges = []  
         self.maps   = []  
69    
70      def __iter__(self):      def __iter__(self):
71          return ClassIterator(self.DefaultGroup,          return ClassIterator(self.__groups)
72                               self.points,  
73                               self.ranges,      def __deepcopy__(self, memo):
74                               self.maps)          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      def __SendMessage(self, message):          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:          if self.layer is not None:
89              self.layer.changed(message, self.layer)              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 == "":          if field == "":
102              field = None              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.__SendMessage(LAYER_LEGEND_CHANGED)  
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 SetLayer(self, layer):      def GetFieldType(self):
131          assert(isinstance(layer, Thuban.Model.layer.Layer))          """Return the field type."""
132          self.layer = layer          return self.fieldType
         self.__SendMessage(LAYER_LEGEND_CHANGED)  
133    
134      def GetLayer(self):      def SetFieldType(self, type):
135          return layer.self          """Set the type of the field used by this classification.
136    
137      def SetDefaultGroup(self, group):          A ValueError is raised if the owning layer is not None and
138          """Set the group to be used when a value can't be classified.          'type' is different from the current field type.
139            """
140    
141             group -- group that the value maps to. See class description.          if type != self.fieldType:
142                if self.layer is not None:
143                    raise ValueError()
144                else:
145                    self.fieldType = type
146                    self.__SendNotification()
147    
148        def 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          assert(isinstance(group, ClassGroupDefault))          # prevent infinite recursion when calling SetClassification()
156          self.DefaultGroup = group          if self.__setLayerLock: return
157    
158            self.__setLayerLock = True
159    
160            if layer is None:
161                if self.layer is not None:
162                    l = self.layer
163                    self.layer = None
164                    l.SetClassification(None)
165            else:
166                assert isinstance(layer, Thuban.Model.layer.Layer)
167    
168                old_layer = self.layer
169    
170                self.layer = layer
171    
172                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    
     def GetDefaultGroup(self):  
         return self.DefaultGroup  
187    
188      #      #
189      # these SetDefault* methods are really only provided for      # these SetDefault* methods are really only provided for
# Line 112  class Classification: Line 192  class Classification:
192      #      #
193    
194      def SetDefaultFill(self, fill):      def SetDefaultFill(self, fill):
195          assert(isinstance(fill, Color))          """Set the default fill color.
196          self.DefaultGroup.GetProperties().SetFill(fill)  
197          self.__SendMessage(LAYER_LEGEND_CHANGED)          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.DefaultGroup.GetProperties().GetFill()          """Return the default fill color."""
205            return self.GetDefaultGroup().GetProperties().GetFill()
206                    
207      def SetDefaultStroke(self, stroke):      def SetDefaultLineColor(self, color):
208          assert(isinstance(stroke, Color))          """Set the default line color.
209          self.DefaultGroup.GetProperties().SetStroke(stroke)  
210          self.__SendMessage(LAYER_LEGEND_CHANGED)          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.DefaultGroup.GetProperties().GetStroke()          """Return the default line color."""
218            return self.GetDefaultGroup().GetProperties().GetLineColor()
219                    
220      def SetDefaultStrokeWidth(self, strokeWidth):      def SetDefaultLineWidth(self, lineWidth):
221          assert(isinstance(strokeWidth, IntType))          """Set the default line width.
222          self.DefaultGroup.GetProperties().SetStrokeWidth(strokeWidth)  
223          self.__SendMessage(LAYER_LEGEND_CHANGED)          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.DefaultGroup.GetProperties().GetStrokeWidth()          """Return the default line width."""
231            return self.GetDefaultGroup().GetProperties().GetLineWidth()
232                    
     def AddGroup(self, item):  
         assert(isinstance(item, ClassGroup))  
233    
234          if isinstance(item, ClassGroupDefault):      #
235              self.SetDefaultGroup(item)      # The methods that manipulate self.__groups have to be kept in
236          elif isinstance(item, ClassGroupSingleton):      # sync. We store the default group in index 0 to make it
237              self.points.append(item)      # convienent to iterate over the classification's groups, but
238          elif isinstance(item, ClassGroupRange):      # from the user's perspective the first (non-default) group is
239              self.ranges.append(item)      # at index 0 and the DefaultGroup is a special entity.
240          elif isinstance(item, ClassGroupMap):      #
241              self.maps.append(item)  
242        def SetDefaultGroup(self, group):
243            """Set the group to be used when a value can't be classified.
244    
245            group -- group that the value maps to.
246            """
247    
248            assert isinstance(group, ClassGroupDefault)
249            if len(self.__groups) > 0:
250                self.__groups[0] = group
251          else:          else:
252              raise ValueError(_("Unrecognized ClassGroup"))              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.__SendMessage(LAYER_LEGEND_CHANGED)          self.InsertGroup(self.GetNumGroups(), item)
265    
266      def GetGroup(self, value):      def InsertGroup(self, index, group):
267          """Return the associated data, or the default data.          
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            self.__groups[index + 1] = group
281    
282             The following search technique is used:          self.__SendNotification()
                (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 properties  
         """  
   
         if self.field is not None and value is not None:  
   
             for p in self:  
                 if p.Matches(value):  
                     return p  
 #           #  
 #           # check the discrete values  
 #           #  
 #           if self.points.has_key(value):  
 #               return self.points[value]  
 #           #for p in self.points:  
 #               #if p.Value  
   
 #           #  
 #           # 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  
283    
284          return self.DefaultGroup      def GetGroup(self, index):
285            return self.__groups[index + 1]
286    
287        def GetNumGroups(self):
288            """Return the number of non-default groups in the classification."""
289            return len(self.__groups) - 1
290    
291    
292        def FindGroup(self, value):
293            """Return the associated group, or the default group.
294    
295            Groups are checked in the order the were added to the
296            Classification.
297    
298            value -- the value to classify. If there is no mapping,
299                     the field is None or value is None,
300                     return the default properties
301            """
302    
303            if self.GetField() is not None and value is not None:
304    
305                for i in range(1, len(self.__groups)):
306                    group = self.__groups[i]
307                    if group.Matches(value):
308                        return group
309    
310            return self.GetDefaultGroup()
311    
312      def GetProperties(self, value):      def GetProperties(self, value):
313          return self.GetGroup(value).GetProperties()          """Return the properties associated with the given value.
314          
315            Use this function rather than Classification.FindGroup().GetProperties()
316            since the returned group may be a ClassGroupMap which doesn't support
317            a call to GetProperties().
318            """
319    
320            group = self.FindGroup(value)
321            if isinstance(group, ClassGroupMap):
322                return group.GetPropertiesFromValue(value)
323            else:
324                return group.GetProperties()
325    
326      def TreeInfo(self):      def TreeInfo(self):
327          items = []          items = []
328    
329          def build_color_item(text, color):          def build_color_item(text, color):
330              if color is Color.None:              if color is Color.Transparent:
331                  return ("%s: %s" % (text, _("None")), None)                  return ("%s: %s" % (text, _("None")), None)
332    
333              return ("%s: (%.3f, %.3f, %.3f)" %              return ("%s: (%.3f, %.3f, %.3f)" %
# Line 218  class Classification: Line 343  class Classification:
343    
344              props = group.GetProperties()              props = group.GetProperties()
345              i = []              i = []
346              v = props.GetStroke()              v = props.GetLineColor()
347              i.append(build_color_item(_("Stroke"), v))              i.append(build_color_item(_("Line Color"), v))
348              v = props.GetStrokeWidth()              v = props.GetLineWidth()
349              i.append(_("Stroke Width: %s") % v)              i.append(_("Line Width: %s") % v)
350              v = props.GetFill()              v = props.GetFill()
351              i.append(build_color_item(_("Fill"), v))              i.append(build_color_item(_("Fill"), v))
352              return (label, i)              return (label, i)
353    
354          for p in self:          for p in self:
355              if isinstance(p, ClassGroupDefault):              items.append(build_item(p, p.GetDisplayText()))
                 items.append(build_item(self.DefaultGroup, _("'DEFAULT'")))  
             elif isinstance(p, ClassGroupSingleton):  
                 items.append(build_item(p, str(p.GetValue())))  
             elif isinstance(p, ClassGroupRange):  
                 items.append(build_item(p, "%s - %s" %  
                                            (p.GetMin(), p.GetMax())))  
356    
357  #       for p in self.points.values():  #           if isinstance(p, ClassGroupDefault):
358  #           items.append(build_item(p, str(p.GetValue())))  #               items.append(build_item(self.GetDefaultGroup(), _("'DEFAULT'")))
359    #           elif isinstance(p, ClassGroupSingleton):
360  #       for p in self.ranges:  #               items.append(build_item(p, str(p.GetValue())))
361  #           items.append(build_item(p, "%s - %s" % (p.GetMin(), p.GetMax())))  #           elif isinstance(p, ClassGroupRange):
362    #               items.append(build_item(p, "%s - %s" %
363    #                                          (p.GetMin(), p.GetMax())))
364    
365          return (_("Classification"), items)          return (_("Classification"), items)
366    
367  class ClassIterator:  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      def __init__(self, default, points, ranges, maps):          default -- the default group
378          self.data = [default, points, ranges, maps]  
379          self.data_iter = iter(self.data)          points -- a list of singleton groups
380          self.iter = None  
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):      def __iter__(self):
392          return self          return self
393    
394      def next(self):      def next(self):
395          if self.iter is None:          """Return the next item."""
396              try:  
397                  self.data_item = self.data_iter.next()          if self.data_index >= len(self.data):
398                  self.iter = iter(self.data_item)              raise StopIteration
399              except TypeError:          else:
400                  return self.data_item              d = self.data[self.data_index]
401                self.data_index += 1
402          try:              return d
403              return self.iter.next()          
404          except StopIteration:  #       if self.iter is None:
405              self.iter = None  #           try:
406              return self.next()  #               self.data_item = self.data_iter.next()
407    #               self.iter = iter(self.data_item)
408    #           except TypeError:
409    #               return self.data_item
410    
411    #       try:
412    #           return self.iter.next()
413    #       except StopIteration:
414    #           self.iter = None
415    #           return self.next()
416                
417  class ClassGroupProperties:  class ClassGroupProperties:
418        """Represents the properties of a single Classification Group.
419      
420        These are used when rendering a layer."""
421    
422      def __init__(self, prop = None):      def __init__(self, props = None):
423            """Constructor.
424    
425          if prop is not None:          props -- a ClassGroupProperties object. The class is copied if
426              self.SetStroke(prop.GetStroke())                   prop is not None. Otherwise, a default set of properties
427              self.SetStrokeWidth(prop.GetStrokeWidth())                   is created such that: line color = Color.Black, line width = 1,
428              self.SetFill(prop.GetFill())                   and fill color = Color.Transparent
429          else:          """
             self.SetStroke(Color.None)  
             self.SetStrokeWidth(1)  
             self.SetFill(Color.None)  
430    
431      def GetStroke(self):          #self.stroke = None
432            #self.strokeWidth = 0
433            #self.fill = None
434    
435            if props is not None:
436                self.SetProperties(props)
437            else:
438                self.SetLineColor(Color.Black)
439                self.SetLineWidth(1)
440                self.SetFill(Color.Transparent)
441    
442        def SetProperties(self, props):
443            """Set this class's properties to those in class props."""
444    
445            assert isinstance(props, ClassGroupProperties)
446            self.SetLineColor(props.GetLineColor())
447            self.SetLineWidth(props.GetLineWidth())
448            self.SetFill(props.GetFill())
449            
450        def GetLineColor(self):
451            """Return the line color as a Color object."""
452          return self.stroke          return self.stroke
453    
454      def SetStroke(self, stroke):      def SetLineColor(self, color):
455          assert(isinstance(stroke, Color))          """Set the line color.
456          self.stroke = stroke  
457            color -- the color of the line. This must be a Color object.
458      def GetStrokeWidth(self):          """
459          return self.stroke_width  
460            assert isinstance(color, Color)
461      def SetStrokeWidth(self, stroke_width):          self.stroke = color
462          assert(isinstance(stroke_width, IntType))  
463          if (stroke_width < 1):      def GetLineWidth(self):
464              raise ValueError(_("stroke_width < 1"))          """Return the line width."""
465            return self.strokeWidth
466    
467        def SetLineWidth(self, lineWidth):
468            """Set the line width.
469    
470          self.stroke_width = stroke_width          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 the fill color as a Color object."""
480          return self.fill          return self.fill
481    
482      def SetFill(self, fill):      def SetFill(self, fill):
483          assert(isinstance(fill, Color))          """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          self.fill = fill
490    
491        def __eq__(self, other):
492            """Return true if 'props' has the same attributes as this class"""
493    
494            return isinstance(other, ClassGroupProperties)   \
495                and self.stroke      == other.GetLineColor() \
496                and self.strokeWidth == other.GetLineWidth() \
497                and self.fill        == other.GetFill()
498    
499        def __ne__(self, other):
500            return not self.__eq__(other)
501    
502        def __copy__(self):
503            return ClassGroupProperties(self)
504    
505        def __deepcopy__(self):
506            return ClassGroupProperties(self)
507    
508  class ClassGroup:  class ClassGroup:
509        """A base class for all Groups within a Classification"""
510    
511      def __init__(self, label = ""):      def __init__(self, label = "", props = None, group = None):
512          self.label = label          """Constructor.
513    
514            label -- A string representing the Group's label
515            """
516    
517            if group is not None:
518                self.SetLabel(copy.copy(group.GetLabel()))
519                self.SetProperties(copy.copy(group.GetProperties()))
520                self.SetVisible(group.IsVisible())
521            else:
522                self.SetLabel(label)
523                self.SetProperties(props)
524                self.SetVisible(True)
525    
526      def GetLabel(self):      def GetLabel(self):
527            """Return the Group's label."""
528          return self.label          return self.label
529    
530      def SetLabel(self, label):      def SetLabel(self, label):
531            """Set the Group's label.
532    
533            label -- a string representing the Group's label. This must
534                     not be None.
535            """
536            assert isinstance(label, StringType)
537          self.label = label          self.label = label
538    
539        def GetDisplayText(self):
540            assert False, "GetDisplay must be overridden by subclass!"
541            return ""
542    
543      def Matches(self, value):      def Matches(self, value):
544          """This needs to be implemented by all subclasses."""          """Determines if this Group is associated with the given value.
         pass  
545    
546      def GetProperties(self, value):          Returns False. This needs to be overridden by all subclasses.
547          """This needs to be implemented by all subclasses."""          """
548          pass          assert False, "GetMatches must be overridden by subclass!"
549            return False
550    
551        def GetProperties(self):
552            """Return the properties associated with the given value."""
553    
554            return self.prop
555    
556        def SetProperties(self, prop):
557            """Set the properties associated with this Group.
558    
559            prop -- a ClassGroupProperties object. if prop is None,
560                    a default set of properties is created.
561            """
562    
563            if prop is None: prop = ClassGroupProperties()
564            assert isinstance(prop, ClassGroupProperties)
565            self.prop = prop
566    
567        def IsVisible(self):
568            return self.visible
569    
570        def SetVisible(self, visible):
571            self.visible = visible
572    
573        def __eq__(self, other):
574            return isinstance(other, ClassGroup) \
575                and self.GetProperties() == other.GetProperties()
576    
577        def __ne__(self, other):
578            return not self.__eq__(other)
579    
580            
581  class ClassGroupSingleton(ClassGroup):  class ClassGroupSingleton(ClassGroup):
582        """A Group that is associated with a single value."""
583    
584      def __init__(self, value = 0, prop = None, label = ""):      def __init__(self, value = 0, props = None, label = "", group = None):
585          ClassGroup.__init__(self, label)          """Constructor.
586    
587            value -- the associated value.
588    
589            prop -- a ClassGroupProperites object. If prop is None a default
590                     set of properties is created.
591    
592            label -- a label for this group.
593            """
594            ClassGroup.__init__(self, label, props, group)
595    
596          self.SetValue(value)          self.SetValue(value)
         self.SetProperties(prop)  
597    
598      def __copy__(self):      def __copy__(self):
599          return ClassGroupSingleton(self.value, self.prop, self.label)          return ClassGroupSingleton(self.GetValue(),
600                                       self.GetProperties(),
601                                       self.GetLabel())
602    
603        def __deepcopy__(self, memo):
604            return ClassGroupSingleton(self.GetValue(), group = self)
605    
606      def GetValue(self):      def GetValue(self):
607            """Return the associated value."""
608          return self.value          return self.value
609    
610      def SetValue(self, value):      def SetValue(self, value):
611            """Associate this Group with the given value."""
612          self.value = value          self.value = value
613    
614      def Matches(self, value):      def Matches(self, value):
615            """Determine if the given value matches the associated Group value."""
616    
617            """Returns True if the value matches, False otherwise."""
618    
619          return self.value == value          return self.value == value
620    
621      def GetProperties(self, value = None):      def GetDisplayText(self):
622          if value is None: return self.prop          label = self.GetLabel()
623    
624          if self.Matches(value):          if label != "": return label
             return self.prop  
         else:  
             return None  
625    
626      def SetProperties(self, prop):          return str(self.GetValue())
627          if prop is None: prop = ClassGroupProperties()  
628          assert(isinstance(prop, ClassGroupProperties))      def __eq__(self, other):
629          self.prop = prop          return ClassGroup.__eq__(self, other) \
630                and isinstance(other, ClassGroupSingleton) \
631                and self.GetValue() == other.GetValue()
632    
633    class ClassGroupDefault(ClassGroup):
634        """The default Group. When values do not match any other
635           Group within a Classification, the properties from this
636           class are used."""
637    
638        def __init__(self, props = None, label = "", group = None):
639            """Constructor.
640    
641            prop -- a ClassGroupProperites object. If prop is None a default
642                     set of properties is created.
643    
644            label -- a label for this group.
645            """
646    
647  class ClassGroupDefault(ClassGroupSingleton):          ClassGroup.__init__(self, label, props, group)
     def __init__(self, prop = None, label = ""):  
         ClassGroupSingleton.__init__(self, 0, prop, label)  
648    
649      def __copy__(self):      def __copy__(self):
650          return ClassGroupDefault(self.prop, self.label)          return ClassGroupDefault(self.GetProperties(), self.GetLabel())
651    
652      def GetProperties(self, value = None):      def __deepcopy__(self, memo):
653          return self.prop          return ClassGroupDefault(label = self.GetLabel(), group = self)
654    
655        def Matches(self, value):
656            return True
657    
658        def GetDisplayText(self):
659            label = self.GetLabel()
660    
661            if label != "": return label
662    
663            return _("DEFAULT")
664    
665        def __eq__(self, other):
666            return ClassGroup.__eq__(self, other) \
667                and isinstance(other, ClassGroupDefault) \
668                and self.GetProperties() == other.GetProperties()
669    
670  class ClassGroupRange(ClassGroup):  class ClassGroupRange(ClassGroup):
671        """A Group that represents a range of values that map to the same
672           set of properties."""
673    
674      def __init__(self, min = 0, max = 1, prop = None, label = ""):      def __init__(self, min = 0, max = 1, props = None, label = "", group=None):
675          ClassGroup.__init__(self, label)          """Constructor.
676    
677            The minumum value must be strictly less than the maximum.
678    
679            min -- the minimum range value
680    
681            max -- the maximum range value
682    
683            prop -- a ClassGroupProperites object. If prop is None a default
684                     set of properties is created.
685    
686            label -- a label for this group.
687            """
688    
689            ClassGroup.__init__(self, label, props, group)
690    
691            self.min = self.max = 0
692    
693          self.SetRange(min, max)          self.SetRange(min, max)
         self.SetProperties(prop)  
694    
695      def __copy__(self):      def __copy__(self):
696          return ClassGroupRange(self.min, self.max, self.prop, self.label)          return ClassGroupRange(self.GetMin(),
697                                   self.GetMax(),
698                                   self.GetProperties(),
699                                   self.GetLabel())
700    
701        def __deepcopy__(self, memo):
702            return ClassGroupRange(copy.copy(self.GetMin()),
703                                   copy.copy(self.GetMax()),
704                                   group = self)
705    
706      def GetMin(self):      def GetMin(self):
707            """Return the range's minimum value."""
708          return self.min          return self.min
709    
710      def SetMin(self, min):      def SetMin(self, min):
711            """Set the range's minimum value.
712        
713            min -- the new minimum. Note that this must be less than the current
714                   maximum value. Use SetRange() to change both min and max values.
715            """
716        
717          self.SetRange(min, self.max)          self.SetRange(min, self.max)
718    
719      def GetMax(self):      def GetMax(self):
720            """Return the range's maximum value."""
721          return self.max          return self.max
722    
723      def SetMax(self, max):      def SetMax(self, max):
724            """Set the range's maximum value.
725        
726            max -- the new maximum. Note that this must be greater than the current
727                   minimum value. Use SetRange() to change both min and max values.
728            """
729          self.SetRange(self.min, max)          self.SetRange(self.min, max)
730    
731      def SetRange(self, min, max):      def SetRange(self, min, max):
732            """Set a new range.
733    
734            Note that min must be strictly less than max.
735    
736            min -- the new minimum value
737            min -- the new maximum value
738            """
739    
740          if min >= max:          if min >= max:
741              raise ValueError(_("ClassGroupRange: %i(min) >= %i(max)!") %              raise ValueError(_("ClassGroupRange: %i(min) >= %i(max)!") %
742                               (min, max))                               (min, max))
# Line 400  class ClassGroupRange(ClassGroup): Line 744  class ClassGroupRange(ClassGroup):
744          self.max = max          self.max = max
745    
746      def GetRange(self):      def GetRange(self):
747            """Return the range as a tuple (min, max)"""
748          return (self.min, self.max)          return (self.min, self.max)
749    
750      def Matches(self, value):      def Matches(self, value):
751            """Determine if the given value lies with the current range.
752    
753            The following check is used: min <= value < max.
754            """
755    
756          return self.min <= value < self.max          return self.min <= value < self.max
757    
758      def GetProperties(self, value = None):      def GetDisplayText(self):
759          if value is None: return self.prop          label = self.GetLabel()
760    
761          if self.Matches(value):          if label != "": return label
             return self.prop  
         else:  
             return None  
762    
763      def SetProperties(self, prop):          return _("%s - %s") % (self.GetMin(), self.GetMax())
764          if prop is None: prop = ClassGroupProperties()  
765          assert(isinstance(prop, ClassGroupProperties))      def __eq__(self, other):
766          self.prop = prop          return ClassGroup.__eq__(self, other) \
767                and isinstance(other, ClassGroupRange) \
768                and self.GetRange() == other.GetRange()
769    
770  class ClassGroupMap(ClassGroup):  class ClassGroupMap(ClassGroup):
771        """Currently, this class is not used."""
772    
773      FUNC_ID = "id"      FUNC_ID = "id"
774    
775      def __init__(self, map_type = FUNC_ID, func = None, prop = None, label=""):      def __init__(self, map_type = FUNC_ID, func = None, prop = None, label=""):
776          ClassGroup.__init__(self, prop)          ClassGroup.__init__(self, label)
777    
778          self.map_type = map_type          self.map_type = map_type
779          self.func = func          self.func = func
# Line 434  class ClassGroupMap(ClassGroup): Line 784  class ClassGroupMap(ClassGroup):
784      def Map(self, value):      def Map(self, value):
785          return self.func(value)          return self.func(value)
786    
787        def GetProperties(self):
788            return None
789    
790        def GetPropertiesFromValue(self, value):
791            pass
792    
793        def GetDisplayText(self):
794            return "Map: " + self.map_type
795    
796      #      #
797      # built-in mappings      # built-in mappings
798      #      #

Legend:
Removed from v.453  
changed lines
  Added in v.643

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26