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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26