oops
authorClaus Gittinger <cg@exept.de>
Wed, 29 May 1996 00:52:31 +0200
changeset 280 39e270e5aa30
parent 279 bf069aab8a8c
child 281 00fba16f745e
oops
StrokeWrpr.st
StrokingWrapper.st
--- a/StrokeWrpr.st	Wed May 29 00:43:47 1996 +0200
+++ b/StrokeWrpr.st	Wed May 29 00:52:31 1996 +0200
@@ -11,14 +11,14 @@
 "
 
 
-Wrapper subclass:#TranslatingWrapper
-	instanceVariableNames:'origin'
+GeometricWrapper subclass:#StrokingWrapper
+	instanceVariableNames:'lineWidth lineStyle capStyle joinStyle'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'Graphics-Display Objects'
 !
 
-!TranslatingWrapper class methodsFor:'documentation'!
+!StrokingWrapper class methodsFor:'documentation'!
 
 copyright
 "
@@ -37,9 +37,12 @@
 
 documentation
 "
-    a wrapper which shifts the origin of its wrapped component.
-    This allows the wrapped thingy to think & draw in its own 0/0 based
-    coordinates.
+    a wrapper for a geometric object, which is to be drawn stroked.
+    This allows any geometric thingy to be used as a component in a view.
+
+    (background info: geometrics are mathematical objects - they do not 
+     keep any color or lineStyle attributes. Wrappers add this information
+     and can also be used as components of a view)
 
     Notice: 
         this class was implemented using protocol information
@@ -49,7 +52,7 @@
         describing the incompatibility verbal (i.e. no code) to the ST/X team.
 
     [see also:]
-        Wrapper 
+        FillingWrapper Geometric GraphicsContext
 
     [author:]
         Claus Gittinger
@@ -58,7 +61,73 @@
 
 examples
 "
-  some components without translatingWrapper
+  wrap an ellipticArc and display it
+  (notice, that no automatic redraw is performed):
+                                                                        [exBegin]
+    |v e component|
+
+    v := (StandardSystemView extent:250@250) openAndWait.
+
+    e := EllipticalArc boundingBox:(10@10 corner:90@90)
+                        startAngle:0 
+                        sweepAngle:270.
+    component := StrokingWrapper on:e.
+
+    component displayOn:v.
+                                                                        [exEnd]
+
+  wrap a rectangle and an ellipticArc,
+  and add them as components to a View
+  (notice, that doing so makes the redraw automatic):
+                                                                        [exBegin]
+    |v e component|
+
+    v := StandardSystemView extent:250@250.
+
+    e := Rectangle origin:10@10 corner:90@90.
+    component := FillingWrapper on:e.
+    component foregroundColor:Color red.
+
+    v addComponent:component.
+
+    e := EllipticalArc boundingBox:(10@10 corner:90@90)
+                     startAngle:0 sweepAngle:360.
+    component := StrokingWrapper on:e.
+    component lineWidth:5.
+
+    v addComponent:component.
+
+    v addComponent:(Button label:'hello').
+
+    v open
+                                                                        [exEnd]
+  with lineWidth & style:
+  (notice, that the redraw is automatic):
+                                                                        [exBegin]
+    |v e|
+
+    v := StandardSystemView extent:250@250.
+
+    e := EllipticalArc boundingBox:(10@10 corner:90@90)
+                        startAngle:0 
+                        sweepAngle:270.
+    v addComponent:((StrokingWrapper on:e)
+                        lineWidth:5;
+                        lineStyle:#dashed;
+                        foregroundColor:(Color red)).
+
+    e := EllipticalArc boundingBox:(30@30 corner:70@70)
+                        startAngle:90 
+                        sweepAngle:270.
+    v addComponent:((StrokingWrapper on:e)
+                        lineWidth:5;
+                        lineStyle:#doubleDashed;
+                        foregroundColor:(Color red);
+                        backgroundColor:(Color green)).
+    v open.
+                                                                        [exEnd]
+
+  scrolling:
                                                                         [exBegin]
     |t s v e component|
 
@@ -83,48 +152,7 @@
     component lineWidth:2.
     v addComponent:component.
 
-    t open
-                                                                        [exEnd]
-  the same components WITH translatingWrappers
-                                                                        [exBegin]
-    |t s v e component|
-
-    t := StandardSystemView extent:250@200.
-    s := HVScrollableView for:View miniScroller:true in:t.
-    s origin:0.0@0.0 corner:1.0@1.0.
-    v := s scrolledView.
-
-    e := Rectangle origin:0@0 corner:80@80.
-    component := FillingWrapper on:e.
-    component foregroundColor:Color red.
-    v addComponent:(TranslatingWrapper on:component at:10@10).
-
-    e := EllipticalArc boundingBox:(0@0 corner:80@80)
-                     startAngle:0 sweepAngle:360.
-    component := StrokingWrapper on:e.
-    component lineWidth:5.
-    v addComponent:(TranslatingWrapper on:component at:10@10).
-
-    e := Arrow from:0@0 to:50@150.
-    component := StrokingWrapper on:e.
-    component lineWidth:2.
-    v addComponent:(TranslatingWrapper on:component at:100@100).
-
-    v addComponent:(TranslatingWrapper on:(Image fromFile:'SBrowser.xbm') at:0@100).
-
-    t open
-                                                                        [exEnd]
-                                                                        [exBegin]
-    |t s v e component|
-
-    t := StandardSystemView extent:250@200.
-    s := HVScrollableView for:View miniScroller:true in:t.
-    s origin:0.0@0.0 corner:1.0@1.0.
-    v := s scrolledView.
-
-    e := LabelAndIcon icon:(Image fromFile:'bitmaps/SBrowser.xbm')
-                     string:'hello'.
-    v addComponent:(TranslatingWrapper on:e at:10@10).
+    v addComponent:(Button label:'hello').
 
     t open
                                                                         [exEnd]
@@ -132,96 +160,145 @@
 "
 ! !
 
-!TranslatingWrapper class methodsFor:'instance creation'!
+!StrokingWrapper methodsFor:'accessing'!
+
+bounds
+    "return the boundary rectangle - here, must take care of the lineWidth"
+
+    ^ component bounds insetBy:(lineWidth // 2 + 1) negated
 
-on:aComponent at:originPoint
-    "create and return a translatingWrapper, which positions
-     aComponent at some originPoint"
+    "Created: 8.5.1996 / 23:22:43 / cg"
+    "Modified: 26.5.1996 / 13:03:50 / cg"
+!
 
-    ^ (self on:aComponent) translation:originPoint
+capStyle
+    "return the capStyle"
+
+    ^ capStyle
 
-    "Created: 26.5.1996 / 16:07:29 / cg"
-    "Modified: 26.5.1996 / 16:12:28 / cg"
-! !
+    "Created: 8.5.1996 / 23:22:04 / cg"
+    "Modified: 9.5.1996 / 00:09:12 / cg"
+!
 
-!TranslatingWrapper methodsFor:'accessing'!
+capStyle:aSymbol
+    "set the capStyle"
+
+    capStyle := aSymbol
 
-translation
-    "return the origin offset"
+    "Created: 8.5.1996 / 23:22:13 / cg"
+    "Modified: 9.5.1996 / 00:09:17 / cg"
+!
 
-    ^ origin
+joinStyle
+    "return the joinStyle"
 
-    "Modified: 26.5.1996 / 16:06:32 / cg"
+    ^ joinStyle
+
+    "Created: 8.5.1996 / 23:22:04 / cg"
+    "Modified: 9.5.1996 / 00:09:12 / cg"
 !
 
-translation:originPoint
-    "set the origin offset"
+joinStyle:aSymbol
+    "set the joinStyle"
 
-    origin := originPoint
+    joinStyle := aSymbol
 
-    "Modified: 26.5.1996 / 16:06:32 / cg"
-    "Created: 26.5.1996 / 16:07:47 / cg"
-! !
-
-!TranslatingWrapper methodsFor:'accessing - bounds'!
+    "Created: 8.5.1996 / 23:22:13 / cg"
+    "Modified: 9.5.1996 / 00:09:17 / cg"
+!
 
-bounds
-    ^ component bounds + origin
+lineStyle
+    "return the lineStyle"
 
-    "Created: 26.5.1996 / 16:13:05 / cg"
-    "Modified: 26.5.1996 / 16:44:26 / cg"
+    ^ lineStyle
+
+    "Created: 8.5.1996 / 23:22:04 / cg"
+    "Modified: 9.5.1996 / 00:09:12 / cg"
 !
 
-bounds:newBounds
-    component bounds:(newBounds - origin).
+lineStyle:aSymbol
+    "set the lineStyle"
+
+    lineStyle := aSymbol
+
+    "Created: 8.5.1996 / 23:22:13 / cg"
+    "Modified: 9.5.1996 / 00:09:17 / cg"
+!
+
+lineWidth
+    "return the lineWidth"
 
-    "Created: 26.5.1996 / 16:44:16 / cg"
+    ^ lineWidth
+
+    "Created: 8.5.1996 / 23:22:04 / cg"
+    "Modified: 9.5.1996 / 00:09:12 / cg"
+!
+
+lineWidth:aNumber
+    "set the lineWidth"
+
+    lineWidth := aNumber
+
+    "Created: 8.5.1996 / 23:22:13 / cg"
+    "Modified: 9.5.1996 / 00:09:17 / cg"
 !
 
 preferredBounds
-    ^ component preferredBounds + origin
+    "return the components bounds as preferredBounds"
 
-    "Modified: 26.5.1996 / 16:44:26 / cg"
-    "Created: 26.5.1996 / 16:44:53 / cg"
+    ^ self bounds
+
+    "Created: 8.5.1996 / 23:23:00 / cg"
+    "Modified: 9.5.1996 / 00:09:31 / cg"
 ! !
 
-!TranslatingWrapper methodsFor:'displaying'!
+!StrokingWrapper methodsFor:'displaying'!
 
 displayOn:aGC
-    |oldTranslation oldPaint oldBgPaint|
+    "display myself - here, display the geometric object asStroked"
+
+    |prevLineWidth prevLineStyle prevCapStyle prevJoinStyle 
+     prevFg prevBg|
 
-    oldTranslation := aGC translation.
-    oldPaint := aGC paint.
-    oldBgPaint := aGC backgroundPaint.
+    prevLineWidth := aGC lineWidth.
+    prevLineStyle := aGC lineStyle.
+    prevJoinStyle := aGC joinStyle.
+    prevCapStyle  := aGC capStyle.
+    prevFg := aGC paint.
+    prevBg := aGC backgroundPaint.
 
-    aGC translation:(origin + aGC translation).
+    aGC lineWidth:lineWidth.
+    aGC lineStyle:lineStyle.
+    aGC joinStyle:joinStyle.
+    aGC capStyle:capStyle.
     aGC paint:fgColor on:bgColor.
 
-    component displayOn:aGC.
+    component displayStrokedOn:aGC.
 
-    aGC translation:oldTranslation.
-    aGC paint:oldPaint on:oldBgPaint.
+    aGC lineWidth:prevLineWidth.
+    aGC lineStyle:prevLineStyle.
+    aGC joinStyle:prevJoinStyle.
+    aGC capStyle:prevCapStyle.
+    aGC paint:prevFg on:prevBg.
 
-    "Created: 26.5.1996 / 15:27:54 / cg"
-    "Modified: 26.5.1996 / 16:13:44 / cg"
+    "Created: 8.5.1996 / 23:24:04 / cg"
+    "Modified: 9.5.1996 / 00:11:17 / cg"
 ! !
 
-!TranslatingWrapper methodsFor:'testing'!
+!StrokingWrapper methodsFor:'initialization'!
 
-containsPoint:aPoint
-    ^ component containsPoint:(aPoint - origin)
+initialize
+    "default my lineWidth to one pixel"
 
-    "Created: 26.5.1996 / 16:48:14 / cg"
-!
+    super initialize.
+    lineWidth := 1.
 
-intersects:aRectangle
-    ^ component intersects:(aRectangle - origin)
-
-    "Created: 26.5.1996 / 16:48:33 / cg"
+    "Created: 8.5.1996 / 23:49:27 / cg"
+    "Modified: 9.5.1996 / 00:11:51 / cg"
 ! !
 
-!TranslatingWrapper class methodsFor:'documentation'!
+!StrokingWrapper class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview2/Attic/StrokeWrpr.st,v 1.10 1996-05-28 22:43:43 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/Attic/StrokeWrpr.st,v 1.11 1996-05-28 22:52:31 cg Exp $'
 ! !
--- a/StrokingWrapper.st	Wed May 29 00:43:47 1996 +0200
+++ b/StrokingWrapper.st	Wed May 29 00:52:31 1996 +0200
@@ -11,14 +11,14 @@
 "
 
 
-Wrapper subclass:#TranslatingWrapper
-	instanceVariableNames:'origin'
+GeometricWrapper subclass:#StrokingWrapper
+	instanceVariableNames:'lineWidth lineStyle capStyle joinStyle'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'Graphics-Display Objects'
 !
 
-!TranslatingWrapper class methodsFor:'documentation'!
+!StrokingWrapper class methodsFor:'documentation'!
 
 copyright
 "
@@ -37,9 +37,12 @@
 
 documentation
 "
-    a wrapper which shifts the origin of its wrapped component.
-    This allows the wrapped thingy to think & draw in its own 0/0 based
-    coordinates.
+    a wrapper for a geometric object, which is to be drawn stroked.
+    This allows any geometric thingy to be used as a component in a view.
+
+    (background info: geometrics are mathematical objects - they do not 
+     keep any color or lineStyle attributes. Wrappers add this information
+     and can also be used as components of a view)
 
     Notice: 
         this class was implemented using protocol information
@@ -49,7 +52,7 @@
         describing the incompatibility verbal (i.e. no code) to the ST/X team.
 
     [see also:]
-        Wrapper 
+        FillingWrapper Geometric GraphicsContext
 
     [author:]
         Claus Gittinger
@@ -58,7 +61,73 @@
 
 examples
 "
-  some components without translatingWrapper
+  wrap an ellipticArc and display it
+  (notice, that no automatic redraw is performed):
+                                                                        [exBegin]
+    |v e component|
+
+    v := (StandardSystemView extent:250@250) openAndWait.
+
+    e := EllipticalArc boundingBox:(10@10 corner:90@90)
+                        startAngle:0 
+                        sweepAngle:270.
+    component := StrokingWrapper on:e.
+
+    component displayOn:v.
+                                                                        [exEnd]
+
+  wrap a rectangle and an ellipticArc,
+  and add them as components to a View
+  (notice, that doing so makes the redraw automatic):
+                                                                        [exBegin]
+    |v e component|
+
+    v := StandardSystemView extent:250@250.
+
+    e := Rectangle origin:10@10 corner:90@90.
+    component := FillingWrapper on:e.
+    component foregroundColor:Color red.
+
+    v addComponent:component.
+
+    e := EllipticalArc boundingBox:(10@10 corner:90@90)
+                     startAngle:0 sweepAngle:360.
+    component := StrokingWrapper on:e.
+    component lineWidth:5.
+
+    v addComponent:component.
+
+    v addComponent:(Button label:'hello').
+
+    v open
+                                                                        [exEnd]
+  with lineWidth & style:
+  (notice, that the redraw is automatic):
+                                                                        [exBegin]
+    |v e|
+
+    v := StandardSystemView extent:250@250.
+
+    e := EllipticalArc boundingBox:(10@10 corner:90@90)
+                        startAngle:0 
+                        sweepAngle:270.
+    v addComponent:((StrokingWrapper on:e)
+                        lineWidth:5;
+                        lineStyle:#dashed;
+                        foregroundColor:(Color red)).
+
+    e := EllipticalArc boundingBox:(30@30 corner:70@70)
+                        startAngle:90 
+                        sweepAngle:270.
+    v addComponent:((StrokingWrapper on:e)
+                        lineWidth:5;
+                        lineStyle:#doubleDashed;
+                        foregroundColor:(Color red);
+                        backgroundColor:(Color green)).
+    v open.
+                                                                        [exEnd]
+
+  scrolling:
                                                                         [exBegin]
     |t s v e component|
 
@@ -83,48 +152,7 @@
     component lineWidth:2.
     v addComponent:component.
 
-    t open
-                                                                        [exEnd]
-  the same components WITH translatingWrappers
-                                                                        [exBegin]
-    |t s v e component|
-
-    t := StandardSystemView extent:250@200.
-    s := HVScrollableView for:View miniScroller:true in:t.
-    s origin:0.0@0.0 corner:1.0@1.0.
-    v := s scrolledView.
-
-    e := Rectangle origin:0@0 corner:80@80.
-    component := FillingWrapper on:e.
-    component foregroundColor:Color red.
-    v addComponent:(TranslatingWrapper on:component at:10@10).
-
-    e := EllipticalArc boundingBox:(0@0 corner:80@80)
-                     startAngle:0 sweepAngle:360.
-    component := StrokingWrapper on:e.
-    component lineWidth:5.
-    v addComponent:(TranslatingWrapper on:component at:10@10).
-
-    e := Arrow from:0@0 to:50@150.
-    component := StrokingWrapper on:e.
-    component lineWidth:2.
-    v addComponent:(TranslatingWrapper on:component at:100@100).
-
-    v addComponent:(TranslatingWrapper on:(Image fromFile:'SBrowser.xbm') at:0@100).
-
-    t open
-                                                                        [exEnd]
-                                                                        [exBegin]
-    |t s v e component|
-
-    t := StandardSystemView extent:250@200.
-    s := HVScrollableView for:View miniScroller:true in:t.
-    s origin:0.0@0.0 corner:1.0@1.0.
-    v := s scrolledView.
-
-    e := LabelAndIcon icon:(Image fromFile:'bitmaps/SBrowser.xbm')
-                     string:'hello'.
-    v addComponent:(TranslatingWrapper on:e at:10@10).
+    v addComponent:(Button label:'hello').
 
     t open
                                                                         [exEnd]
@@ -132,96 +160,145 @@
 "
 ! !
 
-!TranslatingWrapper class methodsFor:'instance creation'!
+!StrokingWrapper methodsFor:'accessing'!
+
+bounds
+    "return the boundary rectangle - here, must take care of the lineWidth"
+
+    ^ component bounds insetBy:(lineWidth // 2 + 1) negated
 
-on:aComponent at:originPoint
-    "create and return a translatingWrapper, which positions
-     aComponent at some originPoint"
+    "Created: 8.5.1996 / 23:22:43 / cg"
+    "Modified: 26.5.1996 / 13:03:50 / cg"
+!
 
-    ^ (self on:aComponent) translation:originPoint
+capStyle
+    "return the capStyle"
+
+    ^ capStyle
 
-    "Created: 26.5.1996 / 16:07:29 / cg"
-    "Modified: 26.5.1996 / 16:12:28 / cg"
-! !
+    "Created: 8.5.1996 / 23:22:04 / cg"
+    "Modified: 9.5.1996 / 00:09:12 / cg"
+!
 
-!TranslatingWrapper methodsFor:'accessing'!
+capStyle:aSymbol
+    "set the capStyle"
+
+    capStyle := aSymbol
 
-translation
-    "return the origin offset"
+    "Created: 8.5.1996 / 23:22:13 / cg"
+    "Modified: 9.5.1996 / 00:09:17 / cg"
+!
 
-    ^ origin
+joinStyle
+    "return the joinStyle"
 
-    "Modified: 26.5.1996 / 16:06:32 / cg"
+    ^ joinStyle
+
+    "Created: 8.5.1996 / 23:22:04 / cg"
+    "Modified: 9.5.1996 / 00:09:12 / cg"
 !
 
-translation:originPoint
-    "set the origin offset"
+joinStyle:aSymbol
+    "set the joinStyle"
 
-    origin := originPoint
+    joinStyle := aSymbol
 
-    "Modified: 26.5.1996 / 16:06:32 / cg"
-    "Created: 26.5.1996 / 16:07:47 / cg"
-! !
-
-!TranslatingWrapper methodsFor:'accessing - bounds'!
+    "Created: 8.5.1996 / 23:22:13 / cg"
+    "Modified: 9.5.1996 / 00:09:17 / cg"
+!
 
-bounds
-    ^ component bounds + origin
+lineStyle
+    "return the lineStyle"
 
-    "Created: 26.5.1996 / 16:13:05 / cg"
-    "Modified: 26.5.1996 / 16:44:26 / cg"
+    ^ lineStyle
+
+    "Created: 8.5.1996 / 23:22:04 / cg"
+    "Modified: 9.5.1996 / 00:09:12 / cg"
 !
 
-bounds:newBounds
-    component bounds:(newBounds - origin).
+lineStyle:aSymbol
+    "set the lineStyle"
+
+    lineStyle := aSymbol
+
+    "Created: 8.5.1996 / 23:22:13 / cg"
+    "Modified: 9.5.1996 / 00:09:17 / cg"
+!
+
+lineWidth
+    "return the lineWidth"
 
-    "Created: 26.5.1996 / 16:44:16 / cg"
+    ^ lineWidth
+
+    "Created: 8.5.1996 / 23:22:04 / cg"
+    "Modified: 9.5.1996 / 00:09:12 / cg"
+!
+
+lineWidth:aNumber
+    "set the lineWidth"
+
+    lineWidth := aNumber
+
+    "Created: 8.5.1996 / 23:22:13 / cg"
+    "Modified: 9.5.1996 / 00:09:17 / cg"
 !
 
 preferredBounds
-    ^ component preferredBounds + origin
+    "return the components bounds as preferredBounds"
 
-    "Modified: 26.5.1996 / 16:44:26 / cg"
-    "Created: 26.5.1996 / 16:44:53 / cg"
+    ^ self bounds
+
+    "Created: 8.5.1996 / 23:23:00 / cg"
+    "Modified: 9.5.1996 / 00:09:31 / cg"
 ! !
 
-!TranslatingWrapper methodsFor:'displaying'!
+!StrokingWrapper methodsFor:'displaying'!
 
 displayOn:aGC
-    |oldTranslation oldPaint oldBgPaint|
+    "display myself - here, display the geometric object asStroked"
+
+    |prevLineWidth prevLineStyle prevCapStyle prevJoinStyle 
+     prevFg prevBg|
 
-    oldTranslation := aGC translation.
-    oldPaint := aGC paint.
-    oldBgPaint := aGC backgroundPaint.
+    prevLineWidth := aGC lineWidth.
+    prevLineStyle := aGC lineStyle.
+    prevJoinStyle := aGC joinStyle.
+    prevCapStyle  := aGC capStyle.
+    prevFg := aGC paint.
+    prevBg := aGC backgroundPaint.
 
-    aGC translation:(origin + aGC translation).
+    aGC lineWidth:lineWidth.
+    aGC lineStyle:lineStyle.
+    aGC joinStyle:joinStyle.
+    aGC capStyle:capStyle.
     aGC paint:fgColor on:bgColor.
 
-    component displayOn:aGC.
+    component displayStrokedOn:aGC.
 
-    aGC translation:oldTranslation.
-    aGC paint:oldPaint on:oldBgPaint.
+    aGC lineWidth:prevLineWidth.
+    aGC lineStyle:prevLineStyle.
+    aGC joinStyle:prevJoinStyle.
+    aGC capStyle:prevCapStyle.
+    aGC paint:prevFg on:prevBg.
 
-    "Created: 26.5.1996 / 15:27:54 / cg"
-    "Modified: 26.5.1996 / 16:13:44 / cg"
+    "Created: 8.5.1996 / 23:24:04 / cg"
+    "Modified: 9.5.1996 / 00:11:17 / cg"
 ! !
 
-!TranslatingWrapper methodsFor:'testing'!
+!StrokingWrapper methodsFor:'initialization'!
 
-containsPoint:aPoint
-    ^ component containsPoint:(aPoint - origin)
+initialize
+    "default my lineWidth to one pixel"
 
-    "Created: 26.5.1996 / 16:48:14 / cg"
-!
+    super initialize.
+    lineWidth := 1.
 
-intersects:aRectangle
-    ^ component intersects:(aRectangle - origin)
-
-    "Created: 26.5.1996 / 16:48:33 / cg"
+    "Created: 8.5.1996 / 23:49:27 / cg"
+    "Modified: 9.5.1996 / 00:11:51 / cg"
 ! !
 
-!TranslatingWrapper class methodsFor:'documentation'!
+!StrokingWrapper class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview2/StrokingWrapper.st,v 1.10 1996-05-28 22:43:43 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/StrokingWrapper.st,v 1.11 1996-05-28 22:52:31 cg Exp $'
 ! !