Correct Syntax???!!!

David Burgun dburgun at dsl.pipex.com
Sat Mar 25 06:15:22 EST 2006


Hi,

On 24 Mar 2006, at 21:15, J. Landman Gay wrote:

> I think the main point is that you can structure this handler any  
> way you need to in order to accomplish a generic goal. You don't  
> necessarily need to change every field's contents; the handler can  
> check for a field property, field contents, a list in a global  
> variable, anything at all, and only act when appropriate. There  
> could be default values, updated values, values based on a  
> calculation, no value changed, whatever you need. It doesn't have  
> to be only fields; you can use the more generic "control" keyword  
> and check everything on the card. The idea is that
> one or a few handlers in a central location manage everything. The  
> script becomes universal and transportable.

But then you need to change the script each time you add a new object  
that needs some specialized initialization. Also you need to ensure  
that the script is copied onto all cards in your Stack, meaning that  
if you have an object of type "X" that needs initialization of type  
"Y" to ensure that the scripts of all cards containing *that* type of  
object are changed.

Using my method, I just drop the new Object into one card, get it  
working, then wherever I want to use that in another card or stack I  
just paste it in and it works! I don't need to change anything else  
anywhere!

Also there is nothing from preventing you from having the "guts' of  
the script in a centralized location and calling it from each object.  
All I am trying to achieve is Object re-use. I develop Groups/Objects  
that can be used *anywhere* without adding/changing anything but the  
Group or Object you have added.

> I would use Revolution's native system messages to trigger a  
> handler which is located in the stack script, the background  
> script, or a library script. The system message I'd trap depends on  
> the situation, but in this case a preOpenCard message would allow  
> the fields to change their content before the card is displayed.  
> Instead of adding a script to each field (unnecessary overhead,) I  
> would mark the field in some way as "special"; set a property, or  
> (more typically for me) preface the field name with particular  
> string. It doesn't matter how these fields are differentiated, it  
> only matters that a script can test for the fact that they are  
> controls that need to be handled.

The script is a property! So we are actually doing the same thing!

> Then in my library/stack/background script, I'd have a handler:
>
> on preOpenCard
>   doCalcStuff
> end preOpenCard
>
> on doCalStuff -- all actual work goes here
>   repeat with x = 1 to the number of controls -- or "flds","btns",  
> etc.
>     if the uUpdate of control x then <whatever>
>   end repeat
> end doCalcStuff
>
> A doCalcStuff handler would check the Preferences stack to see what  
> the user's measurement preference is, and re-calculate those fields  
> that require it before the card opens. It can update both the  
> measurement popups as well as the data calculation fields at the  
> same time.
>
But you are now visiting all the objects whether they need to be  
changed or not or you are specifically hard-coding object names into  
the script so if you delete an object or add a new one, you have to  
change the script. This is what I was trying to avoid. I just want to  
be able to drop a Group or Object into a card and have it work  
without changing anything except (maybe) the object I have just  
dropped in.

> You get the same results, with less scripting and more portability.  
> In addition, the fields themselves do not need to take any kind of  
> active "listening" role at all, nor do they need any particular  
> scripts; they need do nothing. All the updating is handled in a  
> single place -- a backscript or similar -- and if you need to  
> change the behavior you only need to change the backscript.

I really can't see how it's less scripting! I would say my method  
results in *much* less scripting, since I don't need to do any  
scripting at all to add a new measurement control.

> The effort required to change a measurement preference is identical  
> to the method you are currently working with. The user makes only a  
> single selection in the Preferences stack, and in fact no other  
> actions take place at that time. There is no performance hit  
> because the actual updating doesn't happen until the card is  
> displayed, where the update is virtually instantaneous.

Yes, I agree this is the same, except if the preferences stack itself  
needs to change as a result of the users actions (like if they change  
the language from English to Spanish). incidentally

> Now, I think I know what you will say: what happens if you do need  
> everything to update all at once? No problem. You can do that by  
> writing your handler to trap a different trigger; for example, trap  
> preOpenStack to loop through the cards and run the doCalcStuff  
> handler on each one when the stack first opens, or trap  
> preOpenBackground to do the same for only a subset of cards. Or  
> trap closeStack in your Preferences stack and run the doCalcStuff  
> then; that way when the prefs stack closes, all the fields,  
> buttons, controls, whatever are updated when the user changes  
> preference settings.

But using this you are looping thru each card regardless of whether  
they need that type of action or not. With my method only the objects  
that are listening for  the particular action are called and then  
only if that action has changed since the last time it was run.

> The result is just what you have described, if I understand your  
> method correctly. And there is only one script to manage it all.  
> The objects themselves need nothing more than a property or a name,  
> and in many situations they don't even need that. Sometimes a  
> generic check is all you need; i.e., checking to see if the field  
> contains a number, or if its owner is a particular group, or if its  
> backgroundcolor is green, or its short name is "lbl" (one of my  
> favorite tests, I use it all the time to update object labels on  
> the fly.)

Exactly! You have one monster routine that handles everything, and  
you have to change it whenever a new object or a new object type is  
added. I would say that this is very error prone, since when you  
change it you are potentially affecting ALL objects. Say you had  
objects of type A, B, C but the current card only contained types A  
and C. Now you add type Z and change your routine accordingly. You  
test it and see that type A and C still work and so does Z. But  
without knowing it you have added a side-effect that now stops type B  
from working! Two weeks later you add type B and it doesn't work! Now  
you have to backtrack and find out that you added a side-effect to  
Type B.

With my method adding type Z only affects type Z. If type B is not  
being used then there will be no code for it in the stack, when you  
add type B, type B's code gets added.
>
>> I don't need to open the script editor either! And if I delete an   
>> object then messages just stop being sent to it!
>
> The same applies to the above approach. You would need to open the  
> script editor if you wanted to change the way doCalcStuff works, in  
> either of our methods. With the above approach, a non-existent  
> object can't possibly be dealt with in a handler that specifically  
> works with existing objects.

But I would only open the the scripts on the object I have added and  
I wouldn't need to maintain the "doCalcStuff" routine over many  
stacks and cards. Everything that it needed to drive the object is in  
the ISM library or in the object itself. However, in order to not  
dupe code in every object of type "X", you could write a function/ 
hanlder called "doCalcStuffForTypeX" and put it in the stack or card  
script or in a library stack. Then call this from all objects of type  
"X".

>> ISM is a library so I am using this technique.
>
> Most libraries do not rely on anything but themselves; if your  
> system requires that every object have its own "listening" handler,  
> then it isn't really a library, it's more of a whole development  
> system. I would think this would be less portable than a true  
> library, which is generally comprised of only a single script that  
> does not rely on the state of any other objects.

The ISM library does not rely on anything but itself. You only  
require a listening handler if you call ISMListenForMessage() and  
ISMListenForMessage() checks if the handler is defined and returns an  
error if not.

> Apologies for the long message. As I said, since you have your  
> method working now, the above is mostly for anyone who may be  
> interested in a more standard xtalk approach.

I don't see how my way of doing things is in anyway not a standard  
xTalk approach. What we are talking about it the basic Object- 
Oriented programming. The concept of keeping all the house keeping of  
an object in that object and not spread across many different layers.

I guess it's a different way of looking at something and I guess  
people are scared of things that are "different" but there really is  
no need to be. Once I get a chance to do the modifications to ISM I  
will post it on revOnline and you can take a look at it yourself and  
then be in a better position to judge.

All the Best
Dave












More information about the use-livecode mailing list