how to reference code outside of current card?

LiveCode is the premier environment for creating multi-platform solutions for all major operating systems - Windows, Mac OS X, Linux, the Web, Server environments and Mobile platforms. Brand new to LiveCode? Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

billworld
Posts: 188
Joined: Sat Oct 25, 2008 12:32 am

Post by billworld » Wed Nov 19, 2008 1:30 am

Somewhat related, I see that I can set the script property of an object to the script of any other object. This is close to what I'm envisioning, however, with this approach you can only have up to 10 statements. Further, it appears that going this route prevents you from actually viewing the script in the Script Editor. Still confused on how to reference a block of code.

SparkOut
Posts: 2947
Joined: Sun Sep 23, 2007 4:58 pm

Post by SparkOut » Wed Nov 19, 2008 2:52 am

Well, as you can see Bill, there are many ways of interpreting things in Rev.
The message path is the most important concept to understand in this context.
In its simplest form, you want to have a way of reusing code so that you don't have to rewrite scripts for multiple objects in multiple stacks, right?
So, starting off simply (and forgive me for any uber-basic patronisation, which is not the intention), you have, say a couple of buttons on a card.
In button1 you have a mouseUp handler

Code: Select all

on mouseUp
  answer "This is button 1"
end mouseUp
and button2 has a separate, specific nouseUp handler of its own

Code: Select all

on mouseUp
  answer "This is button 2"
end mouseUp
If you use a common handler for each mouseUp event on each button you could put the same script in each button

Code: Select all

on mouseUp
  doAnswer (the short name of me)
end mouseUp
and in the card script you can have a handler that each button will be able to reach

Code: Select all

on doAnswer pName
  answer "This is button" && the last char of pName
  --assuming single digit button naming applies - not a real world example!
end doAnswer
Putting the doAnswer script in the card makes it available to all the objects on that card. If you put it higher up the message path, in the stack script, you can make it available to all the objects in the stack.
Now you can also leave out the mouseUp handlers on each button on the card and put the mouseUp handler in the card or stack script. This means that on clicking (say) button1 (or any object in the card or stack accordingly), because you left out a specific mouseUp handler in "the target", the mouseUp message is not trapped by the "target" button and the mouseUp message will continue to follow the message path until it reaches a handler - which in this case you will have put in the card or stack script. By testing the (long) name of the target to check for appropriate conditions, the mouseUp message can be trapped and trigger the right actions accordingly. (This is what bernd was explaining with his examples.)
If you have multiple substacks and you leave out all mouseUp handlers and just have one mouseUp handler in the mainstack script, then clicking on objects in all the substacks will generate mouseUp messages which will travel along the message path until they reach the mainstack mouseUp handler. You can, if you wish, rely on just one mainstack mouseUp handler to respond to all the mouseUp (or any other) messages, but it would need to be quite sophisticated to work out what to do in the case of all the objects which may have created the message. Of course, it needn't have to handle "every" mouseUp message, because say you have a specific set of buttons on one card of one substack that would trigger different events and you don't want to have to test for every target permutation in the mainstack handler - just adding a mouseUp handler lower down the message path, on the card of the substack, or in the buttons themselves will intercept the mouseUp message and react, before the message gets to the mainstack. Unless you "pass" the message in the more local script, it will be trapped there and not trigger any events via the mainstack handler.
If you want to reuse code on multiple projects, then creating a library stack, or making front/back scripts are useful options. A library stack is somewhat less ingrained and potentially simpler and/or more flexible, depending on your needs. If you "start using <librarystackname>" (usually somewhere like in the openStack handler of your project mainstack) then you can make the library handlers available to the mainstack and all its substacks. So by creating a generic mouseUp handler and putting it into a library stack, then telling the project mainstack to "start using" the library, you can click a button on a card of a substack and that will generate a mouseUp message, which will (ignoring front scripts for now) travel from the button, through any group script of which it may be a member, the card script, any background group script of which it may be a member, the substack script, the mainstack script, then the library, any backscripts, and finally the engine. If the mouseUp message reaches a mouseUp handler at any point along the path then the handler will kick in, and the mouseUp message will stop at that point, unless the handler specifically "passes" the message.
Does that make it any clearer?

SparkOut
Posts: 2947
Joined: Sun Sep 23, 2007 4:58 pm

Post by SparkOut » Wed Nov 19, 2008 3:04 am

Oh, and one thing that can help with making a higher level handler react appropriately in the absence of "parameters" barring the (long) name of the target is to use getProp and setProp handlers to test custom properties of the target objects.

billworld
Posts: 188
Joined: Sat Oct 25, 2008 12:32 am

Post by billworld » Wed Nov 19, 2008 4:25 am

Thanks a bunch for the lengthy and detailed reply. I'm getting the drift of message path etc. as a way of controlling what gets triggered when. I could see how it's powerful. However, it seems like a lot of work and bother to track all of this (e.g. the multiple levels of the message path) when in my case, all I simply want to do is insert/include a block of context-independent code at a specified location.

Anyway, is there truly no equivalent of an include command which simply inserts a block of code wherever the "include" command is inserted? My mind is thinking along the lines of that being the best/easiest way to isolate code for a given context without having to worry about all of the other scenarios generated by other objects which are under the same stack umbrella.

That's what I thought "insert script" was supposed to do, but, it's not working that way.

Thanks again and apologies if I'm hard-headed on this. There are SO many nice and intuitive things about Transcript and RR. I'm just not getting this one (with surely others to follow I gather!).

Best,

Bill
SparkOut wrote: Does that make it any clearer?

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4172
Joined: Sun Jan 07, 2007 9:12 pm

Post by bn » Wed Nov 19, 2008 3:44 pm

Bill,
from what I gather what you want is to reuse code that is pertinent to many similar actions without putting it into the script of each of these objects.
I give it a try in RunRev. Sparkout explained the message path and that if you put a command or a function into the script of the mainstack it will be executed, even if issued from a substack. (unless of course in the way of the message path this command/handler has been intercepted)
So lets suppose you put the following into a stack script:

Code: Select all

on mouseEnter
    DimmDimmNot  the long name of the target
end mouseEnter

on mouseLeave
    DimmDimmNot  the long name of the target
end mouseLeave

on DimmDimmNot pWhoToDimm
    if pWhoToDimm contains "image" then
        if the blendlevel of pWhoToDimm = 80 then
            set the blendlevel  of pWhoToDimm to 0
        else 
            set the blendlevel of pWhoToDimm to 80
        end if
    end if
end DimmDimmNot
the little test stack consists of at least two cards with at least an image on each card. You could of course add one or more substacks with as many cards and as many pictures on them as you want. No image has any script.
Whenever you have a mouseEnter or mouseLeave event it will go up to the script of the mainstack and it will find a command or as it is sometimes called a handler for mouseEnter and mouseLeave.
These handlers now get the target's long name and passes it to a custom made command 'DimmDimmNot' that takes care of dimming or not dimming as you can see.

I think the custom command 'DimmDimmNot' is what you are after if I am not off track.
The nice thing is that you isolate the execution from the call for execution.
For example, if you take the on mouseEnter and mouseLeave commands out of the stack script and put them in the images you end up with little code in the images and a central procedure for execution. That way you can decide to which images the dimming will apply and to which not.
This way you can fine tune the behaviour of your objects with relatively litte code that applies to all of them.
This is basically what you do when you create a library, a repository for many of those little or longer custom commands. But a library is more useful for generic code, that you use in different projects. If you just want to reuse code in one project putting the code into the main stack script might be all you need to do.
(by the way a library is not that complicated: just create a stack and put your library commands and functions into the stack script of that stack. If you want to use the library you call it with "start using stack "xyz". It is then inserted into the message path above (gets events later than) the script of the main stack. All the commands of your library are accessible to the open stacks and substacks.

you might want to try the example and see if it is close to what you want.
If not then it might be helpful if you posted a short example of your idea on revOnline and someone can help.

Sparkout has a very clear way to explain, I hope I didnt obscure the topic more than necessary...
regards
Bernd

billworld
Posts: 188
Joined: Sat Oct 25, 2008 12:32 am

Post by billworld » Wed Nov 19, 2008 4:54 pm

Thanks Bernd. Yes, I clearly see how the message path approach works. However, again, what I'm asking if there's simply an equivalent to an "include" command in RR where an entire block of code (e.g. including multiple handlers) can be inserted at any specific point (e.g. as a script of a specific object or group)? It appears that you always need to insert within a specified handler vs what I'm contemplating (and other languages provide) where a code block can be inserted anywhere, regardless of the existence of a handler.

I understand how one can insert custom commands within specified handlers within objects which point to or reference said custom command centrally located elsewhere. However, that just operates on a per-handler basis. What about a block of code containing multiple handlers which needs to be inserted into a specific script of a specific object? That's the thinking being the "include" concept and what I thought "insert script" offered.

Anyway, I see there's other ways of accomplishing the same end result without the "include" approach. It's just not as intuitive to me (maybe at first).

Maybe I'll just go with custom commands to hold blocks of code and reference them within groups of objects all which inherit the same functionality. That way I don't have to worry about trapping for particular names of objects or types using the global library or stack script approach. Still, however, I'll be inserting several handlers for each group with each one pointing to a centrally located custom command. And, across the app there will be dozens of groups sharing the same functionality. Well, maybe here I can eliminate code repetition by simply naming each of the groups which share common functionality and then trap for the unique group name identifier in the commands inside the global stack script.

Anyway, it still seems logical to me for a language to offer the ability to reference a block of code (e.g. multiple handlers) with a single reference point. And, I'm not clear on how that's accomplished (if at all possible) in RR.

Maybe if RR had a special handler for retrieving a block of code contained elsewhere on the event of the app. being initialized such as:

Code: Select all

on initialize
 include script "Bill's Wacky Multi-Handler Routine" of card "card1" of stack "library"
end initialize
This handler could be inserted in any group/object/card/stack. The end result is that the targeted group/object/card/stack gets all of the functionality provided by the "Bill's Wacky Multi-Handler Routine" script without requiring individually calling handlers to be inserted in the group/object/card/stack and without having to trap for specific group/object/card/stack names in global routines achieved via other means.

Does that make sense?

Thanks again for the help in thinking through this.

Best,

Bill
bn wrote: Sparkout has a very clear way to explain, I hope I didnt obscure the topic more than necessary...
regards
Bernd

SparkOut
Posts: 2947
Joined: Sun Sep 23, 2007 4:58 pm

Post by SparkOut » Wed Nov 19, 2008 5:11 pm

Now I'm getting more confused, but I'd really like to help you get to the bottom of things. It may be that you will end up having to rethink your way around Rev, and (we have to face it) sometimes that's the only way to do it. Rev does provide a very rich and varied way of being able to do most things, and this flexibility does lead to a variety of approaches and techniques.
billworld wrote:Anyway, it still seems logical to me for a language to offer the ability to reference a block of code (e.g. multiple handlers) with a single reference point. And, I'm not clear on how that's accomplished (if at all possible) in RR.
Can you help me understand exactly how you would like to trigger the code? By responding to mouseUp events for example? I don't have any other programming background than Rev, so a concept that doesn't use the message path approach isn't intuitive to me, either!
billworld wrote:Maybe if RR had a special handler for retrieving a block of code contained elsewhere on the event of the app. being initialized such as:

Code: Select all

on initialize
 include script "Bill's Wacky Multi-Handler Routine" of card "card1" of stack "library"
end initialize
This sounds to me very like the "start using <librarystack>" idea, so I'm desperately trying to understand what is the difference in your concept.
billworld wrote:This handler could be inserted in any group/object/card/stack. The end result is that the targeted group/object/card/stack gets all of the functionality provided by the "Bill's Wacky Multi-Handler Routine" script without requiring individually calling handlers to be inserted in the group/object/card/stack and without having to trap for specific group/object/card/stack names in global routines achieved via other means.

Does that make sense?
You've obviously got something in mind and it's intuitive to you. With my mindset as is, focussed on Rev, I'm not sure exactly what you're driving at. Could it be that you'd like to programmatically assign handlers to objects? At the risk of muddying things completely, perhaps introducing "set the script of <object> to <...the script of another object, for example>" into the mix is warranted? Or not?!

billworld
Posts: 188
Joined: Sat Oct 25, 2008 12:32 am

Post by billworld » Wed Nov 19, 2008 5:37 pm

The important difference is that with "start using" you send the routine to a stack, not to a specific object/group, etc. So, that means you then need to trap for the targeted object/group in your script routine.

By simply including the script in the actual object/group, you don't have to worry about trapping for it at the stack level. Make sense?
SparkOut wrote:
billworld wrote:

Code: Select all

on initialize
 include script "Bill's Wacky Multi-Handler Routine" of card "card1" of stack "library"
end initialize
This sounds to me very like the "start using <librarystack>" idea, so I'm desperately trying to understand what is the difference in your concept.

SparkOut
Posts: 2947
Joined: Sun Sep 23, 2007 4:58 pm

Post by SparkOut » Wed Nov 19, 2008 5:46 pm

Ah! So "set the script of <object> to <script list>" would actually be what you're looking for then?

I see at the top of this page that you mentioned that idea, but that you believed there to be a 10 line limit. This is only true in a standalone that has already been compiled. (In other words, if during the course of the operation of the standalone you set scripts programmatically there would be a 10 line limit. There's no limit if you create the application in the IDE and set the scripts of the objects you need, then compile it as a standalone.)

billworld
Posts: 188
Joined: Sat Oct 25, 2008 12:32 am

Post by billworld » Wed Nov 19, 2008 6:15 pm

Hmm... Thanks for the clarification on the 10 line limit. I've just re-read the docs on this and see it spelled out there (I initially misinterpreted it).

The only other thing regarding this approach that caused me pause was the fact that you don't see the resulting script or even a pointer to it in the Script Editor. So, it's not as easy to see whether or not a script has been applied to an object already and to understand which script has actually been applied. It's kinda a one-way street, no? Set the script and then forget about it. That approach seems like a nightmare to maintain and bring sense to apps. coded months back. I guess one could check to see if a script property has been set, but, again, that's just not as easy to deal with (e.g. scanning code to make sense of it).

Any suggestions for that?

Thanks a bunch.
SparkOut wrote:Ah! So "set the script of <object> to <script list>" would actually be what you're looking for then?

I see at the top of this page that you mentioned that idea, but that you believed there to be a 10 line limit. This is only true in a standalone that has already been compiled. (In other words, if during the course of the operation of the standalone you set scripts programmatically there would be a 10 line limit. There's no limit if you create the application in the IDE and set the scripts of the objects you need, then compile it as a standalone.)

SparkOut
Posts: 2947
Joined: Sun Sep 23, 2007 4:58 pm

Post by SparkOut » Wed Nov 19, 2008 6:18 pm

Um... no - I can set the script of an object via "set the script of..." and then using the IDE to edit the script of that object I can see all the code... :?

billworld
Posts: 188
Joined: Sat Oct 25, 2008 12:32 am

Post by billworld » Wed Nov 19, 2008 6:26 pm

I guess the real difference between this initialize/include approach I've asserted and the "set script of object x to script of object y" at startup routine is where the trail for the code of this routine is placed. If the set script routine is part of a startup script, I guess one could include a comment as part of an otherwise empty script for the object whose script was set at startup. That way, there's something in the Script Editor pointing to what's going on script-wise with the particular object.

Something like:

Code: Select all

/*
Icon Behavior Routine Source
Script set at startup in global startup routine referencing the script located on "button1" of card 1 of stack "MainStack" 
*/
billworld wrote:Hmm... Thanks for the clarification on the 10 line limit. I've just re-read the docs on this and see it spelled out there (I initially misinterpreted it).

The only other thing regarding this approach that caused me pause was the fact that you don't see the resulting script or even a pointer to it in the Script Editor. So, it's not as easy to see whether or not a script has been applied to an object already and to understand which script has actually been applied. It's kinda a one-way street, no? Set the script and then forget about it. That approach seems like a nightmare to maintain and bring sense to apps. coded months back. I guess one could check to see if a script property has been set, but, again, that's just not as easy to deal with (e.g. scanning code to make sense of it).

Any suggestions for that?

Thanks a bunch.
SparkOut wrote:Ah! So "set the script of <object> to <script list>" would actually be what you're looking for then?

I see at the top of this page that you mentioned that idea, but that you believed there to be a 10 line limit. This is only true in a standalone that has already been compiled. (In other words, if during the course of the operation of the standalone you set scripts programmatically there would be a 10 line limit. There's no limit if you create the application in the IDE and set the scripts of the objects you need, then compile it as a standalone.)

billworld
Posts: 188
Joined: Sat Oct 25, 2008 12:32 am

Post by billworld » Wed Nov 19, 2008 7:03 pm

SparkOut wrote:Um... no - I can set the script of an object via "set the script of..." and then using the IDE to edit the script of that object I can see all the code... :?
Hmm... You're right! I know I tried this before and didn't see the script set. Maybe there was an error with how I was setting it. Just did it again and worked just fine. Sorry for the misunderstanding on that...

Anyway, this still is not ideal as again, it's prone to error (which some of us are good at!). Inserting the actual block of code is different than inserting a reference to a block of code. I'm just not set on this way of doing things. I'm used to pointing to code located elsewhere. I guess the only way to really do that here is at the stack level and then to trap for individual objects within the stack in the stack script.

SparkOut
Posts: 2947
Joined: Sun Sep 23, 2007 4:58 pm

Post by SparkOut » Wed Nov 19, 2008 7:39 pm

I guess that's the thing, like I said, there are various approaches and techniques, but at some point, you will have to change the way of thinking to get the full benefit of Rev.

After all that, it sounds a little simplistic but maybe the best for your situation is to have a stack script with custom handlers such as "on doStuff pParameter", and then set the script of the various objects to "on mouseUp doStuff theParameter...etc"

billworld
Posts: 188
Joined: Sat Oct 25, 2008 12:32 am

Post by billworld » Wed Nov 19, 2008 8:10 pm

Yeah I think the param approach is closer to achieving what I had in mind. Thanks for the suggestion!
SparkOut wrote:I guess that's the thing, like I said, there are various approaches and techniques, but at some point, you will have to change the way of thinking to get the full benefit of Rev.

After all that, it sounds a little simplistic but maybe the best for your situation is to have a stack script with custom handlers such as "on doStuff pParameter", and then set the script of the various objects to "on mouseUp doStuff theParameter...etc"

Post Reply