author | ca |
Thu, 10 Oct 2002 07:58:47 +0200 | |
changeset 2265 | 5304bdf0f8e2 |
parent 2264 | 0241177f2a2b |
child 2274 | c973acbc021d |
permissions | -rw-r--r-- |
1431 | 1 |
" |
2 |
COPYRIGHT (c) 1999 by eXept Software AG |
|
2265 | 3 |
All Rights Reserved |
1431 | 4 |
|
5 |
This software is furnished under a license and may be used |
|
6 |
only in accordance with the terms of that license and with the |
|
7 |
inclusion of the above copyright notice. This software may not |
|
8 |
be provided or otherwise made available to, or used by, any |
|
9 |
other person. No title to or ownership of the software is |
|
10 |
hereby transferred. |
|
11 |
" |
|
12 |
||
13 |
||
1752 | 14 |
"{ Package: 'stx:libwidg2' }" |
15 |
||
1390 | 16 |
View subclass:#ListModelView |
17 |
instanceVariableNames:'list listHolder textStartLeft viewOrigin enabled fgColor bgColor |
|
1399 | 18 |
lineSpacing widthOfContents computeWidthInRange startOfLinesY |
1827 | 19 |
displayedFrames syncronizeEvents autoScroll autoScrollBlock |
2264 | 20 |
scrollWhenUpdating hasConstantHeight constantHeight' |
1390 | 21 |
classVariableNames:'DefaultForegroundColor DefaultBackgroundColor DefaultShadowColor |
22 |
DefaultLightColor StopRedrawSignal' |
|
23 |
poolDictionaries:'' |
|
1430 | 24 |
category:'Views-Lists' |
1390 | 25 |
! |
26 |
||
27 |
!ListModelView class methodsFor:'documentation'! |
|
28 |
||
1431 | 29 |
copyright |
30 |
" |
|
31 |
COPYRIGHT (c) 1999 by eXept Software AG |
|
2265 | 32 |
All Rights Reserved |
1431 | 33 |
|
34 |
This software is furnished under a license and may be used |
|
35 |
only in accordance with the terms of that license and with the |
|
36 |
inclusion of the above copyright notice. This software may not |
|
37 |
be provided or otherwise made available to, or used by, any |
|
38 |
other person. No title to or ownership of the software is |
|
39 |
hereby transferred. |
|
40 |
" |
|
41 |
||
42 |
! |
|
43 |
||
1390 | 44 |
documentation |
45 |
" |
|
1431 | 46 |
This widget is a new improved revision of the good-old ListView. |
47 |
In contrast to ListView, this one reacts on changes of the |
|
48 |
underlying model and performs optimized redraws. |
|
49 |
It requires a List (or alike) as model. |
|
50 |
||
1390 | 51 |
This class can only passively display collections of elements. |
52 |
The class doesn't keep its own list, it works directly on |
|
53 |
the model( List or HierarchicalList ). |
|
54 |
||
55 |
Each list item is obligated to provide 3 services: |
|
2265 | 56 |
- heightOn:aGC |
57 |
- widthOn:aGC |
|
58 |
- displayOn:aGC x:x y:y |
|
1390 | 59 |
|
60 |
[Instance variables:] |
|
2265 | 61 |
list <List-Model> List or HierarchicalList ... |
62 |
listHolder <Model> Model, which keeps a List |
|
63 |
textStartLeft <Number> left inset of text |
|
64 |
viewOrigin <Point> the current origin |
|
65 |
enabled <Boolean> widget is enabled/disabeled |
|
66 |
fgColor <Color> color to draw characters |
|
67 |
bgColor <Color> the background |
|
68 |
lineSpacing <Number> pixels between lines |
|
69 |
widthOfContents <Number> cached width of widest line |
|
70 |
computeWidthInRange <Point> used for recompute width of contents |
|
71 |
startOfLinesY <Collection> keeps all the absolute Y-start positions |
|
72 |
for each line in the list. The first |
|
73 |
entry into the list is the top Y inset. |
|
74 |
supportsDisplayInRange <Boolean> set to true if the list elements |
|
75 |
supports the service: |
|
76 |
#displayOn:x:y:h: |
|
1535
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
77 |
|
2265 | 78 |
displayedFrames <WeakIdentityDictionary> |
79 |
keep the frames within the widget |
|
1390 | 80 |
|
2265 | 81 |
syncronizeEvents <Boolean> set to true if list and model changes |
82 |
should be handled synchronized; an event |
|
83 |
will be pushed on the event loop. |
|
84 |
on default it is disabled. |
|
1554 | 85 |
|
2265 | 86 |
hasConstantHeight <Boolean> true, than each line has the same height |
2264 | 87 |
|
2265 | 88 |
constantHeight <SmallInteger> hasConstantHeight is turned on, this |
89 |
is the used line height |
|
2264 | 90 |
|
1390 | 91 |
[author:] |
2265 | 92 |
Claus Atzkern |
1390 | 93 |
|
94 |
[see also:] |
|
95 |
||
2265 | 96 |
SelectionInListModelView |
97 |
HierarchicalListView |
|
98 |
List |
|
99 |
HierarchicalList |
|
1390 | 100 |
" |
101 |
! |
|
102 |
||
103 |
examples |
|
104 |
" |
|
2265 | 105 |
[exBegin] |
1390 | 106 |
|top list view up index| |
107 |
||
108 |
list := List new. |
|
109 |
||
110 |
top := StandardSystemView new; extent:300@300. |
|
111 |
view := ScrollableView for:ListModelView miniScroller:true |
|
2265 | 112 |
origin:0.0@0.0 corner:1.0@1.0 in:top. |
1827 | 113 |
|
1390 | 114 |
view list:list. |
115 |
top openAndWait. |
|
116 |
up := true. |
|
117 |
||
118 |
[top shown] whileTrue:[ |
|
2265 | 119 |
Delay waitForSeconds:0.2. |
1390 | 120 |
|
2265 | 121 |
up ifTrue:[ |
122 |
index := 1 + (list size). |
|
123 |
list add:('element: ', index printString). |
|
124 |
up := index < 20 |
|
125 |
] ifFalse:[ |
|
126 |
list removeIndex:1. |
|
127 |
up := list isEmpty. |
|
128 |
] |
|
1390 | 129 |
]. |
2265 | 130 |
[exEnd] |
1390 | 131 |
|
132 |
" |
|
133 |
||
134 |
! ! |
|
135 |
||
136 |
!ListModelView class methodsFor:'initialization'! |
|
137 |
||
138 |
initialize |
|
1409 | 139 |
"setup the signals |
140 |
" |
|
141 |
super initialize. |
|
1390 | 142 |
|
1736
eda99db343be
StopRedrawSignal is a Notification, not an Error.
Stefan Vogel <sv@exept.de>
parents:
1732
diff
changeset
|
143 |
StopRedrawSignal := Notification newSignalMayProceed:false. |
1390 | 144 |
! ! |
145 |
||
146 |
!ListModelView class methodsFor:'Signal constants'! |
|
147 |
||
148 |
stopRedrawSignal |
|
149 |
^ StopRedrawSignal |
|
150 |
! ! |
|
151 |
||
152 |
!ListModelView class methodsFor:'defaults'! |
|
153 |
||
154 |
updateStyleCache |
|
155 |
"extract values from the styleSheet and cache them in class variables" |
|
156 |
||
157 |
<resource: #style ( |
|
2265 | 158 |
#'text.backgroundColor' #'text.foregroundColor' |
159 |
#'selection.shadowColor' #'selection.lightColor' |
|
160 |
#'text.font' |
|
161 |
)> |
|
1390 | 162 |
|
163 |
DefaultForegroundColor := StyleSheet colorAt:'text.foregroundColor' default:Black. |
|
164 |
DefaultBackgroundColor := StyleSheet colorAt:'text.backgroundColor'. |
|
165 |
DefaultShadowColor := StyleSheet colorAt:'selection.shadowColor'. |
|
166 |
DefaultLightColor := StyleSheet colorAt:'selection.lightColor'. |
|
167 |
DefaultFont := StyleSheet fontAt:'text.font'. |
|
168 |
||
169 |
" |
|
170 |
self updateStyleCache |
|
171 |
" |
|
172 |
||
173 |
||
174 |
! ! |
|
175 |
||
176 |
!ListModelView methodsFor:'accessing'! |
|
177 |
||
178 |
list |
|
179 |
"get the list of items |
|
180 |
" |
|
181 |
^ list |
|
182 |
||
183 |
||
184 |
! |
|
185 |
||
186 |
list:aList |
|
187 |
"set the list of items |
|
188 |
" |
|
2264 | 189 |
|negatedOrg| |
1443 | 190 |
|
1554 | 191 |
self syncFlushEvent:#syncUpdate:with:. |
1390 | 192 |
|
1535
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
193 |
displayedFrames keys do:[:aView| aView destroy]. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
194 |
displayedFrames := WeakIdentityDictionary new. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
195 |
|
1452 | 196 |
list ~~ aList ifTrue:[ |
2265 | 197 |
list removeDependent:self. |
1390 | 198 |
]. |
1452 | 199 |
(list := aList) notNil ifTrue:[ |
2265 | 200 |
list addDependent:self |
1452 | 201 |
]. |
2264 | 202 |
preferredExtent := nil. |
203 |
widthOfContents := nil. |
|
204 |
||
205 |
self realized ifFalse:[^ self]. |
|
206 |
||
1390 | 207 |
self recomputeHeightOfContents. |
208 |
||
209 |
||
1827 | 210 |
scrollWhenUpdating == #beginOfText ifTrue:[ |
2265 | 211 |
viewOrigin = (0@0) ifFalse:[ |
212 |
self originWillChange. |
|
213 |
negatedOrg := viewOrigin negated. |
|
214 |
viewOrigin := (0@0). |
|
215 |
self originChanged:negatedOrg. |
|
216 |
]. |
|
1827 | 217 |
] ifFalse:[ |
2265 | 218 |
scrollWhenUpdating == #endOfText ifTrue:[ |
219 |
self scrollTo:(0 @ self heightOfContents - self innerHeight) redraw:false |
|
220 |
] |
|
1422 | 221 |
]. |
1827 | 222 |
|
1422 | 223 |
self invalidate. |
1457 | 224 |
self contentsChanged |
1390 | 225 |
! ! |
226 |
||
1818 | 227 |
!ListModelView methodsFor:'accessing-behavior'! |
1390 | 228 |
|
1748 | 229 |
autoScroll |
230 |
"returns true if auto scrolling is enabled |
|
231 |
" |
|
232 |
^ autoScroll |
|
233 |
! |
|
234 |
||
235 |
autoScroll:aBool |
|
236 |
"returns true if auto scrolling is enabled |
|
237 |
" |
|
238 |
autoScroll := aBool ? true. |
|
239 |
! |
|
240 |
||
1390 | 241 |
enabled |
242 |
"returns the enabled state |
|
243 |
" |
|
244 |
^ enabled |
|
245 |
||
246 |
||
247 |
! |
|
248 |
||
249 |
enabled:aBoolean |
|
250 |
"set the enabled state |
|
251 |
" |
|
252 |
enabled := aBoolean |
|
253 |
||
254 |
||
1742 | 255 |
! |
256 |
||
2261 | 257 |
hasConstantHeight |
258 |
"user configured; true if each line has the same lineHeight |
|
259 |
optimize for scroller update |
|
260 |
" |
|
261 |
^ hasConstantHeight |
|
262 |
! |
|
263 |
||
264 |
hasConstantHeight:aBool |
|
265 |
"user configured; true if each line has the same lineHeight |
|
266 |
optimize for scroller update |
|
267 |
" |
|
268 |
aBool == hasConstantHeight ifTrue:[ |
|
2265 | 269 |
^ self |
2261 | 270 |
]. |
2264 | 271 |
constantHeight := nil. |
2261 | 272 |
hasConstantHeight := aBool. |
273 |
||
274 |
self lostSynchronisation. |
|
275 |
! |
|
276 |
||
1742 | 277 |
scrollWhenUpdating:aSymbolOrNil |
278 |
"define how to scroll, when I get a new text |
|
279 |
(via the model or the #contents/#list) |
|
280 |
Allowed arguments are: |
|
2265 | 281 |
#keep / nil -> no change |
282 |
#endOfText -> scroll to the end |
|
283 |
#beginOfText -> scroll to the top |
|
1742 | 284 |
The default is #beginOfText. |
285 |
This may be useful for fields which get new values assigned from |
|
286 |
the program (i.e. not from the user) |
|
287 |
" |
|
288 |
||
1827 | 289 |
scrollWhenUpdating := aSymbolOrNil |
1742 | 290 |
|
291 |
||
1390 | 292 |
! ! |
293 |
||
1818 | 294 |
!ListModelView methodsFor:'accessing-items'! |
1390 | 295 |
|
296 |
at:anIndex |
|
297 |
"return the list element at an index |
|
298 |
" |
|
299 |
^ list at:anIndex |
|
300 |
! |
|
301 |
||
302 |
at:anIndex ifAbsent:exceptionBlock |
|
303 |
"return the list element at an index if valid. |
|
304 |
If the index is invalid, return the result of evaluating |
|
305 |
the exceptionblock. |
|
306 |
" |
|
307 |
list notNil ifTrue:[ |
|
2265 | 308 |
^ list at:anIndex ifAbsent:exceptionBlock |
1390 | 309 |
]. |
310 |
^ nil. |
|
311 |
! |
|
312 |
||
313 |
identityIndexOf:anElement |
|
314 |
"returns the index of an element or nil |
|
315 |
" |
|
316 |
^ list notNil ifTrue:[list identityIndexOf:anElement] |
|
2265 | 317 |
ifFalse:[0] |
1390 | 318 |
|
319 |
||
320 |
! ! |
|
321 |
||
1818 | 322 |
!ListModelView methodsFor:'accessing-look'! |
1390 | 323 |
|
324 |
backgroundColor |
|
325 |
"get the background color |
|
326 |
" |
|
327 |
^ bgColor |
|
328 |
||
329 |
||
330 |
! |
|
331 |
||
332 |
backgroundColor:aColor |
|
333 |
"set the background color |
|
334 |
" |
|
335 |
(aColor notNil and:[bgColor ~~ aColor]) ifTrue:[ |
|
2265 | 336 |
super viewBackground:bgColor. |
1390 | 337 |
|
2265 | 338 |
self realized ifTrue:[ |
339 |
bgColor := aColor onDevice:device. |
|
340 |
self invalidate |
|
341 |
] ifFalse:[ |
|
342 |
bgColor := aColor |
|
343 |
] |
|
1390 | 344 |
] |
345 |
! |
|
346 |
||
347 |
font:aFont |
|
348 |
"set a new font |
|
349 |
" |
|
350 |
|oldWidth oldHeight| |
|
351 |
||
352 |
(aFont isNil or:[aFont = font]) ifFalse:[ |
|
2265 | 353 |
oldWidth := font width. |
354 |
oldHeight := font height. |
|
1390 | 355 |
|
2265 | 356 |
super font:aFont. |
1390 | 357 |
|
2265 | 358 |
(font widthOn:device) ~~ oldWidth ifTrue:[ "/ force a recomputation |
359 |
preferredExtent := nil. |
|
360 |
widthOfContents := nil. |
|
361 |
]. |
|
362 |
oldHeight ~~ (font heightOn:device) ifTrue:[ |
|
363 |
self recomputeHeightOfContents. |
|
364 |
]. |
|
365 |
shown ifTrue:[ self invalidate ] |
|
1390 | 366 |
]. |
367 |
! |
|
368 |
||
369 |
foregroundColor |
|
370 |
"get the foreground color |
|
371 |
" |
|
372 |
^ fgColor |
|
373 |
||
374 |
! |
|
375 |
||
376 |
foregroundColor:aColor |
|
377 |
"set the foreground color |
|
378 |
" |
|
379 |
(aColor notNil and:[fgColor ~~ aColor]) ifTrue:[ |
|
2265 | 380 |
self realized ifTrue:[ |
381 |
fgColor := aColor onDevice:device. |
|
382 |
self invalidate |
|
383 |
] ifFalse:[ |
|
384 |
fgColor := aColor |
|
385 |
] |
|
1390 | 386 |
] |
1945 | 387 |
! |
388 |
||
389 |
lineSpacing |
|
390 |
"get the lineSpacing - thats an additional number of pixels, |
|
391 |
by which lines are vertically separated. |
|
392 |
" |
|
393 |
^ lineSpacing |
|
394 |
! |
|
395 |
||
396 |
lineSpacing:aNumber |
|
397 |
"set the lineSpacing - thats an additional number of pixels, |
|
398 |
by which lines are vertically separated. |
|
399 |
" |
|
400 |
lineSpacing ~= aNumber ifTrue:[ |
|
2265 | 401 |
lineSpacing := aNumber. |
1945 | 402 |
|
2265 | 403 |
self recomputeHeightOfContents. |
1945 | 404 |
|
2265 | 405 |
shown ifTrue:[ |
406 |
self invalidate |
|
407 |
] |
|
1945 | 408 |
] |
1390 | 409 |
! ! |
410 |
||
1818 | 411 |
!ListModelView methodsFor:'accessing-mvc'! |
1390 | 412 |
|
413 |
listHolder |
|
414 |
"returns the listHolder or nil |
|
415 |
" |
|
416 |
^ listHolder |
|
417 |
! |
|
418 |
||
419 |
listHolder:aListHolder |
|
420 |
"set a new listHolder |
|
421 |
" |
|
422 |
listHolder removeDependent:self. |
|
423 |
||
424 |
(listHolder := aListHolder) notNil ifTrue:[ |
|
2265 | 425 |
listHolder addDependent:self. |
1390 | 426 |
]. |
427 |
self list:(listHolder value). |
|
428 |
! ! |
|
429 |
||
1818 | 430 |
!ListModelView methodsFor:'accessing-views'! |
1535
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
431 |
|
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
432 |
destroyFrame:aFrame |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
433 |
"destroy a frame |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
434 |
" |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
435 |
aFrame notNil ifTrue:[ |
2265 | 436 |
displayedFrames removeKey:aFrame ifAbsent:nil. |
437 |
aFrame destroy. |
|
1535
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
438 |
]. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
439 |
! |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
440 |
|
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
441 |
registerFrame:aView atLine:aLineNr x:logX width:w |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
442 |
"register a frame for a line and set the origin@corner of the frame |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
443 |
" |
2265 | 444 |
|x y h item| |
1535
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
445 |
|
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
446 |
(item := list at:aLineNr ifAbsent:nil) isNil ifTrue:[ |
2265 | 447 |
^ self |
1535
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
448 |
]. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
449 |
y := self yVisibleOfLine:aLineNr. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
450 |
x := logX - viewOrigin x. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
451 |
h := (startOfLinesY at:(aLineNr + 1)) - (startOfLinesY at:aLineNr). |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
452 |
|
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
453 |
aView origin:(x@y) extent:(w@h). |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
454 |
self addSubView:aView. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
455 |
displayedFrames at:aView put:item. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
456 |
realized ifTrue:[aView realize]. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
457 |
! ! |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
458 |
|
1390 | 459 |
!ListModelView methodsFor:'change & update'! |
460 |
||
1535
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
461 |
contentsChanged |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
462 |
"contents changed; recompute origin Y of registered views |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
463 |
" |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
464 |
|idx y x| |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
465 |
|
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
466 |
displayedFrames keysAndValuesDo:[:aFrame :anItem| |
2265 | 467 |
(idx := list identityIndexOf:anItem) == 0 ifTrue:[ |
468 |
aFrame beInvisible. |
|
469 |
] ifFalse:[ |
|
470 |
y := self yVisibleOfLine:idx. |
|
471 |
x := aFrame origin x. |
|
472 |
aFrame origin:(x @ y). |
|
473 |
aFrame beVisible. |
|
474 |
] |
|
1535
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
475 |
]. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
476 |
super contentsChanged. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
477 |
|
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
478 |
! |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
479 |
|
1390 | 480 |
lineChangedAt:aLnNr with:arg |
481 |
"line changed at position; check whether line height changed |
|
482 |
" |
|
483 |
| |
|
484 |
oldHeight "{ Class:SmallInteger }" |
|
485 |
dltHeight "{ Class:SmallInteger }" |
|
486 |
| |
|
487 |
||
488 |
||
489 |
(arg notNil and:[(arg == #icon or:[arg == #hierarchy])]) ifTrue:[ |
|
2265 | 490 |
^ self |
1390 | 491 |
]. |
2264 | 492 |
hasConstantHeight ifTrue:[ |
2265 | 493 |
self invalidateLineAt:aLnNr. |
2264 | 494 |
^ self |
495 |
]. |
|
496 |
||
1390 | 497 |
oldHeight := (self yVisibleOfLine:(aLnNr + 1)) - (self yVisibleOfLine:aLnNr). |
498 |
dltHeight := (self heightOfLineAt:aLnNr) - oldHeight. |
|
499 |
||
500 |
dltHeight == 0 ifTrue:[ |
|
2265 | 501 |
self invalidateLineAt:aLnNr. |
2244
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
502 |
^ self |
1390 | 503 |
]. |
504 |
||
505 |
aLnNr + 1 to:startOfLinesY size do:[:i| |
|
2265 | 506 |
startOfLinesY at:i put:((startOfLinesY at:i) + dltHeight) |
1390 | 507 |
]. |
508 |
self invalidate. |
|
509 |
! |
|
510 |
||
511 |
listChangedInsert:start nItems:nLines |
|
512 |
"list changed; items are added |
|
513 |
" |
|
1457 | 514 |
| |
1390 | 515 |
run "{ Class: SmallInteger }" |
1457 | 516 |
newSz "{ Class: SmallInteger }" |
1390 | 517 |
cpyHg "{ Class: SmallInteger }" |
518 |
absY0 "{ Class: SmallInteger }" |
|
519 |
absY1 "{ Class: SmallInteger }" |
|
520 |
visY0 "{ Class: SmallInteger }" |
|
521 |
visY1 "{ Class: SmallInteger }" |
|
522 |
orgY "{ Class: SmallInteger }" |
|
523 |
dltY "{ Class: SmallInteger }" |
|
524 |
maxHg "{ Class: SmallInteger }" |
|
525 |
| |
|
526 |
||
527 |
nLines == 0 ifTrue:[^ self ]. |
|
528 |
self listSizeChanged:start nLines:nLines. |
|
529 |
shown not ifTrue:[^ self]. |
|
530 |
||
1457 | 531 |
newSz := startOfLinesY size + nLines. |
532 |
||
533 |
(newSz - 1) ~~ list size ifTrue:[ |
|
2265 | 534 |
"/ |
535 |
"/ no longer synchrounous |
|
536 |
"/ |
|
537 |
^ self lostSynchronisation |
|
1451 | 538 |
]. |
539 |
||
1390 | 540 |
startOfLinesY addAll:(Array new:nLines) beforeIndex:start + 1. |
541 |
absY0 := startOfLinesY at:start. |
|
542 |
absY1 := absY0. |
|
543 |
run := start. |
|
544 |
||
545 |
nLines timesRepeat:[ |
|
2265 | 546 |
absY1 := absY1 + (self heightOfLineAt:run). |
547 |
run := run + 1. |
|
548 |
startOfLinesY at:run put:absY1. |
|
1390 | 549 |
]. |
550 |
dltY := absY1 - absY0. |
|
1457 | 551 |
|
552 |
run + 1 to:newSz do:[:i||v| |
|
2265 | 553 |
startOfLinesY at:i put:((startOfLinesY at:i) + dltY) |
1390 | 554 |
]. |
555 |
||
556 |
orgY := viewOrigin y. |
|
557 |
absY1 := absY0 + dltY. |
|
558 |
visY0 := absY0 - orgY. |
|
559 |
visY1 := absY1 - orgY. |
|
560 |
maxHg := height - margin. |
|
561 |
||
562 |
absY0 < orgY ifTrue:[ |
|
2265 | 563 |
self originWillChange. |
564 |
viewOrigin y:(dltY + orgY). |
|
565 |
self originChanged:(0 @ dltY). |
|
1390 | 566 |
]. |
1457 | 567 |
|
1390 | 568 |
(visY0 >= maxHg or:[visY1 <= margin]) ifTrue:[ |
2265 | 569 |
^ self contentsChanged |
1390 | 570 |
]. |
571 |
visY0 := visY0 max:margin. |
|
572 |
visY1 := visY1 min:maxHg. |
|
573 |
||
1773
9dba0f0dda0e
invalidate uptoend not all if a damage exists (insert/remove)
ca
parents:
1753
diff
changeset
|
574 |
self hasDamage ifTrue:[ |
2265 | 575 |
self invalidate:(Rectangle left:0 |
576 |
top:visY0 |
|
577 |
width:width |
|
578 |
height:height - visY0). |
|
1773
9dba0f0dda0e
invalidate uptoend not all if a damage exists (insert/remove)
ca
parents:
1753
diff
changeset
|
579 |
|
9dba0f0dda0e
invalidate uptoend not all if a damage exists (insert/remove)
ca
parents:
1753
diff
changeset
|
580 |
^ self contentsChanged. |
9dba0f0dda0e
invalidate uptoend not all if a damage exists (insert/remove)
ca
parents:
1753
diff
changeset
|
581 |
]. |
9dba0f0dda0e
invalidate uptoend not all if a damage exists (insert/remove)
ca
parents:
1753
diff
changeset
|
582 |
|
1390 | 583 |
(start == list size or:[(cpyHg := maxHg - visY1) < 20]) ifTrue:[ |
2265 | 584 |
visY1 := maxHg |
1390 | 585 |
] ifFalse:[ |
2265 | 586 |
self catchExpose. |
1390 | 587 |
|
2265 | 588 |
self copyFrom:self x:0 y:visY0 |
589 |
toX:0 y:visY1 |
|
590 |
width:width height:cpyHg async:true. |
|
1390 | 591 |
|
2265 | 592 |
self waitForExpose |
1390 | 593 |
]. |
594 |
||
1457 | 595 |
self invalidateX:margin |
2265 | 596 |
y:visY0 |
597 |
width:width - margin - margin |
|
598 |
height:(visY1 - visY0). |
|
1457 | 599 |
|
1390 | 600 |
self contentsChanged. |
601 |
! |
|
602 |
||
1446
fb46beba2d0c
startOfLines can have nil at end; lookup the first not nil
Claus Gittinger <cg@exept.de>
parents:
1444
diff
changeset
|
603 |
listChangedRemove:aStart toIndex:aStop |
1390 | 604 |
"list changed; items are removed |
605 |
" |
|
606 |
|noRedraw |
|
607 |
size "{ Class: SmallInteger }" |
|
608 |
absY0 "{ Class: SmallInteger }" |
|
609 |
absY1 "{ Class: SmallInteger }" |
|
610 |
visY0 "{ Class: SmallInteger }" |
|
611 |
visY1 "{ Class: SmallInteger }" |
|
612 |
orgY "{ Class: SmallInteger }" |
|
613 |
orgX "{ Class: SmallInteger }" |
|
614 |
dltY "{ Class: SmallInteger }" |
|
615 |
cpyHg "{ Class: SmallInteger }" |
|
616 |
maxHg "{ Class: SmallInteger }" |
|
1444
0b7cd00e2537
check range before delete lines
Claus Gittinger <cg@exept.de>
parents:
1443
diff
changeset
|
617 |
stop "{ Class: SmallInteger }" |
1446
fb46beba2d0c
startOfLines can have nil at end; lookup the first not nil
Claus Gittinger <cg@exept.de>
parents:
1444
diff
changeset
|
618 |
start "{ Class: SmallInteger }" |
1457 | 619 |
newSz "{ Class: SmallInteger }" |
1390 | 620 |
| |
1446
fb46beba2d0c
startOfLines can have nil at end; lookup the first not nil
Claus Gittinger <cg@exept.de>
parents:
1444
diff
changeset
|
621 |
stop := aStop. |
fb46beba2d0c
startOfLines can have nil at end; lookup the first not nil
Claus Gittinger <cg@exept.de>
parents:
1444
diff
changeset
|
622 |
start := aStart. |
1390 | 623 |
|
1446
fb46beba2d0c
startOfLines can have nil at end; lookup the first not nil
Claus Gittinger <cg@exept.de>
parents:
1444
diff
changeset
|
624 |
(size := stop - start + 1) == 0 ifTrue:[ |
2265 | 625 |
^ self |
1390 | 626 |
]. |
1446
fb46beba2d0c
startOfLines can have nil at end; lookup the first not nil
Claus Gittinger <cg@exept.de>
parents:
1444
diff
changeset
|
627 |
|
1390 | 628 |
self listSizeChanged:start nLines:(size negated). |
629 |
shown not ifTrue:[^ self]. |
|
1451 | 630 |
|
1457 | 631 |
newSz := startOfLinesY size - size. |
632 |
||
633 |
(newSz - 1) ~~ list size ifTrue:[ |
|
2265 | 634 |
"/ |
635 |
"/ no longer synchrounous |
|
636 |
"/ |
|
637 |
^ self lostSynchronisation |
|
1451 | 638 |
]. |
639 |
||
1390 | 640 |
absY0 := self yAbsoluteOfLine:start. |
1457 | 641 |
absY1 := self yAbsoluteOfLine:stop + 1. |
1390 | 642 |
dltY := absY1 - absY0. |
643 |
||
1457 | 644 |
startOfLinesY removeFromIndex:(start + 1) toIndex:(stop + 1). |
1390 | 645 |
|
1457 | 646 |
(start + 1) to:newSz do:[:i| |
2265 | 647 |
absY0 := startOfLinesY at:i. |
648 |
startOfLinesY at:i put:(absY0 - dltY). |
|
1390 | 649 |
]. |
650 |
||
651 |
orgY := viewOrigin y. |
|
652 |
orgX := viewOrigin x. |
|
653 |
||
654 |
absY0 := self yAbsoluteOfLine:start. |
|
655 |
absY1 := absY0 + dltY. |
|
656 |
visY0 := absY0 - orgY. |
|
657 |
visY1 := absY1 - orgY. |
|
658 |
maxHg := height - margin. |
|
659 |
||
660 |
(list size == 0 or:[(orgY ~~ 0 and:[self maxViewOriginY == 0])]) ifTrue:[ |
|
2265 | 661 |
(orgX ~~ 0 or:[orgY ~~ 0]) ifTrue:[ |
662 |
self originWillChange. |
|
663 |
viewOrigin := 0@0. |
|
664 |
self originChanged:((orgX @ orgY) negated). |
|
665 |
]. |
|
666 |
self invalidate. |
|
1390 | 667 |
^ self contentsChanged |
668 |
]. |
|
669 |
||
670 |
visY0 < margin ifTrue:[ |
|
2265 | 671 |
noRedraw := visY1 <= margin. |
672 |
noRedraw ifTrue:[dltY := dltY negated] ifFalse:[dltY := visY0]. |
|
1390 | 673 |
|
2265 | 674 |
self originWillChange. |
675 |
viewOrigin y:(dltY + orgY). |
|
676 |
self originChanged:(0 @ dltY). |
|
1390 | 677 |
] ifFalse:[ |
2265 | 678 |
noRedraw := visY0 >= maxHg |
1390 | 679 |
]. |
1773
9dba0f0dda0e
invalidate uptoend not all if a damage exists (insert/remove)
ca
parents:
1753
diff
changeset
|
680 |
visY0 := visY0 max:margin. |
9dba0f0dda0e
invalidate uptoend not all if a damage exists (insert/remove)
ca
parents:
1753
diff
changeset
|
681 |
|
1457 | 682 |
self hasDamage ifTrue:[ |
2265 | 683 |
self invalidate:(Rectangle left:0 |
684 |
top:visY0 |
|
685 |
width:width |
|
686 |
height:height - visY0). |
|
1773
9dba0f0dda0e
invalidate uptoend not all if a damage exists (insert/remove)
ca
parents:
1753
diff
changeset
|
687 |
|
2265 | 688 |
noRedraw := true |
1457 | 689 |
]. |
1390 | 690 |
|
1457 | 691 |
noRedraw ifFalse:[ |
2265 | 692 |
cpyHg := maxHg - visY1. |
1390 | 693 |
|
2265 | 694 |
cpyHg > 20 ifTrue:[ |
695 |
self catchExpose. |
|
696 |
self copyFrom:self x:0 y:visY1 toX:0 y:visY0 |
|
697 |
width:width height:cpyHg async:true. |
|
698 |
self waitForExpose. |
|
699 |
visY0 := visY0 + cpyHg. |
|
700 |
]. |
|
1390 | 701 |
|
2265 | 702 |
self invalidateX:margin |
703 |
y:visY0 |
|
704 |
width:width - margin - margin |
|
705 |
height:(maxHg - visY0). |
|
1390 | 706 |
]. |
707 |
self contentsChanged. |
|
708 |
! |
|
709 |
||
1535
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
710 |
originChanged:aDelta |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
711 |
"change origin of registered views |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
712 |
" |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
713 |
displayedFrames keys do:[:aFrame| |
2265 | 714 |
aFrame origin:(aFrame origin - aDelta) |
1535
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
715 |
]. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
716 |
super originChanged:aDelta. |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
717 |
|
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
718 |
! |
872422bc0e81
support frames (views) within the list
Claus Gittinger <cg@exept.de>
parents:
1534
diff
changeset
|
719 |
|
1443 | 720 |
syncUpdate:what with:args |
721 |
"handle synchronous change |
|
1390 | 722 |
" |
1443 | 723 |
|a1 a2| |
1390 | 724 |
|
1443 | 725 |
args isCollection ifFalse:[ |
2265 | 726 |
what == #at: ifTrue:[self lineChangedAt:args with:nil. ^ self]. |
727 |
what == #insert: ifTrue:[self listChangedInsert:args nItems:1. ^ self]. |
|
728 |
what == #remove: ifTrue:[self listChangedRemove:args toIndex:args. ^ self]. |
|
729 |
^ self. |
|
1995 | 730 |
]. |
1390 | 731 |
|
1995 | 732 |
a1 := args at:1. |
733 |
a2 := args at:2. |
|
1390 | 734 |
|
1995 | 735 |
what == #at: ifTrue:[self lineChangedAt:a1 with:a2. ^ self]. |
736 |
what == #insertCollection: ifTrue:[self listChangedInsert:a1 nItems:a2. ^ self]. |
|
737 |
what == #removeFrom: ifTrue:[self listChangedRemove:a1 toIndex:a2. ^ self]. |
|
738 |
what == #replace: ifTrue:[ |
|
2265 | 739 |
a1 to:a2 do:[:i|self lineChangedAt:i with:nil]. |
740 |
^ self |
|
1995 | 741 |
]. |
1443 | 742 |
! |
743 |
||
744 |
update:what with:aPara from:chgObj |
|
745 |
"catch and handle any notification raised from the list model |
|
746 |
or list holder |
|
747 |
" |
|
1773
9dba0f0dda0e
invalidate uptoend not all if a damage exists (insert/remove)
ca
parents:
1753
diff
changeset
|
748 |
|
1443 | 749 |
chgObj ~~ list ifTrue:[ |
2265 | 750 |
chgObj == listHolder ifTrue:[ |
751 |
self syncPushEvent:#list: with:(listHolder value) |
|
752 |
] ifFalse:[ |
|
753 |
super update:what with:aPara from:chgObj |
|
754 |
]. |
|
755 |
^ self |
|
1443 | 756 |
]. |
757 |
||
758 |
( #( insert: |
|
2265 | 759 |
remove: |
760 |
removeFrom: |
|
761 |
insertCollection: |
|
762 |
at: |
|
763 |
replace: |
|
764 |
) includes:what |
|
1443 | 765 |
) ifTrue:[ |
2265 | 766 |
(aPara isCollection and:[(aPara at:1) == 1 and:[(aPara at:2) == list size]]) ifTrue:[ |
767 |
self list:list |
|
768 |
] ifFalse:[ |
|
769 |
self syncPushEvent:#syncUpdate:with: with:what with:aPara |
|
770 |
] |
|
1443 | 771 |
] |
1390 | 772 |
! ! |
773 |
||
774 |
!ListModelView methodsFor:'drawing'! |
|
775 |
||
1532
56e0fafc4349
change display protocol for item
Claus Gittinger <cg@exept.de>
parents:
1531
diff
changeset
|
776 |
displayElement:anItem x:x y:y h:h |
56e0fafc4349
change display protocol for item
Claus Gittinger <cg@exept.de>
parents:
1531
diff
changeset
|
777 |
"draw a label at x/y; fg/bg colors are already set |
1390 | 778 |
" |
2265 | 779 |
|label |
1532
56e0fafc4349
change display protocol for item
Claus Gittinger <cg@exept.de>
parents:
1531
diff
changeset
|
780 |
y0 "{ Class: SmallInteger }" |
1390 | 781 |
| |
1752 | 782 |
anItem isHierarchicalItem ifTrue:[ |
2265 | 783 |
anItem displayOn:self x:x y:y h:h |
1399 | 784 |
] ifFalse:[ |
2265 | 785 |
y0 := y - ((anItem heightOn:self) + 1 - h // 2). |
786 |
label := anItem. |
|
1390 | 787 |
|
2265 | 788 |
label isImageOrForm ifFalse:[ |
789 |
label isNumber ifTrue:[ |
|
790 |
label := label printString |
|
791 |
]. |
|
792 |
y0 := y0 + font ascent |
|
793 |
]. |
|
794 |
label displayOn:self x:x y:y0 |
|
795 |
]. |
|
1390 | 796 |
|
797 |
! |
|
798 |
||
2244
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
799 |
invalidateLineAt:aLineNr |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
800 |
"invalidate a specific line; add a damage to redraw to the input event queue. |
1399 | 801 |
" |
2244
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
802 |
self invalidateLineAt:aLineNr repairNow:false. |
1390 | 803 |
! |
804 |
||
2244
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
805 |
invalidateLineAt:aLineNr repairNow:doRepair |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
806 |
"add a damage to redraw the line specified by its line number to the |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
807 |
input event queue. If repairNow is true, force the view to repair all |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
808 |
of its damaged areas right now. |
1390 | 809 |
" |
810 |
|y0 "{ Class:SmallInteger }" |
|
811 |
y1 "{ Class:SmallInteger }" |
|
812 |
yB "{ Class:SmallInteger }" |
|
813 |
| |
|
814 |
||
2244
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
815 |
(shown and:[aLineNr notNil and:[aLineNr > 0]]) ifFalse:[ |
2265 | 816 |
^ self |
2244
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
817 |
]. |
1390 | 818 |
|
2244
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
819 |
yB := height - margin. |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
820 |
y0 := (self yVisibleOfLine:aLineNr) max:margin. |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
821 |
|
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
822 |
y0 < yB ifTrue:[ |
2265 | 823 |
y1 := (self yVisibleOfLine:(aLineNr + 1)) min:yB. |
2244
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
824 |
|
2265 | 825 |
y1 > margin ifTrue:[ |
826 |
self invalidateX:0 y:y0 width:width height:(y1 - y0) repairNow:doRepair. |
|
827 |
] |
|
1390 | 828 |
] |
2244
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
829 |
! |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
830 |
|
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
831 |
redraw |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
832 |
"redraw complete view |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
833 |
" |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
834 |
self redrawX:0 y:0 width:width height:height. |
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
835 |
|
1390 | 836 |
|
837 |
! |
|
838 |
||
839 |
redrawX:x y:y width:w height:h |
|
840 |
"redraw part of myself immediately, given logical coordinates |
|
841 |
" |
|
842 |
|savClip start stop yAbs| |
|
843 |
||
844 |
shown ifFalse:[^ self]. |
|
845 |
||
846 |
self paint:bgColor. |
|
847 |
self fillRectangleX:x y:y width:w height:h. |
|
848 |
||
1615 | 849 |
widthOfContents isNil ifTrue:[self preferredExtent]. |
850 |
||
1390 | 851 |
(start := self yVisibleToLineNr:y) isNil ifTrue:[ |
2265 | 852 |
^ self |
1390 | 853 |
]. |
854 |
yAbs := y + h. |
|
855 |
||
856 |
(stop := self yVisibleToLineNr:yAbs) isNil ifTrue:[ |
|
2265 | 857 |
stop := list size. |
1390 | 858 |
] ifFalse:[ |
2265 | 859 |
yAbs == (startOfLinesY at:stop) ifTrue:[ |
860 |
stop := (stop - 1) max:start |
|
861 |
]. |
|
2188 | 862 |
]. |
863 |
stop < start ifTrue:[ |
|
2265 | 864 |
"/ oops, list changed during redraw |
865 |
^ self invalidate |
|
2188 | 866 |
]. |
1390 | 867 |
|
868 |
savClip := clipRect. |
|
869 |
self clippingRectangle:(Rectangle left:x top:y width:w height:h). |
|
870 |
||
871 |
StopRedrawSignal handle:[:ex| self invalidate. |
|
2265 | 872 |
ex return |
873 |
] do:[ self drawFrom:start |
|
874 |
to:stop |
|
875 |
x:x |
|
876 |
y:(self yVisibleOfLine:start) |
|
877 |
w:w |
|
878 |
]. |
|
1390 | 879 |
|
880 |
self clippingRectangle:savClip. |
|
881 |
! ! |
|
882 |
||
883 |
!ListModelView methodsFor:'event handling'! |
|
884 |
||
885 |
keyPress:aKey x:x y:y |
|
886 |
"a key was pressed - handle page-keys here |
|
887 |
" |
|
888 |
<resource: #keyboard( #PreviousPage #NextPage #HalfPageUp #HalfPageDown |
|
2265 | 889 |
#BeginOfText #EndOfText #ScrollUp #ScrollDown |
890 |
)> |
|
1390 | 891 |
|
892 |
|n sensor| |
|
893 |
||
894 |
list size ~~ 0 ifTrue:[ |
|
2265 | 895 |
(aKey == #PreviousPage) ifTrue:[^ self pageUp]. |
896 |
(aKey == #NextPage) ifTrue:[^ self pageDown]. |
|
897 |
(aKey == #HalfPageUp) ifTrue:[^ self halfPageUp]. |
|
898 |
(aKey == #HalfPageDown) ifTrue:[^ self halfPageDown]. |
|
899 |
(aKey == #BeginOfText) ifTrue:[^ self scrollToTop]. |
|
900 |
(aKey == #EndOfText) ifTrue:[^ self scrollToBottom]. |
|
1390 | 901 |
|
2265 | 902 |
(aKey == #ScrollUp or:[aKey == #ScrollDown]) ifTrue:[ |
903 |
sensor := self sensor. |
|
1390 | 904 |
|
2265 | 905 |
n := sensor notNil ifTrue:[1 + (sensor compressKeyPressEventsWithKey:aKey)] |
906 |
ifFalse:[1]. |
|
1390 | 907 |
|
2265 | 908 |
n := n * self verticalScrollStep. |
1390 | 909 |
|
2265 | 910 |
aKey == #ScrollUp ifTrue:[self scrollUp:n] |
911 |
ifFalse:[self scrollDown:n]. |
|
912 |
^ self |
|
913 |
]. |
|
1390 | 914 |
]. |
915 |
super keyPress:aKey x:x y:y |
|
916 |
! ! |
|
917 |
||
1554 | 918 |
!ListModelView methodsFor:'event simulation'! |
919 |
||
920 |
syncFlushEvent:aSelector |
|
921 |
"throw away all pending syncronization events for a specific selector |
|
922 |
" |
|
923 |
|sensor| |
|
924 |
||
925 |
(syncronizeEvents and:[(sensor := self sensor) notNil]) ifTrue:[ |
|
2265 | 926 |
sensor flushUserEventsFor:self withType:aSelector |
1554 | 927 |
] |
928 |
||
929 |
! |
|
930 |
||
931 |
syncPushEvent:aSelector |
|
932 |
"if events are synchronized, the message send is pushed into my |
|
933 |
event queue and will be performed when its time to handle events. |
|
934 |
Otherwise the event is handled immediately |
|
935 |
" |
|
936 |
|sensor| |
|
937 |
||
938 |
(syncronizeEvents and:[(sensor := self sensor) notNil]) ifTrue:[ |
|
2265 | 939 |
sensor pushUserEvent:aSelector for:self withArguments:#() |
1554 | 940 |
] ifFalse:[ |
2265 | 941 |
self perform:aSelector |
1554 | 942 |
] |
943 |
||
944 |
||
945 |
! |
|
946 |
||
947 |
syncPushEvent:aSelector with:arg |
|
948 |
"if events are synchronized, the message send is pushed into my |
|
949 |
event queue and will be performed when its time to handle events. |
|
950 |
Otherwise the event is handled immediately |
|
951 |
" |
|
952 |
|sensor| |
|
953 |
||
954 |
(syncronizeEvents and:[(sensor := self sensor) notNil]) ifTrue:[ |
|
2265 | 955 |
sensor pushUserEvent:aSelector for:self withArguments:(Array with:arg) |
1554 | 956 |
] ifFalse:[ |
2265 | 957 |
self perform:aSelector with:arg |
1554 | 958 |
] |
959 |
||
960 |
! |
|
961 |
||
962 |
syncPushEvent:aSelector with:arg1 with:arg2 |
|
963 |
"if events are synchronized, the message send is pushed into my |
|
964 |
event queue and will be performed when its time to handle events. |
|
965 |
Otherwise the event is handled immediately |
|
966 |
" |
|
967 |
|sensor| |
|
968 |
||
969 |
(syncronizeEvents and:[(sensor := self sensor) notNil]) ifTrue:[ |
|
2265 | 970 |
sensor pushUserEvent:aSelector for:self withArguments:(Array with:arg1 with:arg2) |
1554 | 971 |
] ifFalse:[ |
2265 | 972 |
self perform:aSelector with:arg1 with:arg2 |
1554 | 973 |
] |
974 |
||
975 |
! |
|
976 |
||
977 |
syncronizeEvents |
|
978 |
"if true, all asynchronous events are pushed into my event queue |
|
979 |
and will be performed when its time to handle the events. |
|
980 |
Otherwise these events are handled immediately. On default disabled. |
|
981 |
" |
|
982 |
^ syncronizeEvents |
|
983 |
! |
|
984 |
||
985 |
syncronizeEvents:aBoolean |
|
986 |
"if true, all asynchronous events are pushed into my event queue |
|
987 |
and will be performed when its time to handle the events. |
|
988 |
Otherwise these events are handled immediately. On default disabled. |
|
989 |
" |
|
990 |
syncronizeEvents := aBoolean ? false. |
|
991 |
! ! |
|
992 |
||
1390 | 993 |
!ListModelView methodsFor:'fetch resources'! |
994 |
||
995 |
colorOnDevice:aColor |
|
996 |
"fetch a device colors |
|
997 |
" |
|
2097 | 998 |
^ aColor notNil ifTrue:[aColor onDevice:device] ifFalse:[nil] |
1390 | 999 |
! |
1000 |
||
1001 |
imageOnDevice:anImage |
|
1002 |
"associate image to device and clear pixel mask |
|
1003 |
returns the new image. |
|
1004 |
" |
|
1005 |
|image| |
|
1006 |
||
1007 |
(image := anImage) notNil ifTrue:[ |
|
2265 | 1008 |
image device ~~ device ifTrue:[ |
1009 |
image := image copy. |
|
1010 |
]. |
|
1011 |
image := image onDevice:device. |
|
1012 |
image := image clearMaskedPixels. |
|
1390 | 1013 |
]. |
1014 |
^ image |
|
1015 |
! ! |
|
1016 |
||
1417 | 1017 |
!ListModelView methodsFor:'focus handling'! |
1018 |
||
1019 |
wantsFocusWithButtonPress |
|
1020 |
"catch the keyboard focus on button click |
|
1021 |
" |
|
1022 |
^ true |
|
1023 |
||
1024 |
||
1025 |
! |
|
1026 |
||
1027 |
wantsFocusWithPointerEnter |
|
1028 |
"views which like to take the keyboard focus |
|
1029 |
when the pointer enters can do so by redefining this |
|
1030 |
to return true" |
|
1031 |
||
1032 |
^ true |
|
1033 |
||
1034 |
! ! |
|
1035 |
||
1390 | 1036 |
!ListModelView methodsFor:'initialize / release'! |
1037 |
||
1038 |
create |
|
1039 |
"fetch device dependent resources |
|
1040 |
" |
|
1041 |
super create. |
|
1042 |
self fetchResources. |
|
1043 |
! |
|
1044 |
||
1045 |
initStyle |
|
1046 |
"setup viewStyle specifics |
|
1047 |
" |
|
1048 |
super initStyle. |
|
1049 |
||
1595 | 1050 |
DefaultForegroundColor isNil ifTrue:[ |
2265 | 1051 |
self updateStyleCache |
1595 | 1052 |
]. |
1053 |
||
1390 | 1054 |
DefaultBackgroundColor notNil ifTrue:[ |
2265 | 1055 |
viewBackground := DefaultBackgroundColor |
1390 | 1056 |
]. |
1057 |
lineSpacing := 0. |
|
1058 |
textStartLeft := 2. |
|
1059 |
fgColor := DefaultForegroundColor. |
|
1060 |
bgColor := viewBackground. |
|
1061 |
startOfLinesY := OrderedCollection new. |
|
1062 |
||
1063 |
startOfLinesY add:(2 + margin). "/ top inset of first line |
|
1064 |
||
1065 |
DefaultShadowColor notNil ifTrue:[ |
|
2265 | 1066 |
shadowColor := DefaultShadowColor |
1390 | 1067 |
]. |
1068 |
||
1069 |
DefaultLightColor notNil ifTrue:[ |
|
2265 | 1070 |
lightColor := DefaultLightColor |
1390 | 1071 |
]. |
1072 |
! |
|
1073 |
||
1074 |
initialize |
|
1075 |
"setup default attributes |
|
1076 |
" |
|
1077 |
super initialize. |
|
1078 |
||
2261 | 1079 |
viewOrigin := 0@0. |
1080 |
bitGravity := #NorthWest. |
|
1081 |
enabled := true. |
|
1082 |
displayedFrames := WeakIdentityDictionary new. |
|
1083 |
syncronizeEvents := false. |
|
1084 |
autoScroll := true. |
|
1827 | 1085 |
scrollWhenUpdating := #beginOfText. |
2261 | 1086 |
hasConstantHeight := false. |
1390 | 1087 |
! |
1088 |
||
1562 | 1089 |
mapped |
1090 |
"recompute list |
|
1091 |
" |
|
1092 |
shown ifFalse:[ |
|
2265 | 1093 |
self recomputeHeightOfContents. |
1094 |
self contentsChanged. |
|
1562 | 1095 |
]. |
1096 |
super mapped |
|
1097 |
||
1098 |
! |
|
1099 |
||
1390 | 1100 |
recreate |
1832 | 1101 |
"sent after a snapin or a migration, reinit for new device" |
1828 | 1102 |
|
1390 | 1103 |
super recreate. |
1104 |
self fetchResources. |
|
1796
c9d801c011f7
recompute layout after snapIn (font geometry could be different)
Claus Gittinger <cg@exept.de>
parents:
1773
diff
changeset
|
1105 |
! |
c9d801c011f7
recompute layout after snapIn (font geometry could be different)
Claus Gittinger <cg@exept.de>
parents:
1773
diff
changeset
|
1106 |
|
c9d801c011f7
recompute layout after snapIn (font geometry could be different)
Claus Gittinger <cg@exept.de>
parents:
1773
diff
changeset
|
1107 |
reinitialize |
c9d801c011f7
recompute layout after snapIn (font geometry could be different)
Claus Gittinger <cg@exept.de>
parents:
1773
diff
changeset
|
1108 |
"reinit after snapIn (font geometry might be different) |
c9d801c011f7
recompute layout after snapIn (font geometry could be different)
Claus Gittinger <cg@exept.de>
parents:
1773
diff
changeset
|
1109 |
" |
c9d801c011f7
recompute layout after snapIn (font geometry could be different)
Claus Gittinger <cg@exept.de>
parents:
1773
diff
changeset
|
1110 |
super reinitialize. |
c9d801c011f7
recompute layout after snapIn (font geometry could be different)
Claus Gittinger <cg@exept.de>
parents:
1773
diff
changeset
|
1111 |
self recomputeHeightOfContents. |
c9d801c011f7
recompute layout after snapIn (font geometry could be different)
Claus Gittinger <cg@exept.de>
parents:
1773
diff
changeset
|
1112 |
self contentsChanged. |
c9d801c011f7
recompute layout after snapIn (font geometry could be different)
Claus Gittinger <cg@exept.de>
parents:
1773
diff
changeset
|
1113 |
|
2156 | 1114 |
! |
1115 |
||
1116 |
release |
|
1117 |
"remove dependencies |
|
1118 |
" |
|
1119 |
listHolder removeDependent:self. |
|
1120 |
list removeDependent:self. |
|
1121 |
||
1122 |
super release |
|
1390 | 1123 |
! ! |
1124 |
||
1125 |
!ListModelView methodsFor:'private'! |
|
1126 |
||
1457 | 1127 |
hasDamage |
1128 |
"return true, if any damage events (i.e. expose or resize) are pending. |
|
1129 |
" |
|
1130 |
|sensor| |
|
1131 |
||
1132 |
^ (sensor := self sensor) isNil or:[sensor hasDamageFor:self] |
|
1133 |
! |
|
1134 |
||
1390 | 1135 |
yAbsoluteOfLine:aLineNr |
1136 |
"given a lineNr, return y-coordinate absolute |
|
1137 |
" |
|
1744 | 1138 |
|y y2 y1 cash| |
1446
fb46beba2d0c
startOfLines can have nil at end; lookup the first not nil
Claus Gittinger <cg@exept.de>
parents:
1444
diff
changeset
|
1139 |
|
1744 | 1140 |
cash := startOfLinesY. |
1446
fb46beba2d0c
startOfLines can have nil at end; lookup the first not nil
Claus Gittinger <cg@exept.de>
parents:
1444
diff
changeset
|
1141 |
|
1744 | 1142 |
(y := cash at:aLineNr ifAbsent:nil) notNil ifTrue:[ |
2265 | 1143 |
^ y |
1446
fb46beba2d0c
startOfLines can have nil at end; lookup the first not nil
Claus Gittinger <cg@exept.de>
parents:
1444
diff
changeset
|
1144 |
]. |
1744 | 1145 |
|
1146 |
"/ recompute a y position |
|
1147 |
y1 := startOfLinesY at:1 ifAbsent:2. |
|
1148 |
y2 := startOfLinesY at:2 ifAbsent:10. |
|
1149 |
^ aLineNr * (y2 - y1) + y1 |
|
1390 | 1150 |
! |
1151 |
||
1152 |
yVisibleOfLine:aLineNr |
|
1153 |
"given a lineNr, return y-coordinate in view |
|
1154 |
" |
|
1744 | 1155 |
^ (self yAbsoluteOfLine:aLineNr) - viewOrigin y |
1390 | 1156 |
|
1157 |
||
1158 |
! |
|
1159 |
||
1160 |
yVisibleToLineNr:yVisible |
|
1161 |
"returns the line number assigned to a physical y or nil |
|
1162 |
" |
|
1643 | 1163 |
|eol cash |
1390 | 1164 |
yAbs "{ Class: SmallInteger}" |
1165 |
yMid "{ Class: SmallInteger}" |
|
1166 |
size "{ Class: SmallInteger}" |
|
1167 |
next "{ Class: SmallInteger}" |
|
1168 |
low "{ Class: SmallInteger}" |
|
1169 |
high "{ Class: SmallInteger}" |
|
1170 |
middle "{ Class: SmallInteger}" |
|
1171 |
| |
|
1643 | 1172 |
cash := startOfLinesY. |
1390 | 1173 |
|
1643 | 1174 |
(size := cash size) == 1 ifTrue:[^ nil]. "/ EMPTY LIST |
1390 | 1175 |
yAbs := yVisible + viewOrigin y. |
1643 | 1176 |
eol := cash at:size ifAbsent:nil. |
1642 | 1177 |
(eol isNil or:[yAbs > eol]) ifTrue:[^ nil]. "/ END OF LIST |
1390 | 1178 |
|
1179 |
middle := size. |
|
1180 |
size := size - 1. |
|
1181 |
high := size. |
|
1182 |
low := 1. |
|
1183 |
||
1184 |
[(next := low + high // 2) ~~ middle] whileTrue:[ |
|
2265 | 1185 |
(eol := cash at:next ifAbsent:nil) isNil ifTrue:[ |
1186 |
^ nil "/ LIST CHANGED |
|
1187 |
]. |
|
1188 |
middle := next. |
|
1189 |
yMid := eol. |
|
1390 | 1190 |
|
2265 | 1191 |
yMid < yAbs ifTrue:[low := middle] |
1192 |
ifFalse:[high := middle] |
|
1390 | 1193 |
]. |
1194 |
||
1195 |
yAbs < yMid ifTrue:[ |
|
2265 | 1196 |
^ (middle - 1) max:1. |
1390 | 1197 |
]. |
1198 |
middle < size ifTrue:[ |
|
2265 | 1199 |
next := middle + 1. |
1200 |
(eol := cash at:next ifAbsent:nil) isNil ifTrue:[ |
|
1201 |
^ nil "/ LIST CHANGED |
|
1202 |
]. |
|
1203 |
^ eol > yAbs ifTrue:[middle] ifFalse:[next] |
|
1390 | 1204 |
]. |
1205 |
^ size |
|
1206 |
! ! |
|
1207 |
||
1208 |
!ListModelView methodsFor:'protocol'! |
|
1209 |
||
1532
56e0fafc4349
change display protocol for item
Claus Gittinger <cg@exept.de>
parents:
1531
diff
changeset
|
1210 |
drawFrom:start to:stop x:x y:y w:w |
1390 | 1211 |
"draw lines from start to stop. |
1212 |
clipping and clearing the background is already done |
|
1213 |
" |
|
1399 | 1214 |
|item |
1215 |
y0 "{ Class:SmallInteger }" |
|
1390 | 1216 |
y1 "{ Class:SmallInteger }" |
1217 |
x0 "{ Class:SmallInteger }" |
|
1218 |
| |
|
1219 |
self paint:fgColor on:bgColor. |
|
1220 |
||
1221 |
x0 := textStartLeft - viewOrigin x. |
|
1532
56e0fafc4349
change display protocol for item
Claus Gittinger <cg@exept.de>
parents:
1531
diff
changeset
|
1222 |
y1 := y. |
1390 | 1223 |
|
1224 |
start to:stop do:[:i| |
|
2265 | 1225 |
y0 := y1. |
1226 |
y1 := self yVisibleOfLine:(i + 1). |
|
1399 | 1227 |
|
2265 | 1228 |
(item := list at:i ifAbsent:nil) notNil ifTrue:[ |
1229 |
self displayElement:item x:x0 y:y0 h:(y1 - y0) |
|
1230 |
] |
|
1399 | 1231 |
] |
1390 | 1232 |
|
1233 |
! |
|
1234 |
||
1235 |
fetchResources |
|
1236 |
"fetch device colors and ..., to avoid reallocation at redraw time; |
|
1237 |
*** called after a create or snapin to fetch all device resources |
|
1238 |
" |
|
1239 |
fgColor := self colorOnDevice:fgColor. |
|
1240 |
bgColor := self colorOnDevice:bgColor. |
|
2097 | 1241 |
font := font onDevice:device. |
1390 | 1242 |
! |
1243 |
||
2261 | 1244 |
heightOfItem:anItem |
1245 |
"returns the height of an item excluding lineSpacing ... |
|
1390 | 1246 |
" |
2261 | 1247 |
^ anItem heightOn:self |
1390 | 1248 |
! |
1249 |
||
1250 |
listSizeChanged:anIndex nLines:noLines |
|
1251 |
"list size changed; information is stored to recompute the |
|
1252 |
width if required( preferredExtent, horizontal scroller ... ). |
|
1253 |
see: widthOfContents |
|
1254 |
*** if nLines is negative, lines are removed otherwise added. |
|
1255 |
" |
|
1256 |
|start "{ Class:SmallInteger }" |
|
1257 |
stop "{ Class:SmallInteger }" |
|
1258 |
size "{ Class:SmallInteger }" |
|
1259 |
| |
|
1260 |
preferredExtent := nil. |
|
1261 |
||
1262 |
widthOfContents isNil ifTrue:[ "/ recompute whole list |
|
2265 | 1263 |
^ self |
1390 | 1264 |
]. |
1265 |
||
1266 |
(noLines < 0 or:[(size := list size) <= noLines]) ifTrue:[ |
|
2265 | 1267 |
widthOfContents := nil. "/ force recompute whole list |
1268 |
^ self |
|
1390 | 1269 |
]. |
1270 |
||
1271 |
stop := anIndex + noLines - 1. "/ recompute a range |
|
1272 |
start := anIndex. |
|
1273 |
||
1274 |
computeWidthInRange notNil ifTrue:[ |
|
2265 | 1275 |
start := computeWidthInRange y. |
1276 |
stop < start ifTrue:[stop := start min:size]. |
|
1277 |
start := (computeWidthInRange x) min:anIndex. |
|
1390 | 1278 |
]. |
1279 |
computeWidthInRange := start@stop |
|
1280 |
! |
|
1281 |
||
1457 | 1282 |
lostSynchronisation |
1283 |
"called when the changes derived from the model are faster than the handling |
|
1284 |
" |
|
1285 |
shown ifTrue:[ |
|
2265 | 1286 |
self syncFlushEvent:#syncUpdate:with:. |
1287 |
self recomputeHeightOfContents. |
|
1288 |
self invalidate. |
|
1289 |
self contentsChanged |
|
1457 | 1290 |
]. |
1291 |
||
1292 |
||
1293 |
||
1294 |
||
1295 |
! |
|
1296 |
||
1390 | 1297 |
widthOfWidestLineBetween:firstLine and:lastLine |
1298 |
"return the width in pixels of the widest line in a range |
|
1299 |
" |
|
2265 | 1300 |
|item |
1390 | 1301 |
width "{ Class: SmallInteger }" |
1302 |
| |
|
1303 |
width := textStartLeft. |
|
1304 |
||
1305 |
firstLine to:lastLine do:[:anIndex| |
|
2265 | 1306 |
item := list at:anIndex ifAbsent:nil. |
1508
9c54f2e53da1
check whether #at:ifAbsent returns nil.
Claus Gittinger <cg@exept.de>
parents:
1457
diff
changeset
|
1307 |
|
2265 | 1308 |
item isNil ifTrue:[^ width + textStartLeft]. |
1508
9c54f2e53da1
check whether #at:ifAbsent returns nil.
Claus Gittinger <cg@exept.de>
parents:
1457
diff
changeset
|
1309 |
|
2265 | 1310 |
width := (item widthOn:self) max:width |
1390 | 1311 |
]. |
1312 |
^ width + textStartLeft |
|
1313 |
||
1314 |
! ! |
|
1315 |
||
1820 | 1316 |
!ListModelView methodsFor:'queries'! |
1317 |
||
1318 |
size |
|
1319 |
"returns number of raws |
|
1320 |
" |
|
1321 |
^ list size |
|
1322 |
||
1323 |
||
1324 |
! ! |
|
1325 |
||
1390 | 1326 |
!ListModelView methodsFor:'recomputation'! |
1327 |
||
1328 |
preferredExtent |
|
1329 |
"returns the preferred extent |
|
1330 |
" |
|
1331 |
|x y| |
|
1332 |
||
1333 |
preferredExtent isNil ifTrue:[ |
|
2265 | 1334 |
y := self heightOfContents. |
1335 |
x := self widthOfContents. |
|
1336 |
preferredExtent := x@y |
|
1390 | 1337 |
]. |
1338 |
^ preferredExtent |
|
1339 |
||
1340 |
||
1341 |
! |
|
1342 |
||
1343 |
recomputeHeightOfContents |
|
1344 |
"recompute all the y positions |
|
1345 |
" |
|
1643 | 1346 |
|newList |
1347 |
yAbs "{ Class: SmallInteger }" |
|
1390 | 1348 |
lnHg "{ Class: SmallInteger }" |
1643 | 1349 |
size "{ Class: SmallInteger }" |
1390 | 1350 |
| |
1351 |
||
1643 | 1352 |
yAbs := startOfLinesY at:1. "/ top inset of first line |
1353 |
size := list size. |
|
1354 |
newList := OrderedCollection new:(size + 1). |
|
1355 |
||
1356 |
newList add:yAbs. |
|
1390 | 1357 |
|
2264 | 1358 |
size == 0 ifTrue:[ |
2265 | 1359 |
startOfLinesY := newList. |
2264 | 1360 |
^ self |
1361 |
]. |
|
1362 |
||
1363 |
hasConstantHeight ifTrue:[ |
|
2265 | 1364 |
constantHeight notNil ifTrue:[ lnHg := constantHeight ] |
1365 |
ifFalse:[ lnHg := self heightOfLineAt:1 ]. |
|
1366 |
||
1367 |
1 to:size do:[:anIndex| |
|
1368 |
newList add:(yAbs := yAbs + lnHg) |
|
1369 |
]. |
|
1370 |
startOfLinesY := newList. |
|
2264 | 1371 |
^ self |
1372 |
]. |
|
1373 |
||
1643 | 1374 |
1 to:size do:[:anIndex| |
2265 | 1375 |
lnHg := self heightOfLineAt:anIndex. |
1376 |
newList add:(yAbs := yAbs + lnHg) |
|
1390 | 1377 |
]. |
1643 | 1378 |
startOfLinesY := newList. |
1390 | 1379 |
! ! |
1380 |
||
1381 |
!ListModelView methodsFor:'scroller interface'! |
|
1382 |
||
1383 |
heightOfContents |
|
1384 |
"return the height of the contents in pixels |
|
1385 |
" |
|
2257
6d59932d078d
avoid returning nil heightOfContents
Claus Gittinger <cg@exept.de>
parents:
2244
diff
changeset
|
1386 |
^ startOfLinesY last ? 0 |
1390 | 1387 |
! |
1388 |
||
2261 | 1389 |
heightOfLineAt:aLineNr |
1390 |
"returns the total height for a line at an index( including lineSpacing ... ) |
|
1391 |
" |
|
1392 |
|item| |
|
1393 |
||
1394 |
hasConstantHeight ifTrue:[ |
|
2265 | 1395 |
constantHeight notNil ifTrue:[ ^ constantHeight ]. |
1396 |
item := list at:1 ifAbsent:nil. |
|
2264 | 1397 |
|
2265 | 1398 |
item notNil ifTrue:[ |
1399 |
constantHeight := lineSpacing + (self heightOfItem:item). |
|
1400 |
^ constantHeight |
|
1401 |
] |
|
2264 | 1402 |
] ifFalse:[ |
2265 | 1403 |
item := list at:aLineNr ifAbsent:nil. |
2264 | 1404 |
|
2265 | 1405 |
item notNil ifTrue:[ |
1406 |
^ lineSpacing + (self heightOfItem:item) |
|
1407 |
] |
|
2261 | 1408 |
]. |
2264 | 1409 |
^ 4 |
2261 | 1410 |
! |
1411 |
||
1390 | 1412 |
innerHeight |
1413 |
"returns the inner height of the contents shown |
|
1414 |
" |
|
1415 |
^ height - margin - margin |
|
1416 |
||
1417 |
! |
|
1418 |
||
1419 |
innerWidth |
|
1420 |
"returns the inner width of the contents shown |
|
1421 |
" |
|
1422 |
^ width - margin - margin |
|
1423 |
||
1424 |
! |
|
1425 |
||
1426 |
maxViewOriginY |
|
1427 |
"returns the maximum possible y of the view origin |
|
1428 |
" |
|
1429 |
^ (self heightOfContents - self innerHeight) max:0 |
|
1430 |
||
1431 |
||
1432 |
! |
|
1433 |
||
1434 |
verticalScrollStep |
|
1435 |
"return the amount to scroll when stepping up/down. |
|
1436 |
" |
|
1437 |
^ 10 |
|
1438 |
||
1439 |
! |
|
1440 |
||
1441 |
viewOrigin |
|
1442 |
"return the viewOrigin; thats the coordinate of the contents |
|
1443 |
which is shown topLeft in the view. |
|
1444 |
" |
|
1445 |
^ viewOrigin |
|
1446 |
||
1447 |
! |
|
1448 |
||
1449 |
widthOfContents |
|
1450 |
"return the width of the contents in pixels |
|
1451 |
" |
|
1452 |
|range |
|
1453 |
size "{ Class:SmallInteger }" |
|
1454 |
start "{ Class:SmallInteger }" |
|
1455 |
stop "{ Class:SmallInteger }" |
|
1456 |
| |
|
1457 |
(widthOfContents notNil and:[computeWidthInRange isNil]) ifTrue:[ |
|
2265 | 1458 |
^ widthOfContents + textStartLeft |
1390 | 1459 |
]. |
1460 |
range := computeWidthInRange. |
|
1461 |
computeWidthInRange := nil. |
|
1462 |
preferredExtent := nil. |
|
1463 |
size := list size. |
|
1464 |
||
1465 |
size == 0 ifTrue:[ |
|
2265 | 1466 |
widthOfContents := 20. |
1390 | 1467 |
] ifFalse:[ |
2265 | 1468 |
widthOfContents isNil ifTrue:[ |
1469 |
widthOfContents := self widthOfWidestLineBetween:1 and:size |
|
1470 |
] ifFalse:[ |
|
1471 |
start := range x. |
|
1472 |
stop := range y min:size. |
|
1390 | 1473 |
|
2265 | 1474 |
start > stop ifFalse:[ |
1475 |
size := self widthOfWidestLineBetween:start and:stop. |
|
1390 | 1476 |
|
2265 | 1477 |
widthOfContents < size ifTrue:[ |
1478 |
widthOfContents := size |
|
1479 |
] |
|
1480 |
] |
|
1481 |
] |
|
1390 | 1482 |
]. |
1483 |
^ widthOfContents + textStartLeft |
|
1484 |
! |
|
1485 |
||
1486 |
xOriginOfContents |
|
1487 |
"return the horizontal origin of the contents in pixels |
|
1488 |
" |
|
1489 |
^ viewOrigin x |
|
1490 |
||
1491 |
! |
|
1492 |
||
1493 |
yOriginOfContents |
|
1494 |
"return the vertical origin of the contents in pixels |
|
1495 |
" |
|
1496 |
^ viewOrigin y |
|
1497 |
||
1498 |
! ! |
|
1499 |
||
1500 |
!ListModelView methodsFor:'scrolling'! |
|
1501 |
||
1502 |
halfPageDown |
|
1503 |
"scroll down half a page |
|
1504 |
" |
|
1827 | 1505 |
self scrollDown:(height // 2). |
1390 | 1506 |
|
1507 |
! |
|
1508 |
||
1509 |
halfPageUp |
|
1510 |
"scroll up half a page |
|
1511 |
" |
|
1827 | 1512 |
self scrollUp:(height // 2). |
1390 | 1513 |
|
1514 |
! |
|
1515 |
||
1516 |
scrollTo:anOrigin redraw:doRedraw |
|
1517 |
"change origin to have newOrigin be visible at the top-left. |
|
1518 |
" |
|
1538 | 1519 |
|newOrg dltOrg winGrp |
1390 | 1520 |
innerWT "{ Class:SmallInteger }" |
1521 |
innerHG "{ Class:SmallInteger }" |
|
1522 |
h "{ Class:SmallInteger }" |
|
1523 |
x "{ Class:SmallInteger }" |
|
1524 |
x0 "{ Class:SmallInteger }" |
|
1525 |
x1 "{ Class:SmallInteger }" |
|
1526 |
y "{ Class:SmallInteger }" |
|
1527 |
w "{ Class:SmallInteger }" |
|
1528 |
y0 "{ Class:SmallInteger }" |
|
1529 |
y1 "{ Class:SmallInteger }" |
|
1530 |
dX "{ Class:SmallInteger }" |
|
1531 |
dY "{ Class:SmallInteger }" |
|
1532 |
| |
|
1531 | 1533 |
|
1580 | 1534 |
realized ifFalse:[ |
2265 | 1535 |
^ self |
1390 | 1536 |
]. |
1580 | 1537 |
|
1390 | 1538 |
innerWT := self innerWidth. |
1539 |
innerHG := self innerHeight. |
|
1540 |
||
1541 |
h := viewOrigin y. |
|
1542 |
||
1543 |
(y := anOrigin y) > h ifTrue:[ "/ end of contents |
|
2265 | 1544 |
y > (dY := self maxViewOriginY) ifTrue:[ |
1545 |
y := dY max:h |
|
1546 |
] |
|
1390 | 1547 |
] ifFalse:[ |
2265 | 1548 |
y := y max:0. |
1390 | 1549 |
]. |
1550 |
||
1551 |
(x := anOrigin x) > 0 ifTrue:[ |
|
2265 | 1552 |
x := x min:(self widthOfContents - innerWT). |
1390 | 1553 |
]. |
1554 |
x := x max:0. |
|
1555 |
newOrg := (x @ y). |
|
1556 |
dltOrg := newOrg - viewOrigin. |
|
1557 |
dX := dltOrg x. |
|
1558 |
dY := dltOrg y. |
|
1559 |
||
1560 |
(dX == 0 and:[dY == 0]) ifTrue:[ |
|
2265 | 1561 |
^ self |
1390 | 1562 |
]. |
1534 | 1563 |
dY := dY abs. |
1564 |
dX := dX abs. |
|
1390 | 1565 |
|
1534 | 1566 |
( (dX ~~ 0 and:[dY ~~ 0]) "/ scroll vertical & horizontal |
1567 |
or:[(innerHG - dY < 20 or:[innerWT - dX < 20])] "/ faster to invalidate screen |
|
1568 |
) ifTrue:[ |
|
2265 | 1569 |
viewOrigin := newOrg. |
1570 |
self originChanged:dltOrg. |
|
1534 | 1571 |
^ self invalidate |
1572 |
]. |
|
1753
17769f8df493
#scrollTo:redraw: first check whether full invalidate otherwise processRealExposeEventsFor:
ca
parents:
1752
diff
changeset
|
1573 |
|
17769f8df493
#scrollTo:redraw: first check whether full invalidate otherwise processRealExposeEventsFor:
ca
parents:
1752
diff
changeset
|
1574 |
(winGrp := self windowGroup) notNil ifTrue:[ |
2265 | 1575 |
winGrp processRealExposeEventsFor:self. |
1753
17769f8df493
#scrollTo:redraw: first check whether full invalidate otherwise processRealExposeEventsFor:
ca
parents:
1752
diff
changeset
|
1576 |
]. |
17769f8df493
#scrollTo:redraw: first check whether full invalidate otherwise processRealExposeEventsFor:
ca
parents:
1752
diff
changeset
|
1577 |
|
17769f8df493
#scrollTo:redraw: first check whether full invalidate otherwise processRealExposeEventsFor:
ca
parents:
1752
diff
changeset
|
1578 |
self originWillChange. |
17769f8df493
#scrollTo:redraw: first check whether full invalidate otherwise processRealExposeEventsFor:
ca
parents:
1752
diff
changeset
|
1579 |
|
17769f8df493
#scrollTo:redraw: first check whether full invalidate otherwise processRealExposeEventsFor:
ca
parents:
1752
diff
changeset
|
1580 |
doRedraw ifFalse:[ |
2265 | 1581 |
viewOrigin := newOrg. |
1582 |
^ self originChanged:dltOrg |
|
1753
17769f8df493
#scrollTo:redraw: first check whether full invalidate otherwise processRealExposeEventsFor:
ca
parents:
1752
diff
changeset
|
1583 |
]. |
17769f8df493
#scrollTo:redraw: first check whether full invalidate otherwise processRealExposeEventsFor:
ca
parents:
1752
diff
changeset
|
1584 |
|
1531 | 1585 |
self catchExpose. |
1586 |
viewOrigin := newOrg. |
|
1587 |
||
1390 | 1588 |
dY ~~ 0 ifTrue:[ "/ SCROLL VERTICAL |
2265 | 1589 |
y0 := y1 := margin + dY. |
1590 |
h := innerHG - dY. |
|
1390 | 1591 |
|
2265 | 1592 |
dltOrg y < 0 ifTrue:[y0 := margin. y := y0] |
1593 |
ifFalse:[y1 := margin. y := y1 + h]. |
|
1390 | 1594 |
|
2265 | 1595 |
self copyFrom:self x:margin y:y0 toX:margin y:y1 width:innerWT height:h async:true. |
1596 |
self invalidateX:margin y:y width:innerWT height:(innerHG - h). |
|
1390 | 1597 |
|
1598 |
] ifFalse:[ "/ SCROLL HORIZONTAL |
|
2265 | 1599 |
x0 := x1 := dX + margin. |
1600 |
w := innerWT - dX. |
|
1390 | 1601 |
|
2265 | 1602 |
dltOrg x < 0 ifTrue:[x0 := x := margin ] |
1603 |
ifFalse:[x1 := margin. x := w]. |
|
1390 | 1604 |
|
2265 | 1605 |
self copyFrom:self x:x0 y:margin toX:x1 y:margin width:w height:innerHG async:true. |
1606 |
self invalidateX:x y:margin width:(width - w) height:innerHG. |
|
1390 | 1607 |
]. |
1608 |
self originChanged:dltOrg. |
|
1531 | 1609 |
self waitForExpose. |
1610 |
||
1390 | 1611 |
! |
1612 |
||
1613 |
scrollToLine:aLineNumber |
|
1614 |
"make line visible |
|
1615 |
" |
|
1744 | 1616 |
|inHg "{ Class:SmallInteger }" |
1617 |
yTop "{ Class:SmallInteger }" |
|
1618 |
orgY "{ Class:SmallInteger }" |
|
1619 |
yBot "{ Class:SmallInteger }" |
|
1390 | 1620 |
| |
1744 | 1621 |
(shown and:[aLineNumber notNil and:[aLineNumber between:1 and:list size]]) ifFalse:[ |
2265 | 1622 |
^ self |
1390 | 1623 |
]. |
1624 |
||
1744 | 1625 |
yTop := self yAbsoluteOfLine:aLineNumber. |
1626 |
inHg := self innerHeight. |
|
1627 |
orgY := viewOrigin y. |
|
1628 |
||
1629 |
yTop > orgY ifTrue:[ |
|
2265 | 1630 |
yBot := self yAbsoluteOfLine:(aLineNumber + 1). |
1390 | 1631 |
|
2265 | 1632 |
yBot <= (orgY + inHg) ifTrue:[ |
1633 |
^ self |
|
1634 |
]. |
|
1390 | 1635 |
]. |
1744 | 1636 |
yTop := (yTop - (inHg // 2)) max:0. |
1637 |
self scrollTo:(viewOrigin x @ yTop). |
|
1390 | 1638 |
|
1639 |
||
1640 |
! ! |
|
1641 |
||
1748 | 1642 |
!ListModelView methodsFor:'scrolling auto'! |
1643 |
||
1644 |
startAutoScroll:aBlock distance:aDistance |
|
1645 |
"setup for auto-scroll (when button-press-moving below view); |
|
1646 |
- timeDelta for scroll is computed from distance |
|
1647 |
" |
|
1648 |
|timeDelta| |
|
1649 |
||
1650 |
(autoScroll and:[aBlock notNil]) ifFalse:[ |
|
2265 | 1651 |
^ self stopAutoScroll |
1748 | 1652 |
]. |
1653 |
autoScrollBlock notNil ifTrue:[ |
|
2265 | 1654 |
Processor removeTimedBlock:autoScrollBlock. |
1748 | 1655 |
] ifFalse:[ |
2265 | 1656 |
self compressMotionEvents:false. |
1748 | 1657 |
]. |
1658 |
||
1659 |
timeDelta := 0.5 / (aDistance abs). |
|
1660 |
||
1661 |
autoScrollBlock := [ |
|
2265 | 1662 |
aBlock value. |
1663 |
Processor addTimedBlock:autoScrollBlock afterSeconds:timeDelta. |
|
1748 | 1664 |
]. |
1665 |
Processor addTimedBlock:autoScrollBlock afterSeconds:timeDelta. |
|
1666 |
||
1667 |
! |
|
1668 |
||
1669 |
stopAutoScroll |
|
1670 |
"stop any autoScroll |
|
1671 |
" |
|
1672 |
autoScrollBlock notNil ifTrue:[ |
|
2265 | 1673 |
Processor removeTimedBlock:autoScrollBlock. |
1674 |
autoScrollBlock := nil. |
|
1675 |
self compressMotionEvents:true. |
|
1748 | 1676 |
]. |
1677 |
! ! |
|
1678 |
||
1390 | 1679 |
!ListModelView class methodsFor:'documentation'! |
1680 |
||
1681 |
version |
|
2265 | 1682 |
^ '$Header: /cvs/stx/stx/libwidg2/ListModelView.st,v 1.62 2002-10-10 05:58:47 ca Exp $' |
1390 | 1683 |
! ! |
2244
c9a195d28e72
change #redrawLineAt: to #invalidateLineAt: (because is a invalidate)
ca
parents:
2188
diff
changeset
|
1684 |
|
1390 | 1685 |
ListModelView initialize! |