blob: 18f534d3179bf43bb464cafae3d4ad7e3d2e2afe [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 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.jface.util.Geometry;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
class DragAndDropUtil {
public static final String IGNORE_AS_DROP_TARGET = "ignore_as_drop_target"; //$NON-NLS-1$
/**
* Shorthand method. Returns the bounding rectangle for the given control,
* in display coordinates.
*
* @param boundsControl
* the control whose bounds are to be computed
* @return the bounds of the given control in display coordinates
*/
public static Rectangle getDisplayBounds(Control boundsControl) {
Control parent = boundsControl.getParent();
if (parent == null || boundsControl instanceof Shell) {
return boundsControl.getBounds();
}
return Geometry.toDisplay(parent, boundsControl.getBounds());
}
/**
* Finds and returns the most specific SWT control at the given location.
* (Note: this does a DFS on the SWT widget hierarchy, which can be slow).
* Any invisible control or control tagged with IGNORE_AS_DROP_TARGET will
* be ignored by this method.
*
* @param displayToSearch
* the display to search for potential controls
* @param locationToFind
* the position, in display coordinates, to be located
* @return the most specific SWT control at the given location
*/
public static Control findControl(Display displayToSearch, Point locationToFind) {
Shell[] shells = displayToSearch.getShells();
return findControl(shells, locationToFind);
}
/**
* Searches the given list of controls for a control containing the given
* point. If the array contains any composites, those composites will be
* recursively searched to find the most specific child that contains the
* point. Any invisible control or control tagged with IGNORE_AS_DROP_TARGET
* will be ignored by this method.
*
* @param toSearch
* an array of controls to be searched for potential matches
* @param locationToFind
* a point (in display coordinates)
* @return the most specific Control that overlaps the given point, or null
* if none
*/
public static Control findControl(Control[] toSearch, Point locationToFind) {
for (int idx = toSearch.length - 1; idx >= 0; idx--) {
Control next = toSearch[idx];
if (next.getData(IGNORE_AS_DROP_TARGET) != null) {
continue;
}
if (!next.isDisposed() && next.isVisible()) {
Rectangle bounds = getDisplayBounds(next);
if (bounds.contains(locationToFind)) {
if (next instanceof Composite) {
Control result = findControl((Composite) next, locationToFind);
if (result != null) {
return result;
}
}
return next;
}
}
}
return null;
}
/**
* Finds the control at the given location. Any invisible control or control
* tagged with IGNORE_AS_DROP_TARGET will be ignored by this method.
*
* @param toSearch
* the composite to be searched for potential matches.
* @param locationToFind
* location (in display coordinates)
* @return the control at the given location
*/
public static Control findControl(Composite toSearch, Point locationToFind) {
Control[] children = toSearch.getChildren();
return findControl(children, locationToFind);
}
}