1 " |
|
2 COPYRIGHT (c) 1989 by Claus Gittinger |
|
3 All Rights Reserved |
|
4 |
|
5 This software is furnished under a license and may be used |
|
6 only in accordance with the terms of that license and with the |
|
7 inclusion of the above copyright notice. This software may not |
|
8 be provided or otherwise made available to, or used by, any |
|
9 other person. No title to or ownership of the software is |
|
10 hereby transferred. |
|
11 " |
|
12 |
|
13 ListView subclass:#SelectionInListView |
|
14 instanceVariableNames:'selection actionBlock enabled hilightFgColor hilightBgColor |
|
15 halfIntensityFgColor doubleClickActionBlock selectConditionBlock |
|
16 listAttributes multipleSelectOk clickLine initialSelectionMsg |
|
17 printItems oneItem useIndex hilightLevel hilightFrameColor |
|
18 ignoreReselect arrowLevel smallArrow keyActionStyle |
|
19 returnKeyActionStyle toggleSelect strikeOut iSearchString items |
|
20 doubleClickMsg hilightStyle clickPosition allowDrag |
|
21 dragObjectConverter dragIsActive endDragAction dropTarget |
|
22 dropSource visualBlock selectedVisualBlock' |
|
23 classVariableNames:'RightArrowShadowForm RightArrowLightForm RightArrowForm |
|
24 SmallRightArrowShadowForm SmallRightArrowLightForm |
|
25 DefaultForegroundColor DefaultBackgroundColor |
|
26 DefaultHilightForegroundColor DefaultHilightBackgroundColor |
|
27 DefaultHilightFrameColor DefaultHilightLevel |
|
28 DefaultRightArrowStyle DefaultRightArrowLevel |
|
29 DefaultDisabledForegroundColor DefaultShadowColor |
|
30 DefaultLightColor DefaultHilightStyle' |
|
31 poolDictionaries:'' |
|
32 category:'Views-Lists' |
|
33 ! |
|
34 |
|
35 !SelectionInListView class methodsFor:'documentation'! |
|
36 |
|
37 copyright |
|
38 " |
|
39 COPYRIGHT (c) 1989 by Claus Gittinger |
|
40 All Rights Reserved |
|
41 |
|
42 This software is furnished under a license and may be used |
|
43 only in accordance with the terms of that license and with the |
|
44 inclusion of the above copyright notice. This software may not |
|
45 be provided or otherwise made available to, or used by, any |
|
46 other person. No title to or ownership of the software is |
|
47 hereby transferred. |
|
48 " |
|
49 ! |
|
50 |
|
51 documentation |
|
52 " |
|
53 this one is a ListView with a selected line (which is shown highlighted) |
|
54 If multipleSelectionsOk is true, it is also allowed to shift-click multiple |
|
55 entries. |
|
56 If toggleSelect is true, clicking toggles (i.e. click on a seleted item |
|
57 will deselect). |
|
58 |
|
59 Whenever the selection changes, an action-block is evaluated, passing the |
|
60 current selection as argument. |
|
61 Currently, the selection can be nil, aNumber or a collection of numbers; |
|
62 this will change to be either nil or a collection, making selection handling |
|
63 easier in the future. (this stupid behavior is due to the multiple |
|
64 select feature being added later - the first implementation used to support |
|
65 only single selections). |
|
66 |
|
67 The actionBlock is called with the current selection (single number or |
|
68 collection of numbers) as argument. |
|
69 |
|
70 Also, to support ST-80 MVC-style use, the model (if nonNil) is notified |
|
71 by the change mechanism (performs changeMsg) and vice versa, the view |
|
72 updates if the model changes (with aspect of either #list or #selectionIndex). |
|
73 |
|
74 Before actually adding entries to the the selection, a checkBlock (if non-nil) is evaluated |
|
75 passing the number of the entry whch is about to be selected as argument. |
|
76 The select change operation is only done if this returns true. This allows |
|
77 interception of select, for example to query the user if he/she wants to save |
|
78 the old contents before (see uses in SystemBrowser and FileBrowser), or to |
|
79 disable individual entries. |
|
80 |
|
81 It is also possible to select entries with the keyboard; use the cursor up/ |
|
82 down keys to select prev/next, Home- and End-keys to select first/last. |
|
83 Use the return key to apply the double-click-action to the current selection. |
|
84 Also, alphabetic keys will select the next entry starting with that key. |
|
85 |
|
86 The keyboard behavior can be further controlled with the keyActionStyle |
|
87 instance variable (see SelectionInListView>>keyActionStyle:). |
|
88 |
|
89 Finally, ignoreReselect controls if pressing on an already selected item |
|
90 triggers the action or not. For some applications it is useful to allow |
|
91 reselects (for example, the SystemBrowsers method-list updates the |
|
92 source code in this case). |
|
93 |
|
94 Currently, some limited form of line attributes are supported. These |
|
95 are kept in the instance variable lineAttributes. |
|
96 This may change (using mechanisms similar to MultiColListEntry), so |
|
97 be prepared. (dont use the listAttributes instvar directly; if possible, |
|
98 use MultiColListEntry or subclasses of it. |
|
99 |
|
100 Although currently based on the listAttributes instVar, the implementation of |
|
101 text attributes will be changed in the near future (when Text/DisplayText are |
|
102 available). |
|
103 However, the protocol will probably be kept for backward compatibility |
|
104 (i.e. use #attributeAt: / #attributeAt:put etc. - at least, these are easy to find |
|
105 when migrating to the new attributed text handling). |
|
106 |
|
107 [Instance variables:] |
|
108 selection <misc> the current selection. nil, a number or collection of numbers |
|
109 |
|
110 actionBlock <Block> block to be evaluated on selection changes |
|
111 (1-arg blocks gets selectionIndex or selectionValue |
|
112 as arg - depending upon the useIndex setting) |
|
113 |
|
114 useIndex <Boolean> if true, the index of a selection is passed to |
|
115 the actionBlock or stuffed into the selection valueHolder; |
|
116 if false, the seelction-value is passed. |
|
117 |
|
118 enabled <Boolean> true: selection changes allowed; false: ignore clicks |
|
119 |
|
120 hilightFgColor |
|
121 hilightBgColor <Color> how highlighted items are drawn |
|
122 |
|
123 halfIntensityColor <Color> foreground for disabled items |
|
124 |
|
125 selectConditionBlock <Block> if non-nil, this nlock can decide if selection is ok |
|
126 |
|
127 doubleClickActionBlock <Block> action to perform on double-click |
|
128 (1-arg blocks gets selectionIndex or selectionValue |
|
129 as arg - depending upon the useIndex setting) |
|
130 |
|
131 listAttributes dont use - will vanish |
|
132 |
|
133 hilightLevel <Integer> level to draw selections (i.e. for 3D effect) |
|
134 hilightFrameColor <Color> rectangle around highlighted items |
|
135 |
|
136 multipleSelectOk <Boolean> if true, multiple selections (with shift) are ok. |
|
137 default: false |
|
138 |
|
139 ignoreReselect <Boolean> if true, selecting same again does not trigger action; |
|
140 if false, every select triggers it. |
|
141 default: true |
|
142 |
|
143 toggleSelect <Boolean> if true, click toggles; |
|
144 if false, click selects. |
|
145 default: false |
|
146 |
|
147 arrowLevel <Integer> level to draw right-arrows (for submenus etc.) |
|
148 smallArrow <Boolean> if true, uses a small arrow bitmap |
|
149 |
|
150 listMsg if non-nil, use ST-80 style (model-access) |
|
151 initialSelectionMsg |
|
152 printItems |
|
153 oneItem |
|
154 |
|
155 keyActionStyle <Symbol> controls how to respond to keyboard selects |
|
156 |
|
157 returnKeyActionStyle <Symbol> controls how to respond to return key |
|
158 |
|
159 written spring/summer 89 by claus |
|
160 3D Jan 90 by claus |
|
161 multiselect Jun 92 by claus |
|
162 keyboard-select jun 94 by claus |
|
163 |
|
164 [author:] |
|
165 Claus Gittinger |
|
166 " |
|
167 ! |
|
168 |
|
169 examples |
|
170 " |
|
171 SelectionInListView can be used both in the ST/X way, using action blocks |
|
172 or in the traditional mvc way. |
|
173 with actions: |
|
174 |
|
175 basic interface: |
|
176 [exBegin] |
|
177 |top slv| |
|
178 |
|
179 top := StandardSystemView new |
|
180 label:'select'; |
|
181 minExtent:100@100; |
|
182 maxExtent:300@400; |
|
183 extent:200@200. |
|
184 |
|
185 slv := SelectionInListView new. |
|
186 slv list:#('one' 'two' 'three'). |
|
187 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
188 |
|
189 top add:slv in:(0.0@0.0 corner:1.0@1.0). |
|
190 top open |
|
191 [exEnd] |
|
192 |
|
193 |
|
194 get element instead of index: |
|
195 [exBegin] |
|
196 |top slv| |
|
197 |
|
198 top := StandardSystemView new |
|
199 label:'select'; |
|
200 minExtent:100@100; |
|
201 maxExtent:300@400; |
|
202 extent:200@200. |
|
203 |
|
204 slv := SelectionInListView new. |
|
205 slv list:#('one' 'two' 'three'). |
|
206 slv action:[:element | Transcript showCR:'selected ' , element printString]. |
|
207 slv useIndex:false. |
|
208 |
|
209 top add:slv in:(0.0@0.0 corner:1.0@1.0). |
|
210 top open |
|
211 [exEnd] |
|
212 |
|
213 |
|
214 concrete example; show filenames: |
|
215 (notice: normally, you would use a FileSelectionList) |
|
216 [exBegin] |
|
217 |top slv| |
|
218 |
|
219 top := StandardSystemView new |
|
220 label:'select'; |
|
221 minExtent:100@100; |
|
222 maxExtent:300@400; |
|
223 extent:200@200. |
|
224 |
|
225 slv := SelectionInListView new. |
|
226 slv list:(Filename currentDirectory directoryContents). |
|
227 slv action:[:index | |
|
228 Transcript showCR:'selected ' , index printString. |
|
229 Transcript showCR:' the value is: ', slv selectionValue]. |
|
230 |
|
231 top add:slv in:(0.0@0.0 corner:1.0@1.0). |
|
232 top open |
|
233 [exEnd] |
|
234 |
|
235 |
|
236 add a scrollbar: |
|
237 [exBegin] |
|
238 |top slv| |
|
239 |
|
240 top := StandardSystemView new |
|
241 label:'select'; |
|
242 minExtent:100@100; |
|
243 maxExtent:300@400; |
|
244 extent:200@200. |
|
245 |
|
246 slv := SelectionInListView new. |
|
247 slv list:(Filename currentDirectory directoryContents). |
|
248 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
249 |
|
250 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
251 top open |
|
252 [exEnd] |
|
253 |
|
254 |
|
255 allow reselect |
|
256 (clicking on already selected entry |
|
257 triggers action/changeNotification again): |
|
258 [exBegin] |
|
259 |top slv| |
|
260 |
|
261 top := StandardSystemView new |
|
262 label:'select'; |
|
263 minExtent:100@100; |
|
264 maxExtent:300@400; |
|
265 extent:200@200. |
|
266 |
|
267 slv := SelectionInListView new. |
|
268 slv list:(Filename currentDirectory directoryContents). |
|
269 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
270 slv ignoreReselect:false. |
|
271 |
|
272 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
273 top open |
|
274 [exEnd] |
|
275 |
|
276 |
|
277 allow multiple selections (shift-select): |
|
278 [exBegin] |
|
279 |top slv| |
|
280 |
|
281 top := StandardSystemView new |
|
282 label:'select'; |
|
283 minExtent:100@100; |
|
284 maxExtent:300@400; |
|
285 extent:200@200. |
|
286 |
|
287 slv := SelectionInListView new. |
|
288 slv list:(Filename currentDirectory directoryContents). |
|
289 slv action:[:indexList | Transcript showCR:'selected ' , indexList printString]. |
|
290 slv multipleSelectOk:true. |
|
291 |
|
292 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
293 top open |
|
294 [exEnd] |
|
295 |
|
296 same, not using index: |
|
297 [exBegin] |
|
298 |top slv| |
|
299 |
|
300 top := StandardSystemView new |
|
301 label:'select'; |
|
302 minExtent:100@100; |
|
303 maxExtent:300@400; |
|
304 extent:200@200. |
|
305 |
|
306 slv := SelectionInListView new. |
|
307 slv list:(Filename currentDirectory directoryContents). |
|
308 slv action:[:indexList | Transcript showCR:'selected ' , indexList printString]. |
|
309 slv multipleSelectOk:true; useIndex:false. |
|
310 |
|
311 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
312 top open |
|
313 [exEnd] |
|
314 |
|
315 |
|
316 strikeout mode (single): |
|
317 [exBegin] |
|
318 |top slv| |
|
319 |
|
320 top := StandardSystemView new |
|
321 label:'select'; |
|
322 minExtent:100@100; |
|
323 maxExtent:300@400; |
|
324 extent:200@200. |
|
325 |
|
326 slv := SelectionInListView new. |
|
327 slv list:(Filename currentDirectory directoryContents). |
|
328 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
329 slv strikeOut:true. |
|
330 |
|
331 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
332 top open |
|
333 [exEnd] |
|
334 |
|
335 |
|
336 strikeout mode (multiple): |
|
337 [exBegin] |
|
338 |top slv| |
|
339 |
|
340 top := StandardSystemView new |
|
341 label:'select'; |
|
342 minExtent:100@100; |
|
343 maxExtent:300@400; |
|
344 extent:200@200. |
|
345 |
|
346 slv := SelectionInListView new. |
|
347 slv list:(Filename currentDirectory directoryContents). |
|
348 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
349 slv strikeOut:true; multipleSelectOk:true. |
|
350 |
|
351 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
352 top open |
|
353 [exEnd] |
|
354 |
|
355 toggleSelect mode (clicking on selected entry deselects it): |
|
356 [exBegin] |
|
357 |top slv| |
|
358 |
|
359 top := StandardSystemView new |
|
360 label:'select'; |
|
361 minExtent:100@100; |
|
362 maxExtent:300@400; |
|
363 extent:200@200. |
|
364 |
|
365 slv := SelectionInListView new. |
|
366 slv list:(Filename currentDirectory directoryContents). |
|
367 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
368 slv toggleSelect:true. |
|
369 |
|
370 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
371 top open |
|
372 [exEnd] |
|
373 |
|
374 define what to do on double-click: |
|
375 [exBegin] |
|
376 |top slv| |
|
377 |
|
378 top := StandardSystemView new |
|
379 label:'select'; |
|
380 minExtent:100@100; |
|
381 maxExtent:300@400; |
|
382 extent:200@200. |
|
383 |
|
384 slv := SelectionInListView new. |
|
385 slv list:(Filename currentDirectory directoryContents). |
|
386 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
387 slv doubleClickAction:[:index | Transcript showCR:'doubleclick on ' , index printString]. |
|
388 |
|
389 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
390 top open |
|
391 [exEnd] |
|
392 |
|
393 enable / disable: |
|
394 [exBegin] |
|
395 |top slv| |
|
396 |
|
397 top := StandardSystemView new |
|
398 label:'select'; |
|
399 minExtent:100@100; |
|
400 maxExtent:300@400; |
|
401 extent:200@200. |
|
402 |
|
403 slv := SelectionInListView new. |
|
404 slv list:(Filename currentDirectory directoryContents). |
|
405 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
406 slv disable. |
|
407 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
408 top open. |
|
409 Delay waitForSeconds:5. |
|
410 slv enable. |
|
411 [exEnd] |
|
412 |
|
413 enable / disable via a channel: |
|
414 [exBegin] |
|
415 |top slv enableChannel t| |
|
416 |
|
417 enableChannel := true asValue. |
|
418 t := Toggle label:'enable'. |
|
419 t model:enableChannel. |
|
420 t open. |
|
421 |
|
422 top := StandardSystemView new |
|
423 label:'select'; |
|
424 minExtent:100@100; |
|
425 maxExtent:300@400; |
|
426 extent:200@200. |
|
427 |
|
428 slv := SelectionInListView new. |
|
429 slv list:(Filename currentDirectory directoryContents). |
|
430 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
431 slv enableChannel:enableChannel. |
|
432 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
433 top open. |
|
434 [exEnd] |
|
435 |
|
436 using a Model: |
|
437 [exBegin] |
|
438 |top slv model| |
|
439 |
|
440 model := Plug new. |
|
441 model respondTo:#getList with:[#('foo' 'bar' 'baz' 'hello')]. |
|
442 model respondTo:#initial with:[1]. |
|
443 model respondTo:#setSelection: with:[:arg | Transcript showCR:'model selected:', arg printString]. |
|
444 |
|
445 top := StandardSystemView new |
|
446 label:'select'; |
|
447 minExtent:100@100; |
|
448 maxExtent:300@400; |
|
449 extent:200@200. |
|
450 |
|
451 slv := SelectionInListView |
|
452 on:model |
|
453 aspect:#someAspect |
|
454 change:#setSelection: |
|
455 list:#getList |
|
456 initialSelection:#initial. |
|
457 |
|
458 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
459 top open |
|
460 [exEnd] |
|
461 |
|
462 notice, that the ST-80 behavaior on reselect is to send a selection change |
|
463 with an index of 0. |
|
464 |
|
465 same, with useIndex false: |
|
466 [exBegin] |
|
467 |top slv model| |
|
468 |
|
469 model := Plug new. |
|
470 model respondTo:#getList with:[#('foo' 'bar' 'baz' 'hello')]. |
|
471 model respondTo:#initial with:['bar']. |
|
472 model respondTo:#setSelection: with:[:arg | Transcript showCR:'model selected:', arg printString]. |
|
473 |
|
474 top := StandardSystemView new |
|
475 label:'select'; |
|
476 minExtent:100@100; |
|
477 maxExtent:300@400; |
|
478 extent:200@200. |
|
479 |
|
480 slv := SelectionInListView |
|
481 on:model |
|
482 aspect:#someAspect |
|
483 change:#setSelection: |
|
484 list:#getList |
|
485 initialSelection:#initial. |
|
486 slv useIndex:false. |
|
487 |
|
488 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
489 top open |
|
490 [exEnd] |
|
491 |
|
492 |
|
493 self changing list: |
|
494 (selectionInListView updates itself when button changes initial selection): |
|
495 [exBegin] |
|
496 |top slv model sel changeButton| |
|
497 |
|
498 sel := 'bar'. |
|
499 model := Plug new. |
|
500 model respondTo:#getList with:['getList' printNL. #('foo' 'bar' 'baz' 'hello')]. |
|
501 model respondTo:#initial with:['initial' printNL. sel]. |
|
502 model respondTo:#setSelection: with:[:arg | ('model selected:', arg) printNL. sel := arg]. |
|
503 |
|
504 changeButton := Button label:'change selection'. |
|
505 changeButton action:[sel := 'foo'. model changed:#initial]. |
|
506 changeButton open. |
|
507 |
|
508 top := StandardSystemView new |
|
509 label:'select'; |
|
510 minExtent:100@100; |
|
511 maxExtent:300@400; |
|
512 extent:200@200. |
|
513 |
|
514 slv := SelectionInListView |
|
515 on:model |
|
516 aspect:#someAspect |
|
517 change:#setSelection: |
|
518 list:#getList |
|
519 initialSelection:#initial. |
|
520 slv useIndex:false. |
|
521 |
|
522 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
523 top open |
|
524 [exEnd] |
|
525 |
|
526 |
|
527 using a SelectionInList-Model: |
|
528 (see how changes in the model (via list:...) are reflected in the view) |
|
529 [exBegin] |
|
530 |top slv model| |
|
531 |
|
532 model := SelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
|
533 model selection:'bar'. |
|
534 |
|
535 top := StandardSystemView new |
|
536 label:'select'; |
|
537 minExtent:100@100; |
|
538 maxExtent:300@400; |
|
539 extent:200@200. |
|
540 |
|
541 slv := SelectionInListView on:model. |
|
542 |
|
543 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
544 top open. |
|
545 |
|
546 InspectorView openOn:model monitor:'selectionIndexHolder' |
|
547 [exEnd] |
|
548 |
|
549 |
|
550 two selectionInListViews on the same selectionInList model: |
|
551 [exBegin] |
|
552 |top1 slv1 top2 slv2 model| |
|
553 |
|
554 model := SelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
|
555 |
|
556 top1 := StandardSystemView new |
|
557 label:'select'; |
|
558 minExtent:100@100; |
|
559 maxExtent:300@400; |
|
560 extent:200@200. |
|
561 |
|
562 slv1 := SelectionInListView on:model. |
|
563 |
|
564 top1 add:(ScrollableView forView:slv1) in:(0.0@0.0 corner:1.0@1.0). |
|
565 top1 open. |
|
566 |
|
567 top2 := StandardSystemView new |
|
568 label:'select'; |
|
569 minExtent:100@100; |
|
570 maxExtent:300@400; |
|
571 extent:200@200. |
|
572 |
|
573 slv2 := SelectionInListView on:model. |
|
574 |
|
575 top2 add:(ScrollableView forView:slv2) in:(0.0@0.0 corner:1.0@1.0). |
|
576 top2 open. |
|
577 [exEnd] |
|
578 |
|
579 |
|
580 a MultiSelectionInList model: |
|
581 [exBegin] |
|
582 |top slv model| |
|
583 |
|
584 model := MultiSelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
|
585 model selection:#('foo' 'bar'). |
|
586 |
|
587 top := StandardSystemView new |
|
588 label:'select'; |
|
589 minExtent:100@100; |
|
590 maxExtent:300@400; |
|
591 extent:200@200. |
|
592 |
|
593 slv := SelectionInListView on:model. |
|
594 slv multipleSelectOk:true. |
|
595 |
|
596 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
597 top open. |
|
598 |
|
599 InspectorView openOn:model monitor:'selectionIndexHolder' |
|
600 [exEnd] |
|
601 |
|
602 with strikeOut: |
|
603 [exBegin] |
|
604 |top slv model| |
|
605 |
|
606 model := MultiSelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
|
607 model selection:#('foo' 'bar'). |
|
608 |
|
609 top := StandardSystemView new |
|
610 label:'select'; |
|
611 minExtent:100@100; |
|
612 maxExtent:300@400; |
|
613 extent:200@200. |
|
614 |
|
615 slv := SelectionInListView on:model. |
|
616 slv multipleSelectOk:true; toggleSelect:true; strikeOut:true. |
|
617 |
|
618 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
619 top open. |
|
620 |
|
621 InspectorView openOn:model monitor:'selectionIndexHolder' |
|
622 [exEnd] |
|
623 |
|
624 |
|
625 two listViews on the same list, but separate selections |
|
626 [exBegin] |
|
627 |top top2 lv1 lv2 selInL1 selInL2 listHolder l1 l2| |
|
628 |
|
629 top := StandardSystemView new extent:300@300. |
|
630 |
|
631 lv1 := SelectionInListView origin:0.0@0.0 corner:1.0@0.5 in:top. |
|
632 lv1 level:-1. |
|
633 lv1 toggleSelect:true. |
|
634 |
|
635 lv2 := SelectionInListView origin:0.0@0.5 corner:1.0@1.0 in:top. |
|
636 lv2 level:-1. |
|
637 lv2 toggleSelect:true. |
|
638 |
|
639 selInL1 := SelectionInList new. |
|
640 selInL2 := SelectionInList new. |
|
641 |
|
642 listHolder := #('foo' 'bar' 'baz') asValue. |
|
643 |
|
644 selInL1 listHolder:listHolder. |
|
645 selInL2 listHolder:listHolder. |
|
646 |
|
647 lv1 model:selInL1. |
|
648 lv2 model:selInL2. |
|
649 |
|
650 top open. |
|
651 |
|
652 top2 := StandardSystemView new extent:100 @ 30. |
|
653 l1 := Label origin:0.0@0.0 corner:0.5@1.0 in:top2. |
|
654 l2 := Label origin:0.5@0.0 corner:1.0@1.0 in:top2. |
|
655 |
|
656 l1 model:(BlockValue with:[:arg | arg value printString] argument:selInL1 selectionIndexHolder). |
|
657 l2 model:(BlockValue with:[:arg | arg value printString] argument:selInL2 selectionIndexHolder). |
|
658 |
|
659 l1 labelMessage:#value. |
|
660 l2 labelMessage:#value. |
|
661 |
|
662 top2 open. |
|
663 |
|
664 Delay waitForSeconds:2. |
|
665 listHolder value:#('1' '2' '3' '4'). |
|
666 [exEnd] |
|
667 non-string entries (text) |
|
668 [exBegin] |
|
669 |top l slv| |
|
670 |
|
671 top := StandardSystemView new |
|
672 label:'select'; |
|
673 minExtent:100@100; |
|
674 maxExtent:300@400; |
|
675 extent:200@200. |
|
676 |
|
677 slv := SelectionInListView new. |
|
678 l := OrderedCollection new. |
|
679 l add:(Text string:'red' emphasis:(#color->Color red)). |
|
680 l add:(Text string:'green' emphasis:(#color->Color green)). |
|
681 l add:(Text string:'blue' emphasis:(#color->Color blue)). |
|
682 slv list:l. |
|
683 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
684 |
|
685 top add:slv in:(0.0@0.0 corner:1.0@1.0). |
|
686 top open |
|
687 [exEnd] |
|
688 |
|
689 non string entries |
|
690 [exBegin] |
|
691 |top slv wrapper l fileImage dirImage m| |
|
692 |
|
693 dirImage := Image fromFile:'DirObj.xbm'. |
|
694 fileImage := Image fromFile:'FileObj.xbm'. |
|
695 |
|
696 |
|
697 l := OrderedCollection new. |
|
698 Filename currentDirectory directoryContents do:[:s | |
|
699 s asFilename isDirectory ifTrue:[ |
|
700 l add:(LabelAndIcon icon:dirImage string:s) |
|
701 ] ifFalse:[ |
|
702 l add:(LabelAndIcon icon:fileImage string:s) |
|
703 ] |
|
704 ]. |
|
705 |
|
706 m := SelectionInList new. |
|
707 m list:l. |
|
708 |
|
709 slv := SelectionInListView new. |
|
710 slv model:m. |
|
711 wrapper := HVScrollableView forView:slv miniScrollerH:true. |
|
712 |
|
713 top := StandardSystemView extent:150@200. |
|
714 top add:wrapper in:(0.0@0.0 corner:1.0@1.0). |
|
715 top open. |
|
716 [exEnd] |
|
717 |
|
718 [exBegin] |
|
719 |top slv| |
|
720 |
|
721 top := StandardSystemView new |
|
722 label:'select'; |
|
723 minExtent:100@100; |
|
724 maxExtent:300@400; |
|
725 extent:200@200. |
|
726 |
|
727 slv := SelectionInListView new. |
|
728 slv list:#('one' 'two' 'three'). |
|
729 slv action:[:index | Transcript showCR:'selected ' , index printString]. |
|
730 slv multipleSelectOk:true. |
|
731 slv allowDrag:true. |
|
732 |
|
733 top add:slv in:(0.0@0.0 corner:1.0@1.0). |
|
734 top open |
|
735 [exEnd] |
|
736 " |
|
737 |
|
738 "Modified: 26.10.1995 / 16:42:02 / cg" |
|
739 ! ! |
|
740 |
|
741 !SelectionInListView class methodsFor:'instance creation'! |
|
742 |
|
743 on:aModel aspect:aspect change:change list:list initialSelection:initial |
|
744 ^ self on:aModel |
|
745 printItems:true |
|
746 oneItem:false |
|
747 aspect:aspect |
|
748 change:change |
|
749 list:list |
|
750 menu:nil |
|
751 initialSelection:initial |
|
752 useIndex:true |
|
753 ! |
|
754 |
|
755 on:aModel aspect:aspect change:change list:list menu:menu initialSelection:initial |
|
756 ^ self on:aModel |
|
757 printItems:true |
|
758 oneItem:false |
|
759 aspect:aspect |
|
760 change:change |
|
761 list:list |
|
762 menu:menu |
|
763 initialSelection:initial |
|
764 useIndex:true |
|
765 ! |
|
766 |
|
767 on:aModel printItems:print oneItem:one aspect:aspect |
|
768 change:change list:list menu:menu initialSelection:initial |
|
769 |
|
770 "for ST-80 compatibility" |
|
771 |
|
772 ^ self on:aModel |
|
773 printItems:print |
|
774 oneItem:one |
|
775 aspect:aspect |
|
776 change:change |
|
777 list:list |
|
778 menu:menu |
|
779 initialSelection:initial |
|
780 useIndex:false |
|
781 ! |
|
782 |
|
783 on:aModel printItems:print oneItem:one aspect:aspect change:change |
|
784 list:list menu:menu initialSelection:initial useIndex:useIndex |
|
785 |
|
786 "for ST-80 compatibility" |
|
787 |
|
788 ^ (self new) on:aModel |
|
789 printItems:print |
|
790 oneItem:one |
|
791 aspect:aspect |
|
792 change:change |
|
793 list:list |
|
794 menu:menu |
|
795 initialSelection:initial |
|
796 useIndex:useIndex |
|
797 ! ! |
|
798 |
|
799 !SelectionInListView class methodsFor:'defaults'! |
|
800 |
|
801 defaultAspectMessage |
|
802 ^ nil |
|
803 ! |
|
804 |
|
805 defaultChangeMessage |
|
806 ^ #selectionIndex: |
|
807 ! |
|
808 |
|
809 defaultListMessage |
|
810 ^ #list |
|
811 ! |
|
812 |
|
813 defaultSelectionMessage |
|
814 ^ #selectionIndex |
|
815 ! |
|
816 |
|
817 rightArrowFormOn:aDevice |
|
818 "return the form used for the right arrow (non 3D)" |
|
819 |
|
820 <resource: #style (#'selection.rightArrowForm' #'selection.rightArrowFormFile')> |
|
821 |
|
822 |f fn bits| |
|
823 |
|
824 ((aDevice == Display) and:[RightArrowForm notNil]) ifTrue:[ |
|
825 ^ RightArrowForm |
|
826 ]. |
|
827 |
|
828 f := StyleSheet at:#'selection.rightArrowForm'. |
|
829 f isNil ifTrue:[ |
|
830 fn := StyleSheet at:#'selection.rightArrowFormFile' default:'RightArrow.xbm'. |
|
831 f := Image fromFile:fn resolution:100 on:aDevice. |
|
832 f isNil ifTrue:[ |
|
833 DefaultRightArrowStyle == #solid ifTrue:[ |
|
834 bits := #[2r00000000 2r00000000 |
|
835 2r00000000 2r00000000 |
|
836 2r00000000 2r00000000 |
|
837 2r00000010 2r00000000 |
|
838 2r00000011 2r00000000 |
|
839 2r00000011 2r10000000 |
|
840 2r00000011 2r11000000 |
|
841 2r00000011 2r11100000 |
|
842 2r00000011 2r11110000 |
|
843 2r00000011 2r11100000 |
|
844 2r00000011 2r11000000 |
|
845 2r00000011 2r10000000 |
|
846 2r00000011 2r00000000 |
|
847 2r00000010 2r00000000 |
|
848 2r00000000 2r00000000 |
|
849 2r00000000 2r00000000] |
|
850 ] ifFalse:[ |
|
851 bits := #[2r00000000 2r00000000 |
|
852 2r00000000 2r00000000 |
|
853 2r00000000 2r00000000 |
|
854 2r00000110 2r00000000 |
|
855 2r00000101 2r00000000 |
|
856 2r00000100 2r10000000 |
|
857 2r00000100 2r01000000 |
|
858 2r00000100 2r00100000 |
|
859 2r00000100 2r00010000 |
|
860 2r00000100 2r00100000 |
|
861 2r00000100 2r01000000 |
|
862 2r00000100 2r10000000 |
|
863 2r00000101 2r00000000 |
|
864 2r00000110 2r00000000 |
|
865 2r00000000 2r00000000 |
|
866 2r00000000 2r00000000] |
|
867 ]. |
|
868 f := Form width:16 height:16 fromArray:bits on:aDevice |
|
869 ] |
|
870 ]. |
|
871 (aDevice == Display) ifTrue:[ |
|
872 RightArrowForm := f |
|
873 ]. |
|
874 ^ f |
|
875 |
|
876 "Modified: / 5.8.1998 / 00:04:40 / cg" |
|
877 ! |
|
878 |
|
879 rightArrowLightFormOn:aDevice |
|
880 "return the form used for the right arrow light pixels (3D only)" |
|
881 |
|
882 |f| |
|
883 |
|
884 ((aDevice == Display) and:[RightArrowLightForm notNil]) ifTrue:[ |
|
885 ^ RightArrowLightForm |
|
886 ]. |
|
887 f := Image fromFile:'bitmaps/RightArrowLight.xbm' resolution:100 on:aDevice. |
|
888 f isNil ifTrue:[ |
|
889 f := Form width:16 height:16 fromArray:#[2r00000000 2r00000000 |
|
890 2r00000000 2r00000000 |
|
891 2r00000000 2r00000000 |
|
892 2r00000110 2r00000000 |
|
893 2r00000101 2r00000000 |
|
894 2r00000100 2r10000000 |
|
895 2r00000100 2r01000000 |
|
896 2r00000100 2r00100000 |
|
897 2r00000100 2r00000000 |
|
898 2r00000100 2r00000000 |
|
899 2r00000100 2r00000000 |
|
900 2r00000100 2r00000000 |
|
901 2r00000100 2r00000000 |
|
902 2r00000100 2r00000000 |
|
903 2r00000000 2r00000000 |
|
904 2r00000000 2r00000000] |
|
905 on:aDevice |
|
906 ]. |
|
907 (aDevice == Display) ifTrue:[ |
|
908 RightArrowLightForm := f |
|
909 ]. |
|
910 ^ f |
|
911 |
|
912 "Modified: 1.1.1970 / 14:10:42 / cg" |
|
913 ! |
|
914 |
|
915 rightArrowShadowFormOn:aDevice |
|
916 "return the form used for the right arrow light pixels (3D only)" |
|
917 |
|
918 |f| |
|
919 |
|
920 ((aDevice == Display) and:[RightArrowShadowForm notNil]) ifTrue:[ |
|
921 ^ RightArrowShadowForm |
|
922 ]. |
|
923 f := Image fromFile:'bitmaps/RightArrowShadow.xbm' resolution:100 on:aDevice. |
|
924 f isNil ifTrue:[ |
|
925 f := Form width:16 height:16 fromArray:#[2r00000000 2r00000000 |
|
926 2r00000000 2r00000000 |
|
927 2r00000000 2r00000000 |
|
928 2r00000000 2r00000000 |
|
929 2r00000000 2r00000000 |
|
930 2r00000000 2r00000000 |
|
931 2r00000000 2r00000000 |
|
932 2r00000000 2r00000000 |
|
933 2r00000000 2r00010000 |
|
934 2r00000000 2r00100000 |
|
935 2r00000000 2r01000000 |
|
936 2r00000000 2r10000000 |
|
937 2r00000001 2r00000000 |
|
938 2r00000010 2r00000000 |
|
939 2r00000000 2r00000000 |
|
940 2r00000000 2r00000000] |
|
941 on:aDevice |
|
942 ]. |
|
943 (aDevice == Display) ifTrue:[ |
|
944 RightArrowShadowForm := f |
|
945 ]. |
|
946 ^ f |
|
947 |
|
948 "Modified: 1.1.1970 / 01:00:00 / cg" |
|
949 ! |
|
950 |
|
951 smallRightArrowLightFormOn:aDevice |
|
952 "return the form used for the small right arrow light pixels (3D only)" |
|
953 |
|
954 |f| |
|
955 |
|
956 ((aDevice == Display) and:[SmallRightArrowLightForm notNil]) ifTrue:[ |
|
957 ^ SmallRightArrowLightForm |
|
958 ]. |
|
959 f := Image fromFile:'bitmaps/SmallRightArrowLight.xbm' resolution:100 on:aDevice. |
|
960 f isNil ifTrue:[ |
|
961 f := Form width:9 height:9 fromArray:#[2r00000000 2r00000000 |
|
962 2r01100000 2r00000000 |
|
963 2r01011000 2r00000000 |
|
964 2r01000110 2r00000000 |
|
965 2r01000000 2r00000000 |
|
966 2r01000000 2r00000000 |
|
967 2r01000000 2r00000000 |
|
968 2r01000000 2r00000000 |
|
969 2r00000000 2r00000000] |
|
970 on:aDevice |
|
971 ]. |
|
972 (aDevice == Display) ifTrue:[ |
|
973 SmallRightArrowLightForm := f |
|
974 ]. |
|
975 ^ f |
|
976 |
|
977 "Modified: 19.12.1996 / 14:10:59 / cg" |
|
978 ! |
|
979 |
|
980 smallRightArrowShadowFormOn:aDevice |
|
981 "return the form used for the small right arrow light pixels (3D only)" |
|
982 |
|
983 |f| |
|
984 |
|
985 ((aDevice == Display) and:[SmallRightArrowShadowForm notNil]) ifTrue:[ |
|
986 ^ SmallRightArrowShadowForm |
|
987 ]. |
|
988 f := Image fromFile:'bitmaps/SmallRightArrowShadow.xbm' resolution:100 on:aDevice. |
|
989 f isNil ifTrue:[ |
|
990 f := Form width:9 height:9 fromArray:#[2r00000000 2r00000000 |
|
991 2r00000000 2r00000000 |
|
992 2r00000000 2r00000000 |
|
993 2r00000000 2r00000000 |
|
994 2r00000001 2r00000000 |
|
995 2r00000110 2r00000000 |
|
996 2r00011000 2r00000000 |
|
997 2r00100000 2r00000000 |
|
998 2r00000000 2r00000000] |
|
999 on:aDevice |
|
1000 ]. |
|
1001 (aDevice == Display) ifTrue:[ |
|
1002 SmallRightArrowShadowForm := f |
|
1003 ]. |
|
1004 ^ f |
|
1005 |
|
1006 "Modified: 19.12.1996 / 14:11:10 / cg" |
|
1007 ! |
|
1008 |
|
1009 updateStyleCache |
|
1010 "extract values from the styleSheet and cache them in class variables" |
|
1011 |
|
1012 <resource: #style (#'selection.disabledForegroundColor' |
|
1013 #'selection.hilightForegroundColor' #'selection.hilightBackgroundColor' |
|
1014 #'selection.hilightFrameColor' #'selection.hilightLevel' |
|
1015 #'selection.rightArrowStyle' #'selection.rightArrowLevel' |
|
1016 #'selection.foregroundColor' #'selection.backgroundColor' |
|
1017 #'selection.shadowColor' #'selection.lightColor' |
|
1018 #'selection.font' #'selection.hilightStyle')> |
|
1019 |
|
1020 DefaultDisabledForegroundColor := StyleSheet colorAt:#'selection.disabledForegroundColor'. |
|
1021 DefaultHilightForegroundColor := StyleSheet colorAt:#'selection.hilightForegroundColor'. |
|
1022 DefaultHilightBackgroundColor := StyleSheet colorAt:#'selection.hilightBackgroundColor'. |
|
1023 DefaultHilightFrameColor := StyleSheet colorAt:#'selection.hilightFrameColor'. |
|
1024 DefaultHilightLevel := StyleSheet at:#'selection.hilightLevel' default:0. |
|
1025 DefaultHilightStyle := StyleSheet at:#'selection.hilightStyle' default:(StyleSheet name). |
|
1026 DefaultRightArrowStyle := StyleSheet at:#'selection.rightArrowStyle'. |
|
1027 DefaultRightArrowLevel := StyleSheet at:#'selection.rightArrowLevel'. |
|
1028 DefaultForegroundColor := StyleSheet colorAt:#'selection.foregroundColor'. |
|
1029 DefaultBackgroundColor := StyleSheet colorAt:#'selection.backgroundColor'. |
|
1030 DefaultShadowColor := StyleSheet colorAt:#'selection.shadowColor'. |
|
1031 DefaultLightColor := StyleSheet colorAt:#'selection.lightColor'. |
|
1032 DefaultFont := StyleSheet fontAt:#'selection.font'. |
|
1033 RightArrowForm := nil. |
|
1034 |
|
1035 " |
|
1036 self updateStyleCache |
|
1037 " |
|
1038 |
|
1039 "Modified: 20.10.1997 / 14:04:26 / cg" |
|
1040 ! ! |
|
1041 |
|
1042 !SelectionInListView methodsFor:'ST80 compatibility'! |
|
1043 |
|
1044 sequence |
|
1045 "same as #list - for ST80 compatibility" |
|
1046 |
|
1047 ^ self list |
|
1048 |
|
1049 "Created: / 21.6.1998 / 02:46:50 / cg" |
|
1050 ! ! |
|
1051 |
|
1052 !SelectionInListView methodsFor:'accessing-actions'! |
|
1053 |
|
1054 action:aBlock |
|
1055 "set the action block to be performed on select. |
|
1056 With useIndex==true, the block gets the selectionIndex as arg, |
|
1057 otherwise, it gets the selectionValue." |
|
1058 |
|
1059 actionBlock := aBlock |
|
1060 ! |
|
1061 |
|
1062 doubleClickAction:aOneArgBlock |
|
1063 "set the double click action block. |
|
1064 If non-nil, that one is evaluated on double click, passing the |
|
1065 selection-line-number (useIndex==true) or selectionValue (useIndex==false) as argument." |
|
1066 |
|
1067 doubleClickActionBlock := aOneArgBlock |
|
1068 |
|
1069 "Modified: 24.2.1996 / 16:07:28 / cg" |
|
1070 ! |
|
1071 |
|
1072 keyActionStyle:aSymbol |
|
1073 "defines how the view should respond to alpha-keys pressed. |
|
1074 Possible values are: |
|
1075 #select -> will select next entry starting with that |
|
1076 character and perform the click-action |
|
1077 |
|
1078 #selectAndDoubleclick -> will select next & perform double-click action |
|
1079 |
|
1080 #pass -> will pass key to superclass (i.e. no special treatment) |
|
1081 |
|
1082 nil -> will ignore key |
|
1083 |
|
1084 the default (set in #initialize) is #select |
|
1085 " |
|
1086 |
|
1087 keyActionStyle := aSymbol |
|
1088 ! |
|
1089 |
|
1090 returnKeyActionStyle:aSymbol |
|
1091 "defines how the view should respond to a return key pressed. |
|
1092 Possible values are: |
|
1093 #doubleClick -> perform double-click action |
|
1094 |
|
1095 #pass -> will pass key to superclass (i.e. no special treatment) |
|
1096 |
|
1097 nil -> will ignore key |
|
1098 |
|
1099 the default (set in #initialize) is #doubleClick |
|
1100 " |
|
1101 |
|
1102 returnKeyActionStyle := aSymbol |
|
1103 ! |
|
1104 |
|
1105 selectConditionBlock:aBlock |
|
1106 "set the conditionBlock; this block is evaluated before a selection |
|
1107 change is performed; the change will not be done, if the evaluation |
|
1108 returns false. For example, this allows confirmation queries in |
|
1109 the SystemBrowser" |
|
1110 |
|
1111 selectConditionBlock := aBlock |
|
1112 ! |
|
1113 |
|
1114 useIndex |
|
1115 "set/clear the useIndex flag. If set, both actionBlock and change-messages |
|
1116 are passed the index(indices) of the selection as argument. |
|
1117 If clear, the value(s) (i.e. the selected string) is passed. |
|
1118 Default is true." |
|
1119 |
|
1120 ^ useIndex |
|
1121 ! |
|
1122 |
|
1123 useIndex:aBoolean |
|
1124 "set/clear the useIndex flag. If set, both actionBlock and change-messages |
|
1125 are passed the index(indices) of the selection as argument. |
|
1126 If clear, the value(s) (i.e. the selected string) is passed. |
|
1127 Default is true." |
|
1128 |
|
1129 useIndex ~~ aBoolean ifTrue:[ |
|
1130 useIndex := aBoolean. |
|
1131 useIndex ifTrue:[ |
|
1132 changeMsg == #selection: ifTrue:[ |
|
1133 changeMsg := #selectionIndex:. |
|
1134 aspectMsg := #selectionIndex. |
|
1135 ] |
|
1136 ] ifFalse:[ |
|
1137 changeMsg == #selectionIndex: ifTrue:[ |
|
1138 changeMsg := #selection:. |
|
1139 aspectMsg := #selection. |
|
1140 ] |
|
1141 ]. |
|
1142 ]. |
|
1143 |
|
1144 ! ! |
|
1145 |
|
1146 !SelectionInListView methodsFor:'accessing-attributes'! |
|
1147 |
|
1148 attributeAt:index |
|
1149 "return the line attribute of list line index. |
|
1150 currently supported are: |
|
1151 #halfIntensity |
|
1152 #disabled |
|
1153 #bold |
|
1154 " |
|
1155 |
|
1156 listAttributes isNil ifFalse:[ |
|
1157 (index > listAttributes size) ifFalse:[ |
|
1158 ^ listAttributes at:index |
|
1159 ] |
|
1160 ]. |
|
1161 ^ nil |
|
1162 ! |
|
1163 |
|
1164 attributeAt:index add:aSymbolOrCollectionOfSymbols |
|
1165 "add to a lines attribute(s); |
|
1166 currently supported are: |
|
1167 #halfIntensity |
|
1168 #disabled |
|
1169 #bold |
|
1170 " |
|
1171 |
|
1172 |current| |
|
1173 |
|
1174 current := self attributeAt:index. |
|
1175 current isNil ifTrue:[ |
|
1176 current := Set new. |
|
1177 ] ifFalse:[ |
|
1178 current isSymbol ifTrue:[ |
|
1179 current == aSymbolOrCollectionOfSymbols ifTrue:[^ self]. |
|
1180 current := Set with:current |
|
1181 ] |
|
1182 ]. |
|
1183 |
|
1184 aSymbolOrCollectionOfSymbols isSymbol ifTrue:[ |
|
1185 current := current add:aSymbolOrCollectionOfSymbols |
|
1186 ] ifFalse:[ |
|
1187 (current includes:aSymbolOrCollectionOfSymbols) ifTrue:[^ self]. |
|
1188 current addAll:aSymbolOrCollectionOfSymbols |
|
1189 ]. |
|
1190 self attributeAt:index put:current |
|
1191 ! |
|
1192 |
|
1193 attributeAt:index put:aSymbolOrCollectionOfSymbolsOrNil |
|
1194 "set a lines attribute(s); |
|
1195 currently supported are: |
|
1196 #halfIntensity |
|
1197 #disabled |
|
1198 #bold |
|
1199 " |
|
1200 |
|
1201 (index > self size) ifFalse:[ |
|
1202 listAttributes isNil ifTrue:[ |
|
1203 listAttributes := (OrderedCollection new:index) grow:index |
|
1204 ] ifFalse:[ |
|
1205 (index > listAttributes size) ifTrue:[ |
|
1206 listAttributes grow:index |
|
1207 ] |
|
1208 ]. |
|
1209 aSymbolOrCollectionOfSymbolsOrNil = (listAttributes at:index) ifFalse:[ |
|
1210 listAttributes at:index put:aSymbolOrCollectionOfSymbolsOrNil. |
|
1211 self redrawLine:index |
|
1212 ] |
|
1213 ] |
|
1214 |
|
1215 ! |
|
1216 |
|
1217 attributeAt:index remove:aSymbolOrCollectionOfSymbols |
|
1218 "remove a line attribute; |
|
1219 currently supported are: |
|
1220 #halfIntensity |
|
1221 #disabled |
|
1222 #bold |
|
1223 " |
|
1224 |
|
1225 |current| |
|
1226 |
|
1227 current := self attributeAt:index. |
|
1228 current isNil ifTrue:[^ self]. |
|
1229 current isSymbol ifTrue:[ |
|
1230 aSymbolOrCollectionOfSymbols isSymbol ifTrue:[ |
|
1231 current == aSymbolOrCollectionOfSymbols ifTrue:[current := nil] |
|
1232 ] ifFalse:[ |
|
1233 (aSymbolOrCollectionOfSymbols includes:current) ifTrue:[ |
|
1234 current := nil |
|
1235 ] |
|
1236 ] |
|
1237 ] ifFalse:[ |
|
1238 aSymbolOrCollectionOfSymbols isSymbol ifTrue:[ |
|
1239 current := current remove:aSymbolOrCollectionOfSymbols ifAbsent:[] |
|
1240 ] ifFalse:[ |
|
1241 aSymbolOrCollectionOfSymbols removeAll:aSymbolOrCollectionOfSymbols |
|
1242 ] |
|
1243 ]. |
|
1244 self attributeAt:index put:current |
|
1245 ! |
|
1246 |
|
1247 line:lineNr hasAttribute:aSymbol |
|
1248 "return true, if line nr has attribute, aSymbol; |
|
1249 currently supported attributes are: |
|
1250 #halfIntensity |
|
1251 #disabled |
|
1252 #bold |
|
1253 " |
|
1254 |
|
1255 |attr| |
|
1256 |
|
1257 listAttributes isNil ifTrue:[^ false]. |
|
1258 (lineNr > listAttributes size) ifTrue:[^ false]. |
|
1259 attr := listAttributes at:lineNr. |
|
1260 attr isNil ifTrue:[^ false]. |
|
1261 attr isSymbol ifTrue:[^ attr == aSymbol]. |
|
1262 ^ (attr includes:aSymbol) |
|
1263 ! |
|
1264 |
|
1265 setAttributes:aList |
|
1266 "set the attribute list. |
|
1267 No redraw is done - the caller should make sure to redraw afterwards |
|
1268 (or use this only before the view is visible)." |
|
1269 |
|
1270 listAttributes := aList |
|
1271 ! |
|
1272 |
|
1273 strikeOut:aBoolean |
|
1274 "turn on/off strikeOut mode" |
|
1275 |
|
1276 strikeOut := aBoolean. |
|
1277 ! ! |
|
1278 |
|
1279 !SelectionInListView methodsFor:'accessing-behavior'! |
|
1280 |
|
1281 dragObjectConverter:aBlock |
|
1282 "set an optional dragObject converter; |
|
1283 if non-nil, this one will be evaluated on a drag-start, |
|
1284 for each dropItem as argument, and supposed |
|
1285 to convert it into a dragObject and return it. |
|
1286 If it returns nil, the object will not be dropped. |
|
1287 Useful, if the receiver view represents fileNames or other |
|
1288 names of the actual objects to be dragged." |
|
1289 |
|
1290 dragObjectConverter := aBlock |
|
1291 |
|
1292 "Created: 6.4.1997 / 12:16:11 / cg" |
|
1293 "Modified: 6.4.1997 / 14:12:45 / cg" |
|
1294 ! |
|
1295 |
|
1296 enabled |
|
1297 "return true if selections are possible" |
|
1298 |
|
1299 ^ enabled. |
|
1300 |
|
1301 "Created: 29.1.1997 / 12:40:54 / stefan" |
|
1302 ! |
|
1303 |
|
1304 enabled:aBoolean |
|
1305 "enable/disable the view - selection changes are allowed/disallowed" |
|
1306 |
|
1307 enabled := aBoolean |
|
1308 |
|
1309 "Modified: / 30.3.1999 / 15:26:10 / stefan" |
|
1310 ! |
|
1311 |
|
1312 ignoreReselect:aBoolean |
|
1313 "set/clear the ignoreReselect flag - |
|
1314 if set, a click on an already selected entry is ignored. |
|
1315 Otherwise the notification is done, even if no |
|
1316 change in the selection occurs. |
|
1317 (for example, in browser to update a method). |
|
1318 Setting ignoreReselect to false makes sense if data is shown |
|
1319 which may change by itself (i.e. without the user doing anything) |
|
1320 For example, the inspector uses this, and redisplays the value, |
|
1321 if the selection is the same. |
|
1322 The default is true, meaning that a click on an already selected |
|
1323 does not lead to a notification via the actionBlock/change mechanism." |
|
1324 |
|
1325 "ca: |
|
1326 multiple selection on: the ignoreReselect will have no influence |
|
1327 " |
|
1328 ignoreReselect := aBoolean |
|
1329 ! |
|
1330 |
|
1331 multipleSelectOk:aBoolean |
|
1332 "allow/disallow multiple selections. If enabled, the |
|
1333 user may select multiple entries in the list, and the program |
|
1334 always gets a collection of selected items (indexes if useIndex is true, |
|
1335 values otherwise). The default is false, for single selections." |
|
1336 |
|
1337 multipleSelectOk := aBoolean. |
|
1338 |
|
1339 ! |
|
1340 |
|
1341 toggleSelect:aBoolean |
|
1342 "turn on/off toggle select. If true, clicking on a selected entry |
|
1343 unselects it and vice versa. The default is false, which means |
|
1344 that clicking on an already selected entry does not change its |
|
1345 select status (see also ignoreReselect:)." |
|
1346 |
|
1347 toggleSelect := aBoolean. |
|
1348 ! ! |
|
1349 |
|
1350 !SelectionInListView methodsFor:'accessing-channels'! |
|
1351 |
|
1352 listHolder |
|
1353 ^ listChannel |
|
1354 ! |
|
1355 |
|
1356 listHolder:aListHolder |
|
1357 listChannel notNil ifTrue:[ |
|
1358 listChannel removeDependent:self |
|
1359 ]. |
|
1360 (listChannel := aListHolder) notNil ifTrue:[ |
|
1361 listChannel addDependent:self |
|
1362 ]. |
|
1363 self getListFromModel |
|
1364 ! ! |
|
1365 |
|
1366 !SelectionInListView methodsFor:'accessing-contents'! |
|
1367 |
|
1368 add:aValue beforeIndex:index |
|
1369 "must recompute our current selections" |
|
1370 |
|
1371 selection notNil ifTrue:[ |
|
1372 multipleSelectOk ifTrue:[ |
|
1373 selection := selection collect:[ :sel | |
|
1374 sel >= index ifTrue:[ |
|
1375 sel + 1 |
|
1376 ] ifFalse:[ |
|
1377 sel |
|
1378 ] |
|
1379 ]. |
|
1380 ] ifFalse:[ |
|
1381 selection >= index ifTrue:[ |
|
1382 selection := selection + 1. |
|
1383 ]. |
|
1384 ]. |
|
1385 ]. |
|
1386 ^ super add:aValue beforeIndex:index. |
|
1387 ! |
|
1388 |
|
1389 contents:aCollection |
|
1390 "set the list - redefined, since setting the list implies unselecting |
|
1391 and clearing attributes. |
|
1392 No redraw is done - the caller should make sure to redraw afterwards |
|
1393 (or use this only before the view is visible)." |
|
1394 |
|
1395 selection := nil. |
|
1396 listAttributes := nil. |
|
1397 super contents:aCollection. |
|
1398 ! |
|
1399 |
|
1400 list:aCollection |
|
1401 "set the list - redefined, since setting the list implies unselecting |
|
1402 and clearing attributes." |
|
1403 |
|
1404 self list:aCollection keepSelection:false |
|
1405 ! |
|
1406 |
|
1407 list:aCollection keepSelection:aBoolean |
|
1408 "set the list - redefined, since setting the list implies unselecting |
|
1409 and clearing attributes." |
|
1410 |
|
1411 |oldSelection| |
|
1412 |
|
1413 "somewhat of a kludge: if selection is first line, |
|
1414 we have to remove the highlight frame by hand here" |
|
1415 |
|
1416 (shown and:[hilightLevel ~~ 0]) ifTrue:[ |
|
1417 selection == firstLineShown ifTrue:[ |
|
1418 self paint:bgColor. |
|
1419 self fillRectangleX:margin y:margin |
|
1420 width:(width - (margin * 2)) |
|
1421 height:(hilightLevel abs). |
|
1422 ]. |
|
1423 ]. |
|
1424 |
|
1425 aBoolean ifTrue:[ |
|
1426 oldSelection := selection. |
|
1427 selection := nil. |
|
1428 ]. |
|
1429 listAttributes := nil. |
|
1430 super list:aCollection expandTabs:printItems. |
|
1431 self setSelection:oldSelection. "/ nil if keep is false |
|
1432 |
|
1433 "Modified: 25.5.1996 / 16:31:13 / cg" |
|
1434 ! |
|
1435 |
|
1436 printItems:aBoolean |
|
1437 "set/clear the printItems flag. If set, items (as set via #list: or |
|
1438 as returned from the model) are sent #printString to display them. |
|
1439 If false, items are assumed to be either strings, or know how to |
|
1440 display themself in a GC (i.e. they are instances of ListEntry). |
|
1441 The default is false. |
|
1442 Caveat: printString seems to be too specialized - I'd rather have |
|
1443 a definable printSelector or - better - a printConverter. |
|
1444 This may be added in the future." |
|
1445 |
|
1446 printItems := aBoolean |
|
1447 ! |
|
1448 |
|
1449 removeIndexWithoutRedraw:lineNr |
|
1450 "delete line - no redraw; |
|
1451 return true, if something was really deleted. |
|
1452 Redefined since we have to care for selection" |
|
1453 |
|
1454 self checkRemovingSelection:lineNr. |
|
1455 ^ super removeIndexWithoutRedraw:lineNr |
|
1456 ! |
|
1457 |
|
1458 setContents:aCollection |
|
1459 "set the list - redefined, since setting the list implies unselecting |
|
1460 and clearing attributes. |
|
1461 No redraw is done - the caller should make sure to redraw afterwards |
|
1462 (or use this only before the view is visible)." |
|
1463 |
|
1464 selection := nil. |
|
1465 listAttributes := nil. |
|
1466 super setContents:aCollection. |
|
1467 ! |
|
1468 |
|
1469 setList:aCollection |
|
1470 "set the list - redefined, since setting the list implies unselecting |
|
1471 and clearing attributes. |
|
1472 No redraw is done - the caller should make sure to redraw afterwards |
|
1473 (or use this only before the view is visible)." |
|
1474 |
|
1475 selection := nil. |
|
1476 listAttributes := nil. |
|
1477 super setList:aCollection. |
|
1478 ! ! |
|
1479 |
|
1480 !SelectionInListView methodsFor:'accessing-look'! |
|
1481 |
|
1482 selectedVisualBlock:aBlock |
|
1483 "ST-80 compatibility - dummy for now" |
|
1484 |
|
1485 selectedVisualBlock := aBlock |
|
1486 |
|
1487 "Created: / 27.10.1997 / 19:50:58 / cg" |
|
1488 "Modified: / 21.6.1998 / 02:40:46 / cg" |
|
1489 ! |
|
1490 |
|
1491 visualBlock:aBlock |
|
1492 "ST-80 compatibility - dummy for now" |
|
1493 |
|
1494 visualBlock := aBlock |
|
1495 |
|
1496 "Modified: / 21.6.1998 / 02:40:57 / cg" |
|
1497 ! ! |
|
1498 |
|
1499 !SelectionInListView methodsFor:'accessing-mvc'! |
|
1500 |
|
1501 addModelInterfaceTo:aDictionary |
|
1502 "see comment in View>>modelInterface" |
|
1503 |
|
1504 super addModelInterfaceTo:aDictionary. |
|
1505 aDictionary at:#doubleClickMessage put:doubleClickMsg. |
|
1506 aDictionary at:#initialSelectionMessage put:initialSelectionMsg. |
|
1507 |
|
1508 " |
|
1509 SelectionInListView new modelInterface |
|
1510 " |
|
1511 ! |
|
1512 |
|
1513 doubleClick:aSymbol |
|
1514 "set the symbol with which the model is informed about double-click. |
|
1515 OBSOLETE: please use #doubleClickMessage:" |
|
1516 |
|
1517 self obsoleteMethodWarning:'please use #doubleClickMessage:'. |
|
1518 doubleClickMsg := aSymbol |
|
1519 ! |
|
1520 |
|
1521 doubleClickMessage |
|
1522 "return the symbol with which the model (if any) is informed about |
|
1523 double-click. If nil (which is the default), it is not informed." |
|
1524 |
|
1525 ^ doubleClickMsg |
|
1526 ! |
|
1527 |
|
1528 doubleClickMessage:aSymbol |
|
1529 "set the symbol with which the model (if any) is informed about double-click. |
|
1530 If nil (which is the default), it is not informed." |
|
1531 |
|
1532 doubleClickMsg := aSymbol |
|
1533 ! |
|
1534 |
|
1535 initialSelectionMessage |
|
1536 "return the symbol by which the model informes me about a changed |
|
1537 selectionIndex. This is used both in change notification and to |
|
1538 actually aquire a new selection value." |
|
1539 |
|
1540 ^ initialSelectionMsg |
|
1541 ! |
|
1542 |
|
1543 initialSelectionMessage:aSymbol |
|
1544 "set the symbol by which the model informes me about a changed |
|
1545 selectionIndex. This is used both in change notification and to |
|
1546 actually aquire a new selection value." |
|
1547 |
|
1548 initialSelectionMsg := aSymbol |
|
1549 ! |
|
1550 |
|
1551 on:aModel printItems:print oneItem:one aspect:aspectSymbol change:changeSymbol |
|
1552 list:listSymbol menu:menuSymbol initialSelection:initialSymbol useIndex:use |
|
1553 |
|
1554 "ST-80 compatibility" |
|
1555 |
|
1556 aspectMsg := aspectSymbol. |
|
1557 changeMsg := changeSymbol. |
|
1558 listMsg := listSymbol. |
|
1559 menuMsg := menuSymbol. |
|
1560 initialSelectionMsg := initialSymbol. |
|
1561 printItems := print. |
|
1562 oneItem := one. |
|
1563 useIndex := use. |
|
1564 ignoreReselect := false. "/ ST80 behavior |
|
1565 self model:aModel. |
|
1566 ! ! |
|
1567 |
|
1568 !SelectionInListView methodsFor:'accessing-selection'! |
|
1569 |
|
1570 addElementToSelection:anObject |
|
1571 "add the element with the same printstring as the argument, anObject |
|
1572 to the selection. The entry is searched by comparing printStrings. |
|
1573 No scrolling is done. Returns true, if ok, false if no such entry |
|
1574 was found. |
|
1575 *** No model and/or actionBlock notification is done here." |
|
1576 |
|
1577 |lineNo str| |
|
1578 |
|
1579 str := anObject printString. |
|
1580 lineNo := list findFirst:[:entry | str = entry printString]. |
|
1581 lineNo ~~ 0 ifTrue:[ |
|
1582 self addToSelection:lineNo. |
|
1583 ^ true |
|
1584 ]. |
|
1585 ^ false |
|
1586 |
|
1587 "Modified: 15.11.1996 / 16:59:43 / cg" |
|
1588 ! |
|
1589 |
|
1590 addToSelection:aNumber |
|
1591 "add entry, aNumber to the selection. No scrolling is done. |
|
1592 *** No model and/or actionBlock notification is done here." |
|
1593 |
|
1594 (self isValidSelection:aNumber) ifFalse:[^ self]. |
|
1595 |
|
1596 (selectConditionBlock notNil |
|
1597 and:[(selectConditionBlock value:aNumber) not]) ifTrue:[^ self]. |
|
1598 |
|
1599 selection isNil ifTrue:[^ self selectWithoutScroll:aNumber]. |
|
1600 selection isCollection ifTrue:[ |
|
1601 (selection includes:aNumber) ifTrue:[^ self]. |
|
1602 selection := selection copyWith:aNumber. |
|
1603 "/ selection add:aNumber |
|
1604 ] ifFalse:[ |
|
1605 (aNumber == selection) ifTrue:[^ self]. |
|
1606 selection := OrderedCollection with:selection with:aNumber |
|
1607 ]. |
|
1608 self redrawElement:aNumber |
|
1609 |
|
1610 "Modified: 15.11.1996 / 16:59:29 / cg" |
|
1611 ! |
|
1612 |
|
1613 removeFromSelection:aNumber |
|
1614 "remove entry, aNumber from the selection. |
|
1615 *** No model and/or actionBlock notification is done here." |
|
1616 |
|
1617 selection isNil ifTrue:[^ self]. |
|
1618 |
|
1619 multipleSelectOk ifTrue:[ |
|
1620 (selection includes:aNumber) ifFalse:[^ self]. |
|
1621 selection := selection copyWithout:aNumber. |
|
1622 "/ selection remove:aNumber. |
|
1623 selection size == 0 ifTrue:[ |
|
1624 selection := nil |
|
1625 ] |
|
1626 ] ifFalse:[ |
|
1627 (aNumber == selection) ifFalse:[^ self]. |
|
1628 selection := nil |
|
1629 ]. |
|
1630 self redrawElement:aNumber |
|
1631 |
|
1632 "Modified: 15.11.1996 / 16:59:04 / cg" |
|
1633 ! ! |
|
1634 |
|
1635 !SelectionInListView methodsFor:'change & update'! |
|
1636 |
|
1637 update:something with:aParameter from:changedObject |
|
1638 |list start stop size idx| |
|
1639 |
|
1640 changedObject == model ifTrue:[ |
|
1641 something == aspectMsg ifTrue:[ |
|
1642 listChannel isNil ifTrue:[ |
|
1643 self getListFromModel |
|
1644 ]. |
|
1645 self getSelectionFromModel. |
|
1646 ^ self |
|
1647 ]. |
|
1648 something == listMsg ifTrue:[ |
|
1649 self getListFromModel. |
|
1650 ^ self |
|
1651 ]. |
|
1652 something == initialSelectionMsg ifTrue:[ |
|
1653 self getSelectionFromModel. |
|
1654 ^ self |
|
1655 ]. |
|
1656 something == #empty ifTrue:[ |
|
1657 self list:nil. |
|
1658 ^ self |
|
1659 ]. |
|
1660 ]. |
|
1661 changedObject == listChannel ifFalse:[ |
|
1662 ^ super update:something with:aParameter from:changedObject |
|
1663 ]. |
|
1664 list := listChannel value. |
|
1665 |
|
1666 something == #at: ifTrue:[ |
|
1667 idx := aParameter isCollection ifTrue:[aParameter at:1] |
|
1668 ifFalse:[aParameter]. |
|
1669 ^ self at:aParameter put:(list at:idx). |
|
1670 ]. |
|
1671 |
|
1672 something == #insert: ifTrue:[ |
|
1673 ^ self add:(list at:aParameter) beforeIndex:aParameter |
|
1674 ]. |
|
1675 |
|
1676 something == #remove: ifTrue:[ |
|
1677 ^ self removeIndex:aParameter |
|
1678 ]. |
|
1679 |
|
1680 something == #insertCollection: ifTrue:[ |
|
1681 (size := aParameter last) ~~ 0 ifTrue:[ |
|
1682 self size == 0 ifTrue:[ |
|
1683 self getListFromModel |
|
1684 ] ifFalse:[ |
|
1685 start := aParameter first. |
|
1686 |
|
1687 size timesRepeat:[ |
|
1688 self add:(list at:start) beforeIndex:start. |
|
1689 start := start + 1 |
|
1690 ] |
|
1691 ] |
|
1692 ]. |
|
1693 ^ self |
|
1694 ]. |
|
1695 |
|
1696 something == #removeFrom: ifTrue:[ |
|
1697 start := aParameter first. |
|
1698 stop := aParameter last. |
|
1699 |
|
1700 (start == 1 and:[stop == self size]) ifTrue:[ |
|
1701 self getListFromModel |
|
1702 ] ifFalse:[ |
|
1703 (stop - start + 1) timesRepeat:[ |
|
1704 self removeIndex:start |
|
1705 ] |
|
1706 ]. |
|
1707 ^ self |
|
1708 ]. |
|
1709 |
|
1710 something == #replace: ifTrue:[ |
|
1711 start := aParameter first. |
|
1712 stop := aParameter last. |
|
1713 |
|
1714 start to:stop do:[:anIndex| |
|
1715 self at:anIndex put:(list at:anIndex) |
|
1716 ]. |
|
1717 ^ self |
|
1718 ]. |
|
1719 |
|
1720 self getListFromModel. |
|
1721 |
|
1722 "Modified: / 14.11.1997 / 13:51:04 / cg" |
|
1723 "Modified: / 30.3.1999 / 14:27:42 / stefan" |
|
1724 ! ! |
|
1725 |
|
1726 !SelectionInListView methodsFor:'drag & drop - new'! |
|
1727 |
|
1728 canDrag |
|
1729 "returns true if dragging is enabled |
|
1730 " |
|
1731 ^ (allowDrag or:[dropSource notNil]) |
|
1732 ! |
|
1733 |
|
1734 dropSource |
|
1735 "returns the dropSource or nil |
|
1736 " |
|
1737 ^ dropSource |
|
1738 ! |
|
1739 |
|
1740 dropSource:aDropSourceOrNil |
|
1741 "set the dropSource or nil |
|
1742 " |
|
1743 dropSource := aDropSourceOrNil. |
|
1744 |
|
1745 |
|
1746 ! |
|
1747 |
|
1748 dropTarget |
|
1749 "returns the dropTarget or nil |
|
1750 " |
|
1751 ^ dropTarget |
|
1752 ! |
|
1753 |
|
1754 dropTarget:aDropTragetOrNil |
|
1755 "set the dropTarget or nil |
|
1756 " |
|
1757 dropTarget := aDropTragetOrNil. |
|
1758 |
|
1759 |
|
1760 ! |
|
1761 |
|
1762 startDragAt:aPoint |
|
1763 |
|
1764 dropSource isNil ifTrue:[ |
|
1765 self startDragX:aPoint x y:aPoint y |
|
1766 ] ifFalse:[ |
|
1767 dropSource startDragIn:self at:aPoint |
|
1768 ] |
|
1769 ! ! |
|
1770 |
|
1771 !SelectionInListView methodsFor:'drag & drop - old'! |
|
1772 |
|
1773 allowDrag:aBoolean |
|
1774 "enable/disable dragging support" |
|
1775 |
|
1776 allowDrag := aBoolean |
|
1777 |
|
1778 "Created: 14.11.1996 / 15:12:58 / cg" |
|
1779 ! |
|
1780 |
|
1781 collectionOfDragObjects |
|
1782 "returns collection of dragable objects assigned to selection |
|
1783 Here, by default, a collection of text-dragObjects is generated; |
|
1784 however, if a dragObjectConverter is defined, that one gets a chance |
|
1785 to convert as appropriate." |
|
1786 |
|
1787 |collection converted| |
|
1788 |
|
1789 collection := OrderedCollection new. |
|
1790 |
|
1791 self selectionDo:[:aNumber||text| |
|
1792 text := self at:aNumber. |
|
1793 collection add:(DropObject newText:text) |
|
1794 ]. |
|
1795 dragObjectConverter notNil ifTrue:[ |
|
1796 converted := OrderedCollection new. |
|
1797 collection do:[:o | |
|
1798 |convertedObject| |
|
1799 |
|
1800 convertedObject := dragObjectConverter value:o. |
|
1801 convertedObject notNil ifTrue:[ |
|
1802 converted add:convertedObject |
|
1803 ] |
|
1804 ]. |
|
1805 collection := converted |
|
1806 ]. |
|
1807 ^ collection. |
|
1808 |
|
1809 "Modified: 6.4.1997 / 14:14:30 / cg" |
|
1810 ! |
|
1811 |
|
1812 endDragAction:aFourArgBlock |
|
1813 "if dragging is enabled, this block will be evaluated |
|
1814 at drag end time. |
|
1815 It gets 4 args passed (see DragAndDropManager>>endDragAt:): |
|
1816 - the targetView (if its a smalltalk view) |
|
1817 - the targetViews windowID (useful, if its an alien view) |
|
1818 - the dropPosition in screen coordinates |
|
1819 - the dropPosition within the target view |
|
1820 " |
|
1821 |
|
1822 endDragAction := aFourArgBlock |
|
1823 |
|
1824 "Created: 14.11.1996 / 15:42:38 / cg" |
|
1825 ! |
|
1826 |
|
1827 showDraggingIn:aView at:p |
|
1828 |nItems items offs| |
|
1829 |
|
1830 items := self selectionValueAsCollection. |
|
1831 (nItems := items size) > 1 ifTrue:[ |
|
1832 offs := 0. |
|
1833 items do:[:item | |
|
1834 item displayOn:aView at:p + (0@offs). |
|
1835 offs := offs + (item heightOn:self) |
|
1836 ] |
|
1837 ] ifFalse:[ |
|
1838 nItems ~~ 0 ifTrue:[ |
|
1839 items first displayOn:aView at:p. |
|
1840 ] |
|
1841 ] |
|
1842 |
|
1843 "Created: 14.11.1996 / 15:31:31 / cg" |
|
1844 "Modified: 14.11.1996 / 16:32:00 / cg" |
|
1845 ! |
|
1846 |
|
1847 startDragX:x y:y |
|
1848 |xOffset w h dragAndDropMgr| |
|
1849 |
|
1850 dragIsActive := true. |
|
1851 xOffset := x. |
|
1852 |
|
1853 h := 0. |
|
1854 w := 0. |
|
1855 |
|
1856 self selectionDo:[:aNumber||e| |
|
1857 e := self at:aNumber. |
|
1858 h := h + (e heightOn:self). |
|
1859 w := w max:(e widthOn:self). |
|
1860 ]. |
|
1861 |
|
1862 DragAndDropManager startDrag:(self collectionOfDragObjects) |
|
1863 from:self |
|
1864 offset:0 @ 0 |
|
1865 atEnd:endDragAction |
|
1866 display:(self selectionValue). |
|
1867 |
|
1868 "/ dragAndDropMgr := DragAndDropManager new. |
|
1869 "/ dragAndDropMgr dropObjects:(self collectionOfDragObjects). |
|
1870 "/ |
|
1871 "/ dragAndDropMgr |
|
1872 "/ startOpaqueDrag:[:aPoint :aView | |
|
1873 "/ self |
|
1874 "/ showDraggingIn:aView |
|
1875 "/ at:aPoint - (xOffset@0) |
|
1876 "/ ] |
|
1877 "/ offset:(xOffset @ h) |
|
1878 "/ extent:(w*5)@(h*2) |
|
1879 "/ in:self |
|
1880 "/ at:(x@y) |
|
1881 "/ atEnd:endDragAction. |
|
1882 "/ |
|
1883 "/ "Modified: 19.4.1997 / 10:00:16 / cg" |
|
1884 "/ |
|
1885 "/ |
|
1886 "/ |
|
1887 ! ! |
|
1888 |
|
1889 !SelectionInListView methodsFor:'drawing'! |
|
1890 |
|
1891 drawRightArrowInVisibleLine:visLineNr |
|
1892 "draw a right arrow (for submenus). |
|
1893 This method is not used here, but provided for subclasses such |
|
1894 as menus or file-lists." |
|
1895 |
|
1896 |y x form form2 topLeftColor botRightColor t itemHeight listLine item| |
|
1897 |
|
1898 x := width - 16. |
|
1899 y := (self yOfVisibleLine:visLineNr). |
|
1900 |
|
1901 listLine := self visibleLineToListLine:visLineNr. |
|
1902 item := self at:listLine. |
|
1903 item isNil ifTrue:[ |
|
1904 itemHeight := fontHeight |
|
1905 ] ifFalse:[ |
|
1906 itemHeight := item heightOn:self. |
|
1907 ]. |
|
1908 |
|
1909 (device depth == 1 or:[arrowLevel == 0]) ifTrue:[ |
|
1910 form := self class rightArrowFormOn:device. |
|
1911 form notNil ifTrue:[ |
|
1912 y := y + ((itemHeight - form height) // 2). |
|
1913 (self isInSelection:listLine) ifTrue:[ |
|
1914 self foreground:hilightFgColor |
|
1915 ] ifFalse:[ |
|
1916 self foreground:fgColor. |
|
1917 ]. |
|
1918 self displayForm:form x:x y:y. |
|
1919 ] |
|
1920 ] ifFalse:[ |
|
1921 smallArrow ifTrue:[ |
|
1922 form := self class smallRightArrowLightFormOn:device. |
|
1923 form2 := self class smallRightArrowShadowFormOn:device. |
|
1924 ] ifFalse:[ |
|
1925 form := self class rightArrowLightFormOn:device. |
|
1926 form2 := self class rightArrowShadowFormOn:device. |
|
1927 ]. |
|
1928 (form isNil or:[form2 isNil]) ifTrue:[ |
|
1929 "/ very bad conditions |
|
1930 ^ self |
|
1931 ]. |
|
1932 y := y + ((itemHeight - form height) // 2). |
|
1933 |
|
1934 topLeftColor := lightColor. |
|
1935 botRightColor := shadowColor. |
|
1936 |
|
1937 "openwin arrow stays down" |
|
1938 styleSheet name ~~ #openwin ifTrue:[ |
|
1939 (self isInSelection:listLine) ifTrue:[ |
|
1940 t := topLeftColor. |
|
1941 topLeftColor := botRightColor. |
|
1942 botRightColor := t. |
|
1943 ] |
|
1944 ]. |
|
1945 arrowLevel < 0 ifTrue:[ |
|
1946 t := topLeftColor. |
|
1947 topLeftColor := botRightColor. |
|
1948 botRightColor := t. |
|
1949 ]. |
|
1950 |
|
1951 "/ self foreground:topLeftColor. |
|
1952 self paint:topLeftColor. |
|
1953 self displayForm:form x:x y:y. |
|
1954 "/ self foreground:botRightColor. |
|
1955 self paint:botRightColor. |
|
1956 self displayForm:form2 x:x y:y. |
|
1957 ] |
|
1958 ! |
|
1959 |
|
1960 drawVisibleLineSelected:visLineNr |
|
1961 "redraw a single line as selected." |
|
1962 |
|
1963 self drawVisibleLineSelected:visLineNr with:hilightFgColor and:hilightBgColor |
|
1964 |
|
1965 "Modified: / 31.8.1995 / 19:24:09 / claus" |
|
1966 "Modified: / 21.6.1998 / 03:12:56 / cg" |
|
1967 ! |
|
1968 |
|
1969 drawVisibleLineSelected:visLineNr with:fg and:bg |
|
1970 "redraw a single line as selected." |
|
1971 |
|
1972 |listLine |
|
1973 y "{ Class: SmallInteger }" |
|
1974 y2 "{ Class: SmallInteger }" |
|
1975 wEdge dObj| |
|
1976 |
|
1977 listLine := self visibleLineToListLine:visLineNr. |
|
1978 listLine notNil ifTrue:[ |
|
1979 selectedVisualBlock notNil ifTrue:[ |
|
1980 dObj := selectedVisualBlock value:self value:listLine. |
|
1981 y := (self yOfVisibleLine:visLineNr) + font ascent. |
|
1982 self paint:bg on:fg. |
|
1983 dObj displayOn:self x:0 y:y opaque:true. |
|
1984 ^ self |
|
1985 ]. |
|
1986 |
|
1987 strikeOut ifTrue:[ |
|
1988 self drawVisibleLine:visLineNr with:fgColor and:bgColor. |
|
1989 y := self yOfVisibleLine:visLineNr. |
|
1990 |
|
1991 self paint:fgColor. |
|
1992 y := y + (fontHeight // 2). |
|
1993 self displayLineFromX:0 y:y toX:width y:y. |
|
1994 ^ self |
|
1995 ]. |
|
1996 |
|
1997 self drawVisibleLine:visLineNr with:fg and:bg. |
|
1998 y := (self yOfVisibleLine:visLineNr) - (lineSpacing//2). |
|
1999 |
|
2000 " |
|
2001 a line above and below |
|
2002 " |
|
2003 hilightFrameColor notNil ifTrue:[ |
|
2004 hilightLevel == 0 ifTrue:[ |
|
2005 self paint:hilightFrameColor. |
|
2006 self displayLineFromX:0 y:y toX:width y:y. |
|
2007 y2 := y + fontHeight - 1. |
|
2008 self displayLineFromX:0 y:y2 toX:width y:y2. |
|
2009 ^ self |
|
2010 ] |
|
2011 ] ifFalse:[ |
|
2012 hilightStyle == #motif ifTrue:[ |
|
2013 self paint:fg. |
|
2014 self displayLineFromX:0 y:y+1 toX:width y:y+1. |
|
2015 y2 := y + fontHeight - 1 - 1. |
|
2016 self displayLineFromX:0 y:y2 toX:width y:y2. |
|
2017 ] |
|
2018 ]. |
|
2019 |
|
2020 " |
|
2021 an edge it around |
|
2022 " |
|
2023 (hilightLevel ~~ 0) ifTrue:[ |
|
2024 " |
|
2025 let edge start at left, extending to the full width |
|
2026 XXX: widthOfContents should be cached in ListView |
|
2027 (instead of recomputing all over) |
|
2028 " |
|
2029 wEdge := width-(2 * margin). |
|
2030 includesNonStrings ifFalse:[ |
|
2031 wEdge := wEdge max:(self widthOfContents). |
|
2032 ]. |
|
2033 self drawEdgesForX:(margin - leftOffset) y:y |
|
2034 width:wEdge+leftOffset height:fontHeight |
|
2035 level:hilightLevel. |
|
2036 |
|
2037 |
|
2038 ]. |
|
2039 ^ self |
|
2040 ]. |
|
2041 ^ super drawVisibleLine:visLineNr with:fg and:bg |
|
2042 |
|
2043 "Modified: / 31.8.1995 / 19:24:09 / claus" |
|
2044 "Created: / 28.2.1996 / 18:40:21 / cg" |
|
2045 "Modified: / 21.6.1998 / 03:51:04 / cg" |
|
2046 ! ! |
|
2047 |
|
2048 !SelectionInListView methodsFor:'event handling'! |
|
2049 |
|
2050 buttonControlPress:button x:x y:y |
|
2051 "if multipleSelectOk: add to the selection; |
|
2052 otherwise, behave like normal select" |
|
2053 |
|
2054 |oldSelection listLineNr| |
|
2055 |
|
2056 ((button == 1) or:[button == #select]) ifTrue:[ |
|
2057 "/ toggleSelect ifTrue:[ |
|
2058 "/ ^ self buttonPress:button x:x y:y |
|
2059 "/ ]. |
|
2060 enabled ifTrue:[ |
|
2061 listLineNr := self visibleLineToListLine:(self visibleLineOfY:y). |
|
2062 listLineNr notNil ifTrue:[ |
|
2063 (self lineIsEnabled:listLineNr) ifFalse:[^ self]. |
|
2064 |
|
2065 (selectConditionBlock notNil |
|
2066 and:[(selectConditionBlock value:listLineNr) not]) ifTrue:[^ self]. |
|
2067 ]. |
|
2068 oldSelection := selection copy. |
|
2069 listLineNr notNil ifTrue: [ |
|
2070 multipleSelectOk ifTrue:[ |
|
2071 (self isInSelection:listLineNr) ifTrue:[ |
|
2072 self removeFromSelection:listLineNr |
|
2073 ] ifFalse:[ |
|
2074 self addToSelection:listLineNr |
|
2075 ] |
|
2076 ] ifFalse:[ |
|
2077 self selectWithoutScroll:listLineNr |
|
2078 ] |
|
2079 ]. |
|
2080 ((ignoreReselect not and:[selection notNil]) |
|
2081 or:[selection ~= oldSelection]) ifTrue:[ |
|
2082 self selectionChangedFrom:oldSelection. |
|
2083 ]. |
|
2084 clickLine := listLineNr |
|
2085 ] |
|
2086 ] ifFalse:[ |
|
2087 super buttonPress:button x:x y:y |
|
2088 ] |
|
2089 |
|
2090 "Created: / 14.11.1996 / 15:51:41 / cg" |
|
2091 "Modified: / 8.8.1998 / 03:24:03 / cg" |
|
2092 ! |
|
2093 |
|
2094 buttonMotion:buttonMask x:x y:y |
|
2095 "mouse-move while button was pressed - handle selection changes" |
|
2096 |
|
2097 (enabled not or:[dragIsActive]) ifTrue:[ |
|
2098 ^ self |
|
2099 ]. |
|
2100 |
|
2101 "is it the select or 1-button ?" |
|
2102 self sensor leftButtonPressed ifFalse:[^ self]. |
|
2103 "/ (device buttonMotionMask:buttonMask includesButton:#select) ifFalse:[ |
|
2104 "/ (device buttonMotionMask:buttonMask includesButton:1) ifFalse:[ |
|
2105 "/ ^ self |
|
2106 "/ ]. |
|
2107 "/ ]. |
|
2108 |
|
2109 clickLine isNil ifTrue:[^ self]. |
|
2110 |
|
2111 (self canDrag and:[clickPosition notNil]) ifTrue:[ "mouse pressed but not released" |
|
2112 (clickPosition dist:(x@y)) > 5.0 ifTrue:[ |
|
2113 ^ self startDragAt:clickPosition |
|
2114 ]. |
|
2115 ^ self |
|
2116 ]. |
|
2117 |
|
2118 "if moved outside of view, start autoscroll" |
|
2119 (y < 0) ifTrue:[ |
|
2120 self compressMotionEvents:false. |
|
2121 self startAutoScrollUp:y. |
|
2122 ^ self |
|
2123 ]. |
|
2124 (y > height) ifTrue:[ |
|
2125 self compressMotionEvents:false. |
|
2126 self startAutoScrollDown:(y - height). |
|
2127 ^ self |
|
2128 ]. |
|
2129 |
|
2130 (self canDrag and:[x < -5]) ifTrue:[ "visible and left out of view" |
|
2131 ^ self startDragAt:(0 @ y) |
|
2132 ]. |
|
2133 |
|
2134 "move inside - stop autoscroll if any" |
|
2135 self stopAutoScroll. |
|
2136 |
|
2137 self expandSelectionToX:x y:y. |
|
2138 |
|
2139 "Modified: / 29.1.1997 / 12:15:31 / stefan" |
|
2140 "Modified: / 28.7.1998 / 16:06:55 / cg" |
|
2141 ! |
|
2142 |
|
2143 buttonMultiPress:button x:x y:y |
|
2144 ((button == 1) or:[button == #select]) ifTrue:[ |
|
2145 "/ doubleClickActionBlock isNil ifTrue:[ |
|
2146 "/ self buttonPress:button x:x y:y |
|
2147 "/ ]. |
|
2148 enabled ifFalse:[ |
|
2149 ^ self |
|
2150 ]. |
|
2151 self doubleClicked. |
|
2152 ] ifFalse:[ |
|
2153 super buttonMultiPress:button x:x y:y |
|
2154 ] |
|
2155 |
|
2156 "Modified: / 26.10.1997 / 18:50:58 / cg" |
|
2157 ! |
|
2158 |
|
2159 buttonPress:button x:x y:y |
|
2160 |sensor lineNr| |
|
2161 |
|
2162 ((button == 1) or:[button == #select]) ifFalse:[ |
|
2163 ^ super buttonPress:button x:x y:y |
|
2164 ]. |
|
2165 enabled ifFalse:[ |
|
2166 ^ self |
|
2167 ]. |
|
2168 |
|
2169 dragIsActive := false. |
|
2170 clickPosition := nil. |
|
2171 |
|
2172 sensor := self sensor. |
|
2173 sensor notNil ifTrue:[ |
|
2174 sensor ctrlDown ifTrue:[ |
|
2175 ^ self buttonControlPress:button x:x y:y |
|
2176 ]. |
|
2177 sensor shiftDown ifTrue:[ |
|
2178 ^ self expandSelectionToX:x y:y |
|
2179 ] |
|
2180 ]. |
|
2181 |
|
2182 self canDrag ifTrue:[ |
|
2183 "/ clicked into the selection ? |
|
2184 |
|
2185 lineNr := self visibleLineToListLine:(self visibleLineOfY:y). |
|
2186 |
|
2187 (self isInSelection:lineNr) ifTrue:[ |
|
2188 "wait for release button |
|
2189 " |
|
2190 clickPosition := x@y. |
|
2191 clickLine := lineNr. |
|
2192 ^ self |
|
2193 ] |
|
2194 ]. |
|
2195 self selectOrToggleAtX:x y:y |
|
2196 |
|
2197 "Modified: / 7.5.1998 / 02:02:20 / cg" |
|
2198 ! |
|
2199 |
|
2200 buttonRelease:button x:x y:y |
|
2201 "stop any autoscroll" |
|
2202 |
|
2203 self stopAutoScroll. |
|
2204 |
|
2205 dragIsActive ifTrue:[ |
|
2206 dragIsActive := false |
|
2207 ] ifFalse:[ |
|
2208 clickPosition notNil ifTrue:[ |
|
2209 enabled ifFalse:[ |
|
2210 ^ self |
|
2211 ]. |
|
2212 self selectOrToggleAtX:(clickPosition x) y:(clickPosition y). |
|
2213 ] |
|
2214 ]. |
|
2215 clickPosition := nil. |
|
2216 |
|
2217 "Modified: / 26.10.1997 / 18:51:14 / cg" |
|
2218 ! |
|
2219 |
|
2220 buttonShiftPress:button x:x y:y |
|
2221 "expand selection |
|
2222 " |
|
2223 self halt. "/ never called |
|
2224 |
|
2225 self expandSelectionToX:x y:y |
|
2226 |
|
2227 "Modified: 17.6.1997 / 18:03:24 / cg" |
|
2228 ! |
|
2229 |
|
2230 doubleClicked |
|
2231 |actionArg| |
|
2232 |
|
2233 clickLine := nil. |
|
2234 |
|
2235 enabled ifFalse:[ |
|
2236 ^ self |
|
2237 ]. |
|
2238 selection isNil ifTrue:[ |
|
2239 "/ can only happen if claus modifies the selection within |
|
2240 "/ the selectAction .... |
|
2241 ^ self |
|
2242 ]. |
|
2243 |
|
2244 actionArg := self argForChangeMessage. |
|
2245 |
|
2246 "/ |
|
2247 "/ the ST-80 way of notifying the model |
|
2248 "/ |
|
2249 (model notNil and:[doubleClickMsg notNil]) ifTrue:[ |
|
2250 self sendChangeMessage:doubleClickMsg with:actionArg. |
|
2251 ]. |
|
2252 |
|
2253 "/ |
|
2254 "/ ST/X action blocks |
|
2255 "/ |
|
2256 doubleClickActionBlock notNil ifTrue:[ |
|
2257 (doubleClickActionBlock numArgs == 1) ifTrue:[ |
|
2258 doubleClickActionBlock value:actionArg |
|
2259 ] ifFalse:[ |
|
2260 doubleClickActionBlock value |
|
2261 ] |
|
2262 ]. |
|
2263 |
|
2264 "Modified: / 26.10.1997 / 18:51:39 / cg" |
|
2265 ! |
|
2266 |
|
2267 key:key select:index x:x y:y |
|
2268 "select an entry by a keyboard action. |
|
2269 This is treated like a doubleClick on that entry" |
|
2270 |
|
2271 |oldSelection| |
|
2272 |
|
2273 enabled ifFalse:[ |
|
2274 ^ self |
|
2275 ]. |
|
2276 (selectConditionBlock isNil or:[selectConditionBlock value:index]) ifTrue:[ |
|
2277 keyActionStyle notNil ifTrue:[ |
|
2278 keyActionStyle == #pass ifTrue:[ |
|
2279 ^ super keyPress:key x:x y:y |
|
2280 ]. |
|
2281 oldSelection := selection. |
|
2282 self selection:index. |
|
2283 "/ |
|
2284 "/ cg; 15-nov-1996 |
|
2285 "/ notification is already done in #selection: |
|
2286 "/ |
|
2287 "/ self selectionChangedFrom:oldSelection. |
|
2288 "/ |
|
2289 |
|
2290 keyActionStyle == #selectAndDoubleClick ifTrue:[ |
|
2291 self doubleClicked |
|
2292 ] |
|
2293 ] |
|
2294 ]. |
|
2295 |
|
2296 "Modified: / 26.10.1997 / 18:51:57 / cg" |
|
2297 ! |
|
2298 |
|
2299 keyPress:key x:x y:y |
|
2300 "handle keyboard input" |
|
2301 |
|
2302 <resource: #keyboard ( #CursorUp #CursorDown #BeginOfText #EndOfText |
|
2303 #BeginOfLine #EndOfLine |
|
2304 #Return ) > |
|
2305 |
|
2306 |index |
|
2307 searchIndex "{Class: SmallInteger}" |
|
2308 startSearch "{Class: SmallInteger}" |
|
2309 backSearch searchPrefix item |
|
2310 mySize sensor s| |
|
2311 |
|
2312 enabled ifFalse:[ |
|
2313 ^ self |
|
2314 ]. |
|
2315 (key == #CursorUp) ifTrue:[ |
|
2316 index := self previousBeforeSelection. |
|
2317 self key:key select:index x:x y:y. |
|
2318 ^ self |
|
2319 ]. |
|
2320 (key == #CursorDown) ifTrue:[ |
|
2321 index := self nextAfterSelection. |
|
2322 self key:key select:index x:x y:y. |
|
2323 ^ self |
|
2324 ]. |
|
2325 "/ |
|
2326 "/ stupid: Home and End are caught in ScrollableView |
|
2327 "/ we normally do not get them ... |
|
2328 "/ (need to call handlesKey: from there ... |
|
2329 "/ ... and implement it here) |
|
2330 "/ |
|
2331 ((key == #BeginOfText) or:[key == #BeginOfLine]) ifTrue:[ |
|
2332 self key:key select:1 x:x y:y. |
|
2333 ^ self |
|
2334 ]. |
|
2335 ((key == #EndOfText) or:[key == #EndOfLine]) ifTrue:[ |
|
2336 index := self size. |
|
2337 self key:key select:index x:x y:y. |
|
2338 ^ self |
|
2339 ]. |
|
2340 key == #Return ifTrue:[ |
|
2341 returnKeyActionStyle == #doubleClick ifTrue:[ |
|
2342 selection notNil ifTrue:[ |
|
2343 self doubleClicked |
|
2344 ]. |
|
2345 ^ self |
|
2346 ]. |
|
2347 returnKeyActionStyle ~~ #pass ifTrue:[ |
|
2348 ^ self |
|
2349 ]. |
|
2350 ]. |
|
2351 |
|
2352 mySize := self size. |
|
2353 |
|
2354 " |
|
2355 alphabetic keys: search for next entry |
|
2356 starting with keys character. If shift is pressed, search backward |
|
2357 " |
|
2358 (mySize > 0 |
|
2359 and:[key isCharacter |
|
2360 and:[key isLetter]]) ifTrue:[ |
|
2361 keyActionStyle isNil ifTrue:[^ self]. |
|
2362 "/ multipleSelectOk ifTrue:[^ self]. |
|
2363 |
|
2364 keyActionStyle == #pass ifFalse:[ |
|
2365 searchPrefix := key asLowercase asString. |
|
2366 |
|
2367 "/ ... isISearch... ifFalse:[ |
|
2368 "/ iSearchString := '' |
|
2369 "/ ] ifTrue:[ |
|
2370 "/ iSearchString := iSearchString , searchPrefix. |
|
2371 "/ searchPrefix := iSearchString |
|
2372 "/ ]. |
|
2373 |
|
2374 backSearch := false. |
|
2375 sensor := self sensor. |
|
2376 sensor notNil ifTrue:[ |
|
2377 backSearch := sensor shiftDown. |
|
2378 ]. |
|
2379 backSearch ifTrue:[ |
|
2380 selection notNil ifTrue:[ |
|
2381 selection size > 0 ifTrue:[ |
|
2382 startSearch := selection first - 1 |
|
2383 ] ifFalse:[ |
|
2384 selection isCollection ifTrue:[ |
|
2385 startSearch := mySize |
|
2386 ] ifFalse:[ |
|
2387 startSearch := selection - 1 |
|
2388 ] |
|
2389 ] |
|
2390 ] ifFalse:[ |
|
2391 startSearch := mySize |
|
2392 ]. |
|
2393 startSearch < 1 ifTrue:[ |
|
2394 startSearch := mySize. |
|
2395 ]. |
|
2396 ] ifFalse:[ |
|
2397 selection notNil ifTrue:[ |
|
2398 selection size > 0 ifTrue:[ |
|
2399 startSearch := selection last + 1 |
|
2400 ] ifFalse:[ |
|
2401 selection isCollection ifTrue:[ |
|
2402 startSearch := 1 |
|
2403 ] ifFalse:[ |
|
2404 startSearch := selection + 1 |
|
2405 ] |
|
2406 ] |
|
2407 ] ifFalse:[ |
|
2408 startSearch := 1 |
|
2409 ]. |
|
2410 startSearch > self size ifTrue:[ |
|
2411 startSearch := 1. |
|
2412 ]. |
|
2413 ]. |
|
2414 searchIndex := startSearch. |
|
2415 [true] whileTrue:[ |
|
2416 item := self at:searchIndex. |
|
2417 item notNil ifTrue:[ |
|
2418 (Object errorSignal catch:[s := item asString]) |
|
2419 ifTrue:[s := item displayString]. |
|
2420 (s withoutSeparators asLowercase startsWith:searchPrefix) ifTrue:[ |
|
2421 searchIndex = selection ifTrue:[^ self]. |
|
2422 ^ self key:key select:searchIndex x:x y:y |
|
2423 ]. |
|
2424 ]. |
|
2425 backSearch ifTrue:[ |
|
2426 searchIndex := searchIndex - 1. |
|
2427 searchIndex < 1 ifTrue:[searchIndex := mySize] |
|
2428 ] ifFalse:[ |
|
2429 searchIndex := searchIndex + 1. |
|
2430 searchIndex > mySize ifTrue:[searchIndex := 1]. |
|
2431 ]. |
|
2432 searchIndex == startSearch ifTrue:[ |
|
2433 ^ self |
|
2434 ] |
|
2435 ] |
|
2436 ]. |
|
2437 ]. |
|
2438 ^ super keyPress:key x:x y:y |
|
2439 |
|
2440 "Modified: / 15.9.1998 / 18:22:31 / cg" |
|
2441 ! |
|
2442 |
|
2443 pointerEnter:state x:x y:y |
|
2444 "mouse pointer moved into my view; |
|
2445 Since I process keyboard events (to position on an entry and/or |
|
2446 for scrolling), request the focus." |
|
2447 |
|
2448 self wantsFocusWithPointerEnter ifTrue:[ |
|
2449 self requestFocus. |
|
2450 ]. |
|
2451 ! |
|
2452 |
|
2453 sizeChanged:how |
|
2454 "if there is a selection, make certain, its visible |
|
2455 after the sizechange" |
|
2456 |
|
2457 |first wasAtEnd selectionWasWisible| |
|
2458 |
|
2459 widthOfWidestLine := nil. |
|
2460 |
|
2461 wasAtEnd := (firstLineShown + nFullLinesShown) >= self size. |
|
2462 |
|
2463 selectionWasWisible := false. |
|
2464 selection notNil ifTrue:[ |
|
2465 multipleSelectOk ifTrue:[ |
|
2466 first := selection firstIfEmpty:nil |
|
2467 ] ifFalse:[ |
|
2468 first := selection |
|
2469 ]. |
|
2470 first notNil ifTrue:[ |
|
2471 selectionWasWisible := (first between:firstLineShown and:(firstLineShown + nFullLinesShown)). |
|
2472 ] |
|
2473 ]. |
|
2474 |
|
2475 super sizeChanged:how. |
|
2476 |
|
2477 shown ifTrue:[ |
|
2478 selection notNil ifTrue:[ |
|
2479 selectionWasWisible ifTrue:[ |
|
2480 multipleSelectOk ifTrue:[ |
|
2481 first := selection firstIfEmpty:nil |
|
2482 ] ifFalse:[ |
|
2483 first := selection |
|
2484 ]. |
|
2485 first notNil ifTrue:[self makeLineVisible:first] |
|
2486 ] |
|
2487 ] ifFalse:[ |
|
2488 " |
|
2489 if we where at the end before, move to the end again. |
|
2490 Still to be seen, if this is better in real life ... |
|
2491 " |
|
2492 wasAtEnd ifTrue:[ |
|
2493 "at end" |
|
2494 self scrollToBottom |
|
2495 ] |
|
2496 ] |
|
2497 ] |
|
2498 |
|
2499 "Modified: / 1.12.1998 / 23:27:27 / cg" |
|
2500 ! ! |
|
2501 |
|
2502 !SelectionInListView methodsFor:'focus handling'! |
|
2503 |
|
2504 wantsFocusWithPointerEnter |
|
2505 "return true, if I want the focus when |
|
2506 the mouse pointer enters" |
|
2507 |
|
2508 |pref| |
|
2509 |
|
2510 pref := UserPreferences current focusFollowsMouse. |
|
2511 (pref ~~ false |
|
2512 and:[(styleSheet at:#'selection.requestFocusOnPointerEnter' default:true) |
|
2513 ]) ifTrue:[ |
|
2514 ^ true |
|
2515 ]. |
|
2516 |
|
2517 ^ false |
|
2518 |
|
2519 ! ! |
|
2520 |
|
2521 !SelectionInListView methodsFor:'initialization'! |
|
2522 |
|
2523 fetchDeviceResources |
|
2524 "fetch device colors, to avoid reallocation at redraw time" |
|
2525 |
|
2526 super fetchDeviceResources. |
|
2527 |
|
2528 hilightFgColor notNil ifTrue:[hilightFgColor := hilightFgColor onDevice:device]. |
|
2529 hilightBgColor notNil ifTrue:[hilightBgColor := hilightBgColor onDevice:device]. |
|
2530 halfIntensityFgColor notNil ifTrue:[halfIntensityFgColor := halfIntensityFgColor onDevice:device]. |
|
2531 hilightFrameColor notNil ifTrue:[hilightFrameColor := hilightFrameColor onDevice:device]. |
|
2532 |
|
2533 "Created: 14.1.1997 / 00:11:13 / cg" |
|
2534 ! |
|
2535 |
|
2536 initCursor |
|
2537 "set the cursor - a hand" |
|
2538 |
|
2539 cursor := Cursor hand |
|
2540 ! |
|
2541 |
|
2542 initStyle |
|
2543 "setup viewStyle specifics" |
|
2544 |
|
2545 super initStyle. |
|
2546 |
|
2547 "/ DefaultFont notNil ifTrue:[font := DefaultFont on:device]. |
|
2548 |
|
2549 bgColor := viewBackground. |
|
2550 hilightFrameColor := nil. |
|
2551 hilightLevel := 0. |
|
2552 hilightStyle := DefaultHilightStyle. |
|
2553 arrowLevel := 1. |
|
2554 smallArrow := false. |
|
2555 |
|
2556 device hasGrayscales ifTrue:[ |
|
2557 " |
|
2558 must get rid of these hard codings |
|
2559 " |
|
2560 (hilightStyle == #next) ifTrue:[ |
|
2561 hilightFgColor := fgColor. |
|
2562 hilightBgColor := White. |
|
2563 hilightFrameColor := fgColor |
|
2564 ] ifFalse:[ |
|
2565 (hilightStyle == #motif) ifTrue:[ |
|
2566 fgColor := White. |
|
2567 bgColor := Grey. |
|
2568 viewBackground := bgColor. |
|
2569 hilightFgColor := bgColor "fgColor" "White". |
|
2570 hilightBgColor := fgColor "bgColor lightened" "darkened". |
|
2571 ] ifFalse:[ |
|
2572 (hilightStyle == #openwin) ifTrue:[ |
|
2573 hilightFgColor := fgColor. |
|
2574 hilightBgColor := Color grey. |
|
2575 smallArrow := true. |
|
2576 ] ifFalse:[ |
|
2577 (hilightStyle == #win95) ifTrue:[ |
|
2578 smallArrow := true. |
|
2579 ] |
|
2580 ] |
|
2581 ] |
|
2582 ] |
|
2583 ]. |
|
2584 |
|
2585 hilightFgColor isNil ifTrue:[ |
|
2586 hilightFgColor := bgColor. |
|
2587 ]. |
|
2588 hilightBgColor isNil ifTrue:[ |
|
2589 hilightBgColor := fgColor. |
|
2590 ]. |
|
2591 DefaultForegroundColor notNil ifTrue:[ |
|
2592 fgColor := DefaultForegroundColor |
|
2593 ]. |
|
2594 DefaultBackgroundColor notNil ifTrue:[ |
|
2595 bgColor := viewBackground := DefaultBackgroundColor |
|
2596 ]. |
|
2597 DefaultHilightForegroundColor notNil ifTrue:[ |
|
2598 hilightFgColor := DefaultHilightForegroundColor |
|
2599 ]. |
|
2600 DefaultHilightBackgroundColor notNil ifTrue:[ |
|
2601 hilightBgColor := DefaultHilightBackgroundColor |
|
2602 ]. |
|
2603 DefaultHilightFrameColor notNil ifTrue:[ |
|
2604 hilightFrameColor := DefaultHilightFrameColor |
|
2605 ]. |
|
2606 DefaultHilightLevel notNil ifTrue:[ |
|
2607 hilightLevel := DefaultHilightLevel |
|
2608 ]. |
|
2609 DefaultRightArrowLevel notNil ifTrue:[ |
|
2610 arrowLevel := DefaultRightArrowLevel |
|
2611 ]. |
|
2612 |
|
2613 DefaultShadowColor notNil ifTrue:[ |
|
2614 shadowColor := DefaultShadowColor |
|
2615 ]. |
|
2616 DefaultLightColor notNil ifTrue:[ |
|
2617 lightColor := DefaultLightColor |
|
2618 ]. |
|
2619 |
|
2620 (hilightLevel abs > 0) ifTrue:[ |
|
2621 lineSpacing := 3 |
|
2622 ] ifFalse:[ |
|
2623 lineSpacing := 2 |
|
2624 ]. |
|
2625 |
|
2626 hilightFgColor isNil ifTrue:[ |
|
2627 hilightFgColor := bgColor. |
|
2628 hilightBgColor := fgColor |
|
2629 ]. |
|
2630 |
|
2631 DefaultDisabledForegroundColor notNil ifTrue:[ |
|
2632 halfIntensityFgColor := DefaultDisabledForegroundColor |
|
2633 ] ifFalse:[ |
|
2634 halfIntensityFgColor := Color darkGray. |
|
2635 ]. |
|
2636 |
|
2637 "Modified: / 5.8.1998 / 00:00:00 / cg" |
|
2638 ! |
|
2639 |
|
2640 initialize |
|
2641 super initialize. |
|
2642 |
|
2643 fontHeight := font height + lineSpacing. |
|
2644 enabled := true. |
|
2645 ignoreReselect := true. |
|
2646 multipleSelectOk := toggleSelect := strikeOut := printItems := false. |
|
2647 useIndex := true. |
|
2648 dragIsActive := allowDrag := false. |
|
2649 |
|
2650 keyActionStyle := #select. |
|
2651 returnKeyActionStyle := #doubleClick. |
|
2652 |
|
2653 listMsg := self class defaultListMessage. |
|
2654 initialSelectionMsg := self class defaultSelectionMessage. |
|
2655 |
|
2656 "Modified: 14.11.1996 / 15:12:33 / cg" |
|
2657 ! |
|
2658 |
|
2659 realize |
|
2660 super realize. |
|
2661 |
|
2662 model notNil ifTrue:[ |
|
2663 self getSelectionFromModel. |
|
2664 ]. |
|
2665 |
|
2666 selection notNil ifTrue:[ |
|
2667 selection isCollection ifTrue:[ |
|
2668 selection notEmpty ifTrue:[ |
|
2669 self makeLineVisible:selection first |
|
2670 ] |
|
2671 ] ifFalse:[ |
|
2672 self makeLineVisible:selection |
|
2673 ] |
|
2674 ]. |
|
2675 |
|
2676 "Modified: 27.2.1997 / 14:23:40 / cg" |
|
2677 ! ! |
|
2678 |
|
2679 !SelectionInListView methodsFor:'private'! |
|
2680 |
|
2681 argForChangeMessage |
|
2682 "return the argument for a selectionChange; |
|
2683 depending on the setting of useIndex, this is either the numeric |
|
2684 index of the selection or the value (i.e. the string)" |
|
2685 |
|
2686 useIndex ~~ false ifTrue:[ "/ i.e. everything except false |
|
2687 multipleSelectOk ifTrue:[ |
|
2688 selection isNil ifTrue:[ |
|
2689 ^ #() |
|
2690 ]. |
|
2691 ]. |
|
2692 ^ selection |
|
2693 ]. |
|
2694 |
|
2695 printItems ifFalse:[ |
|
2696 ^ self selectionValue |
|
2697 ]. |
|
2698 |
|
2699 items notNil ifTrue:[ |
|
2700 multipleSelectOk ifTrue:[ |
|
2701 ^ selection collect:[:nr | items at:nr] |
|
2702 ]. |
|
2703 ^ items at:selection |
|
2704 ]. |
|
2705 |
|
2706 ^ nil "/ cannot happen |
|
2707 |
|
2708 "Modified: 26.10.1995 / 16:28:13 / cg" |
|
2709 ! |
|
2710 |
|
2711 checkRemovingSelection:lineNr |
|
2712 "when a line is removed, we have to adjust selection" |
|
2713 |
|
2714 |newSelection| |
|
2715 |
|
2716 selection notNil ifTrue:[ |
|
2717 multipleSelectOk ifTrue:[ |
|
2718 newSelection := OrderedCollection new. |
|
2719 selection do:[:sel | |
|
2720 sel < lineNr ifTrue:[ |
|
2721 newSelection add:sel |
|
2722 ] ifFalse:[ |
|
2723 sel > lineNr ifTrue:[ |
|
2724 newSelection add:(sel - 1) |
|
2725 ] |
|
2726 "otherwise remove it from the selection" |
|
2727 ] |
|
2728 ]. |
|
2729 newSelection size == 0 ifTrue:[ |
|
2730 selection := nil |
|
2731 ] ifFalse:[ |
|
2732 selection := newSelection |
|
2733 ] |
|
2734 ] ifFalse:[ |
|
2735 selection == lineNr ifTrue:[ |
|
2736 selection := nil |
|
2737 ] ifFalse:[ |
|
2738 selection > lineNr ifTrue:[ |
|
2739 selection := selection - 1 |
|
2740 ] |
|
2741 ] |
|
2742 ] |
|
2743 ] |
|
2744 ! |
|
2745 |
|
2746 getListFromModel |
|
2747 "if I have a model, get my list from it using the listMessage. |
|
2748 If listMessage is nil, try aspectMessage for backward compatibilty." |
|
2749 |
|
2750 |text msg| |
|
2751 |
|
2752 listChannel notNil ifTrue:[ |
|
2753 items := listChannel value copy |
|
2754 ] ifFalse:[ |
|
2755 (model isNil or:[(msg := listMsg) isNil and:[(msg := aspectMsg) isNil]]) ifTrue:[ |
|
2756 ^ self |
|
2757 ]. |
|
2758 items := model perform:msg. |
|
2759 ]. |
|
2760 items notNil ifTrue:[ |
|
2761 printItems ifTrue:[ |
|
2762 text := items collect:[:element | element printString] |
|
2763 ] ifFalse:[ |
|
2764 text := items |
|
2765 ]. |
|
2766 text notNil ifTrue:[ |
|
2767 text isSequenceable ifFalse:[ |
|
2768 text := text asOrderedCollection |
|
2769 ] |
|
2770 ] |
|
2771 ]. |
|
2772 self list:text keepSelection:true. "/ expandTabs:false |
|
2773 ! |
|
2774 |
|
2775 getSelectionFromModel |
|
2776 "if I have a model and an initialSelectionMsg, get my selection from it" |
|
2777 |
|
2778 |sel| |
|
2779 |
|
2780 model notNil ifTrue:[ |
|
2781 listChannel notNil ifTrue:[ |
|
2782 sel := model value. |
|
2783 sel isNil ifTrue:[ |
|
2784 self deselect. |
|
2785 ^ self |
|
2786 ] |
|
2787 ] ifFalse:[ |
|
2788 initialSelectionMsg isNil ifTrue:[^ self]. |
|
2789 sel := model perform:initialSelectionMsg. |
|
2790 ]. |
|
2791 (useIndex or:[sel isNumber]) ifTrue:[ |
|
2792 self setSelection:sel |
|
2793 ] ifFalse:[ |
|
2794 self setSelectElement:sel. |
|
2795 ] |
|
2796 ]. |
|
2797 |
|
2798 "Modified: 25.5.1996 / 16:34:54 / cg" |
|
2799 ! |
|
2800 |
|
2801 isValidSelection:aNumberOrCollection |
|
2802 "return true, if aNumber is ok as a selection index" |
|
2803 |
|
2804 |sz| |
|
2805 |
|
2806 aNumberOrCollection isNil ifTrue:[^ false]. |
|
2807 |
|
2808 sz := self size. |
|
2809 (aNumberOrCollection isCollection) ifTrue:[ |
|
2810 multipleSelectOk ifFalse:[^ false]. |
|
2811 aNumberOrCollection do:[:index | |
|
2812 (index between:1 and:sz) ifFalse:[^ false]. |
|
2813 (self lineIsEnabled:index) ifFalse:[^ false]. |
|
2814 ]. |
|
2815 ] ifFalse:[ |
|
2816 (aNumberOrCollection between:1 and:sz) ifFalse:[^ false]. |
|
2817 (self lineIsEnabled:aNumberOrCollection) ifFalse:[^ false]. |
|
2818 ]. |
|
2819 ^ true. |
|
2820 |
|
2821 "Modified: / 8.8.1998 / 03:34:27 / cg" |
|
2822 ! |
|
2823 |
|
2824 lineIsEnabled:lineNr |
|
2825 ^ (self line:lineNr hasAttribute:#disabled) not |
|
2826 |
|
2827 "Modified: / 8.8.1998 / 03:22:50 / cg" |
|
2828 ! |
|
2829 |
|
2830 positionToSelectionX:x y:y |
|
2831 "given a click position, return the selection lineNo" |
|
2832 |
|
2833 |visibleLine| |
|
2834 |
|
2835 (x between:0 and:width) ifTrue:[ |
|
2836 (y between:0 and:height) ifTrue:[ |
|
2837 visibleLine := self visibleLineOfY:y. |
|
2838 ^ self visibleLineToListLine:visibleLine |
|
2839 ] |
|
2840 ]. |
|
2841 ^ nil |
|
2842 ! |
|
2843 |
|
2844 scrollSelectDown |
|
2845 "auto scroll action; scroll and reinstall timed-block" |
|
2846 |
|
2847 self scrollDown. |
|
2848 Processor addTimedBlock:autoScrollBlock afterSeconds:autoScrollDeltaT. |
|
2849 ! |
|
2850 |
|
2851 scrollSelectUp |
|
2852 "auto scroll action; scroll and reinstall timed-block" |
|
2853 |
|
2854 self scrollUp. |
|
2855 Processor addTimedBlock:autoScrollBlock afterSeconds:autoScrollDeltaT. |
|
2856 ! |
|
2857 |
|
2858 selectOrToggleAtX:x y:y |
|
2859 |oldSelection listLineNr| |
|
2860 |
|
2861 listLineNr := self visibleLineToListLine:(self visibleLineOfY:y). |
|
2862 listLineNr notNil ifTrue:[ |
|
2863 (toggleSelect |
|
2864 and:[self isInSelection:listLineNr]) ifTrue:[ |
|
2865 oldSelection := selection copy. |
|
2866 self removeFromSelection:listLineNr |
|
2867 ] ifFalse:[ |
|
2868 (self lineIsEnabled:listLineNr) ifFalse:[^ self]. |
|
2869 |
|
2870 (selectConditionBlock notNil |
|
2871 and:[(selectConditionBlock value:listLineNr) not]) ifTrue:[^ self]. |
|
2872 |
|
2873 (toggleSelect and:[multipleSelectOk]) ifTrue:[ |
|
2874 oldSelection := selection copy. |
|
2875 self addToSelection:listLineNr |
|
2876 ] ifFalse:[ |
|
2877 oldSelection := selection copy. |
|
2878 self selectWithoutScroll:listLineNr. |
|
2879 ]. |
|
2880 ]. |
|
2881 ((ignoreReselect not and:[selection notNil]) |
|
2882 or:[selection ~= oldSelection]) ifTrue:[ |
|
2883 self selectionChangedFrom:oldSelection. |
|
2884 ]. |
|
2885 clickLine := listLineNr |
|
2886 ] |
|
2887 |
|
2888 "Created: / 14.11.1996 / 16:27:17 / cg" |
|
2889 "Modified: / 8.8.1998 / 03:22:26 / cg" |
|
2890 ! |
|
2891 |
|
2892 visibleLineNeedsSpecialCare:visLineNr |
|
2893 |listLine| |
|
2894 |
|
2895 listLine := self visibleLineToListLine:visLineNr. |
|
2896 listLine isNil ifTrue:[^ false]. |
|
2897 (self isInSelection:listLine) ifTrue:[^ true]. |
|
2898 visualBlock notNil ifTrue:[^true]. |
|
2899 listAttributes notNil ifTrue:[ |
|
2900 (listLine <= listAttributes size) ifTrue:[ |
|
2901 ^ (listAttributes at:listLine) notNil |
|
2902 ] |
|
2903 ]. |
|
2904 ^ false |
|
2905 |
|
2906 "Modified: / 21.6.1998 / 02:43:02 / cg" |
|
2907 ! |
|
2908 |
|
2909 widthForScrollBetween:start and:end |
|
2910 "has to be redefined since WHOLE line is inverted/modified sometimes" |
|
2911 |
|
2912 | anySelectionInRange | |
|
2913 |
|
2914 selection notNil ifTrue:[ |
|
2915 multipleSelectOk ifTrue:[ |
|
2916 anySelectionInRange := false. |
|
2917 selection do:[:s | |
|
2918 (s between:start and:end) ifTrue:[ |
|
2919 anySelectionInRange := true |
|
2920 ] |
|
2921 ] |
|
2922 ] ifFalse:[ |
|
2923 anySelectionInRange := selection between:start and:end |
|
2924 ] |
|
2925 ] ifFalse:[ |
|
2926 anySelectionInRange := false |
|
2927 ]. |
|
2928 |
|
2929 anySelectionInRange ifTrue:[ |
|
2930 ^ width |
|
2931 " |
|
2932 self is3D ifFalse:[ |
|
2933 ^ width |
|
2934 ]. |
|
2935 ( #(next openwin) includes:styleSheet name) ifTrue:[ |
|
2936 ^ width |
|
2937 ]. |
|
2938 viewBackground = background ifFalse:[ |
|
2939 ^ width |
|
2940 ] |
|
2941 " |
|
2942 ]. |
|
2943 ^ super widthForScrollBetween:start and:end |
|
2944 ! ! |
|
2945 |
|
2946 !SelectionInListView methodsFor:'queries'! |
|
2947 |
|
2948 specClass |
|
2949 "redefined, since the name of my specClass is nonStandard (i.e. not SelectionInListSpec)" |
|
2950 |
|
2951 self class == SelectionInListView ifTrue:[^ SequenceViewSpec]. |
|
2952 ^ super specClass |
|
2953 |
|
2954 "Modified: / 5.9.1995 / 23:05:53 / claus" |
|
2955 "Modified: / 31.10.1997 / 19:48:44 / cg" |
|
2956 ! ! |
|
2957 |
|
2958 !SelectionInListView methodsFor:'redrawing'! |
|
2959 |
|
2960 redrawElement:aNumber |
|
2961 "redraw an individual element" |
|
2962 |
|
2963 ^ self redrawLine:aNumber |
|
2964 ! |
|
2965 |
|
2966 redrawFromVisibleLine:startVisLineNr to:endVisLineNr |
|
2967 "redraw a range of lines. |
|
2968 Must check, if any is in the selection and handle this case. |
|
2969 Otherwise draw it en-bloque using supers method." |
|
2970 |
|
2971 |special sel |
|
2972 l1 "{ Class: SmallInteger }" |
|
2973 l2 "{ Class: SmallInteger }" |
|
2974 selNo "{ Class: SmallInteger }" | |
|
2975 |
|
2976 ((selection isCollection) |
|
2977 or:[listAttributes notNil |
|
2978 or:[visualBlock notNil |
|
2979 or:[selectedVisualBlock notNil]]]) ifTrue:[ |
|
2980 "/ cannot do bulk-redraw ... |
|
2981 l1 := startVisLineNr. |
|
2982 l2 := endVisLineNr. |
|
2983 l1 to:l2 do:[:visLine | |
|
2984 self redrawVisibleLine:visLine |
|
2985 ]. |
|
2986 ^ self |
|
2987 ]. |
|
2988 |
|
2989 "XXX only if -1/+1" |
|
2990 "/ hilightLevel ~~ 0 ifTrue:[ |
|
2991 "/ self paint:bgColor. |
|
2992 "/ self fillRectangleX:0 y:(self yOfVisibleLine:startVisLineNr)-1 width:width height:1 |
|
2993 "/ ]. |
|
2994 special := true. |
|
2995 selection isNil ifTrue:[ |
|
2996 special := false |
|
2997 ] ifFalse:[ |
|
2998 sel := self listLineToVisibleLine:selection. |
|
2999 sel isNil ifTrue:[ |
|
3000 special := false |
|
3001 ] ifFalse:[ |
|
3002 special := (sel between:startVisLineNr and:endVisLineNr) |
|
3003 ] |
|
3004 ]. |
|
3005 special ifFalse:[ |
|
3006 ^ super redrawFromVisibleLine:startVisLineNr to:endVisLineNr |
|
3007 ]. |
|
3008 |
|
3009 selNo := sel. |
|
3010 selNo > startVisLineNr ifTrue:[ |
|
3011 super redrawFromVisibleLine:startVisLineNr to:(selNo - 1) |
|
3012 ]. |
|
3013 self redrawVisibleLine:selNo. |
|
3014 selNo < endVisLineNr ifTrue:[ |
|
3015 super redrawFromVisibleLine:(selNo + 1) to:endVisLineNr |
|
3016 ] |
|
3017 |
|
3018 "Modified: / 21.6.1998 / 02:42:17 / cg" |
|
3019 ! |
|
3020 |
|
3021 redrawVisibleLine:visLineNr |
|
3022 "redraw a single line. |
|
3023 Must check, if any is in the selection and handle this case. |
|
3024 Otherwise draw using supers method." |
|
3025 |
|
3026 |listLine fg bg newFont oldFont id dObj y| |
|
3027 |
|
3028 fg := fgColor. |
|
3029 bg := bgColor. |
|
3030 listLine := self visibleLineToListLine:visLineNr. |
|
3031 listLine notNil ifTrue:[ |
|
3032 (self isInSelection:listLine) ifTrue:[ |
|
3033 ^ self drawVisibleLineSelected:visLineNr |
|
3034 ]. |
|
3035 |
|
3036 visualBlock notNil ifTrue:[ |
|
3037 dObj := visualBlock value:self value:listLine. |
|
3038 y := (self yOfVisibleLine:visLineNr) + font ascent. |
|
3039 self paint:fg on:bg. |
|
3040 dObj displayOn:self x:0 y:y opaque:true. |
|
3041 ^ self |
|
3042 ]. |
|
3043 listAttributes notNil ifTrue:[ |
|
3044 ((self line:listLine hasAttribute:#halfIntensity) |
|
3045 or:[ (self lineIsEnabled:listLine) not ]) ifTrue:[ |
|
3046 fg := halfIntensityFgColor |
|
3047 ]. |
|
3048 (self line:listLine hasAttribute:#bold) ifTrue:[ |
|
3049 newFont := font asBold. |
|
3050 (font bold |
|
3051 or:[id := (newFont onDevice:device) fontId. |
|
3052 id isNil]) |
|
3053 ifTrue:[ |
|
3054 " |
|
3055 mhmh - what can be done, if the font is already bold ? |
|
3056 or no such font is available |
|
3057 " |
|
3058 fgColor brightness > 0.5 ifTrue:[ |
|
3059 fg := fgColor darkened "darkened". |
|
3060 ] ifFalse:[ |
|
3061 fg := fgColor lightened "lightened" |
|
3062 ]. |
|
3063 (fg brightness - bg brightness) abs < 0.25 ifTrue:[ |
|
3064 bgColor brightness > 0.5 ifTrue:[ |
|
3065 fg := fg darkened. |
|
3066 ] ifFalse:[ |
|
3067 fg := fg lightened |
|
3068 ]. |
|
3069 ] |
|
3070 ]. |
|
3071 id notNil ifTrue:[ |
|
3072 oldFont := font. |
|
3073 self basicFont:newFont. |
|
3074 self drawVisibleLine:visLineNr with:fg and:bg. |
|
3075 self basicFont:oldFont. |
|
3076 ] ifFalse:[ |
|
3077 self drawVisibleLine:visLineNr with:fg and:bg. |
|
3078 ]. |
|
3079 ^ self |
|
3080 ] |
|
3081 ] |
|
3082 ]. |
|
3083 ^ self drawVisibleLine:visLineNr with:fg and:bg |
|
3084 |
|
3085 "Modified: / 8.8.1998 / 03:42:13 / cg" |
|
3086 ! |
|
3087 |
|
3088 redrawVisibleLine:visLineNr col:colNr |
|
3089 "redraw a single character. |
|
3090 Must check, if its in the selection and handle this case." |
|
3091 |
|
3092 (self visibleLineNeedsSpecialCare:visLineNr) ifTrue:[ |
|
3093 ^ self redrawVisibleLine:visLineNr |
|
3094 ]. |
|
3095 super redrawVisibleLine:visLineNr col:colNr |
|
3096 ! |
|
3097 |
|
3098 redrawVisibleLine:visLineNr from:startCol |
|
3099 "redraw from a col to the right end. |
|
3100 Must check, if its in the selection and handle this case." |
|
3101 |
|
3102 (self visibleLineNeedsSpecialCare:visLineNr) ifTrue:[ |
|
3103 ^ self redrawVisibleLine:visLineNr |
|
3104 ]. |
|
3105 super redrawVisibleLine:visLineNr from:startCol |
|
3106 ! |
|
3107 |
|
3108 redrawVisibleLine:visLineNr from:startCol to:endCol |
|
3109 "redraw from a startCol to endCol. |
|
3110 Must check, if its in the selection and handle this case." |
|
3111 |
|
3112 (self visibleLineNeedsSpecialCare:visLineNr) ifTrue:[ |
|
3113 ^ self redrawVisibleLine:visLineNr |
|
3114 ]. |
|
3115 super redrawVisibleLine:visLineNr from:startCol to:endCol |
|
3116 ! ! |
|
3117 |
|
3118 !SelectionInListView methodsFor:'selections'! |
|
3119 |
|
3120 deselect |
|
3121 "deselect; Model or actionBlock notifications are made. |
|
3122 To deselect without notifications, use #setSelection:nil." |
|
3123 |
|
3124 self selection:nil |
|
3125 |
|
3126 "Modified: 25.5.1996 / 13:03:47 / cg" |
|
3127 ! |
|
3128 |
|
3129 deselectWithoutRedraw |
|
3130 "deselect without redraw or notifications. |
|
3131 No model or actionBlock notifications are made." |
|
3132 |
|
3133 selection := nil |
|
3134 |
|
3135 "Modified: 25.5.1996 / 13:04:14 / cg" |
|
3136 ! |
|
3137 |
|
3138 expandSelectionToX:x y:y |
|
3139 "used with button-motion and shift-press; |
|
3140 expand the selection to include all items from the clicked one, |
|
3141 up to the one under the mouse pointer" |
|
3142 |
|
3143 |movedLine delta oldSel| |
|
3144 |
|
3145 clickLine isNil ifTrue:[^ self]. |
|
3146 |
|
3147 movedLine := self visibleLineToAbsoluteLine:(self visibleLineOfY:y). |
|
3148 |
|
3149 multipleSelectOk ifTrue:[ |
|
3150 movedLine == clickLine ifFalse:[ |
|
3151 delta := (clickLine < movedLine) ifTrue:[1] ifFalse:[-1]. |
|
3152 oldSel := selection copy. |
|
3153 |
|
3154 (clickLine+delta) to:movedLine by:delta do:[:ln | |
|
3155 (self isInSelection:ln) ifTrue:[self removeFromSelection:ln] |
|
3156 ifFalse:[self addToSelection:ln] |
|
3157 ]. |
|
3158 self selectionChangedFrom:oldSel |
|
3159 ] |
|
3160 ]. |
|
3161 clickLine := movedLine. |
|
3162 |
|
3163 "Created: 14.11.1996 / 15:48:10 / cg" |
|
3164 "Modified: 14.11.1996 / 15:50:03 / cg" |
|
3165 |
|
3166 ! |
|
3167 |
|
3168 hasSelection |
|
3169 "return true, if the view has a selection" |
|
3170 |
|
3171 ^ selection notNil |
|
3172 ! |
|
3173 |
|
3174 isInSelection:aNumber |
|
3175 "return true, if line, aNumber is in the selection" |
|
3176 |
|
3177 selection isNil ifTrue:[^ false]. |
|
3178 multipleSelectOk ifTrue:[ |
|
3179 ^ (selection includes:aNumber) |
|
3180 ]. |
|
3181 ^ (aNumber == selection) |
|
3182 ! |
|
3183 |
|
3184 makeSelectionVisible |
|
3185 "scroll to make the selection line visible" |
|
3186 |
|
3187 |line| |
|
3188 |
|
3189 selection notNil ifTrue:[ |
|
3190 multipleSelectOk ifTrue:[ |
|
3191 selection isEmpty ifTrue:[^ self]. |
|
3192 line := selection first. |
|
3193 ] ifFalse:[ |
|
3194 line := selection |
|
3195 ]. |
|
3196 self makeLineVisible:line |
|
3197 ] |
|
3198 ! |
|
3199 |
|
3200 nextAfterSelection |
|
3201 "return the index of the next selectable entry after the selection. |
|
3202 Wrap at end." |
|
3203 |
|
3204 |next sz| |
|
3205 |
|
3206 selection isNil ifTrue:[ |
|
3207 next := firstLineShown |
|
3208 ] ifFalse:[ |
|
3209 selection isCollection ifTrue:[ |
|
3210 selection size == 0 ifTrue:[ |
|
3211 next := firstLineShown |
|
3212 ] ifFalse:[ |
|
3213 next := selection max + 1 |
|
3214 ] |
|
3215 ] ifFalse:[ |
|
3216 next := selection + 1 |
|
3217 ]. |
|
3218 ]. |
|
3219 |
|
3220 (self isValidSelection:next) ifFalse:[ |
|
3221 sz := self size. |
|
3222 next > sz ifTrue:[ |
|
3223 next := 1. |
|
3224 ] ifFalse:[ |
|
3225 [next <= sz |
|
3226 and:[(self isValidSelection:next) not ]] whileTrue:[ |
|
3227 next := next + 1 |
|
3228 ]. |
|
3229 ]. |
|
3230 ]. |
|
3231 |
|
3232 (self isValidSelection:next) ifFalse:[ |
|
3233 next := nil |
|
3234 ]. |
|
3235 ^ next |
|
3236 |
|
3237 "Modified: / 8.8.1998 / 03:36:55 / cg" |
|
3238 ! |
|
3239 |
|
3240 numberOfSelections |
|
3241 "return the number of selected entries" |
|
3242 |
|
3243 |sz| |
|
3244 |
|
3245 selection isNil ifTrue:[^ 0]. |
|
3246 sz := selection size. |
|
3247 sz > 0 ifTrue:[^ sz]. |
|
3248 ^ 1 |
|
3249 ! |
|
3250 |
|
3251 previousBeforeSelection |
|
3252 "return the index of the previous selectable entry before the selection. |
|
3253 Wrap at beginning." |
|
3254 |
|
3255 |prev| |
|
3256 |
|
3257 selection isNil ifTrue:[ |
|
3258 prev := firstLineShown - 1 |
|
3259 ] ifFalse:[ |
|
3260 selection isCollection ifTrue:[ |
|
3261 selection size == 0 ifTrue:[ |
|
3262 prev := firstLineShown - 1 |
|
3263 ] ifFalse:[ |
|
3264 prev := selection min - 1 |
|
3265 ] |
|
3266 ] ifFalse:[ |
|
3267 prev := selection - 1 |
|
3268 ]. |
|
3269 ]. |
|
3270 (self isValidSelection:prev) ifFalse:[ |
|
3271 prev < 1 ifTrue:[ |
|
3272 prev := self size. |
|
3273 ] ifFalse:[ |
|
3274 [prev >= 1 |
|
3275 and:[(self isValidSelection:prev) not]] whileTrue:[ |
|
3276 prev := prev - 1 |
|
3277 ]. |
|
3278 ]. |
|
3279 ]. |
|
3280 (self isValidSelection:prev) ifFalse:[ |
|
3281 prev := nil |
|
3282 ]. |
|
3283 ^ prev |
|
3284 |
|
3285 ! |
|
3286 |
|
3287 selectAll |
|
3288 "select all entries. |
|
3289 Model and/or actionBlock notification IS done." |
|
3290 |
|
3291 |oldSelection| |
|
3292 |
|
3293 multipleSelectOk ifTrue:[ |
|
3294 oldSelection := selection. |
|
3295 selection := OrderedCollection withAll:(1 to:self size). |
|
3296 self invalidate. |
|
3297 self selectionChangedFrom:oldSelection. |
|
3298 ] |
|
3299 |
|
3300 "Modified: 15.11.1996 / 17:00:26 / cg" |
|
3301 ! |
|
3302 |
|
3303 selectElement:anObject |
|
3304 "select the element with same printString as the argument, anObject. |
|
3305 Scroll to make the new selection visible. |
|
3306 Model and/or actionBlock notification IS done." |
|
3307 |
|
3308 |lineNo| |
|
3309 |
|
3310 list notNil ifTrue:[ |
|
3311 items notNil ifTrue:[ |
|
3312 lineNo := items indexOf:anObject ifAbsent:nil |
|
3313 ] ifFalse:[ |
|
3314 lineNo := list indexOf:(anObject printString) ifAbsent:nil. |
|
3315 ]. |
|
3316 lineNo notNil ifTrue:[self selection:lineNo] |
|
3317 ] |
|
3318 |
|
3319 "Modified: 15.11.1996 / 17:01:05 / cg" |
|
3320 ! |
|
3321 |
|
3322 selectElementWithoutScroll:anObject |
|
3323 "select the element with same printString as the argument, anObject. |
|
3324 Do not scroll. |
|
3325 *** No model and/or actionBlock notification is done here." |
|
3326 |
|
3327 |lineNo| |
|
3328 |
|
3329 list notNil ifTrue:[ |
|
3330 items notNil ifTrue:[ |
|
3331 lineNo := items indexOf:anObject ifAbsent:nil |
|
3332 ] ifFalse:[ |
|
3333 lineNo := list indexOf:(anObject printString) ifAbsent:nil. |
|
3334 ]. |
|
3335 lineNo notNil ifTrue:[self selectWithoutScroll:lineNo] |
|
3336 ] |
|
3337 |
|
3338 "Modified: 15.11.1996 / 17:01:17 / cg" |
|
3339 ! |
|
3340 |
|
3341 selectNext |
|
3342 "select next line or first visible if there is currrently no selection. |
|
3343 Wrap at end. |
|
3344 Model and/or actionBlock notification IS done." |
|
3345 |
|
3346 self selection:(self nextAfterSelection) |
|
3347 |
|
3348 "Modified: 15.11.1996 / 17:01:27 / cg" |
|
3349 ! |
|
3350 |
|
3351 selectPrevious |
|
3352 "select previous line or previous visible if there is currently no selection. |
|
3353 Wrap at beginning. |
|
3354 Model and/or actionBlock notification IS done." |
|
3355 |
|
3356 self selection:(self previousBeforeSelection). |
|
3357 |
|
3358 "Modified: 26.9.1995 / 09:41:16 / stefan" |
|
3359 "Modified: 15.11.1996 / 17:01:34 / cg" |
|
3360 ! |
|
3361 |
|
3362 selectWithoutScroll:aNumberOrNilOrCollection |
|
3363 "select line, aNumber or deselect if argument is nil. |
|
3364 *** No model and/or actionBlock notification is done here." |
|
3365 |
|
3366 |prevSelection newSelection| |
|
3367 |
|
3368 newSelection := aNumberOrNilOrCollection. |
|
3369 newSelection notNil ifTrue:[ |
|
3370 (self isValidSelection:newSelection) ifFalse:[ |
|
3371 newSelection := nil |
|
3372 ]. |
|
3373 newSelection == 0 ifTrue:[ |
|
3374 newSelection := nil |
|
3375 ] ifFalse:[ |
|
3376 (newSelection isCollection |
|
3377 and:[newSelection size == 0]) ifTrue:[ |
|
3378 newSelection := nil |
|
3379 ] |
|
3380 ]. |
|
3381 |
|
3382 newSelection notNil ifTrue:[ |
|
3383 multipleSelectOk ifTrue:[ |
|
3384 newSelection isCollection ifFalse:[ |
|
3385 newSelection := OrderedCollection with:newSelection |
|
3386 ] |
|
3387 ] |
|
3388 ]. |
|
3389 ]. |
|
3390 |
|
3391 (newSelection = selection) ifTrue: [^ self]. |
|
3392 |
|
3393 " |
|
3394 redraw old selection unhighlighted |
|
3395 " |
|
3396 selection notNil ifTrue: [ |
|
3397 prevSelection := selection. |
|
3398 selection := nil. |
|
3399 multipleSelectOk ifTrue:[ |
|
3400 prevSelection do:[:line | |
|
3401 self redrawElement:line |
|
3402 ] |
|
3403 ] ifFalse:[ |
|
3404 self redrawElement:prevSelection |
|
3405 ] |
|
3406 ]. |
|
3407 |
|
3408 selection := newSelection. |
|
3409 |
|
3410 " |
|
3411 redraw new selection unhighlighted |
|
3412 " |
|
3413 newSelection notNil ifTrue:[ |
|
3414 multipleSelectOk ifTrue:[ |
|
3415 "/ newSelection isCollection ifFalse:[ |
|
3416 "/ selection := OrderedCollection with:newSelection. |
|
3417 "/ ]. |
|
3418 selection do:[:line | |
|
3419 self redrawElement:line |
|
3420 ] |
|
3421 ] ifFalse:[ |
|
3422 self redrawElement:selection |
|
3423 ] |
|
3424 ] |
|
3425 |
|
3426 "Modified: 15.11.1996 / 16:58:46 / cg" |
|
3427 ! |
|
3428 |
|
3429 selection |
|
3430 "return the selection index or collection of indices (if multipleSelect is on)" |
|
3431 |
|
3432 ^ selection |
|
3433 ! |
|
3434 |
|
3435 selection:aNumberOrNil |
|
3436 "select line, aNumber or deselect if argument is nil; |
|
3437 scroll to make the selected line visible. |
|
3438 The model and/or actionBlock IS notified." |
|
3439 |
|
3440 |oldSelection| |
|
3441 |
|
3442 oldSelection := selection. |
|
3443 self setSelection:aNumberOrNil. |
|
3444 selection ~= oldSelection ifTrue:[ |
|
3445 self selectionChangedFrom:oldSelection |
|
3446 ] |
|
3447 |
|
3448 "Modified: / 7.8.1998 / 13:36:34 / cg" |
|
3449 ! |
|
3450 |
|
3451 selectionAsCollection |
|
3452 "return the selection as a collection of line numbers. |
|
3453 This allows users of this class to enumerate independent of |
|
3454 the multipleSelect style." |
|
3455 |
|
3456 selection isNil ifTrue:[^ #()]. |
|
3457 |
|
3458 "/ multipleSelectOk ifTrue:[ |
|
3459 "/ ^ (OrderedCollection new) add:selection; yourself. |
|
3460 "/ ]. |
|
3461 multipleSelectOk ifFalse:[ |
|
3462 ^ (OrderedCollection new) add:selection; yourself. |
|
3463 ]. |
|
3464 ^ selection |
|
3465 ! |
|
3466 |
|
3467 selectionChangedFrom:oldSelection |
|
3468 "selection has changed. Call actionblock and/or send changeMessage if defined" |
|
3469 |
|
3470 |changeArg actionArg nA| |
|
3471 |
|
3472 changeArg := actionArg := self argForChangeMessage. |
|
3473 |
|
3474 "/ |
|
3475 "/ the MVC way of doing things - notify model via changeMsg |
|
3476 "/ |
|
3477 multipleSelectOk ifFalse:[ |
|
3478 "/ ST80 sends 0 as index, if the same selection is reselected ... |
|
3479 selection == oldSelection ifTrue:[ |
|
3480 changeArg := 0 |
|
3481 ]. |
|
3482 ]. |
|
3483 self sendChangeMessageWith:changeArg. |
|
3484 |
|
3485 "/ |
|
3486 "/ the ST/X way of doing things - perform the actionBlock |
|
3487 "/ |
|
3488 actionBlock notNil ifTrue:[ |
|
3489 (actionBlock numArgs) == 1 ifTrue:[ |
|
3490 actionBlock value:actionArg |
|
3491 ] ifFalse:[ |
|
3492 actionBlock value |
|
3493 ] |
|
3494 ]. |
|
3495 |
|
3496 "Modified: 14.2.1997 / 16:49:09 / cg" |
|
3497 ! |
|
3498 |
|
3499 selectionDo:aBlock |
|
3500 "perform aBlock for each nr in the selection. |
|
3501 For single selection, it is called once for the items nr. |
|
3502 For multiple selections, it is called for each." |
|
3503 |
|
3504 selection notNil ifTrue:[ |
|
3505 multipleSelectOk ifTrue:[ |
|
3506 selection do:aBlock |
|
3507 ] ifFalse:[ |
|
3508 aBlock value:selection |
|
3509 ]. |
|
3510 ]. |
|
3511 |
|
3512 ! |
|
3513 |
|
3514 selectionValue |
|
3515 "return the selection value i.e. the text in the selected line. |
|
3516 For multiple selections a collection containing the entries is returned." |
|
3517 |
|
3518 multipleSelectOk ifTrue:[ |
|
3519 selection isNil ifTrue:[^ #()]. |
|
3520 ^ selection collect:[:nr | self at:nr] |
|
3521 ]. |
|
3522 selection isNil ifTrue:[^ nil]. |
|
3523 ^ self at:selection |
|
3524 ! |
|
3525 |
|
3526 selectionValueAsCollection |
|
3527 "return the selection values as a collection - allows selectionValues to |
|
3528 be enumerated independent of the multiSelect settings" |
|
3529 |
|
3530 selection isNil ifTrue:[^ #()]. |
|
3531 multipleSelectOk ifTrue:[ |
|
3532 ^ selection collect:[:nr | self at:nr] |
|
3533 ]. |
|
3534 ^ Array with:(self at:selection) |
|
3535 ! |
|
3536 |
|
3537 setSelectElement:anObject |
|
3538 "select the element with same printString as the argument, anObject. |
|
3539 Scroll to make the new selection visible. |
|
3540 *** No model and/or actionBlock notification is done here." |
|
3541 |
|
3542 |size lineNo coll| |
|
3543 |
|
3544 list isNil ifTrue:[ |
|
3545 ^ self |
|
3546 ]. |
|
3547 |
|
3548 multipleSelectOk ifTrue:[ |
|
3549 (size := anObject size) == 0 ifTrue:[ |
|
3550 ^ self setSelection:nil |
|
3551 ]. |
|
3552 coll := OrderedCollection new:size. |
|
3553 |
|
3554 anObject do:[:o| |
|
3555 items notNil ifTrue:[ |
|
3556 lineNo := items indexOf:o ifAbsent:nil. |
|
3557 ] ifFalse:[ |
|
3558 lineNo := list indexOf:(o printString) ifAbsent:nil |
|
3559 ]. |
|
3560 lineNo notNil ifTrue:[ |
|
3561 coll add:lineNo |
|
3562 ] |
|
3563 ]. |
|
3564 ^ self setSelection:coll |
|
3565 ]. |
|
3566 |
|
3567 items notNil ifTrue:[ |
|
3568 lineNo := items indexOf:anObject ifAbsent:nil |
|
3569 ] ifFalse:[ |
|
3570 lineNo := list indexOf:(anObject printString) ifAbsent:nil. |
|
3571 ]. |
|
3572 lineNo notNil ifTrue:[self setSelection:lineNo]. |
|
3573 ! |
|
3574 |
|
3575 setSelection:aNumberOrNil |
|
3576 "select line, aNumber or deselect if argument is nil; |
|
3577 scroll to make the selected line visible. |
|
3578 *** No model and/or actionBlock notification is done here." |
|
3579 |
|
3580 self selectWithoutScroll:aNumberOrNil. |
|
3581 selection notNil ifTrue:[ |
|
3582 self makeSelectionVisible |
|
3583 ] |
|
3584 |
|
3585 "Created: / 25.5.1996 / 12:23:18 / cg" |
|
3586 "Modified: / 7.8.1998 / 13:36:42 / cg" |
|
3587 ! |
|
3588 |
|
3589 toggleSelection:aNumber |
|
3590 "toggle selection-state of entry, aNumber. |
|
3591 *** No model and/or actionBlock notification is done here." |
|
3592 |
|
3593 (self isInSelection:aNumber) ifTrue:[ |
|
3594 self removeFromSelection:aNumber |
|
3595 ] ifFalse:[ |
|
3596 self addToSelection:aNumber |
|
3597 ] |
|
3598 |
|
3599 "Modified: 15.11.1996 / 17:02:08 / cg" |
|
3600 ! |
|
3601 |
|
3602 valueIsInSelection:someString |
|
3603 "return true, if someString is in the selection" |
|
3604 |
|
3605 |sel| |
|
3606 |
|
3607 selection isNil ifTrue:[^ false]. |
|
3608 sel := self selectionValue. |
|
3609 self numberOfSelections > 1 ifTrue:[ |
|
3610 ^ (sel includes:someString) |
|
3611 ]. |
|
3612 ^ (someString = sel) |
|
3613 ! ! |
|
3614 |
|
3615 !SelectionInListView class methodsFor:'documentation'! |
|
3616 |
|
3617 version |
|
3618 ^ '$Header: /cvs/stx/stx/libwidg/Attic/SelListV.st,v 1.150 1999-08-18 14:36:27 cg Exp $' |
|
3619 ! ! |
|