MorphicEventHandler behavior.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

MorphicEventHandler behavior.

Stéphane Ducasse
Hi fernando

May be you know more than me on MorphicEventHandler.

Gofer new
         squeaksource: 'PharoNonCorePackages';
        package: 'Sound';
        package: 'SoundMorphicUserInterface';
        load.



While trying to make
        PianoKeyboardMorph new openInWorld
        (which works in 1.4 and does not in 20).

It breaks here:

-------------
mouseUpPitch: pitch event: event noteMorph: noteMorph

        noteMorph color: ((#(0 1 3 5 6 8 10) includes: pitch \\12)
                                        ifTrue: [whiteKeyColor]
                                        ifFalse: [blackKeyColor]).
        soundPlaying ifNotNil: [soundPlaying stopGracefully].

pitch is nil because notify:from: uses valueParameter which is nil.
-------------

mouseUpPitch is invoked by notify: anEvent from: sourceMorph which is invoked by notifyMorphsOfEvent: anEvent ofType: eventType from: sourceMorph

notify: anEvent from: sourceMorph
        | arity |
        recipient ifNil: [^ self].
        arity := selector numArgs.
        arity = 0 ifTrue:
                [^ recipient perform: selector].
        arity = 1 ifTrue:
                [^ recipient perform: selector with: anEvent].
        arity = 2 ifTrue:
                [^ recipient perform: selector with: anEvent with: sourceMorph].
        arity = 3 ifTrue:
                [^ recipient perform: selector with: valueParameter with: anEvent with: sourceMorph].
                                                                        ^^^^^^^^^^^^^^^^^^^^^^^
        self error: 'Event handling selectors must be Symbols and take 0-3 arguments'

notifyMorphsOfEvent: anEvent ofType: eventType from: sourceMorph
        | result |
        result := false.
        ((subscriptions includesKey: eventType) not or: [ (subscriptions at: eventType) isEmpty ])
                ifTrue: [ ^false ].
        (subscriptions at: eventType) do: [ :s | result := result | ((s notify: anEvent from: sourceMorph) == true) ].
                                                                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        ^result


The idea is that morphs get notified when a certain event occurs so when we look at the morph creation and event registry we get:


The buildKeyboard create morph and define event with a given value that will be used
        on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self withValue: i-1*12 + (#(2 4 7 9 11) at: j)
below:


buildKeyboard
        | wtWid bkWid keyRect octavePt nWhite nBlack |
        self removeAllMorphs.
        wtWid := 8. bkWid := 5.
        self extent: 10@10.
        1 to: nOctaves+1 do:
                [:i | i <= nOctaves ifTrue: [nWhite := 7.  nBlack := 5]
                                                ifFalse: [nWhite := 1.  nBlack := 0 "High C"].
                octavePt := self innerBounds topLeft + ((7*wtWid*(i-1)-1) @ -1).
                1 to: nWhite do:
                        [:j | keyRect := octavePt + (j-1*wtWid@0) extent: (wtWid+1)@36.
                        self addMorph: ((RectangleMorph newBounds: keyRect color: whiteKeyColor)
                                                                borderWidth: 1;
                                on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: i-1*12 + (#(1 3 5 6 8 10 12) at: j))].
                1 to: nBlack do:
                        [:j | keyRect := octavePt + ((#(6 15 29 38 47) at: j)@1) extent: bkWid@21.
                        self addMorph: ((Morph newBounds: keyRect color: blackKeyColor)
                                on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: i-1*12 + (#(2 4 7 9 11) at: j))]].
        self submorphsDo:
                [:m | m on: #mouseMove send: #mouseMovePitch:event:noteMorph: to: self;
                                on: #mouseUp send: #mouseUpPitch:event:noteMorph: to: self;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self;
                                on: #mouseLeaveDragging send: #mouseUpPitch:event:noteMorph: to: self].
        self extent: (self fullBounds extent + borderWidth - 1)



Now I can understand that
        #mouseDownPitch:event:noteMorph: get notified with a value because this is what is written.
But I do not get why this would be the case with #mouseUpPitch:event:noteMorph:
since we simply get
        on: #mouseUp send: #mouseUpPitch:event:noteMorph: to: self;


And I do not get why this was working in 1.4








Reply | Threaded
Open this post in threaded view
|

Re: MorphicEventHandler behavior.

Guillermo Polito
Steph, 

I was looking and in the end of #buildKeyboard you have:

self submorphsDo:
                [:m | m on: #mouseMove send: #mouseMovePitch:event:noteMorph: to: self;
                                on: #mouseUp send: #mouseUpPitch:event:noteMorph: to: self;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self;
                                on: #mouseLeaveDragging send: #mouseUpPitch:event:noteMorph: to: self].

Which create subscriptions without any value. And that's why you get the nil and the DNU.

It probably was working in 1.4 because the EventHandler code did only manage one subscription at a time and probably didn't notice these last subscriptions. Now int 2.0 all subscriptions to events are handled, and that's the reason of the DNU.

I tested the code without that statement and get it work..

Guille

On Sun, Mar 10, 2013 at 11:01 AM, Stéphane Ducasse <[hidden email]> wrote:
Hi fernando

May be you know more than me on MorphicEventHandler.

Gofer new
         squeaksource: 'PharoNonCorePackages';
        package: 'Sound';
        package: 'SoundMorphicUserInterface';
        load.



While trying to make
        PianoKeyboardMorph new openInWorld
        (which works in 1.4 and does not in 20).

It breaks here:

-------------
mouseUpPitch: pitch event: event noteMorph: noteMorph

        noteMorph color: ((#(0 1 3 5 6 8 10) includes: pitch \\12)
                                        ifTrue: [whiteKeyColor]
                                        ifFalse: [blackKeyColor]).
        soundPlaying ifNotNil: [soundPlaying stopGracefully].

pitch is nil because notify:from: uses valueParameter which is nil.
-------------

mouseUpPitch is invoked by notify: anEvent from: sourceMorph which is invoked by notifyMorphsOfEvent: anEvent ofType: eventType from: sourceMorph

notify: anEvent from: sourceMorph
        | arity |
        recipient ifNil: [^ self].
        arity := selector numArgs.
        arity = 0 ifTrue:
                [^ recipient perform: selector].
        arity = 1 ifTrue:
                [^ recipient perform: selector with: anEvent].
        arity = 2 ifTrue:
                [^ recipient perform: selector with: anEvent with: sourceMorph].
        arity = 3 ifTrue:
                [^ recipient perform: selector with: valueParameter with: anEvent with: sourceMorph].
                                                                        ^^^^^^^^^^^^^^^^^^^^^^^
        self error: 'Event handling selectors must be Symbols and take 0-3 arguments'

notifyMorphsOfEvent: anEvent ofType: eventType from: sourceMorph
        | result |
        result := false.
        ((subscriptions includesKey: eventType) not or: [ (subscriptions at: eventType) isEmpty ])
                ifTrue: [ ^false ].
        (subscriptions at: eventType) do: [ :s | result := result | ((s notify: anEvent from: sourceMorph) == true) ].
                                                                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        ^result


The idea is that morphs get notified when a certain event occurs so when we look at the morph creation and event registry we get:


The buildKeyboard create morph and define event with a given value that will be used
        on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self withValue: i-1*12 + (#(2 4 7 9 11) at: j)
below:


buildKeyboard
        | wtWid bkWid keyRect octavePt nWhite nBlack |
        self removeAllMorphs.
        wtWid := 8. bkWid := 5.
        self extent: 10@10.
        1 to: nOctaves+1 do:
                [:i | i <= nOctaves ifTrue: [nWhite := 7.  nBlack := 5]
                                                ifFalse: [nWhite := 1.  nBlack := 0 "High C"].
                octavePt := self innerBounds topLeft + ((7*wtWid*(i-1)-1) @ -1).
                1 to: nWhite do:
                        [:j | keyRect := octavePt + (j-1*wtWid@0) extent: (wtWid+1)@36.
                        self addMorph: ((RectangleMorph newBounds: keyRect color: whiteKeyColor)
                                                                borderWidth: 1;
                                on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: i-1*12 + (#(1 3 5 6 8 10 12) at: j))].
                1 to: nBlack do:
                        [:j | keyRect := octavePt + ((#(6 15 29 38 47) at: j)@1) extent: bkWid@21.
                        self addMorph: ((Morph newBounds: keyRect color: blackKeyColor)
                                on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: i-1*12 + (#(2 4 7 9 11) at: j))]].
        self submorphsDo:
                [:m | m on: #mouseMove send: #mouseMovePitch:event:noteMorph: to: self;
                                on: #mouseUp send: #mouseUpPitch:event:noteMorph: to: self;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self;
                                on: #mouseLeaveDragging send: #mouseUpPitch:event:noteMorph: to: self].
        self extent: (self fullBounds extent + borderWidth - 1)



Now I can understand that
        #mouseDownPitch:event:noteMorph: get notified with a value because this is what is written.
But I do not get why this would be the case with #mouseUpPitch:event:noteMorph:
since we simply get
        on: #mouseUp send: #mouseUpPitch:event:noteMorph: to: self;


And I do not get why this was working in 1.4









Reply | Threaded
Open this post in threaded view
|

Re: MorphicEventHandler behavior.

stephane ducasse

On Mar 10, 2013, at 5:41 PM, Guillermo Polito <[hidden email]> wrote:

Steph, 

I was looking and in the end of #buildKeyboard you have:

self submorphsDo:
                [:m | m on: #mouseMove send: #mouseMovePitch:event:noteMorph: to: self;
                                on: #mouseUp send: #mouseUpPitch:event:noteMorph: to: self;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self;
                                on: #mouseLeaveDragging send: #mouseUpPitch:event:noteMorph: to: self].

Which create subscriptions without any value. And that's why you get the nil and the DNU.

Yes! this is exactly that. 

It probably was working in 1.4 because the EventHandler code did only manage one subscription at a time and probably didn't notice these last subscriptions.
I have the impression that the code logic relied on the fact that the Event got state.

Now int 2.0 all subscriptions to events are handled, and that's the reason of the DNU.

I tested the code without that statement and get it work..

I did not thought about removing it. 
Now I tried and the problem is that the pressed key stay red. 


Guille

On Sun, Mar 10, 2013 at 11:01 AM, Stéphane Ducasse <[hidden email]> wrote:
Hi fernando

May be you know more than me on MorphicEventHandler.

Gofer new
         squeaksource: 'PharoNonCorePackages';
        package: 'Sound';
        package: 'SoundMorphicUserInterface';
        load.



While trying to make
        PianoKeyboardMorph new openInWorld
        (which works in 1.4 and does not in 20).

It breaks here:

-------------
mouseUpPitch: pitch event: event noteMorph: noteMorph

        noteMorph color: ((#(0 1 3 5 6 8 10) includes: pitch <a href="smb://12">\\12)
                                        ifTrue: [whiteKeyColor]
                                        ifFalse: [blackKeyColor]).
        soundPlaying ifNotNil: [soundPlaying stopGracefully].

pitch is nil because notify:from: uses valueParameter which is nil.
-------------

mouseUpPitch is invoked by notify: anEvent from: sourceMorph which is invoked by notifyMorphsOfEvent: anEvent ofType: eventType from: sourceMorph

notify: anEvent from: sourceMorph
        | arity |
        recipient ifNil: [^ self].
        arity := selector numArgs.
        arity = 0 ifTrue:
                [^ recipient perform: selector].
        arity = 1 ifTrue:
                [^ recipient perform: selector with: anEvent].
        arity = 2 ifTrue:
                [^ recipient perform: selector with: anEvent with: sourceMorph].
        arity = 3 ifTrue:
                [^ recipient perform: selector with: valueParameter with: anEvent with: sourceMorph].
                                                                        ^^^^^^^^^^^^^^^^^^^^^^^
        self error: 'Event handling selectors must be Symbols and take 0-3 arguments'

notifyMorphsOfEvent: anEvent ofType: eventType from: sourceMorph
        | result |
        result := false.
        ((subscriptions includesKey: eventType) not or: [ (subscriptions at: eventType) isEmpty ])
                ifTrue: [ ^false ].
        (subscriptions at: eventType) do: [ :s | result := result | ((s notify: anEvent from: sourceMorph) == true) ].
                                                                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        ^result


The idea is that morphs get notified when a certain event occurs so when we look at the morph creation and event registry we get:


The buildKeyboard create morph and define event with a given value that will be used
        on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self withValue: i-1*12 + (#(2 4 7 9 11) at: j)
below:


buildKeyboard
        | wtWid bkWid keyRect octavePt nWhite nBlack |
        self removeAllMorphs.
        wtWid := 8. bkWid := 5.
        self extent: 10@10.
        1 to: nOctaves+1 do:
                [:i | i <= nOctaves ifTrue: [nWhite := 7.  nBlack := 5]
                                                ifFalse: [nWhite := 1.  nBlack := 0 "High C"].
                octavePt := self innerBounds topLeft + ((7*wtWid*(i-1)-1) @ -1).
                1 to: nWhite do:
                        [:j | keyRect := octavePt + (j-1*wtWid@0) extent: (wtWid+1)@36.
                        self addMorph: ((RectangleMorph newBounds: keyRect color: whiteKeyColor)
                                                                borderWidth: 1;
                                on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: i-1*12 + (#(1 3 5 6 8 10 12) at: j))].
                1 to: nBlack do:
                        [:j | keyRect := octavePt + ((#(6 15 29 38 47) at: j)@1) extent: bkWid@21.
                        self addMorph: ((Morph newBounds: keyRect color: blackKeyColor)
                                on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: i-1*12 + (#(2 4 7 9 11) at: j))]].
        self submorphsDo:
                [:m | m on: #mouseMove send: #mouseMovePitch:event:noteMorph: to: self;
                                on: #mouseUp send: #mouseUpPitch:event:noteMorph: to: self;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self;
                                on: #mouseLeaveDragging send: #mouseUpPitch:event:noteMorph: to: self].
        self extent: (self fullBounds extent + borderWidth - 1)



Now I can understand that
        #mouseDownPitch:event:noteMorph: get notified with a value because this is what is written.
But I do not get why this would be the case with #mouseUpPitch:event:noteMorph:
since we simply get
        on: #mouseUp send: #mouseUpPitch:event:noteMorph: to: self;


And I do not get why this was working in 1.4










Reply | Threaded
Open this post in threaded view
|

Re: MorphicEventHandler behavior.

stephane ducasse
In reply to this post by Guillermo Polito
Guillermo

can you try if the following method works with you?
I folded the external register inside each note.

Stef



buildKeyboard
        | wtWid bkWid keyRect octavePt nWhite nBlack |
        self removeAllMorphs.
        wtWid := 8. bkWid := 5.
        self extent: 10@10.
        1 to: nOctaves+1 do:
                [:i | i <= nOctaves ifTrue: [nWhite := 7.  nBlack := 5]
                                                ifFalse: [nWhite := 1.  nBlack := 0 "High C"].
                octavePt := self innerBounds topLeft + ((7*wtWid*(i-1)-1) @ -1).
                1 to: nWhite do:
                        [:j | | val |
                        keyRect := octavePt + (j-1*wtWid@0) extent: (wtWid+1)@36.
                        val := i-1*12 + (#(1 3 5 6 8 10 12) at: j).
                        self addMorph: ((RectangleMorph newBounds: keyRect color: whiteKeyColor)
                                                                borderWidth: 1;
                                on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: val;
                                on: #mouseUp
                                        send: #mouseUpPitch:event:noteMorph:
                                        to: self
                                        withValue: val;
                                on: #mouseLeaveDragging
                                        send: #mouseUpPitch:event:noteMorph:
                                        to: self
                                        withValue: val;
                                on: #mouseMove
                                        send: #mouseMovePitch:event:noteMorph:
                                        to: self
                                        withValue: val;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: val)
                                                                ].
                1 to: nBlack do:
                        [:j | |val|
                        keyRect := octavePt + ((#(6 15 29 38 47) at: j)@1) extent: bkWid@21.
                        val := i-1*12 + (#(2 4 7 9 11) at: j).
                        self addMorph: ((Morph newBounds: keyRect color: blackKeyColor)
                                on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: val;
                                on: #mouseUp
                                        send: #mouseUpPitch:event:noteMorph:
                                        to: self
                                        withValue: val ;
                                on: #mouseLeaveDragging
                                        send: #mouseUpPitch:event:noteMorph:
                                        to: self
                                        withValue: val;
                                on: #mouseMove
                                        send: #mouseMovePitch:event:noteMorph:
                                        to: self
                                        withValue: val;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: val
                                        )]].
        "self submorphsDo:
                [:m | m on: #mouseMove send: #mouseMovePitch:event:noteMorph: to: self;
                                on: #mouseUp send: #mouseUpPitch:event:noteMorph: to: self;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self;
                                on: #mouseLeaveDragging send: #mouseUpPitch:event:noteMorph: to: self]."
        self extent: (self fullBounds extent + borderWidth - 1)
Reply | Threaded
Open this post in threaded view
|

Re: MorphicEventHandler behavior.

Guillermo Polito
Yes it does :)

On Sun, Mar 10, 2013 at 10:26 PM, stephane ducasse <[hidden email]> wrote:
Guillermo

can you try if the following method works with you?
I folded the external register inside each note.

Stef



buildKeyboard
        | wtWid bkWid keyRect octavePt nWhite nBlack |
        self removeAllMorphs.
        wtWid := 8. bkWid := 5.
        self extent: 10@10.
        1 to: nOctaves+1 do:
                [:i | i <= nOctaves ifTrue: [nWhite := 7.  nBlack := 5]
                                                ifFalse: [nWhite := 1.  nBlack := 0 "High C"].
                octavePt := self innerBounds topLeft + ((7*wtWid*(i-1)-1) @ -1).
                1 to: nWhite do:
                        [:j | | val |
                        keyRect := octavePt + (j-1*wtWid@0) extent: (wtWid+1)@36.
                        val := i-1*12 + (#(1 3 5 6 8 10 12) at: j).
                        self addMorph: ((RectangleMorph newBounds: keyRect color: whiteKeyColor)
                                                                borderWidth: 1;
                                on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: val;
                                on: #mouseUp
                                        send: #mouseUpPitch:event:noteMorph:
                                        to: self
                                        withValue: val;
                                on: #mouseLeaveDragging
                                        send: #mouseUpPitch:event:noteMorph:
                                        to: self
                                        withValue: val;
                                on: #mouseMove
                                        send: #mouseMovePitch:event:noteMorph:
                                        to: self
                                        withValue: val;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: val)
                                                                ].
                1 to: nBlack do:
                        [:j | |val|
                        keyRect := octavePt + ((#(6 15 29 38 47) at: j)@1) extent: bkWid@21.
                        val := i-1*12 + (#(2 4 7 9 11) at: j).
                        self addMorph: ((Morph newBounds: keyRect color: blackKeyColor)
                                on: #mouseDown send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: val;
                                on: #mouseUp
                                        send: #mouseUpPitch:event:noteMorph:
                                        to: self
                                        withValue: val  ;
                                on: #mouseLeaveDragging
                                        send: #mouseUpPitch:event:noteMorph:
                                        to: self
                                        withValue: val;
                                on: #mouseMove
                                        send: #mouseMovePitch:event:noteMorph:
                                        to: self
                                        withValue: val;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self
                                                                withValue: val
                                        )]].
        "self submorphsDo:
                [:m | m on: #mouseMove send: #mouseMovePitch:event:noteMorph: to: self;
                                on: #mouseUp send: #mouseUpPitch:event:noteMorph: to: self;
                                on: #mouseEnterDragging send: #mouseDownPitch:event:noteMorph: to: self;
                                on: #mouseLeaveDragging send: #mouseUpPitch:event:noteMorph: to: self]."
        self extent: (self fullBounds extent + borderWidth - 1)