/*******************************************************************************
* Copyright (c) 2010, 2014 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.e4.ui.workbench.addons.dndaddon;
import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.DragDetectEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
class DnDInfo {
Point cursorPos;
Control curCtrl;
Item curItem;
MUIElement curElement;
MUIElement itemElement;
int itemIndex;
Rectangle itemRect;
Shell dragHost = null;
int offsetX = 0;
int offsetY = 0;
Rectangle dragHostBounds = null;
Point initialHostSize;
MWindow topLevelWindow;
Display display;
EModelService modelService;
public DnDInfo(MWindow topWin) {
topLevelWindow = topWin;
display = ((Control) (topWin.getWidget())).getDisplay();
modelService = topWin.getContext().get(EModelService.class);
update();
}
public void setDragHost(Shell hostingShell, int xOffset, int yOffset) {
dragHost = hostingShell;
offsetX = xOffset;
offsetY = yOffset;
dragHostBounds = null;
if (dragHost == null) {
return;
}
// Punch a 'hole' where the cursor is using a region
Region rgn = dragHost.getRegion();
// if (rgn != null && !rgn.isDisposed())
// rgn.dispose();
// rgn = new Region(display);
Rectangle bounds = dragHost.getBounds();
rgn.add(0, 0, bounds.width, bounds.height);
rgn.subtract(offsetX, offsetY, 1, 1);
dragHost.setRegion(rgn);
initialHostSize = dragHost.getSize();
// Do an initial 'track'
Point curLoc = dragHost.getDisplay().getCursorLocation();
dragHost.setLocation(curLoc.x - offsetX, curLoc.y - offsetY);
dragHost.layout(true);
}
public void setDragHostBounds(Rectangle displayRect) {
if (dragHost == null) {
return;
}
dragHostBounds = displayRect;
// Re-attach the drag host to the cursor
if (dragHostBounds == null) {
dragHost.setSize(initialHostSize);
setDragHost(dragHost, offsetX, offsetY);
return;
}
// dragHost.setVisible(false);
dragHost.setAlpha(200);
dragHost.setBounds(dragHostBounds);
// punch a 'hole' where the cursor *is*
Point cursorLoc = display.getCursorLocation();
cursorLoc = display.map(null, dragHost, cursorLoc);
Region rgn = dragHost.getRegion();
Rectangle bounds = dragHost.getBounds();
rgn.add(0, 0, bounds.width, bounds.height);
rgn.subtract(cursorLoc.x, cursorLoc.y, 1, 1);
display.update();
}
private void reset() {
cursorPos = null;
curCtrl = null;
curItem = null;
curElement = null;
itemElement = null;
itemIndex = -1;
itemRect = null;
}
private void setItemInfo() {
if (curElement == null) {
return;
}
Control ctrl = (Control) curElement.getWidget();
// KLUDGE!! Should delegate to curElement's renderer
if (ctrl instanceof CTabFolder) {
CTabFolder ctf = (CTabFolder) ctrl;
Point localPos = display.map(null, ctf, cursorPos);
curItem = ctf.getItem(localPos);
if (curItem != null) {
itemElement = (MUIElement) curItem.getData(AbstractPartRenderer.OWNING_ME);
if (itemElement != null) {
itemIndex = ctf.indexOf((CTabItem) curItem);
itemRect = display.map(ctf, ctf.getShell(), ((CTabItem) curItem).getBounds());
}
}
} else if (ctrl instanceof ToolBar) {
ToolBar tb = (ToolBar) ctrl;
Point localPos = display.map(null, tb, cursorPos);
ToolItem curItem = tb.getItem(localPos);
if (curItem != null) {
itemElement = (MUIElement) curItem.getData(AbstractPartRenderer.OWNING_ME);
if (itemElement != null) {
itemIndex = tb.indexOf(curItem);
itemRect = display.map(tb, tb.getShell(), curItem.getBounds());
}
}
}
}
private MUIElement getModelElement(Control ctrl) {
if (ctrl == null) {
return null;
}
MUIElement element = (MUIElement) ctrl.getData(AbstractPartRenderer.OWNING_ME);
if (element != null) {
return element;
}
return getModelElement(ctrl.getParent());
}
public void update() {
final Display display = Display.getCurrent();
if (display == null) {
return;
}
// If we're in the same location presume the info is OK
Point cPoint = display.getCursorLocation();
if (cPoint != null && cursorPos != null && cPoint.x == cursorPos.x
&& cPoint.y == cursorPos.y) {
return;
}
reset();
cursorPos = display.getCursorLocation();
if (dragHost != null && !dragHost.isDisposed() && dragHost.getVisible()) {
if (dragHostBounds == null) {
// First move the dragHost so that its 'hole' is where the mouse is
dragHost.setLocation(cursorPos.x - offsetX, cursorPos.y - offsetY);
} else {
// Move the 'hole' to where the cursor is
Point cursorLoc = display.getCursorLocation();
cursorLoc = display.map(null, dragHost, cursorLoc);
Region rgn = dragHost.getRegion();
Rectangle bounds = dragHost.getBounds();
rgn.add(0, 0, bounds.width, bounds.height);
rgn.subtract(cursorLoc.x, cursorLoc.y, 1, 1);
}
}
curCtrl = DragAndDropUtil.findControl(display, display.getCursorLocation());
if (curCtrl == null) {
return;
}
curElement = getModelElement(curCtrl);
setItemInfo();
}
public void update(DragDetectEvent e) {
reset();
if (!(e.widget instanceof Control)) {
return;
}
curCtrl = (Control) e.widget;
cursorPos = new Point(e.x, e.y);
cursorPos = curCtrl.getDisplay().map(curCtrl, null, cursorPos);
curElement = getModelElement(curCtrl);
setItemInfo();
}
}