changeset 5:898c9e02c8c9

7902099: Add JemmySWT to jemmy/v3
author shurailine
date Mon, 29 Jan 2018 10:53:15 -0800
parents 1d98600736c5
children 7cde94b782c9
files SWT/JemmySWT/build.xml SWT/JemmySWT/src/org/jemmy/input/KeyboardSelectable.java SWT/JemmySWT/src/org/jemmy/input/KeyboardSelector.java SWT/JemmySWT/src/org/jemmy/swt/Browser.java SWT/JemmySWT/src/org/jemmy/swt/CComboWrap.java SWT/JemmySWT/src/org/jemmy/swt/CTabFolderWrap.java SWT/JemmySWT/src/org/jemmy/swt/ComboWrap.java SWT/JemmySWT/src/org/jemmy/swt/CompositeWrap.java SWT/JemmySWT/src/org/jemmy/swt/ControlWrap.java SWT/JemmySWT/src/org/jemmy/swt/IndexItemSelector.java SWT/JemmySWT/src/org/jemmy/swt/ItemParent.java SWT/JemmySWT/src/org/jemmy/swt/ItemWrap.java SWT/JemmySWT/src/org/jemmy/swt/ListWrap.java SWT/JemmySWT/src/org/jemmy/swt/MenuItemParent.java SWT/JemmySWT/src/org/jemmy/swt/SWTExecutor.java SWT/JemmySWT/src/org/jemmy/swt/SWTMenu.java SWT/JemmySWT/src/org/jemmy/swt/SWTMenuOwner.java SWT/JemmySWT/src/org/jemmy/swt/SWTPopupOwner.java SWT/JemmySWT/src/org/jemmy/swt/SWTTree.java SWT/JemmySWT/src/org/jemmy/swt/ScrollableWrap.java SWT/JemmySWT/src/org/jemmy/swt/ShellWrap.java SWT/JemmySWT/src/org/jemmy/swt/Shells.java SWT/JemmySWT/src/org/jemmy/swt/TabFolderWrap.java SWT/JemmySWT/src/org/jemmy/swt/TableWrap.java SWT/JemmySWT/src/org/jemmy/swt/TextItemSelector.java SWT/JemmySWT/src/org/jemmy/swt/TextWrap.java SWT/JemmySWT/src/org/jemmy/swt/ToolBarWrap.java SWT/JemmySWT/src/org/jemmy/swt/ToolTipItemSelector.java SWT/JemmySWT/src/org/jemmy/swt/TreeWrap.java SWT/JemmySWT/src/org/jemmy/swt/Version.java SWT/JemmySWT/src/org/jemmy/swt/jemmy.properties SWT/JemmySWT/src/org/jemmy/swt/lookup/ByItemLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByItemStringsLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByItemToolTipLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByName.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByStringQueueLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextButtonLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextControlLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextItem.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextLabelLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextShell.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextTextLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByToolTipControl.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByToolTipItem.java SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTooltipButtonLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/CoordinateLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/QueueLookup.java SWT/JemmySWT/src/org/jemmy/swt/lookup/WrapperLookup.java SWT/JemmySWT/test/TEST.ROOT SWT/JemmySWT/test/org/jemmy/swt/Items.java SWT/JemmySWT/test/org/jemmy/swt/ItemsTest.java SWT/JemmySWT/test/org/jemmy/swt/MenuTest.java SWT/JemmySWT/test/org/jemmy/swt/PushButtonTest.java SWT/JemmySWT/test/org/jemmy/swt/Sample.java SWT/JemmySWT/test/org/jemmy/swt/SelectableTest.java SWT/JemmySWT/test/org/jemmy/swt/TestBrowser.java SWT/JemmySWT/test/org/jemmy/swt/TreeTest.java SWT/make/jemmy-v3-swt-ii/.idea/compiler.xml SWT/make/jemmy-v3-swt-ii/.idea/copyright/Oracle.xml SWT/make/jemmy-v3-swt-ii/.idea/encodings.xml SWT/make/jemmy-v3-swt-ii/.idea/misc.xml SWT/make/jemmy-v3-swt-ii/.idea/modules.xml SWT/make/jemmy-v3-swt-ii/swt/swt.iml core/JemmyAWTInput/build.xml core/JemmyBrowser/build.xml core/JemmyCore/build.xml core/make/build_template.xml make/build_template.xml
diffstat 68 files changed, 6034 insertions(+), 95 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/build.xml	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+ -->
+<project name="jemmy-browser" default="compile" basedir=".">
+    <import file="${basedir}/../../make/build_template.xml"/>
+    <property name="core.jar" location="../../core/JemmyCore/build/JemmyCore.jar"/>
+    <property name="awt_input.jar" location="../../core/JemmyAWTInput/build/JemmyAWTInput.jar"/>
+    <property name="browser.jar" location="../../core/JemmyBrowser/build/JemmyBrowser.jar"/>
+    <property name="version.file" value="org/jemmy/swt/jemmy.properties"/>
+    <property name="version.class" value="org.jemmy.swt.Version"/>
+    <property name="dependencies.classpath" value="${core.jar}:${browser.jar}:${awt_input.jar}:${swt.jar}"/>
+    <target name="check-dependecies-impl">
+        <fail message="Please specify swt.jar" unless="swt.jar"/>
+        <available file="${browser.jar}" property="dependencies.are.built"/>
+    </target>
+    <target name="build-dependecies-impl">
+        <ant dir="${basedir}/../../core/JemmyCore" target="jar" inheritAll="false"/>
+        <ant dir="${basedir}/../../core/JemmyAWTInput" target="jar" inheritAll="false"/>
+        <ant dir="${basedir}/../../core/JemmyBrowser" target="jar" inheritAll="false"/>
+    </target>
+    <target name="test-dependecies-impl">
+        <ant dir="${basedir}/../../core/JemmyCore" target="test" inheritAll="false"/>
+        <ant dir="${basedir}/../../core/JemmyAWTInput" target="test" inheritAll="false"/>
+        <ant dir="${basedir}/../../core/JemmyBrowser" target="test" inheritAll="false"/>
+    </target>
+</project>
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/input/KeyboardSelectable.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.interfaces.Selectable;
+
+/**
+ *
+ * @author shura
+ */
+public interface KeyboardSelectable<T> extends Selectable<T> {
+    public boolean isVertical();
+    public int index(T item);
+    public int selection();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/input/KeyboardSelector.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.Focusable;
+import org.jemmy.interfaces.Keyboard.KeyboardButton;
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.jemmy.interfaces.Selector;
+
+/**
+ *
+ * @author shura
+ */
+public class KeyboardSelector<T> implements Selector<T> {
+
+    private final Wrap<?> wrap;
+    private final KeyboardSelectable<T> control;
+
+    public KeyboardSelector(Wrap<?> wrap, KeyboardSelectable<T> control) {
+        this.wrap = wrap;
+        this.control = control;
+    }
+
+    public void select(T state) {
+        wrap.as(Focusable.class).focuser().focus();
+        int to = control.index(state);
+        int from = control.selection();
+        KeyboardButton btt;
+        if (control.isVertical()) {
+            btt = (to > from)
+                    ? KeyboardButtons.DOWN : KeyboardButtons.UP;
+        } else {
+            btt = (to > from)
+                    ? KeyboardButtons.RIGHT : KeyboardButtons.LEFT;
+        }
+        for (int i = 0; i < Math.abs(to - from); i++) {
+            wrap.keyboard().pushKey(btt);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/Browser.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.awt.AWTException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.Tree;
+import org.jemmy.action.GetAction;
+import org.jemmy.browser.BrowserDescriptor;
+import org.jemmy.browser.HierarchyDescriptor;
+import org.jemmy.browser.HierarchyView;
+import org.jemmy.control.Wrap;
+import org.jemmy.control.Wrapper;
+import org.jemmy.env.Environment;
+import org.jemmy.lookup.ControlHierarchy;
+import org.jemmy.lookup.ControlList;
+
+/**
+ *
+ * @author shura, erikgreijus
+ */
+public class Browser implements BrowserDescriptor {
+
+    public static void main(final String[] args) throws AWTException {
+        HierarchyView.startApp(args);
+        try {
+            new HierarchyView(new Browser()).setVisible(true);
+        } catch (AWTException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public String getTitle() {
+        return "SWT hierarchy";
+    }
+
+    public ControlList getHierarchy() {
+        return new ControlHierarchy() {
+
+            public List<?> getChildren(final Object subParent) {
+                return Arrays.asList(new GetAction<Object[]>() {
+
+                    public void run(Object... parameters) {
+                        Display.getDefault().syncExec(new Runnable() {
+
+                            public void run() {
+                                if (subParent instanceof Composite) {
+                                    setResult(((Composite) subParent).getChildren());
+                                } else {
+                                    setResult(new Object[0]);
+                                }
+                            }
+                        });
+                    }
+                }.dispatch(Environment.getEnvironment()));
+            }
+
+            public Object getParent(final Object child) {
+                return new GetAction<Object>() {
+
+                    public void run(Object... parameters) {
+                        Display.getDefault().syncExec(new Runnable() {
+
+                            public void run() {
+                                if (child instanceof Control) {
+                                    setResult(((Control) child).getParent());
+                                } else if (child instanceof Item) {
+                                    setResult("");
+                                } else {
+                                    setResult(null);
+                                }
+                            }
+                        });
+                    }
+                }.dispatch(Environment.getEnvironment());
+            }
+
+            public List<?> getControls() {
+                return Arrays.asList(new GetAction<Shell[]>() {
+
+                    public void run(Object... parameters) {
+                        Display.getDefault().syncExec(new Runnable() {
+
+                            public void run() {
+                                setResult(Display.getDefault().getShells());
+                            }
+                        });
+                    }
+                }.dispatch(Environment.getEnvironment()));
+            }
+        };
+    }
+
+    public Wrapper getWrapper() {
+        return Shells.SHELLS.swtWrapper;
+    }
+
+    public HierarchyDescriptor getSubHierarchyDescriptor(Wrap wrap) {
+        if (wrap.getControl() instanceof Control) {
+            ItemsGet ig = new ItemsGet((Control) wrap.getControl());
+            Display.getDefault().syncExec(ig);
+            if (ig.items != null) {
+                return new ItemHierarchyDescriptor(wrap, TableItem.class,
+                        ig.items);
+            }
+        }
+        return null;
+    }
+
+    class ItemsGet implements Runnable {
+
+        Item[] items;
+        Control control;
+
+        public ItemsGet(Control control) {
+            this.control = control;
+        }
+
+        public void run() {
+            if (control instanceof Table) {
+                items = ((Table) control).getItems();
+            } else if (control instanceof Tree) {
+                items = ((Tree) control).getItems();
+            } else if (control instanceof ToolBar) {
+                items = ((ToolBar) control).getItems();
+            } else if (control instanceof TabFolder) {
+                items = ((TabFolder) control).getItems();
+            } else if (control instanceof CTabFolder) {
+                items = ((CTabFolder) control).getItems();
+            }
+        }
+    }
+
+    private class ItemHierarchyDescriptor implements HierarchyDescriptor {
+
+        Wrap<?> parent;
+        ItemParent<?> items;
+
+        public ItemHierarchyDescriptor(Wrap<?> parent, Class type, final Item[] items) {
+            this.parent = parent;
+            this.items = new ItemParent(parent, type) {
+
+                @Override
+                protected List getItems() {
+                    return Arrays.asList(items);
+                }
+            };
+        }
+
+        public ControlList getHierarchy() {
+            return items.controList;
+        }
+
+        public Wrapper getWrapper() {
+            return items.wrapper;
+        }
+
+        public HierarchyDescriptor getSubHierarchyDescriptor(Wrap wrap) {
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/CComboWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.Arrays;
+
+import org.eclipse.swt.custom.CCombo;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.control.Property;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Environment;
+import org.jemmy.input.KeyboardSelectable;
+import org.jemmy.input.KeyboardSelector;
+import org.jemmy.input.SelectionText;
+import org.jemmy.interfaces.ControlInterface;
+import org.jemmy.interfaces.Focusable;
+import org.jemmy.interfaces.Selector;
+
+/**
+ * @author Erik Greijus
+ */
+@ControlType(CCombo.class)
+public class CComboWrap<T extends CCombo> extends ControlWrap<T> implements KeyboardSelectable<String>, Focusable {
+
+    class FocusableSelectionText extends SelectionText implements Focusable {
+
+        protected ClickFocus focuser;
+        private final CComboWrap cComboWrap;
+
+        public FocusableSelectionText(CComboWrap textWrap) {
+            super(textWrap);
+            this.cComboWrap = textWrap;
+        }
+
+        @Override
+        public double position() {
+            return cComboWrap.position();
+        }
+
+        @Override
+        public String text() {
+            return cComboWrap.text();
+        }
+
+        @Override
+        public double anchor() {
+            return cComboWrap.anchor();
+        }
+
+        @Override
+        public ClickFocus focuser() {
+            if (focuser == null) {
+                focuser = new ClickFocus();
+            }
+            return focuser;
+        }
+    }
+
+    FocusableSelectionText text = new FocusableSelectionText(this);
+    private KeyboardSelector<String> selector = null;
+
+    public CComboWrap(Environment env, T node) {
+        super(env, node);
+    }
+
+    @Override
+    public java.util.List<String> getStates() {
+        return new GetAction<java.util.List<String>>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                setResult(Arrays.asList(getControl().getItems()));
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Override
+    public String getState() {
+        return new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                if (getControl().getSelectionIndex() >= 0) {
+                    setResult(getControl().getItem(getControl().getSelectionIndex()));
+                } else {
+                    setResult(null);
+                }
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Override
+    public int selection() {
+        return new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                setResult(getControl().getSelectionIndex());
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Override
+    public Selector<String> selector() {
+        if (selector == null) {
+            selector = new KeyboardSelector<String>(this, this);
+        }
+        return selector;
+    }
+
+    @Override
+    public Class<String> getType() {
+        return String.class;
+    }
+
+    @Override
+    public boolean isVertical() {
+        return true;
+    }
+
+    @Override
+    public int index(String item) {
+        return getStates().indexOf(item);
+    }
+
+    @Override
+    public ClickFocus focuser() {
+        if (focuser == null) {
+            super.focuser().clickCount = 2;
+        }
+        return focuser;
+    }
+
+    @Property(Wrap.POSITION_PROP_NAME)
+    public Integer position() {
+        GetAction<Integer> action = new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getSelection().x);
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Property(SelectionText.SELECTION_ANCHOR_PROP_NAME)
+    public Integer anchor() {
+        return position();
+    }
+
+    @Property(Wrap.TEXT_PROP_NAME)
+    @Override
+    public String text() {
+        GetAction<String> action = new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getText());
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> boolean is(Class<INTERFACE> interfaceClass) {
+        if (interfaceClass.isAssignableFrom(SelectionText.class)) {
+            return true;
+        }
+        if (interfaceClass.equals(Focusable.class)) {
+            return true;
+        }
+        return super.is(interfaceClass);
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> INTERFACE as(Class<INTERFACE> interfaceClass) {
+        if (interfaceClass.isAssignableFrom(SelectionText.class)) {
+            return (INTERFACE) text;
+        }
+        if (interfaceClass.isAssignableFrom(Focusable.class)) {
+            return (INTERFACE) text;
+        }
+        return super.as(interfaceClass);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/CTabFolderWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.control.Property;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.interfaces.Selectable;
+import org.jemmy.interfaces.Selector;
+import org.jemmy.interfaces.TypeControlInterface;
+import org.jemmy.lookup.Lookup;
+
+/**
+ *
+ * @author shura, erikgreijus
+ * @param <T>
+ */
+@ControlType(CTabFolder.class)
+public class CTabFolderWrap<T extends CTabFolder> extends ControlWrap<T> implements Selectable<String> {
+
+    private ItemParent<CTabItem> items = null;
+    private TextItemSelector selector = null;
+
+    public CTabFolderWrap(Environment env, T node) {
+        super(env, node);
+    }
+
+    @Override
+    public <TYPE, INTERFACE extends TypeControlInterface<TYPE>> INTERFACE as(Class<INTERFACE> interfaceClass, Class<TYPE> type) {
+        if (interfaceClass.equals(Parent.class) && CTabItem.class.equals(type)) {
+            if (items == null) {
+                items = new ItemParent<CTabItem>(this, CTabItem.class) {
+
+                    @Override
+                    protected List<CTabItem> getItems() {
+                        return Arrays.asList(new GetAction<CTabItem[]>() {
+
+                            @Override
+                            public void run(Object... parameters) {
+                                setResult(getControl().getItems());
+                            }
+                        }.dispatch(getEnvironment()));
+                    }
+                };
+            }
+            return (INTERFACE) items;
+        }
+        return super.as(interfaceClass, type);
+    }
+
+    @Override
+    public <TYPE, INTERFACE extends TypeControlInterface<TYPE>> boolean is(Class<INTERFACE> interfaceClass, Class<TYPE> type) {
+        if (interfaceClass.equals(Parent.class) && CTabItem.class.equals(type)) {
+            return true;
+        }
+        return super.is(interfaceClass, type);
+    }
+
+    public int getItemCount() {
+        return new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getItemCount());
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Property(Selectable.STATES_PROP_NAME)
+    public List<String> getStates() {
+        return new GetAction<List<String>>() {
+            @Override
+            public void run(Object... parameters) {
+                Lookup<CTabItem> lookup = as(Parent.class, CTabItem.class).lookup();
+                ArrayList<String> res = new ArrayList<String>();
+                for (int i = 0; i < lookup.size(); i++) {
+                    res.add(lookup.get(i).getText());
+                }
+                setResult(res);
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Property(Selectable.STATE_PROP_NAME)
+    public String getState() {
+        return new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) {
+                CTabItem selected = getControl().getSelection();
+                setResult(selected != null ? selected.getText() : "No selection");
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    public Selector<String> selector() {
+        if (selector == null) {
+            if (items == null) {
+                as(Parent.class, CTabItem.class);
+            }
+            selector = new TextItemSelector(items);
+        }
+        return selector;
+    }
+
+    public Class<String> getType() {
+        return String.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/ComboWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.Arrays;
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Combo;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.control.Property;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Environment;
+import org.jemmy.input.KeyboardSelectable;
+import org.jemmy.input.KeyboardSelector;
+import org.jemmy.input.SelectionText;
+import org.jemmy.interfaces.ControlInterface;
+import org.jemmy.interfaces.Focusable;
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.jemmy.interfaces.Keyboard.KeyboardModifier;
+import org.jemmy.interfaces.Selector;
+
+/**
+ *
+ * @author shura, erikgreijus
+ * @param <T>
+ */
+@ControlType(Combo.class)
+public class ComboWrap<T extends Combo> extends ControlWrap<T> implements
+        KeyboardSelectable<String>, Focusable {
+
+    public static final String DISMISSAL_BUTTON_PROP = ComboWrap.class.getName() + ".dismissal.button";
+    public static final String DISMISSAL_MODIFIER_PROP = ComboWrap.class.getName() + ".dismissal.modifier";
+    private final KeyboardButtons dismissalButton;
+    private final KeyboardModifier[] dismissalModifier;
+
+    class ComboKeyboardSelector<T> extends KeyboardSelector<T> {
+
+        private final Wrap<?> comboWrap;
+
+        public ComboKeyboardSelector(Wrap<?> wrap, KeyboardSelectable<T> control) {
+            super(wrap, control);
+            comboWrap = wrap;
+        }
+
+        @Override
+        public void select(T state) {
+            super.select(state);
+            comboWrap.keyboard().pushKey(dismissalButton, dismissalModifier);
+        }
+    }
+
+    class FocusableSelectionText extends SelectionText implements Focusable {
+
+        protected ClickFocus focuser;
+        private final ComboWrap<T> comboWrap;
+
+        public FocusableSelectionText(ComboWrap<T> textWrap) {
+            super(textWrap);
+            this.comboWrap = textWrap;
+        }
+
+        @Override
+        public double position() {
+            return comboWrap.position();
+        }
+
+        @Override
+        public String text() {
+            return comboWrap.text();
+        }
+
+        @Override
+        public double anchor() {
+            return comboWrap.anchor();
+        }
+
+        @Override
+        public ClickFocus focuser() {
+            if (focuser == null) {
+                focuser = new ClickFocus();
+            }
+            return focuser;
+        }
+    }
+
+    FocusableSelectionText text = new FocusableSelectionText(this);
+    private ComboKeyboardSelector<String> selector = null;
+
+    public ComboWrap(Environment env, T node) {
+        super(env, node);
+        KeyboardButtons defaultDismissalButton = System.getProperty("os.name").toLowerCase().contains("windows") ? KeyboardButtons.ESCAPE : KeyboardButtons.SPACE;
+        KeyboardModifier[] defaultDismissalModifiers = new KeyboardModifier[0];
+        dismissalButton = env.getProperty(KeyboardButtons.class,
+                DISMISSAL_BUTTON_PROP, defaultDismissalButton);
+        dismissalModifier = (KeyboardModifier[]) env.getProperty(KeyboardModifier[].class,
+                DISMISSAL_MODIFIER_PROP, defaultDismissalModifiers);
+    }
+
+    @Override
+    public java.util.List<String> getStates() {
+        return new GetAction<java.util.List<String>>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                setResult(Arrays.asList(getControl().getItems()));
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Override
+    public String getState() {
+        return new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                if (getControl().getSelectionIndex() >= 0) {
+                    setResult(getControl().getItem(getControl().getSelectionIndex()));
+                } else {
+                    setResult(null);
+                }
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Override
+    public int selection() {
+        return new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                setResult(getControl().getSelectionIndex());
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Override
+    public Selector<String> selector() {
+        if (selector == null) {
+            selector = new ComboKeyboardSelector<>(this, this);
+        }
+        return selector;
+    }
+
+    @Override
+    public Class<String> getType() {
+        return String.class;
+    }
+
+    @Override
+    public boolean isVertical() {
+        return true;
+    }
+
+    @Override
+    public int index(String item) {
+        return new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                setResult(getControl().indexOf(item));
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Override
+    public ClickFocus focuser() {
+        if (focuser == null) {
+            super.focuser().clickCount = 2;
+        }
+        return focuser;
+    }
+
+    @Override
+    public boolean hasFocus() {
+        GetAction<Boolean> action;
+        action = new GetAction<Boolean>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().isFocusControl() || getControl().getListVisible());
+            }
+
+            @Override
+            public String toString() {
+                return "Getting focus state for " + getControl();
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Property(Wrap.POSITION_PROP_NAME)
+    public Integer position() {
+        GetAction<Integer> action = new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getSelection().x);
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Property(SelectionText.SELECTION_ANCHOR_PROP_NAME)
+    public Integer anchor() {
+        GetAction<Integer> action = new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) {
+                Point selection = getControl().getSelection();
+                setResult((selection.x == getControl().getCaretPosition())
+                        ? selection.y : selection.x);
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Property(Wrap.TEXT_PROP_NAME)
+    @Override
+    public String text() {
+        GetAction<String> action = new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getText());
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> boolean is(Class<INTERFACE> interfaceClass) {
+        if (interfaceClass.isAssignableFrom(SelectionText.class)) {
+            return true;
+        }
+        if (interfaceClass.equals(Focusable.class)) {
+            return true;
+        }
+        return super.is(interfaceClass);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <INTERFACE extends ControlInterface> INTERFACE as(Class<INTERFACE> interfaceClass) {
+        if (interfaceClass.isAssignableFrom(SelectionText.class)) {
+            return (INTERFACE) text;
+        }
+        if (interfaceClass.isAssignableFrom(Focusable.class)) {
+            return (INTERFACE) text;
+        }
+        return super.as(interfaceClass);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/CompositeWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.lookup.Any;
+import org.jemmy.lookup.ControlHierarchy;
+import org.jemmy.lookup.HierarchyLookup;
+import org.jemmy.lookup.Lookup;
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ *
+ * @author shura, erikgreijus
+ * @param <T>
+ */
+@ControlType(Composite.class)
+public class CompositeWrap<T extends Composite> extends ControlWrap<T> implements Parent<Control> {
+
+    private final SWTHierarchy swth;
+    public CompositeWrap(Environment env, T node) {
+        super(env, node);
+        swth = new SWTHierarchy();
+    }
+
+    public <ST extends org.eclipse.swt.widgets.Control> Lookup<ST> lookup(Class<ST> controlClass, LookupCriteria<ST> criteria) {
+        return new HierarchyLookup(getEnvironment(), swth, Shells.SHELLS.swtWrapper, controlClass, criteria);
+    }
+
+    public <ST extends Control> Lookup<ST> lookup(Class<ST> controlClass) {
+        return lookup(controlClass, new Any<ST>());
+    }
+
+    public Lookup<org.eclipse.swt.widgets.Control> lookup(LookupCriteria<org.eclipse.swt.widgets.Control> criteria) {
+        return lookup(getType(), criteria);
+    }
+
+    public Lookup<Control> lookup() {
+        return lookup(new Any<Control>());
+    }
+
+    public Class<org.eclipse.swt.widgets.Control> getType() {
+        return org.eclipse.swt.widgets.Control.class;
+    }
+
+    private class SWTHierarchy implements ControlHierarchy {
+
+        public List<?> getControls() {
+            GetAction<org.eclipse.swt.widgets.Control[]> action = new GetAction<org.eclipse.swt.widgets.Control[]>() {
+                public void run(Object... parameters) {
+                    Display.getDefault().syncExec(new Runnable() {
+                        public void run() {
+                            if (!getControl().isDisposed()) {
+                                setResult(getControl().getChildren());
+                            } else {
+                                setResult(new Control[0]);
+                            }
+                        }
+                    });
+                }
+            };
+            getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+            return Arrays.asList(action.getResult());
+        }
+
+        public List<?> getChildren(final Object subParent) {
+            if(!(subParent instanceof Composite)) return null;
+            GetAction<org.eclipse.swt.widgets.Control[]> action = new GetAction<org.eclipse.swt.widgets.Control[]>() {
+                public void run(Object... parameters) {
+                    Display.getDefault().syncExec(new Runnable() {
+                        public void run() {
+                            Composite subParentComposite = Composite.class.cast(subParent);
+                            if (!subParentComposite.isDisposed()) {
+                                setResult(subParentComposite.getChildren());
+                            } else {
+                                setResult(new Control[0]);
+                            }
+                        }
+                    });
+                }
+            };
+            getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+            return Arrays.asList(action.getResult());
+        }
+
+        public Object getParent(final Object child) {
+            GetAction<Object> action = new GetAction<Object>() {
+                public void run(Object... parameters) {
+                    Display.getDefault().syncExec(new Runnable() {
+                        public void run() {
+                            Widget childWidget = Widget.class.cast(child);
+                            if (!childWidget.isDisposed()) {
+                                setResult(((org.eclipse.swt.widgets.Control)child).getParent());
+                            } else {
+                                setResult(null);
+                            }
+                        }
+                    });
+                }
+            };
+            getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+            return action.getResult();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/ControlWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.jemmy.Point;
+import org.jemmy.Rectangle;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.Wrap;
+import org.jemmy.control.ControlType;
+import org.jemmy.control.Property;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.ControlInterface;
+import org.jemmy.interfaces.Focus;
+import org.jemmy.interfaces.Focusable;
+import org.jemmy.interfaces.PopupOwner;
+
+/**
+ *
+ * @author shura, erikgreijus
+ * @param <T>
+ */
+@ControlType(org.eclipse.swt.widgets.Control.class)
+public class ControlWrap<T extends org.eclipse.swt.widgets.Control> extends Wrap<T> implements Focusable {
+
+    protected ClickFocus focuser;
+    protected PopupOwner popup = null;
+
+    public ControlWrap(Environment env, T node) {
+        super(env, node);
+    }
+
+    @Override
+    public Rectangle getScreenBounds() {
+        return getScreenBounds(getControl(), getEnvironment());
+    }
+
+    public static Rectangle getScreenBounds(Control control, Environment env) {
+        Rectangle res = getBounds(control, env);
+        org.eclipse.swt.graphics.Point loc = getScreenLocation(control, env);
+        res.x = loc.x;
+        res.y = loc.y;
+        return res;
+    }
+
+    public static org.eclipse.swt.graphics.Point getScreenLocation(final org.eclipse.swt.widgets.Control control, Environment env) {
+        GetAction<org.eclipse.swt.graphics.Point> action = new GetAction<org.eclipse.swt.graphics.Point>() {
+
+            public void run(Object... parameters) {
+                setResult(Display.getDefault().map(control, null, new org.eclipse.swt.graphics.Point(0, 0)));
+            }
+
+            @Override
+            public String toString() {
+                return "Getting parent for " + control;
+            }
+        };
+        env.getExecutor().execute(env, true, action);
+        return action.getResult();
+    }
+
+    public Shell getShell() {
+        GetAction<Shell> action = new GetAction<Shell>() {
+
+            public void run(Object... parameters) {
+                setResult(getControl().getShell());
+            }
+
+            @Override
+            public String toString() {
+                return "Getting shell for " + getControl();
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    public boolean hasFocus() {
+        GetAction<Boolean> action = new GetAction<Boolean>() {
+
+            public void run(Object... parameters) {
+                setResult(getControl().isFocusControl());
+            }
+
+            @Override
+            public String toString() {
+                return "Getting shell for " + getControl();
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    public Menu menu() {
+        GetAction<Menu> action = new GetAction<Menu>() {
+
+            public void run(Object... parameters) {
+                setResult(getControl().getMenu());
+            }
+
+            @Override
+            public String toString() {
+                return "Getting shell for " + getControl();
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    public static Composite getParent(final org.eclipse.swt.widgets.Control control, Environment env) {
+        GetAction<Composite> action = new GetAction<Composite>() {
+
+            public void run(Object... parameters) {
+                setResult(control.getParent());
+            }
+
+            @Override
+            public String toString() {
+                return "Getting parent for " + control;
+            }
+        };
+        env.getExecutor().execute(env, true, action);
+        return action.getResult();
+    }
+
+    public ClickFocus focuser() {
+        if (focuser == null) {
+            focuser = new ClickFocus();
+        }
+        return focuser;
+    }
+
+    public static Rectangle getBounds(final org.eclipse.swt.widgets.Control c, Environment env) {
+        GetAction<org.eclipse.swt.graphics.Rectangle> action = new GetAction<org.eclipse.swt.graphics.Rectangle>() {
+
+            public void run(Object... parameters) {
+                setResult(c.getBounds());
+            }
+
+            @Override
+            public String toString() {
+                return "Getting bounds for " + c;
+            }
+        };
+        env.getExecutor().execute(env, true, action);
+        org.eclipse.swt.graphics.Rectangle res = action.getResult();
+        return new Rectangle(res.x, res.y, res.width, res.height);
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> boolean is(Class<INTERFACE> interfaceClass) {
+        if (PopupOwner.class.isAssignableFrom(interfaceClass)) {
+            return menu() != null;
+        }
+        //disable focusable for now
+        //TODO fix
+        if (interfaceClass.equals(Focusable.class)) {
+            return false;
+        }
+        return super.is(interfaceClass);
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> INTERFACE as(Class<INTERFACE> interfaceClass) {
+        if (PopupOwner.class.isAssignableFrom(interfaceClass)) {
+            if (popup == null) {
+                popup = new SWTPopupOwner(this);
+            }
+            return (INTERFACE) popup;
+        }
+        return super.as(interfaceClass);
+    }
+
+    protected class ClickFocus implements Focus {
+
+        Point pnt = null;
+        int clickCount = 1;
+
+        public void focus() {
+            if (!hasFocus()) {
+                mouse().click(clickCount, pnt);
+            }
+        }
+    }
+
+    @Property(Wrap.NAME_PROP_NAME)
+    public String name() {
+        GetAction<String> action = new GetAction<String>() {
+            @Override
+            public void run(Object... parameters) {
+                setResult((String) getControl().getData("name"));
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Property(Wrap.TEXT_PROP_NAME)
+    public String text() {
+        GetAction<String> action = new GetAction<String>() {
+            @Override
+            public void run(Object... parameters) {
+                String result = "";
+                try {
+                    Method mthd = getControl().getClass().getMethod("getText");
+                    result = (String) mthd.invoke(getControl());
+                } catch (NoSuchMethodException e) {
+                    System.err.println("Exception when using reflection to get text from " + getControl());
+                    e.printStackTrace();
+                } catch (SecurityException e) {
+                    System.err.println("Exception when using reflection to get text from " + getControl());
+                    e.printStackTrace();
+                } catch (IllegalAccessException e) {
+                    System.err.println("Exception when using reflection to get text from " + getControl());
+                    e.printStackTrace();
+                } catch (IllegalArgumentException e) {
+                    System.err.println("Exception when using reflection to get text from " + getControl());
+                    e.printStackTrace();
+                } catch (InvocationTargetException e) {
+                    System.err.println("Exception when using reflection to get text from " + getControl());
+                    e.printStackTrace();
+                }
+                setResult(result);
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/IndexItemSelector.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.widgets.Item;
+import org.jemmy.interfaces.Selector;
+
+/**
+ *
+ * @author shura
+ */
+public class IndexItemSelector implements Selector<Integer> {
+
+    private final ItemParent<? extends Item> parent;
+
+    public IndexItemSelector(ItemParent<? extends Item> parent) {
+        this.parent = parent;
+    }
+
+    public void select(Integer state) {
+        parent.lookup().wrap(state).mouse().click();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/ItemParent.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.swt.widgets.Item;
+import org.jemmy.control.Wrap;
+import org.jemmy.control.Wrapper;
+import org.jemmy.lookup.AbstractParent;
+import org.jemmy.lookup.ControlList;
+import org.jemmy.lookup.Lookup;
+import org.jemmy.lookup.LookupCriteria;
+import org.jemmy.lookup.PlainLookup;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class ItemParent<T extends Item> extends AbstractParent<T> {
+
+    private final Wrap<?> itemListWrap;
+    final ControlList controList;
+    private final Class<T> type;
+    final Wrapper wrapper;
+
+    public ItemParent(Wrap<?> itemListWrap, Class<T> type) {
+        this.itemListWrap = itemListWrap;
+        this.type = type;
+        controList = new ControlList() {
+
+            public List<?> getControls() {
+                List<T> res = getItems();
+                return (res != null) ? res : new ArrayList<T>();
+            }
+        };
+        wrapper = new ItemWrapper(ItemParent.this.itemListWrap);
+    }
+
+    protected abstract List<T> getItems();
+
+    public <ST extends T> Lookup<ST> lookup(Class<ST> controlClass, LookupCriteria<ST> criteria) {
+        return new PlainLookup<ST>(itemListWrap.getEnvironment(),
+                controList, wrapper, controlClass, criteria);
+    }
+
+    public Lookup<T> lookup(LookupCriteria<T> criteria) {
+        return new PlainLookup<T>(itemListWrap.getEnvironment(),
+                controList, wrapper, type, criteria);
+    }
+
+    public Class<T> getType() {
+        return type;
+    }
+
+    static class ItemWrapper implements Wrapper {
+
+        Wrap<?> wrap;
+
+        public ItemWrapper(Wrap<?> wrap) {
+            this.wrap = wrap;
+        }
+
+        public <T> Wrap<? extends T> wrap(Class<T> controlClass, T control) {
+            return new ItemWrap(wrap, (Item) control);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/ItemWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import org.eclipse.swt.widgets.Item;
+import org.jemmy.JemmyException;
+import org.jemmy.Rectangle;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.Property;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Environment;
+
+/**
+ *
+ * @author shura, erikgreijus
+ * @param <T>
+ */
+public class ItemWrap<T extends Item> extends Wrap<T> {
+
+    private final Wrap<?> parent;
+
+    public ItemWrap(Wrap<?> parent, T node) {
+        super(new Environment(parent.getEnvironment()), node);
+        this.parent = parent;
+    }
+
+    @Property(Wrap.TEXT_PROP_NAME)
+    public String getText() {
+        return new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getText());
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    /**
+     * @return The visible part of this item's bounds (intersection of this and the parent's screen bounds)
+     */
+    @Override
+    public Rectangle getScreenBounds() {
+        try {
+            final Method m = getControl().getClass().getMethod("getBounds");
+            org.eclipse.swt.graphics.Rectangle bounds =
+                    new GetAction<org.eclipse.swt.graphics.Rectangle>() {
+
+                @Override
+                public void run(Object... parameters) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+                    setResult((org.eclipse.swt.graphics.Rectangle) m.invoke(getControl()));
+                }
+            }.dispatch(getEnvironment());
+            Rectangle parentBounds = parent.getScreenBounds();
+            return parentBounds.intersection(new Rectangle(bounds.x + parentBounds.x, bounds.y + parentBounds.y, bounds.width, bounds.height));
+        } catch (IllegalArgumentException | SecurityException ex) {
+            throw new JemmyException("Unable to get bounds on " + getControl(), ex);
+        } catch (NoSuchMethodException ex) {
+            throw new JemmyException("Bounds are not supported by " + getControl().getClass().getName(), ex);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/ListWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.Arrays;
+import org.eclipse.swt.widgets.List;
+import org.jemmy.Point;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.env.Environment;
+import org.jemmy.input.KeyboardSelectable;
+import org.jemmy.input.KeyboardSelector;
+import org.jemmy.interfaces.Focusable;
+import org.jemmy.interfaces.Selector;
+
+/**
+ *
+ * @author shura
+ */
+@ControlType(List.class)
+public class ListWrap<T extends List> extends ControlWrap<T> implements KeyboardSelectable<String>, Focusable {
+
+    private KeyboardSelector<String> selector = null;
+
+    public ListWrap(Environment env, T node) {
+        super(env, node);
+    }
+
+    public java.util.List<String> getStates() {
+        return new GetAction<java.util.List<String>>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                setResult(Arrays.asList(getControl().getItems()));
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    public String getState() {
+        return new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                setResult(getControl().getSelection()[0]);
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    public int selection() {
+        return new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                setResult(getControl().getSelectionIndex());
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    public boolean isVertical() {
+        return true;
+    }
+
+    public int index(String item) {
+        return getStates().indexOf(item);
+    }
+
+    public Selector<String> selector() {
+        if (selector == null) {
+            selector = new KeyboardSelector<String>(this, this);
+        }
+        return selector;
+    }
+
+    public Class<String> getType() {
+        return String.class;
+    }
+
+    @Override
+    public ClickFocus focuser() {
+        if (focuser == null) {
+            super.focuser().pnt = new Point(1, 1);
+        }
+        return focuser;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/MenuItemParent.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.Arrays;
+import java.util.List;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.Wrap;
+import org.jemmy.control.Wrapper;
+import org.jemmy.lookup.AbstractParent;
+import org.jemmy.lookup.ControlHierarchy;
+import org.jemmy.lookup.HierarchyLookup;
+import org.jemmy.lookup.Lookup;
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ *
+ * @author shura
+ */
+public class MenuItemParent extends AbstractParent<MenuItem> {
+
+    private Wrap<? extends Shell> shell;
+    private MenuHierarchy hierarchy;
+    private Wrapper wrapper;
+
+    public <ST extends MenuItem> Lookup<ST> lookup(Class<ST> controlClass, LookupCriteria<ST> criteria) {
+        return new HierarchyLookup<ST>(shell.getEnvironment(), hierarchy, wrapper, controlClass, criteria);
+    }
+
+    public Lookup<MenuItem> lookup(LookupCriteria<MenuItem> criteria) {
+        return lookup(MenuItem.class, criteria);
+    }
+
+    public Class<MenuItem> getType() {
+        return MenuItem.class;
+    }
+
+    private class MenuHierarchy implements ControlHierarchy {
+
+        public List<?> getChildren(final Object subParent) {
+            return new GetAction<List<?>>() {
+
+                @Override
+                public void run(Object... parameters) throws Exception {
+                    if(((MenuItem)subParent).getStyle() == SWT.CASCADE) {
+                        setResult(Arrays.asList(((MenuItem)subParent).getMenu().getItems()));
+                    } else {
+                        setResult(null);
+                    }
+                }
+            }.dispatch(shell.getEnvironment());
+        }
+
+        public Object getParent(final Object child) {
+            return new GetAction<MenuItem>() {
+
+                @Override
+                public void run(Object... parameters) throws Exception {
+                    setResult(((MenuItem)child).getMenu().getParentItem());
+                }
+            }.dispatch(shell.getEnvironment());
+        }
+
+        public List<?> getControls() {
+            return new GetAction<List<?>>() {
+
+                @Override
+                public void run(Object... parameters) throws Exception {
+                    setResult(Arrays.asList(shell.getControl().getMenuBar().getItems()));
+                }
+            }.dispatch(shell.getEnvironment());
+        }
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/SWTExecutor.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.widgets.Display;
+import org.jemmy.action.AbstractExecutor;
+import org.jemmy.action.Action;
+import org.jemmy.env.Environment;
+
+/**
+ *
+ * @author shura
+ */
+public class SWTExecutor extends AbstractExecutor {
+
+    @Override
+    public void executeQueue(Environment env, final Action action, final Object[] parameters) {
+        if (!isInAction()) {
+            env.getOutput(QUEUE_ACTION_OUTPUT).println("Running action on event queue: " + action);
+        }
+        Display.getDefault().syncExec(new Runnable() {
+
+            public void run() {
+                action.execute(parameters);
+            }
+        });
+    }
+
+    @Override
+    public void executeQueueDetached(Environment env, final Action action, final Object[] parameters) {
+        if (!isInAction()) {
+            env.getOutput().println("Running detached action on event queue: " + action);
+        }
+        Display.getDefault().asyncExec(new Runnable() {
+
+            public void run() {
+                action.execute(parameters);
+            }
+        });
+    }
+
+    @Override
+    public boolean isOnQueue() {
+        return Display.getDefault().getThread() == Thread.currentThread();
+    }
+
+    @Override
+    protected boolean isQuiet() {
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/SWTMenu.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.jemmy.JemmyException;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Timeout;
+import org.jemmy.interfaces.Keyboard.KeyboardButton;
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.jemmy.interfaces.MenuSelectable;
+import org.jemmy.lookup.LookupCriteria;
+import org.jemmy.resources.StringComparePolicy;
+import org.jemmy.swt.lookup.ByTextItem;
+import org.jemmy.timing.State;
+
+/**
+ *
+ * @author shura, erikgreijus
+ */
+public class SWTMenu implements MenuSelectable<MenuItem> {
+
+    public static final Timeout BETWEEN_KEYS_SLEEP = new Timeout(
+            SWTMenu.class.getName() + ".between.keys.timeout", 100);
+    public static final Timeout SUBMENU_WAIT_TIMEOUT = new Timeout(
+            SWTMenu.class.getName() + ".submenu.wait.timeout", 1000);
+    public static final String SELECTION_BUTTON_PROP
+            = SWTMenu.class.getName() + ".selection.button";
+    public static final String ESCAPE_BUTTON_PROP
+            = SWTMenu.class.getName() + ".escape.button";
+    public static final String MULTI_LEVEL_DISCARD_PROP
+            = SWTMenu.class.getName() + ".multi.level.discard";
+    public static final String SKIPS_DISABLED_PROP
+            = SWTMenu.class.getName() + ".skips.disabled";
+    Wrap<? extends Control> owner;
+    boolean isBar;
+    private final KeyboardButton selectionButton;
+    private final KeyboardButton escapeButton;
+    private final boolean skipsDisabled;
+    private final boolean multiLevelDiscard;
+
+    static {
+        Shells.SHELLS.getEnvironment().initTimeout(BETWEEN_KEYS_SLEEP);
+        Shells.SHELLS.getEnvironment().initTimeout(SUBMENU_WAIT_TIMEOUT);
+    }
+
+    public SWTMenu(Wrap<? extends Control> owner, boolean isBar) {
+        this.owner = owner;
+        this.isBar = isBar;
+
+        KeyboardButtons defaultSelectionButton = System.getProperty("os.name")
+                .contains("Linux") ? KeyboardButtons.SPACE : KeyboardButtons.ENTER;
+        KeyboardButtons defaultEscapeButton = KeyboardButtons.ESCAPE;
+        Boolean defaultSkipsDisabled = System.getProperty("os.name").contains("Linux");
+        Boolean defaultMultiLevelDiscard = System.getProperty("os.name").contains("Windows");
+
+        selectionButton = (KeyboardButton) owner.getEnvironment().getProperty(KeyboardButton.class,
+                SELECTION_BUTTON_PROP, defaultSelectionButton);
+        escapeButton = (KeyboardButton) owner.getEnvironment().getProperty(KeyboardButton.class,
+                ESCAPE_BUTTON_PROP, defaultEscapeButton);
+        skipsDisabled = owner.getEnvironment().getProperty(Boolean.class,
+                SKIPS_DISABLED_PROP, defaultSkipsDisabled);
+        multiLevelDiscard = owner.getEnvironment().getProperty(Boolean.class,
+                MULTI_LEVEL_DISCARD_PROP, defaultMultiLevelDiscard);
+    }
+
+    @Override
+    public void push(LookupCriteria<MenuItem>... criteria) {
+        select(criteria);
+        owner.keyboard().pushKey(selectionButton);
+        owner.getEnvironment().getTimeout(BETWEEN_KEYS_SLEEP).sleep();
+    }
+
+    @Override
+    public void push(boolean desiredSelectionState, LookupCriteria<MenuItem>... criteria) {
+        if (desiredSelectionState != getSelection(select(criteria))) {
+            owner.keyboard().pushKey(selectionButton);
+        } else {
+            pushEscape((multiLevelDiscard) ? criteria.length : 1);
+        }
+        owner.getEnvironment().getTimeout(BETWEEN_KEYS_SLEEP).sleep();
+    }
+
+    @Override
+    public boolean getState(LookupCriteria<MenuItem>... criteria) {
+        boolean result = getSelection(select(criteria));
+        pushEscape((multiLevelDiscard) ? criteria.length : 1);
+        return result;
+    }
+
+    private void pushEscape(int times) {
+        for (int i = 0; i < times; i++) {
+            owner.keyboard().pushKey(escapeButton);
+            owner.getEnvironment().getTimeout(BETWEEN_KEYS_SLEEP).sleep();
+        }
+    }
+
+    private boolean getSelection(Wrap<MenuItem> menuItem) {
+        final boolean[] result = new boolean[]{false};
+        Display.getDefault().syncExec(() -> {
+            result[0] = menuItem.getControl().getSelection();
+        });
+        return result[0];
+    }
+
+    @Override
+    public Wrap<MenuItem> select(LookupCriteria<MenuItem>... criteria) {
+        if (criteria.length == 0) {
+            throw new IllegalArgumentException("Menu path length should be greater than 0");
+        }
+        final org.eclipse.swt.widgets.Menu[] start = new org.eclipse.swt.widgets.Menu[1];
+        if (isBar) {
+            if (!(owner.getControl() instanceof Shell)) {
+                throw new JemmyException("Menu bars are in shells");
+            }
+            Display.getDefault().syncExec(() -> {
+                start[0] = ((Shell) owner.getControl()).getMenuBar();
+            });
+        } else {
+            Display.getDefault().syncExec(() -> {
+                start[0] = owner.getControl().getMenu();
+            });
+        }
+        return select(start[0], Arrays.asList(criteria), true);
+    }
+
+    //selects hierarchically
+    //assumes first item in the menu is selected
+    private Wrap<MenuItem> select(final org.eclipse.swt.widgets.Menu menu, final List<LookupCriteria<MenuItem>> criteria, boolean entry) {
+        waitVisible(menu);
+        final int[] moveTimes = new int[]{0};
+        final MenuItem[] current = new MenuItem[]{null};
+        //find the one we're looking for
+        Display.getDefault().syncExec(() -> {
+            for (MenuItem item : menu.getItems()) {
+                if (criteria.get(0).check(item)) {
+                    current[0] = item;
+                    break;
+                }
+                if ((item.isEnabled() || !skipsDisabled) && !item.toString().contains("{|}")) {
+                    moveTimes[0]++;
+                }
+            }
+        });
+
+        if (current[0] == null) {
+            throw new JemmyException("Unable to find menu item conforming criteria "
+                    + criteria.get(0).toString(), menu);
+        }
+
+        boolean horizontal = entry ? isBar : false;
+        move(moveTimes[0], horizontal);
+
+        if (criteria.size() > 1) {
+            final org.eclipse.swt.widgets.Menu[] nextMenu = new org.eclipse.swt.widgets.Menu[1];
+            List<LookupCriteria<MenuItem>> nextCriteria = new ArrayList<>();
+            nextCriteria.addAll(criteria);
+            nextCriteria.remove(0);
+            KeyboardButton key = horizontal ? KeyboardButtons.DOWN : KeyboardButtons.RIGHT;
+            owner.keyboard().pushKey(key);
+            owner.getEnvironment().getTimeout(BETWEEN_KEYS_SLEEP).sleep();
+            Display.getDefault().syncExec(() -> {
+                nextMenu[0] = current[0].getMenu();
+            });
+            if (nextMenu[0] == null) {
+                throw new JemmyException("No submenu while criteria list length is still " + criteria.size(),
+                        criteria.get(0));
+            }
+            return select(nextMenu[0], nextCriteria, false);
+        }
+        return new ItemWrap<>(owner, current[0]);
+    }
+
+    void waitVisible(final org.eclipse.swt.widgets.Menu menu) {
+        owner.getEnvironment().getWaiter(SUBMENU_WAIT_TIMEOUT).waitValue(true,
+                new State<Boolean>() {
+
+                    boolean state = false;
+
+                    @Override
+                    public Boolean reached() {
+                        Display.getDefault().syncExec(() -> {
+                            state = menu.isVisible();
+                        });
+                        return state;
+                    }
+                });
+    }
+
+    private void move(int moveTimes, boolean horizontal) {
+        KeyboardButton key = horizontal ? KeyboardButtons.RIGHT : KeyboardButtons.DOWN;
+        for (int i = 0; i < moveTimes; i++) {
+            owner.keyboard().pushKey(key);
+            owner.getEnvironment().getTimeout(BETWEEN_KEYS_SLEEP).sleep();
+        }
+    }
+
+    static LookupCriteria<MenuItem> createCriteria(String text, StringComparePolicy policy) {
+        return new ByTextItem<>(text, policy);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/SWTMenuOwner.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.MenuItem;
+import org.jemmy.control.Wrap;
+import org.jemmy.input.StringMenuSelectableOwner;
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.jemmy.interfaces.MenuSelectable;
+import org.jemmy.lookup.LookupCriteria;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author shura, erikgreijus
+ */
+public class SWTMenuOwner extends StringMenuSelectableOwner<MenuItem> {
+
+    final SWTMenu menu;
+    final Wrap<? extends Control> owner;
+
+    public SWTMenuOwner(Wrap<? extends Control> owner, boolean isBar) {
+        super(owner);
+        this.owner = owner;
+        menu = new SWTMenu(owner, isBar);
+    }
+
+    @Override
+    public MenuSelectable menu() {
+        owner.keyboard().pushKey(KeyboardButtons.F10);
+        owner.getEnvironment().getTimeout(SWTMenu.BETWEEN_KEYS_SLEEP).sleep();
+        return menu;
+    }
+
+    @Override
+    public Class<MenuItem> getType() {
+        return MenuItem.class;
+    }
+
+    @Override
+    protected LookupCriteria<MenuItem> createCriteria(String text, StringComparePolicy policy) {
+        return SWTMenu.createCriteria(text, policy);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/SWTPopupOwner.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.MenuItem;
+import org.jemmy.Point;
+import org.jemmy.control.Wrap;
+import org.jemmy.input.StringPopupSelectableOwner;
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.jemmy.interfaces.MenuSelectable;
+import org.jemmy.interfaces.Mouse.MouseButtons;
+import org.jemmy.lookup.LookupCriteria;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author shura, erikgreijus
+ */
+public class SWTPopupOwner extends StringPopupSelectableOwner<MenuItem> {
+
+    final SWTMenu menu;
+    final Wrap<? extends Control> owner;
+
+    public SWTPopupOwner(Wrap<? extends Control> owner) {
+        super(owner);
+        this.owner = owner;
+        menu = new SWTMenu(owner, false);
+    }
+
+    @Override
+    public Class<MenuItem> getType() {
+        return MenuItem.class;
+    }
+
+    @Override
+    public MenuSelectable menu(Point p) {
+        owner.mouse().click(1, p, MouseButtons.BUTTON3);
+        menu.waitVisible(((ControlWrap)owner).menu());
+        owner.keyboard().pushKey(KeyboardButtons.DOWN);
+        owner.getEnvironment().getTimeout(SWTMenu.BETWEEN_KEYS_SLEEP).sleep();
+        return menu;
+    }
+
+    @Override
+    protected LookupCriteria<MenuItem> createCriteria(String text, StringComparePolicy policy) {
+        return SWTMenu.createCriteria(text, policy);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/SWTTree.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.jemmy.TimeoutExpiredException;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Timeout;
+import org.jemmy.input.StringTree;
+import org.jemmy.interfaces.Focusable;
+import org.jemmy.interfaces.Keyboard.KeyboardButton;
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.jemmy.interfaces.Keyboard.KeyboardModifier;
+import org.jemmy.interfaces.TreeSelector;
+import org.jemmy.lookup.LookupCriteria;
+import org.jemmy.resources.StringComparePolicy;
+import org.jemmy.swt.lookup.ByItemStringsLookup;
+import org.jemmy.timing.State;
+
+/**
+ * @author shura, erikgreijus
+ */
+public class SWTTree extends StringTree<TreeItem> {
+
+    public static final Timeout WAIT_NODE_TIMEOUT = new Timeout(SWTTree.class.getName() + ".wait.node.timeout", 1000);
+    public static final Timeout WAIT_NODE_EXPANDED_TIMEOUT = new Timeout(SWTTree.class.getName() + ".wait.node.expanded.timeout", 100);
+    public static final Timeout AFTER_MOVE_SLEEP = new Timeout(SWTTree.class.getName() + ".after.move.sleep.timeout", 100);
+    public static final String EXPAND_BUTTON_PROP = SWTTree.class.getName() + ".expand.button";
+    public static final String EXPAND_MODIFIER_PROP = SWTTree.class.getName() + ".expand.modifier";
+
+    private static final int MAX_MOVE_TRIES = 5;
+
+    static {
+        Shells.SHELLS.getEnvironment().initTimeout(WAIT_NODE_TIMEOUT);
+        Shells.SHELLS.getEnvironment().initTimeout(WAIT_NODE_EXPANDED_TIMEOUT);
+        Shells.SHELLS.getEnvironment().initTimeout(AFTER_MOVE_SLEEP);
+    }
+    final TreeWrap<? extends Tree> owner;
+    SWTTreeSelector selector = null;
+    private final KeyboardButton expandButton;
+    private final KeyboardModifier[] expandModifier;
+
+    public SWTTree(TreeWrap<? extends Tree> owner) {
+        super(owner.getEnvironment());
+        this.owner = owner;
+
+        KeyboardButton defaultExpandButton = System.getProperty("os.name")
+                .contains("Linux") ? KeyboardButtons.ADD
+                        : KeyboardButtons.RIGHT;
+        KeyboardModifier[] defaultExpandModifier = new KeyboardModifier[0];
+
+        expandButton = (KeyboardButton) owner.getEnvironment().getProperty(KeyboardButtons.class,
+                EXPAND_BUTTON_PROP, defaultExpandButton);
+        expandModifier = (KeyboardModifier[]) owner.getEnvironment().getProperty(KeyboardModifier[].class,
+                EXPAND_MODIFIER_PROP, defaultExpandModifier);
+    }
+
+    @Override
+    protected LookupCriteria<TreeItem> createCriteria(String text, StringComparePolicy policy) {
+        return new ByItemStringsLookup<>(text, policy);
+    }
+
+    @Override
+    public TreeSelector<TreeItem> selector() {
+        if (selector == null) {
+            selector = new SWTTreeSelector();
+        }
+        return selector;
+    }
+
+    @Override
+    public Class<TreeItem> getType() {
+        return TreeItem.class;
+    }
+
+    private boolean getExpanded(final TreeItem item) {
+        return new GetAction<Boolean>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                setResult(item.getExpanded());
+            }
+        }.dispatch(owner.getEnvironment());
+    }
+
+    private class SWTTreeSelector implements TreeSelector<TreeItem> {
+
+        private List<LookupCriteria<TreeItem>> criteriaList;
+
+        @Override
+        public Wrap<? extends TreeItem> select(LookupCriteria<TreeItem>... criteria) {
+            criteriaList = Arrays.asList(criteria);
+            owner.as(Focusable.class).focuser().focus();
+            TreeItem[] items = new GetAction<TreeItem[]>() {
+
+                @Override
+                public void run(Object... parameters) throws Exception {
+                    setResult(owner.getControl().getItems());
+                }
+            }.dispatch(owner.getEnvironment());
+            return new ItemWrap<>(owner, waitAndExpand(Arrays.asList(items), Arrays.asList(criteria)));
+        }
+
+        protected TreeItem waitAndExpand(final List<TreeItem> items, final List<LookupCriteria<TreeItem>> criteria) {
+            final TreeItem next = owner.getEnvironment().getWaiter(WAIT_NODE_TIMEOUT).ensureState(new State<TreeItem>() {
+
+                @Override
+                public TreeItem reached() {
+                    for (TreeItem ti : items) {
+                        if (criteria.get(0).check(ti)) {
+                            return ti;
+                        }
+                    }
+                    return null;
+                }
+
+                @Override
+                public String toString() {
+                    return getReadableCriteriaList();
+                }
+            });
+            int numberOfTries = 0;
+            // determine if we really need to walk the tree to this non-leaf node (and expand it) in order to be able to find the next node
+            boolean isExpanded = criteria.size() > 1 && getExpanded(next);
+            while (!next.equals(owner.getSelectedItem()) && !isExpanded) {
+                int from = owner.getItems().indexOf(owner.getSelectedItem());
+                int to = owner.getItems().indexOf(next);
+                if (numberOfTries > 0) {
+                    if (from == -1) {
+                        /* in case we were unable to select the desired item,
+                         * focus (but not selection) is likely on the last or the
+                         * only item in the tree so pushing the down or up key won't select the item.
+                         */
+                        owner.keyboard().pushKey(KeyboardButtons.SPACE);
+                        owner.getEnvironment().getTimeout(AFTER_MOVE_SLEEP).sleep();
+                    } else if (numberOfTries > 1) {
+                        // we could be stuck on an editable field so keyboard navigation won't work until we escape out
+                        // of that. Only do this if the first retry round fails as pushing escape may close a crucial dialog
+                        owner.keyboard().pushKey(KeyboardButtons.ESCAPE);
+                        owner.getEnvironment().getTimeout(AFTER_MOVE_SLEEP).sleep();
+                    }
+                    from = owner.getItems().indexOf(owner.getSelectedItem());
+                }
+
+                KeyboardButton btt = (to > from) ? KeyboardButtons.DOWN : KeyboardButtons.UP;
+                for (int i = 0; i < Math.abs(to - from); i++) {
+                    owner.keyboard().pushKey(btt);
+                    owner.getEnvironment().getTimeout(AFTER_MOVE_SLEEP).sleep();
+                }
+                numberOfTries++;
+                if (numberOfTries >= MAX_MOVE_TRIES) {
+                    if (!next.equals(owner.getSelectedItem())) {
+                        throw new TimeoutExpiredException("Unable to select the tree item with the following path " + getReadableCriteriaList());
+                    } else {
+                        break;
+                    }
+                }
+            }
+
+            if (criteria.size() > 1) {
+                if (!getExpanded(next)) {
+                    owner.keyboard().pushKey(expandButton, expandModifier);
+                    owner.getEnvironment().getTimeout(AFTER_MOVE_SLEEP).sleep();
+                    owner.keyboard().pushKey(KeyboardButtons.DOWN);
+                    owner.getEnvironment().getTimeout(AFTER_MOVE_SLEEP).sleep();
+                }
+                owner.getEnvironment().getWaiter(WAIT_NODE_EXPANDED_TIMEOUT).
+                        ensureValue(true, new State<Boolean>() {
+
+                            @Override
+                            public Boolean reached() {
+                                return getExpanded(next);
+                            }
+                        });
+                return waitAndExpand(getItems(next), criteria.subList(1, criteria.size()));
+            } else {
+                return next;
+            }
+        }
+
+        protected List<TreeItem> getItems(final TreeItem next) {
+            return new GetAction<List<TreeItem>>() {
+
+                @Override
+                public void run(Object... parameters) throws Exception {
+                    setResult(Arrays.asList(next.getItems()));
+                }
+            }.dispatch(owner.getEnvironment());
+        }
+
+        private String getReadableCriteriaList() {
+            List<String> result = new ArrayList<>();
+            criteriaList.stream().forEach((lookupCriteria) -> {
+                result.add(lookupCriteria.toString());
+            });
+            return result.toString();
+        }
+    }
+
+    private LookupCriteria<TreeItem> thisCriteria(final TreeItem item) {
+        return new LookupCriteria<TreeItem>() {
+
+            @Override
+            public boolean check(TreeItem control) {
+                return control == item;
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/ScrollableWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.widgets.Scrollable;
+import org.jemmy.Rectangle;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.env.Environment;
+
+/**
+ * Base wrapper for scrollable controls such as Table and Tree
+ *
+ * @author erikgreijus
+ * @param <T>
+ */
+@ControlType(Scrollable.class)
+public class ScrollableWrap<T extends Scrollable> extends ControlWrap<T> {
+
+    public ScrollableWrap(Environment env, T node) {
+        super(env, node);
+    }
+
+    /**
+     * Returns the screen bounds of this Scrollable
+     *
+     * @return A Rectangle describing the screen bounds of this Scrollable
+     */
+    @Override
+    public Rectangle getScreenBounds() {
+        return getScreenBounds(Scrollable.class.cast(getControl()), getEnvironment());
+    }
+
+    /**
+     * Returns the screen bounds of this Scrollable
+     *
+     * @param scrollable This Scrollable
+     * @param env The environment
+     * @return A Rectangle describing the screen bounds of this Scrollable
+     */
+    public static Rectangle getScreenBounds(Scrollable scrollable, Environment env) {
+        Rectangle res = getBounds(scrollable, env);
+        org.eclipse.swt.graphics.Point loc = getScreenLocation(scrollable, env);
+        res.x = loc.x;
+        res.y = loc.y;
+        return res;
+    }
+
+    /**
+     * Returns a rectangle describing the visible part of the supplied
+     * Scrollable.
+     *
+     * @see org.eclipse.swt.widgets.Scrollable#getClientArea()
+     * @param scrollable The Scrollable for which to get the client area
+     * @param env The Jemmy Environment
+     * @return A rectangle describing the visible part of this scrollable
+     */
+    public static Rectangle getBounds(final Scrollable scrollable, Environment env) {
+        GetAction<org.eclipse.swt.graphics.Rectangle> action = new GetAction<org.eclipse.swt.graphics.Rectangle>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(scrollable.getClientArea());
+            }
+
+            @Override
+            public String toString() {
+                return "Getting bounds (client area) for " + scrollable;
+            }
+        };
+        env.getExecutor().execute(env, true, action);
+        org.eclipse.swt.graphics.Rectangle res = action.getResult();
+        return new Rectangle(res.x, res.y, res.width, res.height);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/ShellWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.awt.Rectangle;
+import org.eclipse.swt.widgets.Shell;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.control.Property;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.ControlInterface;
+import org.jemmy.interfaces.MenuOwner;
+
+/**
+ *
+ * @author shura
+ */
+@ControlType(Shell.class)
+public class ShellWrap<T extends Shell> extends CompositeWrap<T> {
+
+    final SWTMenuOwner menuBar;
+
+    public ShellWrap(Environment env, T node) {
+        super(env, node);
+        menuBar = new SWTMenuOwner(this, true);
+    }
+
+    public static Rectangle getBounds(final Shell s, Environment env) {
+        GetAction<org.eclipse.swt.graphics.Rectangle> action = new GetAction<org.eclipse.swt.graphics.Rectangle>() {
+
+            public void run(Object... parameters) {
+                setResult(s.getBounds());
+            }
+
+            @Override
+            public String toString() {
+                return "Getting bounds for " + s;
+            }
+
+        };
+        env.getExecutor().execute(env, true, action);
+        org.eclipse.swt.graphics.Rectangle res = action.getResult();
+        return new Rectangle(res.x, res.y, res.width, res.height);
+    }
+
+    public static Rectangle getClientArea(final Shell s, Environment env) {
+        GetAction<org.eclipse.swt.graphics.Rectangle> action = new GetAction<org.eclipse.swt.graphics.Rectangle>() {
+
+            public void run(Object... parameters) {
+                setResult(s.getClientArea());
+            }
+
+            @Override
+            public String toString() {
+                return "Getting client area for " + s;
+            }
+
+        };
+        env.getExecutor().execute(env, true, action);
+        org.eclipse.swt.graphics.Rectangle res = action.getResult();
+        return new Rectangle(res.x, res.y, res.width, res.height);
+    }
+
+    @Property(Wrap.TEXT_PROP_NAME)
+    public String getText() {
+        return new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getText());
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> INTERFACE as(Class<INTERFACE> interfaceClass) {
+        if(MenuOwner.class.isAssignableFrom(interfaceClass)) {
+            return (INTERFACE) menuBar;
+        }
+        return super.as(interfaceClass);
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> boolean is(Class<INTERFACE> interfaceClass) {
+        if(MenuOwner.class.isAssignableFrom(interfaceClass)) {
+            return true;
+        }
+        return super.is(interfaceClass);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/Shells.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.Arrays;
+import java.util.List;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.DefaultWrapper;
+import org.jemmy.env.Environment;
+import org.jemmy.input.AWTRobotInputFactory;
+import org.jemmy.lookup.AbstractParent;
+import org.jemmy.lookup.ControlHierarchy;
+import org.jemmy.lookup.HierarchyLookup;
+import org.jemmy.lookup.Lookup;
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ *
+ * @author shura, erikgreijus
+ */
+public class Shells extends AbstractParent<Shell> {
+
+    public static final Shells SHELLS = new Shells();
+    private final Environment env;
+    private final ShellList shells;
+    final DefaultWrapper swtWrapper;
+
+    private Shells() {
+        this(new Environment(Environment.getEnvironment()));
+    }
+
+    private Shells(Environment env) {
+        this.env = env;
+        env.setExecutor(new SWTExecutor());
+        shells = new ShellList(env);
+        swtWrapper = new DefaultWrapper(env);
+        swtWrapper.addAnnotated(ShellWrap.class, ControlWrap.class,
+                CompositeWrap.class, TextWrap.class, TabFolderWrap.class,
+                ToolBarWrap.class, TableWrap.class, ListWrap.class, ComboWrap.class,
+                TreeWrap.class, CTabFolderWrap.class, CComboWrap.class, ScrollableWrap.class);
+        env.setInputFactory(new AWTRobotInputFactory());
+    }
+
+    public <ST extends Shell> Lookup<ST> lookup(Class<ST> controlClass, LookupCriteria<ST> criteria) {
+        return new HierarchyLookup(env, shells, swtWrapper, controlClass, criteria);
+    }
+
+    public Lookup<Shell> lookup(LookupCriteria<Shell> criteria) {
+        return lookup(getType(), criteria);
+    }
+
+    public Environment getEnvironment() {
+        return env;
+    }
+
+    public Class<Shell> getType() {
+        return Shell.class;
+    }
+
+    private static class ShellList implements ControlHierarchy {
+
+        Environment env;
+
+        public ShellList(Environment env) {
+            this.env = env;
+        }
+
+        public List<?> getControls() {
+            GetAction<Shell[]> action = new GetAction<Shell[]>() {
+
+                public void run(Object... parameters) {
+                    Display.getDefault().syncExec(new Runnable() {
+
+                        public void run() {
+                            try {
+                                setResult(Display.getDefault().getShells());
+                            } catch (SWTException e) {
+                                setResult(new Shell[0]);
+                            }
+                        }
+                    });
+                }
+            };
+            env.getExecutor().execute(env, true, action);
+            return Arrays.asList(action.getResult());
+        }
+
+        public List<?> getChildren(final Object subParent) {
+            if (!(subParent instanceof Shell)) {
+                return null;
+            }
+            GetAction<Shell[]> action = new GetAction<Shell[]>() {
+
+                public void run(Object... parameters) {
+                    Display.getDefault().syncExec(new Runnable() {
+
+                        public void run() {
+                            try {
+                                setResult(Shell.class.cast(subParent).getShells());
+                            } catch (SWTException e) {
+                                setResult(new Shell[0]);
+                            }
+                        }
+                    });
+                }
+            };
+            env.getExecutor().execute(env, true, action);
+            return Arrays.asList(action.getResult());
+        }
+
+        public Object getParent(Object child) {
+            //dunno how to do this
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/TabFolderWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.control.Property;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.interfaces.Selectable;
+import org.jemmy.interfaces.Selector;
+import org.jemmy.interfaces.TypeControlInterface;
+import org.jemmy.lookup.Lookup;
+
+/**
+ *
+ * @author shura, erikgreijus
+ * @param <T>
+ */
+@ControlType(TabFolder.class)
+public class TabFolderWrap<T extends TabFolder> extends ControlWrap<T> implements Selectable<String> {
+
+    private ItemParent<TabItem> items = null;
+    private TextItemSelector selector = null;
+
+    public TabFolderWrap(Environment env, T node) {
+        super(env, node);
+    }
+
+    @Override
+    public <TYPE, INTERFACE extends TypeControlInterface<TYPE>> INTERFACE as(Class<INTERFACE> interfaceClass, Class<TYPE> type) {
+        if (interfaceClass.equals(Parent.class) && TabItem.class.equals(type)) {
+            if (items == null) {
+                items = new ItemParent<TabItem>(this, TabItem.class) {
+
+                    @Override
+                    protected List<TabItem> getItems() {
+                        return Arrays.asList(new GetAction<TabItem[]>() {
+
+                            @Override
+                            public void run(Object... parameters) {
+                                setResult(getControl().getItems());
+                            }
+                        }.dispatch(getEnvironment()));
+                    }
+                };
+            }
+            return (INTERFACE) items;
+        }
+        return super.as(interfaceClass, type);
+    }
+
+    @Override
+    public <TYPE, INTERFACE extends TypeControlInterface<TYPE>> boolean is(Class<INTERFACE> interfaceClass, Class<TYPE> type) {
+        if (interfaceClass.equals(Parent.class) && TabItem.class.equals(type)) {
+            return true;
+        }
+        return super.is(interfaceClass, type);
+    }
+
+    public int getItemCount() {
+        return new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getItemCount());
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Property(Selectable.STATES_PROP_NAME)
+    public List<String> getStates() {
+        return new GetAction<List<String>>() {
+
+            @Override
+            public void run(Object... parameters) {
+                Lookup<TabItem> lookup = as(Parent.class, TabItem.class).lookup();
+                ArrayList<String> res = new ArrayList<String>();
+                for (int i = 0; i < lookup.size(); i++) {
+                    res.add(lookup.get(i).getText());
+                }
+                setResult(res);
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Property(Selectable.STATE_PROP_NAME)
+    public String getState() {
+        return new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getSelection()[0].getText());
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    public Selector<String> selector() {
+        if (selector == null) {
+            if (items == null) {
+                as(Parent.class, TabItem.class);
+            }
+            selector = new TextItemSelector(items);
+        }
+        return selector;
+    }
+
+    public Class<String> getType() {
+        return String.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/TableWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.control.Property;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.interfaces.Selectable;
+import org.jemmy.interfaces.Selector;
+import org.jemmy.interfaces.TypeControlInterface;
+
+/**
+ *
+ * @author shura
+ */
+@ControlType(Table.class)
+public class TableWrap<T extends Table> extends ScrollableWrap<T> implements Selectable<Integer> {
+
+    private ItemParent<TableItem> items = null;
+    private List<Integer> states = null;
+    private ItemParent<TableColumn> columns = null;
+    private IndexItemSelector selector = null;
+
+    public TableWrap(Environment env, T node) {
+        super(env, node);
+    }
+
+    @Override
+    public <TYPE, INTERFACE extends TypeControlInterface<TYPE>> INTERFACE as(Class<INTERFACE> interfaceClass, Class<TYPE> type) {
+        if (interfaceClass.equals(Parent.class) && TableItem.class.equals(type)) {
+            List<TableItem> itemList = Arrays.asList(new GetAction<TableItem[]>() {
+
+                @Override
+                public void run(Object... parameters) {
+                    setResult(getControl().getItems());
+                }
+            }.dispatch(getEnvironment()));
+            if (items == null) {
+                items = new ItemParent<TableItem>(this, TableItem.class) {
+
+                    @Override
+                    protected List<TableItem> getItems() {
+                        return Arrays.asList(new GetAction<TableItem[]>() {
+
+                            @Override
+                            public void run(Object... parameters) {
+                                setResult(getControl().getItems());
+                            }
+                        }.dispatch(getEnvironment()));
+                    }
+                };
+            }
+            return (INTERFACE) items;
+        }
+        if (interfaceClass.equals(Parent.class) && TableColumn.class.equals(type)) {
+            if (columns == null) {
+                columns = new ItemParent<TableColumn>(this, TableColumn.class) {
+
+                    @Override
+                    protected List<TableColumn> getItems() {
+                        return Arrays.asList(new GetAction<TableColumn[]>() {
+
+                            @Override
+                            public void run(Object... parameters) {
+                                setResult(getControl().getColumns());
+                            }
+                        }.dispatch(getEnvironment()));
+                    }
+                };
+            }
+            return (INTERFACE) columns;
+        }
+        return super.as(interfaceClass, type);
+    }
+
+    @Override
+    public <TYPE, INTERFACE extends TypeControlInterface<TYPE>> boolean is(Class<INTERFACE> interfaceClass, Class<TYPE> type) {
+        if (interfaceClass.equals(Parent.class) && TableItem.class.equals(type)) {
+            return true;
+        }
+        return super.is(interfaceClass, type);
+    }
+
+    public int getItemCount() {
+        return new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getItemCount());
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    public List<Integer> getStates() {
+        if (states == null) {
+            states = new ArrayList<Integer>();
+        }
+        int size = getItemCount();
+        if (states.size() != size) {
+            states.clear();
+            for (int i = 0; i < size; i++) {
+                states.add(i);
+            }
+        }
+        return states;
+    }
+
+    @Property(Selectable.STATE_PROP_NAME)
+    public Integer getState() {
+        return new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getSelectionIndex());
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    public Selector<Integer> selector() {
+        if (selector == null) {
+            if (items == null) {
+                as(Parent.class, TableItem.class);
+            }
+            selector = new IndexItemSelector(items);
+        }
+        return selector;
+    }
+
+    public Class<Integer> getType() {
+        return Integer.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/TextItemSelector.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.widgets.Item;
+import org.jemmy.interfaces.Selector;
+import org.jemmy.swt.lookup.ByTextItem;
+
+/**
+ *
+ * @author shura
+ */
+public class TextItemSelector implements Selector<String> {
+
+    private ItemParent<? extends Item> parent;
+
+    public TextItemSelector(ItemParent<? extends Item> parent) {
+        this.parent = parent;
+    }
+
+    public void select(String state) {
+        parent.lookup(new ByTextItem(state)).wrap().mouse().click();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/TextWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Text;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.control.Property;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Environment;
+import org.jemmy.input.SelectionText;
+import org.jemmy.interfaces.ControlInterface;
+import org.jemmy.interfaces.Focusable;
+
+/**
+ *
+ * @author shura, erikgreijus
+ * @param <T>
+ */
+@ControlType(Text.class)
+public class TextWrap<T extends Text> extends ControlWrap<T> implements Focusable {
+
+    class FocusableSelectionText extends SelectionText implements Focusable {
+        protected ClickFocus focuser;
+        private final TextWrap textWrap;
+
+        public FocusableSelectionText(TextWrap textWrap) {
+            super(textWrap);
+            this.textWrap = textWrap;
+        }
+
+        public double position() {
+            return textWrap.position();
+        }
+
+        public String text() {
+            return textWrap.text();
+        }
+
+        public String tooltip() {
+            return textWrap.tooltip();
+        }
+
+        public double anchor() {
+            return textWrap.anchor();
+        }
+
+        public ClickFocus focuser() {
+            if (focuser == null) {
+                focuser = new ClickFocus();
+            }
+            return focuser;
+        }
+    }
+
+    FocusableSelectionText text = new FocusableSelectionText(this) ;
+
+    public TextWrap(Environment env, T node) {
+        super(env, node);
+    }
+
+    @Property(Wrap.TEXT_PROP_NAME)
+    @Override
+    public String text() {
+        GetAction<String> action = new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getText());
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Property(Wrap.TOOLTIP_PROP_NAME)
+    public String tooltip() {
+        GetAction<String> action = new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getToolTipText());
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Property(Wrap.POSITION_PROP_NAME)
+    public Integer position() {
+        GetAction<Integer> action = new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) {
+                setResult(getControl().getCaretPosition());
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Property(SelectionText.SELECTION_ANCHOR_PROP_NAME)
+    public Integer anchor() {
+        GetAction<Integer> action = new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) {
+                Point selection = getControl().getSelection();
+                setResult((selection.x == getControl().getCaretPosition()) ?
+                    selection.y : selection.x);
+            }
+        };
+        getEnvironment().getExecutor().execute(getEnvironment(), true, action);
+        return action.getResult();
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> boolean is(Class<INTERFACE> interfaceClass) {
+        if(interfaceClass.isAssignableFrom(SelectionText.class)) {
+            return true;
+        }
+        if(interfaceClass.equals(Focusable.class)) {
+            return true;
+        }
+        return super.is(interfaceClass);
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> INTERFACE as(Class<INTERFACE> interfaceClass) {
+        if(interfaceClass.isAssignableFrom(SelectionText.class)) {
+            return (INTERFACE) text;
+        }
+        if(interfaceClass.isAssignableFrom(Focusable.class)) {
+            return (INTERFACE) text;
+        }
+        return super.as(interfaceClass);
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/ToolBarWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.control.Property;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.interfaces.Selectable;
+import org.jemmy.interfaces.Selector;
+import org.jemmy.interfaces.TypeControlInterface;
+import org.jemmy.lookup.Lookup;
+
+/**
+ *
+ * @author shura, erikgreijus
+ * @param <T>
+ */
+@ControlType(ToolBar.class)
+public class ToolBarWrap<T extends ToolBar> extends ControlWrap<T> implements Selectable<String> {
+
+    private ItemParent<ToolItem> items;
+    private ToolTipItemSelector selector;
+
+    public ToolBarWrap(Environment env, T node) {
+        super(env, node);
+        this.items = null;
+        this.selector = null;
+    }
+
+    @Override
+    public <TYPE, INTERFACE extends TypeControlInterface<TYPE>> INTERFACE as(Class<INTERFACE> interfaceClass, Class<TYPE> type) {
+        if (interfaceClass.equals(Parent.class) && ToolItem.class.equals(type)) {
+            if (items == null) {
+                items = new ItemParent<ToolItem>(this, ToolItem.class) {
+
+                    @Override
+                    protected List<ToolItem> getItems() {
+                        return Arrays.asList(new GetAction<ToolItem[]>() {
+
+                            @Override
+                            public void run(Object... parameters) {
+                                setResult(getControl().getItems());
+                            }
+                        }.dispatch(getEnvironment()));
+                    }
+                };
+            }
+            return (INTERFACE) items;
+        }
+        return super.as(interfaceClass, type);
+    }
+
+    @Override
+    public <TYPE, INTERFACE extends TypeControlInterface<TYPE>> boolean is(Class<INTERFACE> interfaceClass, Class<TYPE> type) {
+        if (interfaceClass.equals(Parent.class) && ToolItem.class.equals(type)) {
+            return true;
+        }
+        return super.is(interfaceClass, type);
+    }
+
+    @Property(Selectable.STATES_PROP_NAME)
+    public List<String> getStates() {
+        return new GetAction<List<String>>() {
+
+            @Override
+            public void run(Object... parameters) {
+                Lookup<ToolItem> lookup = as(Parent.class, ToolItem.class).lookup();
+                ArrayList<String> res = new ArrayList<String>();
+                for (int i = 0; i < lookup.size(); i++) {
+                    res.add(lookup.get(i).getToolTipText());
+                }
+                setResult(res);
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Property(Selectable.STATE_PROP_NAME)
+    public String getState() {
+        return new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) {
+                Lookup<ToolItem> lookup = as(Parent.class, ToolItem.class).lookup();
+                String selected = "No selection";
+                for (int i = 0; i < lookup.size(); i++) {
+                    if (lookup.get(i).getSelection()) {
+                        selected = lookup.get(i).getToolTipText();
+                        break;
+                    }
+                }
+                setResult(selected);
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    public Selector<String> selector() {
+        if (selector == null) {
+            if (items == null) {
+                as(Parent.class, ToolItem.class);
+            }
+            selector = new ToolTipItemSelector(items);
+        }
+        return selector;
+    }
+
+    public Class<String> getType() {
+        return String.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/ToolTipItemSelector.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.widgets.Item;
+import org.jemmy.interfaces.Selector;
+import org.jemmy.swt.lookup.ByToolTipItem;
+
+/**
+ *
+ * @author erikgreijus
+ */
+public class ToolTipItemSelector implements Selector<String> {
+
+    private final ItemParent<? extends Item> parent;
+
+    public ToolTipItemSelector(ItemParent<? extends Item> parent) {
+        this.parent = parent;
+    }
+
+    public void select(String state) {
+        parent.lookup(new ByToolTipItem(state)).wrap().mouse().click();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/TreeWrap.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.jemmy.Point;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.ControlType;
+import org.jemmy.control.Property;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Environment;
+import org.jemmy.input.KeyboardSelectable;
+import org.jemmy.input.KeyboardSelector;
+import org.jemmy.input.StringTree;
+import org.jemmy.interfaces.ControlInterface;
+import org.jemmy.interfaces.Focusable;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.interfaces.Selectable;
+import org.jemmy.interfaces.Selector;
+import org.jemmy.interfaces.TypeControlInterface;
+
+/**
+ *
+ * @author shura, erikgreijus
+ * @param <T>
+ */
+@ControlType(Tree.class)
+public class TreeWrap<T extends Tree> extends ScrollableWrap<T> implements KeyboardSelectable<String>, Focusable {
+
+    private KeyboardSelector<String> selector = null;
+    private ItemParent<TreeItem> items;
+    private SWTTree tree = null;
+
+    public TreeWrap(Environment env, T node) {
+        super(env, node);
+    }
+
+    private void addItems(TreeItem[] items, LinkedList<TreeItem> list) {
+        for (TreeItem item : items) {
+            list.add(item);
+            if (item.getExpanded()) {
+                addItems(item.getItems(), list);
+            }
+        }
+    }
+
+    public List<TreeItem> getItems() {
+        return new GetAction<List<TreeItem>>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                LinkedList<TreeItem> res = new LinkedList<>();
+                addItems(getControl().getItems(), res);
+                setResult(res);
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    public TreeItem getSelectedItem() {
+        return new GetAction<TreeItem>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                if (getControl().getSelection().length > 0) {
+                    setResult(getControl().getSelection()[0]);
+                } else {
+                    setResult(null);
+                }
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Override
+    public int selection() {
+        return new GetAction<Integer>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                if (getControl().getSelection().length > 0) {
+                    TreeItem selection = getControl().getSelection()[0];
+                    setResult(0);
+                    if (selection != null) {
+                        List<TreeItem> items = getItems();
+                        for (int i = 0; i < items.size(); i++) {
+                            if (items.get(i) == selection) {
+                                setResult(i);
+                            }
+                        }
+                    }
+                } else {
+                    setResult(0);
+                }
+
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Override
+    public boolean isVertical() {
+        return true;
+    }
+
+    public int index(TreeItem item) {
+        return getItems().indexOf(item);
+    }
+
+    @Override
+    public Selector<String> selector() {
+        if (selector == null) {
+            selector = new KeyboardSelector<>(this, this);
+        }
+        return selector;
+    }
+
+    @Override
+    public Class<String> getType() {
+        return String.class;
+    }
+
+    /**
+     * Click point for Tree (top of the visible part)
+     *
+     * @return The click point of this Tree
+     */
+    @Override
+    @Property(Wrap.CLICKPOINT_PROP_NAME)
+    public Point getClickPoint() {
+        return new Point(getScreenBounds().getWidth() / 2, 1);
+    }
+
+    @Override
+    public <TYPE, INTERFACE extends TypeControlInterface<TYPE>> INTERFACE as(Class<INTERFACE> interfaceClass, Class<TYPE> type) {
+        if (interfaceClass.equals(Parent.class) && TreeItem.class.equals(type)) {
+            if (items == null) {
+                items = new ItemParent<TreeItem>(this, TreeItem.class) {
+
+                    @Override
+                    protected List<TreeItem> getItems() {
+                        return TreeWrap.this.getItems();
+                    }
+                };
+            }
+            return (INTERFACE) items;
+        }
+        if (org.jemmy.interfaces.Tree.class.isAssignableFrom(interfaceClass)
+                && interfaceClass.isAssignableFrom(StringTree.class) && TreeItem.class.equals(type)) {
+            if (tree == null) {
+                tree = new SWTTree(this);
+            }
+            return (INTERFACE) tree;
+        }
+        return super.as(interfaceClass, type);
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> INTERFACE as(Class<INTERFACE> interfaceClass) {
+        if (org.jemmy.interfaces.Tree.class.isAssignableFrom(interfaceClass)
+                && interfaceClass.isAssignableFrom(StringTree.class)) {
+            if (tree == null) {
+                tree = new SWTTree(this);
+            }
+            return (INTERFACE) tree;
+        }
+        return super.as(interfaceClass);
+    }
+
+    @Override
+    public <TYPE, INTERFACE extends TypeControlInterface<TYPE>> boolean is(Class<INTERFACE> interfaceClass, Class<TYPE> type) {
+        if (interfaceClass.equals(Parent.class) && TreeItem.class.equals(type)) {
+            return true;
+        }
+        if (org.jemmy.interfaces.Tree.class.isAssignableFrom(interfaceClass)
+                && interfaceClass.isAssignableFrom(StringTree.class) && TreeItem.class.equals(type)) {
+            return true;
+        }
+        return super.is(interfaceClass, type);
+    }
+
+    @Override
+    public <INTERFACE extends ControlInterface> boolean is(Class<INTERFACE> interfaceClass) {
+        if (org.jemmy.interfaces.Tree.class.isAssignableFrom(interfaceClass)
+                && interfaceClass.isAssignableFrom(StringTree.class)) {
+            return true;
+        }
+        return super.is(interfaceClass);
+    }
+
+    @Override
+    public int index(String item) {
+        return getStates().indexOf(item);
+    }
+
+    @Property(Selectable.STATES_PROP_NAME)
+    @Override
+    public List<String> getStates() {
+        return new GetAction<List<String>>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                List<TreeItem> itms = getItems();
+                List<String> res = new ArrayList<>(itms.size());
+                itms.stream().forEach((i) -> {
+                    res.add(i.getText());
+                });
+                setResult(res);
+            }
+        }.dispatch(getEnvironment());
+    }
+
+    @Property(Selectable.STATE_PROP_NAME)
+    @Override
+    public String getState() {
+        return new GetAction<String>() {
+
+            @Override
+            public void run(Object... parameters) throws Exception {
+                setResult((getSelectedItem() == null) ? "" : getSelectedItem().getText());
+            }
+        }.dispatch(getEnvironment());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/Version.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+/**
+ *
+ * @author shura
+ */
+public class Version extends org.jemmy.Version {
+
+    public static final Version VERSION = new Version();
+
+    /**
+     *
+     */
+    public Version() {
+        super(Version.class.getPackage().getName());
+    }
+    /**
+     *
+     * @param args
+     */
+    public static void main(String[] args) {
+        System.out.println("JemmySWT version: " + VERSION.getVersion());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/jemmy.properties	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,3 @@
+version.major=0
+version.minor=9
+version.mini=6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByItemLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.Tree;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @param <T>
+ * @author klara, erikgreijus
+ */
+public class ByItemLookup<T extends Composite> extends QueueLookup<T> {
+
+    private final StringComparePolicy policy;
+    private final String text;
+
+    public ByItemLookup(String text) {
+        this(text, StringComparePolicy.SUBSTRING);
+    }
+
+    public ByItemLookup(String text, StringComparePolicy policy) {
+        this.policy = policy;
+        this.text = text;
+    }
+
+    @Override
+    public boolean doCheck(final T control) {
+        Object[] items = null;
+        if (Tree.class.isInstance(control)) {
+            items = Tree.class.cast(control).getItems();
+        } else if (ToolBar.class.isInstance(control)) {
+            items = ToolBar.class.cast(control).getItems();
+        } else if (CTabFolder.class.isInstance(control)) {
+            items = CTabFolder.class.cast(control).getItems();
+        } else if (TabFolder.class.isInstance(control)) {
+            items = TabFolder.class.cast(control).getItems();
+        } else if (Table.class.isInstance(control)) {
+            items = Table.class.cast(control).getItems();
+        } else if (Combo.class.isInstance(control)) {
+            items = Combo.class.cast(control).getItems();
+        } else {
+            System.err.println("Class " + control.getClass() + " does not match any supported class in ByItemLookup");
+            return false;
+        }
+        if (items instanceof Item[]) {
+            for (Item item : Item[].class.cast(items)) {
+                if (policy.compare(text, item.getText())) {
+                    return true;
+                } else {
+                    try {
+                        item.getClass().getMethod("getText", int.class);
+                        return ByItemStringsLookup.getTexts(item).stream().map((textElement) -> policy.compare(text, textElement)).anyMatch((matches) -> (matches));
+                    } catch (NoSuchMethodException e) {
+                        // silently ignore the error to not clutter the logs (not all objects implement the method)
+                    } catch (SecurityException e) {
+                        System.err.println("SecurityException when using reflection to get method 'getText(int)' from " + item);
+                        e.printStackTrace();
+                    }
+                }
+            }
+        } else if (items instanceof String[]) {
+            for (String stringItem : String[].class.cast(items)) {
+                if (policy.compare(text, stringItem)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "Text = " + text;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByItemStringsLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.swt.widgets.Item;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author erikgreijus
+ * @param <T>
+ */
+public class ByItemStringsLookup<T extends Item> extends QueueLookup<T> {
+
+    private final StringComparePolicy policy;
+    private final String text;
+
+    /**
+     *
+     * @param text The text to use for matching
+     */
+    public ByItemStringsLookup(String text) {
+        this(text, StringComparePolicy.SUBSTRING);
+    }
+
+    /**
+     *
+     * @param text The text to use for matching
+     * @param policy The policy to use when matching the text
+     */
+    public ByItemStringsLookup(String text, StringComparePolicy policy) {
+        this.policy = policy;
+        this.text = text;
+    }
+
+    public static <V extends Item> List<String> getTexts(V item) {
+        List<String> result = new ArrayList<>();
+        result.add(item.getText());
+        try {
+            Method getText = item.getClass().getMethod("getText", int.class);
+            Method getParent = item.getClass().getMethod("getParent");
+            Object parent = getParent.invoke(item);
+            Method getColumnCount = parent.getClass().getMethod("getColumnCount");
+            int columnCount = (int) getColumnCount.invoke(parent);
+            for (int i = 0; i < columnCount; i++) {
+                result.add((String) getText.invoke(item, i));
+            }
+        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+            System.err.println("Exception when using reflection to get additional text elements: " + ex.getMessage());
+            ex.printStackTrace();
+        }
+        return result;
+    }
+
+    @Override
+    public boolean doCheck(T control) {
+        // this lookup only supports objects with a getText(int) method
+        try {
+            control.getClass().getMethod("getText", int.class);
+            return getTexts(control).stream().map((textElement) -> policy.compare(text, textElement)).anyMatch((matches) -> (matches));
+        } catch (NoSuchMethodException e) {
+            System.err.println("Class " + control.getClass() + " isn't supported by " + this.getClass().getSimpleName() + " (i.e has no getText(int) method");
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "Text = " + text;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByItemToolTipLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import java.lang.reflect.Method;
+
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.ToolBar;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @param <T>
+ * @author klara
+ */
+public class ByItemToolTipLookup<T extends Composite> extends QueueLookup<T> {
+
+    private final StringComparePolicy policy;
+    private final String text;
+
+    public ByItemToolTipLookup(String text) {
+        this(text, StringComparePolicy.SUBSTRING);
+    }
+
+    protected ByItemToolTipLookup(String text, StringComparePolicy policy) {
+        this.policy = policy;
+        this.text = text;
+    }
+
+    public boolean doCheck(final T control) {
+        Item[] items = null;
+        if (ToolBar.class.isInstance(control)) {
+            items = ToolBar.class.cast(control).getItems();
+        } else if (CTabFolder.class.isInstance(control)) {
+            items = CTabFolder.class.cast(control).getItems();
+        } else if (TabFolder.class.isInstance(control)) {
+            items = TabFolder.class.cast(control).getItems();
+        } else {
+            System.err.println("Class " + control.getClass() + " does not match any supported class in ByItemLookup");
+            return false;
+        }
+        try {
+            for (Item item : items) {
+                Method mthd = item.getClass().getMethod("getToolTipText");
+                if (policy.compare(text, (String) mthd.invoke(item))) {
+                    return true;
+                }
+            }
+        } catch (Exception e) {
+            System.err.println("Exception when using reflection to get tooltip text from items of " + control);
+                e.printStackTrace();
+        }
+        return false;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByName.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.widgets.Widget;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author klara
+ */
+public class ByName<T extends Widget> extends ByStringQueueLookup<T> {
+
+    public ByName(String text) {
+        super(text);
+    }
+
+    public ByName(String text, StringComparePolicy policy) {
+        super(text, policy);
+    }
+
+    @Override
+    public String getText(final T control) {
+        return (String) control.getData("name");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByStringQueueLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @param <T>
+ * @author klara
+ */
+public abstract class ByStringQueueLookup<T> extends QueueLookup<T> {
+
+    private final StringComparePolicy policy;
+    private final String text;
+
+    /**
+     *
+     * @param text
+     */
+    protected ByStringQueueLookup(String text) {
+        this(text, StringComparePolicy.SUBSTRING);
+    }
+
+    /**
+     *
+     * @param text
+     * @param policy
+     */
+    protected ByStringQueueLookup(String text, StringComparePolicy policy) {
+        this.policy = policy;
+        this.text = text;
+    }
+
+    /**
+     *
+     * @param control
+     * @return
+     */
+    public abstract String getText(T control);
+
+    /**
+     *
+     * @param control
+     * @return
+     */
+    public boolean doCheck(T control) {
+        return policy.compare(text, getText(control));
+    }
+
+    @Override
+    public String toString() {
+        return "Text = " + text;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextButtonLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.widgets.Button;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author shura
+ */
+public class ByTextButtonLookup<T extends Button> extends ByStringQueueLookup<T> {
+
+    public ByTextButtonLookup(String text) {
+        super(text);
+    }
+
+    public ByTextButtonLookup(String text, StringComparePolicy policy) {
+        super(text, policy);
+    }
+
+    @Override
+    public String getText(final T control) {
+        return control.getText();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextControlLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import java.lang.reflect.Method;
+
+import org.eclipse.swt.widgets.Control;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author klara, erikgreijus
+ * @param <T>
+ */
+public class ByTextControlLookup<T extends Control> extends ByStringQueueLookup<T> {
+
+    public ByTextControlLookup(String text) {
+        super(text);
+    }
+
+    public ByTextControlLookup(String text, StringComparePolicy policy) {
+        super(text, policy);
+    }
+
+    @Override
+    public String getText(final T control) {
+        Method mthd;
+        try {
+            mthd = control.getClass().getMethod("getText");
+            return (String) mthd.invoke(control);
+        } catch (NoSuchMethodException e) {
+            // silently ignore the error to not clutter the logs (not all objects implement the method)
+        } catch (Exception e) {
+            System.err.println("Exception when using reflection to get text from " + control);
+                e.printStackTrace();
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextItem.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.widgets.Item;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author klara
+ */
+public class ByTextItem<T extends Item> extends ByStringQueueLookup<T> {
+
+    public ByTextItem(String text) {
+        super(text);
+    }
+
+    public ByTextItem(String text, StringComparePolicy policy) {
+        super(text, policy);
+    }
+
+    @Override
+    public String getText(final T control) {
+        return control.getText();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextLabelLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.widgets.Label;
+import org.jemmy.resources.StringComparePolicy;
+
+public class ByTextLabelLookup<T extends Label> extends ByStringQueueLookup<T> {
+
+    public ByTextLabelLookup(String text) {
+        super(text);
+    }
+
+    public ByTextLabelLookup(String text, StringComparePolicy policy) {
+        super(text, policy);
+    }
+
+    @Override
+    public String getText(final T control) {
+        return control.getText();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextShell.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.widgets.Shell;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author klara
+ */
+public class ByTextShell<T extends Shell> extends ByStringQueueLookup<T> {
+
+    public ByTextShell(String text) {
+        super(text);
+    }
+
+    public ByTextShell(String text, StringComparePolicy policy) {
+        super(text, policy);
+    }
+
+    @Override
+    public String getText(final T control) {
+        return control.getText();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTextTextLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.widgets.Text;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author shura
+ */
+public class ByTextTextLookup<T extends Text> extends ByStringQueueLookup<T> {
+
+    public ByTextTextLookup(String text) {
+        super(text);
+    }
+
+    public ByTextTextLookup(String text, StringComparePolicy policy) {
+        super(text, policy);
+    }
+
+    @Override
+    public String getText(final T control) {
+        return control.getText();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByToolTipControl.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.widgets.Control;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author klara
+ */
+public class ByToolTipControl<T extends Control> extends ByStringQueueLookup<T> {
+
+    public ByToolTipControl(String text) {
+        super(text);
+    }
+
+    public ByToolTipControl(String text, StringComparePolicy policy) {
+        super(text, policy);
+    }
+
+    @Override
+    public String getText(final T control) {
+        return control.getToolTipText();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByToolTipItem.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import java.lang.reflect.Method;
+
+import org.eclipse.swt.widgets.Item;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ *
+ * @author klara, erikgreijus
+ * @param <T>
+ */
+public class ByToolTipItem<T extends Item> extends ByStringQueueLookup<T> {
+
+    public ByToolTipItem(String text) {
+        super(text);
+    }
+
+    public ByToolTipItem(String text, StringComparePolicy policy) {
+        super(text, policy);
+    }
+
+    @Override
+    public String getText(final T control) {
+        Method mthd;
+        try {
+            mthd = control.getClass().getMethod("getToolTipText");
+            return (String) mthd.invoke(control);
+        } catch (NoSuchMethodException e) {
+            // silently ignore the error to not clutter the logs (not all objects implement the method)
+        } catch (Exception e) {
+            System.err.println("Exception when using reflection to get tooltip text from " + control);
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/ByTooltipButtonLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.widgets.Button;
+import org.jemmy.resources.StringComparePolicy;
+
+
+public class ByTooltipButtonLookup<T extends Button> extends ByStringQueueLookup<T> {
+    public ByTooltipButtonLookup(String text) {
+        super(text);
+    }
+
+    public ByTooltipButtonLookup(String text, StringComparePolicy policy) {
+        super(text, policy);
+    }
+
+    @Override
+    public String getText(final T control) {
+        return control.getToolTipText();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/CoordinateLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.widgets.Control;
+import org.jemmy.Rectangle;
+import org.jemmy.control.Wrap;
+import org.jemmy.lookup.RelativeCoordinateLookup;
+import org.jemmy.swt.ControlWrap;
+
+/**
+ *
+ * @author shura, erikgreijus
+ * @param <T>
+ */
+public class CoordinateLookup<T extends Control> extends RelativeCoordinateLookup<T> {
+
+    private final Wrap reference;
+
+    public CoordinateLookup(Wrap wrap, boolean includeControl, int hr, int vr) {
+        super(wrap, includeControl, hr, vr);
+        reference = wrap;
+    }
+
+    @Override
+    protected Rectangle getBounds(T control) {
+        if (!control.isDisposed()) {
+            return ControlWrap.getScreenBounds(control, reference.getEnvironment());
+        } else {
+            return null;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/QueueLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.jemmy.action.GetAction;
+import org.jemmy.env.Environment;
+import org.jemmy.lookup.LookupCriteria;
+import org.jemmy.swt.Shells;
+
+/**
+ *
+ * @author shura, erikgreijus
+ */
+public abstract class QueueLookup<T> implements LookupCriteria<T>{
+
+    private final Environment env;
+
+    public QueueLookup(Environment env) {
+        this.env = env;
+    }
+
+    public QueueLookup() {
+        this(Shells.SHELLS.getEnvironment());
+    }
+
+    public final boolean check(final T control) {
+        GetAction<Boolean> action = new GetAction<Boolean>() {
+
+            @Override
+            public void run(Object... parameters) {
+                if (!((org.eclipse.swt.widgets.Widget)control).isDisposed()) {
+                    setResult(doCheck(control));
+                } else {
+                    setResult(false);
+                }
+            }
+        };
+        env.getExecutor().execute(env, true, action);
+        return action.getResult();
+    }
+
+    protected abstract boolean doCheck(T control);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/src/org/jemmy/swt/lookup/WrapperLookup.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt.lookup;
+
+import org.eclipse.swt.widgets.Widget;
+import org.jemmy.env.Environment;
+import org.jemmy.lookup.LookupCriteria;
+import org.jemmy.swt.Shells;
+
+
+/**
+ *
+ * @author shura
+ */
+public class WrapperLookup<T extends Widget> extends QueueLookup<T> {
+
+    private final LookupCriteria<T> subCriteria;
+
+    public WrapperLookup(LookupCriteria<T> subCriteria) {
+        this(Shells.SHELLS.getEnvironment(), subCriteria);
+    }
+
+    public WrapperLookup(Environment env, LookupCriteria<T> subCriteria) {
+        super(env);
+        this.subCriteria = subCriteria;
+    }
+
+    @Override
+    protected boolean doCheck(T control) {
+        return subCriteria.check(control);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/test/TEST.ROOT	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,2 @@
+TestNG.dirs = .
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/test/org/jemmy/swt/Items.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.TreeItem;
+
+/**
+ *
+ * @author shura
+ */
+public class Items {
+
+    static Shell shell;
+
+    public static void main(String[] args) {
+        Display d = Display.getDefault();
+        shell = new Shell(d);
+        shell.setText("lala");
+        GridLayout gridLayout = new GridLayout();
+        gridLayout.numColumns = 1;
+        shell.setLayout(gridLayout);
+
+        final TabFolder tabFolder = new TabFolder(shell, SWT.BORDER);
+
+        //toolbar
+        TabItem tab = new TabItem(tabFolder, SWT.NONE);
+        tab.setText("Toolbar");
+        Composite itemsPanel = new Composite(tabFolder, SWT.BORDER);
+        ToolBar bar = new ToolBar(itemsPanel, SWT.BORDER);
+        for (int i = 0; i < 3; i++) {
+            final ToolItem item = new ToolItem(bar, SWT.PUSH);
+            item.setText("" + i);
+            item.addSelectionListener(new SelectionListener() {
+
+                @Override
+                public void widgetSelected(SelectionEvent arg0) {
+                    shell.setText("ToolItem " + item.getText());
+                }
+
+                @Override
+                public void widgetDefaultSelected(SelectionEvent arg0) {
+                    System.out.println("default selected " + arg0);
+                }
+            });
+        }
+        bar.pack();
+        tab.setControl(itemsPanel);
+
+        Menu popup = new Menu(bar);
+        createMenu(popup);
+        bar.setMenu(popup);
+
+        //table
+        TabItem tableTab = new TabItem(tabFolder, SWT.NONE);
+        tableTab.setText("Table");
+        Composite tablePanel = new Composite(tabFolder, SWT.BORDER);
+        tablePanel.setLayout(new GridLayout());
+        setupTable(tablePanel, "A");
+        setupTable(tablePanel, "B");
+        tableTab.setControl(tablePanel);
+
+        //tree
+        TabItem treeTab = new TabItem(tabFolder, SWT.NONE);
+        treeTab.setText("Tree");
+        Tree tree = new Tree(tabFolder, SWT.MULTI | SWT.BORDER);
+        tree.setHeaderVisible(true);
+        TreeColumn column1 = new TreeColumn(tree, SWT.LEFT);
+        column1.setText("Name");
+        column1.setWidth(200);
+        TreeColumn column2 = new TreeColumn(tree, SWT.CENTER);
+        column2.setText("Description");
+        column2.setWidth(200);
+        TreeColumn column3 = new TreeColumn(tree, SWT.RIGHT);
+        column3.setText("Value");
+        column3.setWidth(200);
+        TreeItem item0 = new TreeItem(tree, SWT.NULL);
+        item0.setText(0, "0");
+        item0.setText(1, "TreeItem 0");
+        item0.setText(2, "zero");
+        TreeItem item00 = new TreeItem(item0, SWT.NULL);
+        item00.setText(0, "00");
+        item00.setText(1, "TreeItem 00");
+        item00.setText(2, "zerozero");
+        TreeItem item01 = new TreeItem(item0, SWT.NULL);
+        item01.setText(0, "01");
+        item01.setText(1, "TreeItem 01");
+        item01.setText(2, "zeroone");
+        TreeItem item010 = new TreeItem(item01, SWT.NULL);
+        item010.setText(0, "010");
+        item010.setText(1, "TreeItem 010");
+        item010.setText(2, "zeroonezero");
+        TreeItem item1 = new TreeItem(tree, SWT.NULL);
+        item1.setText(0, "1");
+        item1.setText(1, "TreeItem 1");
+        item1.setText(2, "one");
+        TreeItem item10 = new TreeItem(item1, SWT.NULL);
+        item10.setText(0, "10");
+        item10.setText(1, "TreeItem 10");
+        item10.setText(2, "onezero");
+        TreeItem item11 = new TreeItem(item1, SWT.NULL);
+        item11.setText(0, "11");
+        item11.setText(1, "TreeItem 11");
+        item11.setText(2, "oneone");
+        tree.addSelectionListener(new SelectionListener() {
+
+            public void widgetSelected(SelectionEvent se) {
+                shell.setText("" + se.item);
+            }
+
+            public void widgetDefaultSelected(SelectionEvent se) {
+            }
+        });
+        treeTab.setControl(tree);
+
+        //buttons
+        TabItem buttonsTab = new TabItem(tabFolder, SWT.NONE);
+        Composite buttonsParent = new Composite(tabFolder, SWT.NONE);
+        buttonsParent.setData("name", "buttonsParent");
+        buttonsParent.setLayout(new RowLayout());
+        final Text lbl = new Text(buttonsParent, SWT.DEFAULT);
+        lbl.setText("click the button, please.");
+        lbl.setBounds(0, 0, 100, 30);
+        lbl.setEditable(true);
+        Button btn = new Button(buttonsParent, SWT.DEFAULT);
+        btn.setText("Click me!");
+        btn.addSelectionListener(new SelectionListener() {
+
+            public void widgetSelected(SelectionEvent arg0) {
+                lbl.setText("Now type some new text");
+            }
+
+            public void widgetDefaultSelected(SelectionEvent arg0) {
+                //System.out.println(arg0);
+            }
+        });
+        Combo combo = new Combo(buttonsParent, SWT.DEFAULT);
+        combo.add("one");
+        combo.add("two");
+        combo.add("three");
+        combo.add("four");
+        combo.select(0);
+        List list = new List(buttonsParent, SWT.DEFAULT);
+        list.add("one");
+        list.add("two");
+        list.add("three");
+        list.add("four");
+        list.select(0);
+        buttonsTab.setText("Buttons");
+        buttonsTab.setControl(buttonsParent);
+
+        tabFolder.pack();
+
+        Menu menuBar = new Menu(shell, SWT.BAR);
+        createMenu(menuBar);
+
+        shell.setMenuBar(menuBar);
+        shell.pack();
+        shell.open();
+        while (!shell.isDisposed()) {
+            if (!d.readAndDispatch()) {
+                d.sleep();
+            }
+        }
+        d.dispose();
+    }
+
+    private static void setupTable(Composite tablePanel, final String tableId) {
+        Table table = new Table(tablePanel, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
+        table.setLinesVisible(true);
+        table.setHeaderVisible(true);
+        GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+        data.heightHint = 200;
+        table.setLayoutData(data);
+        String[] titles = {"0", "1", "2"};
+        for (int i = 0; i < titles.length; i++) {
+            TableColumn column = new TableColumn(table, SWT.NONE);
+            column.setText(titles[i]);
+        }
+        int count = 3;
+        for (int i = 0; i < count; i++) {
+            TableItem item = new TableItem(table, SWT.NONE);
+            item.setText(0, "" + tableId + ":" + (count * i + 0));
+            item.setText(1, "" + tableId + ":" + (count * i + 1));
+            item.setText(2, "" + tableId + ":" + (count * i + 2));
+        }
+        for (int i = 0; i < titles.length; i++) {
+            table.getColumn(i).pack();
+        }
+        table.addListener(SWT.Selection, new Listener() {
+
+            public void handleEvent(Event event) {
+                shell.setText("" + event.item);
+            }
+        });
+    }
+
+    private static void createMenu(Menu menu) {
+        MenuItem menu0Item = new MenuItem(menu, SWT.CASCADE);
+        menu0Item.setText("menu0");
+        Menu menu0 = new Menu(menu);
+        menu0Item.setMenu(menu0);
+        MenuItem item00 = new MenuItem(menu0, SWT.DEFAULT);
+        item00.setText("item00");
+        new MenuSelectionListener(item00);
+        MenuItem itemDisabled = new MenuItem(menu0, SWT.DEFAULT);
+        itemDisabled.setText("disabled");
+        itemDisabled.setEnabled(false);
+        MenuItem item01 = new MenuItem(menu0, SWT.DEFAULT);
+        item01.setText("item01");
+        new MenuSelectionListener(item01);
+        MenuItem menu00Item = new MenuItem(menu0, SWT.CASCADE);
+        menu00Item.setText("menu00");
+        Menu menu00 = new Menu(menu);
+        menu00Item.setMenu(menu00);
+        MenuItem item000 = new MenuItem(menu00, SWT.DEFAULT);
+        item000.setText("item000");
+        new MenuSelectionListener(item000);
+
+        MenuItem menu1Item = new MenuItem(menu, SWT.CASCADE);
+        menu1Item.setText("menu1");
+        Menu menu1 = new Menu(menu);
+        menu1Item.setMenu(menu1);
+        MenuItem item10 = new MenuItem(menu1, SWT.DEFAULT);
+        item10.setText("item10");
+        new MenuSelectionListener(item10);
+        MenuItem item11 = new MenuItem(menu1, SWT.DEFAULT);
+        item11.setText("item11");
+        new MenuSelectionListener(item11);
+        MenuItem item12 = new MenuItem(menu1, SWT.DEFAULT);
+        item12.setText("item12");
+        new MenuSelectionListener(item12);
+    }
+
+    static class MenuSelectionListener implements SelectionListener {
+
+        public MenuSelectionListener(MenuItem item) {
+            this.item = item;
+            item.addSelectionListener(this);
+        }
+        MenuItem item;
+
+        public void widgetSelected(SelectionEvent se) {
+            shell.setText(item.getText() + " selected");
+        }
+
+        public void widgetDefaultSelected(SelectionEvent se) {
+        }
+    }
+
+    static class TreeSelectionListener implements Listener {
+
+        public TreeSelectionListener(TreeItem item) {
+            this.item = item;
+            item.addListener(SWT.Selection, this);
+        }
+        TreeItem item;
+
+        public void handleEvent(Event event) {
+            shell.setText(item.getText() + " selected");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/test/org/jemmy/swt/ItemsTest.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.jemmy.interfaces.Parent;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author shura
+ */
+public class ItemsTest {
+
+    public ItemsTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        new Thread(new Runnable() {
+
+            public void run() {
+                Items.main(null);
+            }
+        }).start();
+        Thread.sleep(2000);
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+    Wrap<? extends Shell> shell;
+
+    @BeforeMethod
+    public void setUp() {
+        shell = Shells.SHELLS.lookup().wrap();
+    }
+
+    @AfterMethod
+    public void tearDown() {
+    }
+
+    @Test
+    public void tabs() throws InterruptedException {
+        Wrap<? extends TabFolder> tabbedPane = Shells.SHELLS.lookup().
+                as(Parent.class, Control.class).lookup(TabFolder.class).wrap();
+        Parent<TabItem> prnt = tabbedPane.as(Parent.class, TabItem.class);
+        prnt.lookup(new ByTextItem<TabItem>("Table")).wrap().mouse().click();
+        prnt.lookup().wrap().mouse().click();
+    }
+
+    private <T extends Control> Wrap<? extends T> select(String tab, Class<T> cls) {
+        Parent<Control> parent = shell.as(Parent.class, Control.class);
+        Wrap<? extends TabFolder> tabbedPane = parent.lookup(TabFolder.class).wrap();
+        Parent<TabItem> prnt = tabbedPane.as(Parent.class, TabItem.class);
+        prnt.lookup(new ByTextItem<TabItem>(tab)).wrap().mouse().click();
+        return parent.lookup(cls).wrap();
+    }
+
+    @Test
+    public void tool() throws InterruptedException {
+        Parent<ToolItem> tb = select("Toolbar", ToolBar.class).as(Parent.class,
+                ToolItem.class);
+        tb.lookup(new ByTextItem<ToolItem>("1")).wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "ToolItem 1");
+        tb.lookup(new ByTextItem<ToolItem>("2")).wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "ToolItem 2");
+        tb.lookup().wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "ToolItem 0");
+    }
+
+    @Test
+    public void table() throws InterruptedException {
+        Parent<TableItem> tb = select("Table", Table.class).as(Parent.class,
+                TableItem.class);
+        tb.lookup().wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TableItem {A:0}");
+        tb.lookup(new ByTextItem<TableItem>("3")).wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TableItem {A:3}");
+        tb.lookup(new ByTextItem<TableItem>("6")).wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TableItem {A:6}");
+    }
+
+    @Test
+    public void tableByItem() throws InterruptedException {
+        select("Table", Table.class).as(Parent.class,
+                TableItem.class);
+        Parent<Control> parent = shell.as(Parent.class, Control.class);
+        Wrap<? extends Table> tableB = parent.lookup(Table.class, new ByItemLookup<Table>("B:0")).wrap();
+        Parent<TableItem> tb = tableB.as(Parent.class, TableItem.class);
+
+        tb.lookup(new ByTextItem<TableItem>("0")).wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TableItem {B:0}");
+        tb.lookup(new ByTextItem<TableItem>("3")).wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TableItem {B:3}");
+        tb.lookup(new ByTextItem<TableItem>("6")).wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TableItem {B:6}");
+    }
+
+    @Test
+    public void tree() throws InterruptedException {
+        Wrap<? extends Tree> tree = select("Tree", Tree.class);
+        Parent<TreeItem> tb = tree.as(Parent.class,
+                TreeItem.class);
+        tb.lookup().wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TreeItem {0}");
+        tb.lookup(new ByTextItem<TreeItem>("1")).wrap().mouse().click(1);
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TreeItem {1}");
+        if (System.getProperty("os.name").contains("Windows")) {
+            tree.keyboard().pushKey(KeyboardButtons.RIGHT);
+        } else {
+            tree.keyboard().typeChar('+');
+        }
+        tb.lookup(new ByTextItem<TreeItem>("11")).wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TreeItem {11}");
+        tb.lookup(new ByTextItem<TreeItem>("0")).wrap().mouse().click(1);
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TreeItem {0}");
+        if (System.getProperty("os.name").contains("Windows")) {
+            tree.keyboard().pushKey(KeyboardButtons.RIGHT);
+        } else {
+            tree.keyboard().typeChar('+');
+        }
+        tb.lookup(new ByTextItem<TreeItem>("01")).wrap().mouse().click(1);
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TreeItem {01}");
+        if (System.getProperty("os.name").contains("Windows")) {
+            tree.keyboard().pushKey(KeyboardButtons.RIGHT);
+        } else {
+            tree.keyboard().typeChar('+');
+        }
+        tb.lookup(new ByTextItem<TreeItem>("010")).wrap().mouse().click();
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "TreeItem {010}");
+    }
+
+    @Test
+    public void columns() throws InterruptedException {
+        Parent<TableColumn> tb = select("Table", Table.class).as(Parent.class,
+                TableColumn.class);
+        tb.lookup().wrap().waitProperty(Wrap.TEXT_PROP_NAME, "0");
+        tb.lookup(new ByTextItem<TableColumn>("1")).wait(1);
+    }
+
+    @Test
+    public void dump() throws InterruptedException {
+        shell.as(Parent.class, Control.class).lookup().wait(5).dump(System.out);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/test/org/jemmy/swt/MenuTest.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.ToolBar;
+import org.jemmy.Point;
+import org.jemmy.control.Wrap;
+import org.jemmy.input.StringMenuOwner;
+import org.jemmy.input.StringPopupOwner;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.interfaces.PopupOwner;
+import org.jemmy.interfaces.Selectable;
+import org.jemmy.resources.StringComparePolicy;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author shura
+ */
+public class MenuTest {
+
+    public MenuTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        new Thread(new Runnable() {
+
+            public void run() {
+                Items.main(null);
+            }
+        }).start();
+        Thread.sleep(2000);
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    static Wrap<? extends Shell> shell;
+
+    @BeforeMethod
+    public void setUp() {
+        shell = Shells.SHELLS.lookup().wrap();
+        ((Selectable)shell.as(Parent.class, Control.class).lookup(TabFolder.class).as(Selectable.class)).selector().select("Toolbar");
+    }
+
+    @AfterMethod
+    public void tearDown() {
+    }
+    String[][] menus = new String[][]{
+        {"menu1", "item10"},
+        {"menu0", "item00"},
+        {"menu1", "item11"},
+        {"menu0", "menu00", "item000"},
+        {"menu1", "item12"},
+        {"menu0", "item01"},};
+
+    @Test
+    public void bar() throws InterruptedException {
+        for (String[] item : menus) {
+            shell.as(StringMenuOwner.class).push(item);
+            shell.waitProperty(Wrap.TEXT_PROP_NAME, item[item.length - 1] + " selected");
+        }
+    }
+
+    @Test
+    public void popup() throws InterruptedException {
+        Wrap<? extends ToolBar> toolbar = shell.as(Parent.class, Control.class).
+                lookup(ToolBar.class).wrap();
+        for (String[] item : menus) {
+            toolbar.as(StringPopupOwner.class).push(PopupOwner.CENTER, item);
+            shell.waitProperty(Wrap.TEXT_PROP_NAME, item[item.length - 1] + " selected");
+        }
+    }
+
+    @Test
+    public void popupPoint() throws InterruptedException {
+        Wrap<? extends ToolBar> toolbar = shell.as(Parent.class, Control.class).
+                lookup(ToolBar.class).wrap();
+        toolbar.as(StringPopupOwner.class).push(new Point(1, 1), menus[0]);
+        toolbar.as(StringPopupOwner.class).push(new Point(1, 1), menus[3]);
+    }
+
+    @Test
+    public void bySubString() {
+        StringMenuOwner menu = shell.as(StringMenuOwner.class);
+        menu.setPolicy(StringComparePolicy.SUBSTRING);
+        menu.push("0", "menu", "");
+        shell.waitProperty(Wrap.TEXT_PROP_NAME, "item000 selected");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/test/org/jemmy/swt/PushButtonTest.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Text;
+import org.jemmy.control.Wrap;
+import org.jemmy.input.SelectionText;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.interfaces.Selectable;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertEquals;
+
+/**
+ *
+ * @author shura
+ */
+public class PushButtonTest {
+
+    private static Parent<Control> shell;
+    private static Parent<Control> buttonsParent;
+
+    public PushButtonTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        new Thread(new Runnable() {
+
+            public void run() {
+                Items.main(null);
+            }
+        }).start();
+        Thread.sleep(2000);
+
+        shell = Shells.SHELLS.lookup().as(Parent.class, Control.class);
+        shell.lookup(TabFolder.class).as(Selectable.class).selector().select("Buttons");
+        buttonsParent = shell.lookup(Composite.class, new ByName<Composite>("buttonsParent")).as(Parent.class, Control.class);
+   }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @BeforeMethod
+    public void setUp() throws InterruptedException {
+    }
+
+    @AfterMethod
+    public void tearDown() {
+    }
+
+    @Test
+    public void push() throws InterruptedException {
+        Wrap<? extends Text> field = buttonsParent.
+                lookup(Text.class, new ByTextTextLookup<Text>("button")).
+                wrap();
+        buttonsParent.lookup().
+                lookup(Button.class).
+                wrap().mouse().click();
+        field.getEnvironment().setTimeout(Wrap.WAIT_STATE_TIMEOUT, 20000);
+        field.waitProperty(Wrap.TEXT_PROP_NAME, "Now type some new text");
+    }
+
+    @Test
+    public void type() throws InterruptedException {
+        Wrap<? extends Text> field = buttonsParent.
+                lookup(Text.class, new ByTextTextLookup<Text>("click the button")).
+                wrap();
+        SelectionText text = field.as(SelectionText.class);
+        text.clear();
+        text.type("Now press the field");
+        text.select("field");
+        text.type("button again");
+        assertTrue(field.as(org.jemmy.interfaces.Text.class).text().
+                contains("again"));
+    }
+
+    @Test
+    public void list() throws InterruptedException {
+        Wrap<? extends List> list = buttonsParent.
+                lookup(List.class).wrap();
+        assertEquals(list.as(Selectable.class).getStates().size(), 4);
+        list.as(Selectable.class).selector().select("three");
+        assertEquals(list.as(Selectable.class).getState(), "three");
+    }
+
+    @Test
+    public void combo() throws InterruptedException {
+        Wrap<? extends List> list = buttonsParent.
+                lookup(List.class).wrap();
+        assertEquals(list.as(Selectable.class).getStates().size(), 4);
+        list.as(Selectable.class).selector().select("three");
+        assertEquals(list.as(Selectable.class).getState(), "three");
+    }
+
+    @Test
+    public void coordinatesLookup() throws InterruptedException {
+        Wrap<? extends Button> btt = buttonsParent.lookup(Button.class).wrap();
+        //find text field to the left
+        buttonsParent.lookup(Text.class, new CoordinateLookup<Text>(btt, false, -1, 0)).wait(1);
+        //find combo to the right
+        buttonsParent.lookup(Combo.class, new CoordinateLookup<Combo>(btt, false , 1, 0)).wait(1);
+        //find list
+        buttonsParent.lookup(List.class, new CoordinateLookup<List>(btt, true, 2, 0)).wait(1);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/test/org/jemmy/swt/Sample.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ *
+ * @author shura
+ */
+public class Sample {
+
+    public static void main(String[] args) {
+        //Creates a new display object for the example to go into
+        Display display = Display.getDefault();
+        //Creates a new shell object
+        final Shell shell = new Shell(display);
+        //Sets the layout for the shell
+        shell.setLayout(new RowLayout());
+        final Text lbl = new Text(shell, SWT.DEFAULT);
+        lbl.setText("click the button, please.");
+        lbl.setBounds(0, 0, 100, 30);
+        lbl.setEditable(true);
+        Button btn = new Button(shell, SWT.DEFAULT);
+        btn.setText("Click me!");
+        btn.addSelectionListener(new SelectionListener() {
+
+            public void widgetSelected(SelectionEvent arg0) {
+                lbl.setText("Now type some new text");
+                System.out.println(shell.getLocation());
+            }
+
+            public void widgetDefaultSelected(SelectionEvent arg0) {
+                //System.out.println(arg0);
+            }
+        });
+        Combo combo = new Combo(shell, SWT.DEFAULT);
+        combo.add("one");
+        combo.add("two");
+        combo.add("three");
+        combo.add("four");
+        combo.select(0);
+        List list = new List(shell, SWT.DEFAULT);
+        list.add("one");
+        list.add("two");
+        list.add("three");
+        list.add("four");
+        list.select(0);
+        //Creates the control example - see import statement for location.
+        shell.setText("Control Example");
+        shell.setBounds(100, 100, 300, 200);
+        shell.open();
+        while (!shell.isDisposed()) {
+            if (!display.readAndDispatch()) {
+                display.sleep();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/test/org/jemmy/swt/SelectableTest.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.Table;
+import org.jemmy.interfaces.Selectable;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Control;
+import org.jemmy.interfaces.Parent;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author shura
+ */
+public class SelectableTest {
+
+    public SelectableTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        new Thread(new Runnable() {
+
+            public void run() {
+                Items.main(null);
+            }
+        }).start();
+        Thread.sleep(2000);
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    Parent<Control> shell;
+
+    @BeforeMethod
+    public void setUp() {
+        shell = Shells.SHELLS.lookup().as(Parent.class, Control.class);
+    }
+
+    @AfterMethod
+    public void tearDown() {
+    }
+
+    @Test
+    public void tab() {
+        Wrap<? extends TabFolder> tab = shell.lookup(TabFolder.class).wrap();
+        Selectable tabs = tab.as(Selectable.class);
+        tabs.selector().select("Toolbar");
+        tab.waitProperty(Selectable.STATE_PROP_NAME, "Toolbar");
+        tabs.selector().select("Table");
+        tab.waitProperty(Selectable.STATE_PROP_NAME, "Table");
+    }
+
+    @Test
+    public void table() {
+        shell.lookup(TabFolder.class).as(Selectable.class).selector().select("Table");
+        Wrap<? extends Table> table = shell.lookup(Table.class).wrap();
+        Selectable<Integer> rows = table.as(Selectable.class, Integer.class);
+        rows.selector().select(1);
+        table.waitProperty(Selectable.STATE_PROP_NAME, 1);
+        rows.selector().select(2);
+        table.waitProperty(Selectable.STATE_PROP_NAME, 2);
+        rows.selector().select(0);
+        table.waitProperty(Selectable.STATE_PROP_NAME, 0);
+    }
+
+    @Test
+    public void tree() {
+        shell.lookup(TabFolder.class).as(Selectable.class).selector().select("Tree");
+        Wrap<? extends Tree> tree = shell.lookup(Tree.class).wrap();
+        Selectable<String> rows = tree.as(Selectable.class, String.class);
+        rows.selector().select("1");
+        tree.waitProperty(Selectable.STATE_PROP_NAME, "1");
+        if (System.getProperty("os.name").contains("Windows")) {
+            tree.keyboard().pushKey(KeyboardButtons.RIGHT);
+        } else {
+            tree.keyboard().typeChar('+');
+        }
+        rows.selector().select("11");
+        tree.waitProperty(Selectable.STATE_PROP_NAME, "11");
+        rows.selector().select("0");
+        tree.waitProperty(Selectable.STATE_PROP_NAME, "0");
+        if (System.getProperty("os.name").contains("Windows")) {
+            tree.keyboard().pushKey(KeyboardButtons.RIGHT);
+        } else {
+            tree.keyboard().typeChar('+');
+        }
+        rows.selector().select("01");
+        tree.waitProperty(Selectable.STATE_PROP_NAME, "01");
+        if (System.getProperty("os.name").contains("Windows")) {
+            tree.keyboard().pushKey(KeyboardButtons.RIGHT);
+        } else {
+            tree.keyboard().typeChar('+');
+        }
+        rows.selector().select("010");
+        tree.waitProperty(Selectable.STATE_PROP_NAME, "010");
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/test/org/jemmy/swt/TestBrowser.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+import java.awt.AWTException;
+
+/**
+ *
+ * @author shura
+ */
+public class TestBrowser {
+    public static void main(String[] args) throws AWTException {
+        new Thread(new Runnable() {
+
+            public void run() {
+                Sample.main(null);
+            }
+        }).start();
+        new Thread(new Runnable() {
+
+            public void run() {
+                Items.main(null);
+            }
+        }).start();
+        Browser.main(null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/JemmySWT/test/org/jemmy/swt/TreeTest.java	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.swt;
+
+
+import java.io.FileNotFoundException;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.jemmy.control.Wrap;
+import org.jemmy.input.StringTree;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.interfaces.Selectable;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author shura
+ */
+public class TreeTest {
+
+    public TreeTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        new Thread(new Runnable() {
+
+            public void run() {
+                Items.main(null);
+            }
+        }).start();
+        Thread.sleep(2000);
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+    Parent<Control> shell;
+
+    @BeforeMethod
+    public void setUp() {
+        shell = Shells.SHELLS.lookup().as(Parent.class, Control.class);
+    }
+
+    @AfterMethod
+    public void tearDown() {
+    }
+    String[][] trees = new String[][]{
+        {"zero", "zeroone", "zeroonezero"},
+        {"1", "TreeItem 10"},
+        {"TreeItem 0", "zeroone", "TreeItem 010"},
+        {"1", "10"},
+        {"0", "00"},
+        {"1", "11"},
+        {"0", "01", "010"},
+        {"0", "01"},
+        {"one"}
+    };
+
+    @Test
+    public void tree() throws InterruptedException, FileNotFoundException {
+        shell.lookup(TabFolder.class).as(Selectable.class).selector().select("Tree");
+        final Wrap<? extends Tree> tree = shell.lookup(Tree.class).wrap();
+        for (String[] path : trees) {
+            tree.as(StringTree.class, TreeItem.class).select(path);
+        }
+        Thread.sleep(1000);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/make/jemmy-v3-swt-ii/.idea/compiler.xml	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <wildcardResourcePatterns>
+      <entry name="!?*.java" />
+      <entry name="!?*.form" />
+      <entry name="!?*.class" />
+      <entry name="!?*.groovy" />
+      <entry name="!?*.scala" />
+      <entry name="!?*.flex" />
+      <entry name="!?*.kt" />
+      <entry name="!?*.clj" />
+    </wildcardResourcePatterns>
+  </component>
+</project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/make/jemmy-v3-swt-ii/.idea/copyright/Oracle.xml	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,6 @@
+<component name="CopyrightManager">
+  <copyright>
+    <option name="notice" value="Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.&#10;DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.&#10;&#10;This code is free software; you can redistribute it and/or modify it&#10;under the terms of the GNU General Public License version 2 only, as&#10;published by the Free Software Foundation.&#10;&#10;This code is distributed in the hope that it will be useful, but WITHOUT&#10;ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or&#10;FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License&#10;version 2 for more details (a copy is included in the LICENSE file that&#10;accompanied this code).&#10;&#10;You should have received a copy of the GNU General Public License version&#10;2 along with this work; if not, write to the Free Software Foundation,&#10;Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.&#10;&#10;Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA&#10;or visit www.oracle.com if you need additional information or have any&#10;questions." />
+    <option name="myName" value="Oracle" />
+  </copyright>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/make/jemmy-v3-swt-ii/.idea/encodings.xml	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding">
+    <file url="PROJECT" charset="UTF-8" />
+  </component>
+</project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/make/jemmy-v3-swt-ii/.idea/misc.xml	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_9" default="true" project-jdk-name="1.9" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/make/jemmy-v3-swt-ii/.idea/modules.xml	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/swt/swt.iml" filepath="$PROJECT_DIR$/swt/swt.iml" />
+    </modules>
+  </component>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWT/make/jemmy-v3-swt-ii/swt/swt.iml	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../JemmySWT/src">
+      <sourceFolder url="file://$MODULE_DIR$/../../../JemmySWT/src" isTestSource="false" />
+    </content>
+    <content url="file://$MODULE_DIR$/../../../JemmySWT/test">
+      <sourceFolder url="file://$MODULE_DIR$/../../../JemmySWT/test" isTestSource="true" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" scope="TEST" name="testng" level="application" />
+    <orderEntry type="library" name="JemmyAWTInput" level="project" />
+    <orderEntry type="library" name="JemmyBrowser" level="project" />
+    <orderEntry type="library" name="JemmyCore" level="project" />
+    <orderEntry type="library" name="swt:swt-macosx:3.0m7" level="project" />
+  </component>
+</module>
\ No newline at end of file
--- a/core/JemmyAWTInput/build.xml	Tue Jan 09 11:03:57 2018 -0800
+++ b/core/JemmyAWTInput/build.xml	Mon Jan 29 10:53:15 2018 -0800
@@ -22,7 +22,7 @@
  questions.
  -->
 <project name="jemmy-awt-input" default="compile" basedir=".">
-    <import file="${basedir}/../make/build_template.xml"/>
+    <import file="${basedir}/../../make/build_template.xml"/>
     <property name="core.jar" location="../JemmyCore/build/JemmyCore.jar"/>
     <property name="version.file" value="org/jemmy/input/jemmy.properties"/>
     <property name="version.class" value="org.jemmy.input.Version"/>
--- a/core/JemmyBrowser/build.xml	Tue Jan 09 11:03:57 2018 -0800
+++ b/core/JemmyBrowser/build.xml	Mon Jan 29 10:53:15 2018 -0800
@@ -22,7 +22,7 @@
  questions.
  -->
 <project name="jemmy-browser" default="compile" basedir=".">
-    <import file="${basedir}/../make/build_template.xml"/>
+    <import file="${basedir}/../../make/build_template.xml"/>
     <property name="core.jar" location="../JemmyCore/build/JemmyCore.jar"/>
     <property name="version.file" value="org/jemmy/browser/jemmy.properties"/>
     <property name="version.class" value="org.jemmy.browser.Version"/>
--- a/core/JemmyCore/build.xml	Tue Jan 09 11:03:57 2018 -0800
+++ b/core/JemmyCore/build.xml	Mon Jan 29 10:53:15 2018 -0800
@@ -22,7 +22,7 @@
  questions.
  -->
 <project name="jemmy-core" default="compile" basedir=".">
-    <import file="${basedir}/../make/build_template.xml"/>
+    <import file="${basedir}/../../make/build_template.xml"/>
     <property name="version.file" value="org/jemmy/jemmy.properties"/>
     <property name="version.class" value="org.jemmy.Version"/>
     <property name="dependencies.classpath" value=""/>
--- a/core/make/build_template.xml	Tue Jan 09 11:03:57 2018 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
- This code is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License version 2 only, as
- published by the Free Software Foundation.
-
- This code is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- version 2 for more details (a copy is included in the LICENSE file that
- accompanied this code).
-
- You should have received a copy of the GNU General Public License version
- 2 along with this work; if not, write to the Free Software Foundation,
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- or visit www.oracle.com if you need additional information or have any
- questions.
- -->
-<project name="jemmy.v3.template">
-    <basename file="${basedir}" property="jemmy.project.name"/>
-    <property name="src.dir" location="${basedir}/src"/>
-    <property name="test.dir" location="${basedir}/test"/>
-    <property name="build.dir" location="${basedir}/build"/>
-    <property name="build.classes.dir" location="${build.dir}/classes"/>
-    <property name="build.test.dir" location="${build.dir}/test"/>
-    <property name="dist.jar" location="${build.dir}/${jemmy.project.name}.jar"/>
-    <property name="test.list" location="${build.dir}/testlist"/>
-    <property name="test.workdir" location="${build.dir}/test_wd"/>
-    <property name="test.report" location="${build.dir}/test_report"/>
-    <target name="timestamp" unless="buildnumber">
-        <tstamp>
-            <format property="buildnumber" pattern="yyyyMMdd"/>
-        </tstamp>
-    </target>
-    <target name="build-dependencies" depends="check-dependecies-impl"
-            unless="dependencies.are.built">
-        <antcall target="build-dependecies-impl"/>
-    </target>
-    <target name="compile" depends="timestamp,build-dependencies">
-        <mkdir dir="${build.classes.dir}"/>
-        <javac srcdir="${src.dir}" classpath="${dependencies.classpath}" destdir="${build.classes.dir}" debug="on" includeantruntime="false"/>
-        <copy file="${src.dir}/${version.file}" tofile="${build.classes.dir}/${version.file}"/>
-        <echo message="build=${buildnumber}" file="${build.classes.dir}/${version.file}" append="true"/>
-    </target>
-    <target name="compile-test" depends="compile">
-        <fail message="Please specify jtreg.home" unless="jtreg.home"/>
-        <mkdir dir="${build.test.dir}"/>
-        <javac srcdir="${test.dir}" destdir="${build.test.dir}" debug="on" includeantruntime="false"
-               classpath="${build.classes.dir}:${dependencies.classpath}:${jtreg.home}/lib/testng.jar"/>
-    </target>
-    <target name="find-tests" unless="tests">
-        <fileset id="testset" dir="${test.dir}">
-            <include name="**/*Test.java" />
-        </fileset>
-        <pathconvert pathsep="${line.separator}" property="testlist" refid="testset">
-            <globmapper from="${test.dir}/*" to="*"/>
-        </pathconvert>
-        <echo file="${test.list}">${testlist}</echo>
-        <property name="tests" value="@${test.list}"/>
-    </target>
-    <target name="test" depends="compile-test,find-tests">
-        <exec executable="${jtreg.home}/bin/jtreg">
-            <arg value="-cpa:${build.classes.dir}:${dependencies.classpath}"/>
-            <arg value="-w:${test.workdir}"/>
-            <arg value="-r:${test.report}"/>
-            <arg value="-conc:1"/>
-            <arg value="-ovm"/>
-            <arg value="-v:default"/>
-            <arg value="-dir:test"/>
-            <arg value="${tests}"/>
-        </exec>
-    </target>
-    <target name="full-test" depends="test-dependecies-impl, test"/>
-    <target name="jar" depends="compile">
-        <mkdir dir="${build.dir}"/>
-        <jar jarfile="${dist.jar}" basedir="${build.classes.dir}">
-            <manifest>
-                <attribute name="Main-Class" value="${version.class}"/>
-            </manifest>
-        </jar>
-    </target>
-    <target name="clean">
-        <delete dir="${build.dir}"/>
-    </target>
-</project>
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/build_template.xml	Mon Jan 29 10:53:15 2018 -0800
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+ -->
+<project name="jemmy.v3.template">
+    <basename file="${basedir}" property="jemmy.project.name"/>
+    <property name="src.dir" location="${basedir}/src"/>
+    <property name="test.dir" location="${basedir}/test"/>
+    <property name="build.dir" location="${basedir}/build"/>
+    <property name="build.classes.dir" location="${build.dir}/classes"/>
+    <property name="build.test.dir" location="${build.dir}/test"/>
+    <property name="dist.jar" location="${build.dir}/${jemmy.project.name}.jar"/>
+    <property name="test.list" location="${build.dir}/testlist"/>
+    <property name="test.workdir" location="${build.dir}/test_wd"/>
+    <property name="test.report" location="${build.dir}/test_report"/>
+    <target name="timestamp" unless="buildnumber">
+        <tstamp>
+            <format property="buildnumber" pattern="yyyyMMdd"/>
+        </tstamp>
+    </target>
+    <target name="build-dependencies" depends="check-dependecies-impl"
+            unless="dependencies.are.built">
+        <antcall target="build-dependecies-impl"/>
+    </target>
+    <target name="compile" depends="timestamp,build-dependencies">
+        <mkdir dir="${build.classes.dir}"/>
+        <javac srcdir="${src.dir}" classpath="${dependencies.classpath}" destdir="${build.classes.dir}" debug="on" includeantruntime="false"/>
+        <copy file="${src.dir}/${version.file}" tofile="${build.classes.dir}/${version.file}"/>
+        <echo message="build=${buildnumber}" file="${build.classes.dir}/${version.file}" append="true"/>
+    </target>
+    <target name="compile-test" depends="compile">
+        <fail message="Please specify jtreg.home" unless="jtreg.home"/>
+        <mkdir dir="${build.test.dir}"/>
+        <javac srcdir="${test.dir}" destdir="${build.test.dir}" debug="on" includeantruntime="false"
+               classpath="${build.classes.dir}:${dependencies.classpath}:${jtreg.home}/lib/testng.jar"/>
+    </target>
+    <target name="find-tests" unless="tests">
+        <fileset id="testset" dir="${test.dir}">
+            <include name="**/*Test.java" />
+        </fileset>
+        <pathconvert pathsep="${line.separator}" property="testlist" refid="testset">
+            <globmapper from="${test.dir}/*" to="*"/>
+        </pathconvert>
+        <echo file="${test.list}">${testlist}</echo>
+        <property name="tests" value="@${test.list}"/>
+    </target>
+    <target name="test" depends="compile-test,find-tests">
+        <exec executable="${jtreg.home}/bin/jtreg">
+            <arg value="-cpa:${build.classes.dir}:${dependencies.classpath}"/>
+            <arg value="-w:${test.workdir}"/>
+            <arg value="-r:${test.report}"/>
+            <arg value="-conc:1"/>
+            <arg value="-ovm"/>
+            <arg value="-v:default"/>
+            <arg value="-dir:test"/>
+            <arg value="${tests}"/>
+        </exec>
+    </target>
+    <target name="full-test" depends="test-dependecies-impl, test"/>
+    <target name="jar" depends="compile">
+        <mkdir dir="${build.dir}"/>
+        <jar jarfile="${dist.jar}" basedir="${build.classes.dir}">
+            <manifest>
+                <attribute name="Main-Class" value="${version.class}"/>
+            </manifest>
+        </jar>
+    </target>
+    <target name="clean">
+        <delete dir="${build.dir}"/>
+    </target>
+</project>
+
+