8 be provided or otherwise made available to, or used by, any |
8 be provided or otherwise made available to, or used by, any |
9 other person. No title to or ownership of the software is |
9 other person. No title to or ownership of the software is |
10 hereby transferred. |
10 hereby transferred. |
11 " |
11 " |
12 |
12 |
13 'From Smalltalk/X, Version:2.10.5 on 4-may-1995 at 6:16:25 am'! |
13 'From Smalltalk/X, Version:2.10.5 on 9-may-1995 at 12:04:16 pm'! |
14 |
14 |
15 Button subclass:#PopUpList |
15 Button subclass:#PopUpList |
16 instanceVariableNames:'menu menuAction values useIndex listMsg' |
16 instanceVariableNames:'menu menuAction values useIndex listMsg initialSelectionMsg' |
17 classVariableNames:'' |
17 classVariableNames:'' |
18 poolDictionaries:'' |
18 poolDictionaries:'' |
19 category:'Views-Interactors' |
19 category:'Views-Interactors' |
20 ! |
20 ! |
21 |
21 |
22 PopUpList comment:' |
22 PopUpList comment:' |
23 COPYRIGHT (c) 1994 by Claus Gittinger |
23 COPYRIGHT (c) 1994 by Claus Gittinger |
24 All Rights Reserved |
24 All Rights Reserved |
25 |
25 |
26 $Header: /cvs/stx/stx/libwidg/PopUpList.st,v 1.11 1995-05-06 14:17:44 claus Exp $ |
26 $Header: /cvs/stx/stx/libwidg/PopUpList.st,v 1.12 1995-05-09 01:56:26 claus Exp $ |
27 '! |
27 '! |
28 |
28 |
29 !PopUpList class methodsFor:'documentation'! |
29 !PopUpList class methodsFor:'documentation'! |
30 |
30 |
31 copyright |
31 copyright |
42 " |
42 " |
43 ! |
43 ! |
44 |
44 |
45 version |
45 version |
46 " |
46 " |
47 $Header: /cvs/stx/stx/libwidg/PopUpList.st,v 1.11 1995-05-06 14:17:44 claus Exp $ |
47 $Header: /cvs/stx/stx/libwidg/PopUpList.st,v 1.12 1995-05-09 01:56:26 claus Exp $ |
48 " |
48 " |
49 ! |
49 ! |
50 |
50 |
51 documentation |
51 documentation |
52 " |
52 " |
53 a PopUpList is basically a button with a popup menu. |
53 a PopUpList is basically a button with a popup menu. |
54 The PopUpLists label is showing the current selection from the |
54 The PopUpLists label is showing the current selection from the |
55 list. |
55 list. |
56 When an entry is selected, an actionBlock (if nonNil) is evaluated |
56 When an entry is selected, an actionBlock (if nonNil) is evaluated |
57 and (if nonNil), the model is notified via the changeMessage. |
57 and (if nonNil), the model is notified via the changeMessage. |
|
58 |
58 The default changeMessage used is #selection:, which allows a |
59 The default changeMessage used is #selection:, which allows a |
59 PopUpList to be used with a SelectionInList as model. |
60 PopUpList to be used with a SelectionInList as model. |
60 (if used with some other model, either use an adaptor, or set the |
61 (if used with some other model, either use an adaptor, or set the |
61 changeMessage to something else ..) |
62 changeMessage to something else ..) |
|
63 |
|
64 Instance variables: |
|
65 |
|
66 menu helpers for the popup menu |
|
67 menuAction |
|
68 values |
|
69 |
|
70 useIndex <Boolean> if true, the index of the selected entry |
|
71 is passed to the action block and the |
|
72 model in a change-message. |
|
73 If false (the default), the value is passed. |
|
74 Notice that the default changeMessage is |
|
75 #selection:, which is not ok to be used |
|
76 with useIndex:true and a selectionInList model. |
|
77 (set the changeMessage to #selectionIndex: then) |
|
78 |
|
79 listMsg <Symbol> message to aquire a new list from the |
|
80 model. Default is #list. |
|
81 |
|
82 |
|
83 initialSelectionMsg <Symbol> message to aquire a new selection from the |
|
84 model. Default is #selection. |
62 " |
85 " |
63 ! |
86 ! |
64 |
87 |
65 examples |
88 examples |
66 " |
89 " |
115 since the list is actually a popupMenu, you can add double-separators: |
138 since the list is actually a popupMenu, you can add double-separators: |
116 |
139 |
117 |p| |
140 |p| |
118 p := PopUpList label:'dummy'. |
141 p := PopUpList label:'dummy'. |
119 p list:#('apples' 'bananas' 'grape' 'lemon' |
142 p list:#('apples' 'bananas' 'grape' 'lemon' |
120 '=' |
143 '=' |
121 'margaritas' 'pina colada' |
144 'margaritas' 'pina colada' |
122 '=' |
145 '=' |
123 'smalltalk' 'c++' 'eiffel'). |
146 'smalltalk' 'c++' 'eiffel'). |
124 p values:#(apples bananas grape lemon |
147 p values:#(apples bananas grape lemon |
125 nil |
148 nil |
126 'mhmh - so good' 'makes headache' |
149 'mhmh - so good' 'makes headache' |
127 nil |
150 nil |
128 'great' 'another headache' 'no bad'). |
151 'great' 'another headache' 'no bad'). |
129 p selection:'apples'. |
152 p selection:'apples'. |
130 p action:[:what | Transcript show:'you selected: '; showCr:what]. |
153 p action:[:what | Transcript show:'you selected: '; showCr:what]. |
131 p open |
154 p open |
132 |
155 |
133 |
156 |
159 |p model| |
182 |p model| |
160 |
183 |
161 model := SelectionInList with:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
184 model := SelectionInList with:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
162 |
185 |
163 p := PopUpList label:'healthy fruit'. |
186 p := PopUpList label:'healthy fruit'. |
164 p model:model; useIndex:true. |
187 p model:model; useIndex:true; change:#selectionIndex:. |
165 p open. |
188 p open. |
|
189 model selectionIndexHolder inspect |
|
190 |
|
191 |
|
192 a popupList and a SelectionInListView on the same model: |
|
193 |
|
194 |p slv model| |
|
195 |
|
196 model := SelectionInList with:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
|
197 model selection:'apples'. |
|
198 |
|
199 p := PopUpList on:model. |
|
200 p open. |
|
201 |
|
202 slv := SelectionInListView on:model. |
|
203 slv open. |
|
204 |
166 model selectionIndexHolder inspect |
205 model selectionIndexHolder inspect |
167 |
206 |
168 |
207 |
169 two PopUpLists on the same model: |
208 two PopUpLists on the same model: |
170 |
209 |
191 |
230 |
192 top open |
231 top open |
193 " |
232 " |
194 ! ! |
233 ! ! |
195 |
234 |
196 !PopUpList methodsFor:'initialization'! |
235 !PopUpList class methodsFor:'defaults'! |
197 |
236 |
198 initialize |
237 defaultAspectMessage |
199 super initialize. |
238 ^ #selection |
200 controller beTriggerOnDown. |
239 ! |
201 controller action:[self popMenu]. |
240 |
202 self adjust:#left. |
241 defaultListMessage |
203 useIndex := false. |
242 ^ #list |
204 changeMsg := #selection:. |
243 ! |
205 listMsg := #list. |
244 |
206 aspectMsg := #selection. |
245 defaultChangeMessage |
207 onLevel := offLevel. |
246 ^ #selection: |
|
247 ! ! |
|
248 |
|
249 !PopUpList methodsFor:'drawing'! |
|
250 |
|
251 drawWith:fgColor and:bgColor |
|
252 |mmH mmV mW mH| |
|
253 |
|
254 controller pressed ifTrue:[ |
|
255 super drawWith:enteredFgColor and:enteredBgColor |
|
256 ] ifFalse:[ |
|
257 super drawWith:fgColor and:bgColor. |
|
258 ]. |
|
259 mmH := device horizontalPixelPerMillimeter rounded. |
|
260 mmV := device verticalPixelPerMillimeter rounded. |
|
261 mW := (device horizontalPixelPerMillimeter * 2.5) rounded. |
|
262 mH := (device verticalPixelPerMillimeter * 1.5) rounded. |
|
263 |
|
264 self drawEdgesForX:(width - mW - (hSpace*2)) y:(height - mmV // 2) |
|
265 width:mW height:mH level:2 |
208 ! ! |
266 ! ! |
209 |
267 |
210 !PopUpList methodsFor:'private'! |
268 !PopUpList methodsFor:'private'! |
|
269 |
|
270 realize |
|
271 super realize. |
|
272 model notNil ifTrue:[ |
|
273 self getListFromModel |
|
274 ]. |
|
275 ! |
211 |
276 |
212 computeLabelSize |
277 computeLabelSize |
213 "compute the extent needed to hold the label plus the mark" |
278 "compute the extent needed to hold the label plus the mark" |
214 |
279 |
215 |mmH mmV savedLogo longest longestWidth| |
280 |mmH mmV savedLogo longest longestWidth| |
258 args:(1 to:aList size) |
324 args:(1 to:aList size) |
259 receiver:self |
325 receiver:self |
260 for:self. |
326 for:self. |
261 ! |
327 ! |
262 |
328 |
263 getSelectionFromModel |
|
264 "if I have a model and a listMsg, get my list from it" |
|
265 |
|
266 (model notNil |
|
267 and:[aspectMsg notNil]) ifTrue:[ |
|
268 self selection:(model perform:aspectMsg). |
|
269 ]. |
|
270 ! |
|
271 |
|
272 getListFromModel |
329 getListFromModel |
273 "if I have a model and a listMsg, get my list from it" |
330 "if I have a model and a listMsg, get my list from it" |
274 |
331 |
275 (model notNil |
332 (model notNil |
276 and:[listMsg notNil]) ifTrue:[ |
333 and:[listMsg notNil]) ifTrue:[ |
277 self list:(model perform:listMsg). |
334 self list:(model perform:listMsg). |
278 ]. |
335 ]. |
279 ! ! |
336 ! ! |
280 |
337 |
281 !PopUpList methodsFor:'event handling'! |
338 !PopUpList methodsFor:'event handling'! |
282 |
339 |
283 popMenu |
340 popMenu |
284 |org mv| |
341 |org mv| |
285 |
342 |
286 menu notNil ifTrue:[ |
343 menu notNil ifTrue:[ |
287 self turnOffWithoutRedraw. |
344 self turnOffWithoutRedraw. |
288 menu font:font. |
345 menu font:font. |
289 |
346 |
290 " |
347 " |
291 adjust the menus width to my current width |
348 adjust the menus width to my current width |
292 " |
349 " |
293 mv := menu menuView. |
350 mv := menu menuView. |
294 mv create. "/ stupid: it resizes itself upon first create |
351 mv create. "/ stupid: it resizes itself upon first create |
295 mv width:(self width - (2 * menu margin) - (menu borderWidth*2)). |
352 mv width:(self width - (2 * menu margin) - (menu borderWidth*2)). |
296 mv level:0; borderWidth:0. |
353 mv level:0; borderWidth:0. |
297 |
354 |
298 " |
355 " |
299 the popupMenu wants Display coordinates in its showAt: method |
356 the popupMenu wants Display coordinates in its showAt: method |
300 " |
357 " |
301 org := device translatePoint:0@0 |
358 org := device translatePoint:0@0 |
302 from:(self id) |
359 from:(self id) |
303 to:(DisplayRootView new id). |
360 to:(DisplayRootView new id). |
304 |
361 |
305 menu showAt:org "resizing:false" |
362 menu showAt:org "resizing:false" |
306 ]. |
363 ]. |
307 ! ! |
|
308 |
|
309 !PopUpList methodsFor:'drawing'! |
|
310 |
|
311 drawWith:fgColor and:bgColor |
|
312 |mmH mmV mW mH| |
|
313 |
|
314 controller pressed ifTrue:[ |
|
315 super drawWith:enteredFgColor and:enteredBgColor |
|
316 ] ifFalse:[ |
|
317 super drawWith:fgColor and:bgColor. |
|
318 ]. |
|
319 mmH := device horizontalPixelPerMillimeter rounded. |
|
320 mmV := device verticalPixelPerMillimeter rounded. |
|
321 mW := (device horizontalPixelPerMillimeter * 2.5) rounded. |
|
322 mH := (device verticalPixelPerMillimeter * 1.5) rounded. |
|
323 |
|
324 self drawEdgesForX:(width - mW - (hSpace*2)) y:(height - mmV // 2) |
|
325 width:mW height:mH level:2 |
|
326 ! ! |
364 ! ! |
327 |
365 |
328 !PopUpList methodsFor:'accessing'! |
366 !PopUpList methodsFor:'accessing'! |
329 |
367 |
330 useIndex:aBoolean |
368 selection:indexOrString |
331 useIndex := aBoolean |
369 "set (force) a selection - usually done to set |
332 |
370 an initial selection without updating others" |
333 " |
371 |
334 |p| |
372 |index| |
335 p := PopUpList label:'fruit ?'. |
373 |
336 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
374 index := menu labels indexOf:indexOrString. |
337 p action:[:val | Transcript showCr:'selected: ' , val printString]. |
375 index == 0 ifTrue:[^ self]. |
338 p open. |
376 self label:(menu labels at:index) |
339 " |
377 |
340 " |
378 " |
341 |p| |
379 |p| |
342 p := PopUpList label:'fruit ?'. |
380 p := PopUpList label:'what fruit ?'. |
343 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
381 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
344 p action:[:val | Transcript showCr:'selected: ' , val printString]. |
382 p selection:'grape'. |
345 p useIndex:true. |
383 p open |
346 p open. |
384 |
|
385 |p| |
|
386 p := PopUpList label:'what fruit ?'. |
|
387 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
|
388 p selection:'blabla'. |
|
389 p open |
347 " |
390 " |
348 ! |
391 ! |
349 |
392 |
350 list:aList |
393 list:aList |
351 "set the list - i.e. the values shown in the pop-up list" |
394 "set the list - i.e. the values shown in the pop-up list" |
370 selection-value as argument" |
413 selection-value as argument" |
371 |
414 |
372 menuAction := aOneArgBlock |
415 menuAction := aOneArgBlock |
373 ! |
416 ! |
374 |
417 |
|
418 useIndex:aBoolean |
|
419 "tell the popuplist to pass the index (instead of the value) |
|
420 to both the actionBlock and model. Notice, that if you use a model, |
|
421 the default changeSelector is not ok for using index and a SelectionInList" |
|
422 |
|
423 useIndex := aBoolean |
|
424 |
|
425 " |
|
426 |p| |
|
427 p := PopUpList label:'fruit ?'. |
|
428 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
|
429 p action:[:val | Transcript showCr:'selected: ' , val printString]. |
|
430 p open. |
|
431 " |
|
432 " |
|
433 |p| |
|
434 p := PopUpList label:'fruit ?'. |
|
435 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
|
436 p action:[:val | Transcript showCr:'selected: ' , val printString]. |
|
437 p useIndex:true. |
|
438 p open. |
|
439 " |
|
440 ! |
|
441 |
375 contents |
442 contents |
376 ^ self label |
443 ^ self label |
377 ! |
444 ! |
378 |
445 |
379 contents:con |
446 contents:con |
383 |
450 |
384 list |
451 list |
385 "return the list - i.e. the values shown in the pop-up list" |
452 "return the list - i.e. the values shown in the pop-up list" |
386 |
453 |
387 ^ menu labels |
454 ^ menu labels |
388 ! |
|
389 |
|
390 selection:indexOrString |
|
391 "set (force) a selection - usually done to set |
|
392 an initial selection" |
|
393 |
|
394 |index| |
|
395 |
|
396 index := menu labels indexOf:indexOrString. |
|
397 index == 0 ifTrue:[^ self]. |
|
398 self label:(menu labels at:index) |
|
399 |
|
400 " |
|
401 |p| |
|
402 p := PopUpList label:'what fruit ?'. |
|
403 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
|
404 p selection:'grape'. |
|
405 p open |
|
406 |
|
407 |p| |
|
408 p := PopUpList label:'what fruit ?'. |
|
409 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
|
410 p selection:'blabla'. |
|
411 p open |
|
412 " |
|
413 ! |
455 ! |
414 |
456 |
415 values:aList |
457 values:aList |
416 "set a value list - these are reported via the action or changeSymbol instead of |
458 "set a value list - these are reported via the action or changeSymbol instead of |
417 the labe strings." |
459 the labe strings." |
443 |
506 |
444 |value label| |
507 |value label| |
445 |
508 |
446 label := menu labels at:anEntry. |
509 label := menu labels at:anEntry. |
447 values isNil ifTrue:[ |
510 values isNil ifTrue:[ |
448 value := anEntry. |
511 value := anEntry. |
449 useIndex ifFalse:[ |
512 useIndex ifFalse:[ |
450 value := menu labels at:anEntry. |
513 value := menu labels at:anEntry. |
451 ] |
514 ] |
452 ] ifFalse:[ |
515 ] ifFalse:[ |
453 value := values at:anEntry |
516 value := values at:anEntry |
454 ]. |
517 ]. |
455 |
518 |
456 menuAction notNil ifTrue:[ |
519 menuAction notNil ifTrue:[ |
457 menuAction value:value. |
520 menuAction value:value. |
458 ]. |
521 ]. |
459 self sizeFixed:true. |
522 self sizeFixed:true. |
460 self label:label printString. |
523 self label:label printString. |
461 " |
524 " |
462 tell my model - if any |
525 tell my model - if any |
465 ! ! |
528 ! ! |
466 |
529 |
467 !PopUpList methodsFor:'change & update'! |
530 !PopUpList methodsFor:'change & update'! |
468 |
531 |
469 update:something with:aParameter from:changedObject |
532 update:something with:aParameter from:changedObject |
470 (changedObject == model) ifTrue:[ |
533 changedObject == model ifTrue:[ |
471 |
534 something == aspectMsg ifTrue:[ |
472 something == aspectMsg ifTrue:[ |
535 self getSelectionFromModel. |
473 self getSelectionFromModel. |
536 ^ self |
474 ] ifFalse:[ |
537 ]. |
475 something == listMsg ifTrue:[ |
538 something == listMsg ifTrue:[ |
476 self getListFromModel. |
539 self getListFromModel. |
477 ]. |
540 ]. |
478 ]. |
541 ^ self |
479 ^ self |
|
480 ]. |
542 ]. |
481 super update:something with:aParameter from:changedObject |
543 super update:something with:aParameter from:changedObject |
482 ! ! |
544 ! ! |
483 |
545 |