Mantis - tweak
Viewing Issue Advanced Details
47 major always 07-29-04 21:56 08-01-04 03:22
sriggins  
andreas  
normal  
resolved  
fixed  
none    
none  
0000047: Cannot assign more than one runScript to an object
This example shows how we want two buttons to fire the same message but Tweak only remembers the last runScript put on an object for a method.

CObject subclass: #ClassToTrigger
    instanceVariableNames: '<?xml version="1.0"?><fields></fields>'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'scriptbug'!

!ClassToTrigger methodsFor: 'script' stamp: 'swr 7/29/2004 12:20'!
onBoo
    Transcript show: 'Boo'; cr! !


!ClassToTrigger methodsFor: 'demoBug' stamp: 'swr 7/29/2004 12:32'!
demoBug

    | pushButton |

    "This looks like we cannot have more than one handler of a script"
    "Both of these buttons should trigger the onBoo method but they do not"

    pushButton := CPushButton open.
    pushButton label: 'First trigger'.
    pushButton origin: 100@100. />     self runScript: #onBoo when: {pushButton. #fire}.

    pushButton := CPushButton open.
    pushButton label: 'Second trigger'.
    pushButton origin:
200@100. />     self runScript: #onBoo when: {pushButton. #fire}.

! !
If there is a better way to do this, let us know, but this was not clear how this should work from the API, esp since you might have three disparate classes attaching scripts without knowing about the others

Notes
(0000037)
andreas   
07-30-04 04:36   
Here is some background and workaround information:

First of all do NOT use #runScript: - it was used in the early days for synchronous callbacks but it no longer is except in a few extreme low-level situations. Instead use #startScript:.

What really happens is that the above use of two entirely independent event-signaler pairs starting the precise same script triggers a fail-safe mechanism. Almost all of the time where I've seen code like the above the intent was not to trigger the same script from multiple sources but rather to give it a new trigger. (when you think about it, the demo - as nice at is may be as an example - is pretty useless; you might expect that if you have two buttons they pass along an extra argument to that method or similar). This issue used to be a source of constant problems before the introduction of <on:in:> annotations (during this time the manual use of #startScript: was common).

Therefore you currently have to kind of "proove" that you know what you're doing if you really want to do what you're doing above, which you can do in either of two ways:

a) Provide an extra argument to the script (this can be bogus), e.g., have the above say

    self startScript: #onBoo
        withArguments:{pushButton}
        when: {pushButton. #fire}.

This will be distinct for each pushButton and because #onBoo doesn't expect any extra arguments it will be ignored.

b) Provide all of the event-signalers at once, e.g.,

    self startScript: #onBoo when: {
        pushButtonA. fire.
        pushButtonB. fire.
    }.

This is the preferred workaround (if possible, e.g., all of the signalers must be known beforehand).