PopUpList.st
changeset 125 3ffa271732f7
parent 121 4e63bbdb266a
child 126 40228f4fd66b
equal deleted inserted replaced
124:7abd3a234296 125:3ffa271732f7
     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|
   241     mmV := device verticalPixelPerMillimeter.
   306     mmV := device verticalPixelPerMillimeter.
   242     labelWidth := labelWidth + hSpace + (mmH * 2.5) rounded + hSpace.
   307     labelWidth := labelWidth + hSpace + (mmH * 2.5) rounded + hSpace.
   243     labelHeight := labelHeight max: (mmV * 2) rounded
   308     labelHeight := labelHeight max: (mmV * 2) rounded
   244 !
   309 !
   245 
   310 
   246 realize
   311 getSelectionFromModel
   247     super realize.
   312     "if I have a model and a listMsg, get my list from it"
   248     model notNil ifTrue:[
   313 
   249 	self createMenuFor:(model perform:listMsg).
   314     (model notNil 
   250         
   315     and:[aspectMsg notNil]) ifTrue:[
       
   316 	self selection:(model perform:aspectMsg).
   251     ].
   317     ].
   252 !
   318 !
   253 
   319 
   254 createMenuFor:aList
   320 createMenuFor:aList
   255     menu := PopUpMenu
   321     menu := PopUpMenu
   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."
   432 listMessage:aSelector
   474 listMessage:aSelector
   433     "set the selector by which we ask the model for the list.
   475     "set the selector by which we ask the model for the list.
   434      Default is #list."
   476      Default is #list."
   435 
   477 
   436     listMsg := aSelector
   478     listMsg := aSelector
       
   479 !
       
   480 
       
   481 listMessage
       
   482     "return the selector by which we ask the model for the list.
       
   483      Default is #list."
       
   484 
       
   485     ^ listMsg
       
   486 ! !
       
   487 
       
   488 !PopUpList methodsFor:'initialization'!
       
   489 
       
   490 initialize
       
   491     super initialize.
       
   492     controller beTriggerOnDown.
       
   493     controller action:[self popMenu].
       
   494     self adjust:#left.
       
   495     useIndex := false.
       
   496 
       
   497     listMsg := self class defaultListMessage.
       
   498 
       
   499     onLevel := offLevel.
   437 ! !
   500 ! !
   438 
   501 
   439 !PopUpList methodsFor:'user actions'!
   502 !PopUpList methodsFor:'user actions'!
   440 
   503 
   441 select:anEntry
   504 select:anEntry
   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