Text box! Usage - qtxie/red GitHub Wiki

Overview

Text Box is a graphic object that represents styled text. It provide support for drawing, cursor navigation, hit testing, text wrapping, alignment, tab expansion, line breaking, etc.

text-box!: object [
    text:       none                    ;-- a string to draw (string!)
    size:       none                    ;-- box size in pixels, infinite size if none (pair! none!)
    font:       none                    ;-- font! object
    para:       none                    ;-- para! object
    ;flow:      'left-to-right          ;-- text flow direction: left-to-right, right-to-left, top-to-bottom and bottom-to-top
    ;reading:   'left-to-right          ;-- reading direction: left-to-right, right-to-left, top-to-bottom and bottom-to-top
    spacing:    none                    ;-- line spacing (integer!)
    tabs:       none                    ;-- tab list (block!)
    styles:     none                    ;-- style list (block!), [start-pos length style1 style2 ...]
    target:     none                    ;-- face!, image!, 
    state:      none                    ;-- OS handles

    ;;
    ;; Query information from text box
    ;;
    offset?: function [
        "Given a text position, returns the corresponding coordinate relative to the top-left of the layout box"
        pos     [integer!]
        return: [pair!]
    ][
        ...
    ]

    index?: function [
        "Given a coordinate, returns the corresponding text position"
        pt      [pair!]
        return: [integer!]
    ][
        ...
    ]

    line-height?: function [
        "Given a text position, returns the corresponding line's height"
        pos     [integer!]
        return: [integer!]
    ][
        ...
    ]

    width?: function [
        "text width in pixel"
        return: [integer!]
    ][
        ...
    ]

    height?: function [
        "text height in pixel"
        return: [integer!]
    ][
        ...
    ]

    line-count?: function [
        "number of lines (> 1 if line wrapped)"
        return: [integer!]
    ][
        ...
    ]
]

Example 1:

ft: make font! [name: "Menlo" size: 12]
txt-box: make text-box! [
    text: "Hello 世界!aBc"
    font: ft
]
view [b: base 300x300 do [b/options: [rich-text?: yes] b/draw: compose [text 60x100 (txt-box)]]]

Example 2:

Set the size of the text-box. By default, the size is infinite.

If the length of the text is larger than the width of the text-box, the text will be wrapped.

ft: make font! [name: "Menlo" size: 12]
txt-box: make text-box! [
    text: "Hello 世界!aBc 123"
    font: ft
    size: 100x300
]
view [b: base 300x300 do [b/options: [rich-text?: yes] b/draw: compose [text 60x100 (txt-box)]]]

Example 3:

Set the styles of the text in text-box. styles is a block!. Styles can overlap and later styles have higher priority.

[
    start-pos length style1 style2 ...        ;-- range 1
    start-pos length style1 style2 ...        ;-- range 2
    ...
]

The following styles are supported:

[
    tuple!                                    ;-- text color
    | backdrop tuple!                         ;-- background color
    | bold                                    ;-- bold font
    | italic
    | underline tuple! (color)  lit-word! ('dash, 'double, 'triple)    ;@@ color and type are not supported yet
    | strike tuple! (color) lit-word! ('wave, 'double)                 ;@@ color and type are not supported yet
    | border tuple! (color) lit-word! ('dash, 'wave)                   ;@@ not implemented
    | font-size integer!
    | font-name string!
]
ft: make font! [name: "Menlo" size: 12]
txt-box: make text-box! [
    text: "Hello 世界!aBc"
    font: ft
    size: 100x300
    styles: [
        1 5 255.0.0 bold italic
        7 3 0.255.0 underline
        10 3 backdrop 200.200.255 font-size 28 strike
    ]
]
view [b: base 300x300 do [b/options: [rich-text?: yes] b/draw: compose [text 60x100 (txt-box)]]]

Example 4:

Query text metrics from the text-box.

ft: make font! [name: "Menlo" size: 12]
txt-box: make text-box! [
    text: "Hello 世界!aBc"
    font: ft
    size: 100x300
    styles: [
        1 5 255.0.0 bold italic
        7 3 0.255.0 underline
        10 3 backdrop 200.200.255 font-size 28 strike
    ]
]
view [
    b: base 300x300 do [b/options: [rich-text?: yes] b/draw: compose [text 60x100 (txt-box)]]
    button "Info" [
        probe txt-box/offset? 3
        probe txt-box/offset? 11
        probe txt-box/index? 10x3
        probe txt-box/line-height? 5
        probe txt-box/line-height? 11
        probe reduce [txt-box/height? txt-box/width? txt-box/line-count?]
    ]
]

Example 5:

Use on-drawing event if you want fine control of the drawing process.

ft: make font! [name: "Menlo" size: 12]
box: make text-box! []
text: "Hello 世界!aBc"
styles: [
    1 5 255.0.0 bold italic
    7 3 0.255.0 underline
    10 3 backdrop 200.200.255 font-size 28 strike
]
view [
    b: base 300x300 on-drawing [
        cmds: [text 0x0 'text-box]

        box/text: text
        box/font: ft
        box/styles: styles
        cmds/3: box
        ;; more code ...

        loop 3 [
            system/view/platform/draw-face b cmds           ;-- drawing on face b
            cmds/2/y: cmds/2/y + box/height?
            random box/text
        ]
    ] do [b/options: [rich-text?: yes] box/target: b] 
]