/******************************************************************************* * Copyright (c) 2012 Google, Inc. * 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: * Google, Inc. - initial API and implementation *******************************************************************************/ package com.windowtester.runtime.swt.internal.operation; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Widget; import com.windowtester.internal.runtime.provisional.WTInternal; /** * A global screen location described in terms of widgets and/or x/y coordinates. If no * widgets are specified, then the x/y coordinates are considered to be global screen * coordinates. If one widget is specified, then the x/y coordinates are considered to be * relative to that widget. Multiple widgets need only be specified if SWT returns bounds * for a widget in terms if its parent rather than in terms of global screen coordinates. */ public abstract class SWTLocation { private static final Point ZERO_ZERO = new Point(0, 0); protected final int relative; private Point offset = ZERO_ZERO; /** * Construct a new instance representing a location relative to a widget * {@link SWTTreeItemLocation} or to the display itself {@link SWTDisplayLocation} * * @param relative how the the location is relative to the widget's or display's * bounding box ( {@link WTInternal#TOPLEFT}, {@link WTInternal#RIGHT}, * ...) */ protected SWTLocation(int relative) { this.relative = relative; } /** * Set the location x/y coordinates. If a widget is specified via * {@link #on(Widget, int)}, then the x, y coordinates specified here are treated as * offsets from the specified widget location. If no widget is specified via * {@link #on(Widget, int)}, then the x, y coordinates specified here are treated as * global coordinates. * * @param x the location's x-coordinate * @param y the location's y-coordinate * @return this object so that calls can be cascaded on a single line such as * <code>new SWTLocation().on(widget, WTInternal.RIGHT).at(-8, 0).location();</code> */ public SWTLocation offset(int x, int y) { return offset(new Point(x, y)); } /** * Set the location x/y coordinates. If a widget is specified via * {@link #on(Widget, int)}, then the x, y coordinates specified here are treated as * offsets from the specified widget location. If no widget is specified via * {@link #on(Widget, int)}, then the x, y coordinates specified here are treated as * global coordinates. * * @param pt the coordinates or <code>null</code> * @return this object so that calls can be cascaded on a single line such as * <code>new SWTLocation().on(widget, WTInternal.RIGHT).at(-8, 0).location();</code> */ public SWTLocation offset(Point pt) { offset = pt; return this; } /** * Answer the global point for the specified widget(s) and offset. This method is * designed to be called from the UI thread and may throw an exception if called from * a non-UI thread. */ public Point location() { Rectangle bounds = getDisplayBounds(); int x; if ((relative & WTInternal.LEFT) == WTInternal.LEFT) x = bounds.x; else if ((relative & WTInternal.RIGHT) == WTInternal.RIGHT) x = bounds.x + bounds.width; else x = bounds.x + (bounds.width / 2); int y; if ((relative & WTInternal.TOP) == WTInternal.TOP) y = bounds.y; else if ((relative & WTInternal.BOTTOM) == WTInternal.BOTTOM) y = bounds.y + bounds.height; else y = bounds.y + (bounds.height / 2); if (offset != null) { x += offset.x; y += offset.y; } return new Point(x, y); } //======================================================================= // Internal /** * Calculate the client area of the widget and convert that from local coordinates to * global coordinates (also known as display coordinates). This method is * designed to be called from the UI thread and may throw an exception if called from * a non-UI thread. * * @return the client area of the widget in display coordinates */ protected abstract Rectangle getDisplayBounds(); }