1 17 package org.eclipse.emf.edit.command; 18 19 20 import java.util.ArrayList ; 21 import java.util.Collection ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.ListIterator ; 25 26 import org.eclipse.emf.common.command.AbstractCommand; 27 import org.eclipse.emf.common.command.Command; 28 import org.eclipse.emf.common.command.CommandWrapper; 29 import org.eclipse.emf.common.command.CompoundCommand; 30 import org.eclipse.emf.common.command.IdentityCommand; 31 import org.eclipse.emf.common.command.UnexecutableCommand; 32 import org.eclipse.emf.ecore.EReference; 33 import org.eclipse.emf.ecore.EStructuralFeature; 34 import org.eclipse.emf.edit.EMFEditPlugin; 35 import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; 36 import org.eclipse.emf.edit.domain.EditingDomain; 37 38 39 48 public class DragAndDropCommand extends AbstractCommand implements DragAndDropFeedback 49 { 50 54 public static class Detail 55 { 56 public float location; 57 public int operations; 58 public int operation; 59 60 public Detail(float location, int operations, int operation) 61 { 62 this.location = location; 63 this.operations = operations; 64 this.operation = operation; 65 } 66 } 67 68 72 public static Command create(EditingDomain domain, Object owner, float location, int operations, int operation, Collection collection) 73 { 74 return 75 domain.createCommand 76 (DragAndDropCommand.class, new CommandParameter(owner, new Detail(location, operations, operation), collection)); 77 } 78 79 82 protected static final String LABEL = EMFEditPlugin.INSTANCE.getString("_UI_DragAndDropCommand_label"); 83 84 87 protected static final String DESCRIPTION = EMFEditPlugin.INSTANCE.getString("_UI_DragAndDropCommand_description"); 88 89 92 protected EditingDomain domain; 93 94 97 protected Object owner; 98 99 102 protected float location; 103 104 107 protected float lowerLocationBound; 108 109 112 protected float upperLocationBound; 113 114 117 protected int operations; 118 119 122 protected int operation; 123 124 127 protected int feedback; 128 129 132 protected Collection collection; 133 134 137 protected Command dragCommand; 138 139 142 protected boolean isDragCommandExecuted; 143 144 147 protected Command dropCommand; 148 149 152 protected boolean optimize; 153 154 157 protected Object optimizedDropCommandOwner; 158 159 168 public DragAndDropCommand(EditingDomain domain, Object owner, float location, int operations, int operation, Collection collection) 169 { 170 this(domain, owner, location, operations, operation, collection, domain == null ? false : domain.getOptimizeCopy()); 171 } 172 173 public DragAndDropCommand 174 (EditingDomain domain, Object owner, float location, int operations, int operation, Collection collection, boolean optimize) 175 { 176 super(LABEL, DESCRIPTION); 177 178 this.domain = domain; 179 this.owner = owner; 180 this.location = location; 181 this.operations = operations; 182 this.operation = operation; 183 this.collection = collection; 184 this.optimize = optimize; 185 186 this.optimize = false; 189 } 190 191 protected boolean analyzeForNonContainment(Command command) 192 { 193 if (command instanceof AddCommand) 194 { 195 return isNonContainment(((AddCommand)command).getFeature()); 196 } 197 else if (command instanceof SetCommand) 198 { 199 return isNonContainment(((SetCommand)command).getFeature()); 200 } 201 else if (command instanceof CommandWrapper) 202 { 203 return analyzeForNonContainment(((CommandWrapper)command).getCommand()); 204 } 205 else if (command instanceof CompoundCommand) 206 { 207 for (Iterator i = ((CompoundCommand)command).getCommandList().iterator(); i.hasNext(); ) 208 { 209 if (analyzeForNonContainment((Command)i.next())) 210 { 211 return true; 212 } 213 } 214 } 215 216 return false; 217 } 218 219 protected boolean isNonContainment(EStructuralFeature feature) 220 { 221 return feature instanceof EReference && !((EReference)feature).isContainment(); 222 } 223 224 public Object getOwner() 225 { 226 return owner; 227 } 228 229 public float getLocation() 230 { 231 return location; 232 } 233 234 public int getOperations() 235 { 236 return operations; 237 } 238 239 public Collection getCollection() 240 { 241 return collection; 242 } 243 244 248 protected boolean prepare() 249 { 250 boolean result = false; 253 254 if (owner != null && collection != null && operations != DROP_NONE && operation != DROP_NONE) 257 { 258 if (location <= 0.20 || location >= 0.80) 261 { 262 result = prepareDropInsert(); 265 if (result) 266 { 267 if (location <= 0.20) 270 { 271 lowerLocationBound = 0.0F; 272 upperLocationBound = 2.0F; 273 } 274 else 275 { 276 lowerLocationBound = 8.0F; 277 upperLocationBound = 1.0F; 278 } 279 } 280 else 281 { 282 reset(); 285 result = prepareDropOn(); 286 287 if (location <= 0.20) 290 { 291 lowerLocationBound = 0.0F; 292 upperLocationBound = 0.8F; 293 } 294 else 295 { 296 lowerLocationBound = 0.2F; 297 upperLocationBound = 1.0F; 298 } 299 } 300 } 301 else 304 { 305 result = prepareDropOn(); 308 if (result) 309 { 310 lowerLocationBound = 0.2F; 313 upperLocationBound = 0.8F; 314 } 315 else 316 { 317 reset(); 320 result = prepareDropInsert(); 321 322 if (location <= 0.50) 325 { 326 lowerLocationBound = 0.0F; 327 upperLocationBound = 0.5F; 328 } 329 else 330 { 331 lowerLocationBound = 0.5F; 332 upperLocationBound = 1.0F; 333 } 334 } 335 } 336 } 337 else 338 { 339 lowerLocationBound = 0.0F; 342 upperLocationBound = 1.0F; 343 } 344 345 return result; 346 } 347 348 351 protected Object getParent(Object object) 352 { 353 return domain.getParent(object); 354 } 355 356 359 protected Collection getChildren(Object object) 360 { 361 return domain.getChildren(object); 362 } 363 364 367 protected boolean prepareDropInsert() 368 { 369 boolean result = false; 372 373 feedback = location < 0.5 ? FEEDBACK_INSERT_BEFORE : FEEDBACK_INSERT_AFTER; 377 378 Object parent = getParent(owner); 381 if (parent == null) 382 { 383 dragCommand = UnexecutableCommand.INSTANCE; 384 dropCommand = UnexecutableCommand.INSTANCE; 385 } 386 else 387 { 388 Collection children = getChildren(parent); 391 int i = 0; 392 for (Iterator iterator = children.iterator(); iterator.hasNext(); ++i) 393 { 394 Object child = iterator.next(); 395 396 if (child == owner) 399 { 400 break; 401 } 402 } 403 404 if (location >= 0.5) 407 { 408 ++i; 409 } 410 411 switch (operation) 414 { 415 case DROP_MOVE: 416 { 417 result = prepareDropMoveInsert(parent, children, i); 418 break; 419 } 420 case DROP_COPY: 421 { 422 result = prepareDropCopyInsert(parent, children, i); 423 break; 424 } 425 case DROP_LINK: 426 { 427 result = prepareDropLinkInsert(parent, children, i); 428 break; 429 } 430 } 431 432 if (!result && operation != DROP_COPY && operation != DROP_LINK && (operations & DROP_COPY) != 0) 435 { 436 reset(); 439 result = prepareDropCopyInsert(parent, children, i); 440 441 if (result) 442 { 443 operation = DROP_COPY; 446 } 447 } 448 449 if (!result && operation != DROP_LINK && (operations & DROP_LINK) != 0) 452 { 453 reset(); 456 result = prepareDropLinkInsert(parent, children, i); 457 if (result) 458 { 459 operation = DROP_LINK; 462 } 463 } 464 } 465 466 return result; 467 } 468 469 472 protected boolean prepareDropMoveInsert(Object parent, Collection children, int index) 473 { 474 if (collection.contains(owner)) 477 { 478 dragCommand = IdentityCommand.INSTANCE; 479 dropCommand = UnexecutableCommand.INSTANCE; 480 } 481 else if (children.containsAll(collection)) 484 { 485 dragCommand = IdentityCommand.INSTANCE; 486 487 CompoundCommand compoundCommand = new CompoundCommand(); 490 List before = new ArrayList (); 491 List after = new ArrayList (); 492 493 int j = 0; 494 for (Iterator objects = children.iterator(); objects.hasNext(); ++j) 495 { 496 Object object = objects.next(); 497 if (collection.contains(object)) 498 { 499 if (j < index) 500 { 501 before.add(object); 502 } 503 else if (j > index) 504 { 505 after.add(object); 506 } 507 } 508 } 509 510 for (Iterator objects = before.iterator(); objects.hasNext(); ) 511 { 512 Object object = objects.next(); 513 compoundCommand.append(MoveCommand.create(domain, parent, null, object, index - 1)); 514 } 515 516 for (ListIterator objects = after.listIterator(after.size()); objects.hasPrevious(); ) 517 { 518 Object object = objects.previous(); 519 compoundCommand.append(MoveCommand.create(domain, parent, null, object, index)); 520 } 521 522 dropCommand = compoundCommand.getCommandList().size() == 0 ? (Command)IdentityCommand.INSTANCE : compoundCommand; 523 } 524 else if (isCrossDomain()) 525 { 526 dragCommand = IdentityCommand.INSTANCE; 527 dropCommand = UnexecutableCommand.INSTANCE; 528 } 529 else 530 { 531 dropCommand = AddCommand.create(domain, parent, null, collection, index); 534 if (analyzeForNonContainment(dropCommand)) 535 { 536 dropCommand.dispose(); 537 dropCommand = UnexecutableCommand.INSTANCE; 538 dragCommand = IdentityCommand.INSTANCE; 539 } 540 else 541 { 542 dragCommand = RemoveCommand.create(domain, collection); 543 } 544 } 545 546 boolean result = dragCommand.canExecute() && dropCommand.canExecute(); 547 return result; 548 } 549 550 protected boolean isCrossDomain() 551 { 552 for (Iterator i = collection.iterator(); i.hasNext(); ) 553 { 554 EditingDomain itemDomain = AdapterFactoryEditingDomain.getEditingDomainFor(i.next()); 555 if (itemDomain != null && itemDomain != domain) 556 { 557 return true; 558 } 559 } 560 return false; 561 } 562 563 566 protected boolean prepareDropCopyInsert(final Object parent, Collection children, final int index) 567 { 568 boolean result; 569 570 if (collection.contains(owner)) 573 { 574 dragCommand = IdentityCommand.INSTANCE; 575 dropCommand = UnexecutableCommand.INSTANCE; 576 result = false; 577 } 578 else 579 { 580 dragCommand = CopyCommand.create(domain, collection); 583 584 if (optimize) 585 { 586 result = optimizedCanExecute(); 587 if (result) 588 { 589 optimizedDropCommandOwner = parent; 590 } 591 } 592 else 593 { 594 if (dragCommand.canExecute() && dragCommand.canUndo()) 595 { 596 dragCommand.execute(); 597 isDragCommandExecuted = true; 598 599 dropCommand = AddCommand.create(domain, parent, null, dragCommand.getResult(), index); 602 if (analyzeForNonContainment(dropCommand)) 603 { 604 dropCommand.dispose(); 605 dropCommand = UnexecutableCommand.INSTANCE;; 606 607 dragCommand.undo(); 608 dragCommand.dispose(); 609 isDragCommandExecuted = false; 610 dragCommand = IdentityCommand.INSTANCE; 611 } 612 result = dropCommand.canExecute(); 613 } 614 else 615 { 616 dropCommand = UnexecutableCommand.INSTANCE; 617 result = false; 618 } 619 } } 622 return result; 623 } 624 625 628 protected boolean prepareDropLinkInsert(Object parent, Collection children, int index) 629 { 630 boolean result; 631 632 if (collection.contains(owner)) 635 { 636 dragCommand = IdentityCommand.INSTANCE; 637 dropCommand = UnexecutableCommand.INSTANCE; 638 result = false; 639 } 640 else 641 { 642 dragCommand = IdentityCommand.INSTANCE; 643 644 dropCommand = AddCommand.create(domain, parent, null, collection, index); 647 if (!analyzeForNonContainment(dropCommand)) 648 { 649 dropCommand.dispose(); 650 dropCommand = UnexecutableCommand.INSTANCE;; 651 } 652 result = dropCommand.canExecute(); 653 } 654 655 return result; 656 } 657 658 661 protected boolean prepareDropOn() 662 { 663 boolean result = false; 666 667 feedback = FEEDBACK_SELECT; 670 671 switch (operation) 674 { 675 case DROP_MOVE: 676 { 677 result = prepareDropMoveOn(); 678 break; 679 } 680 case DROP_COPY: 681 { 682 result = prepareDropCopyOn(); 683 break; 684 } 685 case DROP_LINK: 686 { 687 result = prepareDropLinkOn(); 688 break; 689 } 690 } 691 692 if (!result && operation != DROP_COPY && operation != DROP_LINK && (operations & DROP_COPY) != 0) 695 { 696 reset(); 697 result = prepareDropCopyOn(); 698 if (result) 699 { 700 operation = DROP_COPY; 701 } 702 } 703 704 if (!result && operation != DROP_LINK && (operations & DROP_LINK) != 0) 707 { 708 reset(); 709 result = prepareDropLinkOn(); 710 if (result) 711 { 712 operation = DROP_LINK; 713 } 714 } 715 716 return result; 717 } 718 719 722 protected boolean prepareDropMoveOn() 723 { 724 if (isCrossDomain()) 725 { 726 dragCommand = IdentityCommand.INSTANCE; 727 dropCommand = UnexecutableCommand.INSTANCE; 728 } 729 else 730 { 731 dropCommand = AddCommand.create(domain, owner, null, collection); 732 if (analyzeForNonContainment(dropCommand)) 733 { 734 dropCommand.dispose(); 735 dropCommand = UnexecutableCommand.INSTANCE; 736 dragCommand = IdentityCommand.INSTANCE; 737 } 738 else 739 { 740 dragCommand = RemoveCommand.create(domain, collection); 741 } 742 } 743 744 boolean result = dragCommand.canExecute() && dropCommand.canExecute(); 745 return result; 746 } 747 748 751 protected boolean prepareDropCopyOn() 752 { 753 boolean result; 754 755 dragCommand = CopyCommand.create(domain, collection); 756 757 if (optimize) 758 { 759 result = optimizedCanExecute(); 760 if (result) 761 { 762 optimizedDropCommandOwner = owner; 763 } 764 } 765 else 766 { 767 if (dragCommand.canExecute() && dragCommand.canUndo()) 768 { 769 dragCommand.execute(); 770 isDragCommandExecuted = true; 771 dropCommand = AddCommand.create(domain, owner, null, dragCommand.getResult()); 772 if (analyzeForNonContainment(dropCommand)) 773 { 774 dropCommand.dispose(); 775 dropCommand = UnexecutableCommand.INSTANCE;; 776 777 dragCommand.undo(); 778 dragCommand.dispose(); 779 isDragCommandExecuted = false; 780 dragCommand = IdentityCommand.INSTANCE; 781 } 782 } 783 else 784 { 785 dropCommand = UnexecutableCommand.INSTANCE; 786 } 787 788 result = dragCommand.canExecute() && dropCommand.canExecute(); 789 } 790 return result; 791 } 792 793 796 protected boolean prepareDropLinkOn() 797 { 798 dragCommand = IdentityCommand.INSTANCE; 799 dropCommand = SetCommand.create(domain, owner, null, collection); 800 801 if (!dropCommand.canExecute() && collection.size() == 1) 804 { 805 dropCommand.dispose(); 806 dropCommand = SetCommand.create(domain, owner, null, collection.iterator().next()); 807 } 808 809 if (!dropCommand.canExecute() || analyzeForNonContainment(dropCommand)) 810 { 811 dropCommand.dispose(); 812 dropCommand = AddCommand.create(domain, owner, null, collection); 813 } 814 815 boolean result = dropCommand.canExecute(); 816 return result; 817 } 818 819 protected boolean optimizedCanExecute() 820 { 821 Command addCommand = AddCommand.create(domain, owner, null, collection); 825 boolean result = addCommand.canExecute() && !analyzeForNonContainment(addCommand); 826 addCommand.dispose(); 827 return result; 828 } 829 830 833 protected void reset() 834 { 835 if (dragCommand != null) 836 { 837 if (isDragCommandExecuted) 838 { 839 if (dragCommand.canUndo()) 840 { 841 dragCommand.undo(); 842 } 843 } 844 dragCommand.dispose(); 845 } 846 847 if (dropCommand != null) 848 { 849 dropCommand.dispose(); 850 } 851 852 isPrepared = false; 855 isExecutable = false; 856 857 dragCommand = null; 858 isDragCommandExecuted = false; 859 dropCommand = null; 860 optimizedDropCommandOwner = null; 861 } 862 863 866 public boolean validate(Object owner, float location, int operations, int operation, Collection collection) 867 { 868 if (owner != this.owner || 871 location != this.location || (location < lowerLocationBound || location > upperLocationBound) || 872 operation != this.operation || 873 collection != this.collection) 874 { 875 reset(); 878 879 this.owner = owner; 882 this.location = location; 883 this.operations = operations; 884 this.operation = operation; 885 this.collection = collection; 886 887 return canExecute(); 890 } 891 else 892 { 893 return isExecutable; 896 } 897 } 898 899 public int getFeedback() 900 { 901 return isExecutable ? feedback : FEEDBACK_SELECT; 904 } 905 906 public int getOperation() 907 { 908 return isExecutable ? operation : DROP_NONE; 911 } 912 913 public void execute() 914 { 915 if (dragCommand != null && !isDragCommandExecuted) 916 { 917 if (optimizedDropCommandOwner != null) 920 { 921 if (dragCommand.canExecute()) 922 { 923 dragCommand.execute(); 924 dropCommand = AddCommand.create(domain, optimizedDropCommandOwner, null, dragCommand.getResult()); 925 } 926 else 927 { 928 } 930 } 931 else 932 { 933 dragCommand.execute(); 934 } 935 } 936 937 if (dropCommand != null) 938 { 939 if (dropCommand.canExecute()) 940 { 941 dropCommand.execute(); 942 } 943 else 944 { 945 } 947 } 948 } 949 950 public void undo() 951 { 952 if (dropCommand != null) 953 { 954 dropCommand.undo(); 955 } 956 957 if (dragCommand != null) 958 { 959 dragCommand.undo(); 960 } 961 } 962 963 public void redo() 964 { 965 if (dragCommand != null) 966 { 967 dragCommand.redo(); 968 } 969 970 if (dropCommand != null) 971 { 972 dropCommand.redo(); 973 } 974 } 975 976 public void dispose() 977 { 978 if (dragCommand != null) 979 { 980 dragCommand.dispose(); 981 } 982 if (dropCommand != null) 983 { 984 dropCommand.dispose(); 985 } 986 } 987 988 public Collection getResult() 989 { 990 return 991 dropCommand != null ? 992 dropCommand.getResult() : 993 super.getResult(); 994 } 995 996 public Collection getAffectedObjects() 997 { 998 return 999 dropCommand != null ? 1000 dropCommand.getAffectedObjects() : 1001 super.getAffectedObjects(); 1002 } 1003 1004 1008 public String toString() 1009 { 1010 StringBuffer result = new StringBuffer (super.toString()); 1011 result.append(" (domain: " + domain + ")"); 1012 result.append(" (owner: " + owner + ")"); 1013 result.append(" (location: " + location + ")"); 1014 result.append(" (lowerLocationBound: " + lowerLocationBound + ")"); 1015 result.append(" (upperLocationBound: " + upperLocationBound + ")"); 1016 result.append(" (operations: " + operations + ")"); 1017 result.append(" (operation: " + operation + ")"); 1018 result.append(" (collection: " + collection + ")"); 1019 result.append(" (feedback: " + feedback + ")"); 1020 1021 return result.toString(); 1022 } 1023} 1024 | Popular Tags |