package abbot.tester.swt; import org.eclipse.swt.SWTException; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.CoolItem; import org.eclipse.swt.widgets.Decorations; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swt.widgets.Widget; import abbot.Platform; import com.windowtester.runtime.swt.internal.abbot.SWTWorkarounds; /** * Provides a means to find the coordinates of an SWT Widget in display-space, * given an SWT Display object. * * @author Kevin T Dale * @version $Id: WidgetLocator.java,v 1.6 2008-01-15 18:01:53 pq Exp $ */ public class WidgetLocator{ public static final String copyright = "Licensed Materials -- Property of IBM\n"+ "(c) Copyright International Business Machines Corporation, 2003\nUS Government "+ "Users Restricted Rights - Use, duplication or disclosure restricted by GSA "+ "ADP Schedule Contract with IBM Corp."; /** * Returns the location of the top left-hand corner of a the client area * of a given Widget in display space. * * @param w the Widget to be found * @return the location of Widget w */ public static Point getLocation(Widget w){ return getLocation(w,true); } /** * Returns the location of the top left-hand corner of a given Widget in display * space, optionally ignoring the Widget's trimmings. For example, to obtain * the location of the area of the Widget that can receive mouse actions, use * <code>ignoreBorder==true</code>. * * @param w the Widget to be found * @param ignoreBorder should the border be considered? * @return the location of Widget w */ public static Point getLocation(Widget w, boolean ignoreBorder){ if (w == null || w.isDisposed()) return null; Rectangle bounds; try { bounds = getBounds(w,ignoreBorder); } catch(NullPointerException npe){ return null; } catch (SWTException e) { return null; } if (bounds == null) return null; return new Point(bounds.x,bounds.y); } /** * Finds the display-space rectangle that bounds the given Widget's client area. * * @param w the Widget to be found * @return the bounds of the widget's client area */ public static Rectangle getBounds(Widget w){ return getBounds(w,true); } /** * Finds the display space rectangle that bounds the given Widget, optionally * ignoring the Widget's trimmings. * * @param w the Widget to be found * @param ignoreBorder should the border be considered? * @return the bounding rectangle */ public static Rectangle getBounds(Widget w, boolean ignoreBorder){ if(w instanceof Control){ if(ignoreBorder && w instanceof Decorations){ Rectangle bounds = ((Decorations)w).getBounds(); Rectangle clientArea = ((Decorations)w).getClientArea(); Rectangle calced = ((Decorations)w).computeTrim(bounds.x,bounds.y, clientArea.width,clientArea.height); Rectangle correct = new Rectangle(2*bounds.x-calced.x, 2*bounds.y-calced.y, clientArea.width-1, //bug workaround clientArea.height-1); return toDisplay(correct,((Decorations)w)); } if(ignoreBorder && w instanceof Button){ Rectangle bounds = ((Button)w).getBounds(); bounds.width-=1; bounds.height-=1; return toDisplay(bounds,(Control)w); } else if (ignoreBorder && w instanceof Text) { //!!pq: Text t = (Text)w; Rectangle bounds = ((Control)t).getBounds(); // Composite parent = t.getParent(); // Layout layout = parent.getLayout(); // layout. // if (bounds.height == 0 || bounds.width == 0) { // Object layoutData = t.getLayoutData(); // if (layoutData != null && layoutData instanceof Layout) // bounds = SWTWorkarounds.getBounds(t, (Layout)layoutData); // } //TODO: this is not working: ow to get the bounds of Text object? return toDisplay(bounds,(Control)w); } else if (w instanceof List && Platform.isOSX()) { Control c = (Control) w; Rectangle r = c.getDisplay().map(c, null, c.getBounds()); return r; } else{ return toDisplay(((Control)w).getBounds(),((Control)w)); } } // The following block exists to workaround problems with Widget.getBounds() if(w instanceof CTabItem){ return SWTWorkarounds.getBounds((CTabItem)w); } if(w instanceof MenuItem){ // MenuItem item = (MenuItem)w; // Rectangle bounds = SWTWorkarounds.getBounds(item); // Point p = item.getParent().getParent().toDisplay(bounds.x,bounds.y); // return new Rectangle(p.x,p.y,bounds.width,bounds.height); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=38436#c113 // thanks Veronika Irvine return SWTWorkarounds.getBounds((MenuItem)w); } if(w instanceof TabItem){ // moved to SWTWorkarounds.getBounds(TabItem) // TabItem item = (TabItem)w; // Rectangle bounds = SWTWorkarounds.getBounds(item); // Point p = item.getParent().toDisplay(bounds.x,bounds.y); // return new Rectangle(p.x,p.y,bounds.width,bounds.height); return SWTWorkarounds.getBounds((TabItem)w); } if(w instanceof TableColumn){ // moved to SWTWorkarounds.getBounds(TableColumn) // TableColumn col = (TableColumn)w; // Rectangle bounds = SWTWorkarounds.getBounds(col); // Point p = col.getParent().toDisplay(bounds.x,bounds.y); // return new Rectangle(p.x,p.y,bounds.width,bounds.height); return SWTWorkarounds.getBounds((TableColumn)w); } // if(w instanceof ScrollBar){ // ScrollBar bar = (ScrollBar)w; // Rectangle bounds = bar.getBounds(); // Point p = bar.getParent().toDisplay(bounds.x,bounds.y); // return new Rectangle(p.x,p.y,bounds.width,bounds.height); // } if(w instanceof ToolItem){ // moved to SWTWorkarounds.getBounds(ToolItem) // ToolItem item = (ToolItem)w; // Rectangle bounds = item.getBounds(); // Point p = item.getParent().toDisplay(bounds.x,bounds.y); // return new Rectangle(p.x,p.y,bounds.width,bounds.height); return SWTWorkarounds.getBounds((ToolItem)w); } if(w instanceof CoolItem){ // moved to SWTWorkarounds.getBounds(CoolItem) // CoolItem item = (CoolItem)w; // Rectangle bounds = item.getBounds(); // Point p = item.getParent().toDisplay(bounds.x,bounds.y); // return new Rectangle(p.x,p.y,bounds.width,bounds.height); return SWTWorkarounds.getBounds((CoolItem)w); } if(w instanceof TreeItem){ // moved to SWTWorkarounds.getBounds(TreeItem) // TreeItem item = (TreeItem)w; // Rectangle bounds = item.getBounds(); // Point p = item.getParent().toDisplay(bounds.x,bounds.y); // return new Rectangle(p.x,p.y,bounds.width,bounds.height); return SWTWorkarounds.getBounds((TreeItem)w); } // Tao Weng 04/25/2005 10:39:05 AM: thanks! if(w instanceof TableItem){ // moved to SWTWorkarounds.getBounds(TreeItem) // TableItem item = (TableItem)w; // Rectangle bounds = SWTWorkarounds.getBounds(item); // Point p = item.getParent().toDisplay(bounds.x,bounds.y); // return new Rectangle(p.x,p.y,bounds.width,bounds.height); return SWTWorkarounds.getBounds((TableItem)w); } //TODO: look for ALL items that have a getBounds() method in 3.0: //TODO: (cont'd) ToolItem, CoolItem, TableItem, TreeItem, etc // System.err.println( // "Unable to find coordinates of \""+w.getClass()+"\"; returning NULL"); return null; } // private static Rectangle getBounds(Widget w, Layout layout) { // //return SWTWorkarounds.getBounds(w, layout); // } /** * Helper method to convert a Rectangle, given in the coordinate system of * the given Control's parent, to display-cordinates. */ public static Rectangle toDisplay(Rectangle r, Control c){ Point topLeft = new Point(r.x,r.y); Point bottomRight = new Point(r.x+r.width,r.y+r.height); if(c.getParent()!=null){// if not a top-level shell topLeft = c.getParent().toDisplay(topLeft.x,topLeft.y); bottomRight = c.getParent().toDisplay(bottomRight.x,bottomRight.y); } return new Rectangle(topLeft.x,topLeft.y,bottomRight.x-topLeft.x,bottomRight.y-topLeft.y); } }