author | convert-repo |
Wed, 20 Jun 2018 03:32:04 +0000 | |
changeset 4135 | 616a34e5a8a8 |
parent 4085 | 815d85b10332 |
permissions | -rw-r--r-- |
4085 | 1 |
"{ Encoding: utf8 }" |
2 |
||
75 | 3 |
" |
4 |
COPYRIGHT (c) 1995 by Claus Gittinger |
|
5 |
All Rights Reserved |
|
6 |
||
7 |
This software is furnished under a license and may be used |
|
8 |
only in accordance with the terms of that license and with the |
|
9 |
inclusion of the above copyright notice. This software may not |
|
10 |
be provided or otherwise made available to, or used by, any |
|
11 |
other person. No title to or ownership of the software is |
|
12 |
hereby transferred. |
|
13 |
" |
|
3458 | 14 |
"{ Package: 'stx:libview2' }" |
75 | 15 |
|
3458 | 16 |
"{ NameSpace: Smalltalk }" |
1467
035afe3aa0ed
Use ISO-639 Language abbreviations
Stefan Vogel <sv@exept.de>
parents:
1191
diff
changeset
|
17 |
|
212 | 18 |
Object subclass:#PrintConverter |
19 |
instanceVariableNames:'valueToStringBlock stringToValueBlock type' |
|
20 |
classVariableNames:'' |
|
21 |
poolDictionaries:'' |
|
22 |
category:'Interface-Support' |
|
67 | 23 |
! |
24 |
||
25 |
!PrintConverter class methodsFor:'documentation'! |
|
26 |
||
75 | 27 |
copyright |
28 |
" |
|
29 |
COPYRIGHT (c) 1995 by Claus Gittinger |
|
30 |
All Rights Reserved |
|
31 |
||
32 |
This software is furnished under a license and may be used |
|
33 |
only in accordance with the terms of that license and with the |
|
34 |
inclusion of the above copyright notice. This software may not |
|
35 |
be provided or otherwise made available to, or used by, any |
|
36 |
other person. No title to or ownership of the software is |
|
37 |
hereby transferred. |
|
38 |
" |
|
39 |
! |
|
40 |
||
67 | 41 |
documentation |
42 |
" |
|
86 | 43 |
printConverters can be used with labels and editFields to convert |
44 |
an object to/from some printed representation. |
|
3773 | 45 |
|
46 |
Conversion is done via two blocks, which can be set at instance |
|
47 |
creation time - either as custom blocks or as one of the |
|
48 |
standard conversions. |
|
49 |
||
50 |
There are a number of standard setups for common conversions; |
|
51 |
if none of them fits your needs, |
|
52 |
create a custom converter by defining its two conversion blocks. |
|
67 | 53 |
|
54 |
Notice: this class was implemented using protocol information |
|
55 |
from alpha testers - it may not be complete or compatible to |
|
56 |
the corresponding ST-80 class. If you encounter any incompatibilities, |
|
57 |
please forward a note to the ST/X team. |
|
222 | 58 |
|
59 |
[author:] |
|
60 |
Claus Gittinger |
|
67 | 61 |
" |
62 |
! |
|
63 |
||
64 |
examples |
|
65 |
" |
|
86 | 66 |
stupid examples: |
67 |
convert date <-> string: |
|
230 | 68 |
[exBegin] |
69 | 69 |
|conv| |
67 | 70 |
|
69 | 71 |
conv := (PrintConverter new) |
230 | 72 |
toPrint:[:date | date printString] |
73 |
toRead:[:string | Date readFromString:string]. |
|
69 | 74 |
(conv printStringFor:(Date today)) inspect. |
75 |
(conv readValueFrom:(Date today printString)) inspect |
|
230 | 76 |
[exEnd] |
69 | 77 |
|
78 |
||
86 | 79 |
convert number <-> string: |
230 | 80 |
[exBegin] |
69 | 81 |
|conv| |
82 |
||
83 |
conv := (PrintConverter new) initForNumber. |
|
84 |
(conv printStringFor:12345) inspect. |
|
85 |
(conv readValueFrom:'12345') inspect |
|
230 | 86 |
[exEnd] |
67 | 87 |
|
88 |
||
86 | 89 |
convert boolean <-> string: |
230 | 90 |
[exBegin] |
69 | 91 |
|conv| |
92 |
||
93 |
conv := (PrintConverter new) initForYesNo. |
|
94 |
(conv printStringFor:true). |
|
95 |
(conv printStringFor:false). |
|
96 |
(conv readValueFrom:'yes'). |
|
97 |
(conv readValueFrom:'no'). |
|
1467
035afe3aa0ed
Use ISO-639 Language abbreviations
Stefan Vogel <sv@exept.de>
parents:
1191
diff
changeset
|
98 |
'if language is #de:'. |
69 | 99 |
(conv readValueFrom:'ja'). |
100 |
(conv readValueFrom:'nein') |
|
230 | 101 |
[exEnd] |
69 | 102 |
|
86 | 103 |
concrete examples: |
104 |
convert in an inputField: |
|
230 | 105 |
[exBegin] |
69 | 106 |
|dialog field| |
107 |
||
108 |
dialog := Dialog new. |
|
109 |
dialog addTextLabel:'a number (and only numbers):'. |
|
110 |
dialog addVerticalSpace. |
|
111 |
field := dialog addInputFieldOn:(0 asValue). |
|
112 |
field converter:(PrintConverter new initForNumber). |
|
113 |
field immediateAccept:true. |
|
114 |
dialog addOkButton. |
|
115 |
dialog open. |
|
116 |
dialog accepted ifTrue:[ |
|
268 | 117 |
Transcript showCR:field editValue |
69 | 118 |
] |
230 | 119 |
[exEnd] |
67 | 120 |
|
86 | 121 |
convert a models value for a label: |
230 | 122 |
[exBegin] |
86 | 123 |
|top v1 v2 l1 l2| |
124 |
||
125 |
v1 := 0 asValue. |
|
126 |
v2 := Date today asValue. |
|
127 |
||
128 |
top := StandardSystemView new. |
|
129 |
top extent:200@200. |
|
130 |
||
131 |
l1 := Label origin:0.0@0.0 corner:1.0@0.5 in:top. |
|
132 |
l1 converter:(PrintConverter new initForInteger). |
|
133 |
l1 model:v1; labelMessage:#value; aspect:#value. |
|
134 |
l1 level:-1; inset:10. |
|
135 |
||
136 |
l2 := Label origin:0.0@0.5 corner:1.0@1.0 in:top. |
|
137 |
l2 converter:(PrintConverter new initForDate). |
|
138 |
l2 model:v2; labelMessage:#value; aspect:#value. |
|
139 |
l2 level:-1; inset:10. |
|
140 |
||
141 |
top open. |
|
142 |
||
143 |
'now, change the values ...'. |
|
144 |
[ |
|
230 | 145 |
1 to:50 do:[:i| |
146 |
v1 value:(v1 value + 1). |
|
147 |
v2 value:(v2 value addDays:1). |
|
148 |
(Delay forSeconds:0.5) wait |
|
149 |
] |
|
86 | 150 |
] fork |
230 | 151 |
[exEnd] |
86 | 152 |
|
153 |
convert a models value for a label with limited precision |
|
154 |
float conversion: |
|
230 | 155 |
[exBegin] |
86 | 156 |
|top v l1 l2| |
157 |
||
158 |
v := 0.0 asValue. |
|
159 |
||
160 |
top := StandardSystemView new. |
|
161 |
top extent:200@200. |
|
162 |
||
163 |
l1 := Label origin:0.0@0.0 corner:1.0@0.5 in:top. |
|
164 |
l1 converter:(PrintConverter new initForFloat). |
|
165 |
l1 model:v; labelMessage:#value; aspect:#value. |
|
166 |
l1 level:-1; inset:10. |
|
167 |
||
168 |
l2 := Label origin:0.0@0.5 corner:1.0@1.0 in:top. |
|
169 |
l2 converter:(PrintConverter new initForFloatWithPrecision:2). |
|
170 |
l2 model:v; labelMessage:#value; aspect:#value. |
|
171 |
l2 level:-1; inset:10. |
|
172 |
||
173 |
top open. |
|
174 |
||
175 |
'now, change the values ...'. |
|
176 |
[ |
|
230 | 177 |
1 to:100 do:[:i| |
178 |
v value:(v value + 0.005). |
|
179 |
(Delay forSeconds:0.5) wait |
|
180 |
] |
|
86 | 181 |
] fork |
230 | 182 |
[exEnd] |
86 | 183 |
|
184 |
a custom converter, converting a number to either 'odd' |
|
185 |
or 'even' strings (we only need a one-way converter for labels): |
|
230 | 186 |
[exBegin] |
86 | 187 |
|top v l1 l2| |
188 |
||
189 |
v := 0 asValue. |
|
190 |
||
191 |
top := StandardSystemView new. |
|
192 |
top extent:200@200. |
|
193 |
||
194 |
l1 := Label origin:0.0@0.0 corner:1.0@0.5 in:top. |
|
195 |
l1 converter:(PrintConverter new initForInteger). |
|
196 |
l1 model:v; labelMessage:#value; aspect:#value. |
|
197 |
l1 level:-1; inset:10. |
|
198 |
||
199 |
l2 := Label origin:0.0@0.5 corner:1.0@1.0 in:top. |
|
200 |
l2 converter:(PrintConverter |
|
230 | 201 |
new |
202 |
toPrint:[:num | num even ifTrue:['even'] |
|
203 |
ifFalse:['odd']] |
|
204 |
toRead:[:string | ]). |
|
86 | 205 |
l2 model:v; labelMessage:#value; aspect:#value. |
206 |
l2 level:-1; inset:10. |
|
207 |
||
208 |
top open. |
|
209 |
||
210 |
'now, change the values ...'. |
|
211 |
[ |
|
230 | 212 |
1 to:100 do:[:i| |
213 |
v value:(v value + 1). |
|
214 |
(Delay forSeconds:0.5) wait |
|
215 |
] |
|
86 | 216 |
] fork |
230 | 217 |
[exEnd] |
67 | 218 |
|
69 | 219 |
see more examples in the EditField examples. |
67 | 220 |
" |
221 |
! ! |
|
222 |
||
223 |
!PrintConverter class methodsFor:'instance creation'! |
|
224 |
||
225 |
new |
|
226 |
^ (super new) |
|
227 |
toPrint:[:val | val] |
|
228 |
toRead:[:string | string] |
|
229 |
! ! |
|
230 |
||
86 | 231 |
!PrintConverter class methodsFor:'utilities'! |
232 |
||
233 |
print:aNumber formattedBy:formatString |
|
234 |
"take the digits of aNumbers printString, and squash them |
|
235 |
into formatString, where #-characters are replaced by |
|
236 |
successive characters from the printString. |
|
237 |
Warning: use with care - it does not check for decimal points etc. |
|
3458 | 238 |
the printString of aNumber must have enough digits for all |
239 |
#-characters to be replaced. |
|
240 |
Therefore, precheck the numbers value and use appropriate format |
|
241 |
strings then. |
|
86 | 242 |
For number formatting, see also: printfPrintString: implementations." |
243 |
||
244 |
|pS fS out| |
|
245 |
||
246 |
pS := ReadStream on:aNumber printString. |
|
247 |
fS := ReadStream on:formatString. |
|
3458 | 248 |
out := WriteStream on:(formatString species new:100). |
86 | 249 |
[fS atEnd] whileFalse:[ |
3458 | 250 |
|c| |
86 | 251 |
|
3458 | 252 |
c := fS next. |
253 |
c == $# ifTrue:[ |
|
254 |
c := pS next |
|
255 |
]. |
|
256 |
out nextPut:c |
|
86 | 257 |
]. |
258 |
^ out contents |
|
259 |
||
260 |
" |
|
261 |
PrintConverter print:'123456789' formattedBy:'US$ ###,###.##' |
|
262 |
||
263 |
fails for: |
|
264 |
PrintConverter print:'1234' formattedBy:'US$ ###,###.##' |
|
265 |
||
266 |
invalid string for: |
|
267 |
PrintConverter print:'123456789' formattedBy:'US$ ###' |
|
268 |
" |
|
269 |
! ! |
|
270 |
||
100 | 271 |
!PrintConverter methodsFor:'accessing'! |
272 |
||
273 |
type |
|
3887 | 274 |
"return the type if it's one of the standard converters, |
100 | 275 |
#number, #string etc. nil otherwise" |
276 |
||
277 |
^ type |
|
3887 | 278 |
|
279 |
"Modified (comment): / 13-02-2017 / 20:29:04 / cg" |
|
100 | 280 |
! ! |
281 |
||
212 | 282 |
!PrintConverter methodsFor:'converting'! |
283 |
||
284 |
printStringFor:aValue |
|
285 |
"sent when an inputField wants a models value to be converted to a string |
|
286 |
for display" |
|
287 |
||
288 |
^ valueToStringBlock value:aValue |
|
289 |
! |
|
290 |
||
291 |
readValueFrom:aString |
|
292 |
"sent when an inputField wants a string to be converted to a value |
|
293 |
to be returned as its contents value" |
|
294 |
||
295 |
^ stringToValueBlock value:aString |
|
296 |
! ! |
|
297 |
||
67 | 298 |
!PrintConverter methodsFor:'initialization'! |
299 |
||
100 | 300 |
initFor:aTypeSymbol |
301 |
"initialize to convert to/from objects as specified by aTypeSymbol, |
|
302 |
which may be one of #number, #string, #symbol, #date or #password ..." |
|
303 |
||
304 |
aTypeSymbol == #number ifTrue:[ |
|
407 | 305 |
self initForNumber |
306 |
]. |
|
307 |
aTypeSymbol == #numberOrNil ifTrue:[ |
|
308 |
self initForNumberOrNil |
|
309 |
]. |
|
310 |
aTypeSymbol == #integer ifTrue:[ |
|
311 |
self initForInteger |
|
312 |
]. |
|
313 |
aTypeSymbol == #integerOrNil ifTrue:[ |
|
314 |
self initForIntegerOrNil |
|
100 | 315 |
]. |
316 |
(aTypeSymbol == #string or:[aTypeSymbol == #password]) ifTrue:[ |
|
407 | 317 |
self initForString |
100 | 318 |
]. |
319 |
aTypeSymbol == #date ifTrue:[ |
|
407 | 320 |
self initForDate |
321 |
]. |
|
1191 | 322 |
aTypeSymbol == #time ifTrue:[ |
323 |
self initForTime |
|
324 |
]. |
|
325 |
aTypeSymbol == #timeOrNil ifTrue:[ |
|
326 |
self initForTimeOrNil |
|
327 |
]. |
|
407 | 328 |
aTypeSymbol == #float ifTrue:[ |
329 |
self initForFloat |
|
330 |
]. |
|
331 |
aTypeSymbol == #dateOrNil ifTrue:[ |
|
332 |
self initForDateOrNil |
|
100 | 333 |
]. |
334 |
aTypeSymbol == #symbol ifTrue:[ |
|
407 | 335 |
self initForSymbol |
100 | 336 |
]. |
337 |
||
338 |
type := aTypeSymbol |
|
339 |
||
340 |
"Modified: 6.9.1995 / 12:10:38 / claus" |
|
341 |
! |
|
342 |
||
212 | 343 |
initForDate |
344 |
"initialize to convert to/from a date |
|
345 |
- if the string is empty or invalid, convert to the current date" |
|
69 | 346 |
|
212 | 347 |
valueToStringBlock := [:date | date printString]. |
348 |
stringToValueBlock := [:string | Date readFromString:string onError:[Date today]] |
|
67 | 349 |
! |
350 |
||
212 | 351 |
initForDateOrNil |
352 |
"initialize to convert to/from a date |
|
69 | 353 |
- if the string is empty or invalid, convert to nil" |
354 |
||
212 | 355 |
valueToStringBlock := [:date | date printString]. |
356 |
stringToValueBlock := [:string | Date readFromString:string onError:nil] |
|
69 | 357 |
! |
358 |
||
86 | 359 |
initForFloat |
360 |
"initialize to convert to/from an float |
|
361 |
- if the string is empty or invalid, convert to 0" |
|
362 |
||
363 |
valueToStringBlock := [:num | num asFloat printString]. |
|
364 |
stringToValueBlock := [:string | Float readFromString:string onError:0] |
|
365 |
! |
|
366 |
||
367 |
initForFloatWithPrecision:nDigits |
|
368 |
"initialize to convert to/from an float with nDigits after the decimal point |
|
369 |
(truncating remaining digits). |
|
370 |
- if the string is empty or invalid, convert to 0" |
|
371 |
||
372 |
|conv| |
|
373 |
||
374 |
conv := '%.' , nDigits printString , 'f'. |
|
375 |
valueToStringBlock := [:num | num asFloat printfPrintString:conv]. |
|
376 |
stringToValueBlock := [:string | Float readFromString:string onError:0] |
|
377 |
! |
|
378 |
||
212 | 379 |
initForInteger |
380 |
"initialize to convert to/from an integer |
|
381 |
- if the string is empty or invalid, convert to 0" |
|
382 |
||
383 |
valueToStringBlock := [:num | num truncated printString]. |
|
384 |
stringToValueBlock := [:string | Integer readFromString:string onError:0] |
|
385 |
! |
|
386 |
||
387 |
initForIntegerOrNil |
|
388 |
"initialize to convert to/from an integer |
|
389 |
- if the string is empty or invalid, convert to nil" |
|
390 |
||
4085 | 391 |
valueToStringBlock := |
392 |
[:num | |
|
393 |
num isNil |
|
394 |
ifTrue:[''] |
|
395 |
ifFalse:[num printString] |
|
396 |
]. |
|
397 |
stringToValueBlock := |
|
398 |
[:string | |
|
399 |
Integer readFromString:string onError:nil |
|
400 |
] |
|
212 | 401 |
! |
402 |
||
67 | 403 |
initForNumber |
69 | 404 |
"initialize to convert to/from a number |
405 |
- if the string is empty or invalid, convert to 0" |
|
406 |
||
67 | 407 |
valueToStringBlock := [:num | num printString]. |
408 |
stringToValueBlock := [:string | Number readFromString:string onError:0] |
|
409 |
! |
|
410 |
||
411 |
initForNumberOrNil |
|
69 | 412 |
"initialize to convert to/from a number |
413 |
- if the string is empty or invalid, convert to nil" |
|
414 |
||
4085 | 415 |
valueToStringBlock := |
416 |
[:num | |
|
417 |
num isNil |
|
418 |
ifTrue:[''] |
|
419 |
ifFalse:[num printString] |
|
420 |
]. |
|
421 |
stringToValueBlock := |
|
422 |
[:string | |
|
423 |
|s| |
|
411 | 424 |
|
4085 | 425 |
s := string. |
426 |
(s endsWith:'.') ifTrue:[ |
|
427 |
s := s , '0' |
|
428 |
]. |
|
429 |
Number readFromString:s onError:nil |
|
430 |
] |
|
67 | 431 |
! |
432 |
||
433 |
initForString |
|
69 | 434 |
"initialize for a string - this is trivial" |
435 |
||
67 | 436 |
valueToStringBlock := [:val | val isNil ifTrue:[''] ifFalse:[val]]. |
437 |
stringToValueBlock := [:string | string] |
|
438 |
! |
|
439 |
||
1191 | 440 |
initForTime |
441 |
"initialize to convert to/from a time |
|
442 |
- if the string is empty or invalid, convert to the current time" |
|
443 |
||
444 |
valueToStringBlock := [:time | time printString]. |
|
445 |
stringToValueBlock := [:string | Time readFromString:string onError:[Time now]] |
|
446 |
! |
|
447 |
||
448 |
initForTimeOrNil |
|
449 |
"initialize to convert to/from a time |
|
450 |
- if the string is empty or invalid, convert to nil" |
|
451 |
||
452 |
valueToStringBlock := [:time | time printString]. |
|
453 |
stringToValueBlock := [:string | Time readFromString:string onError:nil] |
|
454 |
! |
|
455 |
||
68 | 456 |
initForYesNo |
3721 | 457 |
"initialize to convert a 'yes'/'no' string to/from a boolean |
69 | 458 |
The string is supposed to be in the current Language |
3721 | 459 |
(i.e. if german, ja/nein has to be entered. |
69 | 460 |
Invalid entries are converted to false." |
461 |
||
4085 | 462 |
valueToStringBlock := |
463 |
[:bool | |
|
464 |
ApplicationModel classResources string:(bool ifTrue:['yes'] ifFalse:['no']) |
|
465 |
]. |
|
466 |
stringToValueBlock := |
|
467 |
[:string | |
|
468 |
string = (ApplicationModel classResources string:'yes') |
|
469 |
] |
|
212 | 470 |
! |
471 |
||
472 |
toPrint:printBlock toRead:readBlock |
|
473 |
"initialize to convert using two custom blocks. |
|
474 |
printBlock is supposed to get the objects value as argument, |
|
475 |
and to return a string. |
|
476 |
readBlock is supposed to get a string as argument, and return |
|
477 |
the corresponding object." |
|
478 |
||
479 |
valueToStringBlock := printBlock. |
|
480 |
stringToValueBlock := readBlock. |
|
67 | 481 |
! ! |
482 |
||
212 | 483 |
!PrintConverter class methodsFor:'documentation'! |
100 | 484 |
|
223 | 485 |
version |
3721 | 486 |
^ '$Header$' |
67 | 487 |
! ! |
3458 | 488 |