/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/classification.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/Thuban/Model/classification.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 873 - (hide annotations)
Fri May 9 16:30:54 2003 UTC (21 years, 10 months ago) by jonathan
Original Path: trunk/thuban/Thuban/Model/classification.py
File MIME type: text/x-python
File size: 24905 byte(s)
Explicit imports.
(ClassGroupRange): Use the Range class to store the underlying
        range information. The interface remains the same, except for
        GetRange(), and you can also supply a Range object as the min
        parameter to SetRange or __init__.

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

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26