ralph@world.std.com (Ralph Lombreglia) (01/24/91)
As the "Palette Maker" card of the "Power Tools" stack advises, I've trapped the "Compact Stack" menu item in order to close my palettes before compacting. However, I can't seem to figure out how to make the handler restore the palettes after the compaction. I'm sure there's a simple answer, but I'm stumped. Why does the following *not* work? on doMenu what if what is "Compact Stack" then close window "MyPalette" pass doMenu palette "MyPalette", "345,80" else pass doMenu end doMenu Thanks. Ralph Lombreglia Internet: ralph@world.std.com MCI Mail: rlombreglia Bix: rlombreglia
jdevoto@Apple.COM (Jeanne A. E. DeVoto) (01/24/91)
In article <1991Jan23.234729.7744@world.std.com> ralph@world.std.com (Ralph Lombreglia) writes: >Why does the following *not* work? > >on doMenu what > if what is "Compact Stack" then > close window "MyPalette" > pass doMenu > palette "MyPalette", "345,80" > else pass doMenu >end doMenu The reason this doesn't work is that the "pass" keyword halts the current handler. "Pass" means "forget this handler and just pass the message on to the next level of the message hierarchy." This should work: on doMenu theItem if theItem is "Compact Stack" then close window "MyPalette" send "doMenu Compact Stack" to HyperCard -- avoids recursion palette "MyPalette", "345,80" else pass doMenu end doMenu -- ========= jeanne a. e. devoto ======================================== jdevoto@apple.com | You may not distribute this article under a jdevoto@well.sf.ca.us | compilation copyright without my permission. ______________________________________________________________________ Apple Computer and I are not authorized | CI$: 72411,165 to speak for each other. |
jk3t+@andrew.cmu.edu (Jonathan King) (01/24/91)
ralph@world.std.com (Ralph Lombreglia) writes: > However, I can't seem to figure out how to make > the handler restore the palettes after the compaction. I'm sure > there's a simple answer, but I'm stumped. Why does the following > *not* work? > > on doMenu what > if what is "Compact Stack" then > close window "MyPalette" > pass doMenu ^^^^ ^^^^^^ > palette "MyPalette", "345,80" > else pass doMenu > end doMenu Your problem is this: the keyword "pass", in addition to passing a message along the message path *immediately stops execution of the handler*. So, in this case, your palette command never executes. Note that the obvious workaround, replacing "pass domenu" with "domenu Compact Stack" could make your handler trip over itself. Using 'send "domenu Compact Stack" to Hypercard' will probably work, but it facistically bypasses any other handlers on the way that want to prepare for stack compaction. About the best you can do here, it would seem, is to send the "domenu" one notch higher along the message path. So, if this handler were on a card, it would read: on doMenu what if what is "Compact Stack" then close window "MyPalette" send "domenu Compact Stack" to this background palette "MyPalette", "345,80" else pass doMenu end doMenu > Thanks. Hope this works... jking
ech@cbnewsk.att.com (ned.horvath) (01/25/91)
In article <1991Jan23.234729.7744@world.std.com> ralph@world.std.com (Ralph Lombreglia) writes: >Why does the following *not* work? >on doMenu what > if what is "Compact Stack" then > close window "MyPalette" > pass doMenu > palette "MyPalette", "345,80" > else pass doMenu >end doMenu From article <48422@apple.Apple.COM>, by jdevoto@Apple.COM (Jeanne A. E. DeVoto): > The reason this doesn't work is that the "pass" keyword halts the current > handler. "Pass" means "forget this handler and just pass the message on > to the next level of the message hierarchy." > > This should work: > > on doMenu theItem > if theItem is "Compact Stack" then > close window "MyPalette" > send "doMenu Compact Stack" to HyperCard -- avoids recursion > palette "MyPalette", "345,80" > else pass doMenu > end doMenu This isn't quite satisfactory: in general, you want to give all the rest of the doMenu handlers in the handler chain a shot at the Compact Stack message. But as far as I know, the only way to refer to "the next handler in the chain" is to pass to it. Why is this reminiscent of "don't tail patch"? =Ned Horvath= ehorvath@attmail.com has to know
John_Miller@mindlink.UUCP (John Miller) (01/29/91)
> Ok, but what if you're the top stack in the stacksInUse and > there's another stack below you that also has a doMenu > handler that closes its windows? If you send the command > straight to HyperCard the other stacks never get it. I've > been wrestling with this general problem (passing on a message > so other stacks get it but still doing something after the > message is "finished") and I haven't come up with a good solution. > I've resorted to setting a global flag and checking it in an idle > handler, but I don't really like doing it that way. Would it be > better to find my stack's place in the stacksInUse list and send > the message on to the following stack? Any suggestions? A solution is to use a global variable, but it doesn't have to be within the idle handler. It can all be handled within the doMenu menu handler. The trick is to deliberately cause one level of recursion. This code relies on the fact that a global variable that is declared but not initialized is considered to be empty: a very useful feature of HyperTalk. on doMenu theItem -- This global is only declared in this handler: nowhere else global amRecursing if amRecursing is not empty then play flute -- Remove from production code :) pass doMenu else if theItem is "Compact Stack" then close window "MyPalette" put true into amRecursing -- Any non-empty value would do send "doMenu Compact Stack" to me -- causes recursion play boing -- Remove from production code :) put empty into amRecursing palette "MyPalette", "345,80" else pass doMenu end if end doMenu Actually, is the warning about hiding palettes valid? HyperCard doesn't complain when I try to compact a stack with a custom palette. It does complain when I try to compact a stack X that contains a windoid that is controlled by an XCMD located in stack X. Presumably, the Palette XCMD "lets go" of the PLTE and PICT resources once it has created the window. (Yes? No?) An unrelated palette question: is the format of the PLTE resource documented or do I have to reverse-engineer it. I was thinking of creating some XCMDs that would allow customization: "If you don't like the default look of the windoid, create your own palette using the Palette Maker. Your palette should have four buttons: the first will invoke ... the second will invoke ...." ---------------------------------------------------------------------- John Miller (604) 433-1795 Symplex Systems AppleLink (rarely) CDA0461 Burnaby, British Columbia Fax: (604) 430-8516 Canada usenet: john_miller@mindlink.uucp ----------------------------------------------------------------------
taylorj@yvax.byu.edu (01/30/91)
In <48422@apple.Apple.COM>, jdevoto@Apple.COM (Jeanne A. E. DeVoto) writes: > on doMenu theItem > if theItem is "Compact Stack" then > close window "MyPalette" > send "doMenu Compact Stack" to HyperCard -- avoids recursion > palette "MyPalette", "345,80" > else pass doMenu > end doMenu Ok, but what if you're the top stack in the stacksInUse and there's another stack below you that also has a doMenu handler that closes its windows? If you send the command straight to HyperCard the other stacks never get it. I've been wrestling with this general problem (passing on a message so other stacks get it but still doing something after the message is "finished") and I haven't come up with a good solution. I've resorted to setting a global flag and checking it in an idle handler, but I don't really like doing it that way. Would it be better to find my stack's place in the stacksInUse list and send the message on to the following stack? Any suggestions? Jim Taylor Microcomputer Support for Curriculum | Brigham Young University | Bitnet: taylorj@byuvax.bitnet 101 HRCB, Provo, UT 84602 | Internet: taylorj@yvax.byu.edu
jk3t+@andrew.cmu.edu (Jonathan King) (01/31/91)
taylorj@yvax.byu.edu writes: > In <48422@apple.Apple.COM>, jdevoto@Apple.COM (Jeanne A. E. DeVoto) writes: > > > on doMenu theItem > > if theItem is "Compact Stack" then > > close window "MyPalette" > > send "doMenu Compact Stack" to HyperCard -- avoids recursion > > palette "MyPalette", "345,80" > > else pass doMenu > > end doMenu > > Ok, but what if you're the top stack in the stacksInUse and there's > another stack below you that also has a doMenu handler that closes > its windows? If you send the command straight to HyperCard the > other stacks never get it. Yup. I pointed this out, too, in my response to this message. And the problem isn't just limited to stacks in use; it could occur anywhere you send a message to Hypercard. But it's a particular problem when possibly several different handlers along the message path have to handle a message or Bad Things happen. > I've been wrestling with this general problem (passing on a message > so other stacks get it but still doing something after the message > is "finished") and I haven't come up with a good solution. I've > resorted to setting a global flag and checking it in an idle handler, > but I don't really like doing it that way. Would it be better to > find my stack's place in the stacksInUse list and send > the message on to the following stack? Any suggestions? I've come to the decision that too many global flag/ idle handler combos are a Bad Thing, although they can be unavoidable sometimes. I once started writing a function nextobject(current object) that would return the next object in the message passing hierarchy given the name of the current object, but it got pretty hairy and inelegant. You had to chase down the background of a card, (not too hard, but it isn't included in the long name of the card), test if you were "Home", maybe sort through the stacksinuse...I just didn't want to do the general case badly enough. And anyway, it seemed really obvious that there should be something like "the next handler" in the language itself to cover this situation: send "foo" to the next handler. Any chance of seeing this in a future version of Hypercard? jking
jdevoto@Apple.COM (Jeanne A. E. DeVoto) (02/03/91)
In article <8bdsGB_00WB4E=Yksu@andrew.cmu.edu> jk3t+@andrew.cmu.edu (Jonathan King)(>) and taylorj@yvax.byu.edu point out a problem with my handler: on doMenu theItem if theItem is "Compact Stack" then close window "MyPalette" send "doMenu Compact Stack" to HyperCard -- avoids recursion palette "MyPalette", "345,80" else pass doMenu end doMenu and more generally with handlers that send their parameters to HyperCard to avoid infinite recursion problems: >> Ok, but what if you're the top stack in the stacksInUse and there's >> another stack below you that also has a doMenu handler that closes >> its windows? If you send the command straight to HyperCard the >> other stacks never get it. > >Yup. I pointed this out, too, in my response to this message. And >the problem isn't just limited to stacks in use; it could occur >anywhere you send a message to Hypercard. But it's a particular >problem when possibly several different handlers along the message >path have to handle a message or Bad Things happen. Here is an improvement. The below is not quite a general case solution, since it won't work in a card script (because doMenu is initially sent to the current card, "the target" will be the same as "me", resulting in passing the doMenu without doing the palette manipulations, if the below handler is in a card's script). However, most handlers of this type are in a background or stack script in any case. on doMenu theItem if theItem is "Compact Stack" then if the target is not the name of me then -- first pass close window "My Palette" send "doMenu Compact Stack" to me palette "My Palette","345,80" else -- second pass pass doMenu end if else pass doMenu end doMenu This avoids the use of a global flag to determine whether the handler has recursed; instead, the message is sent to "me" the first time around, and on the second pass, the target is therefore the same as "me". The handler checks for this and simply passes the message in this case. The message logic looks like this: doMenu (sent as system message when user chooses the menu item) close doMenu (sent to "me" by doMenu handler) pass doMenu up the hierarchy, and afterwards palette (performed by the original doMenu handler) -- ========= jeanne a. e. devoto ======================================== jdevoto@apple.com | You may not distribute this article under a jdevoto@well.sf.ca.us | compilation copyright without my permission. ______________________________________________________________________ Apple Computer and I are not authorized | CI$: 72411,165 to speak for each other. |