SelectionInListModelView.st
changeset 1390 62dc950b9140
child 1391 83ed7574be4c
equal deleted inserted replaced
1389:3548d53b14ae 1390:62dc950b9140
       
     1 ListModelView subclass:#SelectionInListModelView
       
     2 	instanceVariableNames:'selection multipleSelectOk actionBlock doubleClickActionBlock
       
     3 		clickLine highlightMode useIndex hilightFgColor hilightBgColor
       
     4 		hilightLevel hilightFrameColor hilightStyle dragAccessPoint
       
     5 		dropTarget dropSource'
       
     6 	classVariableNames:'DefaultHilightStyle DefaultHilightBackgroundColor
       
     7 		DefaultHilightForegroundColor DefaultHilightLevel
       
     8 		DefaultHilightFrameColor'
       
     9 	poolDictionaries:''
       
    10 	category:'AAA'
       
    11 !
       
    12 
       
    13 !SelectionInListModelView class methodsFor:'documentation'!
       
    14 
       
    15 documentation
       
    16 "
       
    17     SelectionInListModelView is mostly like SelectionInListView,
       
    18     but derives from the ListModelView and thus the list is kept
       
    19     by the model.
       
    20 
       
    21     [Instance variables:]
       
    22         selection               <misc>     the current selection. nil, a number or collection of numbers
       
    23         multipleSelectOk        <Boolean>  allow/disallow multiple selections( default:false )
       
    24         actionBlock             <Block>    action evaluated on single click
       
    25         doubleClickActionBlock  <Block>    action evaluated on double click
       
    26         clickPosition           <Point>    internal use
       
    27         highlightMode           <Symbol>   how to draw the selection
       
    28         useIndex                <Boolean>  representation of the model selection
       
    29         hilightFgColor          <Color>           
       
    30         hilightBgColor          <Color>    how highlighted items are drawn
       
    31         hilightLevel            <Integer>  level to draw selections (i.e. for 3D effect)
       
    32         hilightFrameColor       <Color>    rectangle around highlighted items
       
    33         hilightStyle            <Boolean>  actions on widget are enabled/disabled
       
    34 
       
    35     [author:]
       
    36         Claus Atzkern
       
    37 
       
    38     [see also:]
       
    39 
       
    40         ListModelView
       
    41         HierarchicalListView
       
    42 "
       
    43 
       
    44 
       
    45 !
       
    46 
       
    47 examples
       
    48 "
       
    49                                                                         [exBegin]
       
    50     |top list view|
       
    51 
       
    52     list := List new.
       
    53 
       
    54     1 to:100 do:[:i| list add:('element: ', i printString) ].
       
    55     top  := StandardSystemView new; extent:300@300.
       
    56     view := ScrollableView for:SelectionInListModelView miniScroller:true
       
    57                         origin:0.0@0.0 corner:1.0@1.0 in:top.
       
    58     view list:list.
       
    59     top  open.
       
    60                                                                         [exEnd]
       
    61 
       
    62 
       
    63                                                                         [exBegin]
       
    64     |top list view item|
       
    65 
       
    66     list := HierarchicalList new.
       
    67     item := HierarchicalItem::Example labeled:'Test'.
       
    68     item expand.
       
    69     list showRoot:false.
       
    70     list root:item.
       
    71 
       
    72     top  := StandardSystemView new; extent:300@300.
       
    73     view := ScrollableView for:SelectionInListModelView miniScroller:true
       
    74                         origin:0.0@0.0 corner:1.0@1.0 in:top.
       
    75 
       
    76     view list:list.
       
    77     view doubleClickAction:[:i| (list at:i) toggleExpand ].
       
    78     top  open.
       
    79                                                                         [exEnd]
       
    80 
       
    81 "
       
    82 
       
    83 ! !
       
    84 
       
    85 !SelectionInListModelView class methodsFor:'defaults'!
       
    86 
       
    87 updateStyleCache
       
    88     "extract values from the styleSheet and cache them in class variables"
       
    89 
       
    90     <resource: #style   (
       
    91                         #'selection.hilightForegroundColor' #'selection.hilightBackgroundColor'
       
    92                         #'selection.hilightFrameColor'      #'selection.hilightLevel'
       
    93                         #'selection.foregroundColor'        #'selection.backgroundColor'
       
    94                         #'selection.shadowColor'            #'selection.lightColor'
       
    95                         #'selection.font'                   #'selection.hilightStyle'
       
    96                         #'text.foregroundColor'
       
    97                         )>
       
    98 
       
    99     DefaultHilightForegroundColor  := StyleSheet colorAt:'selection.hilightForegroundColor'.
       
   100     DefaultHilightBackgroundColor  := StyleSheet colorAt:'selection.hilightBackgroundColor'.
       
   101     DefaultHilightFrameColor       := StyleSheet colorAt:'selection.hilightFrameColor'.
       
   102     DefaultHilightLevel            := StyleSheet at:'selection.hilightLevel' default:0.
       
   103     DefaultHilightStyle            := StyleSheet at:'selection.hilightStyle' default:(StyleSheet name).
       
   104     DefaultForegroundColor         := StyleSheet colorAt:'selection.foregroundColor'.
       
   105     DefaultBackgroundColor         := StyleSheet colorAt:'selection.backgroundColor'.
       
   106     DefaultShadowColor             := StyleSheet colorAt:'selection.shadowColor'.
       
   107     DefaultLightColor              := StyleSheet colorAt:'selection.lightColor'.
       
   108 
       
   109     DefaultForegroundColor isNil ifTrue:[
       
   110         DefaultForegroundColor := StyleSheet colorAt:'text.foregroundColor' default:Black
       
   111     ].
       
   112     "
       
   113      self updateStyleCache
       
   114     "
       
   115 
       
   116 
       
   117 ! !
       
   118 
       
   119 !SelectionInListModelView methodsFor:'accessing'!
       
   120 
       
   121 list:aList
       
   122     "get the status of <showRoot> from the list
       
   123     "
       
   124     selection notNil ifTrue:[
       
   125         selection := nil.
       
   126         self selectionChanged.
       
   127     ].
       
   128   ^ super list:aList
       
   129 ! !
       
   130 
       
   131 !SelectionInListModelView methodsFor:'accessing behavior'!
       
   132 
       
   133 highlightMode
       
   134     "get the mode how to draw a selected line:
       
   135         #line           draw whole line selected
       
   136         #label          draw label selected
       
   137     "
       
   138     ^ highlightMode
       
   139 
       
   140 
       
   141 !
       
   142 
       
   143 highlightMode:aMode
       
   144     "set the mode how to draw a selected line:
       
   145         #line           draw whole line selected
       
   146         #label          draw label selected
       
   147     "
       
   148     (aMode ~~ highlightMode and:[(aMode == #label or:[aMode == #line])]) ifTrue:[
       
   149         highlightMode := aMode.
       
   150 
       
   151         shown ifTrue:[
       
   152             self selectionDo:[:i|self redrawSelectionAt:i]
       
   153         ]
       
   154     ]
       
   155 
       
   156 !
       
   157 
       
   158 multipleSelectOk
       
   159     "allow/disallow multiple selections; the default is false
       
   160     "
       
   161     ^ multipleSelectOk
       
   162 
       
   163 
       
   164 !
       
   165 
       
   166 multipleSelectOk:aState
       
   167     "allow/disallow multiple selections; the default is false
       
   168     "
       
   169     aState == multipleSelectOk ifFalse:[
       
   170         multipleSelectOk := aState.
       
   171         selection notNil ifTrue:[
       
   172             multipleSelectOk ifTrue:[
       
   173                 selection := Array with:selection
       
   174             ] ifFalse:[
       
   175                 selection size ~~ 1 ifTrue:[
       
   176                     selection := nil.
       
   177                     self invalidate.
       
   178                     self selectionChanged
       
   179                 ] ifFalse:[
       
   180                     selection := selection at:1
       
   181                 ]
       
   182             ]
       
   183         ]
       
   184     ]
       
   185 
       
   186 !
       
   187 
       
   188 useIndex
       
   189     "set/clear the useIndex flag.
       
   190      the selection writen to the model are the indices into the list
       
   191      or the elements selected.
       
   192     "
       
   193     ^ useIndex
       
   194 
       
   195 
       
   196 !
       
   197 
       
   198 useIndex:aBoolean
       
   199     "set/clear the useIndex flag.
       
   200      the selection writen to the model are the indices into the list
       
   201      or the elements selected.
       
   202     "
       
   203     useIndex := aBoolean ? true
       
   204 
       
   205 
       
   206 ! !
       
   207 
       
   208 !SelectionInListModelView methodsFor:'actions'!
       
   209 
       
   210 action:aOneArgAction
       
   211     "set the action block to be performed on select
       
   212     "
       
   213     actionBlock := aOneArgAction
       
   214 
       
   215 
       
   216 !
       
   217 
       
   218 doubleClickAction:aOneArgAction
       
   219     "set the action block to be performed on doubleclick
       
   220     "
       
   221     doubleClickActionBlock := aOneArgAction
       
   222 
       
   223 
       
   224 ! !
       
   225 
       
   226 !SelectionInListModelView methodsFor:'change & update'!
       
   227 
       
   228 argForChangeMessage
       
   229     "return the argument for a selectionChange;
       
   230      depending on the setting of useIndex, this is either the numeric
       
   231      index of the selection or the value (i.e. the string)
       
   232     "
       
   233     useIndex ifFalse:[
       
   234         ^ self selectionValue
       
   235     ].
       
   236     selection isNil ifTrue:[
       
   237         ^ multipleSelectOk ifTrue:[#()] ifFalse:[0]
       
   238     ].
       
   239   ^ multipleSelectOk ifTrue:[selection copy] ifFalse:[selection]
       
   240 !
       
   241 
       
   242 getSelectionFromModel
       
   243     "get selection from model; returns a selection or nil
       
   244     "
       
   245     |value newSel|
       
   246 
       
   247     (    model isNil
       
   248      or:[(value := model value) isNil
       
   249      or:[value == 0]]
       
   250     ) ifTrue:[
       
   251         ^ nil
       
   252     ].
       
   253 
       
   254     multipleSelectOk ifFalse:[
       
   255         useIndex ifFalse:[
       
   256             (value := self identityIndexOf:value) == 0 ifTrue:[
       
   257                 ^ nil
       
   258             ]
       
   259         ].
       
   260         ^ value
       
   261     ].
       
   262 
       
   263     "/ MULTI SELECT
       
   264 
       
   265     value isEmpty ifTrue:[^ nil].
       
   266     useIndex      ifTrue:[^ value].
       
   267 
       
   268     newSel := OrderedCollection new.
       
   269 
       
   270     value do:[:el||index|
       
   271         (index := self identityIndexOf:el) ~~ 0 ifTrue:[
       
   272             newSel add:index
       
   273         ]
       
   274     ].
       
   275 
       
   276     ^ newSel notEmpty ifTrue:[newSel] ifFalse:[nil]
       
   277 !
       
   278 
       
   279 listSizeChanged:aLnNr nLines:aDeltaLines
       
   280     "update selection
       
   281     "
       
   282     |newSel noChg size changed|
       
   283 
       
   284     super listSizeChanged:aLnNr nLines:aDeltaLines.
       
   285 
       
   286     selection isNil ifTrue:[^ self].
       
   287 
       
   288     list size == 0 ifTrue:[
       
   289       ^ self deselectWithoutRedraw
       
   290     ].
       
   291     multipleSelectOk ifFalse:[
       
   292         selection >= aLnNr ifTrue:[
       
   293             selection := selection + aDeltaLines.
       
   294 
       
   295             (aDeltaLines < 0 and:[selection < aLnNr]) ifTrue:[
       
   296                 self deselectWithoutRedraw
       
   297             ] ifFalse:[
       
   298                 (model notNil and:[useIndex]) ifTrue:[
       
   299                     model setValue:selection
       
   300                 ]
       
   301             ]
       
   302         ].
       
   303         ^ self
       
   304     ].
       
   305 
       
   306     size    := selection size.
       
   307     changed := false.
       
   308 
       
   309     aDeltaLines < 0  ifFalse:[
       
   310         1 to:size do:[:anIndex|
       
   311             newSel := selection at:anIndex.
       
   312 
       
   313             newSel >= aLnNr ifTrue:[
       
   314                 changed := true.
       
   315                 selection at:anIndex put:(newSel + aDeltaLines)
       
   316             ]
       
   317         ].
       
   318         (changed and:[useIndex and:[model notNil]]) ifTrue:[
       
   319             model setValue:(selection copy)
       
   320         ].
       
   321         ^ self
       
   322     ].
       
   323     noChg := 0.
       
   324 
       
   325     1 to:size do:[:anIndex|
       
   326         newSel := selection at:anIndex.
       
   327 
       
   328         newSel >= aLnNr ifTrue:[
       
   329             newSel  := newSel + aDeltaLines.
       
   330             changed := true.
       
   331 
       
   332             newSel < aLnNr ifTrue:[
       
   333                 noChg  := noChg + 1.
       
   334                 newSel := 0.
       
   335             ].
       
   336             selection at:anIndex put:newSel
       
   337         ]
       
   338     ].
       
   339 
       
   340     noChg ~~ 0 ifTrue:[
       
   341         noChg == size ifTrue:[
       
   342             self deselectWithoutRedraw
       
   343         ] ifFalse:[
       
   344             selection := selection select:[:i| i ~~ 0].
       
   345             self selectionChanged
       
   346         ]
       
   347     ] ifFalse:[
       
   348         (changed and:[useIndex and:[model notNil]]) ifTrue:[
       
   349             model setValue:(selection copy)
       
   350         ]
       
   351     ]
       
   352 
       
   353 !
       
   354 
       
   355 selectionChanged
       
   356     "selection has changed. Call actionblock and/or send changeMessage if defined
       
   357     "
       
   358     |value arg|
       
   359 
       
   360     (model isNil and:[actionBlock isNil]) ifTrue:[
       
   361         ^ self
       
   362     ].
       
   363 
       
   364     arg := self argForChangeMessage.
       
   365 
       
   366     model notNil ifTrue:[
       
   367         model removeDependent:self.
       
   368         self sendChangeMessage:#value: with:arg.
       
   369         model addDependent:self.
       
   370     ].
       
   371 
       
   372     actionBlock notNil ifTrue:[
       
   373         (actionBlock numArgs) == 1 ifTrue:[
       
   374             actionBlock value:arg
       
   375         ] ifFalse:[
       
   376             actionBlock value
       
   377         ]
       
   378     ].
       
   379 
       
   380 !
       
   381 
       
   382 update:something with:aParameter from:changedObject
       
   383     "one of my models changed
       
   384     "
       
   385     |newSelection|
       
   386 
       
   387     changedObject == model ifTrue:[
       
   388         newSelection := self getSelectionFromModel.
       
   389 
       
   390         newSelection ~= selection ifTrue:[
       
   391             self setSelection:newSelection
       
   392         ]
       
   393     ] ifFalse:[
       
   394         super update:something with:aParameter from:changedObject
       
   395     ].
       
   396 ! !
       
   397 
       
   398 !SelectionInListModelView methodsFor:'drag & drop'!
       
   399 
       
   400 canDrag
       
   401     "returns true if dragging is enabled
       
   402     "
       
   403     ^ dropSource notNil
       
   404 
       
   405 !
       
   406 
       
   407 dropSource
       
   408     "returns the dropSource or nil
       
   409     "
       
   410     ^ dropSource
       
   411 
       
   412 !
       
   413 
       
   414 dropSource:aDropSourceOrNil
       
   415     "set the dropSource or nil
       
   416     "
       
   417     dropSource := aDropSourceOrNil.
       
   418 
       
   419 !
       
   420 
       
   421 dropTarget
       
   422     "returns the dropTarget or nil
       
   423     "
       
   424     ^ dropTarget
       
   425 
       
   426 
       
   427 !
       
   428 
       
   429 dropTarget:aDropTragetOrNil
       
   430     "set the dropTarget or nil
       
   431     "
       
   432     dropTarget := aDropTragetOrNil.
       
   433 
       
   434 !
       
   435 
       
   436 startDragAt:aPoint
       
   437     "start drag at a point
       
   438     "
       
   439     dropSource notNil ifTrue:[
       
   440         dropSource startDragSelector notNil ifTrue:[
       
   441             dropSource startDragIn:self at:aPoint
       
   442         ] ifFalse:[
       
   443             DragAndDropManager new startDragFrom:self
       
   444                                       dropSource:dropSource
       
   445                                           offset:#center
       
   446         ]
       
   447     ]
       
   448 
       
   449 ! !
       
   450 
       
   451 !SelectionInListModelView methodsFor:'drawing'!
       
   452 
       
   453 drawFrom:start to:stop x:x y:y width:w
       
   454     "draw the lines between start to stop without clearing the background
       
   455     "
       
   456     |selY selH
       
   457      y0       "{ Class:SmallInteger }"
       
   458      y1       "{ Class:SmallInteger }"
       
   459      hg       "{ Class:SmallInteger }"
       
   460     |
       
   461     (highlightMode == #line and:[selection notNil]) ifTrue:[
       
   462         "/ redraw the background for all selected lines in the invalid range
       
   463 
       
   464         self selectionDo:[:lnNr|
       
   465             (lnNr between:start and:stop) ifTrue:[
       
   466                 selY isNil ifTrue:[
       
   467                     selY := OrderedCollection new.
       
   468                     selH := OrderedCollection new.
       
   469                     self paint:hilightBgColor.
       
   470                 ].
       
   471                 y0 := self yVisibleOfLine:lnNr.
       
   472                 y1 := self yVisibleOfLine:(lnNr + 1).
       
   473                 hg := y1 - y0.
       
   474                 selY add:y0.
       
   475                 selH add:hg.
       
   476                 self fillRectangleX:x y:y0 width:w height:hg.
       
   477             ]
       
   478         ]
       
   479     ].
       
   480     self drawElementsFrom:start to:stop x:x y:y width:w.
       
   481 
       
   482     "/ draw selection frames
       
   483     selY notNil ifTrue:[
       
   484         1 to:selY size do:[:i|
       
   485             self drawSelectionFrameAtX:x y:(selY at:i) width:w h:(selH at:i)
       
   486         ]
       
   487     ].
       
   488 
       
   489 
       
   490 
       
   491 !
       
   492 
       
   493 drawLabelAt:x y:y h:h index:anIndex
       
   494     "draw the label at position x/y without clearing the background
       
   495     "
       
   496     |label item
       
   497      w  "{ Class:SmallInteger }"
       
   498      x0 "{ Class:SmallInteger }"
       
   499     |
       
   500     item := list at:anIndex ifAbsent:[^ self].
       
   501 
       
   502     (self isInSelection:anIndex) ifTrue:[
       
   503         highlightMode == #label ifTrue:[
       
   504             w  := (item widthOn:self) + textStartLeft.
       
   505             x0 := x - (textStartLeft // 2).
       
   506             self paint:hilightBgColor.
       
   507             self fillRectangleX:x0 y:y width:w height:h.
       
   508             self drawSelectionFrameAtX:x0 y:y width:w h:h.
       
   509         ].
       
   510         self paint:hilightFgColor on:hilightBgColor
       
   511     ] ifFalse:[
       
   512         self paint:fgColor on:bgColor.
       
   513     ].
       
   514     self displayElement:item atX:x y:y h:h
       
   515 
       
   516 
       
   517 !
       
   518 
       
   519 drawSelectionFrameAtX:x0 y:y0 width:w h:h
       
   520     "redraw selection frame for a line
       
   521     "
       
   522     |
       
   523      x1 "{ Class: SmallInteger }"
       
   524      x  "{ Class: SmallInteger }" 
       
   525      y  "{ Class: SmallInteger }" 
       
   526     |
       
   527     x1 := x0 + w.
       
   528 
       
   529     hilightFrameColor notNil ifTrue:[
       
   530         hilightLevel == 0 ifTrue:[
       
   531             self paint:hilightFrameColor.
       
   532 
       
   533             highlightMode == #line ifTrue:[
       
   534                 self displayLineFromX:x0 y:y0 toX:x1 y:y0.
       
   535                 y := y0 + h - 1.
       
   536                 self displayLineFromX:x0 y:y toX:x1 y:y.
       
   537             ] ifFalse:[
       
   538                 self displayRectangleX:x0 y:y0 width:w height:h
       
   539             ].
       
   540             ^ self.
       
   541         ]
       
   542     ] ifFalse:[
       
   543         hilightStyle == #motif ifTrue:[
       
   544             self paint:bgColor.
       
   545             y := y0 + 1.
       
   546             highlightMode == #line ifTrue:[
       
   547                 self displayLineFromX:x0 y:y toX:x1 y:y.
       
   548                 y := y0 + h - 2.
       
   549                 self displayLineFromX:x0 y:y toX:x1 y:y.
       
   550             ] ifFalse:[
       
   551                 self displayRectangleX:x0 + 1 y:y width:w - 2 height:h - 2
       
   552             ]
       
   553         ]
       
   554     ].
       
   555 
       
   556     hilightLevel ~~ 0 ifTrue:[
       
   557         "/ draw edge
       
   558         highlightMode == #line ifTrue:[
       
   559             x  := margin.
       
   560             x1 := width - x - x.
       
   561         ] ifFalse:[
       
   562             x  := x0.
       
   563             x1 := w.
       
   564         ].
       
   565         self drawEdgesForX:x y:y0 width:x1 height:h level:hilightLevel.
       
   566     ]
       
   567 
       
   568 !
       
   569 
       
   570 redrawSelectionAt:anIndex
       
   571     "called to redraw a line caused by a change of the selection
       
   572     "
       
   573     |item
       
   574      h  "{ Class:SmallInteger }"
       
   575      y0 "{ Class:SmallInteger }"
       
   576      y1 "{ Class:SmallInteger }"
       
   577     |
       
   578     shown ifFalse:[^ self].
       
   579 
       
   580     y0 := (self yVisibleOfLine:anIndex)       max:margin.
       
   581     y1 := (self yVisibleOfLine:(anIndex + 1)) min:(height - margin).
       
   582 
       
   583     (h := y1 - y0) > 0 ifTrue:[
       
   584         (     highlightMode == #label
       
   585          and:[(item := list at:anIndex ifAbsent:nil) notNil]
       
   586         ) ifTrue:[
       
   587             self redrawLabelFromItem:item atY:y0 h:h
       
   588         ] ifFalse:[
       
   589             self redrawX:margin y:y0 width:(self innerWidth) height:h
       
   590         ]
       
   591     ]
       
   592 ! !
       
   593 
       
   594 !SelectionInListModelView methodsFor:'event handling'!
       
   595 
       
   596 buttonMotion:buttonMask x:x y:y
       
   597     "mouse-move while button was pressed - handle selection changes
       
   598     "
       
   599     |sensor idx  p cY oY lnNr h|
       
   600 
       
   601     (enabled and:[selection notNil]) ifFalse:[^ self].
       
   602 
       
   603     dragAccessPoint notNil ifTrue:[
       
   604         p := x @ y.
       
   605 
       
   606         (dragAccessPoint dist:p) > 5.0 ifTrue:[
       
   607             dragAccessPoint := nil.
       
   608             self startDragAt:p
       
   609         ].
       
   610         ^ self
       
   611     ].
       
   612 
       
   613     (multipleSelectOk and:[self sensor leftButtonPressed]) ifFalse:[
       
   614         ^ self
       
   615     ].
       
   616 
       
   617     clickLine isNil ifTrue:[
       
   618         ^ self
       
   619     ].
       
   620     cY := self yVisibleOfLine:clickLine.
       
   621     oY := cY.
       
   622 
       
   623     y < cY ifTrue:[
       
   624         (lnNr := clickLine - 1) == 0 ifTrue:[^ self].
       
   625         cY := self yVisibleOfLine:lnNr.
       
   626         h  := oY - cY.
       
   627     ] ifFalse:[
       
   628         (    (lnNr := clickLine + 1) > list size
       
   629          or:[(cY   := self yVisibleOfLine:lnNr) > y]
       
   630         ) ifTrue:[
       
   631             ^ self
       
   632         ].
       
   633         h  := cY - oY.
       
   634     ].
       
   635     selection := selection asOrderedCollection.
       
   636 
       
   637     (selection removeIdentical:lnNr ifAbsent:nil) isNil ifTrue:[
       
   638         selection add:lnNr
       
   639     ].
       
   640     clickLine := lnNr.
       
   641 
       
   642     (cY between:margin and:(height - h)) ifTrue:[
       
   643         self redrawSelectionAt:lnNr
       
   644     ] ifFalse:[
       
   645         self scrollToLine:lnNr.
       
   646     ].
       
   647     self selectionChanged
       
   648 
       
   649 !
       
   650 
       
   651 buttonMultiPress:button x:x y:y
       
   652     "button was pressed multiple - handle a doubleClick action
       
   653     "
       
   654     clickLine := nil.
       
   655     dragAccessPoint := nil.
       
   656 
       
   657     enabled ifFalse:[^ self].
       
   658 
       
   659     ((button == 1) or:[button == #select]) ifFalse:[
       
   660         ^ super buttonMultiPress:button x:x y:y
       
   661     ].
       
   662     self doubleClicked
       
   663 !
       
   664 
       
   665 buttonPress:button x:x y:y
       
   666     "a button was pressed - handle selection here
       
   667     "
       
   668     |lnNr sensor start step list changed|
       
   669 
       
   670     clickLine       := nil.
       
   671     dragAccessPoint := nil.
       
   672 
       
   673     enabled ifFalse:[^ self].
       
   674 
       
   675     (button == 1 or:[button == #select]) ifFalse:[
       
   676         ^ super buttonPress:button x:x y:y
       
   677     ].
       
   678 
       
   679     (lnNr := self yVisibleToLineNr:y) isNil ifTrue:[
       
   680         ^ self
       
   681     ].
       
   682     clickLine := lnNr.
       
   683 
       
   684     (multipleSelectOk and:[(sensor := self sensor) notNil]) ifTrue:[
       
   685         sensor ctrlDown ifTrue:[
       
   686             (self isInSelection:lnNr) ifTrue:[self removeFromSelection:lnNr]
       
   687                                      ifFalse:[self addToSelection:lnNr].
       
   688           ^ self selectionChanged
       
   689 
       
   690         ].
       
   691         (selection notNil and:[sensor shiftDown]) ifTrue:[
       
   692             start     := selection at:1.
       
   693             step      := lnNr < start ifTrue:[-1] ifFalse:[1].
       
   694             list      := selection.
       
   695             selection := OrderedCollection new.
       
   696             changed   := false.
       
   697 
       
   698             start to:lnNr by:step do:[:i|
       
   699                 selection add:i.
       
   700                 (list identityIndexOf:i) == 0 ifTrue:[
       
   701                     changed := true.
       
   702                     self redrawSelectionAt:i    "/ redraw selected
       
   703                 ]
       
   704             ].
       
   705             list do:[:i|
       
   706                 (selection identityIndexOf:i) == 0 ifTrue:[
       
   707                     changed := true.
       
   708                     self redrawSelectionAt:i    "/ redraw unselected
       
   709                 ].
       
   710             ].
       
   711             changed ifTrue:[
       
   712                 self selectionChanged
       
   713             ].
       
   714             ^ self
       
   715         ]
       
   716     ].
       
   717 
       
   718     (self canDrag and:[self isInSelection:lnNr]) ifTrue:[
       
   719         dragAccessPoint := x @ y
       
   720     ] ifFalse:[
       
   721         self selectedIndex ~~ lnNr ifTrue:[
       
   722             self selectWithoutScroll:lnNr.
       
   723             self selectionChanged
       
   724         ]
       
   725     ]
       
   726 !
       
   727 
       
   728 buttonRelease:button x:x y:y
       
   729     "a button was released
       
   730     "
       
   731     enabled ifTrue:[ 
       
   732         (dragAccessPoint notNil and:[clickLine notNil]) ifTrue:[
       
   733             self selectedIndex ~~ clickLine ifTrue:[
       
   734                 self selectWithoutScroll:clickLine.
       
   735                 self selectionChanged
       
   736             ]
       
   737         ]
       
   738     ].
       
   739     clickLine       := nil.
       
   740     dragAccessPoint := nil.
       
   741 
       
   742 
       
   743 !
       
   744 
       
   745 characterPress:aKey x:x y:y
       
   746     " a character is pressed - lookup and change selection
       
   747     "
       
   748     |lnNr size idx sensor stp to1 fr2|
       
   749 
       
   750     (enabled and:[(size := self size) > 1]) ifFalse:[
       
   751         ^ self
       
   752     ].
       
   753     lnNr := self firstInSelection ? 0.
       
   754 
       
   755     ((sensor := self sensor) notNil and:[sensor shiftDown]) ifTrue:[
       
   756         stp := -1.              "/ search backward
       
   757         to1 :=  1.
       
   758         fr2 := size.
       
   759     ] ifFalse:[
       
   760         stp := 1.               "/ search forward
       
   761         to1 := size.
       
   762         fr2 := 1.
       
   763     ].
       
   764 
       
   765     idx := self findLineFrom:lnNr+stp to:to1 by:stp startingWithCharacter:aKey.
       
   766 
       
   767     idx == 0 ifTrue:[
       
   768         idx := self findLineFrom:fr2 to:lnNr-stp by:stp startingWithCharacter:aKey
       
   769     ].
       
   770     idx ~~ 0 ifTrue:[^ self selection:idx]
       
   771 !
       
   772 
       
   773 doubleClicked
       
   774     "handle a double click
       
   775     "
       
   776     (doubleClickActionBlock notNil and:[self numberOfSelections == 1]) ifTrue:[
       
   777         (doubleClickActionBlock numArgs == 1) ifTrue:[
       
   778             doubleClickActionBlock value:(self selectedIndex)
       
   779         ] ifFalse:[
       
   780             doubleClickActionBlock value
       
   781         ]
       
   782     ]
       
   783 
       
   784 !
       
   785 
       
   786 findLineFrom:aStart to:aStop by:aStep startingWithCharacter:aCharacter
       
   787     "find a line starting with a character
       
   788     "
       
   789     |item char lbl cmp
       
   790      size     "{ Class:SmallInteger }"
       
   791      start    "{ Class:SmallInteger }"
       
   792      stop     "{ Class:SmallInteger }"
       
   793     |
       
   794     (size := list size) ~~ 0 ifTrue:[
       
   795         aStep > 0 ifTrue:[
       
   796             aStart > aStop ifTrue:[^ 0].
       
   797         ] ifFalse:[
       
   798             (aStep == 0 or:[aStop > aStart]) ifTrue:[^ 0]
       
   799         ].
       
   800 
       
   801         start := aStart < 0 ifTrue:[1] ifFalse:[aStart min:size].
       
   802         stop  := aStop  < 0 ifTrue:[1] ifFalse:[aStop  min:size].
       
   803         char  := aCharacter asUppercase.
       
   804 
       
   805         start to:stop by:aStep do:[:anIndex|
       
   806             item := list at:anIndex ifAbsent:[^ 0]. "/ list changed
       
   807             lbl  := item perform:#string ifNotUnderstood:nil.
       
   808 
       
   809             lbl notNil ifTrue:[
       
   810                 cmp := lbl string at:1 ifAbsent:nil.
       
   811 
       
   812                 cmp notNil ifTrue:[
       
   813                     (char == cmp or:[char == cmp asUppercase]) ifTrue:[
       
   814                         ^ anIndex
       
   815                     ]
       
   816                 ]
       
   817             ]
       
   818         ]
       
   819     ].
       
   820     ^ 0
       
   821 
       
   822 
       
   823 !
       
   824 
       
   825 keyPress:aKey x:x y:y
       
   826     "a key was pressed - handle page-keys here
       
   827     "
       
   828     <resource: #keyboard( #Return #CursorUp #CursorDown )>
       
   829 
       
   830     |sensor n size lineNr|
       
   831 
       
   832     enabled ifFalse:[
       
   833         ^ super keyPress:aKey x:x y:y
       
   834     ].
       
   835     aKey == #Return ifTrue:[
       
   836         self numberOfSelections == 1 ifTrue:[self doubleClicked].
       
   837       ^ self
       
   838     ].
       
   839 
       
   840     aKey isCharacter ifTrue:[
       
   841         ^ self characterPress:aKey x:x y:y
       
   842     ].
       
   843 
       
   844     (aKey == #CursorUp or:[aKey == #CursorDown]) ifFalse:[
       
   845         ^ super keyPress:aKey x:x y:y
       
   846     ].
       
   847 
       
   848     (size := self size) == 0 ifTrue:[
       
   849         ^ self
       
   850     ].
       
   851 
       
   852     lineNr := self selectedIndex.
       
   853     sensor := self sensor.
       
   854 
       
   855     sensor notNil ifTrue:[
       
   856         n := (1 + (sensor compressKeyPressEventsWithKey:aKey)) \\ size.
       
   857         n == 0 ifTrue:[^ self].
       
   858     ] ifFalse:[
       
   859         n := 1
       
   860     ].
       
   861 
       
   862     aKey == #CursorUp ifTrue:[
       
   863         lineNr == 0 ifTrue:[lineNr := size + 1].
       
   864         (n := lineNr - n) <= 0 ifTrue:[n := size + n]
       
   865     ] ifFalse:[
       
   866         (n := lineNr + n) > size ifTrue:[n := n - size]
       
   867     ].
       
   868     self selection:n
       
   869 ! !
       
   870 
       
   871 !SelectionInListModelView methodsFor:'initialize / release'!
       
   872 
       
   873 fetchResources
       
   874     "fetch device colors and ..., to avoid reallocation at redraw time;
       
   875      *** called after a create or snapin to fetch all device resources
       
   876     "
       
   877 
       
   878     super fetchResources.
       
   879 
       
   880     hilightFgColor    := self colorOnDevice:hilightFgColor.
       
   881     hilightBgColor    := self colorOnDevice:hilightBgColor.
       
   882     hilightFrameColor := self colorOnDevice:hilightFrameColor.
       
   883 !
       
   884 
       
   885 initStyle
       
   886     "setup viewStyle specifics
       
   887     "
       
   888     |h|
       
   889 
       
   890     super initStyle.
       
   891 
       
   892     hilightFrameColor := nil.
       
   893     hilightLevel      := 0.
       
   894     hilightStyle      := DefaultHilightStyle.
       
   895     highlightMode     := #line.
       
   896     textStartLeft     := 4.
       
   897 
       
   898     device hasGrayscales ifTrue:[
       
   899         "
       
   900          must get rid of these hard codings
       
   901         "
       
   902         (hilightStyle == #next) ifTrue:[
       
   903             hilightFgColor := fgColor.
       
   904             hilightBgColor := White.
       
   905             hilightFrameColor := fgColor
       
   906         ] ifFalse:[
       
   907             (hilightStyle == #motif) ifTrue:[
       
   908                 fgColor := White.
       
   909                 bgColor := Grey.
       
   910                 viewBackground := bgColor.
       
   911                 hilightFgColor := bgColor.
       
   912                 hilightBgColor := fgColor.
       
   913             ] ifFalse:[
       
   914                 (hilightStyle == #openwin) ifTrue:[
       
   915                     hilightFgColor := fgColor.
       
   916                     hilightBgColor := Color grey.
       
   917                 ]
       
   918             ]
       
   919         ]
       
   920     ].
       
   921 
       
   922     hilightFgColor isNil ifTrue:[
       
   923         hilightFgColor := bgColor.
       
   924     ].
       
   925     hilightBgColor isNil ifTrue:[
       
   926         hilightBgColor := fgColor.
       
   927     ].
       
   928     DefaultForegroundColor notNil ifTrue:[
       
   929         fgColor := DefaultForegroundColor
       
   930     ].
       
   931     DefaultBackgroundColor notNil ifTrue:[
       
   932         bgColor := viewBackground := DefaultBackgroundColor
       
   933     ].
       
   934 
       
   935     DefaultHilightForegroundColor notNil ifTrue:[
       
   936         hilightFgColor := DefaultHilightForegroundColor
       
   937     ].
       
   938     DefaultHilightBackgroundColor notNil ifTrue:[
       
   939         hilightBgColor := DefaultHilightBackgroundColor
       
   940     ].
       
   941     DefaultHilightFrameColor notNil ifTrue:[
       
   942         hilightFrameColor := DefaultHilightFrameColor
       
   943     ].
       
   944     DefaultHilightLevel notNil ifTrue:[
       
   945         hilightLevel := DefaultHilightLevel
       
   946     ].
       
   947     lineSpacing := 2 * (hilightLevel abs).
       
   948 
       
   949     (hilightStyle == #motif) ifTrue:[
       
   950         lineSpacing := lineSpacing max:6.
       
   951     ] ifFalse:[
       
   952         lineSpacing := lineSpacing max:4.
       
   953     ].
       
   954     hilightFgColor isNil ifTrue:[
       
   955         hilightFgColor := bgColor.
       
   956         hilightBgColor := fgColor
       
   957     ].
       
   958 !
       
   959 
       
   960 initialize
       
   961     "setup default attributes/behavior
       
   962     "
       
   963     super initialize.
       
   964 
       
   965     multipleSelectOk := false.
       
   966     useIndex         := true.
       
   967 
       
   968 !
       
   969 
       
   970 realize
       
   971     "get selection from model; scroll to selection
       
   972     "
       
   973     selection := self getSelectionFromModel.
       
   974 
       
   975     super realize.
       
   976 
       
   977     selection notNil ifTrue:[
       
   978         useIndex ifTrue:[selection := selection copy].
       
   979         self makeSelectionVisible.
       
   980     ]
       
   981 ! !
       
   982 
       
   983 !SelectionInListModelView methodsFor:'protocol'!
       
   984 
       
   985 drawElementsFrom:start to:stop x:x y:y width:width
       
   986     "draw the items between start to stop without clearing the background
       
   987     "
       
   988     |y0 "{ Class:SmallInteger }"
       
   989      y1 "{ Class:SmallInteger }"
       
   990      x0 "{ Class:SmallInteger }"
       
   991     |
       
   992     x0 := textStartLeft - viewOrigin x.
       
   993     y1 := y.
       
   994 
       
   995     start to:stop do:[:i|
       
   996         y0 := y1.
       
   997         y1 := self yVisibleOfLine:(i + 1).
       
   998         self drawLabelAt:x0 y:y0 h:(y1 - y0) index:i.
       
   999     ].
       
  1000 
       
  1001 
       
  1002 !
       
  1003 
       
  1004 redrawLabelFromItem:anItem atY:y h:h
       
  1005     "called to redraw a label caused by a selection changed
       
  1006     "
       
  1007     |
       
  1008      x0 "{ Class:SmallInteger }"
       
  1009      x1 "{ Class:SmallInteger }"
       
  1010     |
       
  1011     x0 := textStartLeft // 2 - viewOrigin x.
       
  1012     x1 := x0 + textStartLeft + (anItem widthOn:self).
       
  1013     x0 := x0 max:margin.
       
  1014     x1 := x1 min:(self innerWidth).
       
  1015 
       
  1016     x1 > x0 ifTrue:[
       
  1017         self redrawX:x0 y:y width:(x1 - x0) height:h.
       
  1018     ]
       
  1019 ! !
       
  1020 
       
  1021 !SelectionInListModelView methodsFor:'selection'!
       
  1022 
       
  1023 deselect
       
  1024     "clear selection
       
  1025     "
       
  1026     self selection:nil
       
  1027 
       
  1028 !
       
  1029 
       
  1030 firstInSelection
       
  1031     "returns line number of first element selected or nil
       
  1032     "
       
  1033     |lineNr|
       
  1034 
       
  1035     selection notNil ifTrue:[
       
  1036         ^ multipleSelectOk ifTrue:[selection at:1] ifFalse:[selection]
       
  1037     ].
       
  1038     ^ nil
       
  1039 
       
  1040 
       
  1041 !
       
  1042 
       
  1043 hasSelection
       
  1044     "returns true if a selection exists
       
  1045     "
       
  1046     ^ selection notNil
       
  1047 
       
  1048 !
       
  1049 
       
  1050 isInSelection:aNumber
       
  1051     "return true, if line, aNumber is in the selection
       
  1052     "
       
  1053     selection isNil ifTrue:[^ false].
       
  1054 
       
  1055     ^ multipleSelectOk ifFalse:[aNumber == selection]
       
  1056                         ifTrue:[selection includes:aNumber]
       
  1057 !
       
  1058 
       
  1059 lastInSelection
       
  1060     "returns line number of last element selected or nil
       
  1061     "
       
  1062     |lineNr|
       
  1063 
       
  1064     selection notNil ifTrue:[
       
  1065         ^ multipleSelectOk ifTrue:[selection last] ifFalse:[selection]
       
  1066     ].
       
  1067     ^ nil
       
  1068 
       
  1069 
       
  1070 !
       
  1071 
       
  1072 numberOfSelections
       
  1073     "return the number of selected items
       
  1074     "
       
  1075     selection isNil   ifTrue:[^ 0].
       
  1076   ^ multipleSelectOk ifFalse:[1] ifTrue:[selection size]
       
  1077 
       
  1078 
       
  1079 !
       
  1080 
       
  1081 selectElement:anElement
       
  1082     "select the element. Scroll to make the new selection visible.
       
  1083      Model and/or actionBlock notification IS done.
       
  1084     "
       
  1085     |index|
       
  1086 
       
  1087     (index := self identityIndexOf:anElement) ~~ 0 ifTrue:[
       
  1088         self selection:index
       
  1089     ]
       
  1090         
       
  1091 !
       
  1092 
       
  1093 selectedElement
       
  1094     "return the single selected item or nil
       
  1095     "
       
  1096     |index|
       
  1097 
       
  1098     index := self selectedIndex.
       
  1099   ^ index ~~ 0 ifTrue:[self at:index ifAbsent:nil] ifFalse:[nil]
       
  1100 
       
  1101 !
       
  1102 
       
  1103 selectedIndex
       
  1104     "returns the index of the selected line or 0. If more
       
  1105      lines are selected, 0 is returned
       
  1106     "
       
  1107     selection notNil ifTrue:[
       
  1108         multipleSelectOk    ifFalse:[^ selection].
       
  1109         selection size == 1 ifTrue:[^ selection at:1]
       
  1110     ].
       
  1111     ^ 0
       
  1112 !
       
  1113 
       
  1114 selection
       
  1115     "return the selection index or collection of indices 
       
  1116      in case of multiple selection enabled
       
  1117     "
       
  1118     ^ selection
       
  1119 
       
  1120 !
       
  1121 
       
  1122 selection:aNumberOrNil
       
  1123     "select line, aNumber or deselect if argument is nil;
       
  1124      scroll to make the selected line visible.
       
  1125      The model and/or actionBlock IS notified.
       
  1126     "
       
  1127     |oldSelection|
       
  1128 
       
  1129     oldSelection := selection.
       
  1130     self setSelection:aNumberOrNil.
       
  1131 
       
  1132     selection ~= oldSelection ifTrue:[
       
  1133         self selectionChanged
       
  1134     ]
       
  1135 
       
  1136 
       
  1137 !
       
  1138 
       
  1139 selectionDo:aBlock
       
  1140     "perform aBlock for each nr in the selection.
       
  1141      For single selection, it is called once for the items nr.
       
  1142      For multiple selections, it is called for each.
       
  1143     "
       
  1144     selection notNil ifTrue:[
       
  1145         multipleSelectOk ifTrue:[
       
  1146             selection do:aBlock
       
  1147         ] ifFalse:[
       
  1148             aBlock value:selection
       
  1149         ].
       
  1150     ].
       
  1151 
       
  1152 
       
  1153 !
       
  1154 
       
  1155 selectionValue
       
  1156     "return the selection value. For multiple selections a collection
       
  1157      containing the elements is returned. Otherwise the selected element
       
  1158     "
       
  1159     selection isNil ifTrue:[
       
  1160         ^ multipleSelectOk ifTrue:[#()] ifFalse:[nil]
       
  1161     ].
       
  1162     multipleSelectOk ifTrue:[
       
  1163          ^ selection collect:[:nr | list at:nr ifAbsent:nil ]
       
  1164     ].
       
  1165     ^ list at:selection ifAbsent:nil
       
  1166 !
       
  1167 
       
  1168 setSelection:aNumberOrNilOrCollection
       
  1169     "select line, aNumber or deselect if argument is nil;
       
  1170      scroll to make the selected line visible.
       
  1171      *** No model and/or actionBlock notification is done here.
       
  1172     "
       
  1173     self selectWithoutScroll:aNumberOrNilOrCollection.
       
  1174 
       
  1175     selection notNil ifTrue:[
       
  1176         self makeSelectionVisible
       
  1177     ]
       
  1178 
       
  1179 !
       
  1180 
       
  1181 toggleSelection:aNumber
       
  1182     "toggle selection-state of entry, aNumber.
       
  1183      *** No model and/or actionBlock notification is done here.
       
  1184     "
       
  1185     aNumber notNil ifTrue:[
       
  1186         (self isInSelection:aNumber) ifTrue:[
       
  1187             self removeFromSelection:aNumber
       
  1188         ] ifFalse:[
       
  1189             self addToSelection:aNumber
       
  1190         ]
       
  1191     ]
       
  1192 ! !
       
  1193 
       
  1194 !SelectionInListModelView methodsFor:'selection private'!
       
  1195 
       
  1196 addToSelection:aNumber
       
  1197     "add a number to the selection. No scrolling is done.
       
  1198      *** No model and/or actionBlock notification is done here.
       
  1199     "
       
  1200     |newSelect oldSelect|
       
  1201 
       
  1202     (aNumber notNil and:[aNumber between:1 and:(self size)]) ifFalse:[
       
  1203         ^ self
       
  1204     ].
       
  1205     multipleSelectOk ifFalse:[
       
  1206         oldSelect == selection ifTrue:[^ self].
       
  1207         oldSelect := selection.
       
  1208         selection := aNumber.
       
  1209         oldSelect notNil ifTrue:[self redrawSelectionAt:oldSelect].
       
  1210     ] ifTrue:[
       
  1211         selection isNil ifTrue:[
       
  1212             selection := Array with:aNumber.
       
  1213         ] ifFalse:[
       
  1214             (selection includes:aNumber) ifTrue:[^ self].
       
  1215             selection := selection copyWith:aNumber.
       
  1216         ].
       
  1217     ].
       
  1218     self redrawSelectionAt:aNumber.
       
  1219 !
       
  1220 
       
  1221 deselectWithoutRedraw
       
  1222     "set selection without redraw, scrolling.
       
  1223      The model and/or actionBlock IS notified.
       
  1224     "
       
  1225     selection notNil ifTrue:[
       
  1226         selection := nil.
       
  1227         self selectionChanged
       
  1228     ]
       
  1229 !
       
  1230 
       
  1231 makeSelectionVisible
       
  1232     "scroll to make the selection line visible
       
  1233     "
       
  1234     |lineNr|
       
  1235 
       
  1236     (lineNr := self firstInSelection) notNil ifTrue:[
       
  1237         self scrollToLine:lineNr
       
  1238     ]
       
  1239 
       
  1240 
       
  1241 !
       
  1242 
       
  1243 removeFromSelection:aNumber
       
  1244     "remove aNumber from the selection and redraw line;
       
  1245      *** No model and/or actionBlock notification is done here.
       
  1246     "
       
  1247     selection notNil ifTrue:[
       
  1248         multipleSelectOk ifTrue:[
       
  1249             (selection includes:aNumber) ifTrue:[
       
  1250                 selection size == 1 ifTrue:[
       
  1251                     selection := nil
       
  1252                 ] ifFalse:[
       
  1253                     selection := selection copyWithout:aNumber
       
  1254                 ].
       
  1255                 self redrawSelectionAt:aNumber
       
  1256             ]
       
  1257         ] ifFalse:[
       
  1258             aNumber == selection ifFalse:[
       
  1259                 selection := nil.
       
  1260                 self redrawSelectionAt:aNumber
       
  1261             ]
       
  1262         ]
       
  1263     ]
       
  1264 
       
  1265 !
       
  1266 
       
  1267 selectWithoutScroll:aNumberOrNilOrCollection
       
  1268     "select line, aNumber or deselect if argument is nil;
       
  1269      scroll to make the selected line visible.
       
  1270      *** No model and/or actionBlock notification is done here.
       
  1271     "
       
  1272     |oldSelect|
       
  1273 
       
  1274     oldSelect := selection.
       
  1275     selection := self validateSelection:aNumberOrNilOrCollection.
       
  1276 
       
  1277     (shown and:[selection ~= oldSelect]) ifFalse:[
       
  1278         ^ self
       
  1279     ].
       
  1280 
       
  1281     multipleSelectOk ifFalse:[
       
  1282         oldSelect notNil ifTrue:[self redrawSelectionAt:oldSelect].
       
  1283         selection notNil ifTrue:[self redrawSelectionAt:selection].
       
  1284     ] ifTrue:[
       
  1285         selection isNil ifTrue:[
       
  1286             oldSelect do:[:i|self redrawSelectionAt:i].
       
  1287         ] ifFalse:[
       
  1288             oldSelect isNil ifTrue:[
       
  1289                 selection do:[:i|self redrawSelectionAt:i].
       
  1290             ] ifFalse:[
       
  1291                 selection do:[:i|
       
  1292                     (oldSelect includes:i) ifFalse:[self redrawSelectionAt:i]
       
  1293                 ].
       
  1294                 oldSelect do:[:i|
       
  1295                     (selection includes:i) ifFalse:[self redrawSelectionAt:i]
       
  1296                 ].
       
  1297             ]
       
  1298         ]
       
  1299     ].
       
  1300 
       
  1301 
       
  1302 
       
  1303 !
       
  1304 
       
  1305 selectionWithoutRedraw:aSelection
       
  1306     "set selection without redraw, scrolling.
       
  1307      The model and/or actionBlock IS notified.
       
  1308     "
       
  1309     selection ~= aSelection ifTrue:[
       
  1310         selection := aSelection.
       
  1311         self selectionChanged
       
  1312     ]
       
  1313 !
       
  1314 
       
  1315 validateSelection:aNumberOrCollection
       
  1316     "validate the selection; returns a valid selection or nil
       
  1317     "
       
  1318     |sz newSelection|
       
  1319 
       
  1320     (aNumberOrCollection notNil and:[aNumberOrCollection ~~ 0]) ifTrue:[
       
  1321         sz := self size.
       
  1322 
       
  1323         aNumberOrCollection isCollection ifFalse:[
       
  1324             (aNumberOrCollection between:1 and:sz) ifTrue:[
       
  1325                 ^ multipleSelectOk ifFalse:[aNumberOrCollection ]
       
  1326                                     ifTrue:[Array with:aNumberOrCollection]
       
  1327             ]
       
  1328         ] ifTrue:[
       
  1329             (aNumberOrCollection notNil and:[multipleSelectOk]) ifTrue:[
       
  1330                 newSelection := OrderedCollection new.
       
  1331 
       
  1332                 aNumberOrCollection do:[:anIndex|
       
  1333                     (anIndex between:1 and:sz) ifFalse:[^ nil].
       
  1334                     newSelection add:anIndex.
       
  1335                 ].
       
  1336                 ^ newSelection
       
  1337             ]
       
  1338         ]
       
  1339     ].
       
  1340     ^ nil
       
  1341 
       
  1342 
       
  1343 ! !
       
  1344 
       
  1345 !SelectionInListModelView class methodsFor:'documentation'!
       
  1346 
       
  1347 version
       
  1348     ^ '$Header: /cvs/stx/stx/libwidg2/SelectionInListModelView.st,v 1.1 1999-05-23 12:56:29 cg Exp $'
       
  1349 ! !