Tuesday, 31 July 2012

How to block a field

If you need to remove a user to modify the content of a field, you can use the following script:

    Title: "disable face"
    Date: 12-Dec-2001/7:23:24+1:00
    Version: 1.0.0
    File: %disable-face.r
    Author: "Volker Nitsch"
    Usage: "see demo"
    Purpose: "disable and enable face"
    Email: nitsch-lists@netcologne.de
    Web: http://www.escribe.com/internet/rebol/index.html?by=OneThread&t=%5BREBOL%5D%20Changing%20VID%20Styles
    todo: "seperate handling of field/info"
disable-face: func [face'] [
    if 'disabler = face'/parent-face/style [return]
    change find face'/parent-face/pane face' (
        make-face/spec get-style 'image [
            style: 'disabler
            offset: face'/offset size: face'/size
            pane: reduce [
                make system/words/face [
                    size: face'/size
                    color: font: para: text: data: image: none
                    effect: [merge colorize 200.0.0]
    face'/offset: 0x0
    show face'/parent-face
enable-face: func [face'] [
    if 'disabler <> face'/parent-face/style [return]
    face': face'/parent-face
    face'/pane/1/offset: face'/offset
    change find face'/parent-face/pane face' face'/pane/1
    show face'/parent-face
; demo - snip here
view center-face lay: layout [
    rotary "enable" "disable" [
        either face/data = face/texts [
            enable-face hidi
        ] [disable-face hidi ]
    field "field1"
    hidi: field "hidi"
    field "field2"

Monday, 30 July 2012

Stunt Ace game

There is a game for Android, realized with Rebol, look a this:
The programmer made it with:
  • Deluxe Paint on an Amiga
  • GIMP
  • Waldorf Pulse analogue synthesizer
  • TimewARP 2600 analogue soft synth
  • Roland A-90 keyboard
  • A Mac
  • A PC
  • In-house software
Rebol: making things happen

Friday, 27 July 2012

Thursday, 26 July 2012

Directory tree

Dir-tree is a script that create a block containing all files and directories founded recursively from a specified location. Not that with rebol location can be also an FTP site.

>> dir-tree %.
== [%example.txt %example2/ [%example3.gif] %example4.jpg ]

You can specify the maximum depth to the recursive search.

>> dir-tree %temp/ 4

There are other scipts with more advanced functions, like:

But this is simple and powerful, here the source:
    Title: "dir-tree"
    Date: 20-Jun-1999
    Version: 1.0.0
    File: %dir-tree.r
    Author: "Stephane Bagnier"
    Tabs: 4
    Usage: {
        "dir-tree %My-Directory" echoes a block containing the whole
        hierarchy of files and directories starting from %My-Directory.
        The depth refinement allows you to set a maximum depth to the
        recursive search: "dir-tree/depth %My-Directory 3". Note you can
        use 'dir-tree on a ftp site: "dir-tree ftp://www.rebol.com/".
    Purpose: {
        Recursively build a rebol and human readable tree
                from a directory or a ftp site. Maximum depth can be set.
    Organization: "D2SET french association"
    Web-Site: http://www.multimania.com/d2set/
    Email: bagnier@physique.ens.fr
    Need: 2    
dir-tree: func [
    current-path [file! url!] "directory to explore"
    tree [block!] "useful to avoid stack overflow"
    /depth "recursion depth, 1 for current level, -1 for infinite"
    depth-arg [integer!]
    if all [not inner not block? tree] [tree: copy []]
    depth-arg: either all [depth integer? depth-arg] [depth-arg - 1][-1]
    current-list: read current-path
    if not none? current-list [
        foreach item current-list [
            insert tail tree item
            if all [dir? current-path/:item not-equal? depth-arg 0] [
                sub-tree: copy []
                dir-tree/inner/depth current-path/:item sub-tree depth-arg
                insert/only tail tree sub-tree
    return tree

Wednesday, 25 July 2012


I just finished to write my personal Rebol IDE (Integrated development environment).
You can download it from: http://www.rebol.org/view-script.r?script=rebolide.r
It has all rebol function explained!  
If you pass mouse on a button, a tip will show you the meaning of that function.
If click a button, you'll see the usage of that function.
It contains also all rebol colors and all integrated images.
It helps you to keep all variables name!
The Your vars page contains all variables you define, just push the "Update" button. 
It contains all guides!
If  you go to the help menu, you can activate and read guide on Rebol core manual, VID, Events, DRAW, and SHAPE (do you know the shape dialect?).
This tool permit you to test your script (push the GO button).
See the images below and send me you comments!
Next time I want to add syntax highlighting... Stay tuned!

Monday, 23 July 2012

Double click

Rebol interfaces can detect the double click of a mouse, it's the eighth event of a face, look a this example:

view center-face   layout [
bx: box "double-click me ! " green feel [
    engage: func [f a e] [
        if e/8   [
            bx/color: random 255.255.255
            show f
    ] ; engage

Friday, 20 July 2012

Rebol office

I found the following script on www.rebol.org with direction to the Rebol office:

{road directions to the REBOL office from San Francisco:}
To-New-Office: [
[take "Freeway 101" north]
[go north 109 miles]
[turn left at "Gobbi Street"]
[go west .5 miles]
[turn right at "State Street"]
[go north .5 miles]
[turn right at "301 S. State Street"]
[park anywhere]

This is the result:

Visualizza REBOL Office in una mappa di dimensioni maggiori

Is it true?

Thursday, 19 July 2012

Dice roller generator

Hello, I found this script: http://www.rebol.org/view-script.r?script=dice.r
and I supposed that it was interesting creating a dice roller generator for role-playing games like D&D, so I rewrote it and adding a GUI:

Here the source:
Rebol [
    Title: "Dice roller generator"
    File: %dice-roller.r
    Author: "Massimiliano Vessi"
    Date: 2010-12-31
    Version: 1.0.0
    email: maxint@tiscali.it
    Purpose: {From an idea of Adrew Martin a dice rolling generator for
        role-playing game like D&d or D20.}
random/seed now
roll: func [formula [string!] /local temp temp2 result test ] [
    ;test if good formula:
    test: parse formula [integer! "d" integer!]
    either test [
        temp:   parse formula "d"
        temp2:   reduce [(to-integer temp/1)   (to-integer temp/2)]
        result: 0
        loop temp2/1 [result:   result + (random temp2/2)     ]      
        result]["Invalid formula" ]
view/title layout [
    vtext {Type your formula for dice roll (like 2d6) and push "Roll" button.}
    vlab "Formula:"
    aa: field    
    btn "Roll" [
        insert bb/text ( reform [aa/text ":^/" tab (roll aa/text) newline ] )
        show bb
    bb: area    
    ] "Dice roller generator"

Wednesday, 18 July 2012


The following script is a demo showing all Rebol capabilities, with few lines of code (half a page). Nick Antonaccio wrote this script and condensed all in a very obfuscated way:

File: %demo.r
Date: 3-sep-2009
Title: "Demo"
Author: Nick Antonaccio
Purpose: {
Amazingly small REBOL demo app: 10 useful programs in only 2.5k
1 - FREEHAND PAINT: draw and save graphic images
2 - SNAKE GAME: eat food, avoid hitting the walls and yourself
3 - TILE PUZZLE, "15": arrange the tiles into alphabetical order
4 - CALENDAR: save and view events for any date
5 - VIDEO: live webcam video viewer - not just static images
6 - IPs: display your LAN and WAN IP addresses
7 - EMAIL: read emails from any pop account
8 - COUNT DAYS: count the days between 2 selected dates
9 - PLAY SOUNDS: Browse your computer for wave files to play
10 - FTP TOOL: web site editor (browse folders on your server,
click files to edit and save changes back to the server,
create and edit new files etc.)
This example is 100% native REBOL. No external libraries, images,
GUI components, or other resources of any kind are imported. It runs
on Windows, Mac, Linux, and any other OS supported by REBOL/View.
Taken from the tutorial at http://re-bol.com/rebol.html
p: :append kk: :pick r: :random y: :layout q: 'image
z: :if gg: :to-image v: :length? g: :view k: :center-face ts: :to-string
tu: :to-url sh: :show al: :alert rr: :request-date co: :copy g y[style h
btn 150 h"Paint"[g/new k y[s: area black 650x350 feel[engage: func[f a e][
z a = 'over[p pk: s/effect/draw e/offset sh s]z a = 'up[p pk 'line]]]
effect[draw[line]]b: btn"Save" [ save/png %a.png gg s al"Saved 'a.png'"]btn
"Clear" [ s/effect/draw: co[line]sh s]]]h"Game" [ u: :reduce x: does[al join{
[v b]unview]s: gg y/tight[btn red 10x10]o: gg y/tight[btn tan
10x10]d: 0x10 w: 0 r/seed now b: u[q o(((r 19x19)* 10)+ 50x50)q s(((r
19x19)* 10)+ 50x50)]g/new k y/tight[c: area 305x305 effect[draw b]rate 15
feel[engage: func[f a e][z a = 'key [d: select u['up 0x-10 'down 0x10 'left
-10x0 'right 10x0]e/key]z a = 'time[z any[b/6/1 < 0 b/6/2 < 0 b/6/1 > 290
b/6/2 > 290][x]z find(at b 7)b/6[x]z within? b/6 b/3 10x10[p b u[q s(last
b)]w: 1 b/3:((r 29x29)* 10)]n: co/part b 5 p n(b/6 + d)for i 7(v b)1[
either(type?(kk b i)= pair!)[p n kk b(i - 3)][p n kk b i]]z w = 1 [ clear(
back tail n)p n(last b)w: 0]b: co n sh c]]]do [focus c]]]h"Puzzle"[al{
Arrange tiles alphabetically:}
g/new k y[origin 0x0 space 0x0 across style
p button 60x60[z not find [ 0x60 60x0 0x-60 -60x0]face/offset - x/offset[
exit]tp: face/offset face/offset: x/offset x/offset: tp]p"O"p"N"p"M"p"L"
return p"K"p"J"p"I"p"H"return p"G"p"F"p"E"p"D"return p"C"p"B"p"A"x: p
white edge[size: 0]]]h"Calendar" [do bx:[z not(exists? %s)[write %s ""]rq:
rr g/new k y[h5 ts rq aa: area ts select to-block(find/last(to-block read
%s)rq)rq btn"Save" [write/append %s rejoin[rq" {"aa/text"} "]unview do bx]]
]]h"Video" [wl: tu request-text/title/default"URL:"join"http://cam.luzern.org/axis-cgi/jpg/image.cgi?resolution="
"640x480"g/new k y[image load wl 640x480 rate 0 feel[engage: func[f a e][
z a = 'time [ f/image: load wl show f]]]]]h"IPs" [ parse read tu join"http://"
"guitarz.org/ip.cgi"[thru]i: last parse my none
al ts rejoin [ "WAN: "i" -- LAN: "read join dns:// read dns://]]h"Email"[
g/new k y[mp: field"pop://user:pass@site.com"btn"Read" [ma: co[]foreach i
read tu mp/text[p ma join i"^/^/^/^/^/^/"editor ma]]]]h"Days"[g/new k y[
btn"Start" [ sd: rr]btn"End" [ed: rr db/text: ts(ed - sd)show db]text{Days
db: field]]h"Sounds" [ps: func[sl][wait 0 rg: load sl wf: 1 sp:
open sound:// insert sp rg wait sp close sp wf: 0]wf: 0 change-dir
%/c/Windows/media do wl: [ wv: co[]foreach i read %.[z %.wav = suffix? i[p
wv i]]]g/new k y[ft: text-list data wv[z wf <> 1[z error? try[ps value][al
"Error"close sp wf: 0]]]btn"Dir" [ change-dir request-dir do wl ft/data: wv
sh ft]]]h{FTP}[g/new k y[px: field"ftp://user:pass@site.com/folder/"[
either dir? tu va: value[f/data: sort read tu va sh f][editor tu va]]f:
text-list[editor tu join px/text value]btn"?"[al{Type a URL path to browse
(nonexistent files are created). Click files to edit.}

Don't you believe it? See these images


Game (Snake)
Puzzle (Arrange Tile in Alphabetical order)




Days between two dates

Play sounds


Monday, 16 July 2012

Rebol open-source?

Today I received this message: "Rebol source code is to be released very soon. However there will be conditions precedent to the release."

Keep finger crossed!

Friday, 13 July 2012

VID tips and tricks

I found this guide: http://www.pat665.free.fr/gtk/rebol-view.html.
So I think that it is better to copy here:
Author: pat665
Date: 30-juin-2004


1. Introduction

This is a collection of "good-to-know" information about Rebol/View and VID. Some are mine, most are from the Rebol-List, books or articles about Rebol.

2. 3002-As-pair and to-pair


To-pair as a new friend: As-pair. Reading the new document about the Draw dialect, I found a new function 'as-pair.
>> help as-pair

Combine X and Y values into a pair.
AS-PAIR is a function value.

x -- (Type: number)
y -- (Type: number)

This seems to be more useful than to-pair. It is simpler to work with:
; direct value
>> as-pair 2 5
== 2x5
; variables
>> x: 3
== 3
>> as-pair x x * 2
== 3x6
>> as-pair x 2 * x
== 3x6
>> to-pair 2 5
== 5
>> to-pair [2 5]
== 2x5
>> to-pair reduce [x x * 2]
== 3x6

3. 3004-An example of using the alpha chanel from Cyphre

An example of using the alpha channel from Cyphre.
site: http://www.rebol.com/view
x: 0
d: 5
view center-face layout [
    origin 0x0
    image site/nyc.jpg 300x300
    at 0x0 ;same position
    image site/bay.jpg 300x300 rate 30 feel [
            engage: func [f a e][
            x: x + d
            if x > 250 [d: -5]
            if x < 5 [d: 5]
            f/effect: compose [fit alphamul (x)]
            show f

Here is a simple example how to use DRAW dialect for "painting" into alpha channel of the image. I think with the function make-alpha (bellow in the example) you can draw almost any kind of transparent shape though it is not the fastest method....IMO the possibility to use DRAW pens for alpha channel should be done at Rebol's native level...

make-alpha: func [fx img /local idx][
      append fx 'grayscale
      fx: to-block mold to-image make face [
          size: img/size
          effect: fx
          edge: none
     fx: fx/3/2
img: to-block mold img
      idx: 0
remove-each i fx [
          idx: idx + 1
            either idx > 1 [
              if idx = 3 [idx: 0]
     append img/3 fx
     return do load img
 pic: load-thru/binary http://www.rebol.com/view/bay.jpg
   view center-face layout [
      backdrop effect reduce ['gradient red orange]
      image make-alpha [
          gradient 1x1 0.0.0 255.255.255
         draw [
             pen 0.0.0
             fill-pen 200.200.200
            circle 100x80 50
            fill-pen 0.0.0
            box 80x80 125x125
         ] pic

Note from Cyphre Hello to myself, just little correction: You can use the make-alpha function not only with DRAW but with any other effect-block command (like the transparent gradient in the example) ..and little note: this script need at least Rebol/View version 1.2.5 and up or Rebol/Link from the version where alpha-channel support was added.

4. 3005-How to change the aspect of a box with effect?

How to change the aspect of a box with effect?
Rebol []
a: load-image http://www.rebol.com/view/nyc.jpg
luma-fxblock: [luma 80]
grey-fxblock: [grayscale]
reduce [ 'colorize yellow]
view center-face layout [
  b1: box 100x100 a effect []
  b2: box 100x100 a effect []
  b3: box 100x100 a effect []
  b4: box 100x100 a effect []
  btn 100 "luma" [ insert b2/effect copy luma-fxblock show b2 ]
  btn 100 "greyscale" [insert b3/effect copy grey-fxblock show b3 ]
  btn 100 "colorize" [insert b4/effect copy color-fxblock show b4 ]
  btn 100 "reset" [remove b2/effect   remove b2/effect   show b2 ]
  btn 100 "reset" [remove b3/effect   show b3 ]
  btn 100 "reset" [remove b4/effect   remove b4/effect   show b4 ]

5. 3006-How to change the font of a button?

How to change the font of a button?

Rebol []
view center-face layout [
    b: button "Font Test" font [
      name: "Arial"
      size: 12
    abutton: button "rebol is cool" 150x30 [
        face/font: either ((face/font) = font-a) [:font-b][:font-a]
        show face
        do [
        font-a: make abutton/font [ size: 12 ]
          font-b: make font-a [size: 18 ]
          abutton/font: font-a
          button "Change" [b/font/name: "Times" b/font/size: 18 show b ]

6. 3007-How to change the style of a button?

How to change the style of a button?
Rebol []
view center-face layout [
    style btn1 button green
    a: btn1
    b: btn1 "ok" [unview ]  

7. 3008-How to change the windows title

How to change the windows title?
lay: layout/size [
    btn "Title 1" [set-face lay "Bye everybody !"]
    btn "Title 2" [set-face lay "Ok I stay here"]
    ] 300x100
    lay/access: make lay/access [
        set-face*: func [face value] [face/text: value face/changes: 'text ]
view/title center-face lay "Hello world"

8. 3009-How to create draw buttons?

How to create draw buttons?

8.1. Creating a draw button

Simple shaped buttons can be designed with the draw dialect.
view center-face layout [
  box 24x24 effect [draw [
      pen black
      fill-pen red
      circle 12x12 10

This code produce a red filled circle. However this is more an image than a button because there is no action.

8.2. Adding action

As for any face, action for the right clic is provided in a block, example: [ print "hey, I'm clicked!"].
Defining a draw-button style helps us to save typing.
Rebol []
draw-layout: [
    h2 "Draw buttons"
    style draw-button box 24x24 effect [
        draw [ pen black fill-pen red circle 12x12 10]
    draw-button [print "hey, I'm clicked!"]
    draw-button [print "hey, I'm clicked!"]
    draw-button [print "hey, I'm clicked!"]
    draw-button [print "hey, I'm clicked!"]
view center-face layout draw-layout

9. 3011-How to hide a face when view is called?

How to hide a face when view is called?
The purpose here is to have a face invisible when the layout is displayed the first time by view. The answer is to set face/show? to false. Use show to set the face visible again An example:
Rebol []
example: layout [
  a: button  
  button "Hide" [hide   a ]
  button "Show" [show a]
a/show?: false
view example

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

11. 3013-How to navigate through window-pane?

How to navigate through window/pane? What I am looking for is a way to navigate through window/pane to change some faces without the need of a variable. For example, with a layout composed of a,b,c,d,e I would like that a click on b will change c. In other words, knowing one face, being able to move to the next or the previous face.
var class="dt-cmt">; a simple layout
lay: layout [
  text "Hello"
  button "Test" [mytest face]
; explore lay/pane
mytest: func [f [object!] /local f2 ][
  ; here an object
  foreach face lay/pane [ print [face/style type? face] ]  
  ; here a block
  f2: first find lay/pane f
  print [f2/style type? f2]  
  view center-face lay

11.1. From Romano

var class="dt-function">view layout [
  style bt button [
      value: next find face/parent-face/pane face
      face: first either tail? value [head value][value]
    print face/offset
    bt bt bt bt bt ]

The parent-face is set only after view function has been called (= the layout function does not set it).

11.2. From Brett

In face, the Pane of a face can be one of three types:
  1. face/pane can be set to Object! - In this case the pane contains a single face. A face inside a face.
  2. face/pane can be set to Block! - In this case the pane is a collection of faces. More than one face inside a face.
  3. face/pane can be a Function! - In this case the face is iterated. "Virtual" faces that are calculated dynamically. Examples of this last one in VID is List and Text-list.
You need something to identify the face in the layout. One way is by position. If the faces are A, B, C then B would be the second face in the layout.
view lay: layout [
  text "A"
  text "B"
  text "C"
  button   "Second face" [print lay/pane/2/text]

Or instead of navigating when you need to change, you set up a reference early - assuming your layout does not change:
lay: layout [
box "A"
box "B"
box "C"
button "Change" [ if face/user-data [
    face/user-data/color: get first head reverse [blue green]
    show face/user-data
    ] ] ]  
; Make the user-data field of button refer to the "B" text face.
lay/pane/4/user-data: lay/pane/2  
view center-face lay

The third way is to search through every time looking for some identifying information. Remember though that if you have things like panels you will have a tree of faces with the top layout being the root. So you might need to search recursively. I made some functions to do this searching. Note that they cannot find the "iterated" faces.
cc: http://www.codeconscious.com/rebsite/rebol-library/face-searches.r
do load-thru cc  
change-color: func [face] [
  face/color: random 255.255.255
view/new lay1: layout [
  style box box 50x50
  text "A"
  box "B"
  box "C"
  text "D"
  panel orange [box "E"]
  button "Change D" [show change-color find-face [face/text = "D"] ]
  button "Change E" [show change-color find-face [face/text = "E"] ]
view/new lay2: layout/offset [
box "D"
button "Change Boxes" [ repeat face find-faces [ all [in face 'style face/style = 'box] ] [change-color face] show lay1 show lay2   ]
  button "Close All" [unview/all]
  ] add 2x1 * lay1/offset 1x0 * lay1/size  

These are some ways to avoid using variables. A lot of the time variables are very useful and make understanding the code easier. You can variables in their own contexts to avoid cluttering up the global context or clashes between windows if you have more than one. Here is an example wishes uses this concept.
var class="dt-cmt">; Create a template spec
spec: [
  box-face: none
  lay: layout [
      box-face: box gray
      button "Change" [
          box-face/color: random 255.10.10
      show box-face
      ] ] ]  
; Create multiple layout faces in their own contexts.
context-collection: copy []
current-offset: 50x150
repeat i 5 [
  ; Create a new layout face
  ctx: context spec  
  ; Add it to our collection
  append context-collection ctx  
  ; Reposition it.
  ctx/lay/offset: current-offset  
  ; Move our offset ready for the next
  current-offset/x: current-offset/x + 20 + ctx/lay/size/x  
  ; View it
  view/new ctx/lay
; Close and Change all.
view/new layout/offset [
  space 0x0
  origin 0x0
  button "Change All" [
      repeat ctx context-collection [
          ctx/box-face/color: random 10.255.10
    show ctx/lay
    ] ]
      button "Close All" [unview/all] ] 50x50  
      ; Process events

12. 3014-How to simulate action on one button?

How to simulate action on one button? I'd like to get the same effect as if I had done a mouse click on one button, but this "action" is originated from script itself.

If you create a reference to the face (e.g. my-btn: button), then you can do this:
click-face: func [face][face/feel/engage face 'down none ]

12.1. Other solutions...

view layout [
  b: button "Test" [print "Test pressed"]
  button "Action 2" [b/action b none]

var class="dt-function">view layout [
  b: button "Test" [print "Test pressed"]
  button "In" [b/state: true show b]
  button "Out" [b/state: false show b]
  a: button "Action" [
    b/feel/engage :b 'down none
    b/feel/engage :b 'up none
    a/state: false
    show a ; Not sure why this line is needed...

The "Action" button probably gives you the effect you want, but I'm not sure if it's the best way to do it. If the final line is missing the "Action" button itself stays down for reasons I don't understand, though it's maybe because it's sharing the engage function.

13. 3015-Iterate through the faces of a layout

How to iterate through the faces of a layout?
When you create a layout such as layout puts the set words into face/var So you can iterate through the pane faces and find them out.
lay: layout [
  my-button: button
  my-field: field
foreach face lay/pane [
  print [face/var face/style face/offset face/size   ]

If you want to see the words inside a face, use:
print mold first face
Anton. Every face (like a radio) added to a window is appended to the block window/pane. The group is in the field 'related of the radio face. The variable name is in the field 'var of the radio face.

>> w: layout [
 r1: radio of 'groupe1
 r2: radio of 'groupe1
 r3: radio of 'groupe1
>> foreach x w/pane [print [x/var x/related]]
== r1 groupe1
 r2 groupe1
 r3 groupe1

>> lay: layout [
  my-button: button
 my-field: field
>> foreach face lay/pane [ print [type? face face/var face/style face/offset face/size] ]
== object my-button button 20x20 100x24
  object my-field field 20x52 200x24

14. 3016-VID styles

How to get all the VID styles?
vid-styles: copy []
pad-string: "               "
cpt: 0  
foreach [style x] system/view/vid/vid-styles [append vid-styles style]
sort vid-styles  
foreach v vid-styles [
  style: mold v
  cpt: cpt + 1
  either cpt < 6 [ prin [style copy/part pad-string (15 - length? style)] ][print style cpt: 0 ]    
  print " "

Here the standard result:
  • ANIM
  • AREA
  • BAR
  • blank-face
  • BODY
  • BOX
  • BTN
  • CODE
  • face
  • H1
  • H2
  • H3
  • H4
  • H5
  • ICON
  • INFO
  • KEY
  • LAB
  • LBL
  • LED
  • LIST
  • TEXT
  • TOG
  • TT
  • TXT
  • VH1
  • VH2
  • VH3
  • VH4
  • VLAB

15. 3017-Keyboard shortcuts

How to use keyboard shortcuts?
Just use the key
view layout [
  text "Press Enter or Esc"  
  key enter [alert "You pressed Enter"]  
  key escape [alert "you pressed Escape"]  

16. 3018-Resizing an image

The trick is to use 'layout to perform the resizing. Example:
var class="dt-set-word">img: load %my-image.png
img2: to-image layout [origin 0 image 50x50 img]
save/png %my-image2.png img2

17. 3019-Screen size

How to get the screen size?

>> system/view/screen-face/size
== 1024x768

TIP! This information comes from the center-face function source.
>> source center-face
== center-face: func [
   {Center a face on screen or relative to another face.}
   obj [object!]
   /with "Center relative to a face." face [object!]
   if none? face [face: any [obj/parent-face system/view/screen-face]]
   obj/offset: max 0x0 face/size - obj/size / 2 + either with [face/offset] [0x0]

18. 3020-How to create a bmp file from an image

How to create a bmp file from an image?
view center-face layout [
x: box snow 201x201 effect reduce [ 'gradient 0x1 164.200.255 'grid 8x8 0x0 0.0.0 ]  
button "save" [save/bmp %grid.bmp to-image x]

19. 3021-Selections with list

How to get the selected items of a list?
view layout [
text-list data ["one" "two" "three"] [print face/picked]]

To select more than one, just use the CTRL button.

20. 3022-Stylize/master

An example using stylize/master.
to-width: func [x] [75 + 8 * x - 8 ]  
stylize/master [
  ;     VID types
  lbl: lbl blue to-width 1
  field: field to-width 1
  date-field: field [
      if not empty? face/text [
        either none? attempt [to-date face/text] [
            clear face/text ] [face/text: form to-date face/text show face ]
  ;     Derived types
  lab-address: lbl "Address:"
  fld-address: field to-width 3
  lab-date:     lbl "Date:"
  fld-date:     date-field
  lab-code:     lbl "Code:"
  fld-code:     field
view center-face layout [

22. 3024-Usage of with in VID

Answers to a post of mine regarding 'with. Here is the test code:
draw-layout: [
  h2 "Draw buttons"  
  style draw-button box 24x24 with [ effect:   [draw [
      pen black
      fill-pen user-data
      circle 12x12 10
  r-btn: draw-button user-data red [print "hey, I'm red"]
  b-btn: draw-button user-data blue   [print "hey, I'm blue"]
  y-btn: draw-button user-data yellow [print "hey, I'm yellow!"]
  g-btn: draw-button user-data green   [print "hey, I'm green!"]
view center-face layout draw-layout

22.1. Answer from Brett

Could someone tell me more about this "magic" with ?... All REBOL/View faces are objects. VID and LAYOUT are used to create this object but using a simpler more powerful way to express how to create them. So LAYOUT [ button ] will create an object for the button (it will also create another for the window but lets ignore that for the moment).
When you use LAYOUT [button red] an object is created but this time with a colour of Red.
The VID language and LAYOUT translate the "red" into an action of setting the face's colour facet to red.
WITH is part of the VID language that allows you to specify the facets using a normal REBOL object specification.
So the object that is created has this specification applied to it.
For example, instead of LAYOUT [button red] you could write
layout [button with [color: red] ]

As you can see [button red] is easier, but the advantage of WITH is that you can create entirely new facets using it.
For example,

>> layout [btn: button with [my-special-facet: "Brett"]]
>> btn/my-special-facet
== "Brett"

>Why effect is now a set-word! ? Vid styles are objects too. When you use
layout [style draw-button box 24x24]
You are creating another style object, one which is based on the box style. When Romano used WITH in creating a style he was using a normal REBOL object specification to change the facets (object fields) of the style. This is why EFFECT became a set-word.
> Why is it no more needed in "user-data red"? The style that was created now has this EFFECT. Every face based on that style will have the same EFFECT by default. The EFFECT block refers to USER-DATA which is a built-in facet of every VID style. USER-DATA is a VID keyword and built-in facet.
For example

>> layout [btn: button user-data "Brett"]
>> btn/user-data
== "Brett"

As you can see just like setting the colour we can set USER-DATA just as easily.
> I was asking myself the same questions, when Anton stabbed me in the back with an even more puzzling code with a "little dialect using the words facet". ...
As it seems to me, words is a face/facet used to define a face behaviour in the form of a function.
In this function, new is the object face, while args is a block like [fill 255.0.0 [print "hey, I'm red"]].
The "next args" part is a bit of a puzzle, because it cannot be removed or the face is not displayed correctly.
Pretty close.
Yes WORDS is a facet, but it is used during LAYOUT *only* not during the display of the face. It is a way that more keywords can be added to VID so that your custom styles can have their own specific VID keywords. So what Anton has done is to create a new keyword FILL that is valid for the DRAW-BUTTON style.
When LAYOUT processes this specification [draw-button fill red ] it executes the WORDS of DRAW-BUTTON to process the FILL keyword.
Its goal seems to return whatever is left to be processed to finish the face display.
Yes whatever is left needs to be given back so that LAYOUT can process other attributes and facets after the FILL (and its data). This is an advanced technique. But as you can see it is very powerful.
Using WITH to make custom facets and WORDS to add custom VID keywords you can create altogether new VID styles that are very easy to specify. I hope this helps. Brett.

22.2. Answer from Romano

Could someone tell me more about this "magic" with ? why is it no more needed in "user-data red"?
Why effect is now a set-word! ?
All the magic is relative to object and binding of words. When you define an object starting from a previous object:
ob: make object! [a: 1] make ob [a: 2]
you assign a new value (2) to the word 'a of the object: this can happen because the word 'a in the block is bound to the word 'a in the object before executing the block.
The sequence of operations is:
  1. duplicate object ob and its context
  2. bind the block [a: 2] to the new context
  3. evaluate the block [a: 2]

Now in 3) when you change the value of 'a in the block, you really change the value of 'a in the object.
The point is that words are not variable, they have not a value, they are alphanumeric pointers to context, which are "invisible" structure created by make object! (not only).
The 'with word of Vid is a shortcut for something like this, only 'ob is the style face and the block is the 'with block. The 'effect word of Vid, instead, does not bind the block to the object context, only assign the block to the effect field.
Effect [draw [pen user-data]] is like:

new-face: make face []
new-face/effect: [draw [pen user-data]]

with [effect: [draw [pen user-data]]]
is like
new-face: make face [effect: [draw [pen user-data]]]
only in the latter case the block is bound to the face object before executing.
Ciao Romano

23. 3025-[VID] How to reset guide?

How to reset guide?
I have the following layout:
view layout [
  a: txt "test1"
  b: txt "test2"
  c: txt "test3"
  d: txt "test4"

And I want to be 'd in line with 'a. How do I get rid of the 'guide once set?
I just want to disable it until the next 'guide happens.
I never actually use guide, but this seems to give you what you want...
view layout [
  a: txt "test1"
  b: txt "test2"
  c: txt "test3"
  d: txt "test4"
  e: txt "test5"

Hope that helps.

24. 3001-Clear-fields - how to improve it?

Hi All, CLEAR-FIELDS is one of those really handy functions that annoys me. :\
It's very useful, but also problematic in that it only clears FIELD faces, not AREAs; much less CHECK, RADIO, etc. *and* it only works if a field contains a SERIES! value.
Admittedly, coming up with a completely general solution would probably add lots of code, but can it be made better without too much effort and added code?
I think so, but I'm not sure how far to go, assuming we want to submit the improved version to RT for future inclusion. Here's the standard version:
clear-fields: func ["Clear all text fields faces of a layout." panel [object!] ][
  if not all [in panel 'type panel/type = 'face] [exit]
  foreach face panel/pane [
      if all [series? face/text flag-face? face field] [clear face/text face/line-list: none ]

This one works for AREAs as well, and sets non-series values to NONE:
clear-fields: func ["Clear all text fields faces of a layout." panel [object!] ][
  if not all [in panel 'type panel/type = 'face] [exit]
  foreach face panel/pane [
      if any [flag-face? face field   flag-face? face area][
        either series? face/text [
        clear face/text face/line-list: none ][face/text: none ]

This one does the same as above, but tries to MAKE the type of value that's in the field. E.g. numeric fields would reset to 0:
clear-fields: func ["Clear all text fields faces of a layout." panel [object!] ][
  if not all [in panel 'type panel/type = 'face] [exit]
  foreach face panel/pane [
      if any [flag-face? face field   flag-face? face area][
        either series? face/text [
        clear face/text face/line-list: none ][face/text: attempt [make face/text none ] ] ] ] ]

Beyond these simple kinds of changes, should we directly add support for CHECK, RADIO, etc. or is it better to adopt a more general approach, e.g. using a dialected block as a parameter, that you use to reset the display in your app?
The latter approach makes it more effort to use, but potentially much more useful as well. Any thoughts, or other implementations would be welcome.
-- Gregg

25. 3003-Button with on-off texts

How to change a button text depending on the on/off state?
Just add ontherstring:
view layout [button   "Normal" "Pressed" ]

26. 3010-How to get to a field variable by its string name?

How to get to a field variable by its string name?
; Here we have 4 fields 'fv1, 'fv2, 'fv3, 'fv4
; The idea is to get one by its number
; building the litteral name, like "fv1"  
change-fv: func [/local i n s w f ][
  n: random 4
  ; build a word from the string "fv" + n
  w: to-word rejoin ["fv" n]  
  ; get the global variable attached/bind the w
  f: get :w  
  ; it works ! ! !
  f/text: "Changed"
  show f
fav: layout [
  style fv text 200 "text"  
  fv1: fv "A"
  fv2: fv "B"
  fv3: fv "C"
  fv4: fv "D"  
  btn-enter 60 "test" [change-fv]  
  ] ; layout  
  view center-face fav