168 " |
171 " |
169 SelectionInListView can be used both in the ST/X way, using action blocks |
172 SelectionInListView can be used both in the ST/X way, using action blocks |
170 or in the traditional mvc way. |
173 or in the traditional mvc way. |
171 with actions: |
174 with actions: |
172 |
175 |
173 simple: |
176 basic interface: |
174 |
177 |
175 |top slv| |
178 |top slv| |
176 |
179 |
177 top := StandardSystemView new |
180 top := StandardSystemView new |
178 label:'select'; |
181 label:'select'; |
179 minExtent:100@100; |
182 minExtent:100@100; |
180 maxExtent:300@400; |
183 maxExtent:300@400; |
181 extent:200@200. |
184 extent:200@200. |
182 |
185 |
183 slv := SelectionInListView new. |
186 slv := SelectionInListView new. |
184 slv list:(Filename currentDirectory directoryContents). |
187 slv list:#('one' 'two' 'three'). |
185 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
188 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
186 |
189 |
187 top add:slv in:(0.0@0.0 corner:1.0@1.0). |
190 top add:slv in:(0.0@0.0 corner:1.0@1.0). |
188 top open |
191 top open |
|
192 |
|
193 |
|
194 get element instead of index: |
|
195 |
|
196 |top slv| |
|
197 |
|
198 top := StandardSystemView new |
|
199 label:'select'; |
|
200 minExtent:100@100; |
|
201 maxExtent:300@400; |
|
202 extent:200@200. |
|
203 |
|
204 slv := SelectionInListView new. |
|
205 slv list:#('one' 'two' 'three'). |
|
206 slv action:[:element | Transcript showCr:'selected ' , element printString]. |
|
207 slv useIndex:false. |
|
208 |
|
209 top add:slv in:(0.0@0.0 corner:1.0@1.0). |
|
210 top open |
|
211 |
|
212 |
|
213 concrete example; show filenames: |
|
214 (notice: normally, you would use a FileSelectionList) |
|
215 |
|
216 |top slv| |
|
217 |
|
218 top := StandardSystemView new |
|
219 label:'select'; |
|
220 minExtent:100@100; |
|
221 maxExtent:300@400; |
|
222 extent:200@200. |
|
223 |
|
224 slv := SelectionInListView new. |
|
225 slv list:(Filename currentDirectory directoryContents). |
|
226 slv action:[:index | |
|
227 Transcript showCr:'selected ' , index printString. |
|
228 Transcript showCr:' the value is: ', slv selectionValue]. |
|
229 |
|
230 top add:slv in:(0.0@0.0 corner:1.0@1.0). |
|
231 top open |
|
232 |
189 |
233 |
190 add a scrollbar: |
234 add a scrollbar: |
191 |
235 |
192 |top slv| |
236 |top slv| |
193 |
237 |
194 top := StandardSystemView new |
238 top := StandardSystemView new |
195 label:'select'; |
239 label:'select'; |
196 minExtent:100@100; |
240 minExtent:100@100; |
197 maxExtent:300@400; |
241 maxExtent:300@400; |
198 extent:200@200. |
242 extent:200@200. |
199 |
243 |
200 slv := SelectionInListView new. |
244 slv := SelectionInListView new. |
201 slv list:(Filename currentDirectory directoryContents). |
245 slv list:(Filename currentDirectory directoryContents). |
202 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
246 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
203 |
247 |
204 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
248 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
205 top open |
249 top open |
|
250 |
206 |
251 |
207 allow reselect (clicking on already selected entry): |
252 allow reselect (clicking on already selected entry): |
208 |
253 |
209 |top slv| |
254 |top slv| |
210 |
255 |
211 top := StandardSystemView new |
256 top := StandardSystemView new |
212 label:'select'; |
257 label:'select'; |
213 minExtent:100@100; |
258 minExtent:100@100; |
214 maxExtent:300@400; |
259 maxExtent:300@400; |
215 extent:200@200. |
260 extent:200@200. |
216 |
261 |
217 slv := SelectionInListView new. |
262 slv := SelectionInListView new. |
218 slv list:(Filename currentDirectory directoryContents). |
263 slv list:(Filename currentDirectory directoryContents). |
219 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
264 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
220 slv ignoreReselect:false. |
265 slv ignoreReselect:false. |
221 |
266 |
222 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
267 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
223 top open |
268 top open |
|
269 |
224 |
270 |
225 allow multiple selections: |
271 allow multiple selections: |
226 |
272 |
227 |top slv| |
273 |top slv| |
228 |
274 |
229 top := StandardSystemView new |
275 top := StandardSystemView new |
230 label:'select'; |
276 label:'select'; |
231 minExtent:100@100; |
277 minExtent:100@100; |
232 maxExtent:300@400; |
278 maxExtent:300@400; |
233 extent:200@200. |
279 extent:200@200. |
234 |
280 |
235 slv := SelectionInListView new. |
281 slv := SelectionInListView new. |
236 slv list:(Filename currentDirectory directoryContents). |
282 slv list:(Filename currentDirectory directoryContents). |
237 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
283 slv action:[:indexList | Transcript showCr:'selected ' , indexList printString]. |
238 slv multipleSelectOk:true. |
284 slv multipleSelectOk:true. |
239 |
285 |
240 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
286 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
241 top open |
287 top open |
|
288 |
|
289 |
|
290 same, not using index: |
|
291 |
|
292 |top slv| |
|
293 |
|
294 top := StandardSystemView new |
|
295 label:'select'; |
|
296 minExtent:100@100; |
|
297 maxExtent:300@400; |
|
298 extent:200@200. |
|
299 |
|
300 slv := SelectionInListView new. |
|
301 slv list:(Filename currentDirectory directoryContents). |
|
302 slv action:[:indexList | Transcript showCr:'selected ' , indexList printString]. |
|
303 slv multipleSelectOk:true; useIndex:false. |
|
304 |
|
305 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
306 top open |
|
307 |
242 |
308 |
243 strikeout mode (single): |
309 strikeout mode (single): |
244 |
310 |
245 |top slv| |
311 |top slv| |
246 |
312 |
247 top := StandardSystemView new |
313 top := StandardSystemView new |
248 label:'select'; |
314 label:'select'; |
249 minExtent:100@100; |
315 minExtent:100@100; |
250 maxExtent:300@400; |
316 maxExtent:300@400; |
251 extent:200@200. |
317 extent:200@200. |
252 |
318 |
253 slv := SelectionInListView new. |
319 slv := SelectionInListView new. |
254 slv list:(Filename currentDirectory directoryContents). |
320 slv list:(Filename currentDirectory directoryContents). |
255 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
321 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
256 slv strikeOut:true. |
322 slv strikeOut:true. |
257 |
323 |
258 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
324 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
259 top open |
325 top open |
|
326 |
260 |
327 |
261 strikeout mode (multiple): |
328 strikeout mode (multiple): |
262 |
329 |
263 |top slv| |
330 |top slv| |
264 |
331 |
265 top := StandardSystemView new |
332 top := StandardSystemView new |
266 label:'select'; |
333 label:'select'; |
267 minExtent:100@100; |
334 minExtent:100@100; |
268 maxExtent:300@400; |
335 maxExtent:300@400; |
269 extent:200@200. |
336 extent:200@200. |
270 |
337 |
271 slv := SelectionInListView new. |
338 slv := SelectionInListView new. |
272 slv list:(Filename currentDirectory directoryContents). |
339 slv list:(Filename currentDirectory directoryContents). |
273 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
340 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
274 slv strikeOut:true; multipleSelectOk:true. |
341 slv strikeOut:true; multipleSelectOk:true. |
275 |
342 |
276 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
343 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
277 top open |
344 top open |
|
345 |
278 |
346 |
279 define what to do on double-click: |
347 define what to do on double-click: |
280 |
348 |
281 |top slv| |
349 |top slv| |
282 |
350 |
283 top := StandardSystemView new |
351 top := StandardSystemView new |
284 label:'select'; |
352 label:'select'; |
285 minExtent:100@100; |
353 minExtent:100@100; |
286 maxExtent:300@400; |
354 maxExtent:300@400; |
287 extent:200@200. |
355 extent:200@200. |
288 |
356 |
289 slv := SelectionInListView new. |
357 slv := SelectionInListView new. |
290 slv list:(Filename currentDirectory directoryContents). |
358 slv list:(Filename currentDirectory directoryContents). |
291 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
359 slv action:[:index | Transcript showCr:'selected ' , index printString]. |
292 slv doubleClickAction:[:index | slv selectionValue asFilename edit]. |
360 slv doubleClickAction:[:index | Transcript showCr:'doubleclick on ' , index printString]. |
293 |
361 |
294 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
362 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
295 top open |
363 top open |
296 |
364 |
297 |
365 |
298 using a Model: |
366 using a Model: |
299 |
367 |
300 |top slv model| |
368 |top slv model| |
301 |
369 |
302 model := Plug new. |
370 model := Plug new. |
303 model respondTo:#getList with:[#('foo' 'bar' 'baz' 'hello')]. |
371 model respondTo:#getList with:[#('foo' 'bar' 'baz' 'hello')]. |
304 model respondTo:#initial with:[1]. |
372 model respondTo:#initial with:[1]. |
305 model respondTo:#setSelection: with:[:arg | Transcript showCr:'model selected:', arg printString]. |
373 model respondTo:#setSelection: with:[:arg | Transcript showCr:'model selected:', arg printString]. |
306 |
374 |
307 top := StandardSystemView new |
375 top := StandardSystemView new |
308 label:'select'; |
376 label:'select'; |
309 minExtent:100@100; |
377 minExtent:100@100; |
310 maxExtent:300@400; |
378 maxExtent:300@400; |
311 extent:200@200. |
379 extent:200@200. |
312 |
380 |
313 slv := SelectionInListView |
381 slv := SelectionInListView |
314 on:model |
382 on:model |
315 aspect:#someAspect |
383 aspect:#someAspect |
316 change:#setSelection: |
384 change:#setSelection: |
317 list:#getList |
385 list:#getList |
318 initialSelection:#initial. |
386 initialSelection:#initial. |
319 |
387 |
320 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
388 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
321 top open |
389 top open |
322 |
390 |
323 notice, that the ST-80 behavaior on reselect is to send a selection change |
391 notice, that the ST-80 behavaior on reselect is to send a selection change |
324 with an index of 0. |
392 with an index of 0. |
325 |
393 |
326 |
394 |
|
395 same, with useIndex false: |
|
396 |
|
397 |top slv model| |
|
398 |
|
399 model := Plug new. |
|
400 model respondTo:#getList with:[#('foo' 'bar' 'baz' 'hello')]. |
|
401 model respondTo:#initial with:['bar']. |
|
402 model respondTo:#setSelection: with:[:arg | Transcript showCr:'model selected:', arg printString]. |
|
403 |
|
404 top := StandardSystemView new |
|
405 label:'select'; |
|
406 minExtent:100@100; |
|
407 maxExtent:300@400; |
|
408 extent:200@200. |
|
409 |
|
410 slv := SelectionInListView |
|
411 on:model |
|
412 aspect:#someAspect |
|
413 change:#setSelection: |
|
414 list:#getList |
|
415 initialSelection:#initial. |
|
416 slv useIndex:false. |
|
417 |
|
418 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
|
419 top open |
|
420 |
|
421 |
327 using a SelectionInList-Model: |
422 using a SelectionInList-Model: |
328 (see how changes in the model (via list:...) are reflected in the view) |
423 (see how changes in the model (via list:...) are reflected in the view) |
329 |
424 |
330 |top slv model| |
425 |top slv model| |
331 |
426 |
332 model := SelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
427 model := SelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
333 |
428 model selection:'bar'. |
334 top := StandardSystemView new |
429 |
335 label:'select'; |
430 top := StandardSystemView new |
336 minExtent:100@100; |
431 label:'select'; |
337 maxExtent:300@400; |
432 minExtent:100@100; |
338 extent:200@200. |
433 maxExtent:300@400; |
339 |
434 extent:200@200. |
340 slv := SelectionInListView |
435 |
341 on:model |
436 slv := SelectionInListView on:model. |
342 aspect:#list |
437 |
343 change:#selection: |
438 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
344 list:#list |
439 top open. |
345 initialSelection:#selection. |
440 |
346 |
441 model inspect |
347 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
442 |
348 top open. |
443 |
349 model inspect |
444 two selectionInListViews on the same selectionInList model: |
350 |
445 |
351 |
446 |top1 slv1 top2 slv2 model| |
352 since the above selectors are the default anyway, you can also use: |
447 |
353 |
448 model := SelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
354 |top slv model| |
449 |
355 |
450 top1 := StandardSystemView new |
356 model := SelectionInList with:#('foo' 'bar' 'baz' 'hello'). |
451 label:'select'; |
357 |
452 minExtent:100@100; |
358 top := StandardSystemView new |
453 maxExtent:300@400; |
359 label:'select'; |
454 extent:200@200. |
360 minExtent:100@100; |
455 |
361 maxExtent:300@400; |
456 slv1 := SelectionInListView on:model. |
362 extent:200@200. |
457 |
363 |
458 top1 add:(ScrollableView forView:slv1) in:(0.0@0.0 corner:1.0@1.0). |
364 slv := SelectionInListView on:model. |
459 top1 open. |
365 |
460 |
366 top add:(ScrollableView forView:slv) in:(0.0@0.0 corner:1.0@1.0). |
461 top2 := StandardSystemView new |
367 top open. |
462 label:'select'; |
368 model inspect |
463 minExtent:100@100; |
|
464 maxExtent:300@400; |
|
465 extent:200@200. |
|
466 |
|
467 slv2 := SelectionInListView on:model. |
|
468 |
|
469 top2 add:(ScrollableView forView:slv2) in:(0.0@0.0 corner:1.0@1.0). |
|
470 top2 open. |
369 " |
471 " |
370 ! ! |
472 ! ! |
371 |
473 |
372 !SelectionInListView class methodsFor:'instance creation'! |
474 !SelectionInListView class methodsFor:'instance creation'! |
373 |
475 |
602 SmallRightArrowShadowForm := f |
720 SmallRightArrowShadowForm := f |
603 ]. |
721 ]. |
604 ^ f |
722 ^ f |
605 ! ! |
723 ! ! |
606 |
724 |
|
725 !SelectionInListView methodsFor:'selections'! |
|
726 |
|
727 isInSelection:aNumber |
|
728 "return true, if line, aNumber is in the selection" |
|
729 |
|
730 selection isNil ifTrue:[^ false]. |
|
731 multipleSelectOk ifTrue:[ |
|
732 ^ (selection includes:aNumber) |
|
733 ]. |
|
734 ^ (aNumber == selection) |
|
735 ! |
|
736 |
|
737 selectWithoutScroll:aNumberOrNilOrCollection |
|
738 "select line, aNumber or deselect if argument is nil" |
|
739 |
|
740 |prevSelection newSelection| |
|
741 |
|
742 newSelection := aNumberOrNilOrCollection. |
|
743 newSelection notNil ifTrue:[ |
|
744 (self isValidSelection:newSelection) ifFalse:[ |
|
745 newSelection := nil |
|
746 ] |
|
747 ]. |
|
748 |
|
749 (newSelection = selection) ifTrue: [^ self]. |
|
750 |
|
751 " |
|
752 redraw old selection unhighlighted |
|
753 " |
|
754 selection notNil ifTrue: [ |
|
755 prevSelection := selection. |
|
756 selection := nil. |
|
757 multipleSelectOk ifTrue:[ |
|
758 prevSelection do:[:line | |
|
759 self redrawElement:line |
|
760 ] |
|
761 ] ifFalse:[ |
|
762 self redrawElement:prevSelection |
|
763 ] |
|
764 ]. |
|
765 |
|
766 selection := newSelection. |
|
767 |
|
768 " |
|
769 redraw new selection unhighlighted |
|
770 " |
|
771 newSelection notNil ifTrue:[ |
|
772 multipleSelectOk ifTrue:[ |
|
773 newSelection isCollection ifFalse:[ |
|
774 selection := OrderedCollection with:newSelection. |
|
775 ]. |
|
776 selection do:[:line | |
|
777 self redrawElement:line |
|
778 ] |
|
779 ] ifFalse:[ |
|
780 self redrawElement:selection |
|
781 ] |
|
782 ] |
|
783 |
|
784 ! |
|
785 |
|
786 makeSelectionVisible |
|
787 "scroll to make the selection line visible" |
|
788 |
|
789 |line| |
|
790 |
|
791 selection notNil ifTrue:[ |
|
792 multipleSelectOk ifTrue:[ |
|
793 line := selection first. |
|
794 ] ifFalse:[ |
|
795 line := selection |
|
796 ]. |
|
797 self makeLineVisible:line |
|
798 ] |
|
799 ! |
|
800 |
|
801 selection:aNumberOrNil |
|
802 "select line, aNumber or deselect if argument is nil; |
|
803 scroll to make the selected line visible" |
|
804 |
|
805 self selectWithoutScroll:aNumberOrNil. |
|
806 selection notNil ifTrue:[self makeSelectionVisible] |
|
807 ! |
|
808 |
|
809 selectionValue |
|
810 "return the selection value i.e. the text in the selected line. |
|
811 For multiple selections a collection containing the entries is returned." |
|
812 |
|
813 selection isNil ifTrue:[^ nil]. |
|
814 |
|
815 multipleSelectOk ifTrue:[ |
|
816 ^ selection collect:[:nr | self at:nr] |
|
817 ]. |
|
818 ^ self at:selection |
|
819 |
|
820 ! |
|
821 |
|
822 hasSelection |
|
823 "return true, if the view has a selection" |
|
824 |
|
825 ^ selection notNil |
|
826 ! |
|
827 |
|
828 selectElement:anObject |
|
829 "select the element with same printString as the argument, anObject. |
|
830 Scroll to make the new selection visible." |
|
831 |
|
832 |lineNo| |
|
833 |
|
834 list notNil ifTrue:[ |
|
835 items notNil ifTrue:[ |
|
836 lineNo := items indexOf:anObject ifAbsent:nil |
|
837 ] ifFalse:[ |
|
838 lineNo := list indexOf:(anObject printString) ifAbsent:nil. |
|
839 ]. |
|
840 lineNo notNil ifTrue:[self selection:lineNo] |
|
841 ] |
|
842 ! |
|
843 |
|
844 selection |
|
845 "return the selection index or collection of indices (if multipleSelect is on)" |
|
846 |
|
847 ^ selection |
|
848 ! |
|
849 |
|
850 selectionChangedFrom:oldSelection |
|
851 "selection has changed. Call actionblock and/or send changeMessage if defined" |
|
852 |
|
853 |arg| |
|
854 |
|
855 arg := self argForChangeMessage. |
|
856 " |
|
857 the ST/X way of doing things - perform actionBlock |
|
858 " |
|
859 actionBlock notNil ifTrue:[actionBlock value:arg]. |
|
860 " |
|
861 the ST-80 way of doing things - notify model via changeMsg |
|
862 " |
|
863 "/ ST80 sends 0 as index, if the same selection is reselected ... |
|
864 selection == oldSelection ifTrue:[ |
|
865 arg := 0 |
|
866 ]. |
|
867 self sendChangeMessageWith:arg |
|
868 ! |
|
869 |
|
870 deselect |
|
871 "deselect" |
|
872 |
|
873 self selection:nil |
|
874 ! |
|
875 |
|
876 deselectWithoutRedraw |
|
877 "deselect - no redraw" |
|
878 |
|
879 selection := nil |
|
880 ! |
|
881 |
|
882 numberOfSelections |
|
883 "return the number of selected entries" |
|
884 |
|
885 |sz| |
|
886 |
|
887 selection isNil ifTrue:[^ 0]. |
|
888 sz := selection size. |
|
889 sz > 0 ifTrue:[^ sz]. |
|
890 ^ 1 |
|
891 ! |
|
892 |
|
893 valueIsInSelection:someString |
|
894 "return true, if someString is in the selection" |
|
895 |
|
896 |sel| |
|
897 |
|
898 selection isNil ifTrue:[^ false]. |
|
899 sel := self selectionValue. |
|
900 self numberOfSelections > 1 ifTrue:[ |
|
901 ^ (sel includes:someString) |
|
902 ]. |
|
903 ^ (someString = sel) |
|
904 ! |
|
905 |
|
906 selectElementWithoutScroll:anObject |
|
907 "select the element with same printString as the argument, anObject. |
|
908 Do not scroll." |
|
909 |
|
910 |lineNo| |
|
911 |
|
912 list notNil ifTrue:[ |
|
913 items notNil ifTrue:[ |
|
914 lineNo := items indexOf:anObject ifAbsent:nil |
|
915 ] ifFalse:[ |
|
916 lineNo := list indexOf:(anObject printString) ifAbsent:nil. |
|
917 ]. |
|
918 lineNo notNil ifTrue:[self selectWithoutScroll:lineNo] |
|
919 ] |
|
920 ! |
|
921 |
|
922 nextAfterSelection |
|
923 "return the index of the next selectable entry after the selection. |
|
924 Wrap at end." |
|
925 |
|
926 |next| |
|
927 |
|
928 selection isNil ifTrue:[ |
|
929 next := firstLineShown |
|
930 ] ifFalse:[ |
|
931 selection size ~~ 0 ifTrue:[ |
|
932 next := selection max + 1 |
|
933 ] ifFalse:[ |
|
934 next := selection + 1 |
|
935 ]. |
|
936 ]. |
|
937 (self isValidSelection:next) ifFalse:[ |
|
938 next > self size ifTrue:[ |
|
939 next := 1. |
|
940 ] ifFalse:[ |
|
941 [next <= self size |
|
942 and:[(self isValidSelection:next) not]] whileTrue:[ |
|
943 next := next + 1 |
|
944 ]. |
|
945 ]. |
|
946 ]. |
|
947 (self isValidSelection:next) ifFalse:[ |
|
948 next := nil |
|
949 ]. |
|
950 ^ next |
|
951 ! |
|
952 |
|
953 previousBeforeSelection |
|
954 "return the index of the previous selectable entry before the selection. |
|
955 Wrap at beginning." |
|
956 |
|
957 |prev| |
|
958 |
|
959 selection isNil ifTrue:[ |
|
960 prev := firstLineShown - 1 |
|
961 ] ifFalse:[ |
|
962 selection size ~~ 0 ifTrue:[ |
|
963 prev := selection min - 1 |
|
964 ] ifFalse:[ |
|
965 prev := selection - 1 |
|
966 ]. |
|
967 ]. |
|
968 (self isValidSelection:prev) ifFalse:[ |
|
969 prev < 1 ifTrue:[ |
|
970 prev := self size. |
|
971 ] ifFalse:[ |
|
972 [prev >= 1 |
|
973 and:[(self isValidSelection:prev) not]] whileTrue:[ |
|
974 prev := prev - 1 |
|
975 ]. |
|
976 ]. |
|
977 ]. |
|
978 (self isValidSelection:prev) ifFalse:[ |
|
979 prev := nil |
|
980 ]. |
|
981 ^ prev |
|
982 |
|
983 ! |
|
984 |
|
985 selectAll |
|
986 "select all entries." |
|
987 |
|
988 |oldSelection| |
|
989 |
|
990 multipleSelectOk ifTrue:[ |
|
991 oldSelection := selection. |
|
992 selection := OrderedCollection withAll:(1 to:self size). |
|
993 shown ifTrue:[self redraw]. |
|
994 self selectionChangedFrom:oldSelection. |
|
995 ] |
|
996 ! |
|
997 |
|
998 toggleSelection:aNumber |
|
999 "toggle selection-state of entry, aNumber" |
|
1000 |
|
1001 (self isInSelection:aNumber) ifTrue:[ |
|
1002 self removeFromSelection:aNumber |
|
1003 ] ifFalse:[ |
|
1004 self addToSelection:aNumber |
|
1005 ] |
|
1006 ! |
|
1007 |
|
1008 selectNext |
|
1009 "select next line or first visible if there is currrently no selection. |
|
1010 Wrap at end." |
|
1011 |
|
1012 self selection:(self nextAfterSelection) |
|
1013 ! |
|
1014 |
|
1015 selectPrevious |
|
1016 "select previous line or previous visible if there is currently no selection. |
|
1017 Wrap at beginning." |
|
1018 |
|
1019 self selection:(self previouseBeforeSelection). |
|
1020 ! |
|
1021 |
|
1022 selectionDo:aBlock |
|
1023 "perform aBlock for each nr in the selection. |
|
1024 For single selection, it is called once for the items nr. |
|
1025 For multiple selections, it is called for each." |
|
1026 |
|
1027 selection notNil ifTrue:[ |
|
1028 multipleSelectOk ifTrue:[ |
|
1029 selection do:aBlock |
|
1030 ] ifFalse:[ |
|
1031 aBlock value:selection |
|
1032 ]. |
|
1033 ]. |
|
1034 |
|
1035 ! |
|
1036 |
|
1037 selectionAsCollection |
|
1038 "return the selection as a collection of line numbers. |
|
1039 This allows users of this class to enumerate independent of |
|
1040 the multipleSelect style." |
|
1041 |
|
1042 selection isNil ifTrue:[^ #()]. |
|
1043 |
|
1044 multipleSelectOk ifTrue:[ |
|
1045 ^ (OrderedCollection new) add:selection; yourself. |
|
1046 ]. |
|
1047 ^ selection |
|
1048 ! ! |
|
1049 |
607 !SelectionInListView methodsFor:'redrawing'! |
1050 !SelectionInListView methodsFor:'redrawing'! |
608 |
|
609 redrawElement:aNumber |
|
610 "redraw an individual element" |
|
611 |
|
612 ^ self redrawLine:aNumber |
|
613 ! |
|
614 |
1051 |
615 redrawVisibleLine:visLineNr |
1052 redrawVisibleLine:visLineNr |
616 "redraw a single line. |
1053 "redraw a single line. |
617 Must check, if any is in the selection and handle this case. |
1054 Must check, if any is in the selection and handle this case. |
618 Otherwise draw using supers method." |
1055 Otherwise draw using supers method." |
838 ^ self redrawVisibleLine:visLineNr |
1294 ^ self redrawVisibleLine:visLineNr |
839 ]. |
1295 ]. |
840 super redrawVisibleLine:visLineNr col:colNr |
1296 super redrawVisibleLine:visLineNr col:colNr |
841 ! |
1297 ! |
842 |
1298 |
843 redrawVisibleLine:visLineNr from:startCol to:endCol |
|
844 "redraw from a startCol to endCol. |
|
845 Must check, if its in the selection and handle this case." |
|
846 |
|
847 (self visibleLineNeedsSpecialCare:visLineNr) ifTrue:[ |
|
848 ^ self redrawVisibleLine:visLineNr |
|
849 ]. |
|
850 super redrawVisibleLine:visLineNr from:startCol to:endCol |
|
851 ! |
|
852 |
|
853 redrawVisibleLine:visLineNr from:startCol |
1299 redrawVisibleLine:visLineNr from:startCol |
854 "redraw from a col to the right end. |
1300 "redraw from a col to the right end. |
855 Must check, if its in the selection and handle this case." |
1301 Must check, if its in the selection and handle this case." |
856 |
1302 |
857 (self visibleLineNeedsSpecialCare:visLineNr) ifTrue:[ |
1303 (self visibleLineNeedsSpecialCare:visLineNr) ifTrue:[ |
858 ^ self redrawVisibleLine:visLineNr |
1304 ^ self redrawVisibleLine:visLineNr |
859 ]. |
1305 ]. |
860 super redrawVisibleLine:visLineNr from:startCol |
1306 super redrawVisibleLine:visLineNr from:startCol |
861 ! ! |
1307 ! ! |
862 |
1308 |
863 !SelectionInListView methodsFor:'selections'! |
1309 !SelectionInListView methodsFor:'private'! |
864 |
1310 |
865 selectWithoutScroll:aNumberOrNil |
1311 getListFromModel |
866 "select line, aNumber or deselect if argument is nil" |
1312 "if I have a model and a listMsg, get my list from it" |
867 |
1313 |
868 |prevSelection newSelection| |
1314 |text| |
869 |
1315 |
870 newSelection := aNumberOrNil. |
1316 model notNil ifTrue:[ |
871 newSelection notNil ifTrue:[ |
1317 listMsg notNil ifTrue:[ |
872 (self isValidSelection:newSelection) ifFalse:[ |
1318 items := model perform:listMsg. |
873 newSelection := nil |
1319 items notNil ifTrue:[ |
|
1320 printItems ifTrue:[ |
|
1321 text := items collect:[:element | element printString] |
|
1322 ] ifFalse:[ |
|
1323 text := items |
|
1324 ]. |
|
1325 text notNil ifTrue:[ |
|
1326 text := text asStringCollection. |
|
1327 ] |
|
1328 ]. |
|
1329 self list:text |
|
1330 ]. |
|
1331 ]. |
|
1332 ! |
|
1333 |
|
1334 getSelectionFromModel |
|
1335 "if I have a model and an initialSelectionMsg, get my selection from it" |
|
1336 |
|
1337 |sel| |
|
1338 |
|
1339 model notNil ifTrue:[ |
|
1340 initialSelectionMsg notNil ifTrue:[ |
|
1341 sel := model perform:initialSelectionMsg. |
|
1342 useIndex ifTrue:[ |
|
1343 self selection:sel |
|
1344 ] ifFalse:[ |
|
1345 self selectElement:sel. |
|
1346 ]. |
874 ] |
1347 ] |
875 ]. |
1348 ]. |
876 |
1349 ! |
877 (newSelection == selection) ifTrue: [^ self]. |
1350 |
878 |
1351 argForChangeMessage |
879 selection notNil ifTrue: [ |
1352 "return the argument for a selectionChange; |
880 prevSelection := selection. |
1353 depending on the setting of useIndex, this is either the numeric |
881 selection := nil. |
1354 index of the selection or the value (i.e. the string)" |
882 (prevSelection isCollection) ifTrue:[ |
1355 |
883 prevSelection do:[:line | |
1356 useIndex ~~ false ifTrue:[ "/ i.e. everything except false |
884 self redrawElement:line |
1357 ^ selection |
|
1358 ]. |
|
1359 |
|
1360 printItems ifFalse:[ |
|
1361 ^ self selectionValue |
|
1362 ]. |
|
1363 |
|
1364 items notNil ifTrue:[ |
|
1365 multipleSelectOk ifTrue:[ |
|
1366 ^ selection collect:[:nr | items at:nr] |
|
1367 ]. |
|
1368 ^ items at:selection |
|
1369 ]. |
|
1370 |
|
1371 ^ nil "/ cannot happen |
|
1372 ! |
|
1373 |
|
1374 isValidSelection:aNumberOrCollection |
|
1375 "return true, if aNumber is ok as a selection index" |
|
1376 |
|
1377 aNumberOrCollection isNil ifTrue:[^ false]. |
|
1378 |
|
1379 (aNumberOrCollection isCollection) ifTrue:[ |
|
1380 multipleSelectOk ifFalse:[^ false]. |
|
1381 aNumberOrCollection do:[:index | |
|
1382 (index between:1 and:self size) ifFalse:[^ false]. |
|
1383 ]. |
|
1384 ^ true. |
|
1385 ] ifFalse:[ |
|
1386 ^ (aNumberOrCollection between:1 and:self size). |
|
1387 ]. |
|
1388 |
|
1389 ! |
|
1390 |
|
1391 positionToSelectionX:x y:y |
|
1392 "given a click position, return the selection lineNo" |
|
1393 |
|
1394 |visibleLine| |
|
1395 |
|
1396 (x between:0 and:width) ifTrue:[ |
|
1397 (y between:0 and:height) ifTrue:[ |
|
1398 visibleLine := self visibleLineOfY:y. |
|
1399 ^ self visibleLineToListLine:visibleLine |
|
1400 ] |
|
1401 ]. |
|
1402 ^ nil |
|
1403 ! |
|
1404 |
|
1405 widthForScrollBetween:start and:end |
|
1406 "has to be redefined since WHOLE line is inverted/modified sometimes" |
|
1407 |
|
1408 | anySelectionInRange | |
|
1409 |
|
1410 selection notNil ifTrue:[ |
|
1411 multipleSelectOk ifTrue:[ |
|
1412 anySelectionInRange := false. |
|
1413 selection do:[:s | |
|
1414 (s between:start and:end) ifTrue:[ |
|
1415 anySelectionInRange := true |
|
1416 ] |
885 ] |
1417 ] |
886 ] ifFalse:[ |
1418 ] ifFalse:[ |
887 self redrawElement:prevSelection |
1419 anySelectionInRange := selection between:start and:end |
888 ] |
|
889 ]. |
|
890 selection := newSelection. |
|
891 (selection isCollection) ifTrue:[ |
|
892 selection do:[:line | |
|
893 self redrawElement:line |
|
894 ] |
1420 ] |
895 ] ifFalse:[ |
1421 ] ifFalse:[ |
896 self redrawElement:selection |
1422 anySelectionInRange := false |
|
1423 ]. |
|
1424 |
|
1425 anySelectionInRange ifTrue:[ |
|
1426 ^ width |
|
1427 " |
|
1428 self is3D ifFalse:[ |
|
1429 ^ width |
|
1430 ]. |
|
1431 ( #(next openwin) includes:style) ifTrue:[ |
|
1432 ^ width |
|
1433 ]. |
|
1434 viewBackground = background ifFalse:[ |
|
1435 ^ width |
|
1436 ] |
|
1437 " |
|
1438 ]. |
|
1439 ^ super widthForScrollBetween:start and:end |
|
1440 ! |
|
1441 |
|
1442 visibleLineNeedsSpecialCare:visLineNr |
|
1443 |listLine| |
|
1444 |
|
1445 listLine := self visibleLineToListLine:visLineNr. |
|
1446 listLine isNil ifTrue:[^ false]. |
|
1447 (self isInSelection:listLine) ifTrue:[^ true]. |
|
1448 listAttributes notNil ifTrue:[ |
|
1449 (listLine <= listAttributes size) ifTrue:[ |
|
1450 ^ (listAttributes at:listLine) notNil |
|
1451 ] |
|
1452 ]. |
|
1453 ^ false |
|
1454 ! |
|
1455 |
|
1456 checkRemovingSelection:lineNr |
|
1457 "when a line is removed, we have to adjust selection" |
|
1458 |
|
1459 |newSelection| |
|
1460 |
|
1461 selection notNil ifTrue:[ |
|
1462 multipleSelectOk ifTrue:[ |
|
1463 newSelection := OrderedCollection new. |
|
1464 selection do:[:sel | |
|
1465 sel < lineNr ifTrue:[ |
|
1466 newSelection add:sel |
|
1467 ] ifFalse:[ |
|
1468 sel > lineNr ifTrue:[ |
|
1469 newSelection add:(sel - 1) |
|
1470 ] |
|
1471 "otherwise remove it from the selection" |
|
1472 ] |
|
1473 ]. |
|
1474 newSelection size == 0 ifTrue:[ |
|
1475 selection := nil |
|
1476 ] ifFalse:[ |
|
1477 selection := newSelection |
|
1478 ] |
|
1479 ] ifFalse:[ |
|
1480 selection == lineNr ifTrue:[ |
|
1481 selection := nil |
|
1482 ] ifFalse:[ |
|
1483 selection > lineNr ifTrue:[ |
|
1484 selection := selection - 1 |
|
1485 ] |
|
1486 ] |
|
1487 ] |
897 ] |
1488 ] |
898 |
1489 ! |
899 ! |
1490 |
900 |
1491 scrollSelectDown |
901 selection:aNumberOrNil |
1492 "auto scroll action; scroll and reinstall timed-block" |
902 "select line, aNumber or deselect if argument is nil; |
1493 |
903 scroll to make the selected line visible" |
1494 self scrollDown. |
904 |
1495 Processor addTimedBlock:autoScrollBlock afterSeconds:autoScrollDeltaT. |
905 self selectWithoutScroll:aNumberOrNil. |
1496 ! |
906 selection notNil ifTrue:[self makeSelectionVisible] |
1497 |
907 ! |
1498 scrollSelectUp |
908 |
1499 "auto scroll action; scroll and reinstall timed-block" |
909 makeSelectionVisible |
1500 |
910 "scroll to make the selection line visible" |
1501 self scrollUp. |
911 |
1502 Processor addTimedBlock:autoScrollBlock afterSeconds:autoScrollDeltaT. |
912 |line| |
1503 ! ! |
913 |
1504 |
914 selection notNil ifTrue:[ |
1505 !SelectionInListView methodsFor:'event handling'! |
915 (selection isCollection) ifTrue:[ |
1506 |
916 line := selection first. |
1507 buttonRelease:button x:x y:y |
|
1508 "stop any autoscroll" |
|
1509 |
|
1510 self stopAutoScroll |
|
1511 ! |
|
1512 |
|
1513 buttonPress:button x:x y:y |
|
1514 |oldSelection listLineNr| |
|
1515 |
|
1516 ((button == 1) or:[button == #select]) ifTrue:[ |
|
1517 enabled ifTrue:[ |
|
1518 listLineNr := self visibleLineToListLine:(self visibleLineOfY:y). |
|
1519 listLineNr notNil ifTrue:[ |
|
1520 (toggleSelect |
|
1521 and:[self isInSelection:listLineNr]) ifTrue:[ |
|
1522 oldSelection := selection copy. |
|
1523 self removeFromSelection:listLineNr |
|
1524 ] ifFalse:[ |
|
1525 (self line:listLineNr hasAttribute:#disabled) ifTrue:[^ self]. |
|
1526 |
|
1527 (selectConditionBlock notNil |
|
1528 and:[(selectConditionBlock value:listLineNr) not]) ifTrue:[^ self]. |
|
1529 |
|
1530 (toggleSelect and:[multipleSelectOk]) ifTrue:[ |
|
1531 oldSelection := selection copy. |
|
1532 self addToSelection:listLineNr |
|
1533 ] ifFalse:[ |
|
1534 oldSelection := selection copy. |
|
1535 self selectWithoutScroll:listLineNr. |
|
1536 ]. |
|
1537 ]. |
|
1538 ((ignoreReselect not and:[selection notNil]) |
|
1539 or:[selection ~= oldSelection]) ifTrue:[ |
|
1540 self selectionChangedFrom:oldSelection. |
|
1541 ]. |
|
1542 clickLine := listLineNr |
|
1543 ]. |
|
1544 ] |
|
1545 ] ifFalse:[ |
|
1546 super buttonPress:button x:x y:y |
|
1547 ] |
|
1548 ! |
|
1549 |
|
1550 sizeChanged:how |
|
1551 "if there is a selection, make certain, its visible |
|
1552 after the sizechange" |
|
1553 |
|
1554 |first wasAtEnd| |
|
1555 |
|
1556 wasAtEnd := (firstLineShown + nFullLinesShown) >= self size. |
|
1557 |
|
1558 super sizeChanged:how. |
|
1559 |
|
1560 shown ifTrue:[ |
|
1561 selection notNil ifTrue:[ |
|
1562 multipleSelectOk ifTrue:[ |
|
1563 first := selection first |
|
1564 ] ifFalse:[ |
|
1565 first := selection |
|
1566 ]. |
|
1567 first notNil ifTrue:[self makeLineVisible:first] |
917 ] ifFalse:[ |
1568 ] ifFalse:[ |
918 line := selection |
1569 " |
919 ]. |
1570 if we where at the end before, move to the end again. |
920 self makeLineVisible:line |
1571 Still to be seen, if this is better in real life ... |
|
1572 " |
|
1573 wasAtEnd ifTrue:[ |
|
1574 "at end" |
|
1575 self scrollToBottom |
|
1576 ] |
|
1577 ] |
921 ] |
1578 ] |
922 ! |
1579 ! |
923 |
1580 |
924 isInSelection:aNumber |
1581 keyPress:key x:x y:y |
925 "return true, if line, aNumber is in the selection" |
1582 "handle keyboard input" |
926 |
1583 |
927 selection isNil ifTrue:[^ false]. |
1584 |index startSearch backSearch searchPrefix| |
928 selection isCollection ifTrue:[ |
1585 |
929 ^ (selection includes:aNumber) |
1586 (key == #CursorUp) ifTrue:[ |
930 ]. |
1587 index := self previousBeforeSelection. |
931 ^ (aNumber == selection) |
1588 self key:key select:index x:x y:y. |
932 ! |
1589 ^ self |
933 |
1590 ]. |
934 toggleSelect:aBoolean |
1591 (key == #CursorDown) ifTrue:[ |
935 "turn on/off toggle select" |
1592 index := self nextAfterSelection. |
936 |
1593 self key:key select:index x:x y:y. |
937 toggleSelect := aBoolean. |
1594 ^ self |
938 ! |
1595 ]. |
939 |
1596 "/ |
940 multipleSelectOk:aBoolean |
1597 "/ stupid: Home and End are cought in ScrollableView |
941 "allow/disallow multiple selections" |
1598 "/ we normally do not get them ... |
942 |
1599 "/ (need to call handlesKey: from there ... |
943 multipleSelectOk := aBoolean. |
1600 "/ ... and implement it here) |
944 aBoolean ifTrue:[ |
1601 "/ |
945 self enableButtonMotionEvents |
1602 (key == #Home) ifTrue:[ |
|
1603 self key:key select:1 x:x y:y. |
|
1604 ^ self |
|
1605 ]. |
|
1606 (key == #End) ifTrue:[ |
|
1607 index := self size. |
|
1608 self key:key select:index x:x y:y. |
|
1609 ^ self |
|
1610 ]. |
|
1611 key == #Return ifTrue:[ |
|
1612 returnKeyActionStyle == #doubleClick ifTrue:[ |
|
1613 selection notNil ifTrue:[ |
|
1614 self doubleClicked |
|
1615 ]. |
|
1616 ^ self |
|
1617 ]. |
|
1618 returnKeyActionStyle ~~ #pass ifTrue:[ |
|
1619 ^ self |
|
1620 ]. |
|
1621 ]. |
|
1622 |
|
1623 " |
|
1624 alphabetic keys: search for next entry |
|
1625 starting with keys character. If shift is pressed, search backward |
|
1626 " |
|
1627 (self size > 0 |
|
1628 and:[key isCharacter |
|
1629 and:[key isLetter]]) ifTrue:[ |
|
1630 keyActionStyle isNil ifTrue:[^ self]. |
|
1631 keyActionStyle == #pass ifFalse:[ |
|
1632 searchPrefix := key asLowercase asString. |
|
1633 |
|
1634 "/ ... isISearch... ifFalse:[ |
|
1635 "/ iSearchString := '' |
|
1636 "/ ] ifTrue:[ |
|
1637 "/ iSearchString := iSearchString , searchPrefix. |
|
1638 "/ searchPrefix := iSearchString |
|
1639 "/ ]. |
|
1640 |
|
1641 backSearch := device shiftDown. |
|
1642 backSearch ifTrue:[ |
|
1643 selection notNil ifTrue:[ |
|
1644 selection size > 0 ifTrue:[ |
|
1645 startSearch := selection first - 1 |
|
1646 ] ifFalse:[ |
|
1647 startSearch := selection - 1 |
|
1648 ] |
|
1649 ] ifFalse:[ |
|
1650 startSearch := self size |
|
1651 ]. |
|
1652 startSearch < 1 ifTrue:[ |
|
1653 startSearch := self size. |
|
1654 ]. |
|
1655 ] ifFalse:[ |
|
1656 selection notNil ifTrue:[ |
|
1657 selection size > 0 ifTrue:[ |
|
1658 startSearch := selection last + 1 |
|
1659 ] ifFalse:[ |
|
1660 startSearch := selection + 1 |
|
1661 ] |
|
1662 ] ifFalse:[ |
|
1663 startSearch := 1 |
|
1664 ]. |
|
1665 startSearch > self size ifTrue:[ |
|
1666 startSearch := 1. |
|
1667 ]. |
|
1668 ]. |
|
1669 index := startSearch. |
|
1670 [true] whileTrue:[ |
|
1671 (((self at:index) asString) asLowercase startsWith:searchPrefix) ifTrue:[ |
|
1672 index = selection ifTrue:[^ self]. |
|
1673 ^ self key:key select:index x:x y:y |
|
1674 ]. |
|
1675 backSearch ifTrue:[ |
|
1676 index := index - 1. |
|
1677 index < 1 ifTrue:[index := self size] |
|
1678 ] ifFalse:[ |
|
1679 index := index + 1. |
|
1680 index > self size ifTrue:[index := 1]. |
|
1681 ]. |
|
1682 index == startSearch ifTrue:[ |
|
1683 ^ self |
|
1684 ] |
|
1685 ] |
|
1686 ]. |
|
1687 ]. |
|
1688 ^ super keyPress:key x:x y:y |
|
1689 ! |
|
1690 |
|
1691 buttonMotion:buttonMask x:x y:y |
|
1692 "mouse-move while button was pressed - handle selection changes" |
|
1693 |
|
1694 |movedVisibleLine movedLine delta oldSelection oldSelCount| |
|
1695 |
|
1696 "is it the select or 1-button ?" |
|
1697 (device buttonMotionMask:buttonMask includesButton:#select) ifFalse:[ |
|
1698 (device buttonMotionMask:buttonMask includesButton:1) ifFalse:[ |
|
1699 ^ self |
|
1700 ]. |
|
1701 ]. |
|
1702 |
|
1703 clickLine isNil ifTrue:[^ self]. |
|
1704 |
|
1705 "if moved outside of view, start autoscroll" |
|
1706 (y < 0) ifTrue:[ |
|
1707 self compressMotionEvents:false. |
|
1708 self startAutoScrollUp:y. |
|
1709 ^ self |
|
1710 ]. |
|
1711 (y > height) ifTrue:[ |
|
1712 self compressMotionEvents:false. |
|
1713 self startAutoScrollDown:(y - height). |
|
1714 ^ self |
|
1715 ]. |
|
1716 |
|
1717 "move inside - stop autoscroll if any" |
|
1718 self stopAutoScroll. |
|
1719 |
|
1720 movedVisibleLine := self visibleLineOfY:y. |
|
1721 movedLine := self visibleLineToAbsoluteLine:movedVisibleLine. |
|
1722 (movedLine == clickLine) ifTrue:[^ self]. |
|
1723 |
|
1724 multipleSelectOk ifTrue:[ |
|
1725 delta := (clickLine < movedLine) ifTrue:[1] ifFalse:[-1]. |
|
1726 |
|
1727 oldSelection := selection. |
|
1728 oldSelCount := selection size. |
|
1729 |
|
1730 (clickLine+delta) to:movedLine by:delta do:[:line | |
|
1731 (self isInSelection:line) ifTrue:[ |
|
1732 self removeFromSelection:line |
|
1733 ] ifFalse:[ |
|
1734 self addToSelection:line |
|
1735 ] |
|
1736 ]. |
|
1737 ((selection ~= oldSelection) |
|
1738 or:[selection size ~~ oldSelCount]) ifTrue:[ |
|
1739 self selectionChangedFrom:oldSelection. |
|
1740 ] |
946 ] ifFalse:[ |
1741 ] ifFalse:[ |
947 self disableButtonMotionEvents |
1742 "/ self selectWithoutScroll:movedLine |
948 ] |
1743 ]. |
|
1744 |
|
1745 clickLine := movedLine |
|
1746 ! |
|
1747 |
|
1748 key:key select:index x:x y:y |
|
1749 "select an entry by a keyboard action. |
|
1750 This is treated like a doubleClick on that entry" |
|
1751 |
|
1752 |oldSelection| |
|
1753 |
|
1754 (selectConditionBlock isNil or:[selectConditionBlock value:index]) ifTrue:[ |
|
1755 keyActionStyle notNil ifTrue:[ |
|
1756 keyActionStyle == #pass ifTrue:[ |
|
1757 ^ super keyPress:key x:x y:y |
|
1758 ]. |
|
1759 oldSelection := selection. |
|
1760 self selection:index. |
|
1761 self selectionChangedFrom:oldSelection. |
|
1762 keyActionStyle == #selectAndDoubleClick ifTrue:[ |
|
1763 self doubleClicked |
|
1764 ] |
|
1765 ] |
|
1766 ]. |
|
1767 ! |
|
1768 |
|
1769 buttonMultiPress:button x:x y:y |
|
1770 ((button == 1) or:[button == #select]) ifTrue:[ |
|
1771 "/ doubleClickActionBlock isNil ifTrue:[ |
|
1772 "/ self buttonPress:button x:x y:y |
|
1773 "/ ]. |
|
1774 self doubleClicked. |
|
1775 ] ifFalse:[ |
|
1776 super buttonMultiPress:button x:x y:y |
|
1777 ] |
|
1778 ! |
|
1779 |
|
1780 buttonShiftPress:button x:x y:y |
|
1781 "add to the selection (if multipleSelectOk); otherwise, |
|
1782 behave like normal select" |
|
1783 |
|
1784 |oldSelection listLineNr| |
|
1785 |
|
1786 ((button == 1) or:[button == #select]) ifTrue:[ |
|
1787 toggleSelect ifTrue:[ |
|
1788 ^ self buttonPress:button x:x y:y |
|
1789 ]. |
|
1790 enabled ifTrue:[ |
|
1791 listLineNr := self visibleLineToListLine:(self visibleLineOfY:y). |
|
1792 listLineNr notNil ifTrue:[ |
|
1793 (self line:listLineNr hasAttribute:#disabled) ifTrue:[^ self]. |
|
1794 |
|
1795 (selectConditionBlock notNil |
|
1796 and:[(selectConditionBlock value:listLineNr) not]) ifTrue:[^ self]. |
|
1797 ]. |
|
1798 oldSelection := selection copy. |
|
1799 listLineNr notNil ifTrue: [ |
|
1800 multipleSelectOk ifTrue:[ |
|
1801 (self isInSelection:listLineNr) ifTrue:[ |
|
1802 self removeFromSelection:listLineNr |
|
1803 ] ifFalse:[ |
|
1804 self addToSelection:listLineNr |
|
1805 ] |
|
1806 ] ifFalse:[ |
|
1807 self selectWithoutScroll:listLineNr |
|
1808 ] |
|
1809 ]. |
|
1810 ((ignoreReselect not and:[selection notNil]) |
|
1811 or:[selection ~= oldSelection]) ifTrue:[ |
|
1812 self selectionChangedFrom:oldSelection. |
|
1813 ]. |
|
1814 clickLine := listLineNr |
|
1815 ] |
|
1816 ] ifFalse:[ |
|
1817 super buttonShiftPress:button x:x y:y |
|
1818 ] |
|
1819 ! |
|
1820 |
|
1821 doubleClicked |
|
1822 doubleClickActionBlock notNil ifTrue:[doubleClickActionBlock value:selection]. |
|
1823 (model notNil and:[doubleClickMsg notNil]) ifTrue:[ |
|
1824 self sendChangeMessage:doubleClickMsg with:(self argForChangeMessage). |
|
1825 ]. |
|
1826 ! ! |
|
1827 |
|
1828 !SelectionInListView methodsFor:'accessing-actions'! |
|
1829 |
|
1830 action:aBlock |
|
1831 "set the action block to be performed on select" |
|
1832 |
|
1833 actionBlock := aBlock |
|
1834 ! |
|
1835 |
|
1836 doubleClickAction:aBlock |
|
1837 "set the double click action block to be performed on select" |
|
1838 |
|
1839 doubleClickActionBlock := aBlock |
949 ! |
1840 ! |
950 |
1841 |
951 selectConditionBlock:aBlock |
1842 selectConditionBlock:aBlock |
952 "set the conditionBlock; this block is evaluated before a selection |
1843 "set the conditionBlock; this block is evaluated before a selection |
953 change is performed; the change will not be done, if the evaluation |
1844 change is performed; the change will not be done, if the evaluation |
955 the SystemBrowser" |
1846 the SystemBrowser" |
956 |
1847 |
957 selectConditionBlock := aBlock |
1848 selectConditionBlock := aBlock |
958 ! |
1849 ! |
959 |
1850 |
960 strikeOut:aBoolean |
1851 useIndex:aBoolean |
961 "turn on/off strikeOut mode" |
1852 "set/clear the useIndex flag. If set, both actionBlock and change-messages |
962 |
1853 are passed the index(indices) of the selection as argument. |
963 strikeOut := aBoolean. |
1854 If clear, the value(s) (i.e. the selected string) is passed. |
964 ! |
1855 Default is true." |
965 |
1856 |
966 selection |
1857 useIndex := aBoolean |
967 "return the selection line nr or collection of line numbers" |
1858 ! |
968 |
1859 |
969 ^ selection |
1860 keyActionStyle:aSymbol |
970 ! |
1861 "defines how the view should respond to alpha-keys pressed. |
971 |
1862 Possible values are: |
972 ignoreReselect:aBoolean |
1863 #select -> will select next entry starting with that |
973 "set/clear the ignoreReselect flag - |
1864 character and perform the click-action |
974 if set, a click on an already selected entry is ignored. |
1865 |
975 Otherwise the notification is done, even if no |
1866 #selectAndDoubleclick -> will select next & perform double-click action |
976 change in the selection occurs. |
1867 |
977 (for example, in browser to update a method)" |
1868 #pass -> will pass key to superclass (i.e. no special treatment) |
978 |
1869 |
979 ignoreReselect := aBoolean |
1870 nil -> will ignore key |
980 ! |
1871 |
981 |
1872 the default (set in #initialize) is #select |
982 enable |
|
983 "enable selections" |
|
984 |
|
985 enabled := true |
|
986 ! |
|
987 |
|
988 disable |
|
989 "disable selections" |
|
990 |
|
991 enabled := false |
|
992 ! |
|
993 |
|
994 selectionValue |
|
995 "return the selection value i.e. the text in the selected line. |
|
996 For multiple selections a collection containing the entries is returned." |
|
997 |
|
998 selection isNil ifTrue:[^ nil]. |
|
999 (selection isCollection) ifTrue:[ |
|
1000 ^ selection collect:[:nr | self at:nr] |
|
1001 ]. |
|
1002 ^ self at:selection |
|
1003 |
|
1004 ! |
|
1005 |
|
1006 numberOfSelections |
|
1007 "return the number of selected entries" |
|
1008 |
|
1009 |sz| |
|
1010 |
|
1011 selection isNil ifTrue:[^ 0]. |
|
1012 sz := selection size. |
|
1013 sz > 0 ifTrue:[^ sz]. |
|
1014 ^ 1 |
|
1015 ! |
|
1016 |
|
1017 hasSelection |
|
1018 "return true, if the view has a selection" |
|
1019 |
|
1020 ^ selection notNil |
|
1021 ! |
|
1022 |
|
1023 deselectWithoutRedraw |
|
1024 "deselect - no redraw" |
|
1025 |
|
1026 selection := nil |
|
1027 ! |
|
1028 |
|
1029 deselect |
|
1030 "deselect" |
|
1031 |
|
1032 self selection:nil |
|
1033 ! |
|
1034 |
|
1035 selectElement:anObject |
|
1036 "select the element with same printString as the argument, anObject. |
|
1037 Scroll to make the new selection visible." |
|
1038 |
|
1039 |lineNo| |
|
1040 |
|
1041 list notNil ifTrue:[ |
|
1042 lineNo := list indexOf:(anObject printString) ifAbsent:[]. |
|
1043 lineNo notNil ifTrue:[self selection:lineNo] |
|
1044 ] |
|
1045 ! |
|
1046 |
|
1047 valueIsInSelection:someString |
|
1048 "return true, if someString is in the selection" |
|
1049 |
|
1050 |sel| |
|
1051 |
|
1052 selection isNil ifTrue:[^ false]. |
|
1053 sel := self selectionValue. |
|
1054 self numberOfSelections > 1 ifTrue:[ |
|
1055 ^ (sel includes:someString) |
|
1056 ]. |
|
1057 ^ (someString = sel) |
|
1058 ! |
|
1059 |
|
1060 selectElementWithoutScroll:anObject |
|
1061 "select the element with same printString as the argument, anObject. |
|
1062 Do not scroll." |
|
1063 |
|
1064 |lineNo| |
|
1065 |
|
1066 list notNil ifTrue:[ |
|
1067 lineNo := list indexOf:(anObject printString) ifAbsent:[]. |
|
1068 lineNo notNil ifTrue:[self selectWithoutScroll:lineNo] |
|
1069 ] |
|
1070 ! |
|
1071 |
|
1072 selectAll |
|
1073 "select all entries." |
|
1074 |
|
1075 |oldSelection| |
|
1076 |
|
1077 oldSelection := selection. |
|
1078 selection := OrderedCollection withAll:(1 to:self size). |
|
1079 shown ifTrue:[self redraw]. |
|
1080 self selectionChangedFrom:oldSelection. |
|
1081 ! |
|
1082 |
|
1083 addElementToSelection:anObject |
|
1084 "add the element with the same printstring as the argument, anObject |
|
1085 to the selection. The entry is searched by comparing printStrings. |
|
1086 No scrolling is done. Returns true, if ok, false if no such entry |
|
1087 was found." |
|
1088 |
|
1089 |lineNo str| |
|
1090 |
|
1091 str := anObject printString. |
|
1092 lineNo := list findFirst:[:entry | str = entry printString]. |
|
1093 lineNo ~~ 0 ifTrue:[ |
|
1094 self addToSelection:lineNo. |
|
1095 ^ true |
|
1096 ]. |
|
1097 ^ false |
|
1098 ! |
|
1099 |
|
1100 addToSelection:aNumber |
|
1101 "add entry, aNumber to the selection. No scrolling is done." |
|
1102 |
|
1103 (self isValidSelection:aNumber) ifFalse:[^ self]. |
|
1104 |
|
1105 selection isNil ifTrue:[^ self selectWithoutScroll:aNumber]. |
|
1106 selection isCollection ifTrue:[ |
|
1107 (selection includes:aNumber) ifTrue:[^ self]. |
|
1108 (selectConditionBlock notNil |
|
1109 and:[(selectConditionBlock value:aNumber) not]) ifTrue:[^ self]. |
|
1110 selection add:aNumber |
|
1111 ] ifFalse:[ |
|
1112 (aNumber == selection) ifTrue:[^ self]. |
|
1113 (selectConditionBlock notNil |
|
1114 and:[(selectConditionBlock value:aNumber) not]) ifTrue:[^ self]. |
|
1115 selection := OrderedCollection with:selection with:aNumber |
|
1116 ]. |
|
1117 self redrawElement:aNumber |
|
1118 ! |
|
1119 |
|
1120 removeFromSelection:aNumber |
|
1121 "remove entry, aNumber from the selection." |
|
1122 |
|
1123 selection isNil ifTrue:[^ self]. |
|
1124 |
|
1125 selection isCollection ifTrue:[ |
|
1126 (selection includes:aNumber) ifFalse:[^ self]. |
|
1127 selection remove:aNumber. |
|
1128 selection size == 1 ifTrue:[ |
|
1129 selection := selection first |
|
1130 ] ifFalse:[ |
|
1131 selection size == 0 ifTrue:[ |
|
1132 selection := nil |
|
1133 ] |
|
1134 ] |
|
1135 ] ifFalse:[ |
|
1136 (aNumber == selection) ifFalse:[^ self]. |
|
1137 selection := nil |
|
1138 ]. |
|
1139 self redrawElement:aNumber |
|
1140 ! |
|
1141 |
|
1142 nextAfterSelection |
|
1143 "return the number of the next selectable entry after the selection. |
|
1144 Wrap at end." |
|
1145 |
|
1146 |next| |
|
1147 |
|
1148 selection isNil ifTrue:[ |
|
1149 next := firstLineShown |
|
1150 ] ifFalse:[ |
|
1151 selection size ~~ 0 ifTrue:[ |
|
1152 next := selection max + 1 |
|
1153 ] ifFalse:[ |
|
1154 next := selection + 1 |
|
1155 ]. |
|
1156 ]. |
|
1157 (self isValidSelection:next) ifFalse:[ |
|
1158 next > self size ifTrue:[ |
|
1159 next := 1. |
|
1160 ] ifFalse:[ |
|
1161 [next <= self size |
|
1162 and:[(self isValidSelection:next) not]] whileTrue:[ |
|
1163 next := next + 1 |
|
1164 ]. |
|
1165 ]. |
|
1166 ]. |
|
1167 (self isValidSelection:next) ifFalse:[ |
|
1168 next := nil |
|
1169 ]. |
|
1170 ^ next |
|
1171 ! |
|
1172 |
|
1173 previousBeforeSelection |
|
1174 "return the number of the previous selectable entry before the selection. |
|
1175 Wrap at beginning." |
|
1176 |
|
1177 |prev| |
|
1178 |
|
1179 selection isNil ifTrue:[ |
|
1180 prev := firstLineShown - 1 |
|
1181 ] ifFalse:[ |
|
1182 selection size ~~ 0 ifTrue:[ |
|
1183 prev := selection min - 1 |
|
1184 ] ifFalse:[ |
|
1185 prev := selection - 1 |
|
1186 ]. |
|
1187 ]. |
|
1188 (self isValidSelection:prev) ifFalse:[ |
|
1189 prev < 1 ifTrue:[ |
|
1190 prev := self size. |
|
1191 ] ifFalse:[ |
|
1192 [prev >= 1 |
|
1193 and:[(self isValidSelection:prev) not]] whileTrue:[ |
|
1194 prev := prev - 1 |
|
1195 ]. |
|
1196 ]. |
|
1197 ]. |
|
1198 (self isValidSelection:prev) ifFalse:[ |
|
1199 prev := nil |
|
1200 ]. |
|
1201 ^ prev |
|
1202 |
|
1203 ! |
|
1204 |
|
1205 toggleSelection:aNumber |
|
1206 "toggle selection-state of entry, aNumber" |
|
1207 |
|
1208 (self isInSelection:aNumber) ifTrue:[ |
|
1209 self removeFromSelection:aNumber |
|
1210 ] ifFalse:[ |
|
1211 self addToSelection:aNumber |
|
1212 ] |
|
1213 ! |
|
1214 |
|
1215 selectNext |
|
1216 "select next line or first visible if there is currrently no selection. |
|
1217 Wrap at end." |
|
1218 |
|
1219 self selection:(self nextAfterSelection) |
|
1220 ! |
|
1221 |
|
1222 selectPrevious |
|
1223 "select previous line or previous visible if there is currently no selection. |
|
1224 Wrap at beginning." |
|
1225 |
|
1226 self selection:(self previouseBeforeSelection). |
|
1227 ! |
|
1228 |
|
1229 selectionDo:aBlock |
|
1230 "perform aBlock for each nr in the selection. |
|
1231 For single selection, it is called once for the items nr. |
|
1232 For multiple selections, it is called for each." |
|
1233 |
|
1234 |sz| |
|
1235 |
|
1236 selection isNil ifTrue:[^ self]. |
|
1237 sz := selection size. |
|
1238 sz > 0 ifTrue:[ |
|
1239 selection do:aBlock |
|
1240 ] ifFalse:[ |
|
1241 aBlock value:selection |
|
1242 ]. |
|
1243 ! |
|
1244 |
|
1245 argForChangeMessage |
|
1246 "return the argument for a selectionChange; |
|
1247 depending on the setting of useIndex, this is either the numeric |
|
1248 index of the selection or the value (i.e. the string)" |
|
1249 |
|
1250 useIndex == false ifTrue:[ |
|
1251 printItems ifFalse:[ |
|
1252 ^ self selectionValue |
|
1253 ]. |
|
1254 ^ items at:selection |
|
1255 ]. |
|
1256 "true or nil - strange" |
|
1257 ^ selection. |
|
1258 ! |
|
1259 |
|
1260 selectionChangedFrom:oldSelection |
|
1261 "selection has changed. Call actionblock and/or send changeMessage if defined" |
|
1262 |
|
1263 |arg| |
|
1264 |
|
1265 arg := self argForChangeMessage. |
|
1266 " |
1873 " |
1267 the ST/X way of doing things - perform actionBlock |
1874 |
|
1875 keyActionStyle := aSymbol |
|
1876 ! |
|
1877 |
|
1878 returnKeyActionStyle:aSymbol |
|
1879 "defines how the view should respond to a return key pressed. |
|
1880 Possible values are: |
|
1881 #doubleClick -> perform double-click action |
|
1882 |
|
1883 #pass -> will pass key to superclass (i.e. no special treatment) |
|
1884 |
|
1885 nil -> will ignore key |
|
1886 |
|
1887 the default (set in #initialize) is #doubleClick |
1268 " |
1888 " |
1269 actionBlock notNil ifTrue:[actionBlock value:arg]. |
1889 |
1270 " |
1890 returnKeyActionStyle := aSymbol |
1271 the ST-80 way of doing things - notify model via changeMsg |
|
1272 " |
|
1273 "/ ST80 sends 0 as index, if the same selection is reselected ... |
|
1274 selection == oldSelection ifTrue:[ |
|
1275 arg := 0 |
|
1276 ]. |
|
1277 self sendChangeMessageWith:arg |
|
1278 ! |
|
1279 |
|
1280 selectionAsCollection |
|
1281 "return the selection as a collection of line numbers" |
|
1282 |
|
1283 selection size = 0 ifTrue:[ |
|
1284 selection isNil ifTrue:[^ #()]. |
|
1285 ^ (OrderedCollection new) add:selection; yourself. |
|
1286 ] ifFalse:[ |
|
1287 ^ selection |
|
1288 ]. |
|
1289 ! ! |
1891 ! ! |
1290 |
1892 |
1291 !SelectionInListView methodsFor:'accessing'! |
1893 !SelectionInListView methodsFor:'accessing-attributes'! |
1292 |
1894 |
1293 line:lineNr hasAttribute:aSymbol |
1895 line:lineNr hasAttribute:aSymbol |
1294 "return true, if line nr has attribute, aSymbol; |
1896 "return true, if line nr has attribute, aSymbol; |
1295 currently supported attributes are: |
1897 currently supported attributes are: |
1296 #halfIntensity |
1898 #halfIntensity |
1504 |
2118 |
1505 add:aValue beforeIndex:index |
2119 add:aValue beforeIndex:index |
1506 "must recompute our current selections" |
2120 "must recompute our current selections" |
1507 |
2121 |
1508 selection notNil ifTrue:[ |
2122 selection notNil ifTrue:[ |
1509 selection size = 0 ifTrue:[ |
2123 multipleSelectOk ifTrue:[ |
1510 selection >= index ifTrue:[ |
|
1511 selection := selection + 1. |
|
1512 ]. |
|
1513 ] ifFalse:[ |
|
1514 selection := selection collect:[ :sel | |
2124 selection := selection collect:[ :sel | |
1515 sel >= index ifTrue:[ |
2125 sel >= index ifTrue:[ |
1516 sel + 1 |
2126 sel + 1 |
1517 ] ifFalse:[ |
2127 ] ifFalse:[ |
1518 sel |
2128 sel |
1519 ] |
2129 ] |
1520 ]. |
2130 ]. |
|
2131 ] ifFalse:[ |
|
2132 selection >= index ifTrue:[ |
|
2133 selection := selection + 1. |
|
2134 ]. |
1521 ]. |
2135 ]. |
1522 ]. |
2136 ]. |
1523 ^ super add:aValue beforeIndex:index. |
2137 ^ super add:aValue beforeIndex:index. |
1524 ! |
|
1525 |
|
1526 useIndex:aBoolean |
|
1527 "set/clear the useIndex flag. If set, both actionBlock and change-messages |
|
1528 are passed the index of the selection as argument. If clear, the value |
|
1529 (i.e. the selected string) is passed. |
|
1530 Default is true." |
|
1531 |
|
1532 useIndex := aBoolean |
|
1533 ! ! |
|
1534 |
|
1535 !SelectionInListView methodsFor:'accessing-mvc'! |
|
1536 |
|
1537 on:aModel printItems:print oneItem:one aspect:aspectSymbol change:changeSymbol |
|
1538 list:listSymbol menu:menuSymbol initialSelection:initialSymbol useIndex:use |
|
1539 |
|
1540 "ST-80 compatibility" |
|
1541 |
|
1542 aspectMsg := aspectSymbol. |
|
1543 changeMsg := changeSymbol. |
|
1544 listMsg := listSymbol. |
|
1545 menuMsg := menuSymbol. |
|
1546 initialSelectionMsg := initialSymbol. |
|
1547 printItems := print. |
|
1548 oneItem := one. |
|
1549 useIndex := use. |
|
1550 ignoreReselect := false. "/ ST80 behavior |
|
1551 self model:aModel. |
|
1552 ! |
|
1553 |
|
1554 doubleClickMessage |
|
1555 "return the symbol with which the model (if any) is informed about |
|
1556 double-click. If nil (which is the default), it is not informed." |
|
1557 |
|
1558 ^ doubleClickMsg |
|
1559 ! |
|
1560 |
|
1561 doubleClickMessage:aSymbol |
|
1562 "set the symbol with which the model (if any) is informed about double-click. |
|
1563 If nil (which is the default), it is not informed." |
|
1564 |
|
1565 doubleClickMsg := aSymbol |
|
1566 ! |
|
1567 |
|
1568 doubleClick:aSymbol |
|
1569 "set the symbol with which the model is informed about double-click. |
|
1570 OBSOLETE: please use #doubleClickMessage:" |
|
1571 |
|
1572 self obsoleteMethodWarning:'please use #doubleClickMessage:'. |
|
1573 doubleClickMsg := aSymbol |
|
1574 ! |
|
1575 |
|
1576 selectionMessage |
|
1577 "return the symbol by which the model informes me about a changed |
|
1578 selectionIndex. This is used both in change notification and to |
|
1579 actually aquire a new selection value." |
|
1580 |
|
1581 ^ initialSelectionMsg |
|
1582 ! |
|
1583 |
|
1584 selectionMessage:aSymbol |
|
1585 "set the symbol by which the model informes me about a changed |
|
1586 selectionIndex. This is used both in change notification and to |
|
1587 actually aquire a new selection value." |
|
1588 |
|
1589 initialSelectionMsg := aSymbol |
|
1590 ! |
|
1591 |
|
1592 addModelInterfaceTo:aDictionary |
|
1593 "see comment in View>>modelInterface" |
|
1594 |
|
1595 super addModelInterfaceTo:aDictionary. |
|
1596 aDictionary at:#doubleClickMessage put:doubleClickMsg. |
|
1597 aDictionary at:#selectionMessage put:initialSelectionMsg. |
|
1598 |
|
1599 " |
|
1600 SelectionInListView new modelInterface |
|
1601 " |
|
1602 ! ! |
|
1603 |
|
1604 !SelectionInListView methodsFor:'private'! |
|
1605 |
|
1606 isValidSelection:aNumber |
|
1607 "return true, if aNumber is ok for a selection lineNo" |
|
1608 |
|
1609 aNumber isNil ifTrue:[^ false]. |
|
1610 (aNumber isCollection) ifTrue:[ |
|
1611 (multipleSelectOk or:[aNumber size = 1]) ifFalse:[^ false]. |
|
1612 aNumber do:[ :line | |
|
1613 (line between:1 and:self size) ifFalse:[^ false]. |
|
1614 ]. |
|
1615 ^ true. |
|
1616 ] ifFalse:[ |
|
1617 ^ (aNumber between:1 and:self size). |
|
1618 ]. |
|
1619 |
|
1620 ! |
|
1621 |
|
1622 widthForScrollBetween:start and:end |
|
1623 "has to be redefined since WHOLE line is inverted/modified sometimes" |
|
1624 |
|
1625 | anySelectionInRange | |
|
1626 |
|
1627 selection notNil ifTrue:[ |
|
1628 selection isCollection ifTrue:[ |
|
1629 anySelectionInRange := false. |
|
1630 selection do:[:s | |
|
1631 (s between:start and:end) ifTrue:[ |
|
1632 anySelectionInRange := true |
|
1633 ] |
|
1634 ] |
|
1635 ] ifFalse:[ |
|
1636 anySelectionInRange := selection between:start and:end |
|
1637 ] |
|
1638 ] ifFalse:[ |
|
1639 anySelectionInRange := false |
|
1640 ]. |
|
1641 |
|
1642 anySelectionInRange ifTrue:[ |
|
1643 ^ width |
|
1644 " |
|
1645 self is3D ifFalse:[ |
|
1646 ^ width |
|
1647 ]. |
|
1648 ( #(next openwin) includes:style) ifTrue:[ |
|
1649 ^ width |
|
1650 ]. |
|
1651 viewBackground = background ifFalse:[ |
|
1652 ^ width |
|
1653 ] |
|
1654 " |
|
1655 ]. |
|
1656 ^ super widthForScrollBetween:start and:end |
|
1657 ! |
|
1658 |
|
1659 positionToSelectionX:x y:y |
|
1660 "given a click position, return the selection lineNo" |
|
1661 |
|
1662 |visibleLine| |
|
1663 |
|
1664 (x between:0 and:width) ifTrue:[ |
|
1665 (y between:0 and:height) ifTrue:[ |
|
1666 visibleLine := self visibleLineOfY:y. |
|
1667 ^ self visibleLineToListLine:visibleLine |
|
1668 ] |
|
1669 ]. |
|
1670 ^ nil |
|
1671 ! |
|
1672 |
|
1673 visibleLineNeedsSpecialCare:visLineNr |
|
1674 |listLine| |
|
1675 |
|
1676 listLine := self visibleLineToListLine:visLineNr. |
|
1677 listLine isNil ifTrue:[^ false]. |
|
1678 (self isInSelection:listLine) ifTrue:[^ true]. |
|
1679 listAttributes notNil ifTrue:[ |
|
1680 (listLine <= listAttributes size) ifTrue:[ |
|
1681 ^ (listAttributes at:listLine) notNil |
|
1682 ] |
|
1683 ]. |
|
1684 ^ false |
|
1685 ! |
|
1686 |
|
1687 checkRemovingSelection:lineNr |
|
1688 "when a line is removed, we have to adjust selection" |
|
1689 |
|
1690 |newSelection| |
|
1691 |
|
1692 selection notNil ifTrue:[ |
|
1693 (selection size > 0) ifTrue:[ |
|
1694 newSelection := OrderedCollection new. |
|
1695 selection do:[:sel | |
|
1696 sel < lineNr ifTrue:[ |
|
1697 newSelection add:sel |
|
1698 ] ifFalse:[ |
|
1699 sel > lineNr ifTrue:[ |
|
1700 newSelection add:(sel - 1) |
|
1701 ] |
|
1702 "otherwise remove it from the selection" |
|
1703 ] |
|
1704 ]. |
|
1705 newSelection size == 1 ifTrue:[ |
|
1706 selection := newSelection first |
|
1707 ] ifFalse:[ |
|
1708 newSelection size == 0 ifTrue:[ |
|
1709 selection := nil |
|
1710 ] ifFalse:[ |
|
1711 selection := newSelection |
|
1712 ] |
|
1713 ] |
|
1714 ] ifFalse:[ |
|
1715 selection == lineNr ifTrue:[ |
|
1716 selection := nil |
|
1717 ] ifFalse:[ |
|
1718 selection > lineNr ifTrue:[ |
|
1719 selection := selection - 1 |
|
1720 ] |
|
1721 ] |
|
1722 ] |
|
1723 ] |
|
1724 ! |
|
1725 |
|
1726 scrollSelectDown |
|
1727 "auto scroll action; scroll and reinstall timed-block" |
|
1728 |
|
1729 self scrollDown. |
|
1730 Processor addTimedBlock:autoScrollBlock afterSeconds:autoScrollDeltaT. |
|
1731 ! |
|
1732 |
|
1733 scrollSelectUp |
|
1734 "auto scroll action; scroll and reinstall timed-block" |
|
1735 |
|
1736 self scrollUp. |
|
1737 Processor addTimedBlock:autoScrollBlock afterSeconds:autoScrollDeltaT. |
|
1738 ! |
|
1739 |
|
1740 getListFromModel |
|
1741 "if I have a model and a listMsg, get my list from it" |
|
1742 |
|
1743 |text| |
|
1744 |
|
1745 model notNil ifTrue:[ |
|
1746 listMsg notNil ifTrue:[ |
|
1747 items := model perform:listMsg. |
|
1748 items notNil ifTrue:[ |
|
1749 printItems ifTrue:[ |
|
1750 text := items collect:[:element | element printString] |
|
1751 ] ifFalse:[ |
|
1752 text := items |
|
1753 ]. |
|
1754 text notNil ifTrue:[ |
|
1755 text := text asStringCollection. |
|
1756 ] |
|
1757 ]. |
|
1758 self list:text |
|
1759 ]. |
|
1760 ]. |
|
1761 ! |
|
1762 |
|
1763 getSelectionFromModel |
|
1764 "if I have a model and an initialSelectionMsg, get my selection from it" |
|
1765 |
|
1766 |sel| |
|
1767 |
|
1768 model notNil ifTrue:[ |
|
1769 initialSelectionMsg notNil ifTrue:[ |
|
1770 sel := model perform:initialSelectionMsg. |
|
1771 useIndex ifTrue:[ |
|
1772 self selection:sel |
|
1773 ] ifFalse:[ |
|
1774 self selectElement:sel. |
|
1775 ]. |
|
1776 ] |
|
1777 ]. |
|
1778 ! ! |
2138 ! ! |
1779 |
2139 |
1780 !SelectionInListView methodsFor:'initialization'! |
2140 !SelectionInListView methodsFor:'initialization'! |
1781 |
2141 |
1782 initCursor |
2142 initCursor |
1783 "set the cursor - a hand" |
2143 "set the cursor - a hand" |
1784 |
2144 |
1785 cursor := Cursor hand |
2145 cursor := Cursor hand |
1786 ! |
2146 ! |
1787 |
2147 |
|
2148 initialize |
|
2149 super initialize. |
|
2150 |
|
2151 fontHeight := font height + lineSpacing. |
|
2152 enabled := true. |
|
2153 ignoreReselect := true. |
|
2154 multipleSelectOk := toggleSelect := strikeOut := printItems := false. |
|
2155 useIndex := true. |
|
2156 |
|
2157 keyActionStyle := #select. |
|
2158 returnKeyActionStyle := #doubleClick. |
|
2159 |
|
2160 listMsg := self class defaultListMessage. |
|
2161 initialSelectionMsg := self class defaultSelectionMessage. |
|
2162 |
|
2163 ! |
|
2164 |
1788 realize |
2165 realize |
1789 super realize. |
2166 super realize. |
1790 |
2167 |
|
2168 self getListFromModel. |
|
2169 self getSelectionFromModel. |
|
2170 |
1791 selection notNil ifTrue:[ |
2171 selection notNil ifTrue:[ |
1792 self makeLineVisible:selection |
2172 self makeLineVisible:selection |
1793 ]. |
2173 ]. |
1794 self getListFromModel. |
|
1795 self getSelectionFromModel |
|
1796 ! |
|
1797 |
|
1798 initialize |
|
1799 super initialize. |
|
1800 |
|
1801 fontHeight := font height + lineSpacing. |
|
1802 enabled := true. |
|
1803 multipleSelectOk := false. |
|
1804 ignoreReselect := true. |
|
1805 toggleSelect := false. |
|
1806 strikeOut := false. |
|
1807 keyActionStyle := #select. |
|
1808 ! |
2174 ! |
1809 |
2175 |
1810 initStyle |
2176 initStyle |
1811 |nm| |
2177 |nm| |
1812 |
2178 |
1906 hilightFrameColor notNil ifTrue:[hilightFrameColor := hilightFrameColor on:device]. |
2272 hilightFrameColor notNil ifTrue:[hilightFrameColor := hilightFrameColor on:device]. |
1907 hilightFgColor := hilightFgColor on:device. |
2273 hilightFgColor := hilightFgColor on:device. |
1908 hilightBgColor := hilightBgColor on:device. |
2274 hilightBgColor := hilightBgColor on:device. |
1909 ! ! |
2275 ! ! |
1910 |
2276 |
1911 !SelectionInListView methodsFor:'event handling'! |
2277 !SelectionInListView methodsFor:'change & update'! |
1912 |
2278 |
1913 buttonPress:button x:x y:y |
2279 update:something with:aParameter from:changedObject |
1914 |oldSelection listLineNr| |
2280 changedObject == model ifTrue:[ |
1915 |
2281 something == aspectMsg ifTrue:[ |
1916 ((button == 1) or:[button == #select]) ifTrue:[ |
2282 self getListFromModel. |
1917 enabled ifTrue:[ |
2283 self getSelectionFromModel. |
1918 listLineNr := self visibleLineToListLine:(self visibleLineOfY:y). |
2284 ^ self |
1919 listLineNr notNil ifTrue:[ |
2285 ]. |
1920 (toggleSelect |
2286 something == listMsg ifTrue:[ |
1921 and:[self isInSelection:listLineNr]) ifTrue:[ |
2287 self getListFromModel. |
1922 oldSelection := selection copy. |
2288 ^ self |
1923 self removeFromSelection:listLineNr |
2289 ]. |
1924 ] ifFalse:[ |
2290 something == initialSelectionMsg ifTrue:[ |
1925 (self line:listLineNr hasAttribute:#disabled) ifTrue:[^ self]. |
2291 self getSelectionFromModel. |
1926 |
2292 ^ self |
1927 (selectConditionBlock notNil |
2293 ]. |
1928 and:[(selectConditionBlock value:listLineNr) not]) ifTrue:[^ self]. |
2294 something == #empty ifTrue:[ |
1929 |
2295 self list:nil. |
1930 (toggleSelect and:[multipleSelectOk]) ifTrue:[ |
2296 ^ self |
1931 oldSelection := selection copy. |
2297 ]. |
1932 self addToSelection:listLineNr |
2298 ]. |
1933 ] ifFalse:[ |
2299 ^ super update:something with:aParameter from:changedObject |
1934 oldSelection := selection copy. |
2300 ! ! |
1935 self selectWithoutScroll:listLineNr. |
2301 |
1936 ]. |
2302 !SelectionInListView methodsFor:'accessing-selection'! |
1937 ]. |
2303 |
1938 ((ignoreReselect not and:[selection notNil]) |
2304 addToSelection:aNumber |
1939 or:[selection ~= oldSelection]) ifTrue:[ |
2305 "add entry, aNumber to the selection. No scrolling is done." |
1940 self selectionChangedFrom:oldSelection. |
2306 |
1941 ]. |
2307 (self isValidSelection:aNumber) ifFalse:[^ self]. |
1942 clickLine := listLineNr |
2308 |
1943 ]. |
2309 selection isNil ifTrue:[^ self selectWithoutScroll:aNumber]. |
|
2310 selection isCollection ifTrue:[ |
|
2311 (selection includes:aNumber) ifTrue:[^ self]. |
|
2312 (selectConditionBlock notNil |
|
2313 and:[(selectConditionBlock value:aNumber) not]) ifTrue:[^ self]. |
|
2314 selection add:aNumber |
|
2315 ] ifFalse:[ |
|
2316 (aNumber == selection) ifTrue:[^ self]. |
|
2317 (selectConditionBlock notNil |
|
2318 and:[(selectConditionBlock value:aNumber) not]) ifTrue:[^ self]. |
|
2319 selection := OrderedCollection with:selection with:aNumber |
|
2320 ]. |
|
2321 self redrawElement:aNumber |
|
2322 ! |
|
2323 |
|
2324 addElementToSelection:anObject |
|
2325 "add the element with the same printstring as the argument, anObject |
|
2326 to the selection. The entry is searched by comparing printStrings. |
|
2327 No scrolling is done. Returns true, if ok, false if no such entry |
|
2328 was found." |
|
2329 |
|
2330 |lineNo str| |
|
2331 |
|
2332 str := anObject printString. |
|
2333 lineNo := list findFirst:[:entry | str = entry printString]. |
|
2334 lineNo ~~ 0 ifTrue:[ |
|
2335 self addToSelection:lineNo. |
|
2336 ^ true |
|
2337 ]. |
|
2338 ^ false |
|
2339 ! |
|
2340 |
|
2341 removeFromSelection:aNumber |
|
2342 "remove entry, aNumber from the selection." |
|
2343 |
|
2344 selection isNil ifTrue:[^ self]. |
|
2345 |
|
2346 multipleSelectOk ifTrue:[ |
|
2347 (selection includes:aNumber) ifFalse:[^ self]. |
|
2348 selection remove:aNumber. |
|
2349 selection size == 0 ifTrue:[ |
|
2350 selection := nil |
1944 ] |
2351 ] |
1945 ] ifFalse:[ |
2352 ] ifFalse:[ |
1946 super buttonPress:button x:x y:y |
2353 (aNumber == selection) ifFalse:[^ self]. |
1947 ] |
2354 selection := nil |
1948 ! |
2355 ]. |
1949 |
2356 self redrawElement:aNumber |
1950 sizeChanged:how |
2357 ! ! |
1951 "if there is a selection, make certain, its visible |
2358 |
1952 after the sizechange" |
2359 !SelectionInListView methodsFor:'accessing-mvc'! |
1953 |
2360 |
1954 |first wasAtEnd| |
2361 on:aModel printItems:print oneItem:one aspect:aspectSymbol change:changeSymbol |
1955 |
2362 list:listSymbol menu:menuSymbol initialSelection:initialSymbol useIndex:use |
1956 wasAtEnd := (firstLineShown + nFullLinesShown) >= self size. |
2363 |
1957 |
2364 "ST-80 compatibility" |
1958 super sizeChanged:how. |
2365 |
1959 |
2366 aspectMsg := aspectSymbol. |
1960 shown ifTrue:[ |
2367 changeMsg := changeSymbol. |
1961 selection notNil ifTrue:[ |
2368 listMsg := listSymbol. |
1962 selection isCollection ifTrue:[ |
2369 menuMsg := menuSymbol. |
1963 selection notEmpty ifTrue:[ |
2370 initialSelectionMsg := initialSymbol. |
1964 first := selection first |
2371 printItems := print. |
1965 ] |
2372 oneItem := one. |
1966 ] ifFalse:[ |
2373 useIndex := use. |
1967 first := selection |
2374 ignoreReselect := false. "/ ST80 behavior |
1968 ]. |
2375 self model:aModel. |
1969 first notNil ifTrue:[self makeLineVisible:first] |
2376 ! |
1970 ] ifFalse:[ |
2377 |
1971 " |
2378 doubleClickMessage |
1972 if we where at the end before, move to the end again. |
2379 "return the symbol with which the model (if any) is informed about |
1973 Still to be seen, if this is better in real life ... |
2380 double-click. If nil (which is the default), it is not informed." |
1974 " |
2381 |
1975 wasAtEnd ifTrue:[ |
2382 ^ doubleClickMsg |
1976 "at end" |
2383 ! |
1977 self scrollToBottom |
2384 |
1978 ] |
2385 doubleClickMessage:aSymbol |
1979 ] |
2386 "set the symbol with which the model (if any) is informed about double-click. |
1980 ] |
2387 If nil (which is the default), it is not informed." |
1981 ! |
2388 |
1982 |
2389 doubleClickMsg := aSymbol |
1983 buttonRelease:button x:x y:y |
2390 ! |
1984 "stop any autoscroll" |
2391 |
1985 |
2392 doubleClick:aSymbol |
1986 self stopAutoScroll |
2393 "set the symbol with which the model is informed about double-click. |
1987 ! |
2394 OBSOLETE: please use #doubleClickMessage:" |
1988 |
2395 |
1989 key:key select:selectAction x:x y:y |
2396 self obsoleteMethodWarning:'please use #doubleClickMessage:'. |
1990 "perform keyaction after a key-select" |
2397 doubleClickMsg := aSymbol |
1991 |
2398 ! |
1992 |oldSelection| |
2399 |
1993 |
2400 initialSelectionMessage |
1994 keyActionStyle notNil ifTrue:[ |
2401 "return the symbol by which the model informes me about a changed |
1995 keyActionStyle == #pass ifTrue:[ |
2402 selectionIndex. This is used both in change notification and to |
1996 ^ super keyPress:key x:x y:y |
2403 actually aquire a new selection value." |
1997 ]. |
2404 |
1998 oldSelection := selection. |
2405 ^ initialSelectionMsg |
1999 selectAction value. |
2406 ! |
2000 self selectionChangedFrom:oldSelection. |
2407 |
2001 keyActionStyle == #selectAndDoubleClick ifTrue:[ |
2408 initialSelectionMessage:aSymbol |
2002 doubleClickActionBlock notNil ifTrue:[doubleClickActionBlock value:selection]. |
2409 "set the symbol by which the model informes me about a changed |
2003 ] |
2410 selectionIndex. This is used both in change notification and to |
2004 ]. |
2411 actually aquire a new selection value." |
2005 ! |
2412 |
2006 |
2413 initialSelectionMsg := aSymbol |
2007 keyPress:key x:x y:y |
2414 ! |
2008 "handle keyboard input" |
2415 |
2009 |
2416 addModelInterfaceTo:aDictionary |
2010 |index startSearch backSearch searchPrefix| |
2417 "see comment in View>>modelInterface" |
2011 |
2418 |
2012 (key == #CursorUp) ifTrue:[ |
2419 super addModelInterfaceTo:aDictionary. |
2013 index := self previousBeforeSelection. |
2420 aDictionary at:#doubleClickMessage put:doubleClickMsg. |
2014 (selectConditionBlock isNil or:[selectConditionBlock value:index]) ifTrue:[ |
2421 aDictionary at:#initialSelectionMessage put:initialSelectionMsg. |
2015 self key:key select:[self selection:index] x:x y:y |
2422 |
2016 ]. |
|
2017 ^ self |
|
2018 ]. |
|
2019 (key == #CursorDown) ifTrue:[ |
|
2020 index := self nextAfterSelection. |
|
2021 (selectConditionBlock isNil or:[selectConditionBlock value:index]) ifTrue:[ |
|
2022 self key:key select:[self selection:index] x:x y:y |
|
2023 ]. |
|
2024 ^ self |
|
2025 ]. |
|
2026 (key == #Home) ifTrue:[ |
|
2027 (selectConditionBlock isNil or:[selectConditionBlock value:1]) ifTrue:[ |
|
2028 self key:key select:[self selection:1] x:x y:y |
|
2029 ]. |
|
2030 ^ self |
|
2031 ]. |
|
2032 (key == #End) ifTrue:[ |
|
2033 index := self size. |
|
2034 (selectConditionBlock isNil or:[selectConditionBlock value:index]) ifTrue:[ |
|
2035 self key:key select:[self selection:index] x:x y:y |
|
2036 ]. |
|
2037 ^ self |
|
2038 ]. |
|
2039 key == #Return ifTrue:[ |
|
2040 selection notNil ifTrue:[ |
|
2041 doubleClickActionBlock notNil ifTrue:[ |
|
2042 doubleClickActionBlock value:selection |
|
2043 ]. |
|
2044 ]. |
|
2045 ^ self |
|
2046 ]. |
|
2047 " |
2423 " |
2048 alphabetic keys: search for next entry |
2424 SelectionInListView new modelInterface |
2049 starting with keys character. If shift is pressed, search backward |
|
2050 " |
2425 " |
2051 (self size > 0 |
|
2052 and:[key isCharacter |
|
2053 and:[key isLetter]]) ifTrue:[ |
|
2054 keyActionStyle isNil ifTrue:[^ self]. |
|
2055 keyActionStyle == #pass ifFalse:[ |
|
2056 searchPrefix := key asLowercase asString. |
|
2057 |
|
2058 "/ ... isISearch... ifFalse:[ |
|
2059 "/ iSearchString := '' |
|
2060 "/ ] ifTrue:[ |
|
2061 "/ iSearchString := iSearchString , searchPrefix. |
|
2062 "/ searchPrefix := iSearchString |
|
2063 "/ ]. |
|
2064 |
|
2065 backSearch := device shiftDown. |
|
2066 backSearch ifTrue:[ |
|
2067 selection notNil ifTrue:[ |
|
2068 selection size > 0 ifTrue:[ |
|
2069 startSearch := selection first - 1 |
|
2070 ] ifFalse:[ |
|
2071 startSearch := selection - 1 |
|
2072 ] |
|
2073 ] ifFalse:[ |
|
2074 startSearch := self size |
|
2075 ]. |
|
2076 startSearch < 1 ifTrue:[ |
|
2077 startSearch := self size. |
|
2078 ]. |
|
2079 ] ifFalse:[ |
|
2080 selection notNil ifTrue:[ |
|
2081 selection size > 0 ifTrue:[ |
|
2082 startSearch := selection last + 1 |
|
2083 ] ifFalse:[ |
|
2084 startSearch := selection + 1 |
|
2085 ] |
|
2086 ] ifFalse:[ |
|
2087 startSearch := 1 |
|
2088 ]. |
|
2089 startSearch > self size ifTrue:[ |
|
2090 startSearch := 1. |
|
2091 ]. |
|
2092 ]. |
|
2093 index := startSearch. |
|
2094 [true] whileTrue:[ |
|
2095 (((self at:index) asString) asLowercase startsWith:searchPrefix) ifTrue:[ |
|
2096 index = selection ifTrue:[^ self]. |
|
2097 ^ self key:key select:[self selection:index] x:x y:y |
|
2098 ]. |
|
2099 backSearch ifTrue:[ |
|
2100 index := index - 1. |
|
2101 index < 1 ifTrue:[index := self size] |
|
2102 ] ifFalse:[ |
|
2103 index := index + 1. |
|
2104 index > self size ifTrue:[index := 1]. |
|
2105 ]. |
|
2106 index == startSearch ifTrue:[ |
|
2107 ^ self |
|
2108 ] |
|
2109 ] |
|
2110 ]. |
|
2111 ]. |
|
2112 ^ super keyPress:key x:x y:y |
|
2113 |
|
2114 ! |
|
2115 |
|
2116 buttonMultiPress:button x:x y:y |
|
2117 ((button == 1) or:[button == #select]) ifTrue:[ |
|
2118 doubleClickActionBlock isNil ifTrue:[ |
|
2119 self buttonPress:button x:x y:y |
|
2120 ] ifFalse:[ |
|
2121 doubleClickActionBlock value:selection |
|
2122 ]. |
|
2123 (model notNil and:[doubleClickMsg notNil]) ifTrue:[ |
|
2124 self sendChangeMessage:doubleClickMsg with:(self argForChangeMessage). |
|
2125 ] |
|
2126 ] ifFalse:[ |
|
2127 super buttonMultiPress:button x:x y:y |
|
2128 ] |
|
2129 ! |
|
2130 |
|
2131 buttonShiftPress:button x:x y:y |
|
2132 "add to the selection (if multipleSelectOk); otherwise, |
|
2133 behave like normal select" |
|
2134 |
|
2135 |oldSelection listLineNr| |
|
2136 |
|
2137 ((button == 1) or:[button == #select]) ifTrue:[ |
|
2138 toggleSelect ifTrue:[ |
|
2139 ^ self buttonPress:button x:x y:y |
|
2140 ]. |
|
2141 enabled ifTrue:[ |
|
2142 listLineNr := self visibleLineToListLine:(self visibleLineOfY:y). |
|
2143 listLineNr notNil ifTrue:[ |
|
2144 (self line:listLineNr hasAttribute:#disabled) ifTrue:[^ self]. |
|
2145 |
|
2146 (selectConditionBlock notNil |
|
2147 and:[(selectConditionBlock value:listLineNr) not]) ifTrue:[^ self]. |
|
2148 ]. |
|
2149 oldSelection := selection copy. |
|
2150 listLineNr notNil ifTrue: [ |
|
2151 multipleSelectOk ifTrue:[ |
|
2152 (self isInSelection:listLineNr) ifTrue:[ |
|
2153 self removeFromSelection:listLineNr |
|
2154 ] ifFalse:[ |
|
2155 self addToSelection:listLineNr |
|
2156 ] |
|
2157 ] ifFalse:[ |
|
2158 self selectWithoutScroll:listLineNr |
|
2159 ] |
|
2160 ]. |
|
2161 ((ignoreReselect not and:[selection notNil]) |
|
2162 or:[selection ~= oldSelection]) ifTrue:[ |
|
2163 self selectionChangedFrom:oldSelection. |
|
2164 ]. |
|
2165 clickLine := listLineNr |
|
2166 ] |
|
2167 ] ifFalse:[ |
|
2168 super buttonShiftPress:button x:x y:y |
|
2169 ] |
|
2170 ! |
|
2171 |
|
2172 update:something with:aParameter from:changedObject |
|
2173 changedObject == model ifTrue:[ |
|
2174 something == aspectMsg ifTrue:[ |
|
2175 self getListFromModel. |
|
2176 ^ self |
|
2177 ]. |
|
2178 something == initialSelectionMsg ifTrue:[ |
|
2179 self getSelectionFromModel. |
|
2180 ^ self |
|
2181 ]. |
|
2182 something == #empty ifTrue:[ |
|
2183 self list:nil. |
|
2184 ^ self |
|
2185 ]. |
|
2186 ]. |
|
2187 ^ super update:something with:aParameter from:changedObject |
|
2188 ! |
|
2189 |
|
2190 buttonMotion:buttonMask x:x y:y |
|
2191 "mouse-move while button was pressed - handle selection changes" |
|
2192 |
|
2193 |movedVisibleLine movedLine delta oldSelection oldSelCount| |
|
2194 |
|
2195 "is it the select or 1-button ?" |
|
2196 (device buttonMotionMask:buttonMask includesButton:#select) ifFalse:[ |
|
2197 (device buttonMotionMask:buttonMask includesButton:1) ifFalse:[ |
|
2198 ^ self |
|
2199 ]. |
|
2200 ]. |
|
2201 |
|
2202 clickLine isNil ifTrue:[^ self]. |
|
2203 |
|
2204 "if moved outside of view, start autoscroll" |
|
2205 (y < 0) ifTrue:[ |
|
2206 self compressMotionEvents:false. |
|
2207 self startAutoScrollUp:y. |
|
2208 ^ self |
|
2209 ]. |
|
2210 (y > height) ifTrue:[ |
|
2211 self compressMotionEvents:false. |
|
2212 self startAutoScrollDown:(y - height). |
|
2213 ^ self |
|
2214 ]. |
|
2215 |
|
2216 "move inside - stop autoscroll if any" |
|
2217 self stopAutoScroll. |
|
2218 |
|
2219 movedVisibleLine := self visibleLineOfY:y. |
|
2220 movedLine := self visibleLineToAbsoluteLine:movedVisibleLine. |
|
2221 (movedLine == clickLine) ifTrue:[^ self]. |
|
2222 |
|
2223 multipleSelectOk ifTrue:[ |
|
2224 delta := (clickLine < movedLine) ifTrue:[1] ifFalse:[-1]. |
|
2225 |
|
2226 oldSelection := selection. |
|
2227 oldSelCount := selection size. |
|
2228 |
|
2229 (clickLine+delta) to:movedLine by:delta do:[:line | |
|
2230 (self isInSelection:line) ifTrue:[ |
|
2231 self removeFromSelection:line |
|
2232 ] ifFalse:[ |
|
2233 self addToSelection:line |
|
2234 ] |
|
2235 ]. |
|
2236 ((selection ~= oldSelection) |
|
2237 or:[selection size ~~ oldSelCount]) ifTrue:[ |
|
2238 self selectionChangedFrom:oldSelection. |
|
2239 ] |
|
2240 ] ifFalse:[ |
|
2241 "/ self selectWithoutScroll:movedLine |
|
2242 ]. |
|
2243 |
|
2244 clickLine := movedLine |
|
2245 ! ! |
2426 ! ! |
|
2427 |