001: /*******************************************************************************
002: * Copyright (c) 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: ******************************************************************************/package org.eclipse.ui.internal;
011:
012: import java.util.ArrayList;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: import org.eclipse.jface.action.ToolBarManager;
017: import org.eclipse.jface.util.Geometry;
018: import org.eclipse.swt.SWT;
019: import org.eclipse.swt.events.DisposeEvent;
020: import org.eclipse.swt.events.DisposeListener;
021: import org.eclipse.swt.graphics.Cursor;
022: import org.eclipse.swt.graphics.Point;
023: import org.eclipse.swt.graphics.Rectangle;
024: import org.eclipse.swt.widgets.Control;
025: import org.eclipse.swt.widgets.Event;
026: import org.eclipse.swt.widgets.Listener;
027: import org.eclipse.swt.widgets.ToolBar;
028: import org.eclipse.swt.widgets.ToolItem;
029: import org.eclipse.ui.IViewReference;
030: import org.eclipse.ui.internal.dnd.AbstractDropTarget;
031: import org.eclipse.ui.internal.dnd.DragUtil;
032: import org.eclipse.ui.internal.dnd.IDragOverListener;
033: import org.eclipse.ui.internal.dnd.IDropTarget;
034: import org.eclipse.ui.presentations.PresentationUtil;
035:
036: /**
037: * @since 3.3
038: *
039: */
040: public class FastViewDnDHandler implements IDragOverListener {
041: private String id;
042: private ToolBarManager tbm;
043: private WorkbenchWindow wbw;
044: private ViewDropTarget dropTarget = null;
045:
046: private Listener dragListener = new Listener() {
047: public void handleEvent(Event event) {
048: Point position = DragUtil.getEventLoc(event);
049:
050: ToolBar toolbar = tbm.getControl();
051: Point local = toolbar.toControl(position);
052: ToolItem item = toolbar.getItem(local);
053: IViewReference ref = (IViewReference) item
054: .getData(ShowFastViewContribution.FAST_VIEW);
055:
056: if (ref != null) {
057: startDraggingFastView(ref, position, false);
058: }
059: }
060: };
061:
062: class ViewDropTarget extends AbstractDropTarget {
063: List panes;
064: ToolItem curItem;
065:
066: /**
067: * @param panesToDrop the list of ViewPanes to drop at the given position
068: */
069: public ViewDropTarget(List panesToDrop, ToolItem position) {
070: setTarget(panesToDrop, position);
071: }
072:
073: public void setTarget(List panesToDrop, ToolItem position) {
074: panes = panesToDrop;
075: this .curItem = position;
076: }
077:
078: /* (non-Javadoc)
079: * @see org.eclipse.ui.internal.dnd.IDropTarget#drop()
080: */
081: public void drop() {
082: Perspective persp = wbw.getActiveWorkbenchPage()
083: .getActivePerspective();
084: FastViewManager fvm = persp.getFastViewManager();
085:
086: int insertIndex = tbm.getControl().indexOf(curItem);
087: Iterator iter = panes.iterator();
088: while (iter.hasNext()) {
089: ViewPane pane = (ViewPane) iter.next();
090: IViewReference ref = pane.getViewReference();
091: adoptRef(ref);
092: fvm.addViewReference(id, insertIndex++, ref, !iter
093: .hasNext());
094: }
095: }
096:
097: private void adoptRef(IViewReference ref) {
098: Perspective persp = wbw.getActiveWorkbenchPage()
099: .getActivePerspective();
100: PerspectiveHelper helper = persp.getPresentation();
101: ContainerPlaceholder ourContainerPlaceholder = (ContainerPlaceholder) helper
102: .findPart(id, null);
103: LayoutPart refPart = helper.findPart(ref.getId(), ref
104: .getSecondaryId());
105: ILayoutContainer refContainer = refPart.container;
106: if (refContainer != ourContainerPlaceholder) {
107: // remove the old part... if it's represented by a
108: // placeholder then just remove it...
109: if (refPart instanceof PartPlaceholder) {
110: if (refContainer instanceof ContainerPlaceholder) {
111: // just remove the placeholder
112: ViewStack realContainer = (ViewStack) ((ContainerPlaceholder) refContainer)
113: .getRealContainer();
114: realContainer.remove(refPart);
115: } else if (refContainer instanceof ViewStack) {
116: refContainer.remove(refPart);
117: }
118: } else {
119: // If its a real view ref then defref it...
120: helper.derefPart(refPart);
121: }
122: PartPlaceholder newPlaceholder = new PartPlaceholder(
123: ref.getId());
124: ourContainerPlaceholder.add(newPlaceholder);
125: }
126: }
127:
128: /*
129: * (non-Javadoc)
130: *
131: * @see org.eclipse.ui.internal.dnd.IDropTarget#getCursor()
132: */
133: public Cursor getCursor() {
134: return DragCursors.getCursor(DragCursors.FASTVIEW);
135: }
136:
137: public Rectangle getSnapRectangle() {
138: if (curItem == null) {
139: // As long as the toolbar is not empty, highlight the place
140: // where this view will appear (we
141: // may have compressed it to save space when empty, so the actual
142: // icon location may not be over the toolbar when it is empty)
143: if (tbm.getControl().getItemCount() > 0) {
144: return getLocationOfNextIcon();
145: }
146: // If the toolbar is empty, highlight the entire toolbar
147: return DragUtil.getDisplayBounds(tbm.getControl());
148: }
149:
150: return Geometry.toDisplay(tbm.getControl(), curItem
151: .getBounds());
152: }
153: }
154:
155: /**
156: *
157: */
158: public FastViewDnDHandler(String id, final ToolBarManager tbm,
159: WorkbenchWindow wbw) {
160: this .id = id;
161: this .tbm = tbm;
162: this .wbw = wbw;
163:
164: // Hook the 'drop' listener to the control
165: DragUtil.addDragTarget(tbm.getControl(), this );
166: PresentationUtil
167: .addDragListener(tbm.getControl(), dragListener);
168:
169: // Clean up on dispose
170: tbm.getControl().addDisposeListener(new DisposeListener() {
171: public void widgetDisposed(DisposeEvent e) {
172: DragUtil.removeDragTarget((Control) (e.widget),
173: FastViewDnDHandler.this );
174: PresentationUtil.removeDragListener(tbm.getControl(),
175: dragListener);
176: }
177: });
178: }
179:
180: /**
181: * Returns the toolbar item at the given position, in display coordinates
182: * @param position
183: */
184: private ToolItem getToolItem(Point position) {
185: ToolBar toolbar = tbm.getControl();
186: Point local = toolbar.toControl(position);
187: return toolbar.getItem(local);
188: }
189:
190: /* (non-Javadoc)
191: * @see org.eclipse.ui.internal.dnd.IDragOverListener#drag(org.eclipse.swt.widgets.Control, java.lang.Object, org.eclipse.swt.graphics.Point, org.eclipse.swt.graphics.Rectangle)
192: */
193: public IDropTarget drag(Control currentControl,
194: Object draggedObject, Point position,
195: Rectangle dragRectangle) {
196: // If we're trying to drop onto a 'standalone' stack, don't...
197: if (isStandaloneStack())
198: return null;
199:
200: ToolItem targetItem = getToolItem(position);
201: if (draggedObject instanceof ViewPane) {
202: ViewPane pane = (ViewPane) draggedObject;
203:
204: // Can't drag views between windows
205: if (pane.getWorkbenchWindow() != wbw) {
206: return null;
207: }
208:
209: List newList = new ArrayList(1);
210: newList.add(draggedObject);
211:
212: return createDropTarget(newList, targetItem);
213: }
214: if (draggedObject instanceof ViewStack) {
215: ViewStack folder = (ViewStack) draggedObject;
216:
217: if (folder.getWorkbenchWindow() != wbw) {
218: return null;
219: }
220:
221: List viewList = new ArrayList(folder.getItemCount());
222: LayoutPart[] children = folder.getChildren();
223:
224: for (int idx = 0; idx < children.length; idx++) {
225: if (!(children[idx] instanceof PartPlaceholder)) {
226: viewList.add(children[idx]);
227: }
228: }
229:
230: return createDropTarget(viewList, targetItem);
231: }
232:
233: return null;
234: }
235:
236: /**
237: * Tests the view references associated with the stack and
238: * returns <code>true</code> if any view is a stand-alone view
239: *
240: * @return <code>true</code> is any view is stand-alone
241: */
242: private boolean isStandaloneStack() {
243: Perspective persp = wbw.getActiveWorkbenchPage()
244: .getActivePerspective();
245: List fvs = persp.getFastViewManager().getFastViews(id);
246: for (Iterator iterator = fvs.iterator(); iterator.hasNext();) {
247: IViewReference ref = (IViewReference) iterator.next();
248: if (persp.isStandaloneView(ref))
249: return true;
250: }
251:
252: return false;
253: }
254:
255: private IDropTarget createDropTarget(List viewList,
256: ToolItem targetItem) {
257: if (dropTarget == null) {
258: dropTarget = new ViewDropTarget(viewList, targetItem);
259: } else {
260: dropTarget.setTarget(viewList, targetItem);
261: }
262: return dropTarget;
263: }
264:
265: /**
266: * Returns the approximate location where the next fastview icon
267: * will be drawn (display coordinates)
268: */
269: public Rectangle getLocationOfNextIcon() {
270: ToolBar control = tbm.getControl();
271:
272: Rectangle result = control.getBounds();
273: Point size = control.computeSize(SWT.DEFAULT, SWT.DEFAULT,
274: false);
275: result.height = size.y;
276: result.width = size.x;
277:
278: boolean horizontal = (control.getStyle() & SWT.VERTICAL) == 0;
279: if (control.getItemCount() == 0) {
280: Geometry.setDimension(result, horizontal, 0);
281: }
282:
283: int hoverSide = horizontal ? SWT.RIGHT : SWT.BOTTOM;
284:
285: result = Geometry.getExtrudedEdge(result, -Geometry
286: .getDimension(result, !horizontal), hoverSide);
287:
288: return Geometry.toDisplay(control.getParent(), result);
289: }
290:
291: /**
292: * Returns the index of the ToolItem fronting the view ref
293: * @param toFind the view reference to find the index of
294: * @return the index or -1 if not found
295: */
296: private int getIndex(IViewReference toFind) {
297: ToolItem[] items = tbm.getControl().getItems();
298: for (int i = 0; i < items.length; i++) {
299: if (items[i].getData(ShowFastViewContribution.FAST_VIEW) == toFind) {
300: return i;
301: }
302: }
303:
304: return -1;
305: }
306:
307: /**
308: * Begins dragging a particular fast view
309: *
310: * @param ref
311: * @param position
312: */
313: protected void startDraggingFastView(IViewReference ref,
314: Point position, boolean usingKeyboard) {
315: int index = getIndex(ref);
316: if (index == -1)
317: return;
318:
319: ToolItem item = tbm.getControl().getItem(index);
320: Rectangle dragRect = Geometry.toDisplay(tbm.getControl(), item
321: .getBounds());
322: startDrag(((WorkbenchPartReference) ref).getPane(), dragRect,
323: position, usingKeyboard);
324: }
325:
326: private void startDrag(Object toDrag, Rectangle dragRect,
327: Point position, boolean usingKeyboard) {
328: WorkbenchPage page = wbw.getActiveWorkbenchPage();
329: Perspective persp = page.getActivePerspective();
330:
331: // Prevent dragging non-movable refs out of a minimized stack
332: if (toDrag instanceof ViewPane) {
333: ViewPane pane = (ViewPane) toDrag;
334: if (!persp.isMoveable(pane.getViewReference()))
335: return;
336: }
337:
338: IViewReference oldFastView = null;
339: if (persp != null) {
340: oldFastView = persp.getActiveFastView();
341:
342: if (page != null) {
343: page.hideFastView();
344: }
345: }
346:
347: if (page.isPageZoomed()) {
348: page.zoomOut();
349: }
350:
351: boolean success = DragUtil.performDrag(toDrag, dragRect,
352: position, !usingKeyboard);
353:
354: // If the drag was cancelled, reopen the old fast view
355: if (!success && oldFastView != null && page != null) {
356: page.toggleFastView(oldFastView);
357: }
358: }
359: }
|