/[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 462 by jonathan, Wed Mar 5 18:17:17 2003 UTC revision 609 by jonathan, Fri Apr 4 13:55:59 2003 UTC
# Line 23  on the mapping algorithm. Line 23  on the mapping algorithm.
23  # fix for people using python2.1  # fix for people using python2.1
24  from __future__ import nested_scopes  from __future__ import nested_scopes
25    
26    import copy
27    
28  from types import *  from types import *
29    
30  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \
# Line 33  from Thuban.Model.color import Color Line 35  from Thuban.Model.color import Color
35    
36  import Thuban.Model.layer  import Thuban.Model.layer
37    
   
38  # constants  # constants
39  RANGE_MIN  = 0  RANGE_MIN  = 0
40  RANGE_MAX  = 1  RANGE_MAX  = 1
# Line 58  class Classification: Line 59  class Classification:
59          self.field = None          self.field = None
60          self.fieldType = None          self.fieldType = None
61          self.groups = []          self.groups = []
         self.__sendMessages = False  
62    
63          self.__ToggleMessages(False)          self.__setLayerLock = False
64    
65          self.SetDefaultGroup(ClassGroupDefault())          self.SetDefaultGroup(ClassGroupDefault())
66    
67          self.SetLayer(layer)          self.SetLayer(layer)
68          self.SetField(field)          self.SetField(field)
69    
         self.__ToggleMessages(True)  
   
70      def __iter__(self):      def __iter__(self):
71          return ClassIterator(self.groups)          return ClassIterator(self.groups)
72    
73      def __ToggleMessages(self, on):      def __SendNotification(self):
74          self.__sendMessages = on          """Notify the layer that this class has changed."""
75            if self.layer is not None:
76      def __SendMessage(self, message):              self.layer.ClassChanged()
         """Send the message 'message' to the parent layer."""  
         if self.__sendMessages and self.layer is not None:  
             self.layer.changed(message, self.layer)  
77            
78      def SetField(self, field = None):      def SetField(self, field):
79          """Set the name of the data table field to use.          """Set the name of the data table field to use.
80                    
81               If there is no layer then the field type is set to None,
82               otherwise the layer is queried to find the type of the
83               field data
84    
85             field -- if None then all values map to the default data             field -- if None then all values map to the default data
86          """          """
87    
88          if field == "":          if field == "":
89              field = None              field = None
90    
         self.field = field  
91    
92          if self.layer is not None:          if field is None:
93              fieldType = self.layer.GetFieldType(field)              if self.layer is not None:
94                    self.fieldType = None
95          else:          else:
96              fieldType = None              if self.layer is not None:
97                    fieldType = self.layer.GetFieldType(field)
98                    if fieldType is None:
99                        raise ValueError("'%s' was not found in the layer's table."
100                                         % self.field)
101    
102                    #
103                    # unfortunately we cannot call SetFieldType() because it
104                    # requires the layer to be None
105                    #
106                    self.fieldType = fieldType
107                    #self.SetFieldType(fieldType)
108    
109          self.SetFieldType(fieldType)          self.field = field
   
         # XXX: if fieldType comes back None then field isn't in the table!  
110    
111          self.__SendMessage(LAYER_LEGEND_CHANGED)          self.__SendNotification()
112    
113      def GetField(self):      def GetField(self):
114          """Return the name of the field."""          """Return the name of the field."""
# Line 109  class Classification: Line 119  class Classification:
119          return self.fieldType          return self.fieldType
120    
121      def SetFieldType(self, type):      def SetFieldType(self, type):
122          self.fieldType = type          """Set the type of the field used by this classification.
123    
124            A ValueError is raised if the owning layer is not None and
125            'type' is different from the current field type.
126            """
127    
128            if type != self.fieldType:
129                if self.layer is not None:
130                    raise ValueError()
131                else:
132                    self.fieldType = type
133                    self.__SendNotification()
134    
135      def SetLayer(self, layer):      def SetLayer(self, layer):
136          """Set the owning Layer of this classification."""          """Set the owning Layer of this classification.
137    
138               A ValueError exception will be thrown either the field or
139               field type mismatch the information in the layer's table.
140            """
141    
142            # prevent infinite recursion when calling SetClassification()
143            if self.__setLayerLock: return
144    
145            self.__setLayerLock = True
146    
147          if __debug__:          if layer is None:
148              if layer is not None:              if self.layer is not None:
149                  assert(isinstance(layer, Thuban.Model.layer.Layer))                  l = self.layer
150                    self.layer = None
151                    l.SetClassification(None)
152            else:
153                assert isinstance(layer, Thuban.Model.layer.Layer)
154    
155                old_layer = self.layer
156    
157          self.layer = layer              self.layer = layer
158          self.SetField(self.GetField()) # XXX: this sync's the fieldType  
159                try:
160                    self.SetField(self.GetField()) # this sync's the fieldType
161                except ValueError:
162                    self.layer = old_layer
163                    self.__setLayerLock = False
164                    raise ValueError
165                else:
166                    self.layer.SetClassification(self)
167    
168          self.__SendMessage(LAYER_LEGEND_CHANGED)          self.__setLayerLock = False
169    
170      def GetLayer(self):      def GetLayer(self):
171          """Return the parent layer."""          """Return the parent layer."""
# Line 133  class Classification: Line 177  class Classification:
177             group -- group that the value maps to.             group -- group that the value maps to.
178          """          """
179    
180          assert(isinstance(group, ClassGroupDefault))          assert isinstance(group, ClassGroupDefault)
181          self.AddGroup(group)          self.AddGroup(group)
182    
183      def GetDefaultGroup(self):      def GetDefaultGroup(self):
# Line 151  class Classification: Line 195  class Classification:
195    
196          fill -- a Color object.          fill -- a Color object.
197          """          """
198          assert(isinstance(fill, Color))          assert isinstance(fill, Color)
199          self.GetDefaultGroup().GetProperties().SetFill(fill)          self.GetDefaultGroup().GetProperties().SetFill(fill)
200          self.__SendMessage(LAYER_LEGEND_CHANGED)          self.__SendNotification()
201                    
202      def GetDefaultFill(self):      def GetDefaultFill(self):
203          """Return the default fill color."""          """Return the default fill color."""
# Line 164  class Classification: Line 208  class Classification:
208    
209          color -- a Color object.          color -- a Color object.
210          """          """
211          assert(isinstance(color, Color))          assert isinstance(color, Color)
212          self.GetDefaultGroup().GetProperties().SetLineColor(color)          self.GetDefaultGroup().GetProperties().SetLineColor(color)
213          self.__SendMessage(LAYER_LEGEND_CHANGED)          self.__SendNotification()
214                    
215      def GetDefaultLineColor(self):      def GetDefaultLineColor(self):
216          """Return the default line color."""          """Return the default line color."""
# Line 177  class Classification: Line 221  class Classification:
221    
222          lineWidth -- an integer > 0.          lineWidth -- an integer > 0.
223          """          """
224          assert(isinstance(lineWidth, IntType))          assert isinstance(lineWidth, IntType)
225          self.GetDefaultGroup().GetProperties().SetLineWidth(lineWidth)          self.GetDefaultGroup().GetProperties().SetLineWidth(lineWidth)
226          self.__SendMessage(LAYER_LEGEND_CHANGED)          self.__SendNotification()
227                    
228      def GetDefaultLineWidth(self):      def GetDefaultLineWidth(self):
229          """Return the default line width."""          """Return the default line width."""
# Line 191  class Classification: Line 235  class Classification:
235          item -- this must be a valid ClassGroup object          item -- this must be a valid ClassGroup object
236          """          """
237    
238          assert(isinstance(item, ClassGroup))          assert isinstance(item, ClassGroup)
239    
240          if len(self.groups) > 0 and isinstance(item, ClassGroupDefault):          if len(self.groups) > 0 and isinstance(item, ClassGroupDefault):
241              self.groups[0] = item              self.groups[0] = item
             #self.SetDefaultGroup(item)  
242          else:          else:
243              self.groups.append(item)              self.groups.append(item)
244    
245          self.__SendMessage(LAYER_LEGEND_CHANGED)          self.__SendNotification()
246    
247      def GetGroup(self, value):      def GetGroup(self, value):
248          """Return the associated group, or the default group.          """Return the associated group, or the default group.
# Line 208  class Classification: Line 251  class Classification:
251             Classification.             Classification.
252    
253             value -- the value to classify. If there is no mapping,             value -- the value to classify. If there is no mapping,
254                      or value is None, return the default properties                      the field is None or value is None,
255                        return the default properties
256          """          """
257    
258          if self.field is not None and value is not None:          if self.GetField() is not None and value is not None:
259    
260              for i in range(1, len(self.groups)):              for i in range(1, len(self.groups)):
261                  group = self.groups[i]                  group = self.groups[i]
# Line 233  class Classification: Line 277  class Classification:
277          items = []          items = []
278    
279          def build_color_item(text, color):          def build_color_item(text, color):
280              if color is Color.None:              if color is Color.Transparent:
281                  return ("%s: %s" % (text, _("None")), None)                  return ("%s: %s" % (text, _("None")), None)
282    
283              return ("%s: (%.3f, %.3f, %.3f)" %              return ("%s: (%.3f, %.3f, %.3f)" %
# Line 328  class ClassGroupProperties: Line 372  class ClassGroupProperties:
372    
373          props -- a ClassGroupProperties object. The class is copied if          props -- a ClassGroupProperties object. The class is copied if
374                   prop is not None. Otherwise, a default set of properties                   prop is not None. Otherwise, a default set of properties
375                   is created.                   is created such that: line color = Color.Black, line width = 1,
376                     and fill color = Color.Transparent
377          """          """
378    
379          self.stroke = None          self.stroke = None
# Line 338  class ClassGroupProperties: Line 383  class ClassGroupProperties:
383          if props is not None:          if props is not None:
384              self.SetProperties(props)              self.SetProperties(props)
385          else:          else:
386              self.SetLineColor(Color.None)              self.SetLineColor(Color.Black)
387              self.SetLineWidth(1)              self.SetLineWidth(1)
388              self.SetFill(Color.None)              self.SetFill(Color.Transparent)
389    
390      def SetProperties(self, props):      def SetProperties(self, props):
391          """Set this class's properties to those in class props."""          """Set this class's properties to those in class props."""
392    
393          assert(isinstance(props, ClassGroupProperties))          assert isinstance(props, ClassGroupProperties)
394          self.SetLineColor(props.GetLineColor())          self.SetLineColor(props.GetLineColor())
395          self.SetLineWidth(props.GetLineWidth())          self.SetLineWidth(props.GetLineWidth())
396          self.SetFill(props.GetFill())          self.SetFill(props.GetFill())
# Line 360  class ClassGroupProperties: Line 405  class ClassGroupProperties:
405          color -- the color of the line. This must be a Color object.          color -- the color of the line. This must be a Color object.
406          """          """
407    
408          assert(isinstance(color, Color))          assert isinstance(color, Color)
409          self.stroke = color          self.stroke = color
410    
411      def GetLineWidth(self):      def GetLineWidth(self):
# Line 372  class ClassGroupProperties: Line 417  class ClassGroupProperties:
417    
418          lineWidth -- the new line width. This must be > 0.          lineWidth -- the new line width. This must be > 0.
419          """          """
420          assert(isinstance(lineWidth, IntType))          assert isinstance(lineWidth, IntType)
421          if (lineWidth < 1):          if (lineWidth < 1):
422              raise ValueError(_("lineWidth < 1"))              raise ValueError(_("lineWidth < 1"))
423    
# Line 388  class ClassGroupProperties: Line 433  class ClassGroupProperties:
433          fill -- the color of the fill. This must be a Color object.          fill -- the color of the fill. This must be a Color object.
434          """          """
435    
436          assert(isinstance(fill, Color))          assert isinstance(fill, Color)
437          self.fill = fill          self.fill = fill
438    
439        def __eq__(self, other):
440            """Return true if 'props' has the same attributes as this class"""
441    
442            return isinstance(other, ClassGroupProperties)   \
443                and self.stroke      == other.GetLineColor() \
444                and self.strokeWidth == other.GetLineWidth() \
445                and self.fill        == other.GetFill()
446    
447        def __ne__(self, other):
448            return not self.__eq__(other)
449    
450        def __copy__(self):
451            return ClassGroupProperties(self)
452    
453        def __deepcopy__(self):
454            return ClassGroupProperties(self)
455    
456  class ClassGroup:  class ClassGroup:
457      """A base class for all Groups within a Classification"""      """A base class for all Groups within a Classification"""
# Line 415  class ClassGroup: Line 476  class ClassGroup:
476          label -- a string representing the Group's label. This must          label -- a string representing the Group's label. This must
477                   not be None.                   not be None.
478          """          """
479          assert(isinstance(label, StringType))          assert isinstance(label, StringType)
480          self.label = label          self.label = label
481    
482        def GetDisplayText(self):
483            assert False, "GetDisplay must be overridden by subclass!"
484            return ""
485    
486      def Matches(self, value):      def Matches(self, value):
487          """Determines if this Group is associated with the given value.          """Determines if this Group is associated with the given value.
488    
489          Returns True or False. This needs to be implemented by all subclasses.          Returns False. This needs to be overridden by all subclasses.
490          """          """
491          pass          assert False, "GetMatches must be overridden by subclass!"
492            return False
493    
494      def GetProperties(self):      def GetProperties(self):
495          """Return the properties associated with the given value.          """Return the properties associated with the given value.
496    
497          This needs to be implemented by all subclasses.          Returns None. This needs to be overridden by all subclasses.
498          """          """
499          pass          assert False, "GetProperties must be overridden by subclass!"
500            return None
501    
502            
503  class ClassGroupSingleton(ClassGroup):  class ClassGroupSingleton(ClassGroup):
# Line 455  class ClassGroupSingleton(ClassGroup): Line 522  class ClassGroupSingleton(ClassGroup):
522          self.SetProperties(prop)          self.SetProperties(prop)
523    
524      def __copy__(self):      def __copy__(self):
525          return ClassGroupSingleton(self.value, self.prop, self.label)          return ClassGroupSingleton(self.GetValue(),
526                                       self.GetProperties(),
527                                       self.GetLabel())
528    
529        def __deepcopy__(self, memo):
530            return ClassGroupSingleton(copy.copy(self.GetValue()),
531                                       copy.copy(self.GetProperties()),
532                                       copy.copy(self.GetLabel()))
533    
534      def GetValue(self):      def GetValue(self):
535          """Return the associated value."""          """Return the associated value."""
# Line 485  class ClassGroupSingleton(ClassGroup): Line 559  class ClassGroupSingleton(ClassGroup):
559          """          """
560    
561          if prop is None: prop = ClassGroupProperties()          if prop is None: prop = ClassGroupProperties()
562          assert(isinstance(prop, ClassGroupProperties))          assert isinstance(prop, ClassGroupProperties)
563          self.prop = prop          self.prop = prop
564    
565        def GetDisplayText(self):
566            label = self.GetLabel()
567    
568            if label != "": return label
569    
570            return str(self.GetValue())
571    
572        def __eq__(self, other):
573            return isinstance(other, ClassGroupSingleton) \
574                and self.GetProperties() == other.GetProperties() \
575                and self.GetValue() == other.GetValue()
576    
577  class ClassGroupDefault(ClassGroupSingleton):      def __ne__(self, other):
578            return not self.__eq__(other)
579    
580    class ClassGroupDefault(ClassGroup):
581      """The default Group. When values do not match any other      """The default Group. When values do not match any other
582         Group within a Classification, the properties from this         Group within a Classification, the properties from this
583         class are used."""         class are used."""
# Line 503  class ClassGroupDefault(ClassGroupSingle Line 591  class ClassGroupDefault(ClassGroupSingle
591          label -- a label for this group.          label -- a label for this group.
592          """          """
593    
594          ClassGroupSingleton.__init__(self, 0, prop, label)          ClassGroup.__init__(self, label)
595            self.SetProperties(prop)
596    
597      def __copy__(self):      def __copy__(self):
598          return ClassGroupDefault(self.prop, self.label)          return ClassGroupDefault(self.GetProperties(), self.GetLabel())
599    
600        def __deepcopy__(self, memo):
601            return ClassGroupDefault(copy.copy(self.GetProperties()),
602                                     copy.copy(self.GetLabel()))
603    
604        def Matches(self, value):
605            return True
606    
607      def GetProperties(self):      def GetProperties(self):
608          """Return the Properties associated with this Group."""          """Return the Properties associated with this Group."""
609          return self.prop          return self.prop
610    
611        def SetProperties(self, prop):
612            """Set the properties associated with this Group.
613    
614            prop -- a ClassGroupProperties object. if prop is None,
615                    a default set of properties is created.
616            """
617    
618            if prop is None: prop = ClassGroupProperties()
619            assert isinstance(prop, ClassGroupProperties)
620            self.prop = prop
621    
622        def GetDisplayText(self):
623            label = self.GetLabel()
624    
625            if label != "": return label
626    
627            return "DEFAULT"
628    
629        def __eq__(self, other):
630            return isinstance(other, ClassGroupDefault) \
631                and self.GetProperties() == other.GetProperties()
632    
633        def __ne__(self, other):
634            return not self.__eq__(other)
635    
636  class ClassGroupRange(ClassGroup):  class ClassGroupRange(ClassGroup):
637      """A Group that represents a range of values that map to the same      """A Group that represents a range of values that map to the same
638         set of properties."""         set of properties."""
# Line 540  class ClassGroupRange(ClassGroup): Line 661  class ClassGroupRange(ClassGroup):
661          self.SetProperties(prop)          self.SetProperties(prop)
662    
663      def __copy__(self):      def __copy__(self):
664          return ClassGroupRange(self.min, self.max, self.prop, self.label)          return ClassGroupRange(self.GetMin(),
665                                   self.GetMax(),
666                                   self.GetProperties(),
667                                   self.GetLabel())
668    
669        def __deepcopy__(self, memo):
670            return ClassGroupRange(copy.copy(self.GetMin()),
671                                   copy.copy(self.GetMax()),
672                                   copy.copy(self.GetProperties()),
673                                   copy.copy(self.GetLabel()))
674    
675      def GetMin(self):      def GetMin(self):
676          """Return the range's minimum value."""          """Return the range's minimum value."""
# Line 605  class ClassGroupRange(ClassGroup): Line 735  class ClassGroupRange(ClassGroup):
735                  a default set of properties is created.                  a default set of properties is created.
736          """          """
737          if prop is None: prop = ClassGroupProperties()          if prop is None: prop = ClassGroupProperties()
738          assert(isinstance(prop, ClassGroupProperties))          assert isinstance(prop, ClassGroupProperties)
739          self.prop = prop          self.prop = prop
740    
741        def GetDisplayText(self):
742            label = self.GetLabel()
743    
744            if label != "": return label
745    
746            return _("%s - %s") % (self.GetMin(), self.GetMax())
747    
748        def __eq__(self, other):
749            return isinstance(other, ClassGroupRange) \
750                and self.GetProperties() == other.GetProperties() \
751                and self.GetRange() == other.GetRange()
752    
753        def __ne__(self, other):
754            return not self.__eq__(other)
755    
756  class ClassGroupMap(ClassGroup):  class ClassGroupMap(ClassGroup):
757      """Currently, this class is not used."""      """Currently, this class is not used."""
758    
# Line 631  class ClassGroupMap(ClassGroup): Line 776  class ClassGroupMap(ClassGroup):
776      def GetPropertiesFromValue(self, value):      def GetPropertiesFromValue(self, value):
777          pass          pass
778    
779        def GetDisplayText(self):
780            return "Map: " + self.map_type
781    
782      #      #
783      # built-in mappings      # built-in mappings
784      #      #

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26