001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Pavel Dolgov
019: * @version $Revision$
020: */package org.apache.harmony.awt.datatransfer.windows;
021:
022: import java.awt.Cursor;
023: import java.awt.EventQueue;
024: import java.awt.Image;
025: import java.awt.Point;
026: import java.awt.dnd.DnDConstants;
027: import java.awt.dnd.DragSourceContext;
028: import java.awt.dnd.InvalidDnDOperationException;
029: import java.awt.dnd.peer.DragSourceContextPeer;
030: import java.awt.event.InputEvent;
031:
032: import org.apache.harmony.awt.ContextStorage;
033: import org.apache.harmony.awt.datatransfer.DataSnapshot;
034: import org.apache.harmony.awt.datatransfer.DataSource;
035: import org.apache.harmony.awt.datatransfer.DragSourceEventProxy;
036: import org.apache.harmony.awt.nativebridge.windows.Win32;
037: import org.apache.harmony.awt.nativebridge.windows.WinDataTransfer;
038: import org.apache.harmony.awt.nativebridge.windows.WindowsDefs;
039: import org.apache.harmony.awt.wtk.windows.WinEventQueue;
040:
041: /**
042: * Starts drag operation and handles callbacks from OLE.
043: * The callbacks simply do EventQueue.invokeLater(new DragSourceEventProxy(...))
044: */
045: public class WinDragSource implements DragSourceContextPeer {
046:
047: private static final Win32 win32 = Win32.getInstance();
048:
049: private Cursor cursor;
050: private DragSourceContext context;
051:
052: private final WinEventQueue winEventQueue;
053:
054: private int userAction;
055: private int targetActions;
056: private Point mouseLocation;
057:
058: public WinDragSource() {
059: winEventQueue = (WinEventQueue) ContextStorage
060: .getNativeEventQueue();
061: }
062:
063: public void startDrag(DragSourceContext dsc, Cursor c, Image di,
064: Point ioff) throws InvalidDnDOperationException {
065:
066: synchronized (this ) {
067: context = dsc;
068: cursor = c;
069: }
070: mouseLocation = getCurrentMouseLocation();
071: userAction = 0;
072: targetActions = 0;
073:
074: DataSource dataSource = new DataSource(context
075: .getTransferable());
076: final DataSnapshot snapshot = new DataSnapshot(dataSource);
077: final int srcActions = getWinActions(context.getSourceActions());
078:
079: WinEventQueue.Task task = new WinEventQueue.Task() {
080: @Override
081: public void perform() {
082: WinDataTransfer.startDrag(snapshot, WinDragSource.this ,
083: srcActions);
084: }
085: };
086: winEventQueue.performLater(task);
087: }
088:
089: public Cursor getCursor() {
090: synchronized (this ) {
091: return cursor;
092: }
093: }
094:
095: public void setCursor(Cursor c) throws InvalidDnDOperationException {
096: synchronized (this ) {
097: cursor = c;
098: }
099:
100: // TODO: implement native cursor update,
101: // and in native method WinDragSource::GiveFeedback()
102: // change return value to S_OK to suppress default OLE cursors
103: }
104:
105: public void transferablesFlavorsChanged() {
106: // TODO: call this method from IAdviseSink::OnDataChange()
107: }
108:
109: static int getDndActions(int winActions) {
110: int dndActions = 0;
111: if ((winActions & WindowsDefs.DROPEFFECT_COPY) != 0) {
112: dndActions |= DnDConstants.ACTION_COPY;
113: }
114: if ((winActions & WindowsDefs.DROPEFFECT_MOVE) != 0) {
115: dndActions |= DnDConstants.ACTION_MOVE;
116: }
117: if ((winActions & WindowsDefs.DROPEFFECT_LINK) != 0) {
118: dndActions |= DnDConstants.ACTION_LINK;
119: }
120: return dndActions;
121: }
122:
123: static int getWinActions(int dndActions) {
124: int winActions = 0;
125: if ((dndActions & DnDConstants.ACTION_COPY) != 0) {
126: winActions |= WindowsDefs.DROPEFFECT_COPY;
127: }
128: if ((dndActions & DnDConstants.ACTION_MOVE) != 0) {
129: winActions |= WindowsDefs.DROPEFFECT_MOVE;
130: }
131: if ((dndActions & DnDConstants.ACTION_LINK) != 0) {
132: winActions |= WindowsDefs.DROPEFFECT_LINK;
133: }
134: return winActions;
135: }
136:
137: /**
138: * Called from native method WinDragSource::GiveFeedback()
139: * @param winActions - drop actions acceptable for drop target
140: * @param scroll - scrolling is asked by drop target
141: */
142: public void giveFeedback(int winActions, boolean scroll) {
143: int dndActions = getDndActions(winActions);
144: updateLocationAndActions(dndActions);
145: }
146:
147: /**
148: * Called from native method WinDragSource::QueryContinueDrag()
149: */
150: public void continueDrag() {
151: updateLocationAndActions(targetActions);
152: }
153:
154: /**
155: * Called from native method WinDataTransfer::startDrag()
156: * after drag operation is finished
157: * @param winAction - drop action taken
158: * @param success - drop was completed successfully
159: */
160: public void endDrag(int winAction, boolean success) {
161: int dndAction = getDndActions(winAction);
162: DragSourceEventProxy r = new DragSourceEventProxy(context,
163: DragSourceEventProxy.DRAG_DROP_END, dndAction, success,
164: mouseLocation, getCurrentModifiers());
165: EventQueue.invokeLater(r);
166: }
167:
168: private void updateLocationAndActions(int newTargetActions) {
169: Point newLocation = getCurrentMouseLocation();
170: int modifiers = getCurrentModifiers();
171: int newUserAction = getUserAction(modifiers, newTargetActions);
172:
173: if (!newLocation.equals(mouseLocation)) {
174: mouseLocation.setLocation(newLocation);
175: if (newTargetActions != 0) {
176: DragSourceEventProxy r = new DragSourceEventProxy(
177: context, DragSourceEventProxy.DRAG_MOUSE_MOVED,
178: newUserAction, newTargetActions, mouseLocation,
179: modifiers);
180: EventQueue.invokeLater(r);
181: }
182: }
183:
184: if (newUserAction != userAction
185: || newTargetActions != targetActions) {
186: int type = 0;
187: if (targetActions == 0 && newTargetActions != 0) {
188: type = DragSourceEventProxy.DRAG_ENTER;
189: } else if (targetActions != 0 && newTargetActions == 0) {
190: type = DragSourceEventProxy.DRAG_EXIT;
191: } else {
192: type = DragSourceEventProxy.DRAG_ACTION_CHANGED;
193: }
194: userAction = newUserAction;
195: targetActions = newTargetActions;
196: if (type != 0) {
197: DragSourceEventProxy r = new DragSourceEventProxy(
198: context, type, newUserAction, newTargetActions,
199: mouseLocation, modifiers);
200: EventQueue.invokeLater(r);
201: }
202: }
203: }
204:
205: private static Point getCurrentMouseLocation() {
206: Win32.POINT lpPoint = win32.createPOINT(false);
207: win32.GetCursorPos(lpPoint);
208: return new Point(lpPoint.get_x(), lpPoint.get_y());
209: }
210:
211: private static int getCurrentModifiers() {
212: int modifiers = 0;
213: modifiers |= ((win32.GetKeyState(WindowsDefs.VK_SHIFT) & 0x80) != 0) ? InputEvent.SHIFT_DOWN_MASK
214: : 0;
215: modifiers |= ((win32.GetKeyState(WindowsDefs.VK_CONTROL) & 0x80) != 0) ? InputEvent.CTRL_DOWN_MASK
216: : 0;
217: modifiers |= ((win32.GetKeyState(WindowsDefs.VK_MENU) & 0x80) != 0) ? InputEvent.ALT_DOWN_MASK
218: : 0;
219: modifiers |= ((win32.GetKeyState(WindowsDefs.VK_LBUTTON) & 0x80) != 0) ? InputEvent.BUTTON1_DOWN_MASK
220: : 0;
221: modifiers |= ((win32.GetKeyState(WindowsDefs.VK_MBUTTON) & 0x80) != 0) ? InputEvent.BUTTON2_DOWN_MASK
222: : 0;
223: modifiers |= ((win32.GetKeyState(WindowsDefs.VK_RBUTTON) & 0x80) != 0) ? InputEvent.BUTTON3_DOWN_MASK
224: : 0;
225: return modifiers;
226: }
227:
228: private static int getUserAction(int modifiers, int targetActions) {
229: if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
230: return ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) ? DnDConstants.ACTION_LINK
231: : DnDConstants.ACTION_COPY;
232: }
233: if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
234: return DnDConstants.ACTION_MOVE;
235: }
236: if ((targetActions & DnDConstants.ACTION_MOVE) != 0) {
237: return DnDConstants.ACTION_MOVE;
238: }
239: if ((targetActions & DnDConstants.ACTION_COPY) != 0) {
240: return DnDConstants.ACTION_COPY;
241: }
242: if ((targetActions & DnDConstants.ACTION_LINK) != 0) {
243: return DnDConstants.ACTION_LINK;
244: }
245: return DnDConstants.ACTION_NONE;
246: }
247: }
|