Home   Archive   Permalink



Modifying a VID gui at run time

Hello!
    
I’m trying to add tiles selected by the user to a gui defined with VID.
    
I have an “mgui” block defined as follows:
    
mgui: [
    size: 300x500
    backcolor 100.100.100
    style tile box 40x40
    origin 20x440
    across
    tile red [color: 'red add-tile]
    tile green [color: 'green add-tile]
    origin 20x20
    tile orange tile blue tile purple return
]
    
This creates a standing rectangle with two tiles at the bottom, one red and one green. You can see that the tiles have some code that defines the value of a variable “Color” and then call a function add-tile, that has been defined like this:
    
add-tile: does [append mgui compose [tile (color)] show mgui]
    
Then I try:
    
view layout mgui
    
The expectation is that when the user clicks on one of the tiles at the bottom -for example, the red one- an equivalent tile will appear under the first row of tiles located on the top. Yet, when I run this code, no tile appears and instead the interpreter provides the following error message:
    
Misplaced item: 300x500
** Script Error: Invalid graphics face object
** Where: add-tile
** Near: show mgui
    
However, if I ask to probe mgui I get that the words were added to the mgui block, as you can see after the last return in the code (last two words):
    
>> probe mgui
[
     size: 300x500
     backcolor 100.100.100
     style tile box 40x40
     origin 20x440
     across
     tile red [color: 'red add-tile]
     tile green [color: 'green add-tile]
     origin 20x20
     tile orange tile blue tile purple return tile red
]
    
So I feel that the code was successful in updating the mgui block, however, I don’t get the expected result. Any ideas as of why?
    
Thanks in advance for your input

posted by:   brotherdamian       22-Sep-2019/0:12:27-7:00



Oops! Please note that the “size” instruction in the block provided has an assignment operator, which was a typo that I noted after posting the question. The correct mgui block should read:
    
mgui: [
    size 300x500
    backcolor 100.100.100
    style tile box 40x40
    origin 20x440
    across
    tile red [color: 'red add-tile]
    tile green [color: 'green add-tile]
    origin 20x20
    tile orange tile blue tile purple return
]
    
with this change, the error message after clicking the red tile in the bottom says:
    
** Script Error: Invalid graphics face object
** Where: add-tile
** Near: show mgui
    
And still does not produce the expected result, despite having successfully appended “tile red” at the end of the mgui block.
    
Any insights are deeply appreciated!

posted by:   brotherdamian       22-Sep-2019/11:06:40-7:00



Welcome to the world of dynamic faces!
    
Here's your code minimally fixed to add a new tile at a random location each time you click one of the two lower buttons.
    
Note some changes:
    
-- lo-mgui is the "compiled" version of mgui - ie what comes out of doing a LAYOUT
    
-- lo-mgui/pane is a BLOCK of FACES - it is here that we add our new tile face
    
-- New-tile could better be created with MAKE-FACE, the code here in ADD-TILE uses LAYOUT just for relative simplification of the example code
    
-- We need SHOW LO-GUI at the end of ADD-TILE - Rebol does not automatically update the displayed GUI.
    
    
mgui: [
     size 300x500
     backcolor 100.100.100
     style tile box 40x40
     origin 20x440
     across
     tile red [color: 'red add-tile]
     tile green [color: 'green add-tile]
     origin 20x20
     tile orange tile blue tile purple return
]
    
add-tile: does [
    layout [
     style tile box 40x40
     new-tile: tile pink
     ]
    new-tile/offset: random 200x200
    new-tile/color: random 255.255.255
    append lo-mgui/pane new-tile
    show lo-mgui
    print ["added - number of faces is now" length? lo-mgui/pane]
]
    
unview/all view lo-mgui: layout mgui


posted by:   Sunanda       22-Sep-2019/15:48:54-7:00



Oh! Thank you so much for this. It seems that this subject is a bit more involved.
    
Now I can see that it is not the original block of VID code that I need to modify but the “compiled” version after “Layout” had processed it (what you labeled “lo-mgui”).
    
I can use append regularly, but to the “panel” properties of what I am guessing is an object now. Is that right?
    
If I had not specified the /offset of new-tile, would have Rebol used the default values as defined by “space”, “origin” and the like, uniformly adding to the rows and columns of tiles? Or is that something that "Layout" does and now I need to do it programmatically?
    
Would the code using “make-face” instead of “layout” look like this?
    
New-tile: make-face/styles [ box 40x40 ]
    
I can see why you need to “show” after each addition. But why do you need to unview/all to begin with?
    
Again, thanks for your help!

posted by:   brotherdamian       22-Sep-2019/18:46:42-7:00



All VID FACES are OBJECTs. LAYOUT is simply a convenient way of making a load of FACES in one go, and it handles lots of useful things like working out each FACE's offset.
    
Every FACE OBJECT has a /PANE block. In the case of your tiles, they are the bottom of the FACE hierarchy, so they each have an empty /PANE block.
    
You can look at the basic information for a FACE and any FACES contained in its /PANE block like this:
    
     dump-face lo-mgui
        
LAYOUTs can be more complicated than that - your TILEs could contain other FACEs in their /PANEs - and so on. Here's a very simple example of a FACE hierarchy that is two levels deep:
    
dump-face view/new layout [
         across
             panel 100x100 white [box 50x50 red box 20x20 blue]
             panel 100x100 pink [box 40x40 green box 30x30 yellow]
             ]
    
LAYOUT generates OFFSETs (in accordance with your DOWN or ACROSS) relative to the /PANE in which the FACE appears. If we had not put an OFFSET in the LAYOUT in ADD-TILE, all the new tiles would have default offsets of 10x10 - so they'd overlay your first Red Tile - delete the NEW-TILE/OFFSET line and you should see that behavior.
    
If you want the new tile to go somewhere relative to existing tiles in the same PANEL, then you need to replace the NEW-TILE/OFFSET line with a more sophisticated version of:
    
     last-old-tile: last lo-mgui/pane
     new-tile/offset: 0x40 + last-old-tile/offset
        
UNVIEW/ALL is helpful, especially if you have been doing VIEW/NEW .... DO-EVENTS - it clears all the old GUI windows.
    
VIEW/NEW ... DO-EVENTS is helpful as it gives you access to both the console, and the GUI. Try this:
    
     unview/all view/NEW lo-mgui: layout mgui
    
The GUI appears, but does not respond to clicks. You can still use the console, eg:
    print length? lo-mgui/pane
    print lo-mgui/size
    lo-mgui/pane/1/color: black
    show lo-mgui
    
To get the GUI to start working, type in the console:
    DO-EVENTS
    
    
A good introduction to making FACES dynamically is here:
    
http://www.rebol.com/docs/view-face-funcs.html
    


posted by:   Sunanda       22-Sep-2019/20:47:10-7:00



Name:


Message:


Type the reverse of this captcha text: "u r h t - s s a p"



Home