author | Claus Gittinger <cg@exept.de> |
Wed, 17 Jan 1996 12:18:40 +0100 | |
changeset 291 | 71f4a66b3281 |
parent 271 | 2554fcf338ec |
child 320 | b2ca0310ead0 |
permissions | -rw-r--r-- |
0 | 1 |
" |
5 | 2 |
COPYRIGHT (c) 1989 by Claus Gittinger |
59 | 3 |
All Rights Reserved |
0 | 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 |
||
125 | 13 |
'From Smalltalk/X, Version:2.10.5 on 8-may-1995 at 11:59:03 am'! |
105 | 14 |
|
0 | 15 |
ListView subclass:#SelectionInListView |
105 | 16 |
instanceVariableNames:'selection actionBlock enabled hilightFgColor hilightBgColor |
128 | 17 |
halfIntensityFgColor doubleClickActionBlock selectConditionBlock |
18 |
listAttributes multipleSelectOk clickLine initialSelectionMsg |
|
19 |
printItems oneItem useIndex hilightLevel hilightFrameColor |
|
20 |
ignoreReselect arrowLevel smallArrow keyActionStyle |
|
21 |
returnKeyActionStyle toggleSelect strikeOut iSearchString items |
|
22 |
doubleClickMsg' |
|
59 | 23 |
classVariableNames:'RightArrowShadowForm RightArrowLightForm RightArrowForm |
128 | 24 |
SmallRightArrowShadowForm SmallRightArrowLightForm |
25 |
DefaultForegroundColor DefaultBackgroundColor |
|
26 |
DefaultHilightForegroundColor DefaultHilightBackgroundColor |
|
27 |
DefaultHilightFrameColor DefaultHilightLevel DefaultFont |
|
28 |
DefaultRightArrowStyle DefaultRightArrowLevel |
|
29 |
DefaultDisabledForegroundColor DefaultShadowColor |
|
30 |
DefaultLightColor' |
|
105 | 31 |
poolDictionaries:'' |
32 |
category:'Views-Text' |
|
0 | 33 |
! |
34 |
||
7 | 35 |
!SelectionInListView class methodsFor:'documentation'! |
36 |
||
38 | 37 |
copyright |
38 |
" |
|
39 |
COPYRIGHT (c) 1989 by Claus Gittinger |
|
59 | 40 |
All Rights Reserved |
38 | 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 |
version |
|
271
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
52 |
^ '$Header: /cvs/stx/stx/libwidg/Attic/SelListV.st,v 1.48 1995-12-30 00:29:22 cg Exp $' |
38 | 53 |
! |
54 |
||
7 | 55 |
documentation |
56 |
" |
|
31 | 57 |
this one is a ListView with a selected line (which is shown highlighted) |
38 | 58 |
If multipleSelectionsOk is true, it is also allowed to shift-click multiple |
59 |
entries. |
|
63 | 60 |
If toggleSelect is true, clicking toggles (i.e. click on a seleted item |
61 |
will deselect). |
|
31 | 62 |
|
38 | 63 |
Whenever the selection changes, an action-block is evaluated, passing the |
64 |
current selection as argument. |
|
65 |
Currently, the selection can be nil, aNumber or a collection of numbers; |
|
66 |
this will change to be either nil or a collection, making selection handling |
|
70 | 67 |
easier in the future. (this stupid behavior is due to the multiple |
68 |
select feature being added later - the first implementation used to support |
|
69 |
only single selections). |
|
70 |
||
59 | 71 |
The actionBlock is called with the current selection (single number or |
72 |
collection of numbers) as argument. |
|
73 |
||
74 |
Also, to support ST-80 MVC-style use, the model (if nonNil) is notified |
|
155 | 75 |
by the change mechanism (performs changeMsg) and vice versa, the view |
76 |
updates if the model changes (with aspect of either #list or #selectionIndex). |
|
59 | 77 |
|
60 | 78 |
Before actually adding entries to the the selection, a checkBlock (if non-nil) is evaluated |
79 |
passing the number of the entry whch is about to be selected as argument. |
|
80 |
The select change operation is only done if this returns true. This allows |
|
59 | 81 |
interception of select, for example to query the user if he/she wants to save |
60 | 82 |
the old contents before (see uses in SystemBrowser and FileBrowser), or to |
83 |
disable individual entries. |
|
31 | 84 |
|
38 | 85 |
It is also possible to select entries with the keyboard; use the cursor up/ |
86 |
down keys to select prev/next, Home- and End-keys to select first/last. |
|
87 |
Use the return key to apply the double-click-action to the current selection. |
|
88 |
Also, alphabetic keys will select the next entry starting with that key. |
|
89 |
||
90 |
The keyboard behavior can be further controlled with the keyActionStyle |
|
91 |
instance variable (see SelectionInListView>>keyActionStyle:). |
|
92 |
||
59 | 93 |
Finally, ignoreReselect controls if pressing on an already selected item |
94 |
triggers the action or not. For some applications it is useful to allow |
|
95 |
reselects (for example, the SystemBrowsers method-list updates the |
|
96 |
source code in this case). |
|
38 | 97 |
|
60 | 98 |
Currently, some limited form of line attributes are supported. These |
99 |
are kept in the instance variable lineAttributes. |
|
100 |
This may change (using mechanisms similar to MultiColListEntry), so |
|
63 | 101 |
be prepared. (dont use the listAttributes instvar directly; if possible, |
102 |
use MultiColListEntry or subclasses of it. |
|
120 | 103 |
|
63 | 104 |
Although currently based on the listAttributes instVar, the implementation of |
120 | 105 |
text attributes will be changed in the near future (when Text/DisplayText are |
106 |
available). |
|
107 |
However, the protocol will probably be kept for backward compatibility |
|
108 |
(i.e. use #attributeAt: / #attributeAt:put etc. - at least, these are easy to find |
|
109 |
when migrating to the new attributed text handling). |
|
60 | 110 |
|
31 | 111 |
InstanceVariables: |
59 | 112 |
selection <misc> the current selection. nil, a number or collection of numbers |
31 | 113 |
|
59 | 114 |
actionBlock <Block> block to be evaluated on selection changes |
31 | 115 |
|
59 | 116 |
enabled <Boolean> true: selection changes allowed; false: ignore clicks |
31 | 117 |
|
59 | 118 |
hilightFgColor |
119 |
hilightBgColor <Color> how highlighted items are drawn |
|
31 | 120 |
|
59 | 121 |
halfIntensityColor <Color> foreground for disabled items |
31 | 122 |
|
59 | 123 |
selectConditionBlock <Block> if non-nil, this nlock can decide if selection is ok |
0 | 124 |
|
59 | 125 |
doubleClickActionBlock <Block> action to perform on double-click |
31 | 126 |
|
59 | 127 |
listAttributes dont use - will vanish |
31 | 128 |
|
59 | 129 |
hilightLevel <Integer> level to draw selections (i.e. for 3D effect) |
130 |
hilightFrameColor <Color> rectangle around highlighted items |
|
31 | 131 |
|
63 | 132 |
multipleSelectOk <Boolean> if true, multiple selections (with shift) are ok. |
133 |
default: false |
|
134 |
||
59 | 135 |
ignoreReselect <Boolean> if true, selecting same again does not trigger action; |
63 | 136 |
if false, every select triggers it. |
137 |
default: true |
|
138 |
||
139 |
toggleSelect <Boolean> if true, click toggles; |
|
140 |
if false, click selects. |
|
141 |
default: false |
|
0 | 142 |
|
59 | 143 |
arrowLevel <Integer> level to draw right-arrows (for submenus etc.) |
144 |
smallArrow <Boolean> if true, uses a small arrow bitmap |
|
31 | 145 |
|
119 | 146 |
listMsg if non-nil, use ST-80 style (model-access) |
147 |
initialSelectionMsg |
|
59 | 148 |
printItems |
149 |
oneItem |
|
31 | 150 |
|
59 | 151 |
keyActionStyle <Symbol> controls how to respond to keyboard selects |
31 | 152 |
|
125 | 153 |
returnKeyActionStyle <Symbol> controls how to respond to return key |
154 |
||
31 | 155 |
written spring/summer 89 by claus |
156 |
3D Jan 90 by claus |
|
38 | 157 |
multiselect Jun 92 by claus |
158 |
keyboard-select jun 94 by claus |
|
7 | 159 |
" |
119 | 160 |
! |
161 |
||
162 |
examples |
|
163 |
" |
|
164 |
SelectionInListView can be used both in the ST/X way, using action blocks |
|
165 |
or in the traditional mvc way. |
|
166 |
with actions: |
|
167 |
||
125 | 168 |
basic interface: |
169 |
||
128 | 170 |
|top slv| |
171 |
||
172 |
top := StandardSystemView new |
|
173 |
label:'select'; |
|
174 |
minExtent:100@100; |
|
175 |
maxExtent:300@400; |
|
176 |
extent:200@200. |
|
177 |
||
178 |
slv := SelectionInListView new. |
|
179 |
slv list:#('one' 'two' 'three'). |
|
180 |
slv action:[:index | Transcript showCr:'selected ' , index printString]. |
|
181 |
||
182 |
top add:slv in:(0.0@0.0 corner:1.0@1.0). |
|
183 |
top open |
|
125 | 184 |
|
185 |
||
186 |
get element instead of index: |
|
187 |
||
128 | 188 |
|top slv| |
189 |
||
190 |
top := StandardSystemView new |
|
191 |
label:'select'; |
|
192 |
minExtent:100@100; |
|
193 |
maxExtent:300@400; |
|
194 |
extent:200@200. |
|
195 |
||
196 |
slv := SelectionInListView new. |
|
197 |
slv list:#('one' 'two' 'three'). |
|
198 |
slv action:[:element | Transcript showCr:'selected ' , element printString]. |
|
199 |
slv useIndex:false. |
|
200 |
||
201 |
top add:slv in:(0.0@0.0 corner:1.0@1.0). |
|
202 |
top open |
|
125 | 203 |
|
204 |
||
205 |
concrete example; show filenames: |
|
206 |
(notice: normally, you would use a FileSelectionList) |
|
207 |
||
128 | 208 |
|top slv| |
209 |
||
210 |
top := StandardSystemView new |
|
211 |
label:'select'; |
|
212 |
minExtent:100@100; |
|
213 |
maxExtent:300@400; |
|
214 |
extent:200@200. |
|
215 |
||
216 |
slv := SelectionInListView new. |
|
217 |
slv list:(Filename currentDirectory directoryContents). |
|
218 |
slv action:[:index | |
|
219 |
Transcript showCr:'selected ' , index printString. |
|
220 |
Transcript showCr:' the value is: ', slv selectionValue]. |
|
221 |
||
222 |
top add:slv in:(0.0@0.0 corner:1.0@1.0). |
|
223 |
top open |
|
125 | 224 |
|
119 | 225 |
|
124
7abd3a234296
last version before changing to collection in multipleSelect mode
claus
parents:
120
diff
changeset
|
226 |
add a scrollbar: |
119 | 227 |
|
128 | 228 |
|top slv| |
229 |
||
230 |
top := StandardSystemView new |
|
231 |
label:'select'; |
|
232 |
minExtent:100@100; |
|
233 |
maxExtent:300@400; |
|
234 |
extent:200@200. |
|
235 |
||
236 |
slv := SelectionInListView new. |
|
237 |
slv list:(Filename currentDirectory directoryContents). |
|
238 |
slv action:[:index | Transcript showCr:'selected ' , index printString]. |
|
239 |
||
240 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
241 |
top open |
|
125 | 242 |
|
119 | 243 |
|
124
7abd3a234296
last version before changing to collection in multipleSelect mode
claus
parents:
120
diff
changeset
|
244 |
allow reselect (clicking on already selected entry): |
119 | 245 |
|
128 | 246 |
|top slv| |
247 |
||
248 |
top := StandardSystemView new |
|
249 |
label:'select'; |
|
250 |
minExtent:100@100; |
|
251 |
maxExtent:300@400; |
|
252 |
extent:200@200. |
|
253 |
||
254 |
slv := SelectionInListView new. |
|
255 |
slv list:(Filename currentDirectory directoryContents). |
|
256 |
slv action:[:index | Transcript showCr:'selected ' , index printString]. |
|
257 |
slv ignoreReselect:false. |
|
258 |
||
259 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
260 |
top open |
|
125 | 261 |
|
119 | 262 |
|
124
7abd3a234296
last version before changing to collection in multipleSelect mode
claus
parents:
120
diff
changeset
|
263 |
allow multiple selections: |
119 | 264 |
|
128 | 265 |
|top slv| |
266 |
||
267 |
top := StandardSystemView new |
|
268 |
label:'select'; |
|
269 |
minExtent:100@100; |
|
270 |
maxExtent:300@400; |
|
271 |
extent:200@200. |
|
272 |
||
273 |
slv := SelectionInListView new. |
|
274 |
slv list:(Filename currentDirectory directoryContents). |
|
275 |
slv action:[:indexList | Transcript showCr:'selected ' , indexList printString]. |
|
276 |
slv multipleSelectOk:true. |
|
277 |
||
278 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
279 |
top open |
|
125 | 280 |
|
281 |
||
282 |
same, not using index: |
|
283 |
||
128 | 284 |
|top slv| |
285 |
||
286 |
top := StandardSystemView new |
|
287 |
label:'select'; |
|
288 |
minExtent:100@100; |
|
289 |
maxExtent:300@400; |
|
290 |
extent:200@200. |
|
291 |
||
292 |
slv := SelectionInListView new. |
|
293 |
slv list:(Filename currentDirectory directoryContents). |
|
294 |
slv action:[:indexList | Transcript showCr:'selected ' , indexList printString]. |
|
295 |
slv multipleSelectOk:true; useIndex:false. |
|
296 |
||
297 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
298 |
top open |
|
125 | 299 |
|
119 | 300 |
|
124
7abd3a234296
last version before changing to collection in multipleSelect mode
claus
parents:
120
diff
changeset
|
301 |
strikeout mode (single): |
119 | 302 |
|
128 | 303 |
|top slv| |
304 |
||
305 |
top := StandardSystemView new |
|
306 |
label:'select'; |
|
307 |
minExtent:100@100; |
|
308 |
maxExtent:300@400; |
|
309 |
extent:200@200. |
|
310 |
||
311 |
slv := SelectionInListView new. |
|
312 |
slv list:(Filename currentDirectory directoryContents). |
|
313 |
slv action:[:index | Transcript showCr:'selected ' , index printString]. |
|
314 |
slv strikeOut:true. |
|
315 |
||
316 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
317 |
top open |
|
125 | 318 |
|
119 | 319 |
|
124
7abd3a234296
last version before changing to collection in multipleSelect mode
claus
parents:
120
diff
changeset
|
320 |
strikeout mode (multiple): |
119 | 321 |
|
128 | 322 |
|top slv| |
323 |
||
324 |
top := StandardSystemView new |
|
325 |
label:'select'; |
|
326 |
minExtent:100@100; |
|
327 |
maxExtent:300@400; |
|
328 |
extent:200@200. |
|
329 |
||
330 |
slv := SelectionInListView new. |
|
331 |
slv list:(Filename currentDirectory directoryContents). |
|
332 |
slv action:[:index | Transcript showCr:'selected ' , index printString]. |
|
333 |
slv strikeOut:true; multipleSelectOk:true. |
|
334 |
||
335 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
336 |
top open |
|
125 | 337 |
|
119 | 338 |
|
124
7abd3a234296
last version before changing to collection in multipleSelect mode
claus
parents:
120
diff
changeset
|
339 |
define what to do on double-click: |
119 | 340 |
|
128 | 341 |
|top slv| |
342 |
||
343 |
top := StandardSystemView new |
|
344 |
label:'select'; |
|
345 |
minExtent:100@100; |
|
346 |
maxExtent:300@400; |
|
347 |
extent:200@200. |
|
348 |
||
349 |
slv := SelectionInListView new. |
|
350 |
slv list:(Filename currentDirectory directoryContents). |
|
351 |
slv action:[:index | Transcript showCr:'selected ' , index printString]. |
|
352 |
slv doubleClickAction:[:index | Transcript showCr:'doubleclick on ' , index printString]. |
|
353 |
||
354 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
355 |
top open |
|
119 | 356 |
|
124
7abd3a234296
last version before changing to collection in multipleSelect mode
claus
parents:
120
diff
changeset
|
357 |
|
119 | 358 |
using a Model: |
359 |
||
128 | 360 |
|top slv model| |
361 |
||
362 |
model := Plug new. |
|
363 |
model respondTo:#getList with:[#('foo' 'bar' 'baz' 'hello')]. |
|
364 |
model respondTo:#initial with:[1]. |
|
365 |
model respondTo:#setSelection: with:[:arg | Transcript showCr:'model selected:', arg printString]. |
|
366 |
||
367 |
top := StandardSystemView new |
|
368 |
label:'select'; |
|
369 |
minExtent:100@100; |
|
370 |
maxExtent:300@400; |
|
371 |
extent:200@200. |
|
372 |
||
373 |
slv := SelectionInListView |
|
374 |
on:model |
|
375 |
aspect:#someAspect |
|
376 |
change:#setSelection: |
|
377 |
list:#getList |
|
378 |
initialSelection:#initial. |
|
379 |
||
380 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
381 |
top open |
|
119 | 382 |
|
383 |
notice, that the ST-80 behavaior on reselect is to send a selection change |
|
384 |
with an index of 0. |
|
385 |
||
386 |
||
125 | 387 |
same, with useIndex false: |
388 |
||
128 | 389 |
|top slv model| |
390 |
||
391 |
model := Plug new. |
|
392 |
model respondTo:#getList with:[#('foo' 'bar' 'baz' 'hello')]. |
|
393 |
model respondTo:#initial with:['bar']. |
|
394 |
model respondTo:#setSelection: with:[:arg | Transcript showCr:'model selected:', arg printString]. |
|
395 |
||
396 |
top := StandardSystemView new |
|
397 |
label:'select'; |
|
398 |
minExtent:100@100; |
|
399 |
maxExtent:300@400; |
|
400 |
extent:200@200. |
|
401 |
||
402 |
slv := SelectionInListView |
|
403 |
on:model |
|
404 |
aspect:#someAspect |
|
405 |
change:#setSelection: |
|
406 |
list:#getList |
|
407 |
initialSelection:#initial. |
|
408 |
slv useIndex:false. |
|
409 |
||
410 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
411 |
top open |
|
125 | 412 |
|
413 |
||
155 | 414 |
self changing list: |
415 |
(selectionInListView updates itself when button changes initial selection): |
|
416 |
||
417 |
|top slv model sel changeButton| |
|
418 |
||
419 |
sel := 'bar'. |
|
420 |
model := Plug new. |
|
421 |
model respondTo:#getList with:['getList' printNL. #('foo' 'bar' 'baz' 'hello')]. |
|
422 |
model respondTo:#initial with:['initial' printNL. sel]. |
|
423 |
model respondTo:#setSelection: with:[:arg | ('model selected:', arg) printNL. sel := arg]. |
|
424 |
||
425 |
changeButton := Button label:'change selection'. |
|
426 |
changeButton action:[sel := 'foo'. model changed:#initial]. |
|
427 |
changeButton open. |
|
428 |
||
429 |
top := StandardSystemView new |
|
430 |
label:'select'; |
|
431 |
minExtent:100@100; |
|
432 |
maxExtent:300@400; |
|
433 |
extent:200@200. |
|
434 |
||
435 |
slv := SelectionInListView |
|
436 |
on:model |
|
437 |
aspect:#someAspect |
|
438 |
change:#setSelection: |
|
439 |
list:#getList |
|
440 |
initialSelection:#initial. |
|
441 |
slv useIndex:false. |
|
442 |
||
443 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
444 |
top open |
|
445 |
||
446 |
||
119 | 447 |
using a SelectionInList-Model: |
448 |
(see how changes in the model (via list:...) are reflected in the view) |
|
449 |
||
128 | 450 |
|top slv model| |
451 |
||
452 |
model := SelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
|
453 |
model selection:'bar'. |
|
454 |
||
455 |
top := StandardSystemView new |
|
456 |
label:'select'; |
|
457 |
minExtent:100@100; |
|
458 |
maxExtent:300@400; |
|
459 |
extent:200@200. |
|
460 |
||
461 |
slv := SelectionInListView on:model. |
|
462 |
||
463 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
464 |
top open. |
|
465 |
||
466 |
model inspect |
|
125 | 467 |
|
468 |
||
469 |
two selectionInListViews on the same selectionInList model: |
|
470 |
||
128 | 471 |
|top1 slv1 top2 slv2 model| |
472 |
||
473 |
model := SelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
|
474 |
||
475 |
top1 := StandardSystemView new |
|
476 |
label:'select'; |
|
477 |
minExtent:100@100; |
|
478 |
maxExtent:300@400; |
|
479 |
extent:200@200. |
|
480 |
||
481 |
slv1 := SelectionInListView on:model. |
|
482 |
||
483 |
top1 add:(ScrollableView forView:slv1) in:(0.0@0.0 corner:1.0@1.0). |
|
484 |
top1 open. |
|
485 |
||
486 |
top2 := StandardSystemView new |
|
487 |
label:'select'; |
|
488 |
minExtent:100@100; |
|
489 |
maxExtent:300@400; |
|
490 |
extent:200@200. |
|
491 |
||
492 |
slv2 := SelectionInListView on:model. |
|
493 |
||
494 |
top2 add:(ScrollableView forView:slv2) in:(0.0@0.0 corner:1.0@1.0). |
|
495 |
top2 open. |
|
166 | 496 |
|
497 |
||
498 |
a MultiSelectionInList model: |
|
499 |
||
500 |
|top slv model| |
|
501 |
||
502 |
model := MultiSelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
|
503 |
model selection:#('foo' 'bar'). |
|
504 |
||
505 |
top := StandardSystemView new |
|
506 |
label:'select'; |
|
507 |
minExtent:100@100; |
|
508 |
maxExtent:300@400; |
|
509 |
extent:200@200. |
|
510 |
||
511 |
slv := SelectionInListView on:model. |
|
512 |
slv multipleSelectOk:true. |
|
513 |
||
514 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
515 |
top open. |
|
516 |
||
517 |
model inspect |
|
518 |
||
519 |
with strikeOut: |
|
520 |
||
521 |
|top slv model| |
|
522 |
||
523 |
model := MultiSelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
|
524 |
model selection:#('foo' 'bar'). |
|
525 |
||
526 |
top := StandardSystemView new |
|
527 |
label:'select'; |
|
528 |
minExtent:100@100; |
|
529 |
maxExtent:300@400; |
|
530 |
extent:200@200. |
|
531 |
||
532 |
slv := SelectionInListView on:model. |
|
533 |
slv multipleSelectOk:true; toggleSelect:true; strikeOut:true. |
|
534 |
||
535 |
top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
536 |
top open. |
|
537 |
||
538 |
model inspect |
|
119 | 539 |
" |
166 | 540 |
|
541 |
"Modified: 26.10.1995 / 16:42:02 / cg" |
|
7 | 542 |
! ! |
0 | 543 |
|
105 | 544 |
!SelectionInListView class methodsFor:'instance creation'! |
545 |
||
546 |
on:aModel printItems:print oneItem:one aspect:aspect change:change |
|
547 |
list:list menu:menu initialSelection:initial useIndex:useIndex |
|
548 |
||
549 |
"for ST-80 compatibility" |
|
550 |
||
551 |
^ (self new) on:aModel |
|
552 |
printItems:print |
|
553 |
oneItem:one |
|
554 |
aspect:aspect |
|
555 |
change:change |
|
556 |
list:list |
|
557 |
menu:menu |
|
558 |
initialSelection:initial |
|
559 |
useIndex:useIndex |
|
560 |
! |
|
561 |
||
125 | 562 |
on:aModel aspect:aspect change:change list:list initialSelection:initial |
563 |
^ self on:aModel |
|
564 |
printItems:true |
|
565 |
oneItem:false |
|
566 |
aspect:aspect |
|
567 |
change:change |
|
568 |
list:list |
|
569 |
menu:nil |
|
570 |
initialSelection:initial |
|
571 |
useIndex:true |
|
572 |
! |
|
573 |
||
105 | 574 |
on:aModel printItems:print oneItem:one aspect:aspect |
575 |
change:change list:list menu:menu initialSelection:initial |
|
576 |
||
577 |
"for ST-80 compatibility" |
|
578 |
||
119 | 579 |
^ self on:aModel |
105 | 580 |
printItems:print |
581 |
oneItem:one |
|
582 |
aspect:aspect |
|
583 |
change:change |
|
584 |
list:list |
|
585 |
menu:menu |
|
586 |
initialSelection:initial |
|
587 |
useIndex:false |
|
119 | 588 |
! |
589 |
||
590 |
on:aModel aspect:aspect change:change list:list menu:menu initialSelection:initial |
|
591 |
^ self on:aModel |
|
592 |
printItems:true |
|
593 |
oneItem:false |
|
594 |
aspect:aspect |
|
595 |
change:change |
|
596 |
list:list |
|
597 |
menu:menu |
|
598 |
initialSelection:initial |
|
599 |
useIndex:true |
|
105 | 600 |
! ! |
601 |
||
22 | 602 |
!SelectionInListView class methodsFor:'defaults'! |
603 |
||
125 | 604 |
defaultListMessage |
605 |
^ #list |
|
606 |
! |
|
607 |
||
608 |
defaultChangeMessage |
|
609 |
^ #selectionIndex: |
|
610 |
! |
|
611 |
||
612 |
defaultAspectMessage |
|
613 |
^ nil |
|
614 |
! |
|
615 |
||
616 |
defaultSelectionMessage |
|
617 |
^ #selectionIndex |
|
618 |
! |
|
619 |
||
105 | 620 |
rightArrowShadowFormOn:aDevice |
621 |
"return the form used for the right arrow light pixels (3D only)" |
|
622 |
||
623 |
|f| |
|
59 | 624 |
|
105 | 625 |
((aDevice == Display) and:[RightArrowShadowForm notNil]) ifTrue:[ |
626 |
^ RightArrowShadowForm |
|
627 |
]. |
|
628 |
f := Form fromFile:'RightArrowShadow.xbm' resolution:100 on:aDevice. |
|
629 |
f isNil ifTrue:[ |
|
630 |
f := Form width:16 height:16 fromArray:#[2r00000000 2r00000000 |
|
631 |
2r00000000 2r00000000 |
|
632 |
2r00000000 2r00000000 |
|
633 |
2r00000000 2r00000000 |
|
634 |
2r00000000 2r00000000 |
|
635 |
2r00000000 2r00000000 |
|
636 |
2r00000000 2r00000000 |
|
637 |
2r00000000 2r00000000 |
|
638 |
2r00000000 2r00010000 |
|
639 |
2r00000000 2r00100000 |
|
640 |
2r00000000 2r01000000 |
|
641 |
2r00000000 2r10000000 |
|
642 |
2r00000001 2r00000000 |
|
643 |
2r00000010 2r00000000 |
|
644 |
2r00000000 2r00000000 |
|
645 |
2r00000000 2r00000000] |
|
646 |
on:aDevice |
|
647 |
]. |
|
648 |
(aDevice == Display) ifTrue:[ |
|
649 |
RightArrowShadowForm := f |
|
650 |
]. |
|
651 |
^ f |
|
59 | 652 |
! |
653 |
||
22 | 654 |
rightArrowLightFormOn:aDevice |
655 |
"return the form used for the right arrow light pixels (3D only)" |
|
656 |
||
657 |
|f| |
|
658 |
||
659 |
((aDevice == Display) and:[RightArrowLightForm notNil]) ifTrue:[ |
|
59 | 660 |
^ RightArrowLightForm |
22 | 661 |
]. |
662 |
f := Form fromFile:'RightArrowLight.xbm' resolution:100 on:aDevice. |
|
663 |
f isNil ifTrue:[ |
|
59 | 664 |
f := Form width:16 height:16 fromArray:#[2r00000000 2r00000000 |
665 |
2r00000000 2r00000000 |
|
666 |
2r00000000 2r00000000 |
|
667 |
2r00000110 2r00000000 |
|
668 |
2r00000101 2r00000000 |
|
669 |
2r00000100 2r10000000 |
|
670 |
2r00000100 2r01000000 |
|
671 |
2r00000100 2r00100000 |
|
672 |
2r00000100 2r00000000 |
|
673 |
2r00000100 2r00000000 |
|
674 |
2r00000100 2r00000000 |
|
675 |
2r00000100 2r00000000 |
|
676 |
2r00000100 2r00000000 |
|
677 |
2r00000100 2r00000000 |
|
678 |
2r00000000 2r00000000 |
|
679 |
2r00000000 2r00000000] |
|
680 |
on:aDevice |
|
22 | 681 |
]. |
682 |
(aDevice == Display) ifTrue:[ |
|
59 | 683 |
RightArrowLightForm := f |
22 | 684 |
]. |
685 |
^ f |
|
686 |
! |
|
687 |
||
105 | 688 |
updateStyleCache |
689 |
DefaultDisabledForegroundColor := StyleSheet colorAt:'selectionDisabledForegroundColor'. |
|
690 |
DefaultHilightForegroundColor := StyleSheet colorAt:'selectionHilightForegroundColor'. |
|
691 |
DefaultHilightBackgroundColor := StyleSheet colorAt:'selectionHilightBackgroundColor'. |
|
692 |
DefaultHilightFrameColor := StyleSheet colorAt:'selectionHilightFrameColor'. |
|
693 |
DefaultHilightLevel := StyleSheet at:'selectionHilightLevel' default:0. |
|
694 |
DefaultRightArrowStyle := StyleSheet at:'selectionRightArrowStyle'. |
|
695 |
DefaultRightArrowLevel := StyleSheet at:'selectionRightArrowLevel'. |
|
696 |
DefaultForegroundColor := StyleSheet colorAt:'selectionForegroundColor'. |
|
697 |
DefaultBackgroundColor := StyleSheet colorAt:'selectionBackgroundColor'. |
|
698 |
DefaultShadowColor := StyleSheet colorAt:'selectionShadowColor'. |
|
699 |
DefaultLightColor := StyleSheet colorAt:'selectionLightColor'. |
|
700 |
DefaultFont := StyleSheet fontAt:'selectionFont'. |
|
146 | 701 |
RightArrowForm := nil. |
22 | 702 |
|
105 | 703 |
" |
704 |
self updateStyleCache |
|
705 |
" |
|
22 | 706 |
! |
707 |
||
708 |
rightArrowFormOn:aDevice |
|
709 |
"return the form used for the right arrow (non 3D)" |
|
710 |
||
146 | 711 |
|f bits| |
22 | 712 |
|
713 |
((aDevice == Display) and:[RightArrowForm notNil]) ifTrue:[ |
|
59 | 714 |
^ RightArrowForm |
22 | 715 |
]. |
716 |
f := Form fromFile:'RightArrow.xbm' resolution:100 on:aDevice. |
|
717 |
f isNil ifTrue:[ |
|
146 | 718 |
DefaultRightArrowStyle == #solid ifTrue:[ |
719 |
bits := #[2r00000000 2r00000000 |
|
720 |
2r00000000 2r00000000 |
|
721 |
2r00000000 2r00000000 |
|
722 |
2r00000010 2r00000000 |
|
723 |
2r00000011 2r00000000 |
|
724 |
2r00000011 2r10000000 |
|
725 |
2r00000011 2r11000000 |
|
726 |
2r00000011 2r11100000 |
|
727 |
2r00000011 2r11110000 |
|
728 |
2r00000011 2r11100000 |
|
729 |
2r00000011 2r11000000 |
|
730 |
2r00000011 2r10000000 |
|
731 |
2r00000011 2r00000000 |
|
732 |
2r00000010 2r00000000 |
|
733 |
2r00000000 2r00000000 |
|
734 |
2r00000000 2r00000000] |
|
735 |
] ifFalse:[ |
|
736 |
bits := #[2r00000000 2r00000000 |
|
737 |
2r00000000 2r00000000 |
|
738 |
2r00000000 2r00000000 |
|
739 |
2r00000110 2r00000000 |
|
740 |
2r00000101 2r00000000 |
|
741 |
2r00000100 2r10000000 |
|
742 |
2r00000100 2r01000000 |
|
743 |
2r00000100 2r00100000 |
|
744 |
2r00000100 2r00010000 |
|
745 |
2r00000100 2r00100000 |
|
746 |
2r00000100 2r01000000 |
|
747 |
2r00000100 2r10000000 |
|
748 |
2r00000101 2r00000000 |
|
749 |
2r00000110 2r00000000 |
|
750 |
2r00000000 2r00000000 |
|
751 |
2r00000000 2r00000000] |
|
752 |
]. |
|
753 |
f := Form width:16 height:16 fromArray:bits on:aDevice |
|
22 | 754 |
]. |
755 |
(aDevice == Display) ifTrue:[ |
|
59 | 756 |
RightArrowForm := f |
22 | 757 |
]. |
758 |
^ f |
|
31 | 759 |
! |
760 |
||
761 |
smallRightArrowLightFormOn:aDevice |
|
762 |
"return the form used for the small right arrow light pixels (3D only)" |
|
763 |
||
764 |
|f| |
|
765 |
||
766 |
((aDevice == Display) and:[SmallRightArrowLightForm notNil]) ifTrue:[ |
|
59 | 767 |
^ SmallRightArrowLightForm |
31 | 768 |
]. |
769 |
f := Form fromFile:'SmallRightArrowLight.xbm' resolution:100 on:aDevice. |
|
770 |
f isNil ifTrue:[ |
|
59 | 771 |
f := Form width:9 height:9 fromArray:#[2r00000000 2r00000000 |
772 |
2r01100000 2r00000000 |
|
773 |
2r01011000 2r00000000 |
|
774 |
2r01000110 2r00000000 |
|
775 |
2r01000000 2r00000000 |
|
776 |
2r01000000 2r00000000 |
|
777 |
2r01000000 2r00000000 |
|
778 |
2r01000000 2r00000000 |
|
779 |
2r00000000 2r00000000] |
|
780 |
on:aDevice |
|
31 | 781 |
]. |
782 |
(aDevice == Display) ifTrue:[ |
|
59 | 783 |
SmallRightArrowLightForm := f |
31 | 784 |
]. |
785 |
^ f |
|
786 |
! |
|
787 |
||
788 |
smallRightArrowShadowFormOn:aDevice |
|
789 |
"return the form used for the small right arrow light pixels (3D only)" |
|
790 |
||
791 |
|f| |
|
792 |
||
793 |
((aDevice == Display) and:[SmallRightArrowShadowForm notNil]) ifTrue:[ |
|
59 | 794 |
^ SmallRightArrowShadowForm |
31 | 795 |
]. |
796 |
f := Form fromFile:'SmallRightArrowShadow.xbm' resolution:100 on:aDevice. |
|
797 |
f isNil ifTrue:[ |
|
59 | 798 |
f := Form width:9 height:9 fromArray:#[2r00000000 2r00000000 |
799 |
2r00000000 2r00000000 |
|
800 |
2r00000000 2r00000000 |
|
801 |
2r00000000 2r00000000 |
|
802 |
2r00000001 2r00000000 |
|
803 |
2r00000110 2r00000000 |
|
804 |
2r00011000 2r00000000 |
|
805 |
2r00100000 2r00000000 |
|
806 |
2r00000000 2r00000000] |
|
807 |
on:aDevice |
|
31 | 808 |
]. |
809 |
(aDevice == Display) ifTrue:[ |
|
59 | 810 |
SmallRightArrowShadowForm := f |
31 | 811 |
]. |
812 |
^ f |
|
22 | 813 |
! ! |
814 |
||
125 | 815 |
!SelectionInListView methodsFor:'selections'! |
816 |
||
817 |
isInSelection:aNumber |
|
818 |
"return true, if line, aNumber is in the selection" |
|
819 |
||
820 |
selection isNil ifTrue:[^ false]. |
|
821 |
multipleSelectOk ifTrue:[ |
|
822 |
^ (selection includes:aNumber) |
|
823 |
]. |
|
824 |
^ (aNumber == selection) |
|
825 |
! |
|
826 |
||
827 |
selectWithoutScroll:aNumberOrNilOrCollection |
|
828 |
"select line, aNumber or deselect if argument is nil" |
|
829 |
||
830 |
|prevSelection newSelection| |
|
831 |
||
832 |
newSelection := aNumberOrNilOrCollection. |
|
833 |
newSelection notNil ifTrue:[ |
|
834 |
(self isValidSelection:newSelection) ifFalse:[ |
|
835 |
newSelection := nil |
|
836 |
] |
|
837 |
]. |
|
838 |
||
839 |
(newSelection = selection) ifTrue: [^ self]. |
|
840 |
||
841 |
" |
|
842 |
redraw old selection unhighlighted |
|
843 |
" |
|
844 |
selection notNil ifTrue: [ |
|
845 |
prevSelection := selection. |
|
846 |
selection := nil. |
|
847 |
multipleSelectOk ifTrue:[ |
|
848 |
prevSelection do:[:line | |
|
849 |
self redrawElement:line |
|
850 |
] |
|
851 |
] ifFalse:[ |
|
852 |
self redrawElement:prevSelection |
|
853 |
] |
|
854 |
]. |
|
855 |
||
856 |
selection := newSelection. |
|
857 |
||
858 |
" |
|
859 |
redraw new selection unhighlighted |
|
860 |
" |
|
861 |
newSelection notNil ifTrue:[ |
|
862 |
multipleSelectOk ifTrue:[ |
|
863 |
newSelection isCollection ifFalse:[ |
|
864 |
selection := OrderedCollection with:newSelection. |
|
865 |
]. |
|
866 |
selection do:[:line | |
|
867 |
self redrawElement:line |
|
868 |
] |
|
869 |
] ifFalse:[ |
|
870 |
self redrawElement:selection |
|
871 |
] |
|
872 |
] |
|
873 |
||
874 |
! |
|
875 |
||
876 |
makeSelectionVisible |
|
877 |
"scroll to make the selection line visible" |
|
878 |
||
879 |
|line| |
|
880 |
||
881 |
selection notNil ifTrue:[ |
|
882 |
multipleSelectOk ifTrue:[ |
|
166 | 883 |
selection isEmpty ifTrue:[^ self]. |
125 | 884 |
line := selection first. |
885 |
] ifFalse:[ |
|
886 |
line := selection |
|
887 |
]. |
|
888 |
self makeLineVisible:line |
|
889 |
] |
|
890 |
! |
|
891 |
||
892 |
selection:aNumberOrNil |
|
893 |
"select line, aNumber or deselect if argument is nil; |
|
894 |
scroll to make the selected line visible" |
|
895 |
||
896 |
self selectWithoutScroll:aNumberOrNil. |
|
897 |
selection notNil ifTrue:[self makeSelectionVisible] |
|
898 |
! |
|
899 |
||
900 |
selectionValue |
|
901 |
"return the selection value i.e. the text in the selected line. |
|
902 |
For multiple selections a collection containing the entries is returned." |
|
903 |
||
904 |
multipleSelectOk ifTrue:[ |
|
166 | 905 |
selection isNil ifTrue:[^ #()]. |
125 | 906 |
^ selection collect:[:nr | self at:nr] |
907 |
]. |
|
166 | 908 |
selection isNil ifTrue:[^ nil]. |
125 | 909 |
^ self at:selection |
910 |
! |
|
911 |
||
912 |
hasSelection |
|
913 |
"return true, if the view has a selection" |
|
914 |
||
915 |
^ selection notNil |
|
916 |
! |
|
917 |
||
918 |
selectElement:anObject |
|
919 |
"select the element with same printString as the argument, anObject. |
|
920 |
Scroll to make the new selection visible." |
|
921 |
||
922 |
|lineNo| |
|
923 |
||
924 |
list notNil ifTrue:[ |
|
925 |
items notNil ifTrue:[ |
|
926 |
lineNo := items indexOf:anObject ifAbsent:nil |
|
927 |
] ifFalse:[ |
|
928 |
lineNo := list indexOf:(anObject printString) ifAbsent:nil. |
|
929 |
]. |
|
930 |
lineNo notNil ifTrue:[self selection:lineNo] |
|
931 |
] |
|
932 |
! |
|
933 |
||
934 |
selection |
|
935 |
"return the selection index or collection of indices (if multipleSelect is on)" |
|
936 |
||
937 |
^ selection |
|
938 |
! |
|
939 |
||
940 |
selectionChangedFrom:oldSelection |
|
941 |
"selection has changed. Call actionblock and/or send changeMessage if defined" |
|
942 |
||
943 |
|arg| |
|
944 |
||
945 |
arg := self argForChangeMessage. |
|
946 |
" |
|
947 |
the ST/X way of doing things - perform actionBlock |
|
948 |
" |
|
949 |
actionBlock notNil ifTrue:[actionBlock value:arg]. |
|
950 |
" |
|
166 | 951 |
the MVC way of doing things - notify model via changeMsg |
125 | 952 |
" |
166 | 953 |
multipleSelectOk ifFalse:[ |
954 |
"/ ST80 sends 0 as index, if the same selection is reselected ... |
|
955 |
selection == oldSelection ifTrue:[ |
|
956 |
arg := 0 |
|
957 |
]. |
|
125 | 958 |
]. |
959 |
self sendChangeMessageWith:arg |
|
166 | 960 |
|
961 |
"Modified: 26.10.1995 / 16:33:54 / cg" |
|
125 | 962 |
! |
963 |
||
964 |
deselect |
|
965 |
"deselect" |
|
966 |
||
967 |
self selection:nil |
|
968 |
! |
|
969 |
||
970 |
deselectWithoutRedraw |
|
971 |
"deselect - no redraw" |
|
972 |
||
973 |
selection := nil |
|
974 |
! |
|
975 |
||
976 |
numberOfSelections |
|
977 |
"return the number of selected entries" |
|
978 |
||
979 |
|sz| |
|
980 |
||
981 |
selection isNil ifTrue:[^ 0]. |
|
982 |
sz := selection size. |
|
983 |
sz > 0 ifTrue:[^ sz]. |
|
984 |
^ 1 |
|
985 |
! |
|
986 |
||
987 |
valueIsInSelection:someString |
|
988 |
"return true, if someString is in the selection" |
|
989 |
||
990 |
|sel| |
|
991 |
||
992 |
selection isNil ifTrue:[^ false]. |
|
993 |
sel := self selectionValue. |
|
994 |
self numberOfSelections > 1 ifTrue:[ |
|
995 |
^ (sel includes:someString) |
|
996 |
]. |
|
997 |
^ (someString = sel) |
|
998 |
! |
|
999 |
||
1000 |
selectElementWithoutScroll:anObject |
|
1001 |
"select the element with same printString as the argument, anObject. |
|
1002 |
Do not scroll." |
|
1003 |
||
1004 |
|lineNo| |
|
1005 |
||
1006 |
list notNil ifTrue:[ |
|
1007 |
items notNil ifTrue:[ |
|
1008 |
lineNo := items indexOf:anObject ifAbsent:nil |
|
1009 |
] ifFalse:[ |
|
1010 |
lineNo := list indexOf:(anObject printString) ifAbsent:nil. |
|
1011 |
]. |
|
1012 |
lineNo notNil ifTrue:[self selectWithoutScroll:lineNo] |
|
1013 |
] |
|
1014 |
! |
|
1015 |
||
1016 |
nextAfterSelection |
|
1017 |
"return the index of the next selectable entry after the selection. |
|
1018 |
Wrap at end." |
|
1019 |
||
1020 |
|next| |
|
1021 |
||
1022 |
selection isNil ifTrue:[ |
|
1023 |
next := firstLineShown |
|
1024 |
] ifFalse:[ |
|
1025 |
selection size ~~ 0 ifTrue:[ |
|
1026 |
next := selection max + 1 |
|
1027 |
] ifFalse:[ |
|
1028 |
next := selection + 1 |
|
1029 |
]. |
|
1030 |
]. |
|
1031 |
(self isValidSelection:next) ifFalse:[ |
|
1032 |
next > self size ifTrue:[ |
|
1033 |
next := 1. |
|
1034 |
] ifFalse:[ |
|
1035 |
[next <= self size |
|
1036 |
and:[(self isValidSelection:next) not]] whileTrue:[ |
|
1037 |
next := next + 1 |
|
1038 |
]. |
|
1039 |
]. |
|
1040 |
]. |
|
1041 |
(self isValidSelection:next) ifFalse:[ |
|
1042 |
next := nil |
|
1043 |
]. |
|
1044 |
^ next |
|
1045 |
! |
|
1046 |
||
1047 |
previousBeforeSelection |
|
1048 |
"return the index of the previous selectable entry before the selection. |
|
1049 |
Wrap at beginning." |
|
1050 |
||
1051 |
|prev| |
|
1052 |
||
1053 |
selection isNil ifTrue:[ |
|
1054 |
prev := firstLineShown - 1 |
|
1055 |
] ifFalse:[ |
|
1056 |
selection size ~~ 0 ifTrue:[ |
|
1057 |
prev := selection min - 1 |
|
1058 |
] ifFalse:[ |
|
1059 |
prev := selection - 1 |
|
1060 |
]. |
|
1061 |
]. |
|
1062 |
(self isValidSelection:prev) ifFalse:[ |
|
1063 |
prev < 1 ifTrue:[ |
|
1064 |
prev := self size. |
|
1065 |
] ifFalse:[ |
|
1066 |
[prev >= 1 |
|
1067 |
and:[(self isValidSelection:prev) not]] whileTrue:[ |
|
1068 |
prev := prev - 1 |
|
1069 |
]. |
|
1070 |
]. |
|
1071 |
]. |
|
1072 |
(self isValidSelection:prev) ifFalse:[ |
|
1073 |
prev := nil |
|
1074 |
]. |
|
1075 |
^ prev |
|
1076 |
||
1077 |
! |
|
1078 |
||
1079 |
selectAll |
|
1080 |
"select all entries." |
|
1081 |
||
1082 |
|oldSelection| |
|
1083 |
||
1084 |
multipleSelectOk ifTrue:[ |
|
1085 |
oldSelection := selection. |
|
1086 |
selection := OrderedCollection withAll:(1 to:self size). |
|
1087 |
shown ifTrue:[self redraw]. |
|
1088 |
self selectionChangedFrom:oldSelection. |
|
1089 |
] |
|
1090 |
! |
|
1091 |
||
1092 |
toggleSelection:aNumber |
|
1093 |
"toggle selection-state of entry, aNumber" |
|
1094 |
||
1095 |
(self isInSelection:aNumber) ifTrue:[ |
|
1096 |
self removeFromSelection:aNumber |
|
1097 |
] ifFalse:[ |
|
1098 |
self addToSelection:aNumber |
|
1099 |
] |
|
1100 |
! |
|
1101 |
||
1102 |
selectNext |
|
1103 |
"select next line or first visible if there is currrently no selection. |
|
1104 |
Wrap at end." |
|
1105 |
||
1106 |
self selection:(self nextAfterSelection) |
|
1107 |
! |
|
1108 |
||
1109 |
selectPrevious |
|
1110 |
"select previous line or previous visible if there is currently no selection. |
|
1111 |
Wrap at beginning." |
|
1112 |
||
164 | 1113 |
self selection:(self previousBeforeSelection). |
1114 |
||
1115 |
"Modified: 26.9.1995 / 09:41:16 / stefan" |
|
125 | 1116 |
! |
1117 |
||
1118 |
selectionDo:aBlock |
|
1119 |
"perform aBlock for each nr in the selection. |
|
1120 |
For single selection, it is called once for the items nr. |
|
1121 |
For multiple selections, it is called for each." |
|
1122 |
||
1123 |
selection notNil ifTrue:[ |
|
1124 |
multipleSelectOk ifTrue:[ |
|
1125 |
selection do:aBlock |
|
1126 |
] ifFalse:[ |
|
1127 |
aBlock value:selection |
|
1128 |
]. |
|
1129 |
]. |
|
1130 |
||
1131 |
! |
|
1132 |
||
1133 |
selectionAsCollection |
|
1134 |
"return the selection as a collection of line numbers. |
|
1135 |
This allows users of this class to enumerate independent of |
|
1136 |
the multipleSelect style." |
|
1137 |
||
1138 |
selection isNil ifTrue:[^ #()]. |
|
1139 |
||
130 | 1140 |
"/ multipleSelectOk ifTrue:[ |
1141 |
"/ ^ (OrderedCollection new) add:selection; yourself. |
|
1142 |
"/ ]. |
|
1143 |
multipleSelectOk ifFalse:[ |
|
1144 |
^ (OrderedCollection new) add:selection; yourself. |
|
125 | 1145 |
]. |
1146 |
^ selection |
|
1147 |
! ! |
|
1148 |
||
0 | 1149 |
!SelectionInListView methodsFor:'redrawing'! |
1150 |
||
1151 |
redrawVisibleLine:visLineNr |
|
31 | 1152 |
"redraw a single line. |
1153 |
Must check, if any is in the selection and handle this case. |
|
1154 |
Otherwise draw using supers method." |
|
1155 |
||
131 | 1156 |
|listLine fg bg newFont id| |
0 | 1157 |
|
1158 |
fg := fgColor. |
|
1159 |
bg := bgColor. |
|
1160 |
listLine := self visibleLineToListLine:visLineNr. |
|
1161 |
listLine notNil ifTrue:[ |
|
59 | 1162 |
(self isInSelection:listLine) ifTrue:[ |
1163 |
^ self drawVisibleLineSelected:visLineNr |
|
1164 |
]. |
|
125 | 1165 |
|
1166 |
listAttributes notNil ifTrue:[ |
|
1167 |
(self line:listLine hasAttribute:#halfIntensity) ifTrue:[ |
|
60 | 1168 |
fg := halfIntensityFgColor |
125 | 1169 |
] ifFalse:[ |
1170 |
(self line:listLine hasAttribute:#disabled) ifTrue:[ |
|
1171 |
fg := halfIntensityFgColor |
|
1172 |
]. |
|
65 | 1173 |
]. |
125 | 1174 |
(self line:listLine hasAttribute:#bold) ifTrue:[ |
131 | 1175 |
newFont := font asBold. |
1176 |
(font bold |
|
1177 |
or:[id := (newFont on:device) fontId. |
|
1178 |
id isNil]) |
|
1179 |
ifTrue:[ |
|
125 | 1180 |
" |
1181 |
mhmh - what can be done, if the font is already bold ? |
|
1182 |
" |
|
1183 |
newFont := font. |
|
1184 |
fgColor brightness > 0.5 ifTrue:[ |
|
1185 |
fg := fgColor darkened "darkened". |
|
1186 |
] ifFalse:[ |
|
1187 |
fg := fgColor lightened "lightened" |
|
1188 |
]. |
|
1189 |
(fg brightness - bg brightness) abs < 0.25 ifTrue:[ |
|
1190 |
bgColor brightness > 0.5 ifTrue:[ |
|
1191 |
fg := fg darkened. |
|
1192 |
] ifFalse:[ |
|
1193 |
fg := fg lightened |
|
1194 |
]. |
|
1195 |
] |
|
77 | 1196 |
]. |
131 | 1197 |
id notNil ifTrue:[ |
1198 |
device setFont:id in:gcId. |
|
1199 |
]. |
|
125 | 1200 |
self drawVisibleLine:visLineNr with:fg and:bg. |
1201 |
device setFont:(font on:device) fontId in:gcId. |
|
1202 |
^ self |
|
1203 |
] |
|
63 | 1204 |
] |
31 | 1205 |
]. |
1206 |
^ self drawVisibleLine:visLineNr with:fg and:bg |
|
1207 |
! |
|
1208 |
||
125 | 1209 |
redrawElement:aNumber |
1210 |
"redraw an individual element" |
|
1211 |
||
1212 |
^ self redrawLine:aNumber |
|
1213 |
! |
|
1214 |
||
31 | 1215 |
drawVisibleLineSelected:visLineNr |
1216 |
"redraw a single line as selected." |
|
1217 |
||
1218 |
|listLine fg bg |
|
182
e59e03f374b2
fixed: highlight drawing wrong if frameColor was non-nil (os/2 style)
Claus Gittinger <cg@exept.de>
parents:
174
diff
changeset
|
1219 |
y "{ Class: SmallInteger }" |
e59e03f374b2
fixed: highlight drawing wrong if frameColor was non-nil (os/2 style)
Claus Gittinger <cg@exept.de>
parents:
174
diff
changeset
|
1220 |
y2 "{ Class: SmallInteger }" |
31 | 1221 |
wEdge| |
1222 |
||
1223 |
bg := hilightBgColor. |
|
1224 |
fg := hilightFgColor. |
|
1225 |
listLine := self visibleLineToListLine:visLineNr. |
|
1226 |
listLine notNil ifTrue:[ |
|
63 | 1227 |
strikeOut ifTrue:[ |
1228 |
self drawVisibleLine:visLineNr with:fgColor and:bgColor. |
|
1229 |
y := self yOfVisibleLine:visLineNr. |
|
1230 |
||
1231 |
self paint:fgColor. |
|
1232 |
y := y + (fontHeight // 2). |
|
1233 |
self displayLineFromX:0 y:y toX:width y:y. |
|
1234 |
^ self |
|
1235 |
]. |
|
1236 |
||
59 | 1237 |
self drawVisibleLine:visLineNr with:fg and:bg. |
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
182
diff
changeset
|
1238 |
y := (self yOfVisibleLine:visLineNr) - (lineSpacing//2). |
31 | 1239 |
|
59 | 1240 |
" |
1241 |
a line above and below |
|
1242 |
" |
|
1243 |
hilightFrameColor notNil ifTrue:[ |
|
182
e59e03f374b2
fixed: highlight drawing wrong if frameColor was non-nil (os/2 style)
Claus Gittinger <cg@exept.de>
parents:
174
diff
changeset
|
1244 |
hilightLevel == 0 ifTrue:[ |
e59e03f374b2
fixed: highlight drawing wrong if frameColor was non-nil (os/2 style)
Claus Gittinger <cg@exept.de>
parents:
174
diff
changeset
|
1245 |
self paint:hilightFrameColor. |
e59e03f374b2
fixed: highlight drawing wrong if frameColor was non-nil (os/2 style)
Claus Gittinger <cg@exept.de>
parents:
174
diff
changeset
|
1246 |
self displayLineFromX:0 y:y toX:width y:y. |
e59e03f374b2
fixed: highlight drawing wrong if frameColor was non-nil (os/2 style)
Claus Gittinger <cg@exept.de>
parents:
174
diff
changeset
|
1247 |
y2 := y + fontHeight - 1. |
e59e03f374b2
fixed: highlight drawing wrong if frameColor was non-nil (os/2 style)
Claus Gittinger <cg@exept.de>
parents:
174
diff
changeset
|
1248 |
self displayLineFromX:0 y:y2 toX:width y:y2. |
e59e03f374b2
fixed: highlight drawing wrong if frameColor was non-nil (os/2 style)
Claus Gittinger <cg@exept.de>
parents:
174
diff
changeset
|
1249 |
^ self |
e59e03f374b2
fixed: highlight drawing wrong if frameColor was non-nil (os/2 style)
Claus Gittinger <cg@exept.de>
parents:
174
diff
changeset
|
1250 |
] |
59 | 1251 |
]. |
31 | 1252 |
|
59 | 1253 |
" |
1254 |
an edge it around |
|
1255 |
" |
|
1256 |
(hilightLevel ~~ 0) ifTrue:[ |
|
1257 |
" |
|
1258 |
let edge start at left, extending to the full width |
|
1259 |
XXX: widthOfContents should be cached in ListView |
|
60 | 1260 |
(instead of recomputing all over) |
59 | 1261 |
" |
1262 |
wEdge := width-(2 * margin). |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
182
diff
changeset
|
1263 |
includesNonStrings ifFalse:[ |
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
182
diff
changeset
|
1264 |
wEdge := wEdge max:(self widthOfContents). |
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
182
diff
changeset
|
1265 |
]. |
59 | 1266 |
self drawEdgesForX:(margin - leftOffset) y:y |
224 | 1267 |
width:wEdge+leftOffset height:fontHeight |
59 | 1268 |
level:hilightLevel. |
31 | 1269 |
|
1270 |
||
155 | 1271 |
]. |
1272 |
^ self |
|
0 | 1273 |
]. |
31 | 1274 |
^ super drawVisibleLine:visLineNr with:fg and:bg |
155 | 1275 |
|
1276 |
"Modified: 31.8.1995 / 19:24:09 / claus" |
|
182
e59e03f374b2
fixed: highlight drawing wrong if frameColor was non-nil (os/2 style)
Claus Gittinger <cg@exept.de>
parents:
174
diff
changeset
|
1277 |
"Modified: 17.11.1995 / 09:36:25 / cg" |
105 | 1278 |
! |
1279 |
||
1280 |
redrawFromVisibleLine:startVisLineNr to:endVisLineNr |
|
1281 |
"redraw a range of lines. |
|
1282 |
Must check, if any is in the selection and handle this case. |
|
1283 |
Otherwise draw it en-bloque using supers method." |
|
1284 |
||
1285 |
|special sel |
|
1286 |
selNo "{ Class: SmallInteger }" | |
|
1287 |
||
1288 |
((selection isCollection) or:[listAttributes notNil]) ifTrue:[ |
|
1289 |
startVisLineNr to:endVisLineNr do:[:visLine | |
|
1290 |
self redrawVisibleLine:visLine |
|
1291 |
]. |
|
1292 |
^ self |
|
1293 |
]. |
|
1294 |
||
1295 |
"XXX only if -1/+1" |
|
1296 |
"/ hilightLevel ~~ 0 ifTrue:[ |
|
1297 |
"/ self paint:bgColor. |
|
1298 |
"/ self fillRectangleX:0 y:(self yOfVisibleLine:startVisLineNr)-1 width:width height:1 |
|
1299 |
"/ ]. |
|
1300 |
special := true. |
|
1301 |
selection isNil ifTrue:[ |
|
1302 |
special := false |
|
1303 |
] ifFalse:[ |
|
1304 |
sel := self listLineToVisibleLine:selection. |
|
1305 |
sel isNil ifTrue:[ |
|
1306 |
special := false |
|
1307 |
] ifFalse:[ |
|
1308 |
special := (sel between:startVisLineNr and:endVisLineNr) |
|
1309 |
] |
|
1310 |
]. |
|
1311 |
special ifFalse:[ |
|
1312 |
^ super redrawFromVisibleLine:startVisLineNr |
|
1313 |
to:endVisLineNr |
|
1314 |
]. |
|
1315 |
||
1316 |
selNo := sel. |
|
1317 |
selNo > startVisLineNr ifTrue:[ |
|
1318 |
super redrawFromVisibleLine:startVisLineNr to:(selNo - 1) |
|
1319 |
]. |
|
1320 |
self redrawVisibleLine:selNo. |
|
1321 |
selNo < endVisLineNr ifTrue:[ |
|
1322 |
super redrawFromVisibleLine:(selNo + 1) to:endVisLineNr |
|
1323 |
] |
|
1324 |
! |
|
1325 |
||
125 | 1326 |
redrawVisibleLine:visLineNr from:startCol to:endCol |
1327 |
"redraw from a startCol to endCol. |
|
1328 |
Must check, if its in the selection and handle this case." |
|
1329 |
||
1330 |
(self visibleLineNeedsSpecialCare:visLineNr) ifTrue:[ |
|
1331 |
^ self redrawVisibleLine:visLineNr |
|
1332 |
]. |
|
1333 |
super redrawVisibleLine:visLineNr from:startCol to:endCol |
|
1334 |
! |
|
1335 |
||
105 | 1336 |
drawRightArrowInVisibleLine:visLineNr |
1337 |
"draw a right arrow (for submenus). |
|
1338 |
This method is not used here, but provided for subclasses such |
|
1339 |
as menus or file-lists." |
|
1340 |
||
1341 |
|y x form form2 topLeftColor botRightColor t| |
|
1342 |
||
1343 |
x := width - 16. |
|
1344 |
y := (self yOfVisibleLine:visLineNr). |
|
1345 |
||
146 | 1346 |
(device depth == 1 or:[arrowLevel == 0]) ifTrue:[ |
105 | 1347 |
form := self class rightArrowFormOn:device. |
271
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1348 |
form notNil ifTrue:[ |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1349 |
y := y + ((font height - form height) // 2). |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1350 |
(self isInSelection:(self visibleLineToListLine:visLineNr)) ifTrue:[ |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1351 |
self foreground:hilightFgColor |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1352 |
] ifFalse:[ |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1353 |
self foreground:fgColor. |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1354 |
]. |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1355 |
self displayForm:form x:x y:y. |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1356 |
] |
105 | 1357 |
] ifFalse:[ |
1358 |
smallArrow ifTrue:[ |
|
1359 |
form := self class smallRightArrowLightFormOn:device. |
|
1360 |
form2 := self class smallRightArrowShadowFormOn:device. |
|
1361 |
] ifFalse:[ |
|
1362 |
form := self class rightArrowLightFormOn:device. |
|
1363 |
form2 := self class rightArrowShadowFormOn:device. |
|
1364 |
]. |
|
271
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1365 |
(form isNil or:[form2 isNil]) ifTrue:[ |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1366 |
"/ very bad conditions |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1367 |
^ self |
2554fcf338ec
handle bad cases where the (arrow) bitmaps are not available
Claus Gittinger <cg@exept.de>
parents:
224
diff
changeset
|
1368 |
]. |
105 | 1369 |
y := y + ((font height - form height) // 2). |
1370 |
||
1371 |
topLeftColor := lightColor. |
|
1372 |
botRightColor := shadowColor. |
|
1373 |
||
1374 |
"openwin arrow stays down" |
|
130 | 1375 |
styleSheet name ~~ #openwin ifTrue:[ |
105 | 1376 |
(self isInSelection:(self visibleLineToListLine:visLineNr)) ifTrue:[ |
1377 |
t := topLeftColor. |
|
1378 |
topLeftColor := botRightColor. |
|
1379 |
botRightColor := t. |
|
1380 |
] |
|
1381 |
]. |
|
1382 |
arrowLevel < 0 ifTrue:[ |
|
1383 |
t := topLeftColor. |
|
1384 |
topLeftColor := botRightColor. |
|
1385 |
botRightColor := t. |
|
1386 |
]. |
|
1387 |
||
1388 |
"/ self foreground:topLeftColor. |
|
1389 |
self paint:topLeftColor. |
|
1390 |
self displayForm:form x:x y:y. |
|
1391 |
"/ self foreground:botRightColor. |
|
1392 |
self paint:botRightColor. |
|
1393 |
self displayForm:form2 x:x y:y. |
|
1394 |
] |
|
1395 |
! |
|
1396 |
||
1397 |
redrawVisibleLine:visLineNr col:colNr |
|
1398 |
"redraw a single character. |
|
1399 |
Must check, if its in the selection and handle this case." |
|
1400 |
||
1401 |
(self visibleLineNeedsSpecialCare:visLineNr) ifTrue:[ |
|
1402 |
^ self redrawVisibleLine:visLineNr |
|
1403 |
]. |
|
1404 |
super redrawVisibleLine:visLineNr col:colNr |
|
1405 |
! |
|
1406 |
||
1407 |
redrawVisibleLine:visLineNr from:startCol |
|
1408 |
"redraw from a col to the right end. |
|
1409 |
Must check, if its in the selection and handle this case." |
|
1410 |
||
1411 |
(self visibleLineNeedsSpecialCare:visLineNr) ifTrue:[ |
|
1412 |
^ self redrawVisibleLine:visLineNr |
|
1413 |
]. |
|
1414 |
super redrawVisibleLine:visLineNr from:startCol |
|
1415 |
! ! |
|
1416 |
||
1417 |
!SelectionInListView methodsFor:'private'! |
|
1418 |
||
1419 |
getListFromModel |
|
119 | 1420 |
"if I have a model and a listMsg, get my list from it" |
1421 |
||
105 | 1422 |
|text| |
1423 |
||
119 | 1424 |
model notNil ifTrue:[ |
1425 |
listMsg notNil ifTrue:[ |
|
1426 |
items := model perform:listMsg. |
|
1427 |
items notNil ifTrue:[ |
|
1428 |
printItems ifTrue:[ |
|
1429 |
text := items collect:[:element | element printString] |
|
1430 |
] ifFalse:[ |
|
1431 |
text := items |
|
1432 |
]. |
|
128 | 1433 |
"/ text notNil ifTrue:[ |
1434 |
"/ text := text asStringCollection. |
|
1435 |
"/ ] |
|
119 | 1436 |
]. |
133 | 1437 |
self list:text keepSelection:true. "/ expandTabs:false |
119 | 1438 |
]. |
1439 |
]. |
|
1440 |
! |
|
1441 |
||
1442 |
getSelectionFromModel |
|
1443 |
"if I have a model and an initialSelectionMsg, get my selection from it" |
|
1444 |
||
1445 |
|sel| |
|
1446 |
||
1447 |
model notNil ifTrue:[ |
|
1448 |
initialSelectionMsg notNil ifTrue:[ |
|
1449 |
sel := model perform:initialSelectionMsg. |
|
1450 |
useIndex ifTrue:[ |
|
1451 |
self selection:sel |
|
105 | 1452 |
] ifFalse:[ |
119 | 1453 |
self selectElement:sel. |
105 | 1454 |
]. |
119 | 1455 |
] |
105 | 1456 |
]. |
125 | 1457 |
! |
1458 |
||
1459 |
argForChangeMessage |
|
1460 |
"return the argument for a selectionChange; |
|
1461 |
depending on the setting of useIndex, this is either the numeric |
|
1462 |
index of the selection or the value (i.e. the string)" |
|
1463 |
||
1464 |
useIndex ~~ false ifTrue:[ "/ i.e. everything except false |
|
166 | 1465 |
multipleSelectOk ifTrue:[ |
1466 |
selection isNil ifTrue:[ |
|
1467 |
^ #() |
|
1468 |
]. |
|
1469 |
]. |
|
125 | 1470 |
^ selection |
1471 |
]. |
|
166 | 1472 |
|
125 | 1473 |
printItems ifFalse:[ |
1474 |
^ self selectionValue |
|
1475 |
]. |
|
1476 |
||
1477 |
items notNil ifTrue:[ |
|
1478 |
multipleSelectOk ifTrue:[ |
|
1479 |
^ selection collect:[:nr | items at:nr] |
|
1480 |
]. |
|
1481 |
^ items at:selection |
|
1482 |
]. |
|
1483 |
||
1484 |
^ nil "/ cannot happen |
|
166 | 1485 |
|
1486 |
"Modified: 26.10.1995 / 16:28:13 / cg" |
|
125 | 1487 |
! |
1488 |
||
1489 |
isValidSelection:aNumberOrCollection |
|
1490 |
"return true, if aNumber is ok as a selection index" |
|
1491 |
||
1492 |
aNumberOrCollection isNil ifTrue:[^ false]. |
|
1493 |
||
1494 |
(aNumberOrCollection isCollection) ifTrue:[ |
|
1495 |
multipleSelectOk ifFalse:[^ false]. |
|
1496 |
aNumberOrCollection do:[:index | |
|
1497 |
(index between:1 and:self size) ifFalse:[^ false]. |
|
1498 |
]. |
|
1499 |
^ true. |
|
1500 |
] ifFalse:[ |
|
1501 |
^ (aNumberOrCollection between:1 and:self size). |
|
1502 |
]. |
|
1503 |
||
1504 |
! |
|
1505 |
||
1506 |
positionToSelectionX:x y:y |
|
1507 |
"given a click position, return the selection lineNo" |
|
1508 |
||
1509 |
|visibleLine| |
|
1510 |
||
1511 |
(x between:0 and:width) ifTrue:[ |
|
1512 |
(y between:0 and:height) ifTrue:[ |
|
1513 |
visibleLine := self visibleLineOfY:y. |
|
1514 |
^ self visibleLineToListLine:visibleLine |
|
1515 |
] |
|
1516 |
]. |
|
1517 |
^ nil |
|
1518 |
! |
|
1519 |
||
1520 |
widthForScrollBetween:start and:end |
|
1521 |
"has to be redefined since WHOLE line is inverted/modified sometimes" |
|
1522 |
||
1523 |
| anySelectionInRange | |
|
1524 |
||
1525 |
selection notNil ifTrue:[ |
|
1526 |
multipleSelectOk ifTrue:[ |
|
1527 |
anySelectionInRange := false. |
|
1528 |
selection do:[:s | |
|
1529 |
(s between:start and:end) ifTrue:[ |
|
1530 |
anySelectionInRange := true |
|
1531 |
] |
|
1532 |
] |
|
1533 |
] ifFalse:[ |
|
1534 |
anySelectionInRange := selection between:start and:end |
|
1535 |
] |
|
1536 |
] ifFalse:[ |
|
1537 |
anySelectionInRange := false |
|
1538 |
]. |
|
1539 |
||
1540 |
anySelectionInRange ifTrue:[ |
|
1541 |
^ width |
|
1542 |
" |
|
1543 |
self is3D ifFalse:[ |
|
1544 |
^ width |
|
1545 |
]. |
|
130 | 1546 |
( #(next openwin) includes:styleSheet name) ifTrue:[ |
125 | 1547 |
^ width |
1548 |
]. |
|
1549 |
viewBackground = background ifFalse:[ |
|
1550 |
^ width |
|
1551 |
] |
|
1552 |
" |
|
1553 |
]. |
|
1554 |
^ super widthForScrollBetween:start and:end |
|
1555 |
! |
|
1556 |
||
1557 |
visibleLineNeedsSpecialCare:visLineNr |
|
1558 |
|listLine| |
|
1559 |
||
1560 |
listLine := self visibleLineToListLine:visLineNr. |
|
1561 |
listLine isNil ifTrue:[^ false]. |
|
1562 |
(self isInSelection:listLine) ifTrue:[^ true]. |
|
1563 |
listAttributes notNil ifTrue:[ |
|
1564 |
(listLine <= listAttributes size) ifTrue:[ |
|
1565 |
^ (listAttributes at:listLine) notNil |
|
1566 |
] |
|
1567 |
]. |
|
1568 |
^ false |
|
1569 |
! |
|
1570 |
||
1571 |
checkRemovingSelection:lineNr |
|
1572 |
"when a line is removed, we have to adjust selection" |
|
1573 |
||
1574 |
|newSelection| |
|
1575 |
||
1576 |
selection notNil ifTrue:[ |
|
1577 |
multipleSelectOk ifTrue:[ |
|
1578 |
newSelection := OrderedCollection new. |
|
1579 |
selection do:[:sel | |
|
1580 |
sel < lineNr ifTrue:[ |
|
1581 |
newSelection add:sel |
|
1582 |
] ifFalse:[ |
|
1583 |
sel > lineNr ifTrue:[ |
|
1584 |
newSelection add:(sel - 1) |
|
1585 |
] |
|
1586 |
"otherwise remove it from the selection" |
|
1587 |
] |
|
1588 |
]. |
|
1589 |
newSelection size == 0 ifTrue:[ |
|
1590 |
selection := nil |
|
1591 |
] ifFalse:[ |
|
1592 |
selection := newSelection |
|
1593 |
] |
|
1594 |
] ifFalse:[ |
|
1595 |
selection == lineNr ifTrue:[ |
|
1596 |
selection := nil |
|
1597 |
] ifFalse:[ |
|
1598 |
selection > lineNr ifTrue:[ |
|
1599 |
selection := selection - 1 |
|
1600 |
] |
|
1601 |
] |
|
1602 |
] |
|
1603 |
] |
|
1604 |
! |
|
1605 |
||
1606 |
scrollSelectDown |
|
1607 |
"auto scroll action; scroll and reinstall timed-block" |
|
1608 |
||
1609 |
self scrollDown. |
|
1610 |
Processor addTimedBlock:autoScrollBlock afterSeconds:autoScrollDeltaT. |
|
1611 |
! |
|
1612 |
||
1613 |
scrollSelectUp |
|
1614 |
"auto scroll action; scroll and reinstall timed-block" |
|
1615 |
||
1616 |
self scrollUp. |
|
1617 |
Processor addTimedBlock:autoScrollBlock afterSeconds:autoScrollDeltaT. |
|
1618 |
! ! |
|
1619 |
||
1620 |
!SelectionInListView methodsFor:'event handling'! |
|
1621 |
||
1622 |
buttonRelease:button x:x y:y |
|
1623 |
"stop any autoscroll" |
|
1624 |
||
1625 |
self stopAutoScroll |
|
1626 |
! |
|
1627 |
||
1628 |
buttonPress:button x:x y:y |
|
1629 |
|oldSelection listLineNr| |
|
1630 |
||
1631 |
((button == 1) or:[button == #select]) ifTrue:[ |
|
1632 |
enabled ifTrue:[ |
|
1633 |
listLineNr := self visibleLineToListLine:(self visibleLineOfY:y). |
|
1634 |
listLineNr notNil ifTrue:[ |
|
1635 |
(toggleSelect |
|
1636 |
and:[self isInSelection:listLineNr]) ifTrue:[ |
|
1637 |
oldSelection := selection copy. |
|
1638 |
self removeFromSelection:listLineNr |
|
1639 |
] ifFalse:[ |
|
1640 |
(self line:listLineNr hasAttribute:#disabled) ifTrue:[^ self]. |
|
1641 |
||
1642 |
(selectConditionBlock notNil |
|
1643 |
and:[(selectConditionBlock value:listLineNr) not]) ifTrue:[^ self]. |
|
1644 |
||
1645 |
(toggleSelect and:[multipleSelectOk]) ifTrue:[ |
|
1646 |
oldSelection := selection copy. |
|
1647 |
self addToSelection:listLineNr |
|
1648 |
] ifFalse:[ |
|
1649 |
oldSelection := selection copy. |
|
1650 |
self selectWithoutScroll:listLineNr. |
|
1651 |
]. |
|
1652 |
]. |
|
1653 |
((ignoreReselect not and:[selection notNil]) |
|
1654 |
or:[selection ~= oldSelection]) ifTrue:[ |
|
1655 |
self selectionChangedFrom:oldSelection. |
|
1656 |
]. |
|
1657 |
clickLine := listLineNr |
|
1658 |
]. |
|
1659 |
] |
|
1660 |
] ifFalse:[ |
|
1661 |
super buttonPress:button x:x y:y |
|
1662 |
] |
|
1663 |
! |
|
1664 |
||
1665 |
sizeChanged:how |
|
1666 |
"if there is a selection, make certain, its visible |
|
1667 |
after the sizechange" |
|
1668 |
||
1669 |
|first wasAtEnd| |
|
1670 |
||
1671 |
wasAtEnd := (firstLineShown + nFullLinesShown) >= self size. |
|
1672 |
||
1673 |
super sizeChanged:how. |
|
1674 |
||
1675 |
shown ifTrue:[ |
|
1676 |
selection notNil ifTrue:[ |
|
1677 |
multipleSelectOk ifTrue:[ |
|
1678 |
first := selection first |
|
1679 |
] ifFalse:[ |
|
1680 |
first := selection |
|
1681 |
]. |
|
1682 |
first notNil ifTrue:[self makeLineVisible:first] |
|
1683 |
] ifFalse:[ |
|
1684 |
" |
|
1685 |
if we where at the end before, move to the end again. |
|
1686 |
Still to be seen, if this is better in real life ... |
|
1687 |
" |
|
1688 |
wasAtEnd ifTrue:[ |
|
1689 |
"at end" |
|
1690 |
self scrollToBottom |
|
1691 |
] |
|
1692 |
] |
|
1693 |
] |
|
1694 |
! |
|
1695 |
||
1696 |
keyPress:key x:x y:y |
|
1697 |
"handle keyboard input" |
|
1698 |
||
132 | 1699 |
<resource: #keyboard ( #BeginOfText #EndOfText ) > |
1700 |
||
210
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1701 |
|index |
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1702 |
searchIndex "{Class: SmallInteger}" |
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1703 |
startSearch "{Class: SmallInteger}" |
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1704 |
backSearch searchPrefix| |
125 | 1705 |
|
1706 |
(key == #CursorUp) ifTrue:[ |
|
128 | 1707 |
index := self previousBeforeSelection. |
1708 |
self key:key select:index x:x y:y. |
|
1709 |
^ self |
|
125 | 1710 |
]. |
1711 |
(key == #CursorDown) ifTrue:[ |
|
128 | 1712 |
index := self nextAfterSelection. |
1713 |
self key:key select:index x:x y:y. |
|
1714 |
^ self |
|
125 | 1715 |
]. |
1716 |
"/ |
|
1717 |
"/ stupid: Home and End are cought in ScrollableView |
|
1718 |
"/ we normally do not get them ... |
|
1719 |
"/ (need to call handlesKey: from there ... |
|
1720 |
"/ ... and implement it here) |
|
1721 |
"/ |
|
132 | 1722 |
(key == #BeginOfText) ifTrue:[ |
128 | 1723 |
self key:key select:1 x:x y:y. |
1724 |
^ self |
|
125 | 1725 |
]. |
132 | 1726 |
(key == #EndOfText) ifTrue:[ |
128 | 1727 |
index := self size. |
1728 |
self key:key select:index x:x y:y. |
|
1729 |
^ self |
|
125 | 1730 |
]. |
1731 |
key == #Return ifTrue:[ |
|
128 | 1732 |
returnKeyActionStyle == #doubleClick ifTrue:[ |
1733 |
selection notNil ifTrue:[ |
|
1734 |
self doubleClicked |
|
1735 |
]. |
|
1736 |
^ self |
|
1737 |
]. |
|
1738 |
returnKeyActionStyle ~~ #pass ifTrue:[ |
|
1739 |
^ self |
|
1740 |
]. |
|
125 | 1741 |
]. |
1742 |
||
1743 |
" |
|
1744 |
alphabetic keys: search for next entry |
|
1745 |
starting with keys character. If shift is pressed, search backward |
|
1746 |
" |
|
1747 |
(self size > 0 |
|
1748 |
and:[key isCharacter |
|
1749 |
and:[key isLetter]]) ifTrue:[ |
|
128 | 1750 |
keyActionStyle isNil ifTrue:[^ self]. |
1751 |
keyActionStyle == #pass ifFalse:[ |
|
1752 |
searchPrefix := key asLowercase asString. |
|
125 | 1753 |
|
1754 |
"/ ... isISearch... ifFalse:[ |
|
1755 |
"/ iSearchString := '' |
|
1756 |
"/ ] ifTrue:[ |
|
1757 |
"/ iSearchString := iSearchString , searchPrefix. |
|
1758 |
"/ searchPrefix := iSearchString |
|
1759 |
"/ ]. |
|
1760 |
||
128 | 1761 |
backSearch := device shiftDown. |
1762 |
backSearch ifTrue:[ |
|
1763 |
selection notNil ifTrue:[ |
|
1764 |
selection size > 0 ifTrue:[ |
|
1765 |
startSearch := selection first - 1 |
|
1766 |
] ifFalse:[ |
|
1767 |
startSearch := selection - 1 |
|
1768 |
] |
|
1769 |
] ifFalse:[ |
|
1770 |
startSearch := self size |
|
1771 |
]. |
|
1772 |
startSearch < 1 ifTrue:[ |
|
1773 |
startSearch := self size. |
|
1774 |
]. |
|
1775 |
] ifFalse:[ |
|
1776 |
selection notNil ifTrue:[ |
|
1777 |
selection size > 0 ifTrue:[ |
|
1778 |
startSearch := selection last + 1 |
|
1779 |
] ifFalse:[ |
|
1780 |
startSearch := selection + 1 |
|
1781 |
] |
|
1782 |
] ifFalse:[ |
|
1783 |
startSearch := 1 |
|
1784 |
]. |
|
1785 |
startSearch > self size ifTrue:[ |
|
1786 |
startSearch := 1. |
|
1787 |
]. |
|
1788 |
]. |
|
210
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1789 |
searchIndex := startSearch. |
128 | 1790 |
[true] whileTrue:[ |
210
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1791 |
(((self at:searchIndex) asString) withoutSeparators asLowercase startsWith:searchPrefix) ifTrue:[ |
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1792 |
searchIndex = selection ifTrue:[^ self]. |
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1793 |
^ self key:key select:searchIndex x:x y:y |
128 | 1794 |
]. |
1795 |
backSearch ifTrue:[ |
|
210
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1796 |
searchIndex := searchIndex - 1. |
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1797 |
searchIndex < 1 ifTrue:[searchIndex := self size] |
128 | 1798 |
] ifFalse:[ |
210
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1799 |
searchIndex := searchIndex + 1. |
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1800 |
searchIndex > self size ifTrue:[searchIndex := 1]. |
128 | 1801 |
]. |
210
f7d44c195776
search fixed for lines which start with a separator
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1802 |
searchIndex == startSearch ifTrue:[ |
128 | 1803 |
^ self |
1804 |
] |
|
1805 |
] |
|
1806 |
]. |
|
125 | 1807 |
]. |
1808 |
^ super keyPress:key x:x y:y |
|
1809 |
! |
|
1810 |
||
1811 |
buttonMotion:buttonMask x:x y:y |
|
1812 |
"mouse-move while button was pressed - handle selection changes" |
|
1813 |
||
1814 |
|movedVisibleLine movedLine delta oldSelection oldSelCount| |
|
1815 |
||
1816 |
"is it the select or 1-button ?" |
|
1817 |
(device buttonMotionMask:buttonMask includesButton:#select) ifFalse:[ |
|
1818 |
(device buttonMotionMask:buttonMask includesButton:1) ifFalse:[ |
|
1819 |
^ self |
|
1820 |
]. |
|
1821 |
]. |
|
1822 |
||
1823 |
clickLine isNil ifTrue:[^ self]. |
|
1824 |
||
1825 |
"if moved outside of view, start autoscroll" |
|
1826 |
(y < 0) ifTrue:[ |
|
1827 |
self compressMotionEvents:false. |
|
1828 |
self startAutoScrollUp:y. |
|
1829 |
^ self |
|
1830 |
]. |
|
1831 |
(y > height) ifTrue:[ |
|
1832 |
self compressMotionEvents:false. |
|
1833 |
self startAutoScrollDown:(y - height). |
|
1834 |
^ self |
|
1835 |
]. |
|
1836 |
||
1837 |
"move inside - stop autoscroll if any" |
|
1838 |
self stopAutoScroll. |
|
1839 |
||
1840 |
movedVisibleLine := self visibleLineOfY:y. |
|
1841 |
movedLine := self visibleLineToAbsoluteLine:movedVisibleLine. |
|
1842 |
(movedLine == clickLine) ifTrue:[^ self]. |
|
1843 |
||
1844 |
multipleSelectOk ifTrue:[ |
|
1845 |
delta := (clickLine < movedLine) ifTrue:[1] ifFalse:[-1]. |
|
1846 |
||
1847 |
oldSelection := selection. |
|
1848 |
oldSelCount := selection size. |
|
1849 |
||
1850 |
(clickLine+delta) to:movedLine by:delta do:[:line | |
|
1851 |
(self isInSelection:line) ifTrue:[ |
|
1852 |
self removeFromSelection:line |
|
1853 |
] ifFalse:[ |
|
1854 |
self addToSelection:line |
|
1855 |
] |
|
1856 |
]. |
|
1857 |
((selection ~= oldSelection) |
|
1858 |
or:[selection size ~~ oldSelCount]) ifTrue:[ |
|
1859 |
self selectionChangedFrom:oldSelection. |
|
1860 |
] |
|
1861 |
] ifFalse:[ |
|
1862 |
"/ self selectWithoutScroll:movedLine |
|
1863 |
]. |
|
1864 |
||
1865 |
clickLine := movedLine |
|
1866 |
! |
|
1867 |
||
1868 |
key:key select:index x:x y:y |
|
1869 |
"select an entry by a keyboard action. |
|
1870 |
This is treated like a doubleClick on that entry" |
|
1871 |
||
1872 |
|oldSelection| |
|
1873 |
||
1874 |
(selectConditionBlock isNil or:[selectConditionBlock value:index]) ifTrue:[ |
|
128 | 1875 |
keyActionStyle notNil ifTrue:[ |
1876 |
keyActionStyle == #pass ifTrue:[ |
|
1877 |
^ super keyPress:key x:x y:y |
|
1878 |
]. |
|
1879 |
oldSelection := selection. |
|
1880 |
self selection:index. |
|
1881 |
self selectionChangedFrom:oldSelection. |
|
1882 |
keyActionStyle == #selectAndDoubleClick ifTrue:[ |
|
1883 |
self doubleClicked |
|
1884 |
] |
|
1885 |
] |
|
125 | 1886 |
]. |
1887 |
! |
|
1888 |
||
1889 |
buttonMultiPress:button x:x y:y |
|
1890 |
((button == 1) or:[button == #select]) ifTrue:[ |
|
1891 |
"/ doubleClickActionBlock isNil ifTrue:[ |
|
1892 |
"/ self buttonPress:button x:x y:y |
|
1893 |
"/ ]. |
|
1894 |
self doubleClicked. |
|
1895 |
] ifFalse:[ |
|
1896 |
super buttonMultiPress:button x:x y:y |
|
1897 |
] |
|
1898 |
! |
|
1899 |
||
1900 |
buttonShiftPress:button x:x y:y |
|
1901 |
"add to the selection (if multipleSelectOk); otherwise, |
|
1902 |
behave like normal select" |
|
1903 |
||
1904 |
|oldSelection listLineNr| |
|
1905 |
||
1906 |
((button == 1) or:[button == #select]) ifTrue:[ |
|
1907 |
toggleSelect ifTrue:[ |
|
1908 |
^ self buttonPress:button x:x y:y |
|
1909 |
]. |
|
1910 |
enabled ifTrue:[ |
|
1911 |
listLineNr := self visibleLineToListLine:(self visibleLineOfY:y). |
|
1912 |
listLineNr notNil ifTrue:[ |
|
1913 |
(self line:listLineNr hasAttribute:#disabled) ifTrue:[^ self]. |
|
1914 |
||
1915 |
(selectConditionBlock notNil |
|
1916 |
and:[(selectConditionBlock value:listLineNr) not]) ifTrue:[^ self]. |
|
1917 |
]. |
|
1918 |
oldSelection := selection copy. |
|
1919 |
listLineNr notNil ifTrue: [ |
|
1920 |
multipleSelectOk ifTrue:[ |
|
1921 |
(self isInSelection:listLineNr) ifTrue:[ |
|
1922 |
self removeFromSelection:listLineNr |
|
1923 |
] ifFalse:[ |
|
1924 |
self addToSelection:listLineNr |
|
1925 |
] |
|
1926 |
] ifFalse:[ |
|
1927 |
self selectWithoutScroll:listLineNr |
|
1928 |
] |
|
1929 |
]. |
|
1930 |
((ignoreReselect not and:[selection notNil]) |
|
1931 |
or:[selection ~= oldSelection]) ifTrue:[ |
|
1932 |
self selectionChangedFrom:oldSelection. |
|
1933 |
]. |
|
1934 |
clickLine := listLineNr |
|
1935 |
] |
|
1936 |
] ifFalse:[ |
|
1937 |
super buttonShiftPress:button x:x y:y |
|
1938 |
] |
|
1939 |
! |
|
1940 |
||
1941 |
doubleClicked |
|
1942 |
doubleClickActionBlock notNil ifTrue:[doubleClickActionBlock value:selection]. |
|
1943 |
(model notNil and:[doubleClickMsg notNil]) ifTrue:[ |
|
1944 |
self sendChangeMessage:doubleClickMsg with:(self argForChangeMessage). |
|
1945 |
]. |
|
1946 |
! ! |
|
1947 |
||
1948 |
!SelectionInListView methodsFor:'accessing-actions'! |
|
1949 |
||
1950 |
action:aBlock |
|
1951 |
"set the action block to be performed on select" |
|
1952 |
||
1953 |
actionBlock := aBlock |
|
1954 |
! |
|
1955 |
||
1956 |
doubleClickAction:aBlock |
|
1957 |
"set the double click action block to be performed on select" |
|
1958 |
||
1959 |
doubleClickActionBlock := aBlock |
|
1960 |
! |
|
1961 |
||
1962 |
selectConditionBlock:aBlock |
|
1963 |
"set the conditionBlock; this block is evaluated before a selection |
|
1964 |
change is performed; the change will not be done, if the evaluation |
|
1965 |
returns false. For example, this allows confirmation queries in |
|
1966 |
the SystemBrowser" |
|
1967 |
||
1968 |
selectConditionBlock := aBlock |
|
1969 |
! |
|
1970 |
||
1971 |
useIndex:aBoolean |
|
1972 |
"set/clear the useIndex flag. If set, both actionBlock and change-messages |
|
1973 |
are passed the index(indices) of the selection as argument. |
|
1974 |
If clear, the value(s) (i.e. the selected string) is passed. |
|
1975 |
Default is true." |
|
1976 |
||
1977 |
useIndex := aBoolean |
|
1978 |
! |
|
1979 |
||
1980 |
keyActionStyle:aSymbol |
|
1981 |
"defines how the view should respond to alpha-keys pressed. |
|
1982 |
Possible values are: |
|
1983 |
#select -> will select next entry starting with that |
|
1984 |
character and perform the click-action |
|
1985 |
||
1986 |
#selectAndDoubleclick -> will select next & perform double-click action |
|
1987 |
||
1988 |
#pass -> will pass key to superclass (i.e. no special treatment) |
|
1989 |
||
1990 |
nil -> will ignore key |
|
1991 |
||
1992 |
the default (set in #initialize) is #select |
|
1993 |
" |
|
1994 |
||
1995 |
keyActionStyle := aSymbol |
|
1996 |
! |
|
1997 |
||
1998 |
returnKeyActionStyle:aSymbol |
|
1999 |
"defines how the view should respond to a return key pressed. |
|
2000 |
Possible values are: |
|
2001 |
#doubleClick -> perform double-click action |
|
2002 |
||
2003 |
#pass -> will pass key to superclass (i.e. no special treatment) |
|
2004 |
||
2005 |
nil -> will ignore key |
|
2006 |
||
2007 |
the default (set in #initialize) is #doubleClick |
|
2008 |
" |
|
2009 |
||
2010 |
returnKeyActionStyle := aSymbol |
|
2011 |
! ! |
|
2012 |
||
2013 |
!SelectionInListView methodsFor:'accessing-attributes'! |
|
2014 |
||
2015 |
line:lineNr hasAttribute:aSymbol |
|
2016 |
"return true, if line nr has attribute, aSymbol; |
|
2017 |
currently supported attributes are: |
|
2018 |
#halfIntensity |
|
2019 |
#disabled |
|
2020 |
#bold |
|
2021 |
" |
|
2022 |
||
2023 |
|attr| |
|
2024 |
||
2025 |
listAttributes isNil ifTrue:[^ false]. |
|
2026 |
(lineNr > listAttributes size) ifTrue:[^ false]. |
|
2027 |
attr := listAttributes at:lineNr. |
|
2028 |
attr isNil ifTrue:[^ false]. |
|
2029 |
attr isSymbol ifTrue:[^ attr == aSymbol]. |
|
2030 |
^ (attr includes:aSymbol) |
|
2031 |
! |
|
2032 |
||
2033 |
setAttributes:aList |
|
2034 |
"set the attribute list. |
|
2035 |
No redraw is done - the caller should make sure to redraw afterwards |
|
2036 |
(or use this only before the view is visible)." |
|
2037 |
||
2038 |
listAttributes := aList |
|
2039 |
! |
|
2040 |
||
2041 |
attributeAt:index put:aSymbolOrCollectionOfSymbolsOrNil |
|
2042 |
"set a lines attribute(s); |
|
2043 |
currently supported are: |
|
2044 |
#halfIntensity |
|
2045 |
#disabled |
|
2046 |
#bold |
|
2047 |
" |
|
2048 |
||
2049 |
(index > self size) ifFalse:[ |
|
2050 |
listAttributes isNil ifTrue:[ |
|
2051 |
listAttributes := (OrderedCollection new:index) grow:index |
|
2052 |
] ifFalse:[ |
|
2053 |
(index > listAttributes size) ifTrue:[ |
|
2054 |
listAttributes grow:index |
|
2055 |
] |
|
2056 |
]. |
|
2057 |
aSymbolOrCollectionOfSymbolsOrNil = (listAttributes at:index) ifFalse:[ |
|
2058 |
listAttributes at:index put:aSymbolOrCollectionOfSymbolsOrNil. |
|
2059 |
self redrawLine:index |
|
2060 |
] |
|
2061 |
] |
|
2062 |
||
2063 |
! |
|
2064 |
||
2065 |
strikeOut:aBoolean |
|
2066 |
"turn on/off strikeOut mode" |
|
2067 |
||
2068 |
strikeOut := aBoolean. |
|
2069 |
! |
|
2070 |
||
2071 |
attributeAt:index |
|
2072 |
"return the line attribute of list line index. |
|
2073 |
currently supported are: |
|
2074 |
#halfIntensity |
|
2075 |
#disabled |
|
2076 |
#bold |
|
2077 |
" |
|
2078 |
||
2079 |
listAttributes isNil ifFalse:[ |
|
2080 |
(index > listAttributes size) ifFalse:[ |
|
2081 |
^ listAttributes at:index |
|
2082 |
] |
|
2083 |
]. |
|
2084 |
^ nil |
|
2085 |
! |
|
2086 |
||
2087 |
attributeAt:index add:aSymbolOrCollectionOfSymbols |
|
2088 |
"add to a lines attribute(s); |
|
2089 |
currently supported are: |
|
2090 |
#halfIntensity |
|
2091 |
#disabled |
|
2092 |
#bold |
|
2093 |
" |
|
2094 |
||
2095 |
|current| |
|
2096 |
||
2097 |
current := self attributeAt:index. |
|
2098 |
current isNil ifTrue:[ |
|
2099 |
current := Set new. |
|
2100 |
] ifFalse:[ |
|
2101 |
current isSymbol ifTrue:[ |
|
2102 |
current == aSymbolOrCollectionOfSymbols ifTrue:[^ self]. |
|
2103 |
current := Set with:current |
|
2104 |
] |
|
2105 |
]. |
|
2106 |
||
2107 |
aSymbolOrCollectionOfSymbols isSymbol ifTrue:[ |
|
2108 |
current := current add:aSymbolOrCollectionOfSymbols |
|
2109 |
] ifFalse:[ |
|
2110 |
(current includes:aSymbolOrCollectionOfSymbols) ifTrue:[^ self]. |
|
2111 |
current addAll:aSymbolOrCollectionOfSymbols |
|
2112 |
]. |
|
2113 |
self attributeAt:index put:current |
|
2114 |
! |
|
2115 |
||
2116 |
attributeAt:index remove:aSymbolOrCollectionOfSymbols |
|
2117 |
"remove a line attribute; |
|
2118 |
currently supported are: |
|
2119 |
#halfIntensity |
|
2120 |
#disabled |
|
2121 |
#bold |
|
2122 |
" |
|
2123 |
||
2124 |
|current| |
|
2125 |
||
2126 |
current := self attributeAt:index. |
|
2127 |
current isNil ifTrue:[^ self]. |
|
2128 |
current isSymbol ifTrue:[ |
|
2129 |
aSymbolOrCollectionOfSymbols isSymbol ifTrue:[ |
|
2130 |
current == aSymbolOrCollectionOfSymbols ifTrue:[current := nil] |
|
2131 |
] ifFalse:[ |
|
2132 |
(aSymbolOrCollectionOfSymbols includes:current) ifTrue:[ |
|
2133 |
current := nil |
|
2134 |
] |
|
2135 |
] |
|
2136 |
] ifFalse:[ |
|
2137 |
aSymbolOrCollectionOfSymbols isSymbol ifTrue:[ |
|
2138 |
current := current remove:aSymbolOrCollectionOfSymbols ifAbsent:[] |
|
2139 |
] ifFalse:[ |
|
2140 |
aSymbolOrCollectionOfSymbols removeAll:aSymbolOrCollectionOfSymbols |
|
2141 |
] |
|
2142 |
]. |
|
2143 |
self attributeAt:index put:current |
|
2144 |
! ! |
|
2145 |
||
2146 |
!SelectionInListView methodsFor:'accessing-behavior'! |
|
2147 |
||
2148 |
ignoreReselect:aBoolean |
|
2149 |
"set/clear the ignoreReselect flag - |
|
2150 |
if set, a click on an already selected entry is ignored. |
|
2151 |
Otherwise the notification is done, even if no |
|
2152 |
change in the selection occurs. |
|
130 | 2153 |
(for example, in browser to update a method). |
2154 |
Setting ignoreReselect to false makes sense if data is shown |
|
2155 |
which may change by itself (i.e. without the user doing anything) |
|
2156 |
For example, the inspector uses this, and redisplays the value, |
|
2157 |
if the selection is the same. |
|
2158 |
The default is true, meaning that a click on an already selected |
|
2159 |
does not lead to a notification via the actionBlock/change mechanism." |
|
125 | 2160 |
|
2161 |
ignoreReselect := aBoolean |
|
2162 |
! |
|
2163 |
||
2164 |
toggleSelect:aBoolean |
|
2165 |
"turn on/off toggle select. If true, clicking on a selected entry |
|
130 | 2166 |
unselects it and vice versa. The default is false, which means |
2167 |
that clicking on an already selected entry does not change its |
|
2168 |
select status (see also ignoreReselect:)." |
|
125 | 2169 |
|
2170 |
toggleSelect := aBoolean. |
|
2171 |
! |
|
2172 |
||
2173 |
multipleSelectOk:aBoolean |
|
130 | 2174 |
"allow/disallow multiple selections. If enabled, the |
2175 |
user may select multiple entries in the list, and the program |
|
2176 |
always gets a collection of selected items (indexes if useIndex is true, |
|
2177 |
values otherwise). The default is false, for single selections." |
|
125 | 2178 |
|
2179 |
multipleSelectOk := aBoolean. |
|
2180 |
aBoolean ifTrue:[ |
|
2181 |
self enableButtonMotionEvents |
|
2182 |
] ifFalse:[ |
|
2183 |
self disableButtonMotionEvents |
|
2184 |
] |
|
2185 |
! |
|
2186 |
||
2187 |
enable |
|
2188 |
"enable the view - selection changes are allowed" |
|
2189 |
||
2190 |
enabled := true |
|
2191 |
! |
|
2192 |
||
2193 |
disable |
|
2194 |
"disable the view - no selection changes are allowed" |
|
2195 |
||
2196 |
enabled := false |
|
2197 |
! ! |
|
2198 |
||
2199 |
!SelectionInListView methodsFor:'accessing-contents'! |
|
2200 |
||
128 | 2201 |
printItems:aBoolean |
2202 |
"set/clear the printItems flag. If set, items (as set via #list: or |
|
2203 |
as returned from the model) are sent #printString to display them. |
|
2204 |
If false, items are assumed to be either strings, or know how to |
|
2205 |
display themself in a GC (i.e. they are instances of ListEntry). |
|
2206 |
The default is false. |
|
2207 |
Caveat: printString seems to be too specialized - I'd rather have |
|
2208 |
a definable printSelector or - better - a printConverter. |
|
2209 |
This may be added in the future." |
|
2210 |
||
2211 |
printItems := aBoolean |
|
2212 |
! |
|
2213 |
||
125 | 2214 |
list:aCollection |
2215 |
"set the list - redefined, since setting the list implies unselecting |
|
2216 |
and clearing attributes." |
|
2217 |
||
133 | 2218 |
self list:aCollection keepSelection:false |
2219 |
! |
|
2220 |
||
2221 |
list:aCollection keepSelection:aBoolean |
|
2222 |
"set the list - redefined, since setting the list implies unselecting |
|
2223 |
and clearing attributes." |
|
2224 |
||
2225 |
|oldSelection| |
|
2226 |
||
125 | 2227 |
"somewhat of a kludge: if selection is first line, |
2228 |
we have to remove the highlight frame by hand here" |
|
2229 |
||
2230 |
(shown and:[hilightLevel ~~ 0]) ifTrue:[ |
|
2231 |
selection == firstLineShown ifTrue:[ |
|
2232 |
self paint:bgColor. |
|
2233 |
self fillRectangleX:margin y:margin |
|
2234 |
width:(width - (margin * 2)) |
|
2235 |
height:(hilightLevel abs). |
|
2236 |
]. |
|
2237 |
]. |
|
2238 |
||
133 | 2239 |
aBoolean ifTrue:[ |
2240 |
oldSelection := selection. |
|
2241 |
selection := nil. |
|
2242 |
]. |
|
125 | 2243 |
listAttributes := nil. |
151 | 2244 |
super list:aCollection expandTabs:printItems. |
133 | 2245 |
self selection:oldSelection. "/ nil if keep is false |
125 | 2246 |
! |
2247 |
||
2248 |
setList:aCollection |
|
2249 |
"set the list - redefined, since setting the list implies unselecting |
|
2250 |
and clearing attributes. |
|
2251 |
No redraw is done - the caller should make sure to redraw afterwards |
|
2252 |
(or use this only before the view is visible)." |
|
2253 |
||
2254 |
selection := nil. |
|
2255 |
listAttributes := nil. |
|
2256 |
super setList:aCollection. |
|
2257 |
! |
|
2258 |
||
133 | 2259 |
setContents:aCollection |
2260 |
"set the list - redefined, since setting the list implies unselecting |
|
2261 |
and clearing attributes. |
|
2262 |
No redraw is done - the caller should make sure to redraw afterwards |
|
2263 |
(or use this only before the view is visible)." |
|
2264 |
||
2265 |
selection := nil. |
|
2266 |
listAttributes := nil. |
|
2267 |
super setContents:aCollection. |
|
2268 |
! |
|
2269 |
||
2270 |
contents:aCollection |
|
2271 |
"set the list - redefined, since setting the list implies unselecting |
|
2272 |
and clearing attributes. |
|
2273 |
No redraw is done - the caller should make sure to redraw afterwards |
|
2274 |
(or use this only before the view is visible)." |
|
2275 |
||
2276 |
selection := nil. |
|
2277 |
listAttributes := nil. |
|
2278 |
super contents:aCollection. |
|
2279 |
! |
|
2280 |
||
125 | 2281 |
removeIndexWithoutRedraw:lineNr |
2282 |
"delete line - no redraw; |
|
2283 |
return true, if something was really deleted. |
|
2284 |
Redefined since we have to care for selection" |
|
2285 |
||
2286 |
self checkRemovingSelection:lineNr. |
|
2287 |
^ super removeIndexWithoutRedraw:lineNr |
|
2288 |
! |
|
2289 |
||
2290 |
removeIndex:lineNr |
|
2291 |
"delete line - with redraw. |
|
2292 |
Redefined since we have to care for selection" |
|
2293 |
||
2294 |
self checkRemovingSelection:lineNr. |
|
2295 |
^ super removeIndex:lineNr |
|
2296 |
! |
|
2297 |
||
2298 |
add:aValue beforeIndex:index |
|
2299 |
"must recompute our current selections" |
|
2300 |
||
2301 |
selection notNil ifTrue:[ |
|
2302 |
multipleSelectOk ifTrue:[ |
|
2303 |
selection := selection collect:[ :sel | |
|
2304 |
sel >= index ifTrue:[ |
|
2305 |
sel + 1 |
|
2306 |
] ifFalse:[ |
|
2307 |
sel |
|
2308 |
] |
|
2309 |
]. |
|
2310 |
] ifFalse:[ |
|
2311 |
selection >= index ifTrue:[ |
|
2312 |
selection := selection + 1. |
|
2313 |
]. |
|
2314 |
]. |
|
2315 |
]. |
|
2316 |
^ super add:aValue beforeIndex:index. |
|
105 | 2317 |
! ! |
2318 |
||
155 | 2319 |
!SelectionInListView methodsFor:'queries'! |
2320 |
||
2321 |
specClass |
|
2322 |
self class == SelectionInListView ifTrue:[^ SequenceViewSpec]. |
|
2323 |
^ nil |
|
2324 |
||
2325 |
"Modified: 5.9.1995 / 23:05:53 / claus" |
|
2326 |
! ! |
|
2327 |
||
105 | 2328 |
!SelectionInListView methodsFor:'initialization'! |
2329 |
||
2330 |
initCursor |
|
2331 |
"set the cursor - a hand" |
|
2332 |
||
2333 |
cursor := Cursor hand |
|
2334 |
! |
|
2335 |
||
2336 |
initialize |
|
2337 |
super initialize. |
|
2338 |
||
2339 |
fontHeight := font height + lineSpacing. |
|
2340 |
enabled := true. |
|
2341 |
ignoreReselect := true. |
|
125 | 2342 |
multipleSelectOk := toggleSelect := strikeOut := printItems := false. |
2343 |
useIndex := true. |
|
2344 |
||
105 | 2345 |
keyActionStyle := #select. |
125 | 2346 |
returnKeyActionStyle := #doubleClick. |
2347 |
||
2348 |
listMsg := self class defaultListMessage. |
|
2349 |
initialSelectionMsg := self class defaultSelectionMessage. |
|
2350 |
||
2351 |
! |
|
2352 |
||
2353 |
realize |
|
2354 |
super realize. |
|
2355 |
||
128 | 2356 |
"/ self getListFromModel. -- not needed; superclass did it already |
125 | 2357 |
self getSelectionFromModel. |
2358 |
||
2359 |
selection notNil ifTrue:[ |
|
130 | 2360 |
selection isCollection ifTrue:[ |
166 | 2361 |
selection notEmpty ifTrue:[ |
2362 |
self makeLineVisible:selection first |
|
2363 |
] |
|
130 | 2364 |
] ifFalse:[ |
2365 |
self makeLineVisible:selection |
|
2366 |
] |
|
125 | 2367 |
]. |
105 | 2368 |
! |
2369 |
||
2370 |
initStyle |
|
2371 |
|nm| |
|
2372 |
||
2373 |
super initStyle. |
|
2374 |
||
2375 |
DefaultFont notNil ifTrue:[ |
|
2376 |
font := DefaultFont on:device |
|
2377 |
]. |
|
2378 |
||
2379 |
bgColor := viewBackground. |
|
2380 |
hilightFrameColor := nil. |
|
2381 |
hilightLevel := 0. |
|
2382 |
arrowLevel := 1. |
|
2383 |
smallArrow := false. |
|
2384 |
||
2385 |
device hasGreyscales ifTrue:[ |
|
2386 |
" |
|
2387 |
must get rid of these hard codings |
|
2388 |
" |
|
130 | 2389 |
nm := styleSheet name. |
105 | 2390 |
(nm == #next) ifTrue:[ |
2391 |
hilightFgColor := fgColor. |
|
2392 |
hilightBgColor := White. |
|
2393 |
hilightFrameColor := fgColor |
|
2394 |
] ifFalse:[ |
|
2395 |
(nm == #motif) ifTrue:[ |
|
2396 |
fgColor := White. |
|
2397 |
bgColor := Grey. |
|
2398 |
viewBackground := bgColor. |
|
2399 |
hilightFgColor := bgColor "fgColor" "White". |
|
2400 |
hilightBgColor := fgColor "bgColor lightened" "darkened". |
|
2401 |
] ifFalse:[ |
|
2402 |
(nm == #openwin) ifTrue:[ |
|
2403 |
hilightFgColor := fgColor. |
|
2404 |
hilightBgColor := Color grey. |
|
2405 |
smallArrow := true. |
|
2406 |
] |
|
2407 |
] |
|
2408 |
] |
|
2409 |
]. |
|
2410 |
||
2411 |
hilightFgColor isNil ifTrue:[ |
|
2412 |
hilightFgColor := bgColor. |
|
2413 |
]. |
|
2414 |
hilightBgColor isNil ifTrue:[ |
|
2415 |
hilightBgColor := fgColor. |
|
2416 |
]. |
|
2417 |
DefaultForegroundColor notNil ifTrue:[ |
|
2418 |
fgColor := DefaultForegroundColor |
|
2419 |
]. |
|
2420 |
DefaultBackgroundColor notNil ifTrue:[ |
|
2421 |
bgColor := viewBackground := DefaultBackgroundColor |
|
2422 |
]. |
|
2423 |
DefaultHilightForegroundColor notNil ifTrue:[ |
|
2424 |
hilightFgColor := DefaultHilightForegroundColor |
|
2425 |
]. |
|
2426 |
DefaultHilightBackgroundColor notNil ifTrue:[ |
|
2427 |
hilightBgColor := DefaultHilightBackgroundColor |
|
2428 |
]. |
|
2429 |
DefaultHilightFrameColor notNil ifTrue:[ |
|
2430 |
hilightFrameColor := DefaultHilightFrameColor |
|
2431 |
]. |
|
2432 |
DefaultHilightLevel notNil ifTrue:[ |
|
2433 |
hilightLevel := DefaultHilightLevel |
|
2434 |
]. |
|
2435 |
DefaultRightArrowLevel notNil ifTrue:[ |
|
2436 |
arrowLevel := DefaultRightArrowLevel |
|
2437 |
]. |
|
2438 |
||
2439 |
DefaultShadowColor notNil ifTrue:[ |
|
2440 |
shadowColor := DefaultShadowColor on:device |
|
2441 |
]. |
|
2442 |
DefaultLightColor notNil ifTrue:[ |
|
2443 |
lightColor := DefaultLightColor on:device |
|
2444 |
]. |
|
2445 |
||
2446 |
(hilightLevel abs > 0) ifTrue:[ |
|
2447 |
lineSpacing := 3 |
|
2448 |
] ifFalse:[ |
|
2449 |
lineSpacing := 2 |
|
2450 |
]. |
|
2451 |
||
2452 |
hilightFgColor isNil ifTrue:[ |
|
2453 |
hilightFgColor := bgColor. |
|
2454 |
hilightBgColor := fgColor |
|
2455 |
]. |
|
2456 |
||
2457 |
DefaultDisabledForegroundColor notNil ifTrue:[ |
|
2458 |
halfIntensityFgColor := DefaultDisabledForegroundColor |
|
2459 |
] ifFalse:[ |
|
2460 |
halfIntensityFgColor := Color darkGrey. |
|
2461 |
]. |
|
2462 |
||
2463 |
fgColor := fgColor on:device. |
|
2464 |
bgColor := bgColor on:device. |
|
2465 |
halfIntensityFgColor := halfIntensityFgColor on:device. |
|
2466 |
hilightFrameColor notNil ifTrue:[hilightFrameColor := hilightFrameColor on:device]. |
|
2467 |
hilightFgColor := hilightFgColor on:device. |
|
2468 |
hilightBgColor := hilightBgColor on:device. |
|
0 | 2469 |
! ! |
2470 |
||
125 | 2471 |
!SelectionInListView methodsFor:'change & update'! |
0 | 2472 |
|
105 | 2473 |
update:something with:aParameter from:changedObject |
2474 |
changedObject == model ifTrue:[ |
|
128 | 2475 |
something == aspectMsg ifTrue:[ |
2476 |
self getListFromModel. |
|
2477 |
self getSelectionFromModel. |
|
2478 |
^ self |
|
2479 |
]. |
|
2480 |
something == listMsg ifTrue:[ |
|
2481 |
self getListFromModel. |
|
2482 |
^ self |
|
2483 |
]. |
|
2484 |
something == initialSelectionMsg ifTrue:[ |
|
2485 |
self getSelectionFromModel. |
|
2486 |
^ self |
|
2487 |
]. |
|
2488 |
something == #empty ifTrue:[ |
|
2489 |
self list:nil. |
|
2490 |
^ self |
|
2491 |
]. |
|
105 | 2492 |
]. |
2493 |
^ super update:something with:aParameter from:changedObject |
|
125 | 2494 |
! ! |
2495 |
||
2496 |
!SelectionInListView methodsFor:'accessing-selection'! |
|
2497 |
||
2498 |
addToSelection:aNumber |
|
2499 |
"add entry, aNumber to the selection. No scrolling is done." |
|
2500 |
||
2501 |
(self isValidSelection:aNumber) ifFalse:[^ self]. |
|
2502 |
||
2503 |
selection isNil ifTrue:[^ self selectWithoutScroll:aNumber]. |
|
2504 |
selection isCollection ifTrue:[ |
|
2505 |
(selection includes:aNumber) ifTrue:[^ self]. |
|
2506 |
(selectConditionBlock notNil |
|
2507 |
and:[(selectConditionBlock value:aNumber) not]) ifTrue:[^ self]. |
|
2508 |
selection add:aNumber |
|
2509 |
] ifFalse:[ |
|
2510 |
(aNumber == selection) ifTrue:[^ self]. |
|
2511 |
(selectConditionBlock notNil |
|
2512 |
and:[(selectConditionBlock value:aNumber) not]) ifTrue:[^ self]. |
|
2513 |
selection := OrderedCollection with:selection with:aNumber |
|
63 | 2514 |
]. |
125 | 2515 |
self redrawElement:aNumber |
2516 |
! |
|
2517 |
||
2518 |
addElementToSelection:anObject |
|
2519 |
"add the element with the same printstring as the argument, anObject |
|
2520 |
to the selection. The entry is searched by comparing printStrings. |
|
2521 |
No scrolling is done. Returns true, if ok, false if no such entry |
|
2522 |
was found." |
|
2523 |
||
2524 |
|lineNo str| |
|
2525 |
||
2526 |
str := anObject printString. |
|
2527 |
lineNo := list findFirst:[:entry | str = entry printString]. |
|
2528 |
lineNo ~~ 0 ifTrue:[ |
|
2529 |
self addToSelection:lineNo. |
|
2530 |
^ true |
|
0 | 2531 |
]. |
125 | 2532 |
^ false |
2533 |
! |
|
2534 |
||
2535 |
removeFromSelection:aNumber |
|
2536 |
"remove entry, aNumber from the selection." |
|
2537 |
||
2538 |
selection isNil ifTrue:[^ self]. |
|
0 | 2539 |
|
2540 |
multipleSelectOk ifTrue:[ |
|
125 | 2541 |
(selection includes:aNumber) ifFalse:[^ self]. |
2542 |
selection remove:aNumber. |
|
2543 |
selection size == 0 ifTrue:[ |
|
2544 |
selection := nil |
|
59 | 2545 |
] |
0 | 2546 |
] ifFalse:[ |
125 | 2547 |
(aNumber == selection) ifFalse:[^ self]. |
2548 |
selection := nil |
|
0 | 2549 |
]. |
125 | 2550 |
self redrawElement:aNumber |
0 | 2551 |
! ! |
125 | 2552 |
|
2553 |
!SelectionInListView methodsFor:'accessing-mvc'! |
|
2554 |
||
2555 |
on:aModel printItems:print oneItem:one aspect:aspectSymbol change:changeSymbol |
|
2556 |
list:listSymbol menu:menuSymbol initialSelection:initialSymbol useIndex:use |
|
2557 |
||
2558 |
"ST-80 compatibility" |
|
2559 |
||
2560 |
aspectMsg := aspectSymbol. |
|
2561 |
changeMsg := changeSymbol. |
|
2562 |
listMsg := listSymbol. |
|
2563 |
menuMsg := menuSymbol. |
|
2564 |
initialSelectionMsg := initialSymbol. |
|
2565 |
printItems := print. |
|
2566 |
oneItem := one. |
|
2567 |
useIndex := use. |
|
2568 |
ignoreReselect := false. "/ ST80 behavior |
|
2569 |
self model:aModel. |
|
2570 |
! |
|
2571 |
||
2572 |
doubleClickMessage |
|
2573 |
"return the symbol with which the model (if any) is informed about |
|
2574 |
double-click. If nil (which is the default), it is not informed." |
|
2575 |
||
2576 |
^ doubleClickMsg |
|
2577 |
! |
|
2578 |
||
2579 |
doubleClickMessage:aSymbol |
|
2580 |
"set the symbol with which the model (if any) is informed about double-click. |
|
2581 |
If nil (which is the default), it is not informed." |
|
2582 |
||
2583 |
doubleClickMsg := aSymbol |
|
2584 |
! |
|
2585 |
||
2586 |
doubleClick:aSymbol |
|
2587 |
"set the symbol with which the model is informed about double-click. |
|
2588 |
OBSOLETE: please use #doubleClickMessage:" |
|
2589 |
||
2590 |
self obsoleteMethodWarning:'please use #doubleClickMessage:'. |
|
2591 |
doubleClickMsg := aSymbol |
|
2592 |
! |
|
2593 |
||
2594 |
initialSelectionMessage |
|
2595 |
"return the symbol by which the model informes me about a changed |
|
2596 |
selectionIndex. This is used both in change notification and to |
|
2597 |
actually aquire a new selection value." |
|
2598 |
||
2599 |
^ initialSelectionMsg |
|
2600 |
! |
|
2601 |
||
2602 |
initialSelectionMessage:aSymbol |
|
2603 |
"set the symbol by which the model informes me about a changed |
|
2604 |
selectionIndex. This is used both in change notification and to |
|
2605 |
actually aquire a new selection value." |
|
2606 |
||
2607 |
initialSelectionMsg := aSymbol |
|
2608 |
! |
|
2609 |
||
2610 |
addModelInterfaceTo:aDictionary |
|
2611 |
"see comment in View>>modelInterface" |
|
2612 |
||
2613 |
super addModelInterfaceTo:aDictionary. |
|
2614 |
aDictionary at:#doubleClickMessage put:doubleClickMsg. |
|
2615 |
aDictionary at:#initialSelectionMessage put:initialSelectionMsg. |
|
2616 |
||
2617 |
" |
|
2618 |
SelectionInListView new modelInterface |
|
2619 |
" |
|
2620 |
! ! |