Rebol/View Tips and Techniques

This page is a collection of bits of information that people may find useful when using Rebol/View.

Updating the display

Hiding a field

> I have the following: > > l: layout [ f: field t: text "test"] > hide f > view l > > I expected that the field would be hidden but alas not. How do I hide the > field?

Until the layout has been shown 'hide won't have any effect.

So you could do it this way to keep that face from showing.

view layout [
    f: field with [
        show?: false
    ]
    t: text "test"
]

Once shown 'hide works as expected. e.g

l: layout [ f: field t: text "test"
    button "Hide F" [hide f]
]

view l

Allen Kamp

Hiding self

I suspect that Allen meant something more like:

view l: layout [b: button [b/show?: false unview/all view l]]

Scott Jones

Now if you really want to remove self you can provide your own feel.

At its simplest is..

view layout [
    button "Click me to hide!" 120
    feel [engage: func [f a e][hide f ]]
]

A bit more elaborate

view layout [
   button "Click me to hide!" 120 feel [
        engage: func [face action event][
            switch action [
                down [face/state: on]
                alt-down [face/state: on]
                up [if face/state [hide face exit] face/state: off]
                alt-up [if face/state [hide face exit] face/state: off]
                over [face/state: on]
               away [face/state: off]
            ]
        cue face action
        show face
        ]
    ]
]

Allen Kamp

Text List

What is selected?

> is there a way of seeing which records are selected on a text list??

'picked holds the current list of selected items in a list (ctrl-click for multiple items).

view layout [text-list "A" "B" "C" "D" [print face/picked]]

Allen Kamp

Attributes

Wrap

> Q1. How do you get the text to wrap? eg:

Put the word WRAP in the line.

Layouts

Scrolling views

See below for two methods.

Scrolling Views

Making dynamic layouts

I get asked this question from time to time and there is some insight involved into how VIEW works, so I thought I would post an example to this list for the enlightenment of all:

;This is a template for a blank button
button-layout: layout [button "text" []]

;This is your main VIEW
view layout [
    text "Enter names for some buttons divided by spaces"
    f: field 200
    button "Show me!" [
        ;; first, start off with an empty face to hold the buttons
        button-face: layout []

        ;; keep an offset variable so we know where each button goes
        ofst: 0x0

        ;; Break input from field above into a series of strings
        ;;  and perform some actions on each one
        foreach item parse f/text none [

            ;; The /pane is where sub-faces are stored.
            ;; This adds the modified blank button templates into the
            ;;  blank button face we created above.
            append button-face/pane make button-layout/pane/1 [
                offset: ofst

                ;; Buttons expect their label to be in a field called
                ;;  'texts' which is a block of strings.
                texts: reduce [item]

                ;; The action field determines what will be done when
                ;;  the button is clicked.  The COMPOSE statement
                ;;  reduces only the items in parentheses ().
                action: func [f e] compose [request/ok (item)]
            ]

            ;; Increment the offset for the next button
            ofst: ofst + (button-layout/pane/1/size * 0x1)
        ]

        ;; Set the size for the button-face based on the last offset.
        button-face/size: ofst + button-layout/pane/1/size

        ;; View it!
        view/new button-face
    ]
]

Bo

Your example is elightening, Bo. I'm usually a little too lazy of a VID programmer to redo the work that layout does for me, though, so I generally take a different approach to those kinds of layouts. Here's an alternative way to do the same:

view layout [
     text "Enter names for some buttons divided by spaces"
     f: field 200 (go: [
        buttons: copy [space 0 style bt button [request/ok face/text]]
        foreach item parse f/text none [repend buttons ['bt item]]
        view/new layout/origin buttons 0x0
     ])
     button "Show me!" go
]

The above approach can be called "Meta-programming VID" which means we use REBOL to generate the VID code that we send off to LAYOUT. You see this meta-programming when we use FOREACH to add a BT style to the layout we're constructing for each text peice. In the end we don't have to worry about where anything's placed or how big the window is because that's what layout does for us.

Not all VIEW programming problems are amenable to meta-programming, though. Especially in situations where you have a layout that you are not going to be re-laying out or you have moving and changing faces in a layout-- then directly modifying faces and sizes, offsets and other face facets becomes very necessary. But if you're just going to create a single layout out of some random stuff, why not use metaprogramming?

One other notable difference is instead of reconstructing each button and directly setting its action function separately, we just created a STYLE, BT, which takes care of the same action for all other instances of that style. That's the kind of thing styles are good at taking care of.

Jeff

Jeff shows a very good approach to dynamic layouts. I myself was pleasantly broadened by clever details in his solution of the problem.

The method I show can be extended to handle more complex situations, as Jeff pointed out in his reply. It is Carl's desire that people realize how VID and VIEW faces are interrelated, but not at the expense of added complexity where it is not needed.

Some day someone will write ''10,001 clever methods in REBOL/View''. This will just be scratching the tip of the iceberg. :-)

Bo

Same Layout different windows

> If I want several windows to open but all share the same layout - what is > the best way. > > Create a layout specification block and call layout twice? > Or is there are more preferred approach?

l: does [
    do reduce [
        layout/offset [button "new test layout" [view/new l]]
        to-pair random 100
    ]
]
view l

Cyphre

Printing

Printing a layout

Just do a TO-IMAGE on your View layout, save it as a .png with SAVE/PNG, use BROWSE to browse that image and then click PRINT on the browser! Voila! OK...so I admit it's a hack, but a pretty useful one if I do say so myself! :-)

Bo

Other Info

Segmentation fault

>I try to run run rebol_view on my Debian/Linux Box with libc6. The only >thing I see is an segmentation fault (trying to configure, see the >Demos, etc...).

Make sure you have a file called /etc/termcap, even if it is empty. You can create one easily enough by entering the following at your shell prompt:

touch /etc/termcap

Bo

Stylesheets

Changing styles on the fly

> Can anyone explain me how to change a stylesheet on-the-fly ?

Guess the question is where on-the-fly?

1. You can have as many stylesheets as you want.

2. Layouts can use multiple stylesheets.

3. And finally, stylesheets are just blocks of:

name face

So you can use any series function to modify the stylesheet to insert or remove styles.

Carl Sassenrath

User-friendly scripts

Script Startup

If your script needs to fetch files from the net before it opens a window, it would be good to tell the user about it. Otherwise, the user might think that your script does not work, and run it several times or get frustrated.

Here's an easy way to tell the user:

flash "Downloading files..."
read-thru http://www/file1.jpg
read-thru http://www/file2.jpg
read-thru http://www/file3.jpg
unview

(BTW, note that you don't need to save the result of the read-thru. To get the file later in your script, just use read-thru again and it will be fetched from the disk cache.)

You can also tell the user what's downloading with a function such as:

read-flash: func [url] [
   if not exists-thru? url [
       flash join "Downloading: " url
       read-thru url
       unview
   ]
]

read-flash http://www/file1.jpg

Will help your users to know what's going on. In a future release we will add this capability to script header NEEDS field.

REBOL [
   Title: "A script"
   Needs: [http://www/file1.jpg http://www.file2.jpg]
]

and a downloading message will appear automatically. Would be nice.

Carl Sassenrath

Images

> Does anyone know where to get the image data that > is shown after effects are applied?

view layout [
    pic: image %pondDrop.png effect [colorize 255.0.0] [save/png
        %result.png to-image pic]
]

Cyphre

Keys

Keycodes

Run this code to see the chars and keycodes as you type them (the window must have focus)

REBOL []
key-event: func [face event] [
    if event/type = 'key [
        print mold event/key
    ]
    event
]
insert-event-func :key-event
view layout [
    text {Type and see the char or keycode printed in console}
    button "Remove Event & Close" 200 [
        remove-event-func :key-event unview/all
    ]
]

Allen Kamp

Add to the test script:

print event/shift
print event/control

To tell you these other keys being held down.

Carl Sassenrath