1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.adt.internal.editors.layout.gle2; 18 19 import com.android.annotations.NonNull; 20 import com.android.annotations.Nullable; 21 import com.android.ide.common.api.IViewRule; 22 import com.android.ide.common.api.Rect; 23 24 25 /** 26 * This singleton is used to keep track of drag'n'drops initiated within this 27 * session of Eclipse. A drag can be initiated from a palette or from a canvas 28 * and its content is an Android View fully-qualified class name. 29 * <p/> 30 * Overall this is a workaround: the issue is that the drag'n'drop SWT API does not 31 * allow us to know the transfered data during the initial drag -- only when the 32 * data is dropped do we know what it is about (and to be more exact there is a workaround 33 * to do just that which works on Windows but not on Linux/Mac SWT). 34 * <p/> 35 * In the GLE we'd like to adjust drag feedback to the data being actually dropped. 36 * The singleton instance of this class will be used to track the data currently dragged 37 * off a canvas or its palette and then set back to null when the drag'n'drop is finished. 38 * <p/> 39 * Note that when a drag starts in one instance of Eclipse and the dragOver/drop is done 40 * in a <em>separate</em> instance of Eclipse, the dragged FQCN won't be registered here 41 * and will be null. 42 */ 43 final class GlobalCanvasDragInfo { 44 45 private static final GlobalCanvasDragInfo sInstance = new GlobalCanvasDragInfo(); 46 47 private SimpleElement[] mCurrentElements = null; 48 private SelectionItem[] mCurrentSelection; 49 private Object mSourceCanvas = null; 50 private Runnable mRemoveSourceHandler; 51 private Rect mDragBounds; 52 private int mDragBaseline = -1; 53 54 /** Private constructor. Use {@link #getInstance()} to retrieve the singleton. */ GlobalCanvasDragInfo()55 private GlobalCanvasDragInfo() { 56 // pass 57 } 58 59 /** Returns the singleton instance. */ getInstance()60 public static GlobalCanvasDragInfo getInstance() { 61 return sInstance; 62 } 63 64 /** 65 * Registers the XML elements being dragged. 66 * 67 * @param elements The elements being dragged 68 * @param primary the "primary" element among the elements; when there is a 69 * single item dragged this will be the same, but in 70 * multi-selection it will be the element under the mouse as the 71 * selection was initiated 72 * @param selection The selection (which can be null, for example when the 73 * user drags from the palette) 74 * @param sourceCanvas An object representing the source we are dragging 75 * from (used for identity comparisons only) 76 * @param removeSourceHandler A runnable (or null) which can clean up the 77 * source. It should only be invoked if the drag operation is a 78 * move, not a copy. 79 */ startDrag( @onNull SimpleElement[] elements, @Nullable SelectionItem[] selection, @Nullable Object sourceCanvas, @Nullable Runnable removeSourceHandler)80 public void startDrag( 81 @NonNull SimpleElement[] elements, 82 @Nullable SelectionItem[] selection, 83 @Nullable Object sourceCanvas, 84 @Nullable Runnable removeSourceHandler) { 85 mCurrentElements = elements; 86 mCurrentSelection = selection; 87 mSourceCanvas = sourceCanvas; 88 mRemoveSourceHandler = removeSourceHandler; 89 } 90 91 /** Unregisters elements being dragged. */ stopDrag()92 public void stopDrag() { 93 mCurrentElements = null; 94 mCurrentSelection = null; 95 mSourceCanvas = null; 96 mRemoveSourceHandler = null; 97 mDragBounds = null; 98 } 99 isDragging()100 public boolean isDragging() { 101 return mCurrentElements != null; 102 } 103 104 /** Returns the elements being dragged. */ 105 @NonNull getCurrentElements()106 public SimpleElement[] getCurrentElements() { 107 return mCurrentElements; 108 } 109 110 /** Returns the selection originally dragged. 111 * Can be null if the drag did not start in a canvas. 112 */ getCurrentSelection()113 public SelectionItem[] getCurrentSelection() { 114 return mCurrentSelection; 115 } 116 117 /** 118 * Returns the object that call {@link #startDrag(SimpleElement[], SelectionItem[], Object)}. 119 * Can be null. 120 * This is not meant to access the object indirectly, it is just meant to compare if the 121 * source and the destination of the drag'n'drop are the same, so object identity 122 * is all what matters. 123 */ getSourceCanvas()124 public Object getSourceCanvas() { 125 return mSourceCanvas; 126 } 127 128 /** 129 * Removes source of the drag. This should only be called when the drag and 130 * drop operation is a move (not a copy). 131 */ removeSource()132 public void removeSource() { 133 if (mRemoveSourceHandler != null) { 134 mRemoveSourceHandler.run(); 135 mRemoveSourceHandler = null; 136 } 137 } 138 139 /** 140 * Get the bounds of the drag, relative to the starting mouse position. For example, 141 * if you have a rectangular view of size 100x80, and you start dragging at position 142 * (15,20) from the top left corner of this rectangle, then the drag bounds would be 143 * (-15,-20, 100x80). 144 * <p> 145 * NOTE: The coordinate units will be in SWT/control pixels, not Android view pixels. 146 * In other words, they are affected by the canvas zoom: If you zoom the view and the 147 * bounds of a view grow, the drag bounds will be larger. 148 * 149 * @return the drag bounds, or null if there are no bounds for the current drag 150 */ getDragBounds()151 public Rect getDragBounds() { 152 return mDragBounds; 153 } 154 155 /** 156 * Set the bounds of the drag, relative to the starting mouse position. See 157 * {@link #getDragBounds()} for details on the semantics of the drag bounds. 158 * 159 * @param dragBounds the new drag bounds, or null if there are no drag bounds 160 */ setDragBounds(Rect dragBounds)161 public void setDragBounds(Rect dragBounds) { 162 mDragBounds = dragBounds; 163 } 164 165 /** 166 * Returns the baseline of the drag, or -1 if not applicable 167 * 168 * @return the current SWT modifier key mask as an {@link IViewRule} modifier mask 169 */ getDragBaseline()170 public int getDragBaseline() { 171 return mDragBaseline; 172 } 173 174 /** 175 * Sets the baseline of the drag 176 * 177 * @param baseline the new baseline 178 */ setDragBaseline(int baseline)179 public void setDragBaseline(int baseline) { 180 mDragBaseline = baseline; 181 } 182 } 183