/******************************************************************************* * Copyright (c) 2016 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.browsersim.widgets; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Widget; import org.hamcrest.Matcher; import org.jboss.tools.browsersim.browser.IBrowser; import org.jboss.tools.browsersim.matcher.AndMatcher; import org.jboss.tools.browsersim.matcher.ClassMatcher; import org.jboss.tools.browsersim.matcher.MatcherBuilder; import org.jboss.tools.browsersim.ui.BrowserSim; import org.jboss.tools.browsersim.ui.skin.DeviceComposite; import org.jboss.tools.browsersim.wait.ShellIsAvailable; import org.jboss.tools.browsersim.wait.TimePeriod; import org.jboss.tools.browsersim.wait.WaitUntil; import org.jboss.tools.browsersim.wait.WaitWhile; public class WidgetLookup { public static Shell getBrowsersimShell(){ Shell trShell = getTruncatedShell(); if(trShell != null){ new PushButton("Truncate (recommended)").click(); new WaitWhile(new ShellIsAvailable(trShell)); } return RDDisplay.syncExec(new ResultRunnable<Shell>() { @Override public Shell run() { Shell s = RDDisplay.getDisplay().getActiveShell(); if(s == null){ s = RDDisplay.getDisplay().getShells()[0]; } if(s != null && s.getText().equals("BrowserSim")){ s.setMinimized(false); s.forceActive(); s.setFocus(); return s; } throw new NullPointerException("Unable to retrieve browsersim shell"); } }); } public static Control getBrowsersimControl(final Shell browsersimShell){ return RDDisplay.syncExec(new ResultRunnable<Control>() { @Override public Control run() { Control c = getShellDeviceComposite(browsersimShell); if(c == null){ for(Shell s: browsersimShell.getShells()){ c = getShellDeviceComposite(s); if(c != null){ break; } } } if(c == null){ throw new NullPointerException("Unable to retrieve browsersim control"); } return c; } }); } private static Control getShellDeviceComposite(Shell parentShell){ for(Control c: parentShell.getChildren()){ if(c instanceof DeviceComposite){ c.setFocus(); return c; } } return null; } public static Shell getTruncatedShell(){ return RDDisplay.syncExec(new ResultRunnable<Shell>() { @Override public Shell run() { for(Shell s: RDDisplay.getDisplay().getShells()){ if(s.getText().equals("Device size will be truncated")){ return s; } } return null; } }); } public static IBrowser getBrowsersimBrowser(){ getBrowsersimShell(); return BrowserSim.getInstances().get(0).getBrowser(); } @SuppressWarnings({ "rawtypes", "unchecked" }) public static <T extends Widget> T activeWidget(Control refComposite, Matcher matcher, int index) { T widget = (T)findControl(refComposite, matcher, true, index); return widget; } private static <T extends Widget> T findControl(final Widget parentWidget, final Matcher<T> matcher, final boolean recursive, final int index) { T ret = RDDisplay.syncExec(new ResultRunnable<T>() { @Override public T run() { return findControlUI(parentWidget, matcher, recursive, new Index(index)); } }); return ret; } @SuppressWarnings("unchecked") private static <T extends Widget> T findControlUI(final Widget parentWidget, final Matcher<T> matcher, final boolean recursive, Index index) { if ((parentWidget == null) || parentWidget.isDisposed() || !visible(parentWidget)) { return null; } if (matcher.matches(parentWidget)) try { T control = (T) parentWidget; if(index.isFirst()) { return control; } else { index.passed(); } } catch (ClassCastException exception) { throw new IllegalArgumentException("The specified matcher should only match against is declared type.", exception); } if (recursive) { List<Widget> children = WidgetResolver.getInstance().getChildren(parentWidget); return findControlUI(children, matcher, recursive, index); } return null; } private static <T extends Widget> T findControlUI(final List<Widget> widgets, final Matcher<T> matcher, final boolean recursive, Index index) { for (Widget w : widgets) { T control = findControlUI(w, matcher, recursive, index); if(control != null) { return control; } } return null; } private static class Index { private int value; public Index(int index) { value = index; } public boolean isFirst() { return value <= 0; } public void passed() { value--; } } @SuppressWarnings("rawtypes") public static <T extends Widget> T activeWidget(Control refComposite, Class<T> clazz, int index, Matcher... matchers) { return activeWidget(refComposite, clazz, index, TimePeriod.SHORT , matchers); } @SuppressWarnings({ "rawtypes","unchecked" }) public static <T extends Widget> T activeWidget(Control refComposite, Class<T> clazz, int index, TimePeriod timePeriod, Matcher... matchers) { ClassMatcher cm = new ClassMatcher(clazz); if(matchers == null){ List<Matcher<?>> list= new ArrayList<Matcher<?>>(); matchers = list.toArray(new Matcher[list.size()]); } Matcher[] allMatchers = MatcherBuilder.getInstance().addMatcher(matchers, cm); AndMatcher am = new AndMatcher(allMatchers); Control parentControl = getParentControl(refComposite); WidgetIsFound found = new WidgetIsFound(parentControl, index, am.getMatchers()); new WaitUntil(found, timePeriod); return (T)found.getWidget(); } private static Control getParentControl(Control refComposite){ if (refComposite == null){ return findParent(); } return refComposite; } /** * Finds out whether widget is visible or not. * * @param w widget to resolve * @return true if widget is visible, false otherwise */ private static boolean visible(Widget w) { return !((w instanceof Control) && !((Control) w).getVisible()); } /** * Finds parent control of active widget . * * @return parent control of active widget or throws an exception if null */ public static Control findParent(){ Control parent = ShellLookup.getCurrentActiveShell(); if (parent == null){ throw new IllegalArgumentException("Unable to determine active parent"); } return parent; } }