Opening a window with a nice GUI is a simple process with View, but new users may be tripped up when they wish to open more than one. As an example, consider this little script...
rebol []
view/title layout [
button "New Window" [
view/new/title layout [
box blue "Window 2"
] "Window 2"
]
button "Quit" [unview/all]
] "Main"
(Note: The quickest way to run the examples here is just to copy and paste the code after the "rebol []" line into the View Console. This gets around the hassle of having to save the code first before running it.)
With that, you can open a second window simply by clicking on the New Window button in the Main window. There's a catch with this however, as if you move Window 2 from in front of the Main window and click again on the New Window button, a third window will appear, also called Window 2. This may not be what you want!
Happily, there's an easy way around this - just create a permanant layout and then view/new that. ie...
rebol []
win2: layout [
box blue "Window 2"
]
view/title layout [
button "New Window" [
view/new/title win2 "Window 2"
]
button "Quit" [unview/all]
] "Main"
Now when you open Window 2 you'll find you can't open any more versions of it. This method also comes with an added bonus - if you close the window and then open it again, it'll open in the same place it was last on the screen, thus pleasing your users greatly.
That's an excellent method of window mangement for windows that are unique to your program. There will be times though when you'll want to open any number of windows which are all much the same - such as ones displaying pictures in a graphics program for instance. So, would a version of our first script be okay for that? Let's see...
rebol []
view/title layout [
button "New Window" [
view/new/title layout [
b: box blue "A Box"
button "Change!" [
b/color: random 255.255.255
show b
]
] "A Box"
]
button "Quit" [unview/all]
] "Main"
Run that and you'll find you can open any number windows with a box in, but if you click on their Change! buttons to give a box a random color you'll notice it's always the box in the most recent window you've opened that changes. This is because the B word is global and so can only reference one box at a time - the one in the most recently opened window.
Once again there's a way around this problem (and in fact more than one), though it's not nearly as easy to solve as preventing multiple windows from opening. How we'll do it is by using the VAR word faces in a layout contain, these being for the words (such as our B for box) that can be used as references in layouts.
A layout (which is just a standard REBOL object) has a block PANE which contains all the sub-faces that make up its layout, such as the boxes and buttons we've used so far in these examples. This allows us to search a layout for a face referenced by a specific word and this is what the GET-PANE function in our next example does.
That's only half the problems solved though, as we still need to find the layout we're working with, (ie, the one the button we're actually clicking on is in), before we can call that function. This happily is reasonably easy, the word FACE referencing the button's (or any other style's) face, and FACE/PARENT-FACE referencing it's layout.
With that solved, we can use
GET IN face word (where word is 'text or 'color etc.) to access a value (such as B/COLOR) and
SET IN face word value to change a value. This is more long winded than just using B/TEXT or B/COLOR, but it allows you to use the same references in multiple windows which is a nice thing to be able to do.
And here it all is in use...
rebol []
get-pane: func [face [object!] word [word!]][
foreach pane face/pane [if pane/var = word [return pane]]
make error! rejoin ["Word '" word " not found in layout!"]
]
view/title layout [
button "New Window" [
view/new/title layout [
b: box blue "A Box"
button "Change!" [
set in get-pane face/parent-face 'b 'color random 255.255.255
show get-pane face/parent-face 'b
]
button "Print Color" [
print get in get-pane face/parent-face 'b 'color
]
] "A Box"
]
button "Quit" [unview/all]
] "Main"
That could be simplified a bit further by writing specific functions to handle the SET, GET and SHOW bits - it's just probably best to do that on a script-by-script basis.
Comments and questions about this welcome.