39 The PopUpLists label is showing the current selection from the |
40 The PopUpLists label is showing the current selection from the |
40 list. |
41 list. |
41 When an entry is selected, an actionBlock (if nonNil) is evaluated |
42 When an entry is selected, an actionBlock (if nonNil) is evaluated |
42 and (if nonNil), the model is notified via the changeMessage. |
43 and (if nonNil), the model is notified via the changeMessage. |
43 |
44 |
|
45 If no model is set, the list is assumed to be a static list, which |
|
46 is defined via #list:, and the popUpList evaluates the action block, |
|
47 as defined via #action:. |
|
48 |
|
49 If a model is provided, it should return the list from the listMsg (default |
|
50 is #list) and the current selected items index via |
|
51 #selection or: #selectionIndex (depending on the setting of useIndex). |
|
52 |
44 The default changeMessage used is #selection:, which allows a |
53 The default changeMessage used is #selection:, which allows a |
45 PopUpList to be used with a SelectionInList as model. |
54 PopUpList to be used with a SelectionInList as model. |
46 (if used with some other model, either use an adaptor, or set the |
55 (if used with some other model, either use an adaptor, or set the |
47 changeMessage to something else ..) |
56 changeMessage to something else ..) |
48 |
57 |
49 [Instance variables:] |
58 [Instance variables:] |
50 |
59 |
51 menu helpers for the popup menu |
60 menu helpers for the popup menu |
52 menuAction |
61 menuAction |
53 values |
62 values |
54 |
63 |
55 useIndex <Boolean> if true, the index of the selected entry |
64 useIndex <Boolean> if true, the index of the selected entry |
56 is passed to the action block and the |
65 is passed to the action block and the |
57 model in a change-message. |
66 model in a change-message. |
58 If false (the default), the value is passed. |
67 If false (the default), the value is passed. |
59 Notice that the default changeMessage is |
68 Notice that the default changeMessage is |
60 #selection:, which is not ok to be used |
69 #selection:, which is not ok to be used |
61 with useIndex:true and a selectionInList model. |
70 with useIndex:true and a selectionInList model. |
62 (set the changeMessage to #selectionIndex: then) |
71 (set the changeMessage to #selectionIndex: then) |
63 |
72 |
64 listMsg <Symbol> message to aquire a new list from the |
73 listMsg <Symbol> message to aquire a new list from the |
65 model. Default is #list. |
74 model. Default is #list. |
|
75 |
|
76 |
|
77 listHolder <Object> if non-nil, this object is assumed to return the |
|
78 list via the listMsg (instead of the model). |
|
79 Default is nil. |
|
80 |
|
81 selectionHolder <Object> if non-nil, this object is assumed to return the |
|
82 selection via the changeMsg (instead of the model). |
|
83 UseIndex specifies if its numeric (i.e. a selectionindex) |
|
84 Default is nil. |
66 |
85 |
67 [see also:] |
86 [see also:] |
68 SelectionInListView |
87 SelectionInListView |
69 SelectionInList |
88 SelectionInList |
70 |
89 |
71 [author:] |
90 [author:] |
72 Claus Gittinger |
91 Claus Gittinger |
73 " |
92 " |
74 ! |
93 ! |
75 |
94 |
76 examples |
95 examples |
77 " |
96 " |
78 example use: |
97 example use: |
79 [exBegin] |
98 [exBegin] |
80 |p| |
99 |p| |
81 p := PopUpList label:'healthy fruit'. |
100 p := PopUpList label:'healthy fruit'. |
82 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
101 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
83 p open |
102 p open |
84 [exEnd] |
103 [exEnd] |
85 |
104 |
86 |
105 |
87 with an initial selection: |
106 with an initial selection: |
88 [exBegin] |
107 [exBegin] |
89 |p| |
108 |p| |
90 p := PopUpList label:'dummy'. |
109 p := PopUpList label:'dummy'. |
91 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
110 p list:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
92 p selection:'apples'. |
111 p selection:'apples'. |
93 p open |
112 p open |
94 [exEnd] |
113 [exEnd] |
95 |
114 |
96 |
115 |
97 with separating lines: |
116 with separating lines: |
98 [exBegin] |
117 [exBegin] |
99 |p| |
118 |p| |
100 p := PopUpList label:'fruit'. |
119 p := PopUpList label:'fruit'. |
101 p list:#('apples' 'bananas' 'grape' 'lemon' '-' 'margaritas'). |
120 p list:#('apples' 'bananas' 'grape' 'lemon' '-' 'margaritas'). |
102 p selection:'apples'. |
121 p selection:'apples'. |
103 p open |
122 p open |
104 [exEnd] |
123 [exEnd] |
105 |
124 |
106 |
125 |
107 with an action: |
126 with an action: |
108 [exBegin] |
127 [exBegin] |
109 |p| |
128 |p| |
110 p := PopUpList label:'dummy'. |
129 p := PopUpList label:'dummy'. |
111 p list:#('apples' 'bananas' 'grape' 'lemon' '-' 'margaritas'). |
130 p list:#('apples' 'bananas' 'grape' 'lemon' '-' 'margaritas'). |
112 p selection:'apples'. |
131 p selection:'apples'. |
113 p action:[:what | Transcript showCR:'you selected: ' , what]. |
132 p action:[:what | Transcript showCR:'you selected: ' , what]. |
114 p open |
133 p open |
115 [exEnd] |
134 [exEnd] |
116 |
135 |
117 |
136 |
118 sometimes, you may like the index instead of the value: |
137 sometimes, you may like the index instead of the value: |
119 (notice, that the separating line counts, so you have to take care ...) |
138 (notice, that the separating line counts, so you have to take care ...) |
120 [exBegin] |
139 [exBegin] |
121 |p| |
140 |p| |
122 p := PopUpList label:'dummy'. |
141 p := PopUpList label:'dummy'. |
123 p list:#('apples' 'bananas' 'grape' 'lemon' '-' 'margaritas'). |
142 p list:#('apples' 'bananas' 'grape' 'lemon' '-' 'margaritas'). |
124 p selection:'apples'. |
143 p selection:'apples'. |
125 p action:[:what | Transcript show:'you selected: '; showCR:what]. |
144 p action:[:what | Transcript show:'you selected: '; showCR:what]. |
126 p useIndex:true. |
145 p useIndex:true. |
127 p open |
146 p open |
128 [exEnd] |
147 [exEnd] |
129 |
148 |
130 |
149 |
131 since the list is actually a popupMenu, you can add double-separators: |
150 since the list is actually a popupMenu, you can add double-separators: |
132 [exBegin] |
151 [exBegin] |
133 |p| |
152 |p| |
134 p := PopUpList label:'dummy'. |
153 p := PopUpList label:'dummy'. |
135 p list:#('apples' 'bananas' 'grape' 'lemon' |
154 p list:#('apples' 'bananas' 'grape' 'lemon' |
136 '=' |
155 '=' |
137 'margaritas' 'pina colada' |
156 'margaritas' 'pina colada' |
138 '=' |
157 '=' |
139 'smalltalk' 'c++' 'eiffel' 'java'). |
158 'smalltalk' 'c++' 'eiffel' 'java'). |
140 p values:#(apples bananas grape lemon |
159 p values:#(apples bananas grape lemon |
141 nil |
160 nil |
142 'mhmh - so good' 'makes headache' |
161 'mhmh - so good' 'makes headache' |
143 nil |
162 nil |
144 'great' 'another headache' 'not bad' 'neat'). |
163 'great' 'another headache' 'not bad' 'neat'). |
145 p selection:'apples'. |
164 p selection:'apples'. |
146 p action:[:what | Transcript show:'you selected: '; showCR:what]. |
165 p action:[:what | Transcript show:'you selected: '; showCR:what]. |
147 p open |
166 p open |
148 [exEnd] |
167 [exEnd] |
149 |
168 |
150 |
169 |
151 since the list is actually represented by a menuView, |
170 since the list is actually represented by a menuView, |
152 which itself is inheriting from listView, which itself can display |
171 which itself is inheriting from listView, which itself can display |
153 things different from strings, arbitrary lists can be constructed: |
172 things different from strings, arbitrary lists can be constructed: |
154 (see ListEntry classes) |
173 (see ListEntry classes) |
155 [exBegin] |
174 [exBegin] |
156 |p l| |
175 |p l| |
157 p := PopUpList label:'dummy'. |
176 p := PopUpList label:'dummy'. |
158 l := OrderedCollection new. |
177 l := OrderedCollection new. |
159 l add:(ColoredListEntry string:'apples' color:Color red). |
178 l add:(ColoredListEntry string:'apples' color:Color red). |
160 l add:(ColoredListEntry string:'bananas' color:Color red). |
179 l add:(ColoredListEntry string:'bananas' color:Color red). |
168 l add:(ColoredListEntry string:'c++' color:Color blue). |
187 l add:(ColoredListEntry string:'c++' color:Color blue). |
169 l add:(ColoredListEntry string:'eiffel' color:Color blue). |
188 l add:(ColoredListEntry string:'eiffel' color:Color blue). |
170 l add:(ColoredListEntry string:'java' color:Color blue). |
189 l add:(ColoredListEntry string:'java' color:Color blue). |
171 p list:l. |
190 p list:l. |
172 p values:#(apples bananas grape lemon |
191 p values:#(apples bananas grape lemon |
173 nil |
192 nil |
174 'mhmh - so good' 'makes headache' |
193 'mhmh - so good' 'makes headache' |
175 nil |
194 nil |
176 'great' 'another headache' 'not bad' 'neat'). |
195 'great' 'another headache' 'not bad' 'neat'). |
177 p selection:'apples'. |
196 p selection:'apples'. |
178 p action:[:what | Transcript show:'you selected: '; showCR:what]. |
197 p action:[:what | Transcript show:'you selected: '; showCR:what]. |
179 p open |
198 p open |
180 [exEnd] |
199 [exEnd] |
181 |
200 |
182 |
201 |
183 with values different from the label strings: |
202 with values different from the label strings: |
184 [exBegin] |
203 [exBegin] |
185 |p| |
204 |p| |
186 p := PopUpList label:'dummy'. |
205 p := PopUpList label:'dummy'. |
187 p list:#('apples' 'bananas' 'grape' 'lemon' '-' 'margaritas'). |
206 p list:#('apples' 'bananas' 'grape' 'lemon' '-' 'margaritas'). |
188 p selection:'apples'. |
207 p selection:'apples'. |
189 p values:#(10 20 30 40 nil 50). |
208 p values:#(10 20 30 40 nil 50). |
190 p action:[:what | Transcript show:'you selected: '; showCR:what]. |
209 p action:[:what | Transcript show:'you selected: '; showCR:what]. |
191 p open |
210 p open |
192 [exEnd] |
211 [exEnd] |
193 |
212 |
194 |
213 |
195 with a model (see in the inspector, how the valueHolders index-value changes): |
214 with a model (see in the inspector, how the valueHolders index-value changes): |
196 [exBegin] |
215 [exBegin] |
197 |p model| |
216 |p model| |
198 |
217 |
199 model := SelectionInList with:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
218 model := SelectionInList with:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
200 |
219 |
201 p := PopUpList label:'healthy fruit'. |
220 p := PopUpList label:'healthy fruit'. |
202 p model:model. |
221 p model:model. |
203 p open. |
222 p open. |
204 model selectionIndexHolder inspect |
223 model selectionIndexHolder inspect |
205 [exEnd] |
224 [exEnd] |
206 |
225 |
207 |
226 |
208 a popupList and a SelectionInListView on the same model: |
227 a popupList and a SelectionInListView on the same model: |
209 [exBegin] |
228 [exBegin] |
210 |p slv model| |
229 |p slv model| |
211 |
230 |
212 model := SelectionInList with:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
231 model := SelectionInList with:#('apples' 'bananas' 'grape' 'lemon' 'margaritas'). |
213 model selection:'apples'. |
232 model selection:'apples'. |
214 |
233 |
402 ! |
503 ! |
403 |
504 |
404 getListFromModel |
505 getListFromModel |
405 "if I have a model and a listMsg, get my list from it" |
506 "if I have a model and a listMsg, get my list from it" |
406 |
507 |
407 (model notNil |
508 |l| |
408 and:[listMsg notNil]) ifTrue:[ |
509 |
409 self list:(model perform:listMsg). |
510 listMsg notNil ifTrue:[ |
410 ]. |
511 listHolder notNil ifTrue:[ |
|
512 l := listHolder perform:listMsg |
|
513 ] ifFalse:[ |
|
514 model notNil ifTrue:[ |
|
515 l := model perform:listMsg. |
|
516 ] |
|
517 ]. |
|
518 self list:l |
|
519 ] |
411 ! |
520 ! |
412 |
521 |
413 getSelectionFromModel |
522 getSelectionFromModel |
414 "if I have a model and an aspectMsg, get my current value from it" |
523 "if I have a model and an aspectMsg, get my current value from it" |
415 |
524 |
416 (model notNil |
525 |sel| |
417 and:[aspectMsg notNil]) ifTrue:[ |
526 |
418 menu isNil ifTrue:[ |
527 aspectMsg notNil ifTrue:[ |
419 self getListFromModel |
528 selectionHolder notNil ifTrue:[ |
420 ]. |
529 sel := selectionHolder perform:aspectMsg |
421 self selection:(model perform:aspectMsg). |
530 ] ifFalse:[ |
|
531 model notNil ifTrue:[ |
|
532 sel := model perform:aspectMsg. |
|
533 ] |
|
534 ]. |
|
535 self selection:sel |
422 ]. |
536 ]. |
423 |
537 |
424 "Modified: 25.5.1996 / 14:21:07 / cg" |
538 "Modified: 25.5.1996 / 14:21:07 / cg" |
425 ! |
539 ! |
426 |
540 |
427 listMessage |
541 listMessage |
428 "return the selector by which we ask the model for the list. |
542 "return the selector by which we ask the model for the list. |
429 Default is #list." |
543 The default is #list if used with a model |
|
544 or #value, if used with a listHolder." |
430 |
545 |
431 ^ listMsg |
546 ^ listMsg |
432 ! |
547 ! |
433 |
548 |
434 listMessage:aSelector |
549 listMessage:aSelector |
435 "set the selector by which we ask the model for the list. |
550 "set the selector by which we ask the model for the list. |
436 Default is #list." |
551 The default is #list if used with a model |
|
552 or #value, if used with a listHolder." |
437 |
553 |
438 listMsg := aSelector |
554 listMsg := aSelector |
439 ! ! |
555 ! ! |
440 |
556 |
441 !PopUpList methodsFor:'change & update'! |
557 !PopUpList methodsFor:'change & update'! |
442 |
558 |
443 update:something with:aParameter from:changedObject |
559 update:something with:aParameter from:changedObject |
|
560 changedObject == listHolder ifTrue:[ |
|
561 self getListFromModel. |
|
562 ^ self |
|
563 ]. |
|
564 changedObject == selectionHolder ifTrue:[ |
|
565 self getSelectionFromModel. |
|
566 ^ self |
|
567 ]. |
|
568 |
444 changedObject == model ifTrue:[ |
569 changedObject == model ifTrue:[ |
445 (something == aspectMsg |
570 (something == aspectMsg |
446 or:[something == #selectionIndex]) ifTrue:[ |
571 or:[something == #selectionIndex]) ifTrue:[ |
447 self getSelectionFromModel. |
572 self getSelectionFromModel. |
448 ^ self |
573 ^ self |
544 !PopUpList methodsFor:'private'! |
669 !PopUpList methodsFor:'private'! |
545 |
670 |
546 computeLabelSize |
671 computeLabelSize |
547 "compute the extent needed to hold the label plus the mark" |
672 "compute the extent needed to hold the label plus the mark" |
548 |
673 |
549 |mmH mmV savedLogo longest longestWidth| |
674 |mmH mmV savedLogo longest longestWidth labels| |
550 |
675 |
551 menu isNil ifTrue:[ |
676 menu isNil ifTrue:[ |
552 super computeLabelSize |
677 super computeLabelSize |
553 ] ifFalse:[ |
678 ] ifFalse:[ |
554 "hack: simulate logo change to longest menu entry" |
679 "hack: simulate logo change to longest menu entry" |
555 |
680 |
556 font := font on:device. |
681 font := font on:device. |
557 longest := logo. |
682 longest := logo. |
558 longestWidth := font widthOf:logo. |
683 logo isNil ifTrue:[ |
559 menu labels do:[:entry | |
684 longestWidth := 0 |
560 |this| |
685 ] ifFalse:[ |
561 |
686 longestWidth := font widthOf:logo. |
562 this := font widthOf:entry printString. |
687 ]. |
563 this > longestWidth ifTrue:[ |
688 labels := menu labels. |
564 longest := entry. |
689 labels notNil ifTrue:[ |
565 longestWidth := this |
690 labels do:[:entry | |
566 ]. |
691 |this| |
567 ]. |
692 |
568 savedLogo := logo. |
693 this := font widthOf:entry printString. |
569 logo := longest printString. |
694 this > longestWidth ifTrue:[ |
570 super computeLabelSize. |
695 longest := entry. |
571 logo := savedLogo. |
696 longestWidth := this |
572 "self halt. " |
697 ]. |
|
698 ]. |
|
699 ]. |
|
700 savedLogo := logo. |
|
701 logo := longest printString. |
|
702 super computeLabelSize. |
|
703 logo := savedLogo. |
573 ]. |
704 ]. |
574 mmH := device horizontalPixelPerMillimeter. |
705 mmH := device horizontalPixelPerMillimeter. |
575 mmV := device verticalPixelPerMillimeter. |
706 mmV := device verticalPixelPerMillimeter. |
576 labelWidth := labelWidth + hSpace + (mmH * 2.5) rounded + hSpace. |
707 labelWidth := labelWidth + hSpace + (mmH * 2.5) rounded + hSpace. |
577 labelHeight := labelHeight max: (mmV * 2) rounded |
708 labelHeight := labelHeight max: (mmV * 2) rounded |