Is it possible to use make
command to create gui object
in Red/Rebol. I tried following:
view [
do [guiobj: make object! [
t: text "text"
f: field "fld"
b: button "button" ] ; end make object
obj1: make guiobj
obj2: make guiobj ] ; end do
below
obj1
obj2 ] ; end view
But I get following error:
*** Script Error: field has no value
*** Where: f
*** Stack: view layout do-safe
*** Script Error: VID - invalid syntax at: [obj1 obj2]
*** Where: do
*** Stack: view layout cause-error
I know compose
can be used but can above code be made to work using make
and object
commands?
According to the documentation: Face objects are clones of face! template object.
It's possible to build up UIs without using VID—understanding that will help you understand how to manipulate the output from layout
(and view
). What you lose building things from scratch is the layout feature that VID offers, but we can get the best from both worlds. Let's have a go:
First we'll need a place to put all our elements:
our-window: make face! [
type: 'window
text: "Our Window"
size: 500x500
]
Now let's stick some things in there:
our-window/pane: reduce [
make face! [
type: 'text
offset: 20x20
size: 160x28
text: "Text"
]
make face! [
type: 'field
offset: 200x20
size: 160x24
text: "Field"
]
make face! [
type: 'button
offset: 380x20
size: 160x28
text: "Button"
]
]
And now we can take a look at it:
view our-window
Note that the objects in our-window/pane
are kind-of like the objects that would be generated in this example:
our-vid-window: layout [
text 160 "Text"
field 160 "Field"
button 160 "Button"
]
As I said, with this approach you have to manage sizes and offsets yourself. What we can do is generate our row, take those face objects and append it to our window.
Indeed we can actually create these objects with layout
and drop them in our-window
:
make-row: func [/local row face kid][
row: layout copy/deep [ ; copy so the strings are unique
text 160 "Text"
field 160 "Field"
button 160 "Button"
]
...
]
Using techniques from this answer you can even apply global words to each of these faces and will still work.
Before we do though, we're going to check if our-window
has any children and adjust the offset of each of the new faces to appear below the last child:
if kid: last our-window/pane [
...
foreach face row/pane [
face/offset/y: face/offset/y + kid/offset/y + kid/size/y
]
]
To get the window sizing right, we're also going to adjust the generated row size and apply thus:
row/size/y: row/size/y + kid/offset/y + kid/size/y
...
our-window/size: row/size
And then the fun part:
append our-window/pane row/pane
Bringing this all together, we can generate a nicely sized window.
our-window: layout [
button "Add a Row" [make-row]
]
make-row: func [/local row face kid][
row: layout copy/deep [
text 160 "Text"
field 160 "Field"
button 160 "Button"
]
if kid: last our-window/pane [
row/size/y: row/size/y + kid/offset/y + kid/size/y
foreach face row/pane [
face/offset/y: face/offset/y + kid/offset/y + kid/size/y
]
]
our-window/size: row/size
append our-window/pane row/pane
]
make-row
make-row
make-row
view our-window