views:

154

answers:

2

I am implementing a graphical user interface with Morphic / Squeak. Some of the items have drag & drop functionality. While dragging, I want to be able to rotate these items with the mousewheel.

The first problem is that using the mousewheel ends the drag-action and leads to a drop (attempt). How can I suppress that - and fire the mouseWheelEvent at the same time?

The second problem: How can I assign a mousewheel-event to my Morph? As mentioned above, this event only is relevant while dragging this Morph. (solved)

A: 

Your best bet is to find a morph that does something like what you want and then browse its methods to see how it does it. Having said that, I haven't come across any that support wheel-specific functions, and of course the original Xerox mouse had no such feature.

anon
+1  A: 

Appears that on VM implementations that have chosen to support it, Squeak maps the mouse wheel to Ctrl Up-Arrow and Ctrl-Down-Arrow key events. For instance, on Win32 in sqWin32Window.c:

if( WM_MOUSEWHEEL == message || g_WM_MOUSEWHEEL == message ) {
    /* Record mouse wheel msgs as CTRL-Up/Down */
    short zDelta = (short) HIWORD(wParam);
    if(inputSemaphoreIndex) {
        sqKeyboardEvent *evt = (sqKeyboardEvent*) sqNextEventPut();
        evt->type = EventTypeKeyboard;
        evt->timeStamp = lastMessage->time;
        evt->charCode = (zDelta > 0) ? 30 : 31;
        evt->pressCode = EventKeyChar;
        evt->modifiers = CtrlKeyBit;
        evt->utf32Code = 0;
        evt->reserved1 = 0;
    } else {
        buttonState = 64;
        if (zDelta < 0) {
            recordVirtualKey(message,VK_DOWN,lParam);
        } else {
            recordVirtualKey(message,VK_UP,lParam);
        }
    }
    return 1;
}

So that's pretty much what you've got to work with inside Squeak. (If you're using the Polymorph extensions, there is a special mouseWheel event, but all they're doing is filtering Ctrl-Up and Ctrl-Down and generating a "fake" MouseWheelEvent message.)

Looking at a bit of code for handleEvent in HandMorph:

evt isMouse ifTrue:[
    self sendListenEvent: evt to: self mouseListeners.
    lastMouseEvent _ evt].

    "Check for pending drag or double click operations."
    mouseClickState ifNotNil:[
        (mouseClickState handleEvent: evt from: self) ifFalse:[
        "Possibly dispatched #click: or something and will not re-establish otherwise"
        ^self mouseOverHandler processMouseOver: lastMouseEvent]].

        evt isMove ifTrue:[
            self position: evt position.
            self sendMouseEvent: evt.
        ] ifFalse:[
            "Issue a synthetic move event if we're not at the position of the event"
            (evt position = self position) ifFalse:[self moveToEvent: evt].
            "Drop submorphs on button events"
            (self hasSubmorphs) 
                ifTrue:[self dropMorphs: evt]
                ifFalse:[self sendMouseEvent: evt].
        ].

The Polymorph MouseWheelEvent is a subclass of MouseEvent that doesn't return true to isMove, hence you get a drop. You'll have to change something here if you want this to work.

Hostile Fork
It doesn't happen with other keys. CTRL+Up/Down however terminates it. In the meantime I figured out that there is a mouseWheel event that works quite well - but the first problem remains, it doesn't work while dragging at the moment.
Mef
If you have mouseWheel then you're using the Polymorph extensions, (not Morphic as it ships with Squeak by default). If you look at generateKeyboardEvent in HandMorph you'll see that all they're doing is interpreting Ctrl-Up and Ctrl-Down and sending it as a "MouseWheelEvent" so it's not doing anything magic. Updating answer...
Hostile Fork
Updated. I'll also point out that you might consider the accessibility barrier that such an interface choice presents to users who are using alternative input devices (or even those who have a little trouble with a mouse as is).
Hostile Fork
Thanks for your help so far. I added the isMove to MouseWheelEvent, now it doesn't terminate the drag anymore - but neither the MouseWheelEvent gets fired. Time for bed now... BTW accessibility won't be a problem because this is just one of many ways to achive the involved task, but it would be a REAL ease for those users who have and can use their wheel.
Mef
I don't know that MouseWheelEvent should count as an "isMove" message. But anyway, does your class return handlesMouseWheel as true, in order to indicate that it wishes to receive the events?
Hostile Fork
Yes it does, and it works fine if I just point on the Morph and use the wheel, just not when dragging.
Mef
It appears that the problem lies with sendMouseEvent's concept of the relevant focus during a drag. Looks like it's the parent who gets the mouse wheel event in that case. Try putting a handlesMouseWheel and mouseWheel on the parent...
Hostile Fork