| /******************************************************************************* |
| * Copyright (c) 2007 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| ******************************************************************************/ |
| |
| package org.eclipse.ui.internal; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.jface.action.ToolBarManager; |
| import org.eclipse.jface.util.Geometry; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.graphics.Cursor; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.ToolBar; |
| import org.eclipse.swt.widgets.ToolItem; |
| import org.eclipse.ui.IViewReference; |
| import org.eclipse.ui.internal.dnd.AbstractDropTarget; |
| import org.eclipse.ui.internal.dnd.DragUtil; |
| import org.eclipse.ui.internal.dnd.IDragOverListener; |
| import org.eclipse.ui.internal.dnd.IDropTarget; |
| import org.eclipse.ui.presentations.PresentationUtil; |
| |
| /** |
| * @since 3.3 |
| * |
| */ |
| public class FastViewDnDHandler implements IDragOverListener { |
| private String id; |
| private ToolBarManager tbm; |
| private WorkbenchWindow wbw; |
| private ViewDropTarget dropTarget = null; |
| |
| private Listener dragListener = new Listener() { |
| public void handleEvent(Event event) { |
| Point position = DragUtil.getEventLoc(event); |
| |
| ToolBar toolbar = tbm.getControl(); |
| Point local = toolbar.toControl(position); |
| ToolItem item = toolbar.getItem(local); |
| IViewReference ref = (IViewReference) item |
| .getData(ShowFastViewContribution.FAST_VIEW); |
| |
| if (ref != null) { |
| startDraggingFastView(ref, position, false); |
| } |
| } |
| }; |
| |
| class ViewDropTarget extends AbstractDropTarget { |
| List panes; |
| ToolItem curItem; |
| |
| /** |
| * @param panesToDrop the list of ViewPanes to drop at the given position |
| */ |
| public ViewDropTarget(List panesToDrop, ToolItem position) { |
| setTarget(panesToDrop, position); |
| } |
| |
| public void setTarget(List panesToDrop, ToolItem position) { |
| panes = panesToDrop; |
| this.curItem = position; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.dnd.IDropTarget#drop() |
| */ |
| public void drop() { |
| Perspective persp = wbw.getActiveWorkbenchPage().getActivePerspective(); |
| FastViewManager fvm = persp.getFastViewManager(); |
| |
| int insertIndex = tbm.getControl().indexOf(curItem); |
| Iterator iter = panes.iterator(); |
| while (iter.hasNext()) { |
| ViewPane pane = (ViewPane) iter.next(); |
| IViewReference ref = pane.getViewReference(); |
| adoptRef(ref); |
| fvm.addViewReference(id, insertIndex++, ref, !iter.hasNext()); |
| } |
| } |
| |
| private void adoptRef(IViewReference ref) { |
| Perspective persp = wbw.getActiveWorkbenchPage() |
| .getActivePerspective(); |
| PerspectiveHelper helper = persp.getPresentation(); |
| ContainerPlaceholder ourContainerPlaceholder = (ContainerPlaceholder) helper |
| .findPart(id, null); |
| LayoutPart refPart = helper.findPart(ref.getId(), ref |
| .getSecondaryId()); |
| ILayoutContainer refContainer = refPart.container; |
| if (refContainer != ourContainerPlaceholder) { |
| // remove the old part... if it's represented by a |
| // placeholder then just remove it... |
| if (refPart instanceof PartPlaceholder) { |
| if (refContainer instanceof ContainerPlaceholder) { |
| // just remove the placeholder |
| ViewStack realContainer = (ViewStack) ((ContainerPlaceholder) refContainer) |
| .getRealContainer(); |
| realContainer.remove(refPart); |
| } |
| else if (refContainer instanceof ViewStack) { |
| refContainer.remove(refPart); |
| } |
| } |
| else { |
| // If its a real view ref then defref it... |
| helper.derefPart(refPart); |
| } |
| PartPlaceholder newPlaceholder = new PartPlaceholder(ref |
| .getId()); |
| ourContainerPlaceholder.add(newPlaceholder); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.dnd.IDropTarget#getCursor() |
| */ |
| public Cursor getCursor() { |
| return DragCursors.getCursor(DragCursors.FASTVIEW); |
| } |
| |
| public Rectangle getSnapRectangle() { |
| if (curItem == null) { |
| // As long as the toolbar is not empty, highlight the place |
| // where this view will appear (we |
| // may have compressed it to save space when empty, so the actual |
| // icon location may not be over the toolbar when it is empty) |
| if (tbm.getControl().getItemCount() > 0) { |
| return getLocationOfNextIcon(); |
| } |
| // If the toolbar is empty, highlight the entire toolbar |
| return DragUtil.getDisplayBounds(tbm.getControl()); |
| } |
| |
| return Geometry.toDisplay(tbm.getControl(), curItem.getBounds()); |
| } |
| } |
| |
| /** |
| * |
| */ |
| public FastViewDnDHandler(String id, final ToolBarManager tbm, WorkbenchWindow wbw) { |
| this.id = id; |
| this.tbm = tbm; |
| this.wbw = wbw; |
| |
| // Hook the 'drop' listener to the control |
| DragUtil.addDragTarget(tbm.getControl(), this); |
| PresentationUtil.addDragListener(tbm.getControl(), dragListener); |
| |
| // Clean up on dispose |
| tbm.getControl().addDisposeListener(new DisposeListener() { |
| public void widgetDisposed(DisposeEvent e) { |
| DragUtil.removeDragTarget((Control)(e.widget), FastViewDnDHandler.this); |
| PresentationUtil.removeDragListener(tbm.getControl(), dragListener); |
| } |
| }); |
| } |
| |
| /** |
| * Returns the toolbar item at the given position, in display coordinates |
| * @param position |
| */ |
| private ToolItem getToolItem(Point position) { |
| ToolBar toolbar = tbm.getControl(); |
| Point local = toolbar.toControl(position); |
| return toolbar.getItem(local); |
| } |
| |
| /* (non-Javadoc) |
| * @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) |
| */ |
| public IDropTarget drag(Control currentControl, Object draggedObject, |
| Point position, Rectangle dragRectangle) { |
| // If we're trying to drop onto a 'standalone' stack, don't... |
| if (isStandaloneStack()) |
| return null; |
| |
| ToolItem targetItem = getToolItem(position); |
| if (draggedObject instanceof ViewPane) { |
| ViewPane pane = (ViewPane) draggedObject; |
| |
| // Can't drag views between windows |
| if (pane.getWorkbenchWindow() != wbw) { |
| return null; |
| } |
| |
| List newList = new ArrayList(1); |
| newList.add(draggedObject); |
| |
| return createDropTarget(newList, targetItem); |
| } |
| if (draggedObject instanceof ViewStack) { |
| ViewStack folder = (ViewStack) draggedObject; |
| |
| if (folder.getWorkbenchWindow() != wbw) { |
| return null; |
| } |
| |
| List viewList = new ArrayList(folder.getItemCount()); |
| LayoutPart[] children = folder.getChildren(); |
| |
| for (int idx = 0; idx < children.length; idx++) { |
| if (!(children[idx] instanceof PartPlaceholder)) { |
| viewList.add(children[idx]); |
| } |
| } |
| |
| return createDropTarget(viewList, targetItem); |
| } |
| |
| return null; |
| } |
| /** |
| * Tests the view references associated with the stack and |
| * returns <code>true</code> if any view is a stand-alone view |
| * |
| * @return <code>true</code> is any view is stand-alone |
| */ |
| private boolean isStandaloneStack() { |
| Perspective persp = wbw.getActiveWorkbenchPage().getActivePerspective(); |
| List fvs = persp.getFastViewManager().getFastViews(id); |
| for (Iterator iterator = fvs.iterator(); iterator.hasNext();) { |
| IViewReference ref = (IViewReference) iterator.next(); |
| if (persp.isStandaloneView(ref)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| private IDropTarget createDropTarget(List viewList, ToolItem targetItem) { |
| if (dropTarget == null) { |
| dropTarget = new ViewDropTarget(viewList, targetItem); |
| } else { |
| dropTarget.setTarget(viewList, targetItem); |
| } |
| return dropTarget; |
| } |
| |
| /** |
| * Returns the approximate location where the next fastview icon |
| * will be drawn (display coordinates) |
| */ |
| public Rectangle getLocationOfNextIcon() { |
| ToolBar control = tbm.getControl(); |
| |
| Rectangle result = control.getBounds(); |
| Point size = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, false); |
| result.height = size.y; |
| result.width = size.x; |
| |
| boolean horizontal = (control.getStyle() & SWT.VERTICAL) == 0; |
| if (control.getItemCount() == 0) { |
| Geometry.setDimension(result, horizontal, 0); |
| } |
| |
| int hoverSide = horizontal ? SWT.RIGHT : SWT.BOTTOM; |
| |
| result = Geometry.getExtrudedEdge(result, -Geometry.getDimension( |
| result, !horizontal), hoverSide); |
| |
| return Geometry.toDisplay(control.getParent(), result); |
| } |
| |
| /** |
| * Returns the index of the ToolItem fronting the view ref |
| * @param toFind the view reference to find the index of |
| * @return the index or -1 if not found |
| */ |
| private int getIndex(IViewReference toFind) { |
| ToolItem[] items = tbm.getControl().getItems(); |
| for (int i = 0; i < items.length; i++) { |
| if (items[i].getData(ShowFastViewContribution.FAST_VIEW) == toFind) { |
| return i; |
| } |
| } |
| |
| return -1; |
| } |
| |
| /** |
| * Begins dragging a particular fast view |
| * |
| * @param ref |
| * @param position |
| */ |
| protected void startDraggingFastView(IViewReference ref, Point position, |
| boolean usingKeyboard) { |
| int index = getIndex(ref); |
| if (index == -1) |
| return; |
| |
| ToolItem item = tbm.getControl().getItem(index); |
| Rectangle dragRect = Geometry.toDisplay(tbm.getControl(), item.getBounds()); |
| startDrag(((WorkbenchPartReference) ref).getPane(), dragRect, position, |
| usingKeyboard); |
| } |
| |
| private void startDrag(Object toDrag, Rectangle dragRect, Point position, |
| boolean usingKeyboard) { |
| WorkbenchPage page = wbw.getActiveWorkbenchPage(); |
| Perspective persp = page.getActivePerspective(); |
| |
| // Prevent dragging non-movable refs out of a minimized stack |
| if (toDrag instanceof ViewPane) { |
| ViewPane pane = (ViewPane) toDrag; |
| if (!persp.isMoveable(pane.getViewReference())) |
| return; |
| } |
| |
| IViewReference oldFastView = null; |
| if (persp != null) { |
| oldFastView = persp.getActiveFastView(); |
| |
| if (page != null) { |
| page.hideFastView(); |
| } |
| } |
| |
| if (page.isPageZoomed()) { |
| page.zoomOut(); |
| } |
| |
| boolean success = DragUtil.performDrag(toDrag, dragRect, position, |
| !usingKeyboard); |
| |
| // If the drag was cancelled, reopen the old fast view |
| if (!success && oldFastView != null && page != null) { |
| page.toggleFastView(oldFastView); |
| } |
| } |
| } |