r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[Core] Discuss core issues

Anton
15-Aug-2010
[17854x3]
Ok, so you can rewrite each of your window functions to take, and 
bind itself to, a context argument; or, you can add a "BIND-FUNCS" 
function, taking a context argument, which rebinds all your window 
functions to the context.
Similar to what I've done above.
So, each function binds itself:
hello: func [ctx] [do bind [f/text: copy "hello" show f] ctx]

open-window: does [
	view/new center-face layout vid-context [
		f: field

  button "Hello" [hello self] ;  Pass to HELLO this context (created 
  by VID-CONTEXT).
		button "Clear" [clear-face f]
	]
]

open-window
open-window
do-events
Graham
15-Aug-2010
[17857]
yes ...
Anton
15-Aug-2010
[17858]
Or, all the functions are rebinded by BIND-FUNCS:
Graham
15-Aug-2010
[17859]
That might be the easier way .. .to get the binding be handled by 
the function itself
Anton
15-Aug-2010
[17860x2]
hello: does [f/text: copy "hello" show f]

bind-funcs: func [ctx] [

 foreach window-function [hello][bind second get window-function ctx]
]

open-window: does [
	view/new center-face layout vid-context [
		f: field

  button "Hello" [bind-funcs self hello] ;  Pass to HELLO this context 
  (created by VID-CONTEXT).
		button "Clear" [clear-face f]
	]
]

open-window
open-window
do-events
(Oops - the comment should be ; Pass to BIND-FUNCS ...
Graham
15-Aug-2010
[17862]
you don't like the idea of the function itself doing the binding?
Anton
15-Aug-2010
[17863x6]
If you don't like the idea of modifying all your functions, then 
it might be more convenient. Also, you might call bind-funcs just 
once, then call several of your functions afterwards without having 
to pass them anything.
(Note, all this tricky function rebinding makes the functions non-reentrant.)
Another idea I have is to patch your styles (eg. BUTTON, FIELD etc.) 
so that when their action blocks are converted to functions, the 
blocks are bound to the right context.
You can see here the block: function

print mold get in svv/vid-styles/button 'multi
...
block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1

            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]


It has all it needs to determine the context returned by VID-CONTEXT.
From the FACE argument (eg. the newly created BUTTON face), you can 
climb up to the window face, then search through its subfaces for 
one with a word VAR facet. That word should have been already bound 
by VID-CONTEXT, so that means we can pre-bind the action block to 
the context (just before the action function is created from it).
You would just need to modify the multi/block function for each of 
the styles which converts block to action functions.
Graham
15-Aug-2010
[17869x2]
why does re-entrance matter?
we don't have multitasking in R2
Anton
15-Aug-2010
[17871x2]
Actually, it looks like the multi/block function is the same for 
all styles.
If you want to port your code later, it might be significant. If 
not, don't worry.
Maxim
15-Aug-2010
[17873]
binding control in R3 is one of my favorite things that got a major 
boost in capability.
Anton
16-Aug-2010
[17874x3]
Here's a proof of concept for that idea I mentioned:
svv/vid-styles/button/multi/block: func [face blk][ ; <- This only 
does BUTTON for now.
	if pick blk 1 [
		;face/action: func [face value] pick blk 1

  face/action: func [face value /local window word] compose/only [

   window: face/parent-face ; Find the window face <-- (simplistic for 
   now)

   word: window/pane/1/var ; Find a word which references a field in 
   the window. <-- (simplistic for now)
			print "Remake action function."

   face/action: func [face value] probe append append copy [bind-funcs] 
   to-lit-word word (pick blk 1)
			do-face face value
		]

  if pick blk 2 [face/alt-action: func [face value] pick blk 2] ; <- 
  Also need to remake alt-action similarly to action, above.
	]
]
bind-funcs: func [word] [

 foreach window-function [hello][bind second get window-function word]
]

hello: does [f/text: copy "hello" show f]

open-window: does [
	view/new center-face layout ctx: vid-context [
		f: field
		button "Hello" [hello]
		button "Clear" [clear-face f]
	]
]

open-window
open-window
do-events
That was fun to figure out, but I'm not sure it's worth all the extra 
complication yet. Would have to see if it is straightforward and 
consistent to use, or makes things too confusing to understand later. 
It would definitely need some good docs.
Graham
16-Aug-2010
[17877]
so when you use the action of a button, it binds the context of the 
first word in the action block to the current context
Anton
16-Aug-2010
[17878]
Not the first word in the action block, no.
Graham
16-Aug-2010
[17879x3]
So, what side effects are there ?
if the action is to update a different window in a different context 
.. I guess that action would stop working ....
and it doesn't solve the issue where the function you are rebinding 
actually calls a different function to update the gui
Anton
16-Aug-2010
[17882]
The major side-effect is that the action of each face (eg. button, 
field) will remake itself the first time it is used, to insert a 
snippet of code to rebind the window funcs before your specified 
action code uses them.
Graham
16-Aug-2010
[17883x4]
So, I suspect it is better to allow the programmer to select the 
context instead of automating it.
eg.  I had something like this 


button [ get-data ] ... and get-data called another function to update 
the GUI
binding 'get-data didn't help as the function it calls was still 
bound to global
so I like your first idea better :)
Anton
16-Aug-2010
[17887x3]
You're right about nested function calls. BIND doesn't recurse into 
words, so that the bodies of functions referenced by words are also 
bound. So that could be very damaging.
Updating a different window can still work, though, because you're 
going to need to reference that window anyway to distinguish it from 
the "current" one:
svv/vid-styles/button/multi/block: func [face blk][ ; <- This only 
does BUTTON for now.
	if pick blk 1 [
		;face/action: func [face value] pick blk 1

  face/action: func [face value /local window word] compose/only [

   window: face/parent-face ; Find the window face <-- (simplistic for 
   now)

   word: window/pane/1/var ; Find a word which references a field in 
   the window. <-- (simplistic for now)
			print "Remake action function."

   face/action: func [face value] probe append append copy [bind-funcs] 
   to-lit-word word (pick blk 1)
			do-face face value
		]

  if pick blk 2 [face/alt-action: func [face value] pick blk 2] ; <- 
  Also need to remake alt-action similarly to action, above.
	]
]
bind-funcs: func [word] [

 foreach window-function [hello][bind second get window-function word]
]

hello: does [f/text: copy "hello" show f]

open-window: has [window ctx] [
	window: view/new center-face layout vid-context/to [
		f: field
		button "Hello" [hello]
		button "Clear" [clear-face f]
		button "Clear window2's field" [clear-face window2/user-data/f]
	] 'ctx
	window/user-data: ctx
	window
]

window1: open-window
window2: open-window
do-events
Graham
16-Aug-2010
[17890]
neat trick .. i didn't know about user-data
Anton
16-Aug-2010
[17891x2]
No, wait a minute... that's what BIND-FUNCS is for. Currently it 
only affects HELLO, but you just need to add all the functions which 
need binding into the block:
foreach window-function [hello get-data update-gui etc.]  ...
So you can have nested function calls as deep as you like, as long 
as you specify those which need binding in BIND-FUNCS.
Graham
16-Aug-2010
[17893x2]
ok, but the other issue is that the function has to be rebound each 
time it is used
Was that what Gab was saying ..?
Anton
16-Aug-2010
[17895x2]
No, Gregg's first example suffered because it only did a BIND once, 
when the window was created. It needs to do the bind every time the 
button is pressed.
So Gregg's example would work for each window as long as that window 
was the last window opened. As soon as you opened a new window, none 
of the other windows would work properly anymore.
Graham
16-Aug-2010
[17897]
ah... mine bound with each button press
Anton
16-Aug-2010
[17898]
USER-DATA in the window faces seems unlikely to be used to me. You 
could also probably use DATA without problems as well. It depends 
on whether any other VID extensions are being used in your system, 
which could theoretically use that facet for something. Of course 
you can associate the window with it's vid-context by other means 
which doesn't touch any of the window facets at all...
Gabriele
16-Aug-2010
[17899x2]
Graham: when you use vid-context/to, the word you pass in is set 
to an object. the object contains all the set-words you used in the 
vid block. example:
>> lay: layout vid-context/to [f: field g: button] 'ctx
>> ? ctx
CTX is an object of value: 

   f               object!   [type offset size span pane text color 
   image effec... 

   g               object!   [type offset size span pane text color 
   image effec...
Graham
16-Aug-2010
[17901]
A concrete example would help me here :)
Gabriele
16-Aug-2010
[17902x2]
now you can pass this object to your functions so that you can use 
them with many layouts.
eg. you make c: func [obj] [obj/f/text: "something" ...]