SunDragSourceContextPeer.java :  » 6.0-JDK-Modules-sun » awt » sun » awt » dnd » Java Open Source

Java Open Source » 6.0 JDK Modules sun » awt 
awt » sun » awt » dnd » SunDragSourceContextPeer.java
/*
 * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.awt.dnd;

import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Point;

import java.awt.datatransfer.Transferable;

import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragSourceContext;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.InvalidDnDOperationException;

import java.awt.dnd.peer.DragSourceContextPeer;

import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;

import java.util.Map;
import java.util.SortedMap;

import sun.awt.SunToolkit;
import sun.awt.datatransfer.DataTransferer;

/**
 * <p>
 * TBC
 * </p>
 *
 * @version 1.27.06/05/07
 * @since JDK1.3.1
 *
 */

public abstract class SunDragSourceContextPeer implements DragSourceContextPeer {

    private DragGestureEvent  trigger;
    private Component         component;
    private Cursor            cursor;
    private long              nativeCtxt;
    private DragSourceContext dragSourceContext;
    private int               sourceActions;

    private static boolean    dragDropInProgress = false;
    private static boolean    discardingMouseEvents = false;

    /*
     * dispatch constants
     */

    protected final static int DISPATCH_ENTER   = 1;
    protected final static int DISPATCH_MOTION  = 2;
    protected final static int DISPATCH_CHANGED = 3;
    protected final static int DISPATCH_EXIT    = 4;
    protected final static int DISPATCH_FINISH  = 5;
    protected final static int DISPATCH_MOUSE_MOVED  = 6;

    /**
     * construct a new SunDragSourceContextPeer
     */

    public SunDragSourceContextPeer(DragGestureEvent dge) {
        trigger = dge;
        if (trigger != null) {
            component = trigger.getComponent();
        } else {
            component = null;
        }
    }

    /**
     * Synchro messages in AWT
     */
    public void startSecondaryEventLoop(){}
    public void quitSecondaryEventLoop(){}
    
    /**
     * initiate a DnD operation ...
     */

    public void startDrag(DragSourceContext dsc, Cursor c, Image di, Point p) 
      throws InvalidDnDOperationException {

        /* Fix for 4354044: don't initiate a drag if event sequence provided by
         * DragGestureRecognizer is empty */
        if (getTrigger().getTriggerEvent() == null) {
            throw new InvalidDnDOperationException("DragGestureEvent has a null trigger");
        }

        dragSourceContext = dsc; 
        cursor            = c;
        sourceActions     = getDragSourceContext().getSourceActions();

        Transferable transferable  = getDragSourceContext().getTransferable();
        SortedMap formatMap = DataTransferer.getInstance().getFormatsForTransferable
       (transferable, DataTransferer.adaptFlavorMap
           (getTrigger().getDragSource().getFlavorMap()));
        long[] formats = DataTransferer.getInstance().
      keysToLongArray(formatMap);        
        startDrag(transferable, formats, formatMap);

        /*
         * Fix for 4613903.
         * Filter out all mouse events that are currently on the event queue.
         */
        discardingMouseEvents = true;
        EventQueue.invokeLater(new Runnable() {
                public void run() {
                    discardingMouseEvents = false;
                }
            });
    }

    protected abstract void startDrag(Transferable trans, 
                                      long[] formats, Map formatMap);

    /**
     * set cursor
     */

    public void setCursor(Cursor c) throws InvalidDnDOperationException {
        synchronized (this) {
            if (cursor == null || !cursor.equals(c)) {
                cursor = c;
                // NOTE: native context can be null at this point.
                // setNativeCursor() should handle it properly.
                setNativeCursor(getNativeContext(), c, 
                                c != null ? c.getType() : 0);
            }
        }
    }

    /**
     * return cursor
     */

    public Cursor getCursor() { 
        return cursor; 
    }

    /**
     * downcall into native code
     */


    protected abstract void setNativeCursor(long nativeCtxt, Cursor c, 
                                            int cType);

    protected synchronized void setTrigger(DragGestureEvent dge) { 
        trigger = dge; 
        if (trigger != null) {
            component = trigger.getComponent();
        } else {
            component = null;
        }
    }

    protected DragGestureEvent getTrigger() { 
        return trigger; 
    }

    protected Component getComponent() { 
        return component; 
    }

    protected synchronized void setNativeContext(long ctxt) { 
        nativeCtxt = ctxt; 
    }

    protected synchronized long getNativeContext() { 
        return nativeCtxt; 
    }

    protected DragSourceContext getDragSourceContext() { 
        return dragSourceContext; 
    }

    /**
     * Notify the peer that the transferables' DataFlavors have changed.
     *
     * No longer useful as the transferables are determined at the time
     * of the drag.
     */

    public void transferablesFlavorsChanged() {
    }





    protected final void postDragSourceDragEvent(final int targetAction, 
                                                 final int modifiers,
                                                 final int x, final int y,
                                                 final int dispatchType) {

        final int dropAction =
            SunDragSourceContextPeer.convertModifiersToDropAction(modifiers,
                                                                  sourceActions); 

        DragSourceDragEvent event = 
            new DragSourceDragEvent(getDragSourceContext(), 
                                    dropAction, 
                                    targetAction & sourceActions, 
                                    modifiers, x, y);
        EventDispatcher dispatcher = new EventDispatcher(dispatchType, event);

        SunToolkit.invokeLaterOnAppContext(
            SunToolkit.targetToAppContext(getComponent()), dispatcher);

        startSecondaryEventLoop();
    }

    /**
     * upcall from native code
     */

    private void dragEnter(final int targetActions, 
                           final int modifiers,
                           final int x, final int y) {
        postDragSourceDragEvent(targetActions, modifiers, x, y, DISPATCH_ENTER);
    }

    /**
     * upcall from native code
     */
 
    private void dragMotion(final int targetActions, 
                            final int modifiers,
                            final int x, final int y) {
        postDragSourceDragEvent(targetActions, modifiers, x, y, DISPATCH_MOTION);
    }

    /**
     * upcall from native code
     */

    private void operationChanged(final int targetActions, 
                                  final int modifiers,
                                  final int x, final int y) {
        postDragSourceDragEvent(targetActions, modifiers, x, y, DISPATCH_CHANGED);
    }

    /**
     * upcall from native code
     */

    protected final void dragExit(final int x, final int y) {
        DragSourceEvent event = 
            new DragSourceEvent(getDragSourceContext(), x, y);
        EventDispatcher dispatcher = 
            new EventDispatcher(DISPATCH_EXIT, event);

        SunToolkit.invokeLaterOnAppContext(
            SunToolkit.targetToAppContext(getComponent()), dispatcher);

        startSecondaryEventLoop();
    }

    /**
     * upcall from native code
     */

    private void dragMouseMoved(final int targetActions, 
                                final int modifiers,
                                final int x, final int y) {
        postDragSourceDragEvent(targetActions, modifiers, x, y,
                                DISPATCH_MOUSE_MOVED);
    }

    /**
     * upcall from native code via implemented class (do)
     */

    protected final void dragDropFinished(final boolean success, 
                                          final int operations,
                                          final int x, final int y) {
        DragSourceEvent event = 
            new DragSourceDropEvent(getDragSourceContext(),
                                    operations & sourceActions,
                                    success, x, y);
        EventDispatcher dispatcher = 
            new EventDispatcher(DISPATCH_FINISH, event);

        SunToolkit.invokeLaterOnAppContext(
            SunToolkit.targetToAppContext(getComponent()), dispatcher);

        startSecondaryEventLoop();
        setNativeContext(0);
    }

    public static void setDragDropInProgress(boolean b) 
      throws InvalidDnDOperationException {
        if (dragDropInProgress == b) {
            throw new InvalidDnDOperationException(getExceptionMessage(b));
        }

        synchronized (SunDragSourceContextPeer.class) {
            if (dragDropInProgress == b) {
                throw new InvalidDnDOperationException(getExceptionMessage(b));
            }
            dragDropInProgress = b;
        }
    }

    /**
     * Filters out all mouse events that were on the java event queue when
     * startDrag was called.
     */
    public static boolean checkEvent(AWTEvent event) {
        if (discardingMouseEvents && event instanceof MouseEvent) {
            MouseEvent mouseEvent = (MouseEvent)event;
            if (!(mouseEvent instanceof SunDropTargetEvent)) {
                return false;
            }
        }
        return true;
    }

    public static void checkDragDropInProgress() 
      throws InvalidDnDOperationException {
        if (dragDropInProgress) {
            throw new InvalidDnDOperationException(getExceptionMessage(true));
        }
    }

    private static String getExceptionMessage(boolean b) {
        return b ? "Drag and drop in progress" : "No drag in progress";
    }

    public static int convertModifiersToDropAction(final int modifiers, 
                                                   final int supportedActions) {
        int dropAction = DnDConstants.ACTION_NONE;

        /*
         * Fix for 4285634.
         * Calculate the drop action to match Motif DnD behavior.
         * If the user selects an operation (by pressing a modifier key),
         * return the selected operation or ACTION_NONE if the selected
         * operation is not supported by the drag source. 
         * If the user doesn't select an operation search the set of operations
         * supported by the drag source for ACTION_MOVE, then for 
         * ACTION_COPY, then for ACTION_LINK and return the first operation
         * found.
         */
        switch (modifiers & (InputEvent.SHIFT_DOWN_MASK |
                             InputEvent.CTRL_DOWN_MASK)) { 
        case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK:
            dropAction = DnDConstants.ACTION_LINK; break;
        case InputEvent.CTRL_DOWN_MASK:
            dropAction = DnDConstants.ACTION_COPY; break;
        case InputEvent.SHIFT_DOWN_MASK:
            dropAction = DnDConstants.ACTION_MOVE; break;
        default:
            if ((supportedActions & DnDConstants.ACTION_MOVE) != 0) {
                dropAction = DnDConstants.ACTION_MOVE; 
            } else if ((supportedActions & DnDConstants.ACTION_COPY) != 0) {
                dropAction = DnDConstants.ACTION_COPY; 
            } else if ((supportedActions & DnDConstants.ACTION_LINK) != 0) {
                dropAction = DnDConstants.ACTION_LINK; 
            }
        }

        return dropAction & supportedActions;
    }

    private void cleanup() {
        trigger = null;
        component = null;
        cursor = null;
        dragSourceContext = null;
        SunDropTargetContextPeer.setCurrentJVMLocalSourceTransferable(null);
        SunDragSourceContextPeer.setDragDropInProgress(false);
    }

    private class EventDispatcher implements Runnable {

        private final int dispatchType;

        private final DragSourceEvent event;

        EventDispatcher(int dispatchType, DragSourceEvent event) {
            switch (dispatchType) {
            case DISPATCH_ENTER:
            case DISPATCH_MOTION:
            case DISPATCH_CHANGED:
            case DISPATCH_MOUSE_MOVED: 
                if (!(event instanceof DragSourceDragEvent)) {
                    throw new IllegalArgumentException("Event: " + event);
                }
                break;
            case DISPATCH_EXIT:
                break;
            case DISPATCH_FINISH:
                if (!(event instanceof DragSourceDropEvent)) {
                    throw new IllegalArgumentException("Event: " + event);
                }
                break;
            default:
                throw new IllegalArgumentException("Dispatch type: " +
                                                   dispatchType);
            }

            this.dispatchType  = dispatchType;
            this.event         = event;
        }

        public void run() {
            DragSourceContext dragSourceContext = 
                SunDragSourceContextPeer.this.getDragSourceContext();
            try {
                switch (dispatchType) {
                case DISPATCH_ENTER:
                    dragSourceContext.dragEnter((DragSourceDragEvent)event);
                    break;
                case DISPATCH_MOTION:
                    dragSourceContext.dragOver((DragSourceDragEvent)event);
                    break;
                case DISPATCH_CHANGED:
                    dragSourceContext.dropActionChanged((DragSourceDragEvent)event);
                    break;
                case DISPATCH_EXIT:
                    dragSourceContext.dragExit(event);
                    break;
                case DISPATCH_MOUSE_MOVED:
                    dragSourceContext.dragMouseMoved((DragSourceDragEvent)event);
                    break;
                case DISPATCH_FINISH:
                    try {
                        dragSourceContext.dragDropEnd((DragSourceDropEvent)event);
                    } finally {
                        SunDragSourceContextPeer.this.cleanup();
                    }
                    break;
                default:
                    throw new IllegalStateException("Dispatch type: " +
                                                    dispatchType);
                }
            } finally {
                 SunDragSourceContextPeer.this.quitSecondaryEventLoop();
            }
        }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.