/******************************************************************************* * 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.locator; import java.awt.Point; import java.io.Serializable; import java.lang.reflect.Field; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.graphics.Rectangle; import abbot.Platform; import com.windowtester.runtime.ClickDescription; import com.windowtester.runtime.IClickDescription; import com.windowtester.runtime.IUIContext; import com.windowtester.runtime.WT; import com.windowtester.runtime.WidgetSearchException; import com.windowtester.runtime.condition.IConditionHandler; import com.windowtester.runtime.internal.concurrent.VoidCallable; import com.windowtester.runtime.locator.IWidgetReference; import com.windowtester.runtime.swt.internal.condition.LocatorClosingHandler; import com.windowtester.runtime.swt.internal.locator.ICloseableLocator; import com.windowtester.runtime.swt.internal.operation.BasicSWTWidgetClickOperation; import com.windowtester.runtime.swt.internal.selector.UIDriver; import com.windowtester.runtime.swt.internal.state.MouseConfig; import com.windowtester.runtime.swt.internal.widgets.CTabFolderReference; import com.windowtester.runtime.swt.internal.widgets.DisplayReference; import com.windowtester.runtime.util.StringComparator; /** * Locates {@link CTabItem} widgets. */ public class CTabItemLocator extends SWTWidgetLocator { private static final long serialVersionUID = 2464452061853145190L; private static class Closer implements ICloseableLocator, Serializable { private static final long serialVersionUID = 5713321416399466153L; private static final int BETWEEN_CLICKS_DELAY = 700; private final transient CTabItemLocator tabItemLocator; public Closer(CTabItemLocator tabItemLocator) { this.tabItemLocator = tabItemLocator; } /* (non-Javadoc) * @see com.windowtester.runtime.swt.internal.locator.ICloseableLocator#doClose(com.windowtester.runtime.IUIContext) */ public void doClose(IUIContext ui) throws WidgetSearchException { //conditions handled in find IWidgetReference widget = (IWidgetReference) ui.find(tabItemLocator); IClickDescription click = ClickDescription.create(1, tabItemLocator, MouseConfig.BUTTONS_REMAPPED ? WT.BUTTON3 : WT.BUTTON1); doClose(ui, widget, click); } public void doClose(IUIContext ui, IWidgetReference widget, IClickDescription click) throws WidgetSearchException { selectTabItem(ui, widget, click); closeTabItem(widget, click); } private void closeTabItem(IWidgetReference widget, IClickDescription click) throws WidgetSearchException { final CTabItem item = (CTabItem) widget.getWidget(); final CTabFolder folder[] = new CTabFolder[1]; final Rectangle rect[] = new Rectangle[1]; final Exception exception[] = new Exception[1]; DisplayReference.getDefault().execute(new VoidCallable() { public void call() { folder[0] = item.getParent(); try { Field closeRect = CTabItem.class.getDeclaredField("closeRect"); closeRect.setAccessible(true); rect[0] = (Rectangle) closeRect.get(item); } catch (Exception e) { exception[0] = e; } } }); if (exception[0] != null) throw new WidgetSearchException(exception[0].getMessage()); // tabItemLocator.doClick(1, folder[0], new Point(rect[0].x + rect[0].width/2, rect[0].y + rect[0].height/2), click.modifierMask()); CTabFolderReference folderReference = new CTabFolderReference(folder[0]); new BasicSWTWidgetClickOperation<CTabFolderReference>(folderReference).atOffset(rect[0].x + rect[0].width/2, rect[0].y + rect[0].height/2).withModifiers(click.modifierMask()).execute(); } private void selectTabItem(IUIContext ui, IWidgetReference widget, IClickDescription click) throws WidgetSearchException { //click first to ensure the X is visible.. tabItemLocator.click(ui, widget, click); UIDriver.pause(BETWEEN_CLICKS_DELAY); //to ensure a double click is not registered } } /** * Create a locator instance for the common case where no information is needed * to disambiguate the parent control. * <p> * This convenience constructor is equivalent to the following: * <pre> * new CTabItemLocator(itemText, new SWTWidgetLocator(CTabFolder.class)); * </pre> * * @param text the text of the CTab to select (can be a regular expression as described in the {@link StringComparator} utility) */ public CTabItemLocator(String itemText) { super(CTabItem.class, itemText); } //child /** * Create a locator instance. * @param text the text of the CTab to select (can be a regular expression as described in the {@link StringComparator} utility) * @param parent the parent locator */ public CTabItemLocator(String text, SWTWidgetLocator parent) { super(CTabItem.class, text, parent); } //indexed child /** * Create a locator instance. * @param text the text of the CTab to select (can be a regular expression as described in the {@link StringComparator} utility) * @param index this locators index with respect to its parent * @param parent the parent locator */ public CTabItemLocator(String text, int index, SWTWidgetLocator parent) { super(CTabItem.class, text, index, parent); } /* (non-Javadoc) * @see com.windowtester.runtime.WidgetLocator#getAdapter(java.lang.Class) */ @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) { if (adapter == ICloseableLocator.class) return new Closer(this); return super.getAdapter(adapter); } protected Point getUnspecifiedXYOffset(Rectangle rect) { // account for the closing X on the right in Linux if (Platform.isLinux()) return new Point((rect.width - 20)/2, rect.height/2); return super.getUnspecifiedXYOffset(rect); } /** * Create a condition handler that ensures that this {@link CTabItem} is closed. * * @since 5.0.0 */ public IConditionHandler isClosed() { return new LocatorClosingHandler(this); } }