We coped with a similar problem in the rich text editor; we needed to  
preserve the selected text before the text area loses focus, which is  
parallel to making your mouseover-widget disappear when you mouse  
off. I think. This might help; it's how we handle the preserve- 
selection-on-mouseout behavior in the rich text editor in laszlo  
mail. The code below is the core of how we do it, and it's all in  
context at:
http://svn.openlaszlo.org/openlaszlo/trunk/lps/components/incubator/ 
rich-text/richtexteditarea.lzx

(I think this implementation falls under the rubric of "For various  
reasons, this line of thinking proved nearly impossible to sort out,"  
as you say.)


  <!--- Forget the selection if we lose focus to a focusable widget, but
             keep the selection if we lose focus to a non-focusable  
widget, like
             the toolbar buttons.
             @param view s: the view which is gaining the selection
         -->
         <method event="onblur" args="s">
             this._fieldhasfocus = false;
             // If we're blurring and the focus is going to anything  
*but* the toolbar
             // widgets, set _ssel and _esel to nothing.
             // Semantically, we want to get rid of the selection if  
we lose focus.
             if (s != null) {
                 // We're really giving focus to something else, so,  
forget
                 // about whatever was selected while this component  
still had focus.
                 // It seems to "feel" right to me to move the cursor  
to the end of
                 // the text.
                 this._ssel = this._esel = this.getText().length;
             }
         </method>


         <!--- If the mouse down is over me or any of my children,  
remember that,
             so we can listen for an onmouseup anywhere. A mouseup  
after a mousedown
             indicates that the selection has changed.
             @param view who: the element being moused down on
         -->
         <method event="onmousedown" reference="LzGlobalMouse"  
args="who"><![CDATA[
             if ((who != null) && (this._containsView(who))) {
                 // the mouse went down on a child of me
                 // Debug.write("mousedown on child of me");
                 this._mousedownorigin = who;
             } else if ((who == null) && (inp.containsPt(this.getMouse 
("x"), this.getMouse("y")))) {
                 // the mouse went down on me
                 // Debug.write("mousedown on me");
                 this._mousedownorigin = this;
             } else {
                 // the mouse went down on someone other than me; i'm  
not interested.
                 this._mousedownorigin = null;
             }
             ]]>
         </method>


         <!--- Listen for global mouse up.
             We're only interested in global mouse up if the editor  
has focus.
             If the editor does have focus,
             is there a mousedown/mouseup pair in progress?
             @param view who: the current mousedown element (ben shine)
         -->
         <method event="onmouseup" reference="LzGlobalMouse" args="who">
             if (this._fieldhasfocus) {
                 // Debug.write("onmouseup, field has focus, who is  
", who);

                 if (this._mousedownorigin != null) {
                     // We have focus, and there _is_ a mousedown/ 
mouseup pair in progress.
                     if (this._mousedownorigin == this) {

                         // The mouse click started on the richtext  
editor.

                         // If the mouse click also ended on the rich  
text editor,
                         // it's just a caret move.
                         if (inp.containsPt(this.getMouse("x"),  
this.getMouse("y"))) {
                             this._caretmove();
                         } else {
                             // If the mouseclick ended anywhere but  
the rich text editor,
                             // it's a lost mousedown.
                             this._handleLostMouseDown();
                         }
                     } else {
                         // We have focus, and there's a mousedown/ 
mouseup pair in progress,
                         // and it started on one of the subviews of  
the RTE.
                         // Debug.write("lost mousedown, origin was  
", this._mousedownorigin);
                     }

                 } else {
                     // We have focus, but there's no mousedown/ 
mouseup pair in progress.
                     // Therefore, do nothing.
                     // Debug.write("No mousedown origin. The  
mousedown didn't start on an RTE component.");
                 }
             }

             // Clear the mousedown attribute; a mouseup means that  
whatever
             // the mousedown was, it's gone now.
             this._mousedownorigin = null;
         </method>

...
       <!---
             Handle the case where a mouse drag began on the RTE but  
the mouse up
             was not on the RTE.
             @keywords private
         -->
         <method name="_handleLostMouseDown">
             var selstart = this._field.getSelectionPosition();
             var selend = selstart + this._field.getSelectionSize();
             this.setCurrentFormat( this.getTextFormat(selstart,  
selend), true);
         </method>

         <!--- Restore last selection region.
             Note: this must be called from a delegate in an idle event
             *after* flash completes the "frame" in which the  
selection or focus
             changed.
               @keywords private -->
         <method name="_restoreSelection">
             //--------------------------------------------------------- 
---
             // FIXME [2005-08-16 pkang]: Need to know in which  
direction
             // selection was done so as to not make scrollbar jump.
             //--------------------------------------------------------- 
---
             this._shouldresettoolbar = false;
             this.setSelection(this._ssel, this._esel);
             this._shouldresettoolbar = true;
         </method>


On May 26, 2006, at 10:08 AM, Neil Mix wrote:

> Thanks Benjamin.  That's some good stuff.  Way beyond me, I think.  ;)
>
> Here's a little more info about the problem I'm facing.  It's  
> pretty unique and edge-casey, but maybe you'll find it interesting.
>
> I'm prototyping a graphical widget that appears when you mouse over  
> the album art on a song slide.  I want to make the widget disappear  
> when you mouse away.  Typically, this would be as easy as catching  
> an onmouseout and hiding the widget.  And flash supports that, even  
> when you mouse off the canvas -- you still get an onmouseout (yet  
> the reported mouse coordinates are still within the bounds of the  
> object).
>
> Here's the trick: this widget contains buttons that also receive  
> mouse events.  Those buttons (of course) have hover effects and  
> various states, and clicking them may cause other objects to appear  
> above the buttons.  The net result is that my widget may never  
> receive a mouseout event, because one of the buttons contained  
> within it may instead receive the mouseout.
>
> What I've ended up doing is attaching event handlers to  
> LzGlobalMouse to catch all onmouseover/onmouseout events and check  
> to see whether or not the current mouse position is within the  
> bounds of the the widget.  This is by far the easiest and most  
> fullproof algorithm.  (Alternative would be to catch onmouseout of  
> the contained buttons directly, and then try to determine why a  
> button received a mouseout, and whether the event is worthy of  
> hiding the container widget or not.  For various reasons, this line  
> of thinking proved nearly impossible to sort out.)
>
> As I've thought about it, I've wondered if what I need is extra  
> info in the mouseout event that tells me which object is going to  
> receive the subsequent mouseover (or null if no object is going to  
> get mouseover).  For example, something like:
>
> <method event="onmousemove" reference="LzGlobalMouse"  
> args="who,where">
>       // "who" is the object that received the mouseout event
>       // "where" is the object that the mouse has entered, or null
>       // if no object receives mouse events at the new location
>
>       if(who_is_the_widget_or_its_child()) {
>               keep_visible();
>       } else {
>               make_invisible();
>       }
> </method>
>
> I suppose I could implement this by setting a timer during  
> onmouseout to check what the subsequent onmouseover value is.  The  
> only problem is that I don't know what contractual guarantees the  
> runtime provides with regard to mouse events and their proximity  
> time-wise.  If a mouseout occurs, is any subsequent mouseover  
> guaranteed to happen before the next onidle?  Is it possible for  
> multiple mouseout/mouseover combos to happen before the next onidle?
>
> On May 26, 2006, at 12:43 AM, Benjamin Shine wrote:
>
>> You might try applying a predictive tracking algorithm: something  
>> like watching every mouse move, guessing where the mouse is going,  
>> then setting a timer to see if you get another mouse move event.  
>> You could get into math like evaluating the rate of travel of the  
>> mouse pointer towards a boundary of the app; moving rapidly toward  
>> the border would predict that the border will be crossed; moving  
>> towards the border but decelerating would predict that the border  
>> won't be crossed.
>>
>> Patrick Baudisch, at Microsoft Research, has been doing some  
>> really nice CHI work with user studies on this sort of thing. I  
>> recommend checking out his work. It might not be exactly what you  
>> need, but it's *cool*, and could get you a "+5 nifty!" rating if  
>> you applied it to Pandora.
>> http://www.patrickbaudisch.com/publications/index.html
>>
>> Joe Laviola at Brown has been doing some work with this:
>> http://www.cs.brown.edu/people/jjl/ptracking/ptracking.html
>>
>> Is your app in a javascript wrapper, though? Seems like there  
>> ought to be a clever way of noticing a mouse-enter in DHTML, and  
>> sending a message to the laszlo app to let it know it's lost the  
>> pointer.
>>
>> Please let us know what you learn.
>>
>> On May 25, 2006, at 9:38 AM, Neil Mix wrote:
>>
>>> I'd like to have some way of knowing that the mouse is no longer
>>> above the canvas, i.e. the Flash app is no longer able to receive
>>> mouse events.  Is this possible at all?  What I'm seeing is that the
>>> last moused-over object will receive a mouseout event, but the
>>> getMouse() coords returned are the last known location of the mouse
>>> before it left the canvas (which makes sense).
>>>
>>> I'm guessing I'm out of luck here, but I thought I'd check with the
>>> experts first.  It's OK by me if the solution involves using Flash
>>> native or deeply private LZX stuff.
>>>
>>> TIA, -Neil
>>> _______________________________________________
>>> Laszlo-dev mailing list
>>> [email protected]
>>> http://www.openlaszlo.org/mailman/listinfo/laszlo-dev
>>
>> benjamin shine
>> software engineer
>> [EMAIL PROTECTED]
>>
>>
>>
>

benjamin shine
software engineer
[EMAIL PROTECTED]



_______________________________________________
Laszlo-dev mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-dev

Reply via email to