David Burgun wrote:

  on preOpenCard
      repeat with i = 1 to the number of flds
        if the lockText of fld i is false then
           put empty into fld i
        end if
      end repeat
      pass preOpenCard
  end preOpenCard


Yes, but this only works for fields and it only works on *all* fields, what if you wanted to leave the field untouched from the last time it was used.

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.

Maybe a better example is this. I have a preferences stack, one of the items on it is the unit of measurement, it can be set to MM, CM or Inches. I have a couple of groups in my Group Library to do with measure. One of them has the following fields:

[] = a field
<> = variable value

[Width:]   [ <value_in_units>]   [<Units>]
[Height:]  [ <value_in_units>]  [<Units>]

If the units were set to CM and the values were 100.

Now the user opens the preferences stack and changes the units to MM. I want all <Units> values to change from CM to MM and I want 100 CM's to now be 1000 MM's.

Using ISM, I would do this in the script for the Value and Units fields:

ListenForMessage("PrefsMeasureUnits",kMeasureUnits)

and define the following handlers for the <Units> fields:

on PrefsMeasureUnits theMessageID, theSubClass, theUnitValue
set the text of the long id of me to theUnitValue
end

and on the <value_in_units> fields:

on PrefsMeasureUnits theMessageID, theSubClass, theUnitValue
put CalcualteNewValue(the text of the long id of me, theUnitValue) into myNewValue
set the text of the long id of me to myNewValue
end

And in the script of the popup menu in the preferences stack, I'd write:
get ISMPutMessage("PrefsMeasureUnits", kMeasureUnits,theNewUnitsValue)

And any object in any card on any stack can "listen" for the message, so they all initialize to the correct value. I therefore only need to change the value once, not once for each object.

I think we all do something very similar in most of our stacks, it is a very common goal. And since you now have your method working, there's no point in changing it. But for those who may be curious, I'd accomplish the goal differently and, I think, with less work and far fewer scripts.

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.

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.

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.

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.

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.

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.)

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.

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.

I really don't know
anything about front or back scripts, and to be honest the lack of good documentation has put me off looking at them.

These seem to be pretty well covered in the docs, though the concept is so simple there isn't much to say about them. Look up the "insert" command for starters. A backscript allows you to insert any script you like into the message hierarchy, and is typically how libraries are implemented. They allow you to manipulate the message hierarchy at will and make use of Revolution's native message passing rules rather than trying to add a secondary system on top of the existing one.

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.

--
Jacqueline Landman Gay         |     [EMAIL PROTECTED]
HyperActive Software           |     http://www.hyperactivesw.com
_______________________________________________
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