1 11 package org.eclipse.swt.dnd; 12 13 14 import org.eclipse.swt.*; 15 import org.eclipse.swt.graphics.*; 16 import org.eclipse.swt.widgets.*; 17 import org.eclipse.swt.internal.*; 18 import org.eclipse.swt.internal.ole.win32.*; 19 import org.eclipse.swt.internal.win32.*; 20 21 97 public class DragSource extends Widget { 98 99 Control control; 101 Listener controlListener; 102 Transfer[] transferAgents = new Transfer[0]; 103 DragSourceEffect dragEffect; 104 Composite topControl; 105 int hwndDrag; 106 107 COMObject iDropSource; 109 COMObject iDataObject; 110 int refCount; 111 112 int dataEffect = DND.DROP_NONE; 114 115 static final String DEFAULT_DRAG_SOURCE_EFFECT = "DEFAULT_DRAG_SOURCE_EFFECT"; static final String DRAGSOURCEID = "DragSource"; static final int CFSTR_PERFORMEDDROPEFFECT = Transfer.registerType("Performed DropEffect"); static final TCHAR WindowClass = new TCHAR (0, "#32770", true); 119 120 149 public DragSource(Control control, int style) { 150 super(control, checkStyle(style)); 151 this.control = control; 152 if (control.getData(DRAGSOURCEID) != null) { 153 DND.error(DND.ERROR_CANNOT_INIT_DRAG); 154 } 155 control.setData(DRAGSOURCEID, this); 156 createCOMInterfaces(); 157 this.AddRef(); 158 159 controlListener = new Listener() { 160 public void handleEvent(Event event) { 161 if (event.type == SWT.Dispose) { 162 if (!DragSource.this.isDisposed()) { 163 DragSource.this.dispose(); 164 } 165 } 166 if (event.type == SWT.DragDetect) { 167 if (!DragSource.this.isDisposed()) { 168 DragSource.this.drag(event); 169 } 170 } 171 } 172 }; 173 control.addListener(SWT.Dispose, controlListener); 174 control.addListener(SWT.DragDetect, controlListener); 175 176 this.addListener(SWT.Dispose, new Listener() { 177 public void handleEvent(Event e) { 178 DragSource.this.onDispose(); 179 } 180 }); 181 182 Object effect = control.getData(DEFAULT_DRAG_SOURCE_EFFECT); 183 if (effect instanceof DragSourceEffect) { 184 dragEffect = (DragSourceEffect) effect; 185 } else if (control instanceof Tree) { 186 dragEffect = new TreeDragSourceEffect((Tree) control); 187 } else if (control instanceof Table) { 188 dragEffect = new TableDragSourceEffect((Table) control); 189 } 190 } 191 192 static int checkStyle(int style) { 193 if (style == SWT.NONE) return DND.DROP_MOVE; 194 return style; 195 } 196 197 226 public void addDragListener(DragSourceListener listener) { 227 if (listener == null) DND.error(SWT.ERROR_NULL_ARGUMENT); 228 DNDListener typedListener = new DNDListener(listener); 229 typedListener.dndWidget = this; 230 addListener(DND.DragStart, typedListener); 231 addListener(DND.DragSetData, typedListener); 232 addListener(DND.DragEnd, typedListener); 233 } 234 235 private int AddRef() { 236 refCount++; 237 return refCount; 238 } 239 240 private void createCOMInterfaces() { 241 iDropSource = new COMObject(new int[]{2, 0, 0, 2, 1}){ 243 public int method0(int[] args) {return QueryInterface(args[0], args[1]);} 244 public int method1(int[] args) {return AddRef();} 245 public int method2(int[] args) {return Release();} 246 public int method3(int[] args) {return QueryContinueDrag(args[0], args[1]);} 247 public int method4(int[] args) {return GiveFeedback(args[0]);} 248 }; 249 250 iDataObject = new COMObject(new int[]{2, 0, 0, 2, 2, 1, 2, 3, 2, 4, 1, 1}){ 251 public int method0(int[] args) {return QueryInterface(args[0], args[1]);} 252 public int method1(int[] args) {return AddRef();} 253 public int method2(int[] args) {return Release();} 254 public int method3(int[] args) {return GetData(args[0], args[1]);} 255 public int method5(int[] args) {return QueryGetData(args[0]);} 257 public int method7(int[] args) {return SetData(args[0], args[1], args[2]);} 259 public int method8(int[] args) {return EnumFormatEtc(args[0], args[1]);} 260 }; 264 } 265 266 protected void checkSubclass() { 267 String name = getClass().getName(); 268 String validName = DragSource.class.getName(); 269 if (!validName.equals(name)) { 270 DND.error(SWT.ERROR_INVALID_SUBCLASS); 271 } 272 } 273 274 private void disposeCOMInterfaces() { 275 if (iDropSource != null) 276 iDropSource.dispose(); 277 iDropSource = null; 278 279 if (iDataObject != null) 280 iDataObject.dispose(); 281 iDataObject = null; 282 } 283 284 private void drag(Event dragEvent) { 285 DNDEvent event = new DNDEvent(); 286 event.widget = this; 287 event.x = dragEvent.x; 288 event.y = dragEvent.y; 289 event.time = OS.GetMessageTime(); 290 event.doit = true; 291 notifyListeners(DND.DragStart,event); 292 if (!event.doit || transferAgents == null || transferAgents.length == 0 ) return; 293 294 int[] pdwEffect = new int[1]; 295 int operations = opToOs(getStyle()); 296 Display display = control.getDisplay(); 297 String key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; Object oldValue = display.getData(key); 299 display.setData(key, new Boolean (true)); 300 ImageList imagelist = null; 301 Image image = event.image; 302 hwndDrag = 0; 303 topControl = null; 304 if (image != null) { 305 imagelist = new ImageList(SWT.NONE); 306 imagelist.add(image); 307 topControl = control.getShell(); 308 314 int offset = 0; 315 hwndDrag = topControl.handle; 316 if ((topControl.getStyle() & SWT.RIGHT_TO_LEFT) != 0) { 317 offset = image.getBounds().width; 318 RECT rect = new RECT (); 319 OS.GetClientRect (topControl.handle, rect); 320 hwndDrag = OS.CreateWindowEx ( 321 OS.WS_EX_TRANSPARENT | OS.WS_EX_NOINHERITLAYOUT, 322 WindowClass, 323 null, 324 OS.WS_CHILD | OS.WS_CLIPSIBLINGS, 325 0, 0, 326 rect.right - rect.left, rect.bottom - rect.top, 327 topControl.handle, 328 0, 329 OS.GetModuleHandle (null), 330 null); 331 OS.ShowWindow (hwndDrag, OS.SW_SHOW); 332 } 333 OS.ImageList_BeginDrag(imagelist.getHandle(), 0, offset, 0); 334 342 if (OS.IsWinCE) { 343 OS.UpdateWindow (topControl.handle); 344 } else { 345 int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN; 346 OS.RedrawWindow (topControl.handle, null, 0, flags); 347 } 348 POINT pt = new POINT (); 349 pt.x = dragEvent.x; 350 pt.y = dragEvent.y; 351 OS.MapWindowPoints (control.handle, 0, pt, 1); 352 RECT rect = new RECT (); 353 OS.GetWindowRect (hwndDrag, rect); 354 OS.ImageList_DragEnter(hwndDrag, pt.x - rect.left, pt.y - rect.top); 355 } 356 int result = COM.DRAGDROP_S_CANCEL; 357 try { 358 result = COM.DoDragDrop(iDataObject.getAddress(), iDropSource.getAddress(), operations, pdwEffect); 359 } finally { 360 if (hwndDrag != 0) { 362 OS.ImageList_DragLeave(hwndDrag); 363 OS.ImageList_EndDrag(); 364 imagelist.dispose(); 365 if (hwndDrag != topControl.handle) OS.DestroyWindow(hwndDrag); 366 hwndDrag = 0; 367 topControl = null; 368 } 369 display.setData(key, oldValue); 370 } 371 int operation = osToOp(pdwEffect[0]); 372 if (dataEffect == DND.DROP_MOVE) { 373 operation = (operation == DND.DROP_NONE || operation == DND.DROP_COPY) ? DND.DROP_TARGET_MOVE : DND.DROP_MOVE; 374 } else { 375 if (dataEffect != DND.DROP_NONE) { 376 operation = dataEffect; 377 } 378 } 379 event = new DNDEvent(); 380 event.widget = this; 381 event.time = OS.GetMessageTime(); 382 event.doit = (result == COM.DRAGDROP_S_DROP); 383 event.detail = operation; 384 notifyListeners(DND.DragEnd,event); 385 dataEffect = DND.DROP_NONE; 386 } 387 392 private int EnumFormatEtc(int dwDirection, int ppenumFormatetc) { 393 if (dwDirection == COM.DATADIR_SET) return COM.E_NOTIMPL; 395 396 TransferData[] allowedDataTypes = new TransferData[0]; 398 for (int i = 0; i < transferAgents.length; i++){ 399 Transfer transferAgent = transferAgents[i]; 400 if (transferAgent != null) { 401 TransferData[] formats = transferAgent.getSupportedTypes(); 402 TransferData[] newAllowedDataTypes = new TransferData[allowedDataTypes.length + formats.length]; 403 System.arraycopy(allowedDataTypes, 0, newAllowedDataTypes, 0, allowedDataTypes.length); 404 System.arraycopy(formats, 0, newAllowedDataTypes, allowedDataTypes.length, formats.length); 405 allowedDataTypes = newAllowedDataTypes; 406 } 407 } 408 409 OleEnumFORMATETC enumFORMATETC = new OleEnumFORMATETC(); 410 enumFORMATETC.AddRef(); 411 412 FORMATETC[] formats = new FORMATETC[allowedDataTypes.length]; 413 for (int i = 0; i < formats.length; i++){ 414 formats[i] = allowedDataTypes[i].formatetc; 415 } 416 enumFORMATETC.setFormats(formats); 417 418 OS.MoveMemory(ppenumFormatetc, new int[] {enumFORMATETC.getAddress()}, 4); 419 return COM.S_OK; 420 } 421 427 public Control getControl() { 428 return control; 429 } 430 431 private int GetData(int pFormatetc, int pmedium) { 432 437 if (pFormatetc == 0 || pmedium == 0) return COM.E_INVALIDARG; 438 439 if (QueryGetData(pFormatetc) != COM.S_OK) return COM.DV_E_FORMATETC; 440 441 TransferData transferData = new TransferData(); 442 transferData.formatetc = new FORMATETC(); 443 COM.MoveMemory(transferData.formatetc, pFormatetc, FORMATETC.sizeof); 444 transferData.type = transferData.formatetc.cfFormat; 445 transferData.stgmedium = new STGMEDIUM(); 446 transferData.result = COM.E_FAIL; 447 448 DNDEvent event = new DNDEvent(); 449 event.widget = this; 450 event.time = OS.GetMessageTime(); 451 event.dataType = transferData; 452 notifyListeners(DND.DragSetData,event); 453 454 Transfer transfer = null; 456 for (int i = 0; i < transferAgents.length; i++){ 457 Transfer transferAgent = transferAgents[i]; 458 if (transferAgent != null && transferAgent.isSupportedType(transferData)){ 459 transfer = transferAgent; 460 break; 461 } 462 } 463 464 if (transfer == null) return COM.DV_E_FORMATETC; 465 transfer.javaToNative(event.data, transferData); 466 if (transferData.result != COM.S_OK) return transferData.result; 467 COM.MoveMemory(pmedium, transferData.stgmedium, STGMEDIUM.sizeof); 468 return transferData.result; 469 } 470 471 479 public DragSourceEffect getDragSourceEffect() { 480 return dragEffect; 481 } 482 483 488 public Transfer[] getTransfer(){ 489 return transferAgents; 490 } 491 492 private int GiveFeedback(int dwEffect) { 493 return COM.DRAGDROP_S_USEDEFAULTCURSORS; 494 } 495 496 private int QueryContinueDrag(int fEscapePressed, int grfKeyState) { 497 if (topControl != null && topControl.isDisposed()) return COM.DRAGDROP_S_CANCEL; 498 if (fEscapePressed != 0){ 499 if (hwndDrag != 0) OS.ImageList_DragLeave(hwndDrag); 500 return COM.DRAGDROP_S_CANCEL; 501 } 502 508 int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON; 509 if ((grfKeyState & mask) == 0) { 511 if (hwndDrag != 0) OS.ImageList_DragLeave(hwndDrag); 512 return COM.DRAGDROP_S_DROP; 513 } 514 515 if (hwndDrag != 0) { 516 POINT pt = new POINT (); 517 OS.GetCursorPos (pt); 518 RECT rect = new RECT (); 519 OS.GetWindowRect (hwndDrag, rect); 520 OS.ImageList_DragMove (pt.x - rect.left, pt.y - rect.top); 521 } 522 return COM.S_OK; 523 } 524 525 private void onDispose() { 526 if (control == null) return; 527 this.Release(); 528 if (controlListener != null){ 529 control.removeListener(SWT.Dispose, controlListener); 530 control.removeListener(SWT.DragDetect, controlListener); 531 } 532 controlListener = null; 533 control.setData(DRAGSOURCEID, null); 534 control = null; 535 transferAgents = null; 536 } 537 538 private int opToOs(int operation) { 539 int osOperation = 0; 540 if ((operation & DND.DROP_COPY) != 0){ 541 osOperation |= COM.DROPEFFECT_COPY; 542 } 543 if ((operation & DND.DROP_LINK) != 0) { 544 osOperation |= COM.DROPEFFECT_LINK; 545 } 546 if ((operation & DND.DROP_MOVE) != 0) { 547 osOperation |= COM.DROPEFFECT_MOVE; 548 } 549 return osOperation; 550 } 551 552 private int osToOp(int osOperation){ 553 int operation = 0; 554 if ((osOperation & COM.DROPEFFECT_COPY) != 0){ 555 operation |= DND.DROP_COPY; 556 } 557 if ((osOperation & COM.DROPEFFECT_LINK) != 0) { 558 operation |= DND.DROP_LINK; 559 } 560 if ((osOperation & COM.DROPEFFECT_MOVE) != 0) { 561 operation |= DND.DROP_MOVE; 562 } 563 return operation; 564 } 565 566 private int QueryGetData(int pFormatetc) { 567 if (transferAgents == null) return COM.E_FAIL; 568 TransferData transferData = new TransferData(); 569 transferData.formatetc = new FORMATETC(); 570 COM.MoveMemory(transferData.formatetc, pFormatetc, FORMATETC.sizeof); 571 transferData.type = transferData.formatetc.cfFormat; 572 573 for (int i = 0; i < transferAgents.length; i++){ 575 Transfer transfer = transferAgents[i]; 576 if (transfer != null && transfer.isSupportedType(transferData)) 577 return COM.S_OK; 578 } 579 580 return COM.DV_E_FORMATETC; 581 } 582 583 587 private int QueryInterface(int riid, int ppvObject) { 588 if (riid == 0 || ppvObject == 0) 589 return COM.E_INVALIDARG; 590 GUID guid = new GUID(); 591 COM.MoveMemory(guid, riid, GUID.sizeof); 592 593 if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDropSource)) { 594 OS.MoveMemory(ppvObject, new int[] {iDropSource.getAddress()}, 4); 595 AddRef(); 596 return COM.S_OK; 597 } 598 599 if (COM.IsEqualGUID(guid, COM.IIDIDataObject) ) { 600 OS.MoveMemory(ppvObject, new int[] {iDataObject.getAddress()}, 4); 601 AddRef(); 602 return COM.S_OK; 603 } 604 605 OS.MoveMemory(ppvObject, new int[] {0}, 4); 606 return COM.E_NOINTERFACE; 607 } 608 609 private int Release() { 610 refCount--; 611 if (refCount == 0) { 612 disposeCOMInterfaces(); 613 COM.CoFreeUnusedLibraries(); 614 } 615 return refCount; 616 } 617 618 635 public void removeDragListener(DragSourceListener listener) { 636 if (listener == null) DND.error(SWT.ERROR_NULL_ARGUMENT); 637 removeListener(DND.DragStart, listener); 638 removeListener(DND.DragSetData, listener); 639 removeListener(DND.DragEnd, listener); 640 } 641 642 private int SetData(int pFormatetc, int pmedium, int fRelease) { 643 if (pFormatetc == 0 || pmedium == 0) return COM.E_INVALIDARG; 644 FORMATETC formatetc = new FORMATETC(); 645 COM.MoveMemory(formatetc, pFormatetc, FORMATETC.sizeof); 646 if (formatetc.cfFormat == CFSTR_PERFORMEDDROPEFFECT && formatetc.tymed == COM.TYMED_HGLOBAL) { 647 STGMEDIUM stgmedium = new STGMEDIUM(); 648 COM.MoveMemory(stgmedium, pmedium,STGMEDIUM.sizeof); 649 int[] ptrEffect = new int[1]; 650 OS.MoveMemory(ptrEffect, stgmedium.unionField,4); 651 int[] effect = new int[1]; 652 OS.MoveMemory(effect, ptrEffect[0],4); 653 dataEffect = osToOp(effect[0]); 654 } 655 if (fRelease == 1) { 656 COM.ReleaseStgMedium(pmedium); 657 } 658 return COM.S_OK; 659 } 660 661 669 public void setDragSourceEffect(DragSourceEffect effect) { 670 dragEffect = effect; 671 } 672 673 681 public void setTransfer(Transfer[] transferAgents){ 682 this.transferAgents = transferAgents; 683 } 684 685 } 686 | Popular Tags |