miércoles, 1 de julio de 2009

Quiz: ¿Cómo mejorar esta clase?

Que tal,
les dejo un problema para pensar, no es muy largo ni difícil, con 10 minutos imagino que pueden encontrar la manera de resolverlo. El problema es el siguiente: hay que mejorar el código de la clase MouseOverHandler que se encuentra en Squeak o Pharo, en particular el método #processMouseOver: anEvent.
El motivo por el cual seleccioné este problema se debe a que últimamente en la imagen de Pharo en condiciones aún no encontradas, el método #noticeMouseOver: aMorph event: anEvent envía el mensaje #includes: a nil.
Lo interesante del problema es:
1) Entender como funcionan las instancias de esta clase
2) Encontrar el motivo de por qué funciona incorrectamente el mensaje #noticeMouseOver: aMorph event: anEvent
3) Pensar cómo se puede generar información que confirme lo encontrado en el punto 2
4) El objetivo de este post, mejorar el diseño de esta clase.
Acá está el código por si no tienen ganas de abrir un Squeak/Pharo.
---------------------------
Object subclass: #MouseOverHandler
instanceVariableNames: 'mouseOverMorphs enteredMorphs overMorphs leftMorphs'
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Events'
---------------------------
initialize
super initialize.
mouseOverMorphs := #().
---------------------------
processMouseOver: anEvent
"Re-establish the z-order for all morphs wrt the given event"

| hand localEvt focus evt |
hand := anEvent hand.
leftMorphs := mouseOverMorphs asIdentitySet.
"Assume some coherence for the number of objects in over list"
overMorphs := WriteStream on: (Array new: leftMorphs size).
enteredMorphs := WriteStream on: #().
"Now go looking for eventual mouse overs"
hand handleEvent: anEvent asMouseOver.
"Get out early if there's no change"
(leftMorphs isEmpty and: [enteredMorphs position = 0])
ifTrue: [^leftMorphs := enteredMorphs := overMorphs := nil].
focus := hand mouseFocus.
"Send #mouseLeave as appropriate"
evt := anEvent asMouseLeave.
"Keep the order of the left morphs by recreating it from the mouseOverMorphs"
leftMorphs size > 1
ifTrue: [leftMorphs := mouseOverMorphs select: [:m | leftMorphs includes: m]].
leftMorphs do:
[:m |
(m == focus or: [m hasOwner: focus])
ifTrue:
[localEvt := evt transformedBy: (m transformedFrom: hand).
m handleEvent: localEvt]
ifFalse: [overMorphs nextPut: m]].
"Send #mouseEnter as appropriate"
evt := anEvent asMouseEnter.
enteredMorphs ifNil:
["inform: was called in handleEvent:"

^leftMorphs := enteredMorphs := overMorphs := nil].
enteredMorphs := enteredMorphs contents.
enteredMorphs reverseDo:
[:m |
(m == focus or: [m hasOwner: focus])
ifTrue:
[localEvt := evt transformedBy: (m transformedFrom: hand).
m handleEvent: localEvt]].
"And remember the over list"
overMorphs ifNil:
["inform: was called in handleEvent:"

^leftMorphs := enteredMorphs := overMorphs := nil].
mouseOverMorphs := overMorphs contents.
leftMorphs := enteredMorphs := overMorphs := nil
---------------------------
noticeMouseOver: aMorph event: anEvent
"Remember that the mouse is currently over some morph"
(leftMorphs includes: aMorph)
ifTrue:[leftMorphs remove: aMorph]
ifFalse:[enteredMorphs nextPut: aMorph].
overMorphs nextPut: aMorph.

No hay comentarios.: