So I think that it is better to copy here:
Author: pat665
Date: 30-juin-2004
Contents
- 1. Introduction
- 2. 3002-As-pair and to-pair
- 3. 3004-An example of using the alpha chanel from Cyphre
- 4. 3005-How to change the aspect of a box with effect?
- 5. 3006-How to change the font of a button?
- 6. 3007-How to change the style of a button?
- 7. 3008-How to change the windows title
- 8. 3009-How to create draw buttons?
- 9. 3011-How to hide a face when view is called?
- 11. 3013-How to navigate through window-pane?
- 11.1. From Romano
- 11.2. From Brett
- 12. 3014-How to simulate action on one button?
- 12.1. Other solutions...
- 13. 3015-Iterate through the faces of a layout
- 14. 3016-VID styles
- 15. 3017-Keyboard shortcuts
- 16. 3018-Resizing an image
- 17. 3019-Screen size
- 18. 3020-How to create a bmp file from an image
- 19. 3021-Selections with list
- 20. 3022-Stylize/master
- 22. 3024-Usage of with in VID
- 23. 3025-[VID] How to reset guide?
- 24. 3001-Clear-fields - how to improve it?
- 25. 3003-Button with on-off texts
- 26. 3010-How to get to a field variable by its string name?
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
INFOTo-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
USAGE:
AS-PAIR x y
DESCRIPTION:
Combine X and Y values into a pair.
AS-PAIR is a function value.
ARGUMENTS:
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
INFOAn example of using the alpha channel from Cyphre.
Rebol[]
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...
Rebol[]
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]
true
][false]
]
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?ANSWER:
Rebol []
a: load-image http://www.rebol.com/view/nyc.jpg
luma-fxblock: [luma 80]
grey-fxblock: [grayscale]
color-fxblock:
reduce [ 'colorize yellow]
view center-face layout [
across
b1: box 100x100 a effect []
guide
b2: box 100x100 a effect []
b3: box 100x100 a effect []
b4: box 100x100 a effect []
return
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 ]
return
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?ANSWER:
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?ANSWER:
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?ANSWER:
Rebol[]
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?ANSWER:
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]
]
across
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?ANSWER:
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
Or
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.ANSWER:
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:- face/pane can be set to Object! - In this case the pane contains a single face. A face inside a face.
- face/pane can be set to Block! - In this case the pane is a collection of faces. More than one face inside a face.
- 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.
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 [
across
box "A"
box "B"
box "C"
return
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
face
]
view/new lay1: layout [
style box box 50x50
across
text "A"
box "B"
box "C"
text "D"
panel orange [box "E"]
return
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
do-events
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
do-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.ANSWER
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
- ARROW
- BACKDROP
- BACKTILE
- BANNER
- BAR
- BASE-TEXT
- blank-face
- BODY
- BOX
- BTN
- BTN-CANCEL
- BTN-ENTER
- BTN-HELP
- BUTTON
- CHECK
- CHECK-LINE
- CHECK-MARK
- CHOICE
- CODE
- DROP-DOWN
- face
- FIELD
- H1
- H2
- H3
- H4
- H5
- ICON
- IMAGE
- INFO
- KEY
- LAB
- LABEL
- LBL
- LED
- LIST
- LOGO-BAR
- PANEL
- PROGRESS
- RADIO
- RADIO-LINE
- ROTARY
- SCROLLER
- SENSOR
- SLIDER
- TEXT
- TEXT-LIST
- TITLE
- TOG
- TOGGLE
- TT
- TXT
- VH1
- VH2
- VH3
- VH4
- VLAB
- VTEXT
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]
obj
]
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 [
across
lab-address
fld-address
return
lab-date
fld-date
lab-code
fld-code
]
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
]]]
across
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:
- duplicate object ob and its context
- bind the block [a: 2] to the new context
- 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]]
instead:
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?QUESTION
I have the following layout:
view layout [
across
a: txt "test1"
guide
b: txt "test2"
return
c: txt "test3"
return
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.
ANSWER
I never actually use guide, but this seems to give you what you want...
view layout [
across
a: txt "test1"
guide
b: txt "test2"
return
c: txt "test3"
return
guide
a/offset
d: txt "test4"
return
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]
unfocus
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]
unfocus
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]
unfocus
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?ANSWER
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
]
;cf
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
No comments:
Post a Comment