|
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 ! ! |