author | Claus Gittinger <cg@exept.de> |
Mon, 04 Dec 1995 00:49:33 +0100 | |
changeset 227 | 4908ae89a567 |
parent 226 | 29245e0e4414 |
child 234 | 4afddb0d757f |
permissions | -rw-r--r-- |
0 | 1 |
" |
5 | 2 |
COPYRIGHT (c) 1989 by Claus Gittinger |
59 | 3 |
All Rights Reserved |
0 | 4 |
|
5 |
This software is furnished under a license and may be used |
|
6 |
only in accordance with the terms of that license and with the |
|
7 |
inclusion of the above copyright notice. This software may not |
|
8 |
be provided or otherwise made available to, or used by, any |
|
9 |
other person. No title to or ownership of the software is |
|
10 |
hereby transferred. |
|
11 |
" |
|
12 |
||
105 | 13 |
'From Smalltalk/X, Version:2.10.5 on 14-mar-1995 at 10:59:34 am'! |
14 |
||
0 | 15 |
View subclass:#ListView |
120 | 16 |
instanceVariableNames:'list |
17 |
firstLineShown leftOffset |
|
18 |
nFullLinesShown nLinesShown |
|
19 |
fgColor bgColor |
|
20 |
partialLines leftMargin topMargin |
|
21 |
textStartLeft textStartTop innerWidth |
|
22 |
tabPositions |
|
23 |
lineSpacing |
|
24 |
fontHeight fontAscent fontIsFixedWidth fontWidth |
|
190 | 25 |
autoScroll autoScrollBlock autoScrollDeltaT |
120 | 26 |
searchPattern wordCheck |
27 |
includesNonStrings widthOfWidestLine |
|
28 |
listMsg |
|
29 |
viewOrigin |
|
156 | 30 |
menuHolder menuPerformer |
31 |
listChannel' |
|
120 | 32 |
classVariableNames:'DefaultForegroundColor DefaultBackgroundColor |
33 |
DefaultFont DefaultTabPositions' |
|
105 | 34 |
poolDictionaries:'' |
35 |
category:'Views-Text' |
|
0 | 36 |
! |
37 |
||
38 |
!ListView class methodsFor:'documentation'! |
|
39 |
||
38 | 40 |
copyright |
41 |
" |
|
42 |
COPYRIGHT (c) 1989 by Claus Gittinger |
|
59 | 43 |
All Rights Reserved |
38 | 44 |
|
45 |
This software is furnished under a license and may be used |
|
46 |
only in accordance with the terms of that license and with the |
|
47 |
inclusion of the above copyright notice. This software may not |
|
48 |
be provided or otherwise made available to, or used by, any |
|
49 |
other person. No title to or ownership of the software is |
|
50 |
hereby transferred. |
|
51 |
" |
|
52 |
! |
|
53 |
||
54 |
version |
|
227 | 55 |
^ '$Header: /cvs/stx/stx/libwidg/ListView.st,v 1.50 1995-12-03 23:49:33 cg Exp $' |
38 | 56 |
! |
57 |
||
0 | 58 |
documentation |
59 |
" |
|
38 | 60 |
a View for (string-)lists. |
61 |
||
62 |
This class can only passively display collections of strings- |
|
63 |
selections, editing, cursors etc. must be done in subclasses. |
|
64 |
see SelectionInListView, TextView etc. |
|
65 |
||
66 |
This code currently handles only fixed-height fonts correctly - |
|
67 |
should be rewritten in some places ... |
|
0 | 68 |
|
38 | 69 |
It can only scroll by full lines vertically (i.e. setting firstLineShown to ~~ 1) |
70 |
which should be changed to have this behavior optionally for smooth scroll. |
|
71 |
||
120 | 72 |
The text is internally kept in the list instance variable, and is supposed to consist |
73 |
of a collection (Ordered- or StringCollection) of line entries. |
|
74 |
Typically, individual entries are either strings or nil (for empty lines). |
|
75 |
However, any object which supports the displayOn: and widthIn: protocol can be |
|
76 |
used - see MultipleColumnListEntry as an example. |
|
77 |
Therefore, ListView (and all subclasses) are prepared to handle non-string entries |
|
78 |
(especially: attributed Text). |
|
79 |
||
80 |
The internal version of the text has tabulators expanded to blanks - when text is exchanged |
|
81 |
with an external medium (i.e. reading/writing files), these are expanded/compressed assuming |
|
82 |
a tab-setting of 8. This is done independent of the users tab setting, which is used |
|
83 |
while the text is edited. Thus, even if the tab setting is multiple of 4's, tabs are |
|
84 |
written in multiples of 8 when the text is saved. Since this is the default on all ascii |
|
85 |
terminals and printers, this assures that the text looks correctly indented when finally printed. |
|
86 |
||
87 |
Due to historic reasons (ListView implemented scrolling before the general |
|
88 |
scrolling code in View was added), this one does scrolling different from all other |
|
89 |
views. The general scrolling code (in View) uses the transformation for transparent scrolling. |
|
90 |
Here, the transformation is not used, instead it is done again, by keeping the firstLineShown |
|
91 |
(i.e. vertical offset) and leftOffset (horizontal offset). |
|
92 |
The most annoying consequence of this is, that scrolling is done by lines here, |
|
93 |
while its done in pixels in the View class. Thus, be careful, when changing things |
|
94 |
(better: dont touch it ;-) |
|
95 |
||
96 |
This is being totally rewritten ... so dont depend on the internals; especially the scrolling |
|
97 |
code will be totally removed here and the inherited functionality be used in the next version. |
|
38 | 98 |
|
0 | 99 |
|
38 | 100 |
Instance variables: |
0 | 101 |
|
120 | 102 |
list <aCollection> the text strings |
103 |
||
104 |
firstLineShown <Number> the index of the 1st visible line (1 ..) |
|
105 |
leftOffset <Number> left offset for horizontal scroll |
|
106 |
||
107 |
nFullLinesShown <Number> the number of unclipped lines in visible area |
|
108 |
(internal; updated on size changes) |
|
109 |
nLinesShown <Number> the number of lines in visible area, incl. partial |
|
110 |
(internal; updated on size changes) |
|
111 |
||
112 |
fgColor <Color> color to draw characters |
|
113 |
bgColor <Color> the background |
|
114 |
||
115 |
partialLines <Boolean> allow last line to be partial displayed |
|
116 |
leftMargin <Number> margin at left in pixels |
|
117 |
topMargin <Number> margin at top in pixels |
|
118 |
textStartLeft <Number> margin + leftMargin (internal) |
|
119 |
textStartTop <Number> margin + topMargin (internal) |
|
120 |
innerWidth <Number> width - margins (internal) |
|
121 |
tabPositions <aCollection> tab stops (cols) |
|
122 |
fontHeight <Number> font height in pixels (internal) |
|
123 |
fontAscent <Number> font ascent in pixels (internal) |
|
124 |
fontIsFixed <Boolean> true if its a fixed font (internal) |
|
125 |
fontWidth <Number> width of space (internal) |
|
126 |
lineSpacing <Number> pixels between lines |
|
127 |
searchPattern <String> last pattern for searching |
|
128 |
wordCheck <Block> rule used for check for word boundaries in word select |
|
129 |
(could be changed to allow for underscore and other |
|
130 |
characters to be treated as alphaCharacters) |
|
131 |
||
132 |
autoScrollBlock <Block> block installed as timeoutBlock when doing an |
|
133 |
autoScroll (internal) |
|
134 |
autoScrollDeltaT computed scroll time delta in seconds (internal) |
|
135 |
||
136 |
includesNonStrings cached flag if any non-strings are in list |
|
137 |
widthOfWidestLine cached width of widest line |
|
138 |
listMsg if view has a model and listMsg is non-nil, |
|
139 |
this is sent to the model to aquired a new contents |
|
140 |
whenever a change of the aspect (aspectMsg) occurs. |
|
141 |
||
142 |
viewOrigin the current origin |
|
143 |
||
121 | 144 |
menuHolder who has a menu |
145 |
(default: nil or model here, self in textViews) |
|
146 |
menuPerformer who performs menu actions |
|
147 |
(default: nil or model here, self in textViews) |
|
77 | 148 |
|
149 |
StyleSheet parameters: |
|
150 |
||
120 | 151 |
textForegroundColor defaults to Black |
152 |
textBackgroundColor defaults to White |
|
153 |
textFont defaults to defaultFont |
|
154 |
textTabPositions defaults to #(1 9 17 25 ...) |
|
0 | 155 |
" |
156 |
! ! |
|
157 |
||
158 |
!ListView class methodsFor:'defaults'! |
|
159 |
||
105 | 160 |
defaultTabPositions |
161 |
^ self tab8Positions |
|
162 |
! |
|
163 |
||
59 | 164 |
updateStyleCache |
60 | 165 |
DefaultForegroundColor := StyleSheet colorAt:'textForegroundColor' default:Black. |
166 |
DefaultBackgroundColor := StyleSheet colorAt:'textBackgroundColor' default:White. |
|
167 |
DefaultFont := StyleSheet fontAt:'textFont'. |
|
120 | 168 |
DefaultTabPositions := StyleSheet at:'textTabPositions'. |
169 |
DefaultTabPositions isNil ifTrue:[DefaultTabPositions := self defaultTabPositions]. |
|
59 | 170 |
! |
171 |
||
7 | 172 |
tab4Positions |
173 |
^ #(1 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61 65 69 73 77 81 |
|
59 | 174 |
85 89 93 97 101 105 109 113 114 121 125 129 133 137 141 145) |
120 | 175 |
! |
176 |
||
177 |
tab8Positions |
|
178 |
^ #(1 9 17 25 33 41 49 57 65 73 81 89 97 105 113 121 129 137 145) |
|
0 | 179 |
! ! |
180 |
||
105 | 181 |
!ListView methodsFor:'accessing-contents'! |
182 |
||
183 |
size |
|
120 | 184 |
"return the size (i.e. number of lines) |
185 |
this allows textViews to be used like collections in some places." |
|
186 |
||
105 | 187 |
^ list size. |
65 | 188 |
! |
189 |
||
105 | 190 |
at:lineNr |
120 | 191 |
"retrieve a line; return nil if beyond end-of-text. |
192 |
this allows textViews to be used like collections in some places." |
|
105 | 193 |
|
194 |
list isNil ifTrue:[^ nil]. |
|
195 |
(lineNr between:1 and:self size) ifFalse:[^ nil]. |
|
196 |
^ list at:lineNr |
|
59 | 197 |
! |
198 |
||
105 | 199 |
from:from to:to do:aBlock |
120 | 200 |
"evaluate aBlock on all of my lines" |
201 |
||
105 | 202 |
^ list from:from to:to do:aBlock. |
0 | 203 |
! |
204 |
||
105 | 205 |
withoutRedrawAt:index put:aString |
118 | 206 |
"change a line without redisplay" |
207 |
||
208 |
|w| |
|
105 | 209 |
|
210 |
self checkForExistingLine:index. |
|
211 |
list at:index put:aString. |
|
212 |
includesNonStrings ifFalse:[ |
|
213 |
includesNonStrings := (aString notNil and:[aString isString not]). |
|
214 |
] ifTrue:[ |
|
215 |
(aString isNil or:[aString isString]) ifTrue:[ |
|
216 |
includesNonStrings := (list findFirst:[:l | l notNil and:[l isString not]]) ~~ 0. |
|
217 |
] |
|
218 |
]. |
|
118 | 219 |
widthOfWidestLine notNil ifTrue:[ |
220 |
aString isString ifTrue:[ |
|
221 |
w := font widthOf:aString |
|
222 |
] ifFalse:[ |
|
223 |
w := aString widthIn:self |
|
224 |
]. |
|
225 |
w > widthOfWidestLine ifTrue:[ |
|
226 |
widthOfWidestLine := w |
|
227 |
] ifFalse:[ |
|
228 |
widthOfWidestLine := nil "/ means: unknown |
|
229 |
]. |
|
230 |
] |
|
105 | 231 |
! |
232 |
||
233 |
at:index put:aString |
|
234 |
"change a line and redisplay" |
|
235 |
||
236 |
self withoutRedrawAt:index put:aString. |
|
237 |
shown ifTrue:[ |
|
238 |
self redrawLine:index |
|
239 |
] |
|
240 |
! |
|
241 |
||
242 |
list |
|
243 |
"return the contents as a collection of strings" |
|
244 |
||
245 |
^ list |
|
246 |
! |
|
247 |
||
248 |
setContents:something |
|
249 |
"set the contents (either a string or a Collection of strings) |
|
51 | 250 |
dont change position (i.e. do not scroll). |
251 |
This can be used to update a self-changing list |
|
131 | 252 |
(for example: a file list being shown, without disturbing user too much). |
253 |
Compare with #contents:, which scrolls to top." |
|
105 | 254 |
|
255 |
|l oldSize| |
|
256 |
||
257 |
oldSize := self size. |
|
258 |
l := something. |
|
259 |
l notNil ifTrue:[ |
|
260 |
l isString ifTrue:[ |
|
261 |
l := l asStringCollection |
|
262 |
] |
|
263 |
]. |
|
264 |
self setList:l. |
|
265 |
self size ~~ oldSize ifTrue:[ |
|
266 |
self contentsChanged |
|
267 |
] |
|
268 |
! |
|
269 |
||
270 |
contents:something |
|
271 |
"set the contents (either a string or a Collection of strings) |
|
131 | 272 |
also scroll to top. Compare with #setContents:, which does not scroll." |
105 | 273 |
|
274 |
|l| |
|
275 |
||
276 |
l := something. |
|
277 |
l notNil ifTrue:[ |
|
278 |
l isString ifTrue:[ |
|
279 |
l := l asStringCollection |
|
280 |
] |
|
281 |
]. |
|
282 |
self list:l |
|
51 | 283 |
! |
284 |
||
0 | 285 |
list:aCollection |
128 | 286 |
"set the contents (a collection of strings or list entries) |
287 |
and scroll to top-left" |
|
288 |
||
289 |
self list:aCollection expandTabs:true |
|
290 |
! |
|
291 |
||
292 |
list:aCollection expandTabs:expand |
|
38 | 293 |
"set the contents (a collection of strings) and scroll to top-left" |
0 | 294 |
|
38 | 295 |
|oldFirst oldLeft| |
0 | 296 |
|
297 |
(aCollection isNil and:[list isNil]) ifTrue:[ |
|
59 | 298 |
"no change" |
299 |
self scrollToTop. |
|
300 |
self scrollToLeft. |
|
301 |
^ self |
|
0 | 302 |
]. |
303 |
list := aCollection. |
|
304 |
||
152 | 305 |
list notNil ifTrue:[ |
306 |
expand ifTrue:[ |
|
128 | 307 |
self expandTabs |
152 | 308 |
] ifFalse:[ |
153 | 309 |
includesNonStrings := true. "/ actually: do not know |
128 | 310 |
] |
0 | 311 |
]. |
152 | 312 |
|
125 | 313 |
widthOfWidestLine := nil. "/ i.e. unknown |
0 | 314 |
oldFirst := firstLineShown. |
38 | 315 |
oldLeft := leftOffset. |
0 | 316 |
firstLineShown := 1. |
38 | 317 |
leftOffset := 0. |
318 |
realized ifTrue:[ |
|
59 | 319 |
self contentsChanged. |
320 |
" |
|
321 |
dont use scroll here to avoid the redraw |
|
322 |
" |
|
77 | 323 |
oldFirst ~~ firstLineShown ifTrue:[ |
324 |
self originChanged:(oldFirst - 1) negated. |
|
325 |
]. |
|
59 | 326 |
shown ifTrue:[ |
327 |
self redrawFromVisibleLine:1 to:nLinesShown |
|
328 |
] |
|
0 | 329 |
] |
153 | 330 |
|
331 |
"Modified: 30.8.1995 / 19:07:13 / claus" |
|
0 | 332 |
! |
333 |
||
105 | 334 |
setList:aCollection |
335 |
"set the contents (a collection of strings); |
|
153 | 336 |
do not change position (i.e. do not scroll). |
38 | 337 |
This can be used to update a self-changing list |
105 | 338 |
(for example: a file list being shown, without disturbing user too much)" |
339 |
||
340 |
^ self setList:aCollection expandTabs:true |
|
0 | 341 |
! |
342 |
||
153 | 343 |
setList:aCollection expandTabs:expandTabs |
344 |
"set the contents (a collection of strings); |
|
345 |
do not change position (i.e. do not scroll). |
|
346 |
This can be used to update a self-changing list |
|
347 |
(for example: a file list being shown, without disturbing the user too much)" |
|
348 |
||
349 |
|oldFirst| |
|
350 |
||
351 |
(aCollection isNil and:[list isNil]) ifTrue:[ |
|
352 |
"no change" |
|
353 |
^ self |
|
354 |
]. |
|
355 |
list := aCollection. |
|
356 |
||
357 |
list notNil ifTrue:[ |
|
358 |
expandTabs ifTrue:[ |
|
359 |
self expandTabs |
|
360 |
] ifFalse:[ |
|
361 |
includesNonStrings := true. "/ actually: do not know |
|
362 |
] |
|
363 |
]. |
|
364 |
self contentsChanged. |
|
365 |
||
366 |
"/ new - reposition if too big |
|
367 |
(firstLineShown + nFullLinesShown) > self size ifTrue:[ |
|
368 |
oldFirst := firstLineShown. |
|
369 |
firstLineShown := self size - nFullLinesShown + 1. |
|
370 |
firstLineShown < 1 ifTrue:[firstLineShown := 1]. |
|
371 |
self originChanged:(oldFirst - 1) negated. |
|
372 |
shown ifTrue:[ |
|
373 |
self clear. |
|
374 |
] |
|
375 |
]. |
|
376 |
"/ end new |
|
377 |
shown ifTrue:[ |
|
378 |
self redrawFromVisibleLine:1 to:nLinesShown |
|
379 |
] |
|
380 |
||
381 |
! |
|
382 |
||
0 | 383 |
contents |
384 |
"return the contents as a string" |
|
385 |
||
386 |
list isNil ifTrue:[^ '']. |
|
148 | 387 |
^ list asStringCollection asString |
0 | 388 |
! |
389 |
||
390 |
removeIndexWithoutRedraw:lineNr |
|
63 | 391 |
"delete a line, given its lineNr - no redraw; |
392 |
return true, if something was really deleted (so sender knows, |
|
393 |
if a redraw is needed)" |
|
0 | 394 |
|
105 | 395 |
(list isNil or:[lineNr > self size]) ifTrue:[^ false]. |
0 | 396 |
list removeIndex:lineNr. |
38 | 397 |
|
7 | 398 |
lineNr < firstLineShown ifTrue:[ |
59 | 399 |
firstLineShown := firstLineShown - 1 |
0 | 400 |
]. |
401 |
self contentsChanged. |
|
402 |
^ true |
|
403 |
! |
|
404 |
||
405 |
removeIndex:lineNr |
|
63 | 406 |
"delete line, update view" |
0 | 407 |
|
408 |
|visLine w |
|
409 |
srcY "{ Class: SmallInteger }" | |
|
410 |
||
411 |
(self removeIndexWithoutRedraw:lineNr) ifFalse:[^ self]. |
|
38 | 412 |
" |
413 |
is there a need to redraw ? |
|
414 |
" |
|
77 | 415 |
shown ifFalse:[^ self]. |
0 | 416 |
visLine := self listLineToVisibleLine:lineNr. |
417 |
visLine notNil ifTrue:[ |
|
59 | 418 |
w := self widthForScrollBetween:lineNr and:(firstLineShown + nLinesShown). |
419 |
srcY := topMargin + (visLine * fontHeight). |
|
420 |
self catchExpose. |
|
421 |
self copyFrom:self x:textStartLeft y:srcY |
|
422 |
toX:textStartLeft y:(srcY - fontHeight) |
|
423 |
width:w height:((nLinesShown - visLine) * fontHeight). |
|
424 |
self redrawVisibleLine:nFullLinesShown. |
|
63 | 425 |
" |
426 |
redraw last partial line - if any |
|
427 |
" |
|
59 | 428 |
(nFullLinesShown ~~ nLinesShown) ifTrue:[ |
429 |
self redrawVisibleLine:nLinesShown |
|
430 |
]. |
|
431 |
self waitForExpose |
|
0 | 432 |
] |
433 |
! |
|
434 |
||
105 | 435 |
add:aString beforeIndex:index |
436 |
"add a line and redisplay" |
|
437 |
||
438 |
list add:aString beforeIndex:index. |
|
439 |
includesNonStrings ifFalse:[ |
|
440 |
includesNonStrings := (aString notNil and:[aString isString not]). |
|
441 |
]. |
|
442 |
shown ifTrue:[ |
|
443 |
self redrawFromLine:index. |
|
444 |
self contentsChanged. "recompute scrollbars" |
|
445 |
] |
|
446 |
||
447 |
! |
|
448 |
||
449 |
grow:n |
|
450 |
"grow our list" |
|
120 | 451 |
|
105 | 452 |
^ list grow:n. |
453 |
! |
|
454 |
||
455 |
add:aString |
|
456 |
"add a line and redisplay" |
|
457 |
||
458 |
list add:aString. |
|
459 |
includesNonStrings ifFalse:[ |
|
460 |
includesNonStrings := (aString notNil and:[aString isString not]). |
|
0 | 461 |
]. |
105 | 462 |
shown ifTrue:[ |
463 |
self redrawLine:(self size). |
|
464 |
self contentsChanged. "recompute scrollbars" |
|
465 |
] |
|
466 |
||
467 |
! ! |
|
468 |
||
118 | 469 |
!ListView methodsFor:'accessing-mvc'! |
470 |
||
471 |
on:aModel aspect:aspectSymbol |
|
472 |
"ST-80 compatibility" |
|
473 |
||
474 |
^ self on:aModel aspect:aspectSymbol change:nil list:aspectSymbol menu:nil |
|
475 |
! |
|
476 |
||
125 | 477 |
on:aModel aspect:aspectSymbol change:changeSymbol |
118 | 478 |
"ST-80 compatibility" |
479 |
||
125 | 480 |
^self on:aModel aspect:aspectSymbol change:changeSymbol list:aspectSymbol menu:nil |
118 | 481 |
! |
482 |
||
483 |
on:aModel aspect:aspectSymbol menu:menuSymbol |
|
484 |
"ST-80 compatibility" |
|
485 |
||
486 |
^self on:aModel aspect:aspectSymbol change:nil list:aspectSymbol menu:menuSymbol |
|
487 |
! |
|
488 |
||
125 | 489 |
on:aModel aspect:aspectSymbol list:listSymbol menu:menuSymbol |
118 | 490 |
"ST-80 compatibility" |
491 |
||
125 | 492 |
^ self on:aModel aspect:aspectSymbol change:nil list:listSymbol menu:menuSymbol |
118 | 493 |
! |
494 |
||
495 |
on:aModel aspect:aspectSymbol change:changeSymbol menu:menuSymbol |
|
496 |
"ST-80 compatibility" |
|
497 |
||
498 |
^ self on:aModel aspect:aspectSymbol change:changeSymbol list:nil menu:menuSymbol |
|
499 |
! |
|
500 |
||
501 |
on:aModel aspect:aspectSymbol change:changeSymbol list:listSymbol menu:menuSymbol |
|
502 |
"ST-80 compatibility" |
|
503 |
||
504 |
aspectSymbol notNil ifTrue:[aspectMsg := aspectSymbol. listMsg := aspectSymbol]. |
|
505 |
listSymbol notNil ifTrue:[listMsg := listSymbol]. |
|
506 |
changeSymbol notNil ifTrue:[changeMsg := changeSymbol]. |
|
507 |
menuMsg := menuSymbol. |
|
508 |
self model:aModel. |
|
509 |
! |
|
510 |
||
125 | 511 |
listMessage |
512 |
"return the listMsg selector; |
|
513 |
if non-nil, this is the message sent to the model (if any) to aquire |
|
514 |
a new text upon change of the aspect. |
|
120 | 515 |
This defaults to the aspect-selector." |
118 | 516 |
|
125 | 517 |
^ listMsg |
518 |
! |
|
519 |
||
520 |
listMessage:aSymbol |
|
521 |
"ST-80 compatibility: set the listMsg selector; |
|
522 |
if non-nil, this will be sent to the model (if any) to aquire a |
|
523 |
new text upon change of the aspect. |
|
524 |
This defaults to the aspect-selector." |
|
525 |
||
526 |
listMsg := aSymbol. |
|
120 | 527 |
! |
528 |
||
529 |
menuHolder |
|
121 | 530 |
"who has the menu - this defaults to model or nil here, |
531 |
but self in textView & friends. |
|
532 |
Can be changed with #menuHolder:" |
|
533 |
||
534 |
menuHolder notNil ifTrue:[ |
|
535 |
^ menuHolder |
|
536 |
]. |
|
537 |
^ super menuHolder |
|
120 | 538 |
! |
539 |
||
540 |
menuHolder:anObject |
|
121 | 541 |
"change the one that provides the menu (via menuMsg)." |
120 | 542 |
|
543 |
menuHolder := anObject |
|
544 |
! |
|
545 |
||
546 |
menuPerformer |
|
121 | 547 |
"who does menu actions - this defaults to model or nil here, |
548 |
but self in textView & friends. |
|
549 |
Can be changed with #menuPerformer:" |
|
550 |
||
551 |
menuPerformer notNil ifTrue:[ |
|
552 |
^ menuPerformer |
|
553 |
]. |
|
554 |
^ super menuPerformer |
|
555 |
||
120 | 556 |
! |
557 |
||
558 |
menuPerformer:anObject |
|
121 | 559 |
"change the one that does the menu actions." |
120 | 560 |
|
561 |
menuPerformer := anObject |
|
125 | 562 |
! |
563 |
||
564 |
addModelInterfaceTo:aDictionary |
|
565 |
"see comment in View>>modelInterface" |
|
566 |
||
567 |
super addModelInterfaceTo:aDictionary. |
|
568 |
aDictionary at:#listMessage put:listMsg |
|
118 | 569 |
! ! |
570 |
||
105 | 571 |
!ListView methodsFor:'private'! |
572 |
||
118 | 573 |
getListFromModel |
120 | 574 |
"ask my model (if any) for the text via the listMsg." |
575 |
||
118 | 576 |
|text| |
577 |
||
120 | 578 |
(model notNil |
579 |
and:[listMsg notNil]) ifTrue:[ |
|
118 | 580 |
text := model perform:listMsg. |
581 |
text notNil ifTrue:[ |
|
582 |
text := text asStringCollection. |
|
583 |
]. |
|
584 |
self list:text |
|
585 |
]. |
|
586 |
! |
|
587 |
||
105 | 588 |
visibleLineToListLine:visibleLineNr |
589 |
"given a visible line (1..) return linenr in list or nil |
|
590 |
(this one returns nil if the given visibleLineNr is one of the |
|
591 |
separators)" |
|
592 |
||
593 |
|listLineNr "{ Class: SmallInteger }" |
|
594 |
listsize "{ Class: SmallInteger }" | |
|
595 |
||
596 |
visibleLineNr isNil ifTrue:[^ nil]. |
|
597 |
listLineNr := visibleLineNr + firstLineShown - 1. |
|
598 |
(listLineNr == 0) ifTrue:[^nil]. |
|
599 |
listsize := self size. |
|
600 |
(listLineNr <= listsize) ifTrue:[^ listLineNr]. |
|
601 |
^ nil |
|
602 |
! |
|
603 |
||
604 |
visibleAt:visibleLineNr |
|
156 | 605 |
"return what is visible at line (numbers start at 1). |
606 |
This is used for redrawing; i.e. for non-string entries, this |
|
607 |
returns the original." |
|
105 | 608 |
|
609 |
|listLineNr listsize| |
|
610 |
||
611 |
listLineNr := visibleLineNr + firstLineShown - 1. |
|
612 |
(listLineNr == 0) ifTrue:[^ nil]. |
|
613 |
(list notNil) ifTrue:[ |
|
614 |
listsize := self size |
|
615 |
] ifFalse:[ |
|
616 |
listsize := 0 |
|
617 |
]. |
|
618 |
(listLineNr <= listsize) ifTrue:[^ self at:listLineNr]. |
|
619 |
^ '' |
|
620 |
! |
|
621 |
||
622 |
listAt:lineNr |
|
156 | 623 |
"given a lineNumber, return the corresponding string |
624 |
This is used for accessing; i.e. for non-string entries, this |
|
625 |
returns the corresponding string." |
|
626 |
||
627 |
|l| |
|
105 | 628 |
|
629 |
list isNil ifTrue:[^ nil]. |
|
630 |
(lineNr between:1 and:self size) ifFalse:[^ nil]. |
|
156 | 631 |
l := self at:lineNr. |
632 |
l isNil ifTrue:[^ l]. |
|
633 |
^ l asString |
|
634 |
||
635 |
"Modified: 7.9.1995 / 15:54:59 / claus" |
|
105 | 636 |
! |
637 |
||
638 |
yOfVisibleLine:visLineNr |
|
639 |
"given a visible lineNr, return y-coordinate in view |
|
640 |
- works for fix-height fonts only" |
|
641 |
||
642 |
^ ((visLineNr - 1) * fontHeight) + textStartTop |
|
643 |
! |
|
644 |
||
645 |
computeNumberOfLinesShown |
|
646 |
"recompute the number of visible lines" |
|
647 |
||
224 | 648 |
nFullLinesShown := self innerHeight + lineSpacing // fontHeight. |
105 | 649 |
nLinesShown := nFullLinesShown. |
650 |
||
651 |
partialLines ifTrue:[ |
|
652 |
((nLinesShown * fontHeight) == height) ifFalse:[ |
|
653 |
nLinesShown := nLinesShown + 1 |
|
654 |
] |
|
655 |
] |
|
656 |
! |
|
657 |
||
658 |
visibleLineOfY:y |
|
659 |
"given a y-coordinate, return lineNr |
|
660 |
- works for fix-height fonts only" |
|
661 |
||
662 |
^ ((y - textStartTop) // fontHeight) + 1 |
|
663 |
! |
|
664 |
||
665 |
checkForExistingLine:lineNr |
|
666 |
"check if a line for lineNr exists; if not, expand text" |
|
667 |
||
668 |
list isNil ifTrue: [ |
|
669 |
list := StringCollection new:lineNr. |
|
670 |
self contentsChanged |
|
671 |
] ifFalse: [ |
|
672 |
lineNr > (list size) ifTrue:[ |
|
673 |
self grow:lineNr. |
|
59 | 674 |
self contentsChanged |
675 |
] |
|
38 | 676 |
] |
0 | 677 |
! |
678 |
||
105 | 679 |
xOfCol:col inVisibleLine:visLineNr |
680 |
"given a visible line- and colNr, return x-coordinate in view" |
|
681 |
||
682 |
|line lineSize tcol| |
|
683 |
||
684 |
tcol := col - 1. |
|
685 |
fontIsFixedWidth ifTrue:[ |
|
686 |
^ (tcol * fontWidth) + textStartLeft |
|
687 |
]. |
|
688 |
line := self visibleAt:visLineNr. |
|
689 |
line notNil ifTrue:[ |
|
690 |
lineSize := line size |
|
691 |
] ifFalse:[ |
|
692 |
lineSize := 0 |
|
693 |
]. |
|
694 |
(lineSize == 0) ifTrue:[ |
|
695 |
^ (tcol * fontWidth) + textStartLeft |
|
696 |
]. |
|
697 |
(lineSize < col) ifTrue:[ |
|
698 |
^ (font widthOf:line) |
|
699 |
+ (fontWidth * (tcol - lineSize)) |
|
700 |
+ textStartLeft |
|
701 |
]. |
|
702 |
^ (font widthOf:line from:1 to:tcol) + textStartLeft |
|
0 | 703 |
! |
704 |
||
105 | 705 |
listLineToVisibleLine:listLineNr |
706 |
"given a list line (1..) return visible linenr or nil" |
|
707 |
||
708 |
|visibleLineNr "{ Class: SmallInteger }"| |
|
709 |
||
710 |
shown ifFalse:[^ nil]. |
|
711 |
listLineNr isNil ifTrue:[^ nil]. |
|
712 |
visibleLineNr := listLineNr + 1 - firstLineShown. |
|
713 |
(visibleLineNr between:1 and:nLinesShown) ifFalse:[^ nil]. |
|
714 |
^ visibleLineNr |
|
0 | 715 |
! |
716 |
||
105 | 717 |
visibleLineToAbsoluteLine:visibleLineNr |
718 |
"given a visible line (1..) return absolut linenr" |
|
719 |
||
720 |
visibleLineNr isNil ifTrue:[^ nil]. |
|
721 |
^ visibleLineNr + firstLineShown - 1 |
|
0 | 722 |
! |
723 |
||
105 | 724 |
widthForScrollBetween:firstLine and:lastLine |
725 |
"return the width in pixels for a scroll between firstLine and lastLine. |
|
726 |
- used to optimize scrolling, by limiting the scrolled area. |
|
727 |
Subclasses with selections or other additional visible stuff should redefine |
|
728 |
this method." |
|
729 |
||
730 |
|w| |
|
731 |
||
732 |
"for small width, its not worth searching for |
|
733 |
longest line ... |
|
38 | 734 |
" |
105 | 735 |
(width < 300) ifTrue:[^ innerWidth]. |
736 |
||
737 |
"for large lists, search may take longer than scrolling full |
|
738 |
" |
|
739 |
self size > 2000 ifTrue:[^ innerWidth]. |
|
740 |
||
741 |
" |
|
742 |
if there is a pattern-background, we have to scroll everything |
|
38 | 743 |
" |
105 | 744 |
(viewBackground isColor not |
745 |
or:[viewBackground colorId notNil]) ifTrue:[ |
|
746 |
^ width |
|
747 |
]. |
|
748 |
||
749 |
w := self widthOfWidestLineBetween:firstLine and:lastLine. |
|
750 |
(w > innerWidth) ifTrue:[^ innerWidth]. |
|
751 |
^ w |
|
0 | 752 |
! |
753 |
||
754 |
getFontParameters |
|
755 |
"get some info of the used font. They are cached since we use them often .." |
|
756 |
||
757 |
font := font on:device. |
|
758 |
fontHeight := font height + lineSpacing. |
|
759 |
fontAscent := font ascent. |
|
760 |
fontWidth := font width. |
|
761 |
fontIsFixedWidth := font isFixedWidth. |
|
762 |
! |
|
763 |
||
105 | 764 |
absoluteLineToVisibleLine:absLineNr |
765 |
"given an absolute line (1..) return visible linenr or nil" |
|
766 |
||
767 |
absLineNr isNil ifTrue:[^ nil]. |
|
768 |
(absLineNr < firstLineShown) ifTrue:[^ nil]. |
|
769 |
(absLineNr >= (firstLineShown + nLinesShown)) ifTrue:[^ nil]. |
|
770 |
^ absLineNr - firstLineShown + 1 |
|
771 |
! |
|
772 |
||
773 |
colOfX:x inVisibleLine:visLineNr |
|
774 |
"given a visible lineNr and x-coordinate, return colNr" |
|
775 |
||
776 |
|lineString linePixelWidth xRel runCol posLeft posRight done| |
|
777 |
||
778 |
xRel := x - textStartLeft + leftOffset. |
|
120 | 779 |
" |
780 |
for fix fonts, this is easy ... |
|
781 |
" |
|
105 | 782 |
fontIsFixedWidth ifTrue:[ |
783 |
^ (xRel // fontWidth) + 1 |
|
784 |
]. |
|
120 | 785 |
|
786 |
" |
|
787 |
for variable fonts, more work is required ... |
|
788 |
" |
|
134 | 789 |
lineString := (self visibleAt:visLineNr) asString. |
105 | 790 |
lineString notNil ifTrue:[ |
791 |
linePixelWidth := font widthOf:lineString |
|
792 |
] ifFalse:[ |
|
793 |
linePixelWidth := 0 |
|
794 |
]. |
|
795 |
(xRel <= 0) ifTrue:[^ 1]. |
|
796 |
(linePixelWidth <= xRel) ifTrue:[ |
|
797 |
fontWidth == 0 ifTrue:[ |
|
798 |
" |
|
799 |
although this 'cannot happen', |
|
800 |
it seems that X reports this width for some strange fonts ... |
|
801 |
" |
|
802 |
^ lineString size |
|
803 |
]. |
|
804 |
^ lineString size + ((xRel - linePixelWidth) // fontWidth) + 1 |
|
805 |
]. |
|
806 |
runCol := lineString size // 2. |
|
807 |
(runCol == 0) ifTrue:[runCol := 1]. |
|
808 |
posLeft := font widthOf:lineString from:1 to:(runCol - 1). |
|
809 |
posRight := font widthOf:lineString from:1 to:runCol. |
|
810 |
done := (posLeft <= xRel) and:[posRight > xRel]. |
|
811 |
[done] whileFalse:[ |
|
812 |
(posRight <= xRel) ifTrue:[ |
|
813 |
runCol := runCol + 1. |
|
814 |
posLeft := posRight. |
|
815 |
posRight := font widthOf:lineString from:1 to:runCol |
|
816 |
] ifFalse:[ |
|
817 |
(posLeft > xRel) ifTrue:[ |
|
818 |
runCol := runCol - 1. |
|
819 |
(runCol == 0) ifTrue:[^ 0]. |
|
820 |
posRight := posLeft. |
|
821 |
posLeft := font widthOf:lineString from:1 to:(runCol - 1) |
|
822 |
] |
|
823 |
]. |
|
824 |
done := (posLeft <= xRel) and:[posRight > xRel] |
|
825 |
]. |
|
826 |
^ runCol |
|
0 | 827 |
! |
828 |
||
829 |
convertRTF:aList |
|
830 |
"this is a q&d RTF to poor-text converter which removes any rich stuff. |
|
831 |
- a first shot 'til DocumentView is finished ..." |
|
832 |
||
833 |
|newList newLine charIndex inEscape char special| |
|
834 |
||
81 | 835 |
newList := StringCollection new:200. |
0 | 836 |
newList grow:0. |
837 |
||
838 |
newLine := ''. |
|
839 |
aList do:[:line | |
|
59 | 840 |
((line size == 0) or:[line isBlank]) ifTrue:[ |
841 |
newList add:newLine. |
|
842 |
newLine := '' |
|
843 |
] ifFalse:[ |
|
844 |
special := ((line at:1) == ${) or:[(line includes:$\)]. |
|
845 |
special := special or:[(line at:1) == $}]. |
|
846 |
special ifFalse:[ |
|
847 |
newList add:(newLine , line) |
|
848 |
] ifTrue:[ |
|
849 |
charIndex := 1. |
|
850 |
[charIndex <= line size] whileTrue:[ |
|
851 |
char := line at:charIndex. |
|
852 |
((char == ${ ) or:[char == $} ]) ifTrue:[ |
|
853 |
"left-brace: ignore rest of line" |
|
854 |
charIndex := line size + 1 |
|
855 |
] ifFalse:[ |
|
856 |
(char == $\) ifTrue:[ |
|
857 |
inEscape := true |
|
858 |
] ifFalse:[ |
|
859 |
inEscape ifTrue:[ |
|
860 |
(char == Character space) ifTrue:[ |
|
861 |
inEscape := false |
|
862 |
] |
|
863 |
] ifFalse:[ |
|
864 |
newLine := newLine copyWith:char |
|
865 |
] |
|
866 |
]. |
|
867 |
charIndex := charIndex + 1 |
|
868 |
] |
|
869 |
] |
|
870 |
] |
|
871 |
] |
|
0 | 872 |
]. |
873 |
^ newList |
|
874 |
! |
|
875 |
||
105 | 876 |
listAt:lineNr from:startCol to:endCol |
877 |
"return substring from startCol to endCol of a line" |
|
878 |
||
879 |
|line stop lineLen| |
|
880 |
||
881 |
line := self listAt:lineNr. |
|
882 |
line isNil ifTrue:[^ nil]. |
|
883 |
lineLen := line size. |
|
884 |
(startCol > lineLen) ifTrue:[^ nil]. |
|
885 |
stop := endCol. |
|
886 |
(stop > lineLen) ifTrue:[stop := lineLen]. |
|
887 |
^ line copyFrom:startCol to:stop |
|
0 | 888 |
! |
889 |
||
118 | 890 |
widthOfLineString:entry |
891 |
"return the width of an entry" |
|
892 |
||
893 |
entry isNil ifTrue:[^ 0]. |
|
894 |
entry isString ifTrue:[ |
|
895 |
^ font widthOf:entry |
|
896 |
]. |
|
897 |
^ entry widthIn:self |
|
898 |
! |
|
899 |
||
0 | 900 |
widthOfWidestLineBetween:firstLine and:lastLine |
38 | 901 |
"return the width in pixels of the widest line in a range |
902 |
- used to optimize scrolling, by limiting the scrolled area" |
|
0 | 903 |
|
904 |
|max "{ Class: SmallInteger }" |
|
905 |
first "{ Class: SmallInteger }" |
|
906 |
last "{ Class: SmallInteger }" |
|
907 |
thisLen "{ Class: SmallInteger }" |
|
908 |
listSize "{ Class: SmallInteger }" | |
|
909 |
||
51 | 910 |
includesNonStrings ifTrue:[ |
59 | 911 |
^ width |
51 | 912 |
]. |
913 |
||
0 | 914 |
fontIsFixedWidth ifTrue:[ |
59 | 915 |
^ (self lengthOfLongestLineBetween:firstLine and:lastLine) * fontWidth |
0 | 916 |
]. |
105 | 917 |
listSize := self size. |
0 | 918 |
max := 0. |
919 |
first := firstLine. |
|
920 |
last := lastLine. |
|
921 |
||
922 |
(first > listSize) ifTrue:[^ max]. |
|
923 |
(last > listSize) ifTrue:[ |
|
59 | 924 |
last := listSize |
0 | 925 |
]. |
926 |
||
105 | 927 |
self from:first to:last do:[:line | |
59 | 928 |
line notNil ifTrue:[ |
929 |
thisLen := font widthOf:line. |
|
930 |
(thisLen > max) ifTrue:[ |
|
931 |
max := thisLen |
|
932 |
] |
|
933 |
] |
|
0 | 934 |
]. |
935 |
^ max |
|
936 |
! |
|
937 |
||
938 |
listAt:lineNr from:startCol |
|
3 | 939 |
"return right substring from startCol to end of a line" |
0 | 940 |
|
941 |
|line| |
|
942 |
||
943 |
line := self listAt:lineNr. |
|
944 |
line isNil ifTrue:[^ nil]. |
|
945 |
(startCol > line size) ifTrue:[^ nil]. |
|
38 | 946 |
^ line copyFrom:startCol |
0 | 947 |
! |
948 |
||
949 |
lineOfCharacterPosition:charPos |
|
950 |
"given a character index within the contents-string, |
|
951 |
return the lineNumber where the character is |
|
952 |
- used to find line to hilight from Compilers error-position" |
|
953 |
||
954 |
|lineNr sum lastLine| |
|
955 |
||
956 |
lineNr := 1. |
|
957 |
sum := 0. |
|
105 | 958 |
lastLine := self size. |
0 | 959 |
[sum < charPos] whileTrue:[ |
59 | 960 |
(lineNr > lastLine) ifTrue:[^ lineNr - 1]. |
105 | 961 |
sum := sum + (self at:lineNr) size + 1. |
59 | 962 |
lineNr := lineNr + 1 |
0 | 963 |
]. |
964 |
^ lineNr - 1 |
|
965 |
! |
|
966 |
||
967 |
characterPositionOfLine:lineNr col:col |
|
968 |
"given a line/col position, return the character index within the contents-string, |
|
969 |
- used with Compilers error-positioning" |
|
970 |
||
971 |
|lineString pos| |
|
972 |
||
70 | 973 |
self checkForExistingLine:lineNr. |
0 | 974 |
pos := 1. |
975 |
1 to:(lineNr - 1) do:[:lnr | |
|
105 | 976 |
lineString := self at:lnr. |
59 | 977 |
lineString notNil ifTrue:[ |
978 |
pos := pos + lineString size |
|
979 |
]. |
|
980 |
pos := pos + 1 "the return-character" |
|
0 | 981 |
]. |
982 |
^ pos + col - 1 |
|
105 | 983 |
|
984 |
! |
|
985 |
||
986 |
listAt:lineNr to:endCol |
|
987 |
"return left substring from start to endCol of a line" |
|
988 |
||
989 |
|line stop| |
|
990 |
||
991 |
line := self listAt:lineNr. |
|
992 |
line isNil ifTrue:[^ nil]. |
|
993 |
stop := endCol. |
|
994 |
(stop > line size) ifTrue:[stop := line size]. |
|
995 |
^ line copyTo:stop |
|
0 | 996 |
! ! |
997 |
||
105 | 998 |
!ListView methodsFor:'drawing'! |
999 |
||
1000 |
drawFromVisibleLine:startVisLineNr to:endVisLineNr with:fg and:bg |
|
1001 |
"draw a visible line range in fg/bg" |
|
1002 |
||
1003 |
|y "{ Class: SmallInteger }" |
|
1004 |
x "{ Class: SmallInteger }" |
|
1005 |
startLine "{ Class: SmallInteger }" |
|
1006 |
endLine "{ Class: SmallInteger }" |
|
1007 |
listSize e| |
|
1008 |
||
1009 |
y := self yOfVisibleLine:startVisLineNr. |
|
1010 |
self paint:bg. |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1011 |
self fillRectangleX:margin y:y-(lineSpacing//2) |
105 | 1012 |
width:(width - (margin * 2)) |
1013 |
height:(endVisLineNr - startVisLineNr + 1) * fontHeight. |
|
1014 |
list isNil ifTrue:[^ self]. |
|
1015 |
||
1016 |
y := y + fontAscent. |
|
1017 |
listSize := self size. |
|
1018 |
||
1019 |
startLine := startVisLineNr + firstLineShown - 1. |
|
1020 |
endLine := endVisLineNr + firstLineShown - 1. |
|
1021 |
(startLine == 0) ifTrue:[ |
|
1022 |
y := y + fontHeight. |
|
1023 |
startLine := startLine + 1 |
|
1024 |
]. |
|
1025 |
||
1026 |
(endLine > listSize) ifTrue:[ |
|
1027 |
e := listSize |
|
1028 |
] ifFalse:[ |
|
1029 |
e := endLine |
|
1030 |
]. |
|
1031 |
||
1032 |
(startLine <= e) ifTrue:[ |
|
1033 |
x := textStartLeft - leftOffset. |
|
1034 |
self paint:fg. |
|
1035 |
self from:startLine to:e do:[:line | |
|
1036 |
line notNil ifTrue:[ |
|
1037 |
self displayString:line x:x y:y |
|
1038 |
]. |
|
1039 |
y := y + fontHeight |
|
1040 |
] |
|
1041 |
] |
|
1042 |
||
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1043 |
"Modified: 22.11.1995 / 23:42:37 / cg" |
7 | 1044 |
! |
1045 |
||
131 | 1046 |
drawLine:line atX:x inVisible:visLineNr with:fg and:bg |
1047 |
"draw a given string at visible lines position with |
|
1048 |
given x position in fg/bg. |
|
1049 |
Low level entry; not meant for public use." |
|
1050 |
||
1051 |
|y| |
|
105 | 1052 |
|
1053 |
y := self yOfVisibleLine:visLineNr. |
|
1054 |
self paint:bg. |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1055 |
self fillRectangleX:margin y:y - (lineSpacing//2) |
105 | 1056 |
width:(width - (margin * 2)) |
1057 |
height:fontHeight. |
|
1058 |
line notNil ifTrue:[ |
|
1059 |
self paint:fg. |
|
131 | 1060 |
self displayString:line x:x y:(y + fontAscent) |
105 | 1061 |
] |
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1062 |
|
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1063 |
"Modified: 22.11.1995 / 23:42:45 / cg" |
105 | 1064 |
! |
1065 |
||
131 | 1066 |
drawLine:line inVisible:visLineNr with:fg and:bg |
1067 |
"draw a given string at visible lines position in fg/bg" |
|
1068 |
||
1069 |
self drawLine:line atX:(textStartLeft - leftOffset) inVisible:visLineNr with:fg and:bg |
|
1070 |
! |
|
1071 |
||
1072 |
drawVisibleLine:visLineNr with:fg and:bg |
|
1073 |
"draw a visible line in fg/bg" |
|
1074 |
||
1075 |
self drawLine:(self visibleAt:visLineNr) atX:(textStartLeft - leftOffset) inVisible:visLineNr with:fg and:bg |
|
1076 |
! |
|
1077 |
||
105 | 1078 |
drawVisibleLine:visLineNr col:col with:fg and:bg |
1079 |
"draw single character at col index of visible line in fg/bg" |
|
1080 |
||
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1081 |
|y yf x lineString characterString| |
105 | 1082 |
|
1083 |
lineString := self visibleAt:visLineNr. |
|
1084 |
x := (self xOfCol:col inVisibleLine:visLineNr) - leftOffset. |
|
1085 |
y := self yOfVisibleLine:visLineNr. |
|
1086 |
||
1087 |
self paint:bg. |
|
1088 |
||
1089 |
(lineString notNil and:[lineString isString not]) ifTrue:[ |
|
1090 |
self drawVisibleLine:visLineNr with:fg and:bg |
|
1091 |
] ifFalse:[ |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1092 |
yf := y - (lineSpacing//2). |
105 | 1093 |
col > lineString size ifTrue:[ |
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1094 |
self fillRectangleX:x y:yf width:(font width) height:fontHeight. |
105 | 1095 |
self paint:fg |
1096 |
] ifFalse:[ |
|
1097 |
characterString := (lineString at:col) asString. |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1098 |
self fillRectangleX:x y:yf |
105 | 1099 |
width:(font widthOf:characterString) |
1100 |
height:fontHeight. |
|
1101 |
self paint:fg. |
|
1102 |
self displayString:characterString x:x y:(y + fontAscent) |
|
1103 |
] |
|
1104 |
] |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1105 |
|
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1106 |
"Modified: 22.11.1995 / 23:42:27 / cg" |
105 | 1107 |
! |
1108 |
||
1109 |
drawVisibleLine:visLineNr from:startCol with:fg and:bg |
|
1110 |
"draw right part of a visible line from startCol to end of line in fg/bg" |
|
1111 |
||
1112 |
|y x lineString index1 index2| |
|
1113 |
||
1114 |
(startCol < 1) ifTrue:[ |
|
1115 |
index1 := 1 |
|
1116 |
] ifFalse:[ |
|
1117 |
index1 := startCol |
|
1118 |
]. |
|
1119 |
y := self yOfVisibleLine:visLineNr. |
|
1120 |
x := (self xOfCol:index1 inVisibleLine:visLineNr) - leftOffset. |
|
1121 |
self paint:bg. |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1122 |
self fillRectangleX:x y:y - (lineSpacing // 2) |
105 | 1123 |
width:(width + leftOffset - x) |
1124 |
height:fontHeight. |
|
1125 |
||
1126 |
lineString := self visibleAt:visLineNr. |
|
1127 |
lineString notNil ifTrue:[ |
|
1128 |
lineString isString ifFalse:[ |
|
1129 |
self drawVisibleLine:visLineNr with:fg and:bg. |
|
1130 |
] ifTrue:[ |
|
1131 |
index2 := lineString size. |
|
1132 |
(index2 < index1) ifTrue:[^ self]. |
|
1133 |
(index1 <= index2) ifTrue:[ |
|
1134 |
self paint:fg. |
|
1135 |
self displayString:lineString from:index1 to:index2 x:x y:(y + fontAscent) |
|
59 | 1136 |
] |
1137 |
] |
|
7 | 1138 |
] |
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1139 |
|
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1140 |
"Modified: 22.11.1995 / 23:43:37 / cg" |
7 | 1141 |
! |
1142 |
||
105 | 1143 |
drawVisibleLine:visLineNr from:startCol to:endCol with:fg and:bg |
1144 |
"draw part of a visible line in fg/bg" |
|
1145 |
||
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1146 |
|y yf x lineString len characterString| |
105 | 1147 |
|
1148 |
(endCol >= startCol) ifTrue:[ |
|
1149 |
lineString := self visibleAt:visLineNr. |
|
1150 |
||
1151 |
(lineString notNil and:[lineString isString not]) ifTrue:[ |
|
1152 |
self drawVisibleLine:visLineNr with:fg and:bg. |
|
1153 |
] ifFalse:[ |
|
1154 |
x := (self xOfCol:startCol inVisibleLine:visLineNr) - leftOffset. |
|
1155 |
y := (self yOfVisibleLine:visLineNr). |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1156 |
yf := y - (lineSpacing // 2). |
105 | 1157 |
len := lineString size. |
1158 |
(startCol > len) ifTrue:[ |
|
1159 |
len := endCol - startCol + 1. |
|
1160 |
self paint:bg. |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1161 |
self fillRectangleX:x y:yf |
105 | 1162 |
width:(fontWidth * len) |
1163 |
height:fontHeight |
|
1164 |
] ifFalse:[ |
|
1165 |
(endCol > len) ifTrue:[ |
|
1166 |
characterString := String new:endCol. |
|
1167 |
characterString replaceFrom:1 to:len with:lineString startingAt:1. |
|
1168 |
lineString := characterString |
|
1169 |
]. |
|
1170 |
self paint:bg. |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1171 |
self fillRectangleX:x y:yf width:(font widthOf:lineString from:startCol to:endCol) |
105 | 1172 |
height:fontHeight. |
1173 |
self paint:fg. |
|
1174 |
self displayString:lineString from:startCol to:endCol x:x y:(y + fontAscent) |
|
1175 |
] |
|
1176 |
] |
|
1177 |
] |
|
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1178 |
|
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
1179 |
"Modified: 22.11.1995 / 23:43:21 / cg" |
105 | 1180 |
! ! |
1181 |
||
1182 |
!ListView methodsFor:'queries'! |
|
1183 |
||
1184 |
numberOfLines |
|
1185 |
"return the number of lines the text has" |
|
1186 |
||
1187 |
^ self size |
|
95 | 1188 |
! |
1189 |
||
105 | 1190 |
lengthOfLongestLine |
1191 |
"return the length (in characters) of the longest line" |
|
1192 |
||
1193 |
^ self lengthOfLongestLineBetween:1 and:self size |
|
1194 |
! |
|
1195 |
||
1196 |
lengthOfLongestLineBetween:firstLine and:lastLine |
|
1197 |
"return the length (in characters) of the longest line in a line-range" |
|
1198 |
||
1199 |
|max "{ Class: SmallInteger }" |
|
1200 |
thisLen "{ Class: SmallInteger }" |
|
1201 |
listSize "{ Class: SmallInteger }" |
|
1202 |
first "{ Class: SmallInteger }" |
|
1203 |
last "{ Class: SmallInteger }" | |
|
1204 |
||
1205 |
list isNil ifTrue:[^ 0]. |
|
1206 |
||
1207 |
listSize := self size. |
|
1208 |
max := 0. |
|
1209 |
first := firstLine. |
|
1210 |
last := lastLine. |
|
1211 |
||
1212 |
(first > listSize) ifTrue:[^ max]. |
|
1213 |
(last > listSize) ifTrue:[ |
|
1214 |
last := listSize |
|
60 | 1215 |
]. |
105 | 1216 |
self from:first to:last do:[:lineString | |
1217 |
lineString notNil ifTrue:[ |
|
1218 |
thisLen := lineString size. |
|
1219 |
(thisLen > max) ifTrue:[ |
|
1220 |
max := thisLen |
|
1221 |
] |
|
59 | 1222 |
] |
0 | 1223 |
]. |
105 | 1224 |
^ max |
1225 |
||
0 | 1226 |
! |
1227 |
||
105 | 1228 |
widthOfContents |
1229 |
"return the width of the contents in pixels |
|
1230 |
- used for scrollbar interface" |
|
1231 |
||
1232 |
|max| |
|
1233 |
||
1234 |
list isNil ifTrue:[^ 0]. |
|
118 | 1235 |
widthOfWidestLine notNil ifTrue:[^ widthOfWidestLine + (leftMargin * 2)]. |
105 | 1236 |
|
1237 |
includesNonStrings ifTrue:[ |
|
1238 |
max := list |
|
1239 |
inject:0 |
|
1240 |
into:[:maxSoFar :entry | |
|
1241 |
( |
|
1242 |
entry isNil ifTrue:[ |
|
1243 |
0 |
|
1244 |
] ifFalse:[ |
|
1245 |
entry isString ifTrue:[ |
|
1246 |
font widthOf:entry |
|
1247 |
] ifFalse:[ |
|
1248 |
entry widthIn:self |
|
1249 |
] |
|
1250 |
] |
|
1251 |
) max:maxSoFar. |
|
1252 |
] |
|
1253 |
] ifFalse:[ |
|
1254 |
fontIsFixedWidth ifTrue:[ |
|
1255 |
max := self lengthOfLongestLine * fontWidth |
|
1256 |
] ifFalse:[ |
|
1257 |
max := 0. |
|
1258 |
list notNil ifTrue:[ |
|
1259 |
max := max max:(font widthOf:list) |
|
1260 |
]. |
|
59 | 1261 |
]. |
118 | 1262 |
]. |
1263 |
widthOfWidestLine := max. |
|
1264 |
^ max + (leftMargin * 2) |
|
105 | 1265 |
! |
1266 |
||
1267 |
yOriginOfContents |
|
1268 |
"return the vertical origin of the contents in pixels |
|
1269 |
- used for scrollbar interface" |
|
1270 |
||
1271 |
^ (firstLineShown - 1) * fontHeight |
|
1272 |
! |
|
1273 |
||
1274 |
heightOfContents |
|
1275 |
"return the height of the contents in pixels |
|
1276 |
- used for scrollbar interface" |
|
1277 |
||
1278 |
| numLines | |
|
1279 |
||
1280 |
numLines := self numberOfLines. |
|
1281 |
numLines == 0 ifTrue:[^ 0]. |
|
221 | 1282 |
|
1283 |
"/ |
|
1284 |
"/ kludge for last partial line |
|
1285 |
"/ |
|
226 | 1286 |
"/ nFullLinesShown ~~ nLinesShown ifTrue:[ |
1287 |
"/ numLines := numLines + 1 |
|
1288 |
"/ ]. |
|
105 | 1289 |
" |
1290 |
need device-font for query |
|
1291 |
" |
|
1292 |
font := font on:device. |
|
221 | 1293 |
^ numLines * fontHeight |
1294 |
"/ + textStartTop |
|
226 | 1295 |
- (lineSpacing // 2) |
128 | 1296 |
"/ + (font descent) |
221 | 1297 |
"/ + (font descent * 2) "makes it look better" |
1298 |
. |
|
105 | 1299 |
|
1300 |
"/ "it used to be that code - which is wrong" |
|
1301 |
"/ (nLinesShown == nFullLinesShown) ifTrue:[ |
|
1302 |
"/ ^ numLines * fontHeight |
|
1303 |
"/ ]. |
|
1304 |
"/ "add one - otherwise we cannot make last line |
|
1305 |
"/ fully visible since scrolling is done by full lines only" |
|
1306 |
"/ |
|
1307 |
"/ ^ (numLines + 1) * fontHeight |
|
1308 |
! |
|
1309 |
||
1310 |
xOriginOfContents |
|
1311 |
"return the horizontal origin of the contents in pixels |
|
1312 |
- used for scrollbar interface" |
|
1313 |
||
1314 |
^ leftOffset |
|
1315 |
! |
|
1316 |
||
1317 |
firstLineShown |
|
1318 |
"return the index of the first (possibly partial) visible line" |
|
1319 |
||
1320 |
^ firstLineShown |
|
1321 |
! |
|
1322 |
||
1323 |
lastLineShown |
|
1324 |
"return the index of the last (possibly partial) visible line" |
|
1325 |
||
1326 |
^ firstLineShown + nLinesShown |
|
1327 |
! |
|
1328 |
||
1329 |
leftIndentOfLine:lineNr |
|
1330 |
"return the number of spaces at the left in line, lineNr. |
|
1331 |
returns 0 for empty lines." |
|
1332 |
||
1333 |
|lineString index end| |
|
1334 |
||
1335 |
lineString := self listAt:lineNr. |
|
1336 |
lineString notNil ifTrue:[ |
|
1337 |
index := 1. |
|
1338 |
end := lineString size. |
|
1339 |
[index <= end] whileTrue:[ |
|
1340 |
(lineString at:index) isSeparator ifFalse:[^ index - 1]. |
|
1341 |
index := index + 1 |
|
59 | 1342 |
] |
0 | 1343 |
]. |
105 | 1344 |
^ 0 |
38 | 1345 |
! |
1346 |
||
105 | 1347 |
lineIsVisible:line |
1348 |
"is line visible?" |
|
1349 |
||
1350 |
(line >= firstLineShown and:[ line < (firstLineShown + nLinesShown) ]) ifTrue:[ ^ true ]. |
|
1351 |
^ false. |
|
0 | 1352 |
! ! |
1353 |
||
1354 |
!ListView methodsFor:'scrolling'! |
|
1355 |
||
132 | 1356 |
makeVisible:someString |
1357 |
"if nescessary, scroll to make the (first) |
|
1358 |
line containing someString visible." |
|
1359 |
||
1360 |
|line index| |
|
1361 |
||
1362 |
index := self list indexOf:someString. |
|
1363 |
index ~~ 0 ifTrue:[ |
|
1364 |
self makeLineVisible:index |
|
1365 |
] |
|
1366 |
! |
|
1367 |
||
38 | 1368 |
makeLineVisible:aListLineNr |
1369 |
"if aListLineNr is not visible, scroll to make it visible. |
|
1370 |
Numbering starts with 1 for the very first line of the text." |
|
1371 |
||
1372 |
|bott| |
|
1373 |
||
1374 |
(aListLineNr isNil "or:[shown not]") ifTrue:[^ self]. |
|
1375 |
||
1376 |
(aListLineNr >= firstLineShown) ifTrue:[ |
|
59 | 1377 |
(aListLineNr < (firstLineShown + nFullLinesShown)) ifTrue:[ |
1378 |
^ self |
|
1379 |
] |
|
38 | 1380 |
]. |
1381 |
(aListLineNr < nFullLinesShown) ifTrue:[ |
|
59 | 1382 |
^ self scrollToLine:1 |
38 | 1383 |
]. |
1384 |
(nFullLinesShown < 3) ifTrue:[ |
|
59 | 1385 |
^ self scrollToLine:aListLineNr |
38 | 1386 |
]. |
1387 |
bott := self numberOfLines - (nFullLinesShown - 1). |
|
1388 |
(aListLineNr > bott) ifTrue:[ |
|
59 | 1389 |
^ self scrollToLine:bott |
38 | 1390 |
]. |
1391 |
self scrollToLine:(aListLineNr - (nFullLinesShown // 2) + 1) |
|
1392 |
! |
|
1393 |
||
0 | 1394 |
scrollDown:nLines |
1395 |
"change origin to scroll down some lines" |
|
1396 |
||
1397 |
|w "{ Class:SmallInteger }" |
|
1398 |
h "{ Class:SmallInteger }" |
|
1399 |
m2 "{ Class:SmallInteger }" |
|
51 | 1400 |
count "{ Class:SmallInteger }" |
196
7e3c25063173
scroll offset by half a lineSpacing
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1401 |
y0 "{ Class:SmallInteger }" |
116 | 1402 |
nPixel sz| |
0 | 1403 |
|
1404 |
count := nLines. |
|
116 | 1405 |
sz := self size. |
1406 |
(firstLineShown + nLines + nFullLinesShown > sz) ifTrue:[ |
|
1407 |
count := sz - firstLineShown - nFullLinesShown + 1 |
|
0 | 1408 |
]. |
1409 |
count <= 0 ifTrue:[^ self]. |
|
1410 |
||
1411 |
self originWillChange. |
|
63 | 1412 |
nPixel := fontHeight * count. |
1413 |
||
59 | 1414 |
shown ifFalse:[ |
91 | 1415 |
firstLineShown := firstLineShown + count. |
63 | 1416 |
viewOrigin := viewOrigin x @ (viewOrigin y + nPixel). |
59 | 1417 |
] ifTrue:[ |
1418 |
(count >= nLinesShown) ifTrue:[ |
|
91 | 1419 |
firstLineShown := firstLineShown + count. |
63 | 1420 |
viewOrigin := viewOrigin x @ (viewOrigin y + nPixel). |
59 | 1421 |
self redrawFromVisibleLine:1 to:nLinesShown. |
1422 |
] ifFalse:[ |
|
1423 |
m2 := margin * 2. |
|
91 | 1424 |
w := self widthForScrollBetween:firstLineShown |
1425 |
and:(firstLineShown + nLinesShown). |
|
59 | 1426 |
w := w + leftMargin. |
0 | 1427 |
|
227 | 1428 |
y0 := textStartTop - (lineSpacing//2). |
196
7e3c25063173
scroll offset by half a lineSpacing
Claus Gittinger <cg@exept.de>
parents:
191
diff
changeset
|
1429 |
h := nPixel + y0. |
227 | 1430 |
|
59 | 1431 |
self catchExpose. |
224 | 1432 |
self copyFrom:self x:margin y:h |
1433 |
toX:margin y:y0 |
|
227 | 1434 |
width:w height:(height - h + lineSpacing). |
0 | 1435 |
|
91 | 1436 |
firstLineShown := firstLineShown + count. |
63 | 1437 |
viewOrigin := viewOrigin x @ (viewOrigin y + nPixel). |
223 | 1438 |
self redrawFromVisibleLine:(nFullLinesShown - count + 1) to:nLinesShown. |
59 | 1439 |
self waitForExpose. |
1440 |
]. |
|
51 | 1441 |
]. |
1442 |
self originChanged:count. |
|
0 | 1443 |
! |
1444 |
||
105 | 1445 |
scrollToLine:aLineNr |
1446 |
"change origin to make aLineNr be the top line" |
|
1447 |
||
1448 |
aLineNr < firstLineShown ifTrue:[ |
|
1449 |
self scrollUp:(firstLineShown - aLineNr) |
|
1450 |
] ifFalse:[ |
|
1451 |
aLineNr > firstLineShown ifTrue:[ |
|
1452 |
self scrollDown:(aLineNr - firstLineShown) |
|
1453 |
] |
|
1454 |
] |
|
1455 |
! |
|
1456 |
||
1457 |
scrollToTop |
|
1458 |
"change origin to start of text" |
|
1459 |
||
1460 |
self scrollToLine:1 |
|
1461 |
! |
|
1462 |
||
1463 |
makeColVisible:aCol inLine:aLineNr |
|
1464 |
"if column aCol is not visible, scroll horizontal to make it visible" |
|
1465 |
||
118 | 1466 |
|xWant xVis visLnr| |
105 | 1467 |
|
1468 |
(aCol isNil or:[shown not]) ifTrue:[^ self]. |
|
1469 |
||
1470 |
visLnr := self absoluteLineToVisibleLine:aLineNr. |
|
1471 |
visLnr isNil ifTrue:[^ self]. |
|
1472 |
||
1473 |
xWant := self xOfCol:aCol inVisibleLine:visLnr. |
|
1474 |
xVis := xWant - leftOffset. |
|
1475 |
||
1476 |
" |
|
1477 |
dont scroll, if already visible |
|
1478 |
(but scroll, if not in inner 20%..80% of visible area) |
|
1479 |
" |
|
1480 |
"/ ((xVis >= (width // 5)) and:[xVis <= (width * 4 // 5)]) ifTrue:[ |
|
1481 |
"/ ^ self |
|
1482 |
"/ ]. |
|
1483 |
||
1484 |
" |
|
1485 |
no, the above does not look good, if you click / select at the |
|
1486 |
far right - makes selecting so difficult ... |
|
1487 |
" |
|
1488 |
(xVis >= 0 and:[xVis < (width - font width)]) ifTrue:[^ self]. |
|
1489 |
||
1490 |
self scrollHorizontalTo:(xWant - (width // 2)). |
|
1491 |
! |
|
1492 |
||
0 | 1493 |
scrollDown |
1494 |
"change origin to scroll down one line" |
|
1495 |
||
1496 |
self scrollDown:1 |
|
1497 |
! |
|
1498 |
||
105 | 1499 |
scrollToLeft |
1500 |
"change origin to start (left) of text" |
|
1501 |
||
1502 |
leftOffset ~~ 0 ifTrue:[ |
|
1503 |
self scrollToCol:1 |
|
1504 |
] |
|
1505 |
! |
|
1506 |
||
1507 |
viewOrigin |
|
1508 |
"return the viewOrigin; thats the coordinate of the contents |
|
1509 |
which is shown topLeft in the view |
|
1510 |
(i.e. the origin of the visible part of the contents)." |
|
1511 |
||
1512 |
^ viewOrigin |
|
1513 |
! |
|
1514 |
||
1515 |
gotoLine:aLineNumber |
|
1516 |
"position to line aLineNumber; this may be redefined |
|
1517 |
in subclasses (for example to move the cursor also)" |
|
1518 |
||
1519 |
^ self scrollToLine:aLineNumber |
|
1520 |
! |
|
1521 |
||
0 | 1522 |
scrollUp:nLines |
1523 |
"change origin to scroll up some lines" |
|
1524 |
||
1525 |
|w "{ Class:SmallInteger }" |
|
1526 |
h "{ Class:SmallInteger }" |
|
51 | 1527 |
count "{ Class:SmallInteger }" |
91 | 1528 |
nPixel| |
0 | 1529 |
|
1530 |
count := nLines. |
|
1531 |
count >= firstLineShown ifTrue:[ |
|
59 | 1532 |
count := firstLineShown - 1 |
0 | 1533 |
]. |
1534 |
(count == 0) ifTrue:[^ self]. |
|
1535 |
||
1536 |
self originWillChange. |
|
63 | 1537 |
nPixel := fontHeight * count. |
59 | 1538 |
shown ifFalse:[ |
91 | 1539 |
firstLineShown := firstLineShown - count. |
63 | 1540 |
viewOrigin := viewOrigin x @ (viewOrigin y - nPixel). |
59 | 1541 |
] ifTrue:[ |
1542 |
(count >= nLinesShown) ifTrue:[ |
|
91 | 1543 |
firstLineShown := firstLineShown - count. |
63 | 1544 |
viewOrigin := viewOrigin x @ (viewOrigin y - nPixel). |
59 | 1545 |
self redrawFromVisibleLine:1 to:nLinesShown. |
1546 |
] ifFalse:[ |
|
91 | 1547 |
w := self widthForScrollBetween:firstLineShown |
1548 |
and:(firstLineShown + nLinesShown). |
|
59 | 1549 |
w := w + leftMargin. |
225 | 1550 |
h := nPixel + margin. |
59 | 1551 |
self catchExpose. |
225 | 1552 |
self copyFrom:self x:margin y:margin |
59 | 1553 |
toX:margin y:h |
224 | 1554 |
width:w height:(height - h). |
91 | 1555 |
firstLineShown := firstLineShown - count. |
63 | 1556 |
viewOrigin := viewOrigin x @ (viewOrigin y - nPixel). |
59 | 1557 |
self redrawFromVisibleLine:1 to:count. |
1558 |
self waitForExpose. |
|
1559 |
]. |
|
51 | 1560 |
]. |
1561 |
self originChanged:(count negated). |
|
0 | 1562 |
! |
1563 |
||
105 | 1564 |
pageDown |
1565 |
"change origin to display next page" |
|
1566 |
||
1567 |
|nLines| |
|
1568 |
||
1569 |
nLines := nFullLinesShown. |
|
1570 |
(firstLineShown + nLines + nFullLinesShown > self size) ifTrue:[ |
|
1571 |
nLines := self size - firstLineShown - nFullLinesShown + 1 |
|
1572 |
]. |
|
1573 |
nLines <= 0 ifTrue:[^ self]. |
|
1574 |
||
1575 |
self originWillChange. |
|
1576 |
firstLineShown := firstLineShown + nLines. |
|
1577 |
self originChanged:nLines. |
|
1578 |
self redrawFromVisibleLine:1 to:nLinesShown |
|
1579 |
||
1580 |
! |
|
1581 |
||
1582 |
scrollVerticalToPercent:percent |
|
1583 |
"scroll to a position given in percent of total" |
|
1584 |
||
221 | 1585 |
|nL lineNr| |
1586 |
||
1587 |
nL := self numberOfLines. |
|
1588 |
"/ |
|
1589 |
"/ kludge for last partial line |
|
1590 |
"/ |
|
1591 |
nFullLinesShown ~~ nLinesShown ifTrue:[ |
|
1592 |
nL := nL + 1 |
|
1593 |
]. |
|
1594 |
lineNr := (((nL * percent) asFloat / 100.0) + 0.5) asInteger + 1. |
|
105 | 1595 |
self scrollToLine:lineNr |
1596 |
! |
|
1597 |
||
1598 |
pageUp |
|
1599 |
"change origin to display previous page" |
|
1600 |
||
1601 |
|oldOrg| |
|
1602 |
||
1603 |
(firstLineShown == 1) ifFalse:[ |
|
1604 |
self originWillChange. |
|
1605 |
oldOrg := firstLineShown. |
|
1606 |
firstLineShown := firstLineShown - nFullLinesShown. |
|
1607 |
(firstLineShown < 1) ifTrue:[ |
|
1608 |
firstLineShown := 1 |
|
1609 |
]. |
|
1610 |
self originChanged:(firstLineShown - oldOrg). |
|
1611 |
self redrawFromVisibleLine:1 to:nLinesShown |
|
1612 |
] |
|
1613 |
! |
|
1614 |
||
1615 |
halfPageDown |
|
1616 |
"scroll down half a page" |
|
1617 |
||
1618 |
self scrollDown:(nFullLinesShown // 2) |
|
1619 |
! |
|
1620 |
||
1621 |
halfPageUp |
|
1622 |
"scroll up half a page" |
|
1623 |
||
1624 |
self scrollUp:(nFullLinesShown // 2) |
|
1625 |
! |
|
1626 |
||
0 | 1627 |
scrollUp |
1628 |
"change origin to scroll up one line" |
|
1629 |
||
1630 |
self scrollUp:1 |
|
1631 |
! |
|
1632 |
||
38 | 1633 |
scrollToBottom |
1634 |
"change origin to show end of text" |
|
1635 |
||
1636 |
"scrolling to the end is not really correct (i.e. should scroll to list size - nFullLinesShown), |
|
1637 |
but scrollDown: will adjust it ..." |
|
1638 |
||
105 | 1639 |
self scrollToLine:(self size) |
38 | 1640 |
! |
1641 |
||
1642 |
scrollToCol:aColNr |
|
1643 |
"change origin to make aColNr be the left col" |
|
1644 |
||
1645 |
|pxlOffset| |
|
1646 |
||
1647 |
aColNr == 1 ifTrue:[ |
|
59 | 1648 |
leftOffset ~~ 0 ifTrue:[ |
1649 |
self scrollLeft:leftOffset. |
|
1650 |
]. |
|
1651 |
^ self |
|
38 | 1652 |
]. |
1653 |
||
1654 |
pxlOffset := font width * (aColNr - 1). |
|
1655 |
||
1656 |
pxlOffset < leftOffset ifTrue:[ |
|
59 | 1657 |
self scrollLeft:(leftOffset - pxlOffset) |
38 | 1658 |
] ifFalse:[ |
59 | 1659 |
pxlOffset > leftOffset ifTrue:[ |
1660 |
self scrollRight:(pxlOffset - leftOffset) |
|
1661 |
] |
|
38 | 1662 |
] |
1663 |
! |
|
1664 |
||
105 | 1665 |
stopAutoScroll |
1666 |
"stop any auto-scroll" |
|
1667 |
||
1668 |
autoScrollBlock notNil ifTrue:[ |
|
1669 |
self compressMotionEvents:true. |
|
1670 |
Processor removeTimedBlock:autoScrollBlock. |
|
1671 |
autoScrollBlock := nil. |
|
1672 |
autoScrollDeltaT := nil |
|
1673 |
]. |
|
0 | 1674 |
! |
1675 |
||
1676 |
scrollSelectUp |
|
1677 |
"just a template - I do not know anything about selections" |
|
1678 |
||
1679 |
^ self subclassResponsibility |
|
1680 |
! |
|
1681 |
||
1682 |
scrollSelectDown |
|
1683 |
"just a template - I do not know anything about selections" |
|
1684 |
||
1685 |
^ self subclassResponsibility |
|
1686 |
! |
|
1687 |
||
59 | 1688 |
startAutoScrollDown:yDistance |
0 | 1689 |
"setup for auto-scroll down (when button-press-moving below view) |
1690 |
- timeDelta for scroll is computed from distance" |
|
1691 |
||
1692 |
|deltaT mm| |
|
1693 |
||
190 | 1694 |
autoScroll ifFalse:[^ self]. |
1695 |
||
0 | 1696 |
mm := yDistance // self verticalIntegerPixelPerMillimeter + 1. |
1697 |
deltaT := 0.5 / mm. |
|
1698 |
||
1699 |
(deltaT = autoScrollDeltaT) ifFalse:[ |
|
59 | 1700 |
autoScrollDeltaT := deltaT. |
1701 |
autoScrollBlock isNil ifTrue:[ |
|
1702 |
autoScrollBlock := [self scrollSelectDown]. |
|
1703 |
Processor addTimedBlock:autoScrollBlock afterSeconds:deltaT |
|
1704 |
] |
|
0 | 1705 |
] |
1706 |
! |
|
1707 |
||
59 | 1708 |
startAutoScrollUp:yDistance |
0 | 1709 |
"setup for auto-scroll up (when button-press-moving below view) |
1710 |
- timeDelta for scroll is computed from distance" |
|
1711 |
||
1712 |
|deltaT mm| |
|
1713 |
||
190 | 1714 |
autoScroll ifFalse:[^ self]. |
1715 |
||
0 | 1716 |
mm := yDistance negated // self verticalIntegerPixelPerMillimeter + 1. |
1717 |
deltaT := 0.5 / mm. |
|
1718 |
||
1719 |
(deltaT = autoScrollDeltaT) ifFalse:[ |
|
59 | 1720 |
autoScrollDeltaT := deltaT. |
1721 |
autoScrollBlock isNil ifTrue:[ |
|
1722 |
autoScrollBlock := [self scrollSelectUp]. |
|
1723 |
Processor addTimedBlock:autoScrollBlock afterSeconds:deltaT |
|
1724 |
] |
|
1725 |
] |
|
1726 |
! |
|
1727 |
||
1728 |
startAutoScrollRight:xDistance |
|
1729 |
"setup for auto-scroll down (when button-press-moving to the right of the view) |
|
1730 |
- timeDelta for scroll is computed from distance" |
|
1731 |
||
1732 |
|deltaT mm| |
|
1733 |
||
190 | 1734 |
autoScroll ifFalse:[^ self]. |
1735 |
||
59 | 1736 |
mm := xDistance // self horizontalIntegerPixelPerMillimeter + 1. |
1737 |
deltaT := 0.5 / mm. |
|
1738 |
||
1739 |
(deltaT = autoScrollDeltaT) ifFalse:[ |
|
1740 |
autoScrollDeltaT := deltaT. |
|
1741 |
autoScrollBlock isNil ifTrue:[ |
|
1742 |
autoScrollBlock := [self scrollSelectRight]. |
|
1743 |
Processor addTimedBlock:autoScrollBlock afterSeconds:deltaT |
|
1744 |
] |
|
1745 |
] |
|
1746 |
! |
|
1747 |
||
1748 |
startAutoScrollLeft:xDistance |
|
1749 |
"setup for auto-scroll up (when button-press-moving to the left of the view) |
|
1750 |
- timeDelta for scroll is computed from distance" |
|
1751 |
||
1752 |
|deltaT mm| |
|
1753 |
||
190 | 1754 |
autoScroll ifFalse:[^ self]. |
1755 |
||
59 | 1756 |
mm := xDistance negated // self horizontalIntegerPixelPerMillimeter + 1. |
1757 |
deltaT := 0.5 / mm. |
|
1758 |
||
1759 |
(deltaT = autoScrollDeltaT) ifFalse:[ |
|
1760 |
autoScrollDeltaT := deltaT. |
|
1761 |
autoScrollBlock isNil ifTrue:[ |
|
1762 |
autoScrollBlock := [self scrollSelectLeft]. |
|
1763 |
Processor addTimedBlock:autoScrollBlock afterSeconds:deltaT |
|
1764 |
] |
|
0 | 1765 |
] |
1766 |
! |
|
1767 |
||
38 | 1768 |
scrollRight |
1769 |
"scroll right by one character |
|
1770 |
- question is how much is a good for variable fonts" |
|
1771 |
||
1772 |
self scrollRight:font width |
|
1773 |
! |
|
1774 |
||
1775 |
scrollRight:nPixel |
|
1776 |
"change origin to scroll right some cols" |
|
1777 |
||
1778 |
|wMax cnt| |
|
1779 |
||
1780 |
||
1781 |
cnt := nPixel. |
|
1782 |
||
1783 |
" |
|
1784 |
commenting out the block below allows scrolling to the right of |
|
1785 |
the widest line |
|
1786 |
" |
|
1787 |
" " |
|
1788 |
" |
|
1789 |
the 10 below allows scrolling somewhat behind the end of the line |
|
1790 |
" |
|
1791 |
wMax := self widthOfContents + 10. |
|
1792 |
(leftOffset + nPixel + width > wMax) ifTrue:[ |
|
59 | 1793 |
cnt := wMax - leftOffset - width |
38 | 1794 |
]. |
59 | 1795 |
" " |
38 | 1796 |
cnt <= 0 ifTrue:[^ self]. |
1797 |
self originWillChange. |
|
132 | 1798 |
leftOffset := leftOffset + cnt. |
59 | 1799 |
viewOrigin := leftOffset @ viewOrigin y. |
38 | 1800 |
self redrawFromVisibleLine:1 to:nLinesShown. |
1801 |
self originChanged:(cnt @ 0) |
|
1802 |
! |
|
1803 |
||
1804 |
scrollLeft |
|
1805 |
"scroll left by one character |
|
1806 |
- question is how much is a good for variable fonts" |
|
1807 |
||
1808 |
self scrollLeft:font width |
|
1809 |
! |
|
1810 |
||
1811 |
scrollLeft:nPixel |
|
1812 |
"change origin to scroll left some cols" |
|
1813 |
||
1814 |
|newLeftOffset| |
|
1815 |
||
1816 |
nPixel <= 0 ifTrue:[^ self]. |
|
1817 |
||
1818 |
newLeftOffset := leftOffset - nPixel. |
|
1819 |
newLeftOffset <= 0 ifTrue:[ |
|
59 | 1820 |
leftOffset == 0 ifTrue:[^ self]. |
1821 |
newLeftOffset := 0 |
|
38 | 1822 |
]. |
1823 |
||
1824 |
self originWillChange. |
|
1825 |
leftOffset := newLeftOffset. |
|
59 | 1826 |
viewOrigin := newLeftOffset @ viewOrigin y. |
38 | 1827 |
self redrawFromVisibleLine:1 to:nLinesShown. |
1828 |
self originChanged:(0 @ nPixel) |
|
1829 |
! |
|
1830 |
||
1831 |
scrollHorizontalTo:aPixelOffset |
|
1832 |
"change origin to make aPixelOffset be the left col" |
|
1833 |
||
1834 |
|orgX| |
|
1835 |
||
1836 |
orgX := leftOffset. |
|
1837 |
||
1838 |
(aPixelOffset < orgX) ifTrue:[ |
|
59 | 1839 |
self scrollLeft:(orgX - aPixelOffset) |
38 | 1840 |
] ifFalse:[ |
59 | 1841 |
(aPixelOffset > orgX) ifTrue:[ |
1842 |
self scrollRight:(aPixelOffset - orgX) |
|
1843 |
] |
|
38 | 1844 |
] |
0 | 1845 |
! ! |
1846 |
||
105 | 1847 |
!ListView methodsFor:'tabulators'! |
1848 |
||
1849 |
expandTabs |
|
1850 |
"go through whole text expanding tabs into spaces. |
|
118 | 1851 |
This is meant to be called for text being imported from a file. |
1852 |
Therefore, 8-col tabs are assumed - independent of any private tab setting." |
|
105 | 1853 |
|
1854 |
|line newLine nLines "{ Class: SmallInteger }"| |
|
1855 |
||
153 | 1856 |
includesNonStrings := false. |
105 | 1857 |
list notNil ifTrue:[ |
1858 |
nLines := self size. |
|
1859 |
1 to:nLines do:[:index | |
|
1860 |
line := self at:index. |
|
1861 |
line notNil ifTrue:[ |
|
153 | 1862 |
line isString ifTrue:[ |
158 | 1863 |
newLine := line withTabsExpanded. |
1864 |
newLine ~~ line ifTrue:[ |
|
153 | 1865 |
self withoutRedrawAt:index put:newLine |
1866 |
]. |
|
1867 |
] ifFalse:[ |
|
1868 |
includesNonStrings := true. |
|
105 | 1869 |
] |
59 | 1870 |
] |
1871 |
] |
|
0 | 1872 |
] |
153 | 1873 |
|
1874 |
"Modified: 30.8.1995 / 19:06:37 / claus" |
|
0 | 1875 |
! |
1876 |
||
105 | 1877 |
withTabs:tabulatorTable expand:line |
1878 |
"expand tabs into spaces, return a new line string, |
|
1879 |
or original line, if no tabs are included. |
|
120 | 1880 |
good idea, to make this one a primitive, since it is called |
1881 |
many times if a big text is read from a file." |
|
105 | 1882 |
|
1883 |
|tmpString nString nTabs |
|
1884 |
currentMax "{ Class: SmallInteger }" |
|
1885 |
dstIndex "{ Class: SmallInteger }" |
|
1886 |
nextTab "{ Class: SmallInteger }" | |
|
1887 |
||
120 | 1888 |
" |
1889 |
the code below tries to avoid creating too much garbage; |
|
1890 |
therefore, the string is scanned first for the number of |
|
1891 |
tabs to get a rough idea of the final strings size. |
|
1892 |
(it could be done better, by computing the exact size |
|
1893 |
required here ...) |
|
1894 |
" |
|
105 | 1895 |
line isNil ifTrue:[^ line]. |
1896 |
nTabs := line occurrencesOf:(Character tab). |
|
1897 |
nTabs == 0 ifTrue:[^ line]. |
|
1898 |
||
1899 |
currentMax := line size + (nTabs * 7). |
|
1900 |
tmpString := String new:currentMax. |
|
1901 |
dstIndex := 1. |
|
1902 |
line do:[:character | |
|
1903 |
(character == (Character tab)) ifTrue:[ |
|
1904 |
nextTab := self nextTabAfter:dstIndex in:tabulatorTable. |
|
1905 |
[dstIndex < nextTab] whileTrue:[ |
|
1906 |
tmpString at:dstIndex put:(Character space). |
|
1907 |
dstIndex := dstIndex + 1 |
|
1908 |
] |
|
1909 |
] ifFalse:[ |
|
1910 |
tmpString at:dstIndex put:character. |
|
1911 |
dstIndex := dstIndex + 1 |
|
1912 |
]. |
|
1913 |
(dstIndex > currentMax) ifTrue:[ |
|
1914 |
" |
|
1915 |
this cannot happen with <= 8 tabs |
|
1916 |
" |
|
1917 |
currentMax := currentMax + currentMax. |
|
1918 |
nString := String new:currentMax. |
|
1919 |
nString replaceFrom:1 to:(dstIndex - 1) |
|
1920 |
with:tmpString startingAt:1. |
|
1921 |
tmpString := nString. |
|
1922 |
nString := nil |
|
1923 |
]. |
|
1924 |
||
1925 |
"make stc-optimizer happy |
|
1926 |
- no need to return value of ifTrue:/ifFalse above" |
|
1927 |
0 |
|
0 | 1928 |
]. |
105 | 1929 |
dstIndex := dstIndex - 1. |
1930 |
dstIndex == currentMax ifTrue:[ |
|
1931 |
^ tmpString |
|
1932 |
]. |
|
1933 |
^ tmpString copyTo:dstIndex |
|
1934 |
! |
|
1935 |
||
1936 |
setTab4 |
|
1937 |
"set 4-character tab stops" |
|
1938 |
||
1939 |
tabPositions := self class tab4Positions. |
|
1940 |
! |
|
1941 |
||
1942 |
setTab8 |
|
1943 |
"set 8-character tab stops" |
|
1944 |
||
1945 |
tabPositions := self class tab8Positions. |
|
0 | 1946 |
! |
1947 |
||
105 | 1948 |
nextTabAfter:colNr in:tabPositions |
1949 |
"return the next tab position after col. |
|
120 | 1950 |
The second arg, tabPositions is a collection of tabStops." |
105 | 1951 |
|
1952 |
|col "{ Class: SmallInteger }" |
|
1953 |
tabIndex "{ Class: SmallInteger }" |
|
1954 |
thisTab "{ Class: SmallInteger }" |
|
1955 |
nTabs "{ Class: SmallInteger }" | |
|
1956 |
||
1957 |
tabIndex := 1. |
|
1958 |
col := colNr. |
|
1959 |
thisTab := tabPositions at:tabIndex. |
|
1960 |
nTabs := tabPositions size. |
|
1961 |
[thisTab <= col] whileTrue:[ |
|
1962 |
(tabIndex == nTabs) ifTrue:[^ thisTab]. |
|
1963 |
tabIndex := tabIndex + 1. |
|
1964 |
thisTab := tabPositions at:tabIndex |
|
0 | 1965 |
]. |
105 | 1966 |
^ thisTab |
1967 |
! |
|
1968 |
||
1969 |
nextTabAfter:colNr |
|
1970 |
"return the next tab position after col" |
|
1971 |
||
1972 |
^ self nextTabAfter:colNr in:tabPositions |
|
1973 |
! |
|
1974 |
||
1975 |
prevTabBefore:colNr |
|
1976 |
"return the prev tab position before col" |
|
1977 |
||
1978 |
|col "{ Class: SmallInteger }" |
|
1979 |
tabIndex "{ Class: SmallInteger }" |
|
1980 |
thisTab "{ Class: SmallInteger }" |
|
1981 |
nTabs "{ Class: SmallInteger }" | |
|
1982 |
||
1983 |
tabIndex := 1. |
|
1984 |
col := colNr. |
|
1985 |
thisTab := tabPositions at:tabIndex. |
|
1986 |
nTabs := tabPositions size. |
|
1987 |
[thisTab < col] whileTrue:[ |
|
1988 |
(tabIndex == nTabs) ifTrue:[^ thisTab]. |
|
1989 |
tabIndex := tabIndex + 1. |
|
1990 |
thisTab := tabPositions at:tabIndex |
|
0 | 1991 |
]. |
105 | 1992 |
(tabIndex == 1) ifTrue:[ |
1993 |
^ 1 |
|
1994 |
]. |
|
1995 |
^ tabPositions at:(tabIndex - 1) |
|
1996 |
! |
|
1997 |
||
1998 |
withTabsExpanded:line |
|
1999 |
"expand tabs into spaces, return a new line string, |
|
2000 |
or original line, if no tabs are included. |
|
2001 |
good idea, to make this one a primitive" |
|
2002 |
||
2003 |
^ self withTabs:tabPositions expand:line |
|
0 | 2004 |
! |
2005 |
||
105 | 2006 |
withTabs:line |
2007 |
"Assuming an 8-character tab, |
|
120 | 2008 |
compress multiple leading spaces to tabs, return a new line string |
2009 |
or the original line, if no tabs where created. |
|
2010 |
good idea, to make this one a primitive, since its called |
|
2011 |
many times when a big text is saved to a file." |
|
2012 |
||
2013 |
|newLine eightSpaces nTabs| |
|
2014 |
||
2015 |
" |
|
2016 |
the code below is a hack, producing many garbage strings for lines |
|
2017 |
which compress multiple tabs ... needs rewrite: saving big files |
|
2018 |
stresses the garbage collector a bit ... |
|
2019 |
" |
|
105 | 2020 |
line isNil ifTrue:[^ line]. |
120 | 2021 |
eightSpaces := ' '. |
2022 |
(line startsWith:eightSpaces) ifFalse:[^ line]. |
|
2023 |
||
2024 |
nTabs := 1. |
|
105 | 2025 |
newLine := line copyFrom:9. |
120 | 2026 |
[newLine startsWith:eightSpaces] whileTrue:[ |
2027 |
newLine := newLine copyFrom:9. |
|
2028 |
nTabs := nTabs + 1. |
|
105 | 2029 |
]. |
120 | 2030 |
^ (String new:nTabs withAll:Character tab) asString , newLine. |
0 | 2031 |
! ! |
2032 |
||
2033 |
!ListView methodsFor:'redrawing'! |
|
2034 |
||
105 | 2035 |
redrawLine:lineNr |
2036 |
"redraw a list line" |
|
2037 |
||
2038 |
|visibleLine| |
|
2039 |
||
2040 |
visibleLine := self listLineToVisibleLine:lineNr. |
|
2041 |
visibleLine notNil ifTrue:[ |
|
2042 |
self redrawVisibleLine:visibleLine |
|
2043 |
] |
|
60 | 2044 |
! |
2045 |
||
0 | 2046 |
redrawVisibleLine:visLineNr col:col |
2047 |
"redraw single character at col index of visible line" |
|
2048 |
||
2049 |
shown ifTrue:[ |
|
59 | 2050 |
self drawVisibleLine:visLineNr col:col with:fgColor and:bgColor |
0 | 2051 |
] |
2052 |
! |
|
2053 |
||
2054 |
redrawFromVisibleLine:startVisLineNr to:endVisLineNr |
|
2055 |
"redraw a visible line range" |
|
2056 |
||
2057 |
shown ifTrue:[ |
|
59 | 2058 |
self drawFromVisibleLine:startVisLineNr to:endVisLineNr with:fgColor and:bgColor |
0 | 2059 |
] |
2060 |
! |
|
2061 |
||
105 | 2062 |
redrawLine:lineNr from:startCol |
2063 |
"redraw a list line from startCol to end of line" |
|
2064 |
||
2065 |
|visibleLine| |
|
2066 |
||
2067 |
visibleLine := self listLineToVisibleLine:lineNr. |
|
2068 |
visibleLine notNil ifTrue:[ |
|
2069 |
self redrawVisibleLine:visibleLine from:startCol |
|
2070 |
] |
|
2071 |
! |
|
2072 |
||
2073 |
redrawVisibleLine:visLineNr from:startCol |
|
2074 |
"redraw right part of a visible line from startCol to end of line" |
|
0 | 2075 |
|
2076 |
shown ifTrue:[ |
|
105 | 2077 |
self drawVisibleLine:visLineNr from:startCol with:fgColor and:bgColor |
0 | 2078 |
] |
2079 |
! |
|
2080 |
||
2081 |
redrawLine:lineNr col:col |
|
2082 |
"redraw a single character" |
|
2083 |
||
2084 |
|visibleLine| |
|
2085 |
||
2086 |
visibleLine := self listLineToVisibleLine:lineNr. |
|
2087 |
visibleLine notNil ifTrue:[ |
|
59 | 2088 |
self redrawVisibleLine:visibleLine col:col |
0 | 2089 |
] |
2090 |
! |
|
2091 |
||
105 | 2092 |
redrawVisibleLine:visLineNr |
2093 |
"redraw a visible line" |
|
2094 |
||
2095 |
shown ifTrue:[ |
|
2096 |
self drawVisibleLine:visLineNr with:fgColor and:bgColor |
|
0 | 2097 |
] |
2098 |
! |
|
2099 |
||
2100 |
redrawLine:lineNr from:startCol to:endCol |
|
2101 |
"redraw a list line from startCol to endCol" |
|
2102 |
||
2103 |
|visibleLine| |
|
2104 |
||
2105 |
visibleLine := self listLineToVisibleLine:lineNr. |
|
2106 |
visibleLine notNil ifTrue:[ |
|
59 | 2107 |
self redrawVisibleLine:visibleLine from:startCol to:endCol |
0 | 2108 |
] |
2109 |
! |
|
2110 |
||
105 | 2111 |
redrawVisibleLine:visLineNr from:startCol to:endCol |
2112 |
"redraw part of a visible line" |
|
2113 |
||
2114 |
shown ifTrue:[ |
|
2115 |
self drawVisibleLine:visLineNr from:startCol to:endCol with:fgColor and:bgColor |
|
2116 |
] |
|
2117 |
! |
|
2118 |
||
0 | 2119 |
redrawFromLine:lineNr |
2120 |
"redraw starting at linrNr" |
|
2121 |
||
2122 |
|visibleLine first| |
|
2123 |
||
2124 |
shown ifTrue:[ |
|
59 | 2125 |
"if first line to redraw is above 1st visible line, |
2126 |
start redraw at 1st visible line" |
|
2127 |
(lineNr < firstLineShown) ifTrue:[ |
|
2128 |
first := firstLineShown |
|
2129 |
] ifFalse:[ |
|
2130 |
first := lineNr |
|
2131 |
]. |
|
2132 |
visibleLine := self listLineToVisibleLine:first. |
|
2133 |
visibleLine notNil ifTrue:[ |
|
2134 |
self redrawFromVisibleLine:visibleLine to:nLinesShown |
|
2135 |
] |
|
0 | 2136 |
] |
2137 |
! |
|
2138 |
||
212 | 2139 |
redrawInverted |
2140 |
"show contents in reverse colors" |
|
105 | 2141 |
|
2142 |
|savFg savBg| |
|
2143 |
||
2144 |
savFg := fgColor. |
|
2145 |
savBg := bgColor. |
|
2146 |
fgColor := savBg. |
|
2147 |
bgColor := savFg. |
|
2148 |
self redraw. |
|
2149 |
fgColor := savFg. |
|
2150 |
bgColor := savBg. |
|
212 | 2151 |
! |
2152 |
||
2153 |
flash |
|
2154 |
"show contents in reverse colors for a moment - to wakeup the user :-)" |
|
2155 |
||
2156 |
self redrawInverted. |
|
2157 |
(Delay forSeconds:0.1) wait. |
|
105 | 2158 |
self redraw |
212 | 2159 |
|
2160 |
" |
|
2161 |
Transcript flash |
|
2162 |
Transcript redrawInverted |
|
2163 |
Transcript redraw |
|
2164 |
" |
|
105 | 2165 |
! |
2166 |
||
0 | 2167 |
redrawFromLine:start to:end |
2168 |
"redraw lines from start to end" |
|
2169 |
||
2170 |
|visibleFirst visibleLast first last lastLineShown| |
|
2171 |
||
2172 |
shown ifTrue:[ |
|
59 | 2173 |
lastLineShown := firstLineShown + nLinesShown - 1. |
2174 |
(start <= lastLineShown) ifTrue:[ |
|
2175 |
(end >= firstLineShown) ifTrue:[ |
|
0 | 2176 |
|
59 | 2177 |
"if first line to redraw is above 1st visible line, |
2178 |
start redraw at 1st visible line" |
|
0 | 2179 |
|
59 | 2180 |
(start < firstLineShown) ifTrue:[ |
2181 |
first := firstLineShown |
|
2182 |
] ifFalse:[ |
|
2183 |
first := start |
|
2184 |
]. |
|
2185 |
(end > lastLineShown) ifTrue:[ |
|
2186 |
last := lastLineShown |
|
2187 |
] ifFalse:[ |
|
2188 |
last := end |
|
2189 |
]. |
|
2190 |
visibleFirst := self listLineToVisibleLine:first. |
|
2191 |
visibleLast := self listLineToVisibleLine:last. |
|
2192 |
self redrawFromVisibleLine:visibleFirst to:visibleLast |
|
2193 |
] |
|
2194 |
] |
|
0 | 2195 |
] |
2196 |
! |
|
2197 |
||
2198 |
redraw |
|
2199 |
"redraw complete view" |
|
2200 |
||
2201 |
shown ifTrue:[ |
|
59 | 2202 |
self redrawFromVisibleLine:1 to:nLinesShown |
0 | 2203 |
] |
2204 |
! ! |
|
2205 |
||
105 | 2206 |
!ListView methodsFor:'accessing'! |
2207 |
||
2208 |
level:aNumber |
|
2209 |
"set the level - cought here to update text-position variables |
|
2210 |
(which avoids many computations later)" |
|
2211 |
||
2212 |
super level:aNumber. |
|
2213 |
||
2214 |
textStartLeft := leftMargin + margin. |
|
2215 |
textStartTop := topMargin + margin. |
|
2216 |
innerWidth := width - textStartLeft - margin |
|
2217 |
! |
|
2218 |
||
222 | 2219 |
innerHeight |
105 | 2220 |
"return the number of pixels visible of the contents |
120 | 2221 |
- redefined since ListView adds another margin to start the text |
2222 |
somewhat to indented from the 3D border." |
|
105 | 2223 |
|
222 | 2224 |
^ height - (2 * margin) - topMargin |
105 | 2225 |
! |
2226 |
||
2227 |
backgroundColor |
|
2228 |
"return the background color" |
|
2229 |
||
2230 |
^ bgColor |
|
2231 |
! |
|
2232 |
||
2233 |
foregroundColor |
|
2234 |
"return the foreground color" |
|
2235 |
||
2236 |
^ fgColor |
|
2237 |
! |
|
2238 |
||
2239 |
backgroundColor:aColor |
|
2240 |
"set the background color" |
|
2241 |
||
2242 |
bgColor ~~ aColor ifTrue:[ |
|
2243 |
bgColor := aColor. |
|
2244 |
self viewBackground:bgColor. |
|
2245 |
shown ifTrue:[ |
|
2246 |
self clear. |
|
2247 |
self redraw |
|
2248 |
] |
|
2249 |
] |
|
2250 |
! |
|
2251 |
||
2252 |
foregroundColor:color1 backgroundColor:color2 |
|
2253 |
"set both foreground and background colors" |
|
2254 |
||
2255 |
((fgColor ~~ color1) or:[bgColor ~~ color2]) ifTrue:[ |
|
2256 |
fgColor := color1. |
|
2257 |
bgColor := color2. |
|
2258 |
shown ifTrue:[ |
|
2259 |
self redraw |
|
2260 |
] |
|
2261 |
] |
|
2262 |
! |
|
2263 |
||
2264 |
foregroundColor:aColor |
|
2265 |
"set the foreground color" |
|
2266 |
||
2267 |
fgColor ~~ aColor ifTrue:[ |
|
2268 |
fgColor := aColor. |
|
2269 |
shown ifTrue:[ |
|
2270 |
self redraw |
|
2271 |
] |
|
2272 |
] |
|
2273 |
! |
|
2274 |
||
2275 |
partialLines:aBoolean |
|
2276 |
"allow/disallow display of a last partial line" |
|
2277 |
||
2278 |
partialLines := aBoolean. |
|
2279 |
self computeNumberOfLinesShown |
|
2280 |
! |
|
2281 |
||
2282 |
leftMargin:aNumber |
|
120 | 2283 |
"set the margin between the left border and the 1st col" |
105 | 2284 |
|
2285 |
leftMargin := aNumber. |
|
2286 |
textStartLeft := leftMargin + margin. |
|
2287 |
innerWidth := width - textStartLeft - margin |
|
2288 |
! |
|
2289 |
||
120 | 2290 |
topMargin:aNumber |
2291 |
"set the margin between the top border and the 1st line" |
|
2292 |
||
2293 |
topMargin := aNumber. |
|
2294 |
textStartTop := topMargin + margin. |
|
2295 |
! |
|
2296 |
||
105 | 2297 |
leftMargin |
2298 |
"return the margin to left of 1st col" |
|
2299 |
||
2300 |
^ leftMargin |
|
2301 |
! |
|
2302 |
||
2303 |
font:aFont |
|
2304 |
"set the font for all shown text. |
|
2305 |
Redraws everything." |
|
2306 |
||
2307 |
aFont isNil ifTrue:[ |
|
2308 |
^ self error:'nil font' |
|
2309 |
]. |
|
2310 |
font ~~ aFont ifTrue:[ |
|
2311 |
super font:aFont. |
|
2312 |
realized ifTrue:[ |
|
207
ce156302b0ac
invalidate cached widthOfContents when font changes
Claus Gittinger <cg@exept.de>
parents:
196
diff
changeset
|
2313 |
widthOfWidestLine := nil. "/ i.e. unknown |
105 | 2314 |
(font device == device) ifTrue:[ |
2315 |
self getFontParameters. |
|
2316 |
self computeNumberOfLinesShown. |
|
2317 |
shown ifTrue:[ |
|
2318 |
self redrawFromVisibleLine:1 to:nLinesShown |
|
2319 |
] |
|
2320 |
]. |
|
2321 |
self contentsChanged |
|
2322 |
] |
|
2323 |
] |
|
207
ce156302b0ac
invalidate cached widthOfContents when font changes
Claus Gittinger <cg@exept.de>
parents:
196
diff
changeset
|
2324 |
|
ce156302b0ac
invalidate cached widthOfContents when font changes
Claus Gittinger <cg@exept.de>
parents:
196
diff
changeset
|
2325 |
"Modified: 24.11.1995 / 11:17:06 / cg" |
105 | 2326 |
! |
2327 |
||
2328 |
lineSpacing:pixles |
|
207
ce156302b0ac
invalidate cached widthOfContents when font changes
Claus Gittinger <cg@exept.de>
parents:
196
diff
changeset
|
2329 |
"set the lineSpacing - thats an additional number of pixels, |
ce156302b0ac
invalidate cached widthOfContents when font changes
Claus Gittinger <cg@exept.de>
parents:
196
diff
changeset
|
2330 |
by which lines are vertically separated." |
ce156302b0ac
invalidate cached widthOfContents when font changes
Claus Gittinger <cg@exept.de>
parents:
196
diff
changeset
|
2331 |
|
105 | 2332 |
lineSpacing := pixles. |
2333 |
self getFontParameters. |
|
2334 |
! ! |
|
2335 |
||
2336 |
!ListView methodsFor:'initialization'! |
|
2337 |
||
2338 |
create |
|
2339 |
super create. |
|
2340 |
||
2341 |
"I cache font parameters here - they are used so often ..." |
|
2342 |
self getFontParameters. |
|
0 | 2343 |
self computeNumberOfLinesShown. |
105 | 2344 |
fgColor := fgColor on:device. |
2345 |
bgColor := bgColor on:device |
|
2346 |
! |
|
2347 |
||
2348 |
realize |
|
116 | 2349 |
|sz| |
2350 |
||
105 | 2351 |
extentChanged ifTrue:[ |
2352 |
self computeNumberOfLinesShown. |
|
2353 |
]. |
|
2354 |
firstLineShown ~~ 1 ifTrue:[ |
|
116 | 2355 |
sz := self size. |
2356 |
firstLineShown + nLinesShown > sz ifTrue:[ |
|
2357 |
self scrollToLine:sz - nLinesShown. |
|
105 | 2358 |
] |
2359 |
]. |
|
120 | 2360 |
super realize. |
2361 |
self getListFromModel |
|
105 | 2362 |
! |
2363 |
||
2364 |
initStyle |
|
2365 |
super initStyle. |
|
2366 |
||
191
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
2367 |
self topMargin:(self verticalPixelPerMillimeter:0.5) rounded. |
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
2368 |
self leftMargin:(self horizontalPixelPerMillimeter:0.5) rounded. |
5ccbde40bb6b
draw strings half a lineSpacing lower - highlight frames look better
Claus Gittinger <cg@exept.de>
parents:
190
diff
changeset
|
2369 |
|
105 | 2370 |
lineSpacing := 0. |
2371 |
fgColor := DefaultForegroundColor on:device. |
|
2372 |
bgColor := DefaultBackgroundColor on:device. |
|
2373 |
DefaultFont notNil ifTrue:[font := DefaultFont on:device] |
|
2374 |
! |
|
2375 |
||
120 | 2376 |
initialize |
121 | 2377 |
super initialize. |
2378 |
||
113 | 2379 |
viewOrigin := 0@0. |
128 | 2380 |
|
2381 |
textStartTop := topMargin + margin. |
|
105 | 2382 |
|
2383 |
bitGravity := #NorthWest. |
|
2384 |
list := nil. |
|
2385 |
firstLineShown := 1. |
|
2386 |
nFullLinesShown := 1. "just any value ..." |
|
2387 |
nLinesShown := 1. "just any value" |
|
2388 |
leftOffset := 0. |
|
2389 |
partialLines := true. |
|
120 | 2390 |
tabPositions := DefaultTabPositions. |
105 | 2391 |
self getFontParameters. |
2392 |
wordCheck := [:char | char isNationalAlphaNumeric]. |
|
120 | 2393 |
includesNonStrings := false. |
190 | 2394 |
|
2395 |
autoScroll := true. |
|
105 | 2396 |
! |
2397 |
||
118 | 2398 |
defaultControllerClass |
2399 |
self class == ListView ifTrue:[^ ListViewController]. |
|
2400 |
^ super defaultControllerClass |
|
2401 |
! |
|
2402 |
||
105 | 2403 |
recreate |
2404 |
"recreate after a snapin" |
|
2405 |
||
2406 |
super recreate. |
|
2407 |
||
120 | 2408 |
" |
2409 |
recompute margins and font parameters |
|
2410 |
- display may have different resolution/font sizes. |
|
2411 |
" |
|
128 | 2412 |
topMargin := (self verticalPixelPerMillimeter:0.5) rounded. |
2413 |
self leftMargin:(self horizontalPixelPerMillimeter:0.5) rounded. |
|
105 | 2414 |
self getFontParameters |
2415 |
! ! |
|
2416 |
||
2417 |
!ListView methodsFor:'searching'! |
|
2418 |
||
2419 |
searchForwardFor:pattern startingAtLine:startLine col:startCol ifFound:block1 ifAbsent:block2 |
|
2420 |
"search for a pattern, if found evaluate block1 with row/col as arguments, if not |
|
2421 |
found evaluate block2. |
|
2422 |
Sorry, but pattern is no regular expression pattern (yet)" |
|
2423 |
||
2424 |
|lineString col savedCursor patternSize |
|
2425 |
line1 "{Class: SmallInteger}" |
|
118 | 2426 |
line2 "{Class: SmallInteger}" |
2427 |
p realPattern| |
|
105 | 2428 |
|
2429 |
patternSize := pattern size. |
|
2430 |
(list notNil and:[patternSize ~~ 0]) ifTrue:[ |
|
2431 |
savedCursor := cursor. |
|
2432 |
self cursor:(Cursor questionMark). |
|
118 | 2433 |
|
105 | 2434 |
col := startCol + 1. |
2435 |
line1 := startLine. |
|
2436 |
line2 := list size. |
|
118 | 2437 |
|
2438 |
pattern includesMatchCharacters ifTrue:[ |
|
2439 |
p := ''. |
|
2440 |
(pattern startsWith:$*) ifFalse:[ |
|
2441 |
p := p , '*' |
|
2442 |
]. |
|
2443 |
p := p , pattern. |
|
2444 |
(pattern endsWith:$*) ifFalse:[ |
|
2445 |
p := p , '*' |
|
2446 |
]. |
|
2447 |
realPattern := pattern. |
|
2448 |
(realPattern startsWith:$*) ifTrue:[ |
|
2449 |
realPattern := realPattern copyFrom:2 |
|
105 | 2450 |
]. |
118 | 2451 |
line1 to:line2 do:[:lnr | |
2452 |
lineString := list at:lnr. |
|
2453 |
lineString notNil ifTrue:[ |
|
2454 |
"/ first a crude check ... |
|
2455 |
(p match:lineString) ifTrue:[ |
|
2456 |
"/ ok, there it is; look at which position |
|
2457 |
col := lineString findMatchString:realPattern startingAt:col ignoreCase:false ifAbsent:[0]. |
|
2458 |
col ~~ 0 ifTrue:[ |
|
2459 |
self cursor:savedCursor. |
|
2460 |
^ block1 value:lnr value:col. |
|
2461 |
] |
|
2462 |
]. |
|
2463 |
]. |
|
2464 |
col := 1 |
|
2465 |
] |
|
2466 |
] ifFalse:[ |
|
2467 |
line1 to:line2 do:[:lnr | |
|
2468 |
lineString := list at:lnr. |
|
164 | 2469 |
lineString isString ifTrue:[ |
118 | 2470 |
col := lineString findString:pattern startingAt:col ifAbsent:[0]. |
2471 |
col ~~ 0 ifTrue:[ |
|
2472 |
self cursor:savedCursor. |
|
2473 |
^ block1 value:lnr value:col. |
|
2474 |
] |
|
2475 |
]. |
|
2476 |
col := 1 |
|
2477 |
] |
|
105 | 2478 |
] |
2479 |
]. |
|
2480 |
"not found" |
|
2481 |
||
2482 |
self cursor:savedCursor. |
|
2483 |
^ block2 value |
|
2484 |
! |
|
2485 |
||
2486 |
findEndOfWordAtLine:selectLine col:selectCol |
|
2487 |
"return the col of last character of the word at given line/col. |
|
2488 |
If the character under the initial col is a space character, return |
|
2489 |
the last col of the blank-block. |
|
2490 |
Return 0 if we should wrap to next line (for spaces)" |
|
2491 |
||
2492 |
|endCol thisCharacter len| |
|
2493 |
||
2494 |
endCol := selectCol. |
|
2495 |
endCol == 0 ifTrue:[endCol := 1]. |
|
2496 |
thisCharacter := self characterAtLine:selectLine col:endCol. |
|
2497 |
||
2498 |
"is this acharacter within a word ?" |
|
2499 |
(wordCheck value:thisCharacter) ifTrue:[ |
|
2500 |
thisCharacter := self characterAtLine:selectLine col:endCol. |
|
2501 |
[wordCheck value:thisCharacter] whileTrue:[ |
|
2502 |
endCol := endCol + 1. |
|
2503 |
thisCharacter := self characterAtLine:selectLine col:endCol |
|
65 | 2504 |
]. |
105 | 2505 |
endCol := endCol - 1. |
2506 |
] ifFalse:[ |
|
2507 |
"nope - maybe its a space" |
|
2508 |
thisCharacter == Character space ifTrue:[ |
|
2509 |
len := (self listAt:selectLine) size. |
|
2510 |
endCol > len ifTrue:[ |
|
2511 |
"select rest to end" |
|
2512 |
endCol := 0 |
|
2513 |
] ifFalse:[ |
|
2514 |
thisCharacter := self characterAtLine:selectLine col:endCol. |
|
2515 |
[endCol <= len and:[thisCharacter == Character space]] whileTrue:[ |
|
2516 |
endCol := endCol + 1. |
|
2517 |
thisCharacter := self characterAtLine:selectLine col:endCol |
|
2518 |
]. |
|
2519 |
endCol := endCol - 1. |
|
2520 |
] |
|
2521 |
] ifFalse:[ |
|
2522 |
"select single character" |
|
2523 |
] |
|
2524 |
]. |
|
2525 |
^ endCol. |
|
2526 |
! |
|
2527 |
||
2528 |
findBeginOfWordAtLine:selectLine col:selectCol |
|
2529 |
"return the col of first character of the word at given line/col. |
|
2530 |
If the character under the initial col is a space character, return |
|
2531 |
the first col of the blank-block." |
|
2532 |
||
2533 |
|beginCol thisCharacter| |
|
2534 |
||
2535 |
beginCol := selectCol. |
|
2536 |
thisCharacter := self characterAtLine:selectLine col:beginCol. |
|
2537 |
||
2538 |
"is this acharacter within a word ?" |
|
2539 |
(wordCheck value:thisCharacter) ifTrue:[ |
|
2540 |
[wordCheck value:thisCharacter] whileTrue:[ |
|
2541 |
beginCol := beginCol - 1. |
|
2542 |
beginCol < 1 ifTrue:[ |
|
2543 |
thisCharacter := Character space |
|
2544 |
] ifFalse:[ |
|
2545 |
thisCharacter := self characterAtLine:selectLine col:beginCol |
|
2546 |
] |
|
2547 |
]. |
|
2548 |
beginCol := beginCol + 1. |
|
2549 |
] ifFalse:[ |
|
2550 |
"nope - maybe its a space" |
|
2551 |
thisCharacter == Character space ifTrue:[ |
|
2552 |
[beginCol > 1 and:[thisCharacter == Character space]] whileTrue:[ |
|
2553 |
beginCol := beginCol - 1. |
|
2554 |
thisCharacter := self characterAtLine:selectLine col:beginCol |
|
2555 |
]. |
|
2556 |
thisCharacter ~~ Character space ifTrue:[ |
|
2557 |
beginCol := beginCol + 1. |
|
2558 |
]. |
|
2559 |
] ifFalse:[ |
|
2560 |
"select single character" |
|
2561 |
] |
|
65 | 2562 |
]. |
105 | 2563 |
^ beginCol |
0 | 2564 |
! |
2565 |
||
105 | 2566 |
searchBackwardFor:pattern startingAtLine:startLine col:startCol ifFound:block1 ifAbsent:block2 |
2567 |
"search for a pattern, if found evaluate block1 with row/col as arguments, if not |
|
2568 |
found evaluate block2. |
|
2569 |
Sorry, but pattern is no regular expression pattern (yet)" |
|
2570 |
||
2571 |
|lineString col cc found firstChar savedCursor patternSize |
|
2572 |
line1 "{Class: SmallInteger}"| |
|
2573 |
||
2574 |
patternSize := pattern size. |
|
2575 |
(list notNil and:[patternSize ~~ 0]) ifTrue:[ |
|
2576 |
savedCursor := cursor. |
|
2577 |
self cursor:(Cursor questionMark). |
|
2578 |
"/ searchPattern := pattern. |
|
2579 |
col := startCol - 1. |
|
2580 |
firstChar := pattern at:1. |
|
2581 |
col > (list at:startLine) size ifTrue:[ |
|
2582 |
col := nil |
|
2583 |
]. |
|
2584 |
line1 := startLine. |
|
2585 |
line1 to:1 by:-1 do:[:lnr | |
|
2586 |
lineString := list at:lnr. |
|
2587 |
lineString notNil ifTrue:[ |
|
2588 |
col isNil ifTrue:[col := lineString size - patternSize + 1]. |
|
2589 |
[(col > 0) and:[(lineString at:col) ~~ firstChar]] whileTrue:[ |
|
2590 |
col := col - 1 |
|
2591 |
]. |
|
2592 |
[col > 0] whileTrue:[ |
|
2593 |
cc := col. |
|
2594 |
found := true. |
|
2595 |
1 to:patternSize do:[:cnr | |
|
2596 |
cc > lineString size ifTrue:[ |
|
2597 |
found := false |
|
2598 |
] ifFalse:[ |
|
2599 |
(pattern at:cnr) ~~ (lineString at:cc) ifTrue:[ |
|
2600 |
found := false |
|
2601 |
] |
|
2602 |
]. |
|
2603 |
cc := cc + 1 |
|
2604 |
]. |
|
2605 |
found ifTrue:[ |
|
2606 |
self cursor:savedCursor. |
|
2607 |
^ block1 value:lnr value:col. |
|
2608 |
]. |
|
2609 |
col := col - 1. |
|
2610 |
[(col > 0) and:[(lineString at:col) ~~ firstChar]] whileTrue:[ |
|
2611 |
col := col - 1 |
|
2612 |
] |
|
2613 |
] |
|
2614 |
]. |
|
2615 |
col := nil |
|
2616 |
] |
|
2617 |
]. |
|
2618 |
"not found" |
|
2619 |
||
2620 |
self cursor:savedCursor. |
|
2621 |
^ block2 value |
|
2622 |
! ! |
|
2623 |
||
2624 |
!ListView methodsFor:'change and update '! |
|
2625 |
||
2626 |
update:something with:aParameter from:changedObject |
|
2627 |
changedObject == model ifTrue:[ |
|
118 | 2628 |
(aspectMsg notNil |
2629 |
and:[something == aspectMsg]) ifTrue:[ |
|
2630 |
^ self getListFromModel. |
|
105 | 2631 |
]. |
2632 |
]. |
|
2633 |
^ super update:something with:aParameter from:changedObject |
|
2634 |
! ! |
|
2635 |
||
2636 |
!ListView methodsFor:'event processing'! |
|
2637 |
||
0 | 2638 |
redrawX:x y:y width:w height:h |
2639 |
"a region must be redrawn" |
|
2640 |
||
2641 |
|startLine stopLine startCol endCol| |
|
2642 |
||
127 | 2643 |
shown ifFalse:[^ self]. |
2644 |
||
0 | 2645 |
startLine := self visibleLineOfY:y. |
2646 |
stopLine := self visibleLineOfY:(y + h). |
|
2647 |
||
2648 |
"if text-margin is affected" |
|
2649 |
x < textStartLeft ifTrue:[ |
|
59 | 2650 |
self paint:bgColor. |
2651 |
self fillRectangleX:margin y:margin width:(textStartLeft - margin) |
|
2652 |
height:(height - margin - margin) |
|
0 | 2653 |
]. |
2654 |
y < textStartTop ifTrue:[ |
|
59 | 2655 |
self paint:bgColor. |
2656 |
self fillRectangleX:margin y:margin width:(width - margin - margin) |
|
2657 |
height:(textStartTop - margin) |
|
0 | 2658 |
]. |
2659 |
(w > (width // 4 * 3)) ifTrue:[ |
|
59 | 2660 |
"if area is big enough redraw whole lines" |
2661 |
self redrawFromVisibleLine:startLine to:stopLine |
|
0 | 2662 |
] ifFalse:[ |
59 | 2663 |
includesNonStrings ifTrue:[ |
2664 |
startLine to:stopLine do:[:i | |
|
2665 |
self redrawVisibleLine:i |
|
2666 |
] |
|
2667 |
] ifFalse:[ |
|
2668 |
fontIsFixedWidth ifFalse:[ |
|
2669 |
"start/end col has to be computed for each line" |
|
51 | 2670 |
|
59 | 2671 |
startLine to:stopLine do:[:i | |
2672 |
startCol := self colOfX:x inVisibleLine:i. |
|
2673 |
endCol := self colOfX:(x + w) inVisibleLine:i. |
|
2674 |
startCol > 0 ifTrue:[ |
|
2675 |
endCol > 0 ifTrue:[ |
|
2676 |
self redrawVisibleLine:i from:startCol to:endCol |
|
2677 |
] |
|
2678 |
] |
|
2679 |
] |
|
2680 |
] ifTrue:[ |
|
2681 |
"start/end col is the same for all lines" |
|
0 | 2682 |
|
59 | 2683 |
startCol := self colOfX:x inVisibleLine:startLine. |
2684 |
endCol := self colOfX:(x + w) inVisibleLine:startLine. |
|
2685 |
startCol > 0 ifTrue:[ |
|
2686 |
endCol > 0 ifTrue:[ |
|
2687 |
startLine to:stopLine do:[:i | |
|
2688 |
self redrawVisibleLine:i from:startCol to:endCol |
|
2689 |
] |
|
2690 |
] |
|
2691 |
] |
|
2692 |
] |
|
2693 |
] |
|
0 | 2694 |
] |
2695 |
! |
|
2696 |
||
105 | 2697 |
sizeChanged:how |
2698 |
"size changed - move origin up if possible" |
|
2699 |
||
2700 |
|listSize newOrigin| |
|
2701 |
||
2702 |
super sizeChanged:how. |
|
2703 |
self computeNumberOfLinesShown. |
|
2704 |
||
2705 |
innerWidth := width - textStartLeft - margin. |
|
2706 |
shown ifFalse:[^ self]. |
|
2707 |
list isNil ifTrue:[^ self]. |
|
2708 |
||
2709 |
listSize := self numberOfLines. |
|
2710 |
" |
|
2711 |
if we are behond the end, scroll up a bit |
|
2712 |
" |
|
2713 |
((firstLineShown + nFullLinesShown) > listSize) ifTrue:[ |
|
2714 |
newOrigin := listSize - nFullLinesShown + 1. |
|
2715 |
newOrigin < 1 ifTrue:[ |
|
2716 |
newOrigin := 1 |
|
2717 |
]. |
|
2718 |
self scrollToLine: newOrigin. |
|
2719 |
^ self |
|
2720 |
]. |
|
2721 |
! |
|
2722 |
||
0 | 2723 |
keyPress:key x:x y:y |
2724 |
"a key was pressed - handle page-keys here" |
|
2725 |
||
132 | 2726 |
<resource: #keyboard (#PreviousPage #NextPage #HalfPageUp #HalfPageDown |
2727 |
#BeginOfText #EndOfText |
|
2728 |
#ScrollUp #ScrollDown )> |
|
125 | 2729 |
|sensor n| |
2730 |
||
121 | 2731 |
(key == #PreviousPage) ifTrue: [^ self pageUp]. |
2732 |
(key == #NextPage) ifTrue: [^ self pageDown]. |
|
2733 |
(key == #HalfPageUp) ifTrue: [^ self halfPageUp]. |
|
2734 |
(key == #HalfPageDown) ifTrue: [^ self halfPageDown]. |
|
0 | 2735 |
|
121 | 2736 |
(key == #BeginOfText) ifTrue:[^ self scrollToTop]. |
2737 |
(key == #EndOfText) ifTrue:[^ self scrollToBottom]. |
|
2738 |
||
125 | 2739 |
sensor := self sensor. |
2740 |
(key == #ScrollUp) ifTrue:[ |
|
2741 |
sensor isNil ifTrue:[ |
|
2742 |
n := 1 |
|
2743 |
] ifFalse:[ |
|
2744 |
n := 1 + (sensor compressKeyPressEventsWithKey:#ScrollUp). |
|
2745 |
]. |
|
2746 |
^ self scrollUp:n |
|
2747 |
]. |
|
2748 |
(key == #ScrollDown) ifTrue:[ |
|
2749 |
sensor isNil ifTrue:[ |
|
2750 |
n := 1 |
|
2751 |
] ifFalse:[ |
|
2752 |
n := 1 + (sensor compressKeyPressEventsWithKey:#ScrollDown). |
|
2753 |
]. |
|
2754 |
^ self scrollDown:n |
|
2755 |
]. |
|
2756 |
||
0 | 2757 |
super keyPress:key x:x y:y |
2758 |
! ! |