VID Layout Panel Supporting Multiple Faces Creation [rebol2]

Please review this simple rebol2 code to illustrate my problem:

REBOL [] a: make face [ offset: 0x0 color: yellow size: 20x20 ] b: make face [ offset: 0x0 color: red size: 60x60 pane: reduce [ make a [offset: 0x0] make a [offset: 10x10] make a [offset: 10x20] ] ] view layout [ box 200x200 white with [ pane: reduce [ make b [offset: 0x30] ;; one 'instance' of b ] ] ] 

The main point here is that the layout (or face) can display a bunch of faces inside its panel block so that it is possible to create several creations of the same side ( b in this case), the code shown works well, and the only instance (let me call it that way) b displayed as it should be.

But now suppose I change the code, so I have, say, 2 instances of b :

 view layout [ box 200x200 white with [ pane: reduce [ make b [offset: 0x30] make b [offset: 0x10] ] ] ] 

At this moment I get an error

 ** Script Error: Face object reused (in more than one pane): none ** Where: view ** Near: show scr-face if new [do-events] 

From the message that I am suggesting here that face b somehow reused and claimed by exactly what I am trying to achieve. I did a lot of research on this, and at some point I found that you could get around it by cloning (using make ) the face that should be passed to pane ; what I thought I was doing, but did not succeed at all.

Given this scenario, my question is: how can I solve this? is it rebol2 ok to provide this β€œface creation” or is it better to try something else outside of rebol2 (possibly rebol3)?

Any help would be greatly appreciated.

+5
source share
3 answers

As already stated, the problem is that a reused, not b !

the build function uses a field called init to handle such things. As I understand it, init first attached to the face, and then called with do after the face itself has been created (at least partially).

In this case, I would use the style command in the layout (still partially using the face a object)

 view layout [ style bb box 60x60 with [ append init [ pane reduce [ make a [offset: 0x0] make a [offset: 10x10] make a [offset: 10x20] ] ] ] panel 200x200 white [ at 30x0 bb at 0x0 bb ] ] 

Another alternative, slightly more similar to yours, would be:

 b: make face [ offset: 0x0 color: red size: 60x60 init: [ pane: reduce [ make a [offset: 0x0] make a [offset: 10x10] make a [offset: 10x20] ] ] ] view layout [ box 200x200 with [ append init [ pane: reduce [ make b [ offset: 0x0 do init ] make b [ offset: 0x60 do init ] ] ] ] ] 

Note that init manually called inside the make clause in this case. I'm not quite sure why this is necessary. Finally, everything could be elegantly solved with style

 view layout [ style a box yellow 20x20 style b panel red 60x60 [ at 0x0 a ; we can in this style use the just defined a style at 10x10 a at 10x20 a ] at 0x0 b at 0x60 b ] 
+1
source

Rebol2 is definitely suitable for this.

When you do the second time, you use the same instance of a. This is problem.

You can write a function that creates the necessary faces and adds them to the block and returns. Remember to create '(first person) every time.

Also, check if iterated persons were in the documentation.

Here I added an example:

 REBOL [] make-pane: func [ofst [pair! block!] /local ab faces] [ a: make face [ offset: 0x0 color: yellow size: 20x20 ] faces: copy [] either block? ofst [ foreach o ofst [ append faces make a [offset: o] ] ] [ append faces make a [offset: ofst] ] b: make face [ offset: 0x0 color: red size: 60x60 pane: faces ] ] view layout [ box 200x200 white with [ pane: make-pane [5x30 0x10 20x5] ] ] 

You can change the function to get more options, to change the color and other faces.

+3
source

I said in a comment that I will return to my discoveries, and I think that I have something interesting. As @ endo64 noted, duplicate faces are complex and may not be suitable for what I intended to do when I first asked the question - to achieve a simple / easy way to create objects through panels.

I came up with the code below that implements a kind of instance. This was partially inspired by the @ endo64 face-maker approach along with some iterated-face masters. This instance has a kernel constraint that does not accept several types of objects passed to the constructor, which must be created on the same panel.

In any case, I found this to be an interesting exercise, and I would like to post it here if it can be of any use to anyone.


I use the same code from the question, now solving / bypassing the restriction of creating multiple b objects inside the main breadboard. a and b now holds the instantiator object, which receives the object to create inside its panel and a block of positions (pairs of offsets) where the objects should be placed.

 a: make face [ offset: 0x0 color: yellow size: 30x20 ] b: make face [ offset: 0x0 color: red size: 100x100 inst_b: _instantiator/new reduce a [10x10 10x70 80x80 30x30] ; instantiator here pane: get in inst_b 'pane_function ] 

Instant Code:

 _instantiator: make object! [ _obj: copy [] _offsets: copy [] new: func [ obj [object!] "object to create inside pane" offs [block!] "instances offsets" ][ make self [ _obj: obj _offsets: offs ] ] pane_function: func [face index] [ if integer? index [ if index <= length? _offsets [ _obj/offset: to-pair reduce [_offsets/:index/x _offsets/:index/y] _obj ] ] ] ] 

Code for the main layout:

 _inst: _instantiator/new reduce b [0x0 50x50 130x130] ;;3 b objects are created in the positions indicated in the pairs block _lo: layout [ mybox: box 500x500 white with [ offset: 0x0 pane: get in _inst 'pane_function ] ] view center-face _lo 
0
source

All Articles