dburgun at dsl.pipex.com
Sat Mar 25 06:15:22 EST 2006
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
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
> end preOpenCard
> on doCalStuff -- all actual work goes here
> repeat with x = 1 to the number of controls -- or "flds","btns",
> 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
> 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
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
>> 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
More information about the Use-livecode