[REBOL] Re: Justifying text
From: carl:cybercraft at: 14-Dec-2002 20:23
On 14-Dec-02, Gregg Irwin wrote:
> Hi Carl,
>> How were you hoping to display the text? Something specific (as
>> apposed to general-purpose) mightn't be that hard to put
>> using a list (perhaps).
> I was thinking, that you could do it yourself, though it would
> probably be hideously slow one way, and complex the other way.
> If you could get the lines, as wrapped, for a face (but I don't know
> that you can as line-list doesn't always seem to be set), then you
> could iterate over them, find the actual width for each line, take
> that from the width you want, giving you a width delta, then count
> words and add (delta/word-count) to each offset, using either draw
> commands or faces. Faces would be bad unless you only need a few.
I've had a quick (yeah, right;) go at it, but my approach is slightly
different. As I said, I thought of using font/space to do the
padding, as this would only require two faces per line, as apposed to
one per word. Anyway, below is (the slightly bugged) result I've
come up with....
rebol []
justify: func [
{This accepts a string and an integer and returns a
block containing 4 values, the values being the left
part of the string and the font/space/x value to use
for justifying it, and the right part of the string
and its font/space/x value.
}
text [string!] "Text to be justified."
width [integer!] "Width to justify in pixels."
/local text-width pad rem
][
face/text: text
if none? text-width: size-text face [text-width: 0x0]
if any [width <= text-width/x text = ""][
return reduce [text 0 "" 0]
]
pad: to-integer width - text-width/x / length? text
rem: remainder width - text-width/x length? text
reduce [
copy/part text rem
either rem = 0 [0][pad + 1]
skip text rem
pad
]
]
lines: [
"This is an"
"attempt at"
"justifying"
"text using"
"REBOL/View."
""
"It is pretty"
"limited but"
"might be of"
"some use to"
"someone if"
"they can"
"debug it..."
]
build-layout: does [
lo: copy [
style txt text para [origin: 0x0 margin: 0x0]
across
space 0x0
]
face/text: " "
space-size: size-text face
foreach line lines [
blk: justify line width
append lo reduce [
'txt copy blk/1 'font reduce [
to-set-word 'space to-pair reduce [blk/2 0]
]
]
; This bit is supposed to pad out spaces and the join
; between the two text faces, but it ain't working
; quite right... (: (The justify function should
; probably work out the padding anyway...)
; ------
padding: 0
if not any [empty? blk/1 empty? blk/3][padding: blk/4]
if " " = back tail blk/1 [
padding: padding + space-size/x + blk/2
]
if " " = blk/3/1 [
padding: padding + space-size/x + blk/4
]
if padding > 0 [append lo reduce ['pad padding]]
; ------
append lo reduce [
'txt copy blk/3 'font reduce [
to-set-word 'space to-pair reduce [blk/4 0]
]
'return
]
]
append lo [button 60 "Close" [unview]]
]
; Get longest line
;------------------
width: 0
foreach line lines [
if line-length: size-text make face [text: line][
width: max width line-length/x
]
]
; Tests
;-------
build-layout
view layout lo
width: width + 20
build-layout
view layout lo
width: width + 40
build-layout
view layout lo
--
Carl Read