1 11 package org.eclipse.swt.dnd; 12 13 import org.eclipse.swt.*; 14 import org.eclipse.swt.widgets.*; 15 import org.eclipse.swt.internal.ole.win32.*; 16 import org.eclipse.swt.internal.win32.*; 17 18 69 public class DropTarget extends Widget { 70 71 Control control; 72 Listener controlListener; 73 Transfer[] transferAgents = new Transfer[0]; 74 DropTargetEffect dropEffect; 75 76 TransferData selectedDataType; 78 int selectedOperation; 79 80 int keyOperation = -1; 82 83 IDataObject iDataObject; 87 88 COMObject iDropTarget; 90 int refCount; 91 92 static final String DEFAULT_DROP_TARGET_EFFECT = "DEFAULT_DROP_TARGET_EFFECT"; static final String DROPTARGETID = "DropTarget"; 95 126 public DropTarget(Control control, int style) { 127 super (control, checkStyle(style)); 128 this.control = control; 129 if (control.getData(DROPTARGETID) != null) { 130 DND.error(DND.ERROR_CANNOT_INIT_DROP); 131 } 132 control.setData(DROPTARGETID, this); 133 createCOMInterfaces(); 134 this.AddRef(); 135 136 if (COM.CoLockObjectExternal(iDropTarget.getAddress(), true, true) != COM.S_OK) 137 DND.error(DND.ERROR_CANNOT_INIT_DROP); 138 if (COM.RegisterDragDrop( control.handle, iDropTarget.getAddress()) != COM.S_OK) 139 DND.error(DND.ERROR_CANNOT_INIT_DROP); 140 141 controlListener = new Listener () { 142 public void handleEvent (Event event) { 143 if (!DropTarget.this.isDisposed()){ 144 DropTarget.this.dispose(); 145 } 146 } 147 }; 148 control.addListener (SWT.Dispose, controlListener); 149 150 this.addListener(SWT.Dispose, new Listener () { 151 public void handleEvent (Event event) { 152 onDispose(); 153 } 154 }); 155 156 Object effect = control.getData(DEFAULT_DROP_TARGET_EFFECT); 157 if (effect instanceof DropTargetEffect) { 158 dropEffect = (DropTargetEffect) effect; 159 } else if (control instanceof Table) { 160 dropEffect = new TableDropTargetEffect((Table) control); 161 } else if (control instanceof Tree) { 162 dropEffect = new TreeDropTargetEffect((Tree) control); 163 } 164 } 165 166 static int checkStyle (int style) { 167 if (style == SWT.NONE) return DND.DROP_MOVE; 168 return style; 169 } 170 171 203 public void addDropListener(DropTargetListener listener) { 204 if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT); 205 DNDListener typedListener = new DNDListener (listener); 206 typedListener.dndWidget = this; 207 addListener (DND.DragEnter, typedListener); 208 addListener (DND.DragLeave, typedListener); 209 addListener (DND.DragOver, typedListener); 210 addListener (DND.DragOperationChanged, typedListener); 211 addListener (DND.Drop, typedListener); 212 addListener (DND.DropAccept, typedListener); 213 } 214 215 int AddRef() { 216 refCount++; 217 return refCount; 218 } 219 220 protected void checkSubclass () { 221 String name = getClass().getName (); 222 String validName = DropTarget.class.getName(); 223 if (!validName.equals(name)) { 224 DND.error (SWT.ERROR_INVALID_SUBCLASS); 225 } 226 } 227 228 void createCOMInterfaces() { 229 iDropTarget = new COMObject(new int[]{2, 0, 0, 5, 4, 0, 5}){ 231 public int method0(int[] args) {return QueryInterface(args[0], args[1]);} 232 public int method1(int[] args) {return AddRef();} 233 public int method2(int[] args) {return Release();} 234 public int method3(int[] args) {return DragEnter(args[0], args[1], args[2], args[3], args[4]);} 235 public int method4(int[] args) {return DragOver(args[0], args[1], args[2], args[3]);} 236 public int method5(int[] args) {return DragLeave();} 237 public int method6(int[] args) {return Drop(args[0], args[1], args[2], args[3], args[4]);} 238 }; 239 240 } 241 242 void disposeCOMInterfaces() { 243 if (iDropTarget != null) 244 iDropTarget.dispose(); 245 iDropTarget = null; 246 } 247 248 int DragEnter(int pDataObject, int grfKeyState, int pt_x, int pt_y, int pdwEffect) { 249 selectedDataType = null; 250 selectedOperation = DND.DROP_NONE; 251 if (iDataObject != null) iDataObject.Release(); 252 iDataObject = null; 253 254 DNDEvent event = new DNDEvent(); 255 if (!setEventData(event, pDataObject, grfKeyState, pt_x, pt_y, pdwEffect)) { 256 OS.MoveMemory(pdwEffect, new int[] {COM.DROPEFFECT_NONE}, 4); 257 return COM.S_FALSE; 258 } 259 260 iDataObject = new IDataObject(pDataObject); 262 iDataObject.AddRef(); 263 264 int allowedOperations = event.operations; 265 TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length]; 266 System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length); 267 notifyListeners(DND.DragEnter, event); 268 refresh(); 269 if (event.detail == DND.DROP_DEFAULT) { 270 event.detail = (allowedOperations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE; 271 } 272 273 selectedDataType = null; 274 for (int i = 0; i < allowedDataTypes.length; i++) { 275 if (TransferData.sameType(allowedDataTypes[i], event.dataType)){ 276 selectedDataType = allowedDataTypes[i]; 277 break; 278 } 279 } 280 281 selectedOperation = DND.DROP_NONE; 282 if (selectedDataType != null && ((allowedOperations & event.detail) != 0)) { 283 selectedOperation = event.detail; 284 } 285 286 OS.MoveMemory(pdwEffect, new int[] {opToOs(selectedOperation)}, 4); 287 return COM.S_OK; 288 } 289 290 int DragLeave() { 291 keyOperation = -1; 292 293 if (iDataObject == null) return COM.S_FALSE; 294 295 DNDEvent event = new DNDEvent(); 296 event.widget = this; 297 event.time = OS.GetMessageTime(); 298 event.detail = DND.DROP_NONE; 299 notifyListeners(DND.DragLeave, event); 300 refresh(); 301 302 iDataObject.Release(); 303 iDataObject = null; 304 return COM.S_OK; 305 } 306 307 int DragOver(int grfKeyState, int pt_x, int pt_y, int pdwEffect) { 308 if (iDataObject == null) return COM.S_FALSE; 309 int oldKeyOperation = keyOperation; 310 311 DNDEvent event = new DNDEvent(); 312 if (!setEventData(event, iDataObject.getAddress(), grfKeyState, pt_x, pt_y, pdwEffect)) { 313 keyOperation = -1; 314 OS.MoveMemory(pdwEffect, new int[] {COM.DROPEFFECT_NONE}, 4); 315 return COM.S_FALSE; 316 } 317 318 int allowedOperations = event.operations; 319 TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length]; 320 System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length); 321 322 if (keyOperation == oldKeyOperation) { 323 event.type = DND.DragOver; 324 event.dataType = selectedDataType; 325 event.detail = selectedOperation; 326 } else { 327 event.type = DND.DragOperationChanged; 328 event.dataType = selectedDataType; 329 } 330 notifyListeners(event.type, event); 331 refresh(); 332 if (event.detail == DND.DROP_DEFAULT) { 333 event.detail = (allowedOperations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE; 334 } 335 336 selectedDataType = null; 337 for (int i = 0; i < allowedDataTypes.length; i++) { 338 if (TransferData.sameType(allowedDataTypes[i], event.dataType)){ 339 selectedDataType = allowedDataTypes[i]; 340 break; 341 } 342 } 343 344 selectedOperation = DND.DROP_NONE; 345 if (selectedDataType != null && ((allowedOperations & event.detail) == event.detail)) { 346 selectedOperation = event.detail; 347 } 348 349 OS.MoveMemory(pdwEffect, new int[] {opToOs(selectedOperation)}, 4); 350 return COM.S_OK; 351 } 352 353 int Drop(int pDataObject, int grfKeyState, int pt_x, int pt_y, int pdwEffect) { 354 DNDEvent event = new DNDEvent(); 355 event.widget = this; 356 event.time = OS.GetMessageTime(); 357 if (dropEffect != null) { 358 event.item = dropEffect.getItem(pt_x, pt_y); 359 } 360 event.detail = DND.DROP_NONE; 361 notifyListeners(DND.DragLeave, event); 362 refresh(); 363 364 event = new DNDEvent(); 365 if (!setEventData(event, pDataObject, grfKeyState, pt_x, pt_y, pdwEffect)) { 366 keyOperation = -1; 367 OS.MoveMemory(pdwEffect, new int[] {COM.DROPEFFECT_NONE}, 4); 368 return COM.S_FALSE; 369 } 370 keyOperation = -1; 371 int allowedOperations = event.operations; 372 TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length]; 373 System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length); 374 event.dataType = selectedDataType; 375 event.detail = selectedOperation; 376 notifyListeners(DND.DropAccept,event); 377 refresh(); 378 379 selectedDataType = null; 380 for (int i = 0; i < allowedDataTypes.length; i++) { 381 if (TransferData.sameType(allowedDataTypes[i], event.dataType)){ 382 selectedDataType = allowedDataTypes[i]; 383 break; 384 } 385 } 386 selectedOperation = DND.DROP_NONE; 387 if (selectedDataType != null && (allowedOperations & event.detail) == event.detail) { 388 selectedOperation = event.detail; 389 } 390 391 if (selectedOperation == DND.DROP_NONE){ 392 OS.MoveMemory(pdwEffect, new int[] {COM.DROPEFFECT_NONE}, 4); 393 return COM.S_OK; 394 } 395 396 Object object = null; 398 for (int i = 0; i < transferAgents.length; i++){ 399 Transfer transfer = transferAgents[i]; 400 if (transfer != null && transfer.isSupportedType(selectedDataType)){ 401 object = transfer.nativeToJava(selectedDataType); 402 break; 403 } 404 } 405 if (object == null){ 406 selectedOperation = DND.DROP_NONE; 407 } 408 409 event.detail = selectedOperation; 410 event.dataType = selectedDataType; 411 event.data = object; 412 OS.ImageList_DragShowNolock(false); 413 try { 414 notifyListeners(DND.Drop,event); 415 } finally { 416 OS.ImageList_DragShowNolock(true); 417 } 418 refresh(); 419 selectedOperation = DND.DROP_NONE; 420 if ((allowedOperations & event.detail) == event.detail) { 421 selectedOperation = event.detail; 422 } 423 OS.MoveMemory(pdwEffect, new int[] {opToOs(selectedOperation)}, 4); 425 return COM.S_OK; 426 } 427 428 434 public Control getControl () { 435 return control; 436 } 437 438 447 public DropTargetEffect getDropTargetEffect() { 448 return dropEffect; 449 } 450 451 int getOperationFromKeyState(int grfKeyState) { 452 boolean ctrl = (grfKeyState & OS.MK_CONTROL) != 0; 453 boolean shift = (grfKeyState & OS.MK_SHIFT) != 0; 454 boolean alt = (grfKeyState & OS.MK_ALT) != 0; 455 if (alt) { 456 if (ctrl || shift) return DND.DROP_DEFAULT; 457 return DND.DROP_LINK; 458 } 459 if (ctrl && shift) return DND.DROP_LINK; 460 if (ctrl)return DND.DROP_COPY; 461 if (shift)return DND.DROP_MOVE; 462 return DND.DROP_DEFAULT; 463 } 464 465 470 public Transfer[] getTransfer() { 471 return transferAgents; 472 } 473 474 void onDispose () { 475 if (control == null) return; 476 477 COM.RevokeDragDrop(control.handle); 478 479 if (controlListener != null) 480 control.removeListener(SWT.Dispose, controlListener); 481 controlListener = null; 482 control.setData(DROPTARGETID, null); 483 transferAgents = null; 484 control = null; 485 486 COM.CoLockObjectExternal(iDropTarget.getAddress(), false, true); 487 488 this.Release(); 489 490 COM.CoFreeUnusedLibraries(); 491 } 492 493 int opToOs(int operation) { 494 int osOperation = 0; 495 if ((operation & DND.DROP_COPY) != 0){ 496 osOperation |= COM.DROPEFFECT_COPY; 497 } 498 if ((operation & DND.DROP_LINK) != 0) { 499 osOperation |= COM.DROPEFFECT_LINK; 500 } 501 if ((operation & DND.DROP_MOVE) != 0) { 502 osOperation |= COM.DROPEFFECT_MOVE; 503 } 504 return osOperation; 505 } 506 507 int osToOp(int osOperation){ 508 int operation = 0; 509 if ((osOperation & COM.DROPEFFECT_COPY) != 0){ 510 operation |= DND.DROP_COPY; 511 } 512 if ((osOperation & COM.DROPEFFECT_LINK) != 0) { 513 operation |= DND.DROP_LINK; 514 } 515 if ((osOperation & COM.DROPEFFECT_MOVE) != 0) { 516 operation |= DND.DROP_MOVE; 517 } 518 return operation; 519 } 520 521 525 int QueryInterface(int riid, int ppvObject) { 526 527 if (riid == 0 || ppvObject == 0) 528 return COM.E_INVALIDARG; 529 GUID guid = new GUID(); 530 COM.MoveMemory(guid, riid, GUID.sizeof); 531 if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDropTarget)) { 532 OS.MoveMemory(ppvObject, new int[] {iDropTarget.getAddress()}, 4); 533 AddRef(); 534 return COM.S_OK; 535 } 536 537 OS.MoveMemory(ppvObject, new int[] {0}, 4); 538 return COM.E_NOINTERFACE; 539 } 540 541 int Release() { 542 refCount--; 543 544 if (refCount == 0) { 545 disposeCOMInterfaces(); 546 COM.CoFreeUnusedLibraries(); 547 } 548 549 return refCount; 550 } 551 552 void refresh() { 553 if (control == null || control.isDisposed()) return; 554 int handle = control.handle; 555 RECT lpRect = new RECT(); 556 if (OS.GetUpdateRect(handle, lpRect, false)) { 557 OS.ImageList_DragShowNolock(false); 558 OS.RedrawWindow(handle, lpRect, 0, OS.RDW_UPDATENOW | OS.RDW_INVALIDATE); 559 OS.ImageList_DragShowNolock(true); 560 } 561 } 562 563 580 public void removeDropListener(DropTargetListener listener) { 581 if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT); 582 removeListener (DND.DragEnter, listener); 583 removeListener (DND.DragLeave, listener); 584 removeListener (DND.DragOver, listener); 585 removeListener (DND.DragOperationChanged, listener); 586 removeListener (DND.Drop, listener); 587 removeListener (DND.DropAccept, listener); 588 } 589 590 599 public void setDropTargetEffect(DropTargetEffect effect) { 600 dropEffect = effect; 601 } 602 603 boolean setEventData(DNDEvent event, int pDataObject, int grfKeyState, int pt_x, int pt_y, int pdwEffect) { 604 if (pDataObject == 0 || pdwEffect == 0) return false; 605 606 int style = getStyle(); 608 int[] operations = new int[1]; 609 OS.MoveMemory(operations, pdwEffect, 4); 610 operations[0] = osToOp(operations[0]) & style; 611 if (operations[0] == DND.DROP_NONE) return false; 612 613 int operation = getOperationFromKeyState(grfKeyState); 615 keyOperation = operation; 616 if (operation == DND.DROP_DEFAULT) { 617 if ((style & DND.DROP_DEFAULT) == 0) { 618 operation = (operations[0] & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE; 619 } 620 } else { 621 if ((operation & operations[0]) == 0) operation = DND.DROP_NONE; 622 } 623 624 TransferData[] dataTypes = new TransferData[0]; 626 IDataObject dataObject = new IDataObject(pDataObject); 627 dataObject.AddRef(); 628 try { 629 int[] address = new int[1]; 630 if (dataObject.EnumFormatEtc(COM.DATADIR_GET, address) != COM.S_OK) { 631 return false; 632 } 633 IEnumFORMATETC enumFormatetc = new IEnumFORMATETC(address[0]); 634 try { 635 int rgelt = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, FORMATETC.sizeof); 637 try { 638 int[] pceltFetched = new int[1]; 639 enumFormatetc.Reset(); 640 while (enumFormatetc.Next(1, rgelt, pceltFetched) == COM.S_OK && pceltFetched[0] == 1) { 641 TransferData transferData = new TransferData(); 642 transferData.formatetc = new FORMATETC(); 643 COM.MoveMemory(transferData.formatetc, rgelt, FORMATETC.sizeof); 644 transferData.type = transferData.formatetc.cfFormat; 645 transferData.pIDataObject = pDataObject; 646 for (int i = 0; i < transferAgents.length; i++){ 647 Transfer transfer = transferAgents[i]; 648 if (transfer != null && transfer.isSupportedType(transferData)){ 649 TransferData[] newDataTypes = new TransferData[dataTypes.length + 1]; 650 System.arraycopy(dataTypes, 0, newDataTypes, 0, dataTypes.length); 651 newDataTypes[dataTypes.length] = transferData; 652 dataTypes = newDataTypes; 653 break; 654 } 655 } 656 } 657 } finally { 658 OS.GlobalFree(rgelt); 659 } 660 } finally { 661 enumFormatetc.Release(); 662 } 663 } finally { 664 dataObject.Release(); 665 } 666 if (dataTypes.length == 0) return false; 667 668 event.widget = this; 669 event.x = pt_x; 670 event.y = pt_y; 671 event.time = OS.GetMessageTime(); 672 event.feedback = DND.FEEDBACK_SELECT; 673 event.dataTypes = dataTypes; 674 event.dataType = dataTypes[0]; 675 if (dropEffect != null) { 676 event.item = dropEffect.getItem(pt_x, pt_y); 677 } 678 event.operations = operations[0]; 679 event.detail = operation; 680 return true; 681 } 682 683 696 public void setTransfer(Transfer[] transferAgents){ 697 if (transferAgents == null) DND.error(SWT.ERROR_NULL_ARGUMENT); 698 this.transferAgents = transferAgents; 699 } 700 } 701 | Popular Tags |