The current implementation of HandMorph|handleMouseOver: is risky in that, in some circumstances, it can blow up a common mistake and produce a pollution of walkback windows that are hard to close. The side effect is due to the use of the mouseOverTimes dictionary. The keys of this dictionary are morphs and the values are integers representing times in milliseconds. When the keys of the dictionary are enumerated in the fragment:
1 mouseOverTimes keys do: 2 [:m | "Check pending timers for lingering" 3 t _ mouseOverTimes at: m. 4 "and so on"
the code is assuming that m has a well defined hash. If that precondition fails, then the morph m is in the set of keys but the invocation of at: m produces a keyNotFound error. And of course, the error repeats again and again.
IMO this behavior is opposite to the stability of the system for one simple reason: the programmer who creates a Morph subclass must be aware of the fact that each morph is going to be included in a Dictionary and thus she must provide an infallible hash method.
Moreover, the pollution of walkbacks is not in proportion with the offending mistake which is hard to debug and figure out. Think that most of the times, the initialize method for a new morph has a temporary effect: once the morph has been created, it is re-initialized to its full state. Thus a #hash that is correct and stable from a logical point of view, can change in the interim between steps 1 and 3 (see the fragment above).
Since Morphic is a laboratory, we should keep it safe from the accidents produced during experimentation. Specially when this laboratory is being visited by non-experienced users.
A partial solution to this problem is to rehash the dictionary if it fails to access the morph:
1. mouseOverTimes keys do: 2. [:m | "Check pending timers for lingering" 3. t _ mouseOverTimes at: m ifAbsent: [mouseOverTimes rehash at: m]. 4. "and so on"
This solution is partial in that it does not handle all possible defective hashes. But I think it is safe enough. In any case, my intention is not to provide the best solution but to rise a warning about this situation.
/Leandro
PS: I'm sending this mail to Scott since he is the author who last signed the method in 2.5.
PPS: One more time, the MorphicWrappers made this problem apparent.
Leandro -
the code is assuming that m has a well defined hash. If that precondition fails, then the morph m is in the set of keys but the invocation of at: m produces a keyNotFound error. And of course, the error repeats again and again.
An excellent observation!
PS: I'm sending this mail to Scott since he is the author who last signed the method in 2.5.
But it was I who wrote this code originally. I was never in love with the approach, but it did take us forward with mouse-over time-outs. An interim fix would be simply to use an IdentityDictionary, with some solution such as you recommend for the unlikely case of not finding an entry.
PPS: One more time, the MorphicWrappers made this problem apparent.
How would this approach answer the concerns of MorphicWrappers? [You may respond privately].
- Dan
squeak-dev@lists.squeakfoundation.org