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









_______________________________________________
use-revolution mailing list
[email protected]
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-revolution

Reply via email to