PrintConv.st
changeset 86 38cc61653cb2
parent 83 97fd04d167c8
child 96 948318b2fbd4
--- a/PrintConv.st	Sun Jul 23 04:25:16 1995 +0200
+++ b/PrintConv.st	Sun Jul 23 04:29:14 1995 +0200
@@ -35,17 +35,19 @@
 
 version 
 "
-$Header: /cvs/stx/stx/libview2/Attic/PrintConv.st,v 1.5 1995-07-02 16:16:59 claus Exp $
+$Header: /cvs/stx/stx/libview2/Attic/PrintConv.st,v 1.6 1995-07-23 02:28:06 claus Exp $
 "
 !
 
 documentation
 "
-    printConverters are used with editFields to convert an object
-    to/from some printed representation.
+    printConverters can be used with labels and editFields to convert 
+    an object to/from some printed representation.
     Conversion is done via two blocks which can be set at instance
     creation time - either as custom blocks ot to one of the
-    standard conversions.
+    standard conversions. There are a number of standard setups, for
+    common conversions; if none of them fits your needs, create a custom
+    converter, by defining its two conversion blocks.
 
     Notice: this class was implemented using protocol information
     from alpha testers - it may not be complete or compatible to
@@ -56,7 +58,9 @@
 
 examples 
 "
-    stupid examples:
+  stupid examples:
+    convert date <-> string:
+
       |conv|
 
       conv := (PrintConverter new)
@@ -66,6 +70,8 @@
       (conv readValueFrom:(Date today printString)) inspect
 
 
+    convert number <-> string:
+
       |conv|
 
       conv := (PrintConverter new) initForNumber.
@@ -73,6 +79,8 @@
       (conv readValueFrom:'12345') inspect
 
 
+    convert boolean <-> string:
+
       |conv|
 
       conv := (PrintConverter new) initForYesNo.
@@ -84,7 +92,8 @@
       (conv readValueFrom:'ja').    
       (conv readValueFrom:'nein')  
 
-    concrete example: convert in an inputField:
+  concrete examples: 
+    convert in an inputField:
 
       |dialog field|
 
@@ -100,6 +109,100 @@
 	  Transcript showCr:field editValue
       ]
 
+    convert a models value for a label:
+
+      |top v1 v2 l1 l2|
+
+      v1 := 0 asValue.
+      v2 := Date today asValue.
+
+      top := StandardSystemView new.
+      top extent:200@200.
+
+      l1 := Label origin:0.0@0.0 corner:1.0@0.5 in:top.
+      l1 converter:(PrintConverter new initForInteger).
+      l1 model:v1; labelMessage:#value; aspect:#value.
+      l1 level:-1; inset:10.
+
+      l2 := Label origin:0.0@0.5 corner:1.0@1.0 in:top.
+      l2 converter:(PrintConverter new initForDate).
+      l2 model:v2; labelMessage:#value; aspect:#value.
+      l2 level:-1; inset:10.
+
+      top open.
+
+      'now, change the values ...'.
+      [
+	1 to:50 do:[:i|
+	    v1 value:(v1 value + 1).
+	    v2 value:(v2 value addDays:1).
+	    (Delay forSeconds:0.5) wait
+	]
+      ] fork
+
+    convert a models value for a label with limited precision
+    float conversion:
+
+      |top v l1 l2|
+
+      v := 0.0 asValue.
+
+      top := StandardSystemView new.
+      top extent:200@200.
+
+      l1 := Label origin:0.0@0.0 corner:1.0@0.5 in:top.
+      l1 converter:(PrintConverter new initForFloat).
+      l1 model:v; labelMessage:#value; aspect:#value.
+      l1 level:-1; inset:10.
+
+      l2 := Label origin:0.0@0.5 corner:1.0@1.0 in:top.
+      l2 converter:(PrintConverter new initForFloatWithPrecision:2).
+      l2 model:v; labelMessage:#value; aspect:#value.
+      l2 level:-1; inset:10.
+
+      top open.
+
+      'now, change the values ...'.
+      [
+	1 to:100 do:[:i|
+	    v value:(v value + 0.005).
+	    (Delay forSeconds:0.5) wait
+	]
+      ] fork
+
+    a custom converter, converting a number to either 'odd'
+    or 'even' strings (we only need a one-way converter for labels):
+
+      |top v l1 l2|
+
+      v := 0 asValue.
+
+      top := StandardSystemView new.
+      top extent:200@200.
+
+      l1 := Label origin:0.0@0.0 corner:1.0@0.5 in:top.
+      l1 converter:(PrintConverter new initForInteger).
+      l1 model:v; labelMessage:#value; aspect:#value.
+      l1 level:-1; inset:10.
+
+      l2 := Label origin:0.0@0.5 corner:1.0@1.0 in:top.
+      l2 converter:(PrintConverter 
+		      new 
+			  toPrint:[:num | num even ifTrue:['even'] 
+						   ifFalse:['odd']]
+			  toRead:[:string | ]).
+      l2 model:v; labelMessage:#value; aspect:#value.
+      l2 level:-1; inset:10.
+
+      top open.
+
+      'now, change the values ...'.
+      [
+	1 to:100 do:[:i|
+	    v value:(v value + 1).
+	    (Delay forSeconds:0.5) wait
+	]
+      ] fork
 
     see more examples in the EditField examples.
 "
@@ -113,10 +216,54 @@
 	toRead:[:string | string]
 ! !
 
+!PrintConverter class methodsFor:'utilities'!
+
+print:aNumber formattedBy:formatString
+    "take the digits of aNumbers printString, and squash them
+     into formatString, where #-characters are replaced by
+     successive characters from the printString.
+     Warning: use with care - it does not check for decimal points etc.
+	      the printString of aNumber must have enough digits for all
+	      #-characters to be replaced.
+	      Therefore, precheck the numbers value and use appropriate format
+	      strings then.
+     For number formatting, see also: printfPrintString: implementations."
+
+    |pS fS out|
+
+    pS := ReadStream on:aNumber printString.
+    fS := ReadStream on:formatString.
+    out := WriteStream on:String new.
+    [fS atEnd] whileFalse:[
+	|c|
+
+	c := fS next.
+	c == $# ifTrue:[
+	    c := pS next
+	].
+	out nextPut:c
+    ].
+    ^ out contents
+
+    "
+     PrintConverter print:'123456789' formattedBy:'US$ ###,###.##' 
+
+    fails for:
+     PrintConverter print:'1234' formattedBy:'US$ ###,###.##' 
+
+    invalid string for:
+     PrintConverter print:'123456789' formattedBy:'US$ ###' 
+    "
+! !
+
 !PrintConverter methodsFor:'initialization'!
 
 toPrint:printBlock toRead:readBlock
-    "initialize to convert using two custom blocks"
+    "initialize to convert using two custom blocks.
+     printBlock is supposed to get the objects value as argument,
+     and to return a string.
+     readBlock is supposed to get a string as argument, and return
+     the corresponding object."
 
     valueToStringBlock := printBlock.
     stringToValueBlock := readBlock.
@@ -126,7 +273,7 @@
     "initialize to convert to/from an integer 
      - if the string is empty or invalid, convert to 0"
 
-    valueToStringBlock := [:num | num printString].
+    valueToStringBlock := [:num | num truncated printString].
     stringToValueBlock := [:string | Integer readFromString:string onError:0]
 !
 
@@ -141,6 +288,26 @@
 	Integer readFromString:string onError:nil]
 !
 
+initForFloat
+    "initialize to convert to/from an float 
+     - if the string is empty or invalid, convert to 0"
+
+    valueToStringBlock := [:num | num asFloat printString].
+    stringToValueBlock := [:string | Float readFromString:string onError:0]
+!
+
+initForFloatWithPrecision:nDigits
+    "initialize to convert to/from an float with nDigits after the decimal point
+     (truncating remaining digits).
+     - if the string is empty or invalid, convert to 0"
+
+    |conv|
+
+    conv := '%.' , nDigits printString , 'f'.
+    valueToStringBlock := [:num | num asFloat printfPrintString:conv].
+    stringToValueBlock := [:string | Float readFromString:string onError:0]
+!
+
 initForNumber
     "initialize to convert to/from a number 
      - if the string is empty or invalid, convert to 0"