blob: 6ec9f7dd94f246ef47da1fd3a24978422429a5a8 [file] [log] [blame]
/*******************************************************************************
* 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);
}
}
}