blob: aca9126579fb3b89d809f5bc8fed184182363733 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2006 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.dnd;
import org.eclipse.core.runtime.Assert;
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.Monitor;
import org.eclipse.swt.widgets.Shell;
/**
* Contains static methods for manipulating SWT controls
*
* @since 3.0
*/
public class SwtUtil {
private SwtUtil() {
}
/**
* Returns true if the given control is null or has been disposed
*
* @param toTest the control to test
* @return false if it is safe to invoke methods on the given control
*/
public static boolean isDisposed(Control toTest) {
return toTest == null || toTest.isDisposed();
}
/**
* Returns the control that is covering the given control, or null if none.
*
* @param toTest control to test
* @return a control that obscures the test control or null if none
*/
public static Control controlThatCovers(Control toTest) {
return controlThatCovers(toTest, DragUtil.getDisplayBounds(toTest));
}
private static Control controlThatCovers(Control toTest, Rectangle testRegion) {
Composite parent = toTest.getParent();
if (parent == null || toTest instanceof Shell) {
return null;
}
Control[] children = parent.getChildren();
for (int i = 0; i < children.length; i++) {
Control control = children[i];
if (control == toTest) {
break;
}
if (!control.isVisible()) {
continue;
}
Rectangle nextBounds = DragUtil.getDisplayBounds(control);
if (nextBounds.intersects(testRegion)) {
return control;
}
}
return controlThatCovers(parent, testRegion);
}
/**
* Determines if one control is a child of another. Returns true iff the second
* argument is a child of the first (or the same object).
*
* @param potentialParent
* @param childToTest
* @return
*/
public static boolean isChild(Control potentialParent, Control childToTest) {
if (childToTest == null) {
return false;
}
if (childToTest == potentialParent) {
return true;
}
return isChild(potentialParent, childToTest.getParent());
}
public static boolean isFocusAncestor(Control potentialParent) {
Assert.isNotNull(potentialParent);
Control focusControl = Display.getCurrent().getFocusControl();
if (focusControl == null) {
return false;
}
return isChild(potentialParent, focusControl);
}
/**
* Finds and returns the most specific SWT control at the given location.
* (Note: this does a DFS on the SWT widget hierarchy, which is slow).
*
* @param displayToSearch
* @param locationToFind
* @return
*/
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.
*
* @param toSearch an array of composites
* @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.isDisposed() && next.isVisible()) {
Rectangle bounds = DragUtil.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;
}
public static Control[] getAncestors(Control theControl) {
return getAncestors(theControl, 1);
}
private static Control[] getAncestors(Control theControl, int children) {
Control[] result;
if (theControl.getParent() == null) {
result = new Control[children];
} else {
result = getAncestors(theControl.getParent(), children + 1);
}
result[result.length - children] = theControl;
return result;
}
public static Control findCommonAncestor(Control control1, Control control2) {
Control[] control1Ancestors = getAncestors(control1);
Control[] control2Ancestors = getAncestors(control2);
Control mostSpecific = null;
for (int idx = 0; idx < Math.min(control1Ancestors.length, control2Ancestors.length); idx++) {
Control control1Ancestor = control1Ancestors[idx];
if (control1Ancestor == control2Ancestors[idx]) {
mostSpecific = control1Ancestor;
} else {
break;
}
}
return mostSpecific;
}
/**
* Finds the control in the given location
*
* @param toSearch
* @param locationToFind location (in display coordinates)
* @return
*/
public static Control findControl(Composite toSearch, Point locationToFind) {
Control[] children = toSearch.getChildren();
return findControl(children, locationToFind);
}
/**
*
* Returns true iff the given rectangle is located in the client area of any
* monitor.
*
* @param someRectangle a rectangle in display coordinates (not null)
* @return true iff the given point can be seen on any monitor
*/
public static boolean intersectsAnyMonitor(Display display,
Rectangle someRectangle) {
Monitor[] monitors = display.getMonitors();
for (int idx = 0; idx < monitors.length; idx++) {
Monitor mon = monitors[idx];
if (mon.getClientArea().intersects(someRectangle)) {
return true;
}
}
return false;
}
}