195 lines
5.7 KiB
Smalltalk
195 lines
5.7 KiB
Smalltalk
Class {
|
|
#name : #GrafoscopioComposer,
|
|
#superclass : #Object,
|
|
#instVars : [
|
|
'text',
|
|
'styler',
|
|
'container',
|
|
'lines'
|
|
],
|
|
#category : #'Grafoscopio-Rub'
|
|
}
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> actualWidth [
|
|
^ (lines collect: [ :l | l approximateWidth ]) max
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> calculateMaximumAmountOfCharactersToComposeStartingAt: startingY contemplating: delta [
|
|
|
|
| deltaX deltaY |
|
|
|
|
" This method is mean to restrict the amount of text to be processed. For knowing how much of the text is going to be processed, we calculate the size of a minimal character with the default font.
|
|
This strategy is not really the best, since we should check with the smallest font used in the text instead of using the default.
|
|
But by the time being this code should beenough, knowning that for a text drawn in a scrolled area we have almost infinite space. We should mind this bug first then come back .
|
|
|
|
"
|
|
|
|
deltaX := delta + (((styler fontAt: styler defaultFontIndex) linearWidthOf: $.) roundDownTo: 1).
|
|
deltaY := (styler fontAt: styler defaultFontIndex) height.
|
|
|
|
|
|
^ (container width / deltaX) * ((container height - startingY ) / deltaY ).
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> charWidthForCharIndex: idx [
|
|
| font |
|
|
text ifNil: [ ^ 1 ].
|
|
font := styler
|
|
fontAt:
|
|
((text runs at: idx) detect: [ :a | a isKindOf: TextFontChange ])
|
|
fontNumber.
|
|
^ font widthOf: (text at: idx)
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> composeLinesFrom: from to: to [
|
|
| genLines width charWidth lastAdded maxWidth |
|
|
genLines := OrderedCollection new.
|
|
width := 0.
|
|
lastAdded := from.
|
|
maxWidth := container width.
|
|
|
|
from to: to do: [ :i |
|
|
charWidth := self charWidthForCharIndex: i.
|
|
width + charWidth > maxWidth
|
|
ifTrue: [ genLines
|
|
add:
|
|
(GrafoscopioLine new
|
|
from: lastAdded
|
|
to: i - 1
|
|
text: text
|
|
styler: styler;
|
|
yourself).
|
|
lastAdded := i.
|
|
width := 0
|
|
].
|
|
width := width + charWidth
|
|
].
|
|
^ genLines
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> composeLinesFrom: start to: stop delta: delta into: lineColl priorLines: priorLines atY: startingY [
|
|
| maxChars stackedY bounding |
|
|
" we set the lines collection "
|
|
lines := lineColl.
|
|
" we do calculate the size of an average "
|
|
maxChars := self
|
|
calculateMaximumAmountOfCharactersToComposeStartingAt: startingY
|
|
contemplating: delta.
|
|
" we should care about really fragmenting the composittion once we have this assert failling
|
|
should be enough to stop the inspection of the tree nodes once the from > maxChars.
|
|
something like:
|
|
|
|
text allSegmentsOfLinesUpTo: [: from : to | from > maxChars] collect: [ :from :to | GrafoscopioLine new from: from to: to].
|
|
for this we should implement #allSegmentsOfLinesUpTo:collect:
|
|
"
|
|
stackedY := startingY.
|
|
self assert: stop - start < maxChars.
|
|
bounding := container.
|
|
text
|
|
allSegmentsOfLinesDo: [ :from :to |
|
|
| h |
|
|
(self composeLinesFrom: from to: to)
|
|
do: [ :line |
|
|
lines add: line.
|
|
h := line height.
|
|
line
|
|
bounds:
|
|
(bounding origin x @ stackedY
|
|
corner: bounding corner x @ (stackedY + h)).
|
|
stackedY := stackedY + h ] ].
|
|
lines
|
|
ifEmpty: [ lines
|
|
add:
|
|
(GrafoscopioLine new
|
|
from: 1 to: 1;
|
|
bounds: (0 @ 0 corner: 0 @ 0);
|
|
yourself) ]
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> container: aRectangle [
|
|
container := aRectangle
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> cursorWidth: anInteger [
|
|
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> emphasisHere: anObject [
|
|
self assert: (anObject isNil or: [ anObject isArray ])
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> fastFindFirstLineIndexSuchThat: lineBlock [
|
|
"Perform a binary search of the lines array and return the index
|
|
of the first element for which lineBlock evaluates as true.
|
|
This assumes the condition is one that goes from false to true for
|
|
increasing line numbers (as, eg, yval > somey or start char > somex).
|
|
If lineBlock is not true for any element, return size+1."
|
|
| index low high |
|
|
low := 1.
|
|
high := lines size.
|
|
[index := high + low // 2.
|
|
low > high]
|
|
whileFalse:
|
|
[(lineBlock value: (lines at: index))
|
|
ifTrue: [high := index - 1]
|
|
ifFalse: [low := index + 1]].
|
|
^ low
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> lineIndexForPoint: aPoint [
|
|
"Answer the index of the line in which to select the character nearest to aPoint."
|
|
| i py |
|
|
py := aPoint y truncated.
|
|
"Find the first line at this y-value"
|
|
i := (self fastFindFirstLineIndexSuchThat: [:line | line bottom > py]) min: self lines size.
|
|
|
|
"Now find the first line at this x-value"
|
|
[i < self lines size and: [(self lines at: i+1) top = (self lines at: i) top
|
|
and: [aPoint x >= (self lines at: i+1) left]]]
|
|
whileTrue: [i := i + 1].
|
|
^ i
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> lineIndexOfCharacterIndex: characterIndex [
|
|
^ (self
|
|
fastFindFirstLineIndexSuchThat:
|
|
[ :line | line first >= characterIndex and: [ line last <= characterIndex ] ])
|
|
- 1 max: 1
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> lines [
|
|
^ lines ifNil: [ lines := { GrafoscopioLine new }]
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> replaceFrom: anInteger to: anInteger2 with: aCollection [
|
|
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> text [
|
|
^ text
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> text: aCollection [
|
|
text := aCollection
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioComposer >> textStyle: aTextStyle [
|
|
styler := aTextStyle
|
|
]
|