Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Tiede2012-12-13 15:46:50 +0000
committerMarkus Tiede2012-12-13 15:46:50 +0000
commit87dcf3117f746a5bd16bd3d71fa23827ee508e58 (patch)
treeebfe8745ee0d7407b2aad813fea92408b1c70453
parent8130f1b4fd362036b3d54172efc3b26aa1c1874d (diff)
downloadorg.eclipse.jubula.core-87dcf3117f746a5bd16bd3d71fa23827ee508e58.tar.gz
org.eclipse.jubula.core-87dcf3117f746a5bd16bd3d71fa23827ee508e58.tar.xz
org.eclipse.jubula.core-87dcf3117f746a5bd16bd3d71fa23827ee508e58.zip
Sprint task - patch for enhancement 394179 applied.
-rw-r--r--org.eclipse.jubula.rc.common/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractButtonCAPs.java54
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractComboBoxCAPs.java180
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractListCAPs.java476
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractMenuCAPs.java584
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTableCAPs.java1094
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextComponent.java205
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextInputSupport.java53
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextVerifiable.java49
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTreeCAPs.java754
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractUICAPs.java88
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractWidgetCAPs.java539
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/LabelCAPs.java30
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/TabbedPaneCAPs.java307
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/driver/DragAndDropHelper.java18
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/factory/GUIAdapterFactoryRegistry.java101
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/factory/IUIAdapterFactory.java36
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IButtonAdapter.java34
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComboBoxAdapter.java79
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComponentAdapter.java35
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IListAdapter.java52
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IMenuAdapter.java35
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IMenuItemAdapter.java80
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITabPaneAdapter.java52
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITableAdapter.java128
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITextComponentAdapter.java52
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITextVerifiable.java15
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITreeAdapter.java41
-rw-r--r--org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IWidgetAdapter.java117
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/SwingAUTServer.java6
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/AbstractButtonCAPs.java45
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/CapUtil.java301
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JListCAPs.java29
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JMenuBarCAPs.java191
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JTableCAPs.java190
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JTreeCAPs.java157
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/AbstractButtonAdapter.java103
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/AbstractComponentAdapter.java28
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JComboBoxAdapter.java405
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JLabelAdapter.java39
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JListAdapter.java243
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuAdapter.java91
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuBarAdapter.java74
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuItemAdapter.java225
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JPopupMenuAdapter.java68
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTabbedPaneAdapter.java98
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTableAdapter.java385
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTextComponentAdapter.java119
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTreeAdapter.java65
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/WidgetAdapter.java329
-rw-r--r--org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/factory/SwingAdapterFactory.java119
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/SwtAUTServer.java8
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/ButtonCAPs.java35
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/CAPUtil.java96
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/ListCAPs.java30
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/MenuCAPs.java305
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/TableCAPs.java714
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/TreeCAPs.java901
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/AbstractComboBoxAdapter.java318
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/AbstractComponentAdapter.java29
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ButtonAdapter.java70
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CComboAdapter.java355
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CLabelAdapter.java54
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CTabFolderAdapter.java121
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ComboAdapter.java196
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/LabelAdapter.java54
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ListAdapter.java208
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/MenuAdapter.java106
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/MenuItemAdapter.java532
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/StyledTextAdapter.java151
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TabFolderAdapter.java105
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TableAdapter.java534
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TextComponentAdapter.java153
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TreeAdapter.java66
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/WidgetAdapter.java420
-rw-r--r--org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/factory/SWTAdapterFactory.java104
-rw-r--r--org.eclipse.jubula.toolkit.provider.swing/resources/xml/ComponentConfiguration.xml18
-rw-r--r--org.eclipse.jubula.toolkit.provider.swt/resources/xml/ComponentConfiguration.xml28
78 files changed, 14288 insertions, 24 deletions
diff --git a/org.eclipse.jubula.rc.common/META-INF/MANIFEST.MF b/org.eclipse.jubula.rc.common/META-INF/MANIFEST.MF
index 8c481b025..4d88ec21b 100644
--- a/org.eclipse.jubula.rc.common/META-INF/MANIFEST.MF
+++ b/org.eclipse.jubula.rc.common/META-INF/MANIFEST.MF
@@ -7,6 +7,7 @@ Bundle-Vendor: Eclipse Jubula
Export-Package: org.eclipse.jubula.rc.common,
org.eclipse.jubula.rc.common.adaptable,
org.eclipse.jubula.rc.common.businessprocess,
+ org.eclipse.jubula.rc.common.caps,
org.eclipse.jubula.rc.common.classloader,
org.eclipse.jubula.rc.common.commands,
org.eclipse.jubula.rc.common.components,
@@ -18,6 +19,8 @@ Export-Package: org.eclipse.jubula.rc.common,
org.eclipse.jubula.rc.common.listener,
org.eclipse.jubula.rc.common.logger,
org.eclipse.jubula.rc.common.registration,
+ org.eclipse.jubula.rc.common.uiadapter.factory,
+ org.eclipse.jubula.rc.common.uiadapter.interfaces,
org.eclipse.jubula.rc.common.util
Require-Bundle: org.apache.commons.beanutils;bundle-version="[1.7.0,2.0.0)",
org.apache.commons.lang;bundle-version="[2.4.0,3.0.0)",
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractButtonCAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractButtonCAPs.java
new file mode 100644
index 000000000..ab3213958
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractButtonCAPs.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IButtonAdapter;
+
+
+/**
+ * Implementation for all Button like classes, it holds the
+ * general methods for the testing of buttons.
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public abstract class AbstractButtonCAPs extends AbstractTextVerifiable {
+
+ /**
+ *
+ * @return the IButtonAdapter for the component.
+ */
+ private IButtonAdapter getButtonAdapter() {
+ return (IButtonAdapter)getComponent();
+ }
+
+ /**
+ * Verifies the selected property.
+ *
+ * @param selected The selected property value to verify.
+ */
+ public void gdVerifySelected(boolean selected) {
+
+ Verifier.equals(selected, getButtonAdapter().isSelected());
+ }
+
+ /**
+ * Verifies the passed text.
+ *
+ * @param text The text to verify
+ */
+ public void gdVerifyText(String text) {
+ gdVerifyText(text, MatchUtil.DEFAULT_OPERATOR);
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractComboBoxCAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractComboBoxCAPs.java
new file mode 100644
index 000000000..d8ba160a6
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractComboBoxCAPs.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComboBoxAdapter;
+import org.eclipse.jubula.tools.constants.TestDataConstants;
+import org.eclipse.jubula.tools.utils.StringParsing;
+
+/**
+ * General implementation for ComboBoxes and ComboBox like components.
+ * @author BREDEX GmbH
+ *
+ */
+public class AbstractComboBoxCAPs extends AbstractTextInputSupport {
+
+ /** The dafault separator of a list of values */
+ public static final char VALUE_SEPARATOR =
+ TestDataConstants.VALUE_CHAR_DEFAULT;
+
+ /**
+ *
+ * @return the <code>IComboBoxAdapter</code>
+ */
+ private IComboBoxAdapter getCBAdapter() {
+ return (IComboBoxAdapter) getComponent();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ return null;
+ }
+
+ /**
+ * Verifies the editable property.
+ * @param editable The editable property to verify.
+ */
+ public void gdVerifyEditable(boolean editable) {
+ Verifier.equals(editable, getCBAdapter().isEditable());
+ }
+
+ /**
+ * Checks if the component contains the specified text.
+ * @param text check if this text is in the combobox
+ */
+ public void gdVerifyContainsValue(final String text) {
+ Verifier.equals(true, getCBAdapter().containsValue(text));
+ }
+
+ /**
+ * Verifies if the list contains an element that renderes <code>value</code>.
+ * @param value The text to verify
+ * @param operator The operator used to verify
+ * @param exists If the value should exist or not.
+ */
+ public void gdVerifyContainsValue(String value, String operator,
+ boolean exists) {
+ final boolean contains = getCBAdapter().containsValue(value, operator);
+ Verifier.equals(exists, contains);
+ }
+
+ /**
+ * @see org.eclipse.jubula.rc.swing.swing.implclasses.AbstractSwingImplClass#getText()
+ * @return value from ComboBoxHelper
+ */
+ protected String getText() {
+ return getCBAdapter().getText();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdInputText(String text) {
+ getCBAdapter().input(text, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdReplaceText(String text) throws StepExecutionException {
+ getCBAdapter().input(text, true);
+ }
+
+ /**
+ * Selects <code>index</code> in the combobox.
+ *
+ * @param index
+ * The index to select
+ */
+ public void gdSelectIndex(String index) {
+ int implIdx = IndexConverter.toImplementationIndex(
+ IndexConverter.intValue(index));
+ getCBAdapter().select(implIdx);
+
+ }
+
+ /**
+ * Selects a value from the list of the combobox
+ * @param valueList The value or list of values to (not)select
+ * @param operator if regular expressions are used
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ */
+ public void gdSelectValue(String valueList, String operator,
+ final String searchType) {
+ gdSelectValue(valueList, String.valueOf(VALUE_SEPARATOR), operator,
+ searchType);
+ }
+
+ /**
+ * Selects a value from the list of the combobox
+ *
+ * @param valueList
+ * the item(s) which should be (not)selected.
+ * @param separator
+ * The seperator if <code>text</code> is an enumeration of
+ * values. Not supported by this implementation class
+ * @param operator
+ * if regular expressions are used
+ * @param searchType
+ * Determines where the search begins ("relative" or "absolute")
+ */
+ private void gdSelectValue(String valueList, String separator,
+ String operator, final String searchType) {
+ String[] values = split(valueList, separator);
+ getCBAdapter().select(values, operator, searchType);
+
+ }
+
+ /**
+ * Verifies if the combobox has <code>index</code> selected.
+ * @param index The index to verify
+ * @param isSelected If the index should be selected or not.
+ */
+ public void gdVerifySelectedIndex(String index, boolean isSelected) {
+ int implIdx = IndexConverter.toImplementationIndex(
+ IndexConverter.intValue(index));
+ int actual = getCBAdapter().getSelectedIndex();
+ Verifier.equals(implIdx, actual, isSelected);
+ }
+
+ /**
+ * Verifies if the passed text is currently selected in the combobox.
+ * @param text The text to verify.
+ */
+ public void gdVerifyText(String text) {
+ gdVerifyText(text, MatchUtil.DEFAULT_OPERATOR);
+ }
+
+ /**
+ * Splits the enumeration of values.
+ *
+ * @param values
+ * The values to split
+ * @param separator
+ * The separator, may be <code>null</code>
+ * @return The array of values
+ */
+ private String[] split(String values, String separator) {
+ String[] list = StringParsing.splitToArray(values, ((separator == null)
+ || (separator.length() == 0) ? INDEX_LIST_SEP_CHAR
+ : separator.charAt(0)),
+ TestDataConstants.ESCAPE_CHAR_DEFAULT);
+ return list;
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractListCAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractListCAPs.java
new file mode 100644
index 000000000..66f2b8c32
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractListCAPs.java
@@ -0,0 +1,476 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import java.util.Arrays;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.jubula.rc.common.CompSystemConstants;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.DragAndDropHelper;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
+import org.eclipse.jubula.rc.common.implclasses.ListSelectionVerifier;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IListAdapter;
+import org.eclipse.jubula.tools.constants.StringConstants;
+import org.eclipse.jubula.tools.constants.TestDataConstants;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.jubula.tools.utils.StringParsing;
+
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public abstract class AbstractListCAPs extends AbstractTextVerifiable {
+
+ /** The default separator for enumerations of list values. */
+ public static final char INDEX_LIST_SEP_CHAR =
+ TestDataConstants.VALUE_CHAR_DEFAULT;
+ //FIXME this should be in an upper class or Util
+ /** The default separator of a list of values */
+ public static final char VALUE_SEPARATOR =
+ TestDataConstants.VALUE_CHAR_DEFAULT;
+
+ /**
+ * Splits the enumeration of values.
+ * @param values The values to split
+ * @param separator The separator, may be <code>null</code>
+ * @return The array of values
+ */
+ private String[] split(String values, String separator) {
+ String[] list = StringParsing.splitToArray(values, ((separator == null)
+ || (separator.length() == 0) ? INDEX_LIST_SEP_CHAR
+ : separator.charAt(0)),
+ TestDataConstants.ESCAPE_CHAR_DEFAULT);
+ list = StringUtils.stripAll(list);
+ return list;
+ }
+
+ /**
+ * @return The array of selected indices
+ * @throws StepExecutionException If there are no indices selected
+ */
+ private int[] getCheckedSelectedIndices() throws StepExecutionException {
+ int[] selected = getListAdapter().getSelectedIndices();
+ if (selected.length == 0) {
+ throw new StepExecutionException("No list element selected", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NO_SELECTION));
+ }
+ return selected;
+ }
+
+ /**
+ *
+ * @return the List Adapter
+ */
+ private IListAdapter getListAdapter() {
+ return ((IListAdapter) getComponent());
+ }
+
+ /**
+ * Verifies if the passed index is selected.
+ *
+ * @param index The index to verify
+ * @param expectSelected Whether the index should be selected.
+ */
+ public void gdVerifySelectedIndex(String index, boolean expectSelected) {
+ int[] selected = getCheckedSelectedIndices();
+ int implIndex = IndexConverter.toImplementationIndex(
+ Integer.parseInt(index));
+
+ boolean isSelected = ArrayUtils.contains(selected, implIndex);
+ if (expectSelected != isSelected) {
+ throw new StepExecutionException(
+ "Selection check failed for index: " + index, //$NON-NLS-1$
+ EventFactory.createVerifyFailed(
+ String.valueOf(expectSelected),
+ String.valueOf(isSelected)));
+ }
+ }
+
+ /**
+ * Verifies if the passed value or enumeration of values is selected. By
+ * default, the enumeration separator is <code>,</code>
+ * @param valueList The value or list of values to verify
+ */
+ public void gdVerifySelectedValue(String valueList) {
+ gdVerifySelectedValue(valueList, MatchUtil.DEFAULT_OPERATOR, true);
+ }
+
+ /**
+ * Verifies if the passed value is selected.
+ *
+ * @param value The value to verify
+ * @param operator The operator to use when comparing the
+ * expected and actual values.
+ * @param isSelected if the value should be selected or not.
+ */
+ public void gdVerifySelectedValue(String value, String operator,
+ boolean isSelected) {
+
+ final String[] current = getListAdapter().getSelectedValues();
+ final ListSelectionVerifier listSelVerifier =
+ new ListSelectionVerifier();
+ for (int i = 0; i < current.length; i++) {
+ listSelVerifier.addItem(i, current[i], true);
+ }
+ listSelVerifier.verifySelection(value, operator, isSelected);
+ }
+
+ /**
+ * Verifies if all selected elements of a list match a text.
+ * @param text The text to verify
+ * @param operator The operator used to verify
+ */
+ public void gdVerifyText(String text, String operator) {
+ String[] selected = getListAdapter().getSelectedValues();
+ final int selCount = selected.length;
+ if (selCount < 1) {
+ throw new StepExecutionException("No selection", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NO_SELECTION));
+ }
+ for (int i = 0; i < selCount; i++) {
+ Verifier.match(selected[i], text, operator);
+ }
+ }
+
+ /**
+ * Selects the passed index or enumeration of indices. The enumeration must
+ * be separated by <code>,</code>, e.g. <code>1, 3,6</code>.
+ * @param indexList The index or indices to select
+ * @param extendSelection Whether this selection extends a previous
+ * selection.
+ * @param button what mouse button should be used
+ */
+ public void gdSelectIndex(String indexList, final String extendSelection,
+ int button) {
+ final boolean isExtendSelection = extendSelection
+ .equals(CompSystemConstants.EXTEND_SELECTION_YES);
+ selectIndices(IndexConverter
+ .toImplementationIndices(parseIndices(indexList)), ClickOptions
+ .create().setClickCount(1).setMouseButton(button),
+ isExtendSelection);
+ }
+
+ /**
+ * Selects the passed value or enumeration of values. By default, the
+ * enumeration separator is <code>,</code>.
+ * @param valueList The value or list of values to select
+ * @param operator If regular expressions are used
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param extendSelection Whether this selection extends a previous
+ * selection. If <code>true</code>, the first
+ * element will be selected with CONTROL as a
+ * modifier.
+ * @param button what mouse button should be used
+ */
+ public void gdSelectValue(String valueList, String operator,
+ String searchType, final String extendSelection, int button) {
+ final boolean isExtendSelection =
+ extendSelection.equals(CompSystemConstants.EXTEND_SELECTION_YES);
+ selectValue(valueList, String.valueOf(VALUE_SEPARATOR), operator,
+ searchType, ClickOptions.create()
+ .setClickCount(1)
+ .setMouseButton(button), isExtendSelection);
+ }
+
+ /**
+ * Selects the passed value or enumeration of values. By default, the
+ * enumeration separator is <code>,</code>, but may be changed by
+ * <code>separator</code>.
+ * @param valueList The value or list of values to select
+ * @param separator The separator, optional
+ * @param operator If regular expressions are used
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param clickCount the amount of clicks to use
+ * @param extendSelection Whether this selection extends a previous
+ * selection.
+ */
+ public void gdSelectValue(String valueList, String separator,
+ String operator, final String searchType, int clickCount,
+ final String extendSelection) {
+ final boolean isExtendSelection =
+ extendSelection.equals(CompSystemConstants.EXTEND_SELECTION_YES);
+ selectValue(valueList, separator, operator, searchType, ClickOptions
+ .create().setClickCount(clickCount), isExtendSelection);
+ }
+
+ /**
+ * Verifies if the list contains an element that renderes <code>value</code>.
+ * @param value The text to verify
+ */
+ public void gdVerifyContainsValue(String value) {
+ Verifier.equals(true, containsValue(value));
+ }
+
+ /**
+ * Verifies if the list contains an element that renderes <code>value</code>.
+ * @param value The text to verify
+ * @param operator The operator used to verify
+ * @param exists if the wanted value should exist or not.
+ */
+ public void gdVerifyContainsValue(String value, String operator,
+ boolean exists) {
+
+ Verifier.equals(exists, containsValue(value, operator));
+ }
+
+ /**
+ * Action to read the value of the current selected item of the JList
+ * to store it in a variable in the Client
+ * @param variable the name of the variable
+ * @return the text value.
+ */
+ public String gdReadValue(String variable) {
+ String[] selected = getListAdapter().getSelectedValues();
+ if (selected.length > 0) {
+ return selected[0];
+ }
+ throw new StepExecutionException("No list item selected", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NO_SELECTION));
+ }
+
+ /**
+ * Drags the passed value.
+ *
+ * @param mouseButton the mouseButton.
+ * @param modifier the modifier.
+ * @param value The value to drag
+ * @param operator If regular expressions are used
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ */
+ public void gdDragValue(int mouseButton, String modifier, String value,
+ String operator, final String searchType) {
+
+ DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ dndHelper.setModifier(modifier);
+ dndHelper.setMouseButton(mouseButton);
+
+ Integer [] indices = getListAdapter().findIndicesOfValues(
+ new String [] {value}, operator, searchType);
+ selectIndices(ArrayUtils.toPrimitive(indices),
+ ClickOptions.create().setClickCount(0), false);
+
+ pressOrReleaseModifiers(modifier, true);
+ getRobot().mousePress(null, null, mouseButton);
+ }
+
+ /**
+ * Drops on the passed value.
+ *
+ * @param value The value on which to drop
+ * @param operator If regular expressions are used
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ */
+ public void gdDropValue(String value, String operator,
+ final String searchType, int delayBeforeDrop) {
+
+ DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ try {
+ Integer [] indices = getListAdapter().findIndicesOfValues(
+ new String [] {value}, operator, searchType);
+ selectIndices(ArrayUtils.toPrimitive(indices),
+ ClickOptions.create().setClickCount(0), false);
+ waitBeforeDrop(delayBeforeDrop);
+ } finally {
+ getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(), false);
+ }
+ }
+
+ /**
+ * Drags the passed index.
+ *
+ * @param mouseButton the mouseButton.
+ * @param modifier the modifier.
+ * @param index The index to drag
+ */
+ public void gdDragIndex(final int mouseButton, final String modifier,
+ int index) {
+
+ DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ dndHelper.setModifier(modifier);
+ dndHelper.setMouseButton(mouseButton);
+
+ selectIndices(
+ new int [] {IndexConverter.toImplementationIndex(index)},
+ ClickOptions.create().setClickCount(0), false);
+
+ pressOrReleaseModifiers(modifier, true);
+ getRobot().mousePress(null, null, mouseButton);
+ }
+
+ /**
+ * Drops onto the passed index.
+ *
+ * @param index The index on which to drop
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ */
+ public void gdDropIndex(final int index, int delayBeforeDrop) {
+
+ DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+
+ try {
+ selectIndices(
+ new int [] {IndexConverter.toImplementationIndex(index)},
+ ClickOptions.create().setClickCount(0), false);
+ waitBeforeDrop(delayBeforeDrop);
+ } finally {
+ getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(), false);
+ }
+ }
+
+ /**
+ * @param value The value
+ * @return <code>true</code> if the list contains an element that is rendered with <code>value</code>
+ */
+ public boolean containsValue(String value) {
+ Integer[] indices = getListAdapter().findIndicesOfValues(
+ new String[] { value },
+ MatchUtil.EQUALS, CompSystemConstants.SEARCH_TYPE_ABSOLUTE);
+ return indices.length > 0;
+ }
+
+ /**
+ * @param value The value
+ * @param operator The operator used to verify
+ * @return <code>true</code> if the list contains an element that is rendered with <code>value</code>
+ */
+ public boolean containsValue(String value, String operator) {
+ Integer[] indices = null;
+ if (operator.equals(MatchUtil.NOT_EQUALS)) {
+ indices = getListAdapter().findIndicesOfValues(
+ new String[] { value },
+ MatchUtil.EQUALS, CompSystemConstants.SEARCH_TYPE_ABSOLUTE);
+ return indices.length == 0;
+ }
+ indices = getListAdapter().findIndicesOfValues(new String[] { value },
+ operator, CompSystemConstants.SEARCH_TYPE_ABSOLUTE);
+ return indices.length > 0;
+ }
+
+ /**
+ * Selects the passed value or enumeration of values. By default, the
+ * enumeration separator is <code>,</code>, but may be changed by
+ * <code>separator</code>.
+ * @param valueList The value or list of values to select
+ * @param separator The separator, optional
+ * @param operator If regular expressions are used
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param co the click options to use
+ * @param isExtendSelection Whether this selection extends a previous
+ * selection.
+ */
+ private void selectValue(String valueList, String separator,
+ String operator, final String searchType, ClickOptions co,
+ final boolean isExtendSelection) {
+
+ String[] values = null;
+ if (StringConstants.EMPTY.equals(valueList)) {
+ values = new String[1];
+ values[0] = StringConstants.EMPTY;
+ } else {
+ values = split(valueList, separator);
+ }
+ Integer[] indices = getListAdapter().findIndicesOfValues(values,
+ operator, searchType);
+ Arrays.sort(indices);
+ if (!operator.equals(MatchUtil.NOT_EQUALS)
+ && (indices.length < values.length)) {
+ throw new StepExecutionException("One or more values not found of set: " //$NON-NLS-1$
+ + Arrays.asList(values).toString(),
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+ selectIndices(ArrayUtils.toPrimitive(indices), co, isExtendSelection);
+ }
+
+ /**
+ * Parses the enumeration of indices.
+ * @param indexList The enumeration of indices
+ * @return The array of parsed indices
+ */
+ private int[] parseIndices(String indexList) {
+ String[] list = StringParsing.splitToArray(indexList,
+ INDEX_LIST_SEP_CHAR, TestDataConstants.ESCAPE_CHAR_DEFAULT);
+ int[] indices = new int[list.length];
+ for (int i = 0; i < list.length; i++) {
+ indices[i] = IndexConverter.intValue(list[i]);
+ }
+ return indices;
+ }
+
+ /**
+ * @param indices The indices to select
+ * @param co the click options to use
+ * @param isExtendSelection Whether this selection extends a previous
+ * selection. If <code>true</code>, the first
+ * element will be selected with CONTROL as a
+ * modifier.
+ */
+ private void selectIndices(int[] indices, ClickOptions co,
+ boolean isExtendSelection) {
+ Object list = getListAdapter().getRealComponent();
+ if (indices.length > 0) {
+ try {
+ if (isExtendSelection) {
+ getRobot().keyPress(list,
+ getSystemDefaultModifier());
+ }
+
+ // first selection
+ getListAdapter().clickOnIndex(
+ new Integer(indices[0]), co);
+ } finally {
+ if (isExtendSelection) {
+ getRobot().keyRelease(list,
+ getSystemDefaultModifier());
+ }
+ }
+ }
+ try {
+ getRobot().keyPress(list,
+ getSystemDefaultModifier());
+ // following selections
+ for (int i = 1; i < indices.length; i++) {
+ getListAdapter().clickOnIndex(
+ new Integer(indices[i]), co);
+ }
+ } finally {
+ getRobot().keyRelease(list,
+ getSystemDefaultModifier());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ return null;
+ }
+
+ /**
+ *
+ * @return -
+ */
+ protected abstract int getSystemDefaultModifier();
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractMenuCAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractMenuCAPs.java
new file mode 100644
index 000000000..43d9ef04e
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractMenuCAPs.java
@@ -0,0 +1,584 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.RobotTiming;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.MenuUtilBase;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.logger.AutServerLogger;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
+import org.eclipse.jubula.tools.i18n.I18n;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.jubula.tools.utils.TimeUtil;
+
+/**
+ * General implementation for Menus. Also used for context menus
+ * if they behave the same.
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public abstract class AbstractMenuCAPs extends AbstractUICAPs {
+
+ /** the logger */
+ private static AutServerLogger log = new AutServerLogger(
+ AbstractMenuCAPs.class);
+
+ /**
+ * @return the log
+ */
+ public static AutServerLogger getLog() {
+ return log;
+ }
+
+ /**
+ * This method gets the object which should implementet the menu Interface.
+ * It is saved as Component so it must be casted.
+ * @return the MenuAdapter
+ */
+ public IMenuAdapter getMenuAdapter() {
+ return (IMenuAdapter) getComponent();
+ }
+ /**
+ * Checks if the specified menu item is enabled.
+ *
+ * @param menuItem the menu item as a text path to verify against
+ * @param operator operator used for matching
+ * @param enabled is the specified menu item enabled?
+ */
+ public void verifyEnabled(String menuItem, String operator, boolean enabled)
+ {
+ verifyEnabled(MenuUtilBase.splitPath(menuItem), operator, enabled);
+ }
+
+ /**
+ * Checks if the specified menu item is enabled.
+ *
+ * @param menuItem the menu item to verify against
+ * @param operator operator used for matching
+ * @param enabled is the specified menu item enabled?
+ */
+ public void verifyEnabled(String[] menuItem, String operator,
+ boolean enabled) {
+ checkPathLength(menuItem.length);
+ final IMenuItemAdapter item = navigateToMenuItem(
+ getAndCheckMenu(), menuItem, operator);
+ checkIsNull(item);
+ try {
+ Verifier.equals(enabled, item.isEnabled());
+ } finally {
+ closeMenu(getAndCheckMenu(), menuItem, operator);
+ }
+
+ }
+ /**
+ * Checks if the given MenuItemAdapter is null and thorws an Exception
+ *
+ * @param item the MenuItemAdapter which should be checked
+ */
+ private void checkIsNull(final IMenuItemAdapter item) {
+ if (item.getRealComponent() == null) {
+ throwMenuItemNotFound();
+ }
+ }
+
+ /**
+ * Checks if the specified menu item is enabled.
+ *
+ * @param menuItem the menu item as a text path to verify against
+ * @param enabled is the specified menu item enabled?
+ */
+ public void verifyEnabledByIndexpath(String menuItem, boolean enabled) {
+ verifyEnabledByIndexpath(MenuUtilBase.splitIndexPath(menuItem),
+ enabled);
+ }
+
+ /**
+ * Checks if the specified menu item is enabled.
+ *
+ * @param menuItem the menu item to verify against
+ * @param enabled is the specified menu item enabled?
+ */
+ public void verifyEnabledByIndexpath(int[] menuItem, boolean enabled) {
+ checkPathLength(menuItem.length);
+ final IMenuItemAdapter item = navigateToMenuItem(
+ getAndCheckMenu(), menuItem);
+ checkIsNull(item);
+ try {
+ Verifier.equals(enabled, item.isEnabled());
+ } finally {
+ closeMenu(getAndCheckMenu(), menuItem);
+ }
+ }
+
+
+
+ /**
+ * Verifies if the specified menu item exists
+ *
+ * @param menuItem the menu item to verifiy against
+ * @param operator operator used for matching
+ * @param exists should the menu item exist?
+ */
+ public void verifyExists(String menuItem, String operator, boolean exists) {
+ verifyExists(MenuUtilBase.splitPath(menuItem), operator, exists);
+ }
+
+ /**
+ * Verifies if the specified menu item exists
+ *
+ * @param menuItem the menu item to verify against
+ * @param operator operator used for matching
+ * @param exists should the menu item exist?
+ */
+ public void verifyExists(String[] menuItem, String operator, boolean exists)
+ {
+ checkPathLength(menuItem.length);
+ final IMenuItemAdapter item = navigateToMenuItem(
+ getAndCheckMenu(), menuItem, operator);
+ try {
+ Verifier.equals(exists, item.isExisting());
+ } finally {
+ closeMenu(getAndCheckMenu(), menuItem, operator);
+ }
+ }
+
+
+ /**
+ * Verifies if the specified menu item exists
+ * @param menuItem the menu item to verifiy against
+ * @param exists should the menu item exist?
+ */
+ public void verifyExistsByIndexpath(String menuItem, boolean exists) {
+ verifyExistsByIndexpath(MenuUtilBase.splitIndexPath(menuItem), exists);
+ }
+
+ /**
+ * Verifies if the specified menu item exists
+ *
+ * @param menuItem the menu item to verify against
+ * @param exists should the menu item exist?
+ */
+ public void verifyExistsByIndexpath(int[] menuItem, boolean exists) {
+ checkPathLength(menuItem.length);
+ final IMenuItemAdapter item = navigateToMenuItem(
+ getAndCheckMenu(), menuItem);
+ try {
+ Verifier.equals(exists, item.isExisting());
+ } finally {
+ closeMenu(getAndCheckMenu(), menuItem);
+ }
+
+ }
+
+ /**
+ * Checks if the specified menu item is selected.
+ *
+ * @param menuItem the menu item to verify against
+ * @param operator operator used for matching
+ * @param selected is the specified menu item selected?
+ */
+ public void verifySelected(String menuItem, String operator,
+ boolean selected) {
+ verifySelected(MenuUtilBase.splitPath(menuItem), operator, selected);
+ }
+
+ /**
+ * Checks if the specified menu item is selected.
+ *
+ * @param menuItem the menu item to verify against
+ * @param operator operator used for matching
+ * @param selected is the specified menu item selected?
+ */
+ public void verifySelected(String[] menuItem, String operator,
+ boolean selected) {
+ checkPathLength(menuItem.length);
+ final IMenuItemAdapter item = navigateToMenuItem(
+ getAndCheckMenu(), menuItem, operator);
+ checkIsNull(item);
+ try {
+ Verifier.equals(selected, item.isSelected());
+
+ } finally {
+ closeMenu(getAndCheckMenu(), menuItem, operator);
+ }
+
+ }
+
+ /**
+ * Checks if the specified menu item is selected.
+ *
+ * @param menuItem the menu item to verify against
+ * @param selected is the specified menu item selected?
+ */
+ public void verifySelectedByIndexpath(String menuItem, boolean selected) {
+ verifySelectedByIndexpath(MenuUtilBase.splitIndexPath(menuItem),
+ selected);
+ }
+
+ /**
+ * Checks if the specified menu item is selected.
+ *
+ * @param menuItem the menu item to verify against
+ * @param selected is the specified menu item selected?
+ */
+ public void verifySelectedByIndexpath(int[] menuItem, boolean selected) {
+ checkPathLength(menuItem.length);
+ final IMenuItemAdapter item = navigateToMenuItem(
+ getAndCheckMenu(), menuItem);
+ checkIsNull(item);
+ try {
+ Verifier.equals(selected, item.isSelected());
+
+ } finally {
+ closeMenu(getAndCheckMenu(), menuItem);
+
+ }
+
+ }
+
+ /**
+ * Tries to select a menu item in a menu defined by an Index-Path
+ * @param indexPath the menu item to select
+ */
+ public void selectMenuItemByIndexpath(String indexPath) {
+ int[] indexItems = MenuUtilBase.splitIndexPath(indexPath);
+ checkPathLength(indexItems.length);
+
+ try {
+ final IMenuItemAdapter item = navigateToMenuItem(
+ getAndCheckMenu(), indexItems);
+
+ checkIsNull(item);
+
+ item.selectMenuItem();
+ } catch (StepExecutionException e) {
+ try {
+ closeMenu(getAndCheckMenu(), indexItems);
+ } catch (StepExecutionException e1) {
+ // Menu item is disabled or menu is already closed
+ // Do nothing
+ if (getLog().isInfoEnabled()) {
+ getLog().info("Tried to close a disabled or already closed menu."); //$NON-NLS-1$
+ }
+ }
+ throwMenuItemNotFound();
+ }
+
+ }
+
+ /**
+ * Tries to select a menu item in a menu defined by a Text-Path
+ * @param namePath the menu item to select
+ * @param operator operator used for matching
+ */
+ public void selectMenuItem(String namePath, final String operator) {
+ String[] menuItems = MenuUtilBase.splitPath(namePath);
+ if (menuItems.length == 0) {
+ throw new StepExecutionException("empty path to menuitem not allowed", //$NON-NLS-1$
+ EventFactory.createActionError());
+ }
+ IMenuItemAdapter item = navigateToMenuItem(getAndCheckMenu(),
+ menuItems, operator);
+ if (item == null) {
+ try {
+ closeMenu(getAndCheckMenu(), menuItems, operator);
+ } catch (StepExecutionException see) {
+ // Menu item is disabled or menu is already closed
+ // Do nothing
+ getLog().info("Tried to close a disabled or already closed menu."); //$NON-NLS-1$
+ }
+ throw new StepExecutionException("no such menu item found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+ item.selectMenuItem();
+ }
+
+
+ /**
+ *
+ * @return the IMenuAdapter.
+ * @throws StepExecutionException
+ * if the active window has no menu bar.
+ */
+ protected IMenuAdapter getAndCheckMenu() throws StepExecutionException {
+ Object menu = getMenuAdapter().getRealComponent();
+ // Verify that the active window has a menu bar
+ if (menu == null) {
+ throw new StepExecutionException(
+ I18n.getString(TestErrorEvent.NO_MENU_BAR),
+ EventFactory.createActionError(TestErrorEvent.NO_MENU_BAR));
+ }
+ return getMenuAdapter();
+ }
+
+ /**
+ *
+ */
+ private void throwMenuItemNotFound() {
+ throw new StepExecutionException("no such menu item found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+
+
+ /**
+ * this methods closes the hole menu. It is clicking on the parent item in the menu bar.
+ *
+ * If you need another implementation override this method.
+ * @param menuBar the main menu
+ * @param textPath the text path used for opening the menu
+ * @param operator the operator which was used for opening the menu
+ */
+ protected void closeMenu(IMenuAdapter menuBar, String[] textPath,
+ String operator) {
+ IMenuItemAdapter menuitem = findMenu(menuBar,
+ getIndexForName(menuBar, textPath[0], operator));
+ if (menuitem.getRealComponent() != null) {
+ getRobot().click(
+ menuitem.getRealComponent(),
+ null,
+ ClickOptions.create().setClickType(
+ ClickOptions.ClickType.RELEASED));
+
+ }
+
+ }
+ /**
+ * this methods closes the hole menu. It is clicking on the parent item in the menu bar.
+ *
+ * If you need another implementation override this method.
+ * @param menuBar the main menu
+ * @param path the integer based path used for opening the menu
+ */
+ protected void closeMenu(IMenuAdapter menuBar, int[] path) {
+ IMenuItemAdapter menuitem = findMenu(menuBar, path[0]);
+ if (menuitem.getRealComponent() != null) {
+ getRobot().click(
+ menuitem.getRealComponent(),
+ null,
+ ClickOptions.create().setClickType(
+ ClickOptions.ClickType.RELEASED));
+
+ }
+ }
+
+ /**
+ * Gets the index of the specific menu entry with the name
+ *
+ * @param menu the menu in which all items are stored
+ * @param name the name of the item we want the index from
+ * @param operator the operator for the matching
+ * @return the index for the specific menu entry
+ */
+ protected int getIndexForName(IMenuAdapter menu, String name,
+ String operator) {
+ IMenuItemAdapter [] subElements = menu.getItems();
+ int downcount = 0;
+ for (int j = 0; j < subElements.length; j++) {
+ IMenuItemAdapter tempMenu = (IMenuItemAdapter)subElements[j];
+ if (tempMenu.isSeparator()) {
+ downcount++;
+ }
+ if (tempMenu.isShowing()
+ && MatchUtil.getInstance().match(
+ tempMenu.getText(), name, operator)) {
+ return j - downcount;
+ }
+ }
+ return Integer.MAX_VALUE;
+ }
+
+
+ /**
+ * implementation for "wait for component"
+ * @param timeout the maximum amount of time to wait for the component
+ * @param delay the time to wait after the component is found
+ */
+ public void waitForComponent(int timeout, int delay) {
+ if (getComponent().getRealComponent() == null) {
+ long start = System.currentTimeMillis();
+ do {
+ RobotTiming.sleepWaitForComponentPollingDelay();
+ } while (System.currentTimeMillis() - start < timeout
+ && getComponent().getRealComponent() == null);
+ if (getComponent().getRealComponent() == null) {
+ throw new StepExecutionException("No Menubar found.", //$NON-NLS-1$
+ EventFactory.createComponentNotFoundErrorEvent());
+ }
+ }
+ TimeUtil.delay(delay);
+ }
+
+ /**
+ * Tries to navigate through the menu to the specified menu item.
+ * This method should be overridden if there is a need for a faster implementation.
+ *
+ * @param menuBar the menubar
+ * @param path the path where to navigate in the menu.
+ * @param operator operator used for matching
+ * @return the adapter at the end of the specified path or a adapter that contains no component.
+ */
+ protected IMenuItemAdapter navigateToMenuItem(
+ IMenuAdapter menuBar, String[] path, String operator) {
+ checkPathLength(path.length);
+ IMenuAdapter currentmenu = menuBar;
+ IMenuItemAdapter currentMenuItem = null;
+ final int pathLength = path.length;
+ final int beforeLast = pathLength - 1;
+
+ for (int i = 0; i < path.length; i++) {
+ int pathIndex = getIndexForName(currentmenu, path[i], operator);
+ currentMenuItem = getNextMenuItem(currentmenu, pathIndex);
+
+ if ((currentMenuItem.getRealComponent() == null)
+ && (i < beforeLast)) {
+ return currentMenuItem;
+ }
+
+ if (i < beforeLast) {
+ if (!currentMenuItem.hasSubMenu()) {
+ // the given path is longer than the menu levels
+ return newMenuItemAdapter(null);
+ }
+ currentmenu = currentMenuItem.openSubMenu();
+ }
+ }
+ return currentMenuItem;
+ }
+
+ /**
+ * Tries to navigate through the menu to the specified menu item.
+ * This method should be overridden if there is a need for a faster implementation.
+ *
+ * @param menubar the menubar
+ * @param path the path where to navigate in the menu.
+ * @return -the adapter at the end of the specified path or a adapter that contains no component.
+ */
+ protected IMenuItemAdapter navigateToMenuItem(
+ IMenuAdapter menubar, int[] path) {
+ checkPathLength(path.length);
+
+ IMenuAdapter currentmenu = menubar;
+ IMenuItemAdapter currentMenuItem = null;
+ final int pathLength = path.length;
+ final int beforeLast = pathLength - 1;
+
+ for (int i = 0; i < path.length; i++) {
+ final int pathIndex = path[i];
+ currentMenuItem = getNextMenuItem(currentmenu, pathIndex);
+
+ if ((currentMenuItem.getRealComponent() == null)
+ && (i < beforeLast)) {
+ return currentMenuItem;
+ }
+
+ if (i < beforeLast) {
+ if (!currentMenuItem.hasSubMenu()) {
+ // the given path is longer than the menu levels
+ return newMenuItemAdapter(null);
+ }
+ currentmenu = currentMenuItem.openSubMenu();
+ }
+
+
+
+ }
+
+ return currentMenuItem;
+ }
+ /**
+ * gets the next menu item adapter from its specific index
+ * @param currentmenu the current menu
+ * @param pathIndex the index from the next menu item
+ * @return the wanted menu item in a adapter
+ */
+ private IMenuItemAdapter getNextMenuItem(IMenuAdapter currentmenu,
+ final int pathIndex) {
+ IMenuItemAdapter currentMenuItem;
+ if (pathIndex < 0) {
+ throwInvalidPathException();
+ }
+ currentMenuItem = findMenu(currentmenu, pathIndex);
+ return currentMenuItem;
+ }
+
+
+
+
+
+
+
+
+
+ /**
+ * @param menu menu
+ * @param idx index of the current wanted item
+ * @return the next IMenuItemAdapter from the next cascade
+ */
+ private IMenuItemAdapter findMenu(IMenuAdapter menu, int idx) {
+ List visibleSubMenus = new ArrayList();
+ IMenuItemAdapter[] subElements = menu.getItems();
+
+ for (int i = 0; i < subElements.length; ++i) {
+
+ IMenuItemAdapter menuitem = subElements[i];
+ if (menuitem.getRealComponent() != null && !menuitem.isSeparator()
+ && menuitem.isShowing()) {
+ visibleSubMenus.add(menuitem);
+ }
+
+ }
+
+ if (idx >= visibleSubMenus.size() || idx < 0) {
+ return newMenuItemAdapter(null);
+ }
+
+ return (IMenuItemAdapter) visibleSubMenus.get(idx);
+
+ }
+
+
+ /**
+ * Checks the path for it length and throws and StepExecutionExecption if it is 0
+ * @param length the path length to be checked
+ */
+ private void checkPathLength(int length) {
+ if (length < 1) {
+ throw new StepExecutionException("empty path to menuitem is not allowed", EventFactory //$NON-NLS-1$
+ .createActionError(
+ TestErrorEvent.INVALID_PARAM_VALUE));
+ }
+ }
+
+ /**
+ *
+ */
+ private static void throwInvalidPathException() {
+ throw new StepExecutionException("invalid path", EventFactory //$NON-NLS-1$
+ .createActionError(TestErrorEvent.INVALID_PARAM_VALUE));
+ }
+ /**
+ * This adapts or puts the new MenuItem in the context which is needed for
+ * the algorithms.
+ * @param component the new MenuItem which is used by the next step
+ * @return the adapted or casted MenuItem
+ */
+ protected abstract IMenuItemAdapter newMenuItemAdapter(Object component);
+
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTableCAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTableCAPs.java
new file mode 100644
index 000000000..b6411d943
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTableCAPs.java
@@ -0,0 +1,1094 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import java.awt.Rectangle;
+import org.eclipse.jubula.rc.common.CompSystemConstants;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.DragAndDropHelper;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.implclasses.table.Cell;
+import org.eclipse.jubula.rc.common.logger.AutServerLogger;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITableAdapter;
+import org.eclipse.jubula.tools.constants.InputConstants;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+
+/**
+ * General implementation for tables.
+ *
+ * @author BREDEX GmbH
+ */
+public abstract class AbstractTableCAPs extends AbstractTextInputSupport {
+
+ /** the logger */
+ private static AutServerLogger log = new AutServerLogger(
+ AbstractMenuCAPs.class);
+
+ /**
+ * @return the log
+ */
+ public static AutServerLogger getLog() {
+ return log;
+ }
+
+ /**
+ * This method is mostly needed for clicks
+ * @return the real table as object
+ */
+ private Object getRealTable() {
+ return getComponent().getRealComponent();
+ }
+ /**
+ *
+ * @return the ITableAdapter of this table
+ */
+ private ITableAdapter getTableAdapter() {
+ return (ITableAdapter) getComponent();
+ }
+
+ /**
+ * Verifies the rendered text inside the currently selected cell.
+ *
+ * @param text The cell text to verify.
+ * @throws StepExecutionException
+ * If there is no selected cell, or if the rendered text cannot
+ * be extracted.
+ */
+ public void gdVerifyText(String text)
+ throws StepExecutionException {
+
+ gdVerifyText(text, MatchUtil.DEFAULT_OPERATOR);
+ }
+
+ /**
+ * Verifies the rendered text inside the currently selected cell.
+ * @param text The cell text to verify.
+ * @param operator The operation used to verify
+ * @throws StepExecutionException If there is no selected cell, or if the rendered text cannot be extracted.
+ */
+ public void gdVerifyText(String text, String operator)
+ throws StepExecutionException {
+ ITableAdapter adapter = getTableAdapter();
+ Cell cell = adapter.getSelectedCell();
+ final int implRow = cell.getRow();
+ final int implCol = cell.getCol();
+ checkRowColBounds(implRow, implCol);
+
+ adapter.scrollCellToVisible(implRow, implCol);
+ final String current = getCellText(implRow, implCol);
+ Verifier.match(current, text, operator);
+ }
+
+ /**
+ * Verifies the rendered text inside the passed cell.
+ * @param row The row of the cell.
+ * @param rowOperator The row header operator
+ * @param col The column of the cell.
+ * @param colOperator The column header operator
+ * @param text The cell text to verify.
+ * @param operator The operation used to verify
+ * @throws StepExecutionException If the row or the column is invalid, or if the rendered text cannot be extracted.
+ */
+ public void gdVerifyText(String text, String operator, final String row,
+ final String rowOperator, final String col,
+ final String colOperator) throws StepExecutionException {
+ ITableAdapter adapter = getTableAdapter();
+ final int implRow = adapter.getRowFromString(row, rowOperator);
+ final int implCol = adapter.getColumnFromString(col, colOperator);
+ String current;
+ //if row is header and column is existing
+ if (implRow == -1 && implCol > -1) {
+ current = adapter.getColumnName(implCol);
+ } else {
+ checkRowColBounds(implRow, implCol);
+ adapter.scrollCellToVisible(implRow, implCol);
+ current = getCellText(implRow, implCol);
+ }
+
+
+
+
+ Verifier.match(current, text, operator);
+ }
+
+ /**
+ * Selects the cell of the Table.<br>
+ * With the xPos, yPos, xunits and yUnits the click position inside the cell can be defined.
+ * @param row The row of the cell.
+ * @param rowOperator The row header operator
+ * @param col The column of the cell.
+ * @param colOperator The column header operator
+ * @param clickCount The number of clicks with the right mouse button
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param extendSelection Should this selection be part of a multiple selection
+ * @param button what mouse button should be used
+ * @throws StepExecutionException If the row or the column is invalid
+ */
+ public void gdSelectCell(final String row, final String rowOperator,
+ final String col, final String colOperator,
+ final int clickCount, final int xPos, final String xUnits,
+ final int yPos, final String yUnits, final String extendSelection,
+ int button)
+ throws StepExecutionException {
+ ITableAdapter adapter = getTableAdapter();
+ final int implRow = adapter.getRowFromString(row, rowOperator);
+ final int implCol = adapter.getColumnFromString(col, colOperator);
+ final boolean isExtendSelection = extendSelection.equals(
+ CompSystemConstants.EXTEND_SELECTION_YES);
+ if (log.isDebugEnabled()) {
+ log.debug("Selecting row, col: " + row + ", " + col); //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ Rectangle cellBounds;
+ //if row is header and col is existing
+ if (implRow == -1 && implCol > -1) {
+ cellBounds = adapter.getHeaderBounds(implCol);
+ } else {
+ cellBounds = adapter.scrollCellToVisible(implRow, implCol);
+ }
+ Object o = getSpecificRectangle(cellBounds);
+ ClickOptions clickOptions = ClickOptions.create();
+ clickOptions.setClickCount(clickCount).setScrollToVisible(false);
+ clickOptions.setMouseButton(button);
+ try {
+ if (isExtendSelection) {
+ getRobot().keyPress(getRealTable(),
+ getExtendSelectionModifier());
+ }
+ getRobot().click(getRealTable(), o, clickOptions,
+ xPos, xUnits.equalsIgnoreCase(POS_UNIT_PIXEL),
+ yPos, yUnits.equalsIgnoreCase(POS_UNIT_PIXEL));
+ } finally {
+ if (isExtendSelection) {
+ getRobot().keyRelease(getRealTable(),
+ getExtendSelectionModifier());
+ }
+ }
+ }
+ /**
+ * This is a workaround because the toolkit specific
+ * Robot implementation are using different rectangle types.
+ * @param rectangle the java.awt.rectangle which needs to
+ * casted
+ * @return the rectangle in the type for the specific robot
+ */
+ protected Object getSpecificRectangle(Rectangle rectangle) {
+ //FIXME changing the Robots might be useful here
+ return rectangle;
+ }
+ /**
+ * Verifies, if value exists in column.
+ *
+ * @param col The column of the cell.
+ * @param colOperator the column header operator
+ * @param value The cell text to verify.
+ * @param operator The operation used to verify
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param exists true if value exists, false otherwise
+ * @throws StepExecutionException
+ * If the row or the column is invalid, or if the rendered text
+ * cannot be extracted.
+ */
+ public void gdVerifyValueInColumn(final String col,
+ final String colOperator, final String value,
+ final String operator, final String searchType, boolean exists)
+ throws StepExecutionException {
+ ITableAdapter adapter = getTableAdapter();
+ final int implCol = adapter.getColumnFromString(col, colOperator);
+
+
+ boolean valueExists = isValueExisting(adapter, implCol,
+ value, operator, searchType);
+
+ Verifier.equals(exists, valueExists);
+ }
+ /**
+ * Looks if value exists in the Column.
+ *
+ * @param adapter the teble adapter working on.
+ * @param implCol the implementation column of the cell.
+ * @param value the cellt text to verify.
+ * @param operator The operation used to verify.
+ * @param searchType searchType Determines where the search begins ("relative" or "absolute")
+ * @return <code>true</code> it the value exists in the column
+ */
+ private boolean isValueExisting(ITableAdapter adapter, int implCol,
+ String value, String operator, final String searchType) {
+ final int rowCount = adapter.getRowCount();
+ for (int i = getStartingRowIndex(searchType);
+ i < rowCount; ++i) {
+ if (MatchUtil.getInstance().match(getCellText(i,
+ implCol), value, operator)) {
+ return true;
+ }
+ }
+ if (adapter.isHeaderVisible()) {
+ String header = adapter.getColumnName(implCol);
+ if (MatchUtil.getInstance().match(header, value,
+ operator)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+
+ /**
+ * Verifies, if value exists in row..
+ *
+ * @param row The row of the cell.
+ * @param rowOperator the row header operator
+ * @param value The cell text to verify.
+ * @param operator The operation used to verify
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param exists true if value exists, false otherwise
+ * @throws StepExecutionException
+ * If the row or the column is invalid, or if the rendered text
+ * cannot be extracted.
+ */
+ public void gdVerifyValueInRow(final String row, final String rowOperator,
+ final String value, final String operator, final String searchType,
+ boolean exists)
+ throws StepExecutionException {
+ final ITableAdapter adapter = getTableAdapter();
+ final int implRow = adapter.getRowFromString(row, rowOperator);
+ boolean valueIsExisting = false;
+ //if row is header
+ if (implRow == -1) {
+
+ for (int k = getStartingColIndex(searchType);
+ k < adapter.getColumnCount(); ++k) {
+ if (MatchUtil.getInstance().match(
+ adapter.getColumnName(k),
+ value, operator)) {
+ valueIsExisting = true;
+ break;
+ }
+ }
+
+
+ } else {
+
+ final int columnCount = adapter.getColumnCount();
+ if (columnCount > 0) {
+ for (int i = getStartingColIndex(searchType);
+ i < columnCount; ++i) {
+ if (MatchUtil.getInstance().match(
+ getCellText(implRow, i), value, operator)) {
+ valueIsExisting = true;
+ break;
+ }
+ }
+ } else {
+ // No columns found. This table is used to present a
+ // list-like component.
+ if (MatchUtil.getInstance().match(
+ adapter.getRowName(implRow),
+ value, operator)) {
+ valueIsExisting = true;
+
+ }
+ }
+
+ }
+ Verifier.equals(exists, valueIsExisting);
+ }
+
+ /**
+ * Verifies the editable property of the given indices.
+ *
+ * @param editable
+ * The editable property to verify.
+ * @param row the row to select
+ * @param rowOperator the row header operator
+ * @param col the column to select
+ * @param colOperator the column header operator
+ */
+ public void gdVerifyEditable(boolean editable, String row,
+ String rowOperator, String col, String colOperator) {
+ //if row is header row
+
+ if (getTableAdapter().getRowFromString(row, rowOperator) == -1) {
+ throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
+ }
+ gdSelectCell(row, rowOperator, col, colOperator, ClickOptions.create(),
+ CompSystemConstants.EXTEND_SELECTION_NO);
+ gdVerifyEditable(editable);
+ }
+
+
+ /**
+ * Selects a table cell in the given row and column via click in the midle of the cell.
+ * @param row The row of the cell.
+ * @param rowOperator The row header operator
+ * @param col The column of the cell.
+ * @param colOperator The column header operator
+ * @param co the click options to use
+ * @param extendSelection Should this selection be part of a multiple selection
+ */
+ private void gdSelectCell(final String row, final String rowOperator,
+ final String col, final String colOperator,
+ final ClickOptions co, final String extendSelection) {
+
+ gdSelectCell(row, rowOperator, col, colOperator, co.getClickCount(),
+ 50, POS_UNI_PERCENT, 50, POS_UNI_PERCENT, extendSelection,
+ co.getMouseButton());
+ }
+
+
+ /**
+ * Verifies the rendered text inside cell at the mouse position on screen.
+ *
+ * @param text The cell text to verify.
+ * @param operator The operation used to verify
+ * @throws StepExecutionException If there is no selected cell, or if the
+ * rendered text cannot be extracted.
+ */
+ public void gdVerifyTextAtMousePosition(String text, String operator)
+ throws StepExecutionException {
+ if (isMouseOnHeader()) {
+ throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
+ }
+ Cell cell = getCellAtMousePosition();
+ gdVerifyText(text, operator,
+ Integer.toString(IndexConverter.toUserIndex(cell.getRow())),
+ MatchUtil.EQUALS,
+ Integer.toString(IndexConverter.toUserIndex(cell.getCol())),
+ MatchUtil.EQUALS);
+ }
+
+ /**
+ * Verifies the editable property of the selected cell.
+ *
+ * @param editable the editable property to verify.
+ */
+ public void gdVerifyEditableSelected(boolean editable) {
+ gdVerifyEditable(editable);
+ }
+
+ /**
+ * Verifies the editable property of the current selected cell.
+ *
+ * @param editable The editable property to verify.
+ */
+ public void gdVerifyEditable(boolean editable) {
+ Cell cell = getTableAdapter().getSelectedCell();
+
+ Verifier.equals(editable, getTableAdapter()
+ .isCellEditable(cell.getRow(), cell.getCol()));
+ }
+
+ /**
+ * Verifies the editable property of the cell under current mouse position.
+ *
+ * @param editable the editable property to verify.
+ */
+ public void gdVerifyEditableMousePosition(boolean editable) {
+ //if row is header row
+ if (isMouseOnHeader()) {
+ throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
+ }
+ Cell cell = getCellAtMousePosition();
+ boolean isEditable = getTableAdapter().isCellEditable(
+ cell.getRow(), cell.getCol());
+ Verifier.equals(editable, isEditable);
+ }
+ /**
+ * Finds the first row which contains the value <code>value</code>
+ * in column <code>col</code> and selects this row.
+ * @param col the column
+ * @param colOperator the column header operator
+ * @param value the value
+ * @param clickCount the number of clicks.
+ * @param regexOp the regex operator
+ * @param extendSelection Should this selection be part of a multiple selection
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param button what mouse button should be used
+ */
+ public void gdSelectRowByValue(String col, String colOperator,
+ final String value, final String regexOp, int clickCount,
+ final String extendSelection, final String searchType, int button) {
+ gdSelectRowByValue(col, colOperator, value, regexOp, extendSelection,
+ searchType, ClickOptions.create()
+ .setClickCount(clickCount)
+ .setMouseButton(button));
+ }
+
+ /**
+ * Finds the first row which contains the value <code>value</code>
+ * in column <code>col</code> and selects this row.
+ *
+ * @param col the column
+ * @param colOperator the column header operator
+ * @param value the value
+ * @param regexOp the regex operator
+ * @param extendSelection Should this selection be part of a multiple selection
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param co the clickOptions to use
+ */
+ protected void gdSelectRowByValue(String col, String colOperator,
+ final String value, final String regexOp, final String extendSelection,
+ final String searchType, ClickOptions co) {
+ ITableAdapter adapter = getTableAdapter();
+ final int implCol = adapter.getColumnFromString(col, colOperator);
+ Integer implRow = null;
+ final int rowCount = adapter.getRowCount();
+
+ for (int i = getStartingRowIndex(searchType); i < rowCount; ++i) {
+ if (MatchUtil.getInstance().match(getCellText(i, implCol),
+ value, regexOp)) {
+
+ implRow = new Integer(i);
+ break;
+ }
+ }
+ if (implRow == null) {
+ String header = adapter.getColumnName(implCol);
+ if (MatchUtil.getInstance().match(header, value, regexOp)) {
+ implRow = new Integer(-1);
+ }
+ }
+
+ if (implRow == null) {
+ throw new StepExecutionException("no such row found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+
+ String userIdxRow = new Integer(IndexConverter.toUserIndex(
+ implRow.intValue())).toString();
+ String userIdxCol = new Integer(IndexConverter.toUserIndex(
+ implCol)).toString();
+
+ gdSelectCell(userIdxRow, MatchUtil.EQUALS, userIdxCol, colOperator, co,
+ extendSelection);
+ }
+
+ /**
+ * Finds the first column which contains the value <code>value</code>
+ * in the given row and selects the cell.
+ *
+ * @param row the row to select
+ * @param rowOperator the row header operator
+ * @param value the value
+ * @param clickCount the number of clicks
+ * @param regex search using regex
+ * @param extendSelection Should this selection be part of a multiple selection
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param button what mouse button should be used
+ */
+ public void gdSelectCellByColValue(String row, String rowOperator,
+ final String value, final String regex, int clickCount,
+ final String extendSelection, final String searchType, int button) {
+ gdSelectCellByColValue(row, rowOperator, value, regex, extendSelection,
+ searchType, ClickOptions.create()
+ .setClickCount(clickCount)
+ .setMouseButton(button));
+ }
+
+ /**
+ * Finds the first column which contains the value <code>value</code>
+ * in the given row and selects the cell.
+ *
+ * @param row the row
+ * @param rowOperator the row header operator
+ * @param value the value
+ * @param regex search using regex
+ * @param extendSelection Should this selection be part of a multiple selection
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param co the click options to use
+ */
+ protected void gdSelectCellByColValue(String row, String rowOperator,
+ final String value, final String regex, final String extendSelection,
+ final String searchType, ClickOptions co) {
+ ITableAdapter adapter = getTableAdapter();
+ final int implRow = adapter.getRowFromString(row, rowOperator);
+ int colCount = adapter.getColumnCount();
+ Integer implCol = null;
+ if (implRow == -1) {
+
+ for (int i = getStartingColIndex(searchType); i < colCount; ++i) {
+ if (MatchUtil.getInstance().match(adapter.getColumnName(i),
+ value, regex)) {
+ implCol = new Integer(i);
+ break;
+ }
+ }
+ } else {
+ for (int i = getStartingColIndex(searchType); i < colCount; ++i) {
+ if (MatchUtil.getInstance().match(getCellText(implRow, i),
+ value, regex)) {
+
+ implCol = new Integer(i);
+ break;
+ }
+ }
+ }
+ if (implCol == null) {
+ throw new StepExecutionException("no such cell found", EventFactory //$NON-NLS-1$
+ .createActionError(TestErrorEvent.NOT_FOUND));
+ }
+
+ String usrIdxRowStr = new Integer(IndexConverter.toUserIndex(
+ implRow)).toString();
+ String usrIdxColStr = new Integer(IndexConverter.toUserIndex(
+ implCol.intValue())).toString();
+
+ gdSelectCell(usrIdxRowStr, rowOperator, usrIdxColStr, MatchUtil.EQUALS,
+ co, extendSelection);
+
+ }
+//FIXME
+// /**
+// * Action to read the value of the current selected cell of the JTable
+// * to store it in a variable in the Client
+// * @param variable the name of the variable
+// * @return the text value.
+// */
+// public String gdReadValue(String variable) {
+// final Cell selectedCell = getTableAdapter().getSelectedCell();
+// return getCellText(selectedCell.getRow(), selectedCell.getCol());
+// }
+
+ /**
+ * Action to read the value of the passed cell of the JTable
+ * to store it in a variable in the Client
+ * @param variable the name of the variable
+ * @param row the row to select
+ * @param rowOperator the row header operator
+ * @param col the column to select
+ * @param colOperator the column header operator
+ * @return the text value.
+ */
+ public String gdReadValue(String variable, String row, String rowOperator,
+ String col, String colOperator) {
+ ITableAdapter adapter = getTableAdapter();
+ final int implRow = adapter.getRowFromString(row, rowOperator);
+ final int implCol = adapter.getColumnFromString(col, colOperator);
+
+ //if row is header and column is existing
+ if (implRow == -1 && implCol > -1) {
+ return adapter.getColumnName(implCol);
+ }
+
+ checkRowColBounds(implRow, implCol);
+
+ adapter.scrollCellToVisible(implRow, implCol);
+ return getCellText(implRow, implCol);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String gdReadValueAtMousePosition(String variable) {
+ Cell cellAtMousePosition = getTableAdapter().getSelectedCell();
+ return getCellText(cellAtMousePosition.getRow(),
+ cellAtMousePosition.getCol());
+ }
+
+ /**
+ * Tries to click in the cell under the mouse position. If the mouse is not
+ * over a cell, the current selected cell will be clicked on. If there is no
+ * selected cell, the middle of the table is used to click on.
+ * @param count Number of clicks
+ * @param button The mouse button
+ */
+ public void gdClick(int count, int button) {
+ ITableAdapter adapter = getTableAdapter();
+ Cell cell = null;
+ if (isMouseOverCell()) {
+ cell = getCellAtMousePosition();
+ } else if (adapter.hasCellSelection()) {
+ cell = adapter.getSelectedCell();
+ }
+ if (cell != null) {
+ Rectangle cellRect =
+ adapter.scrollCellToVisible(cell.getRow(), cell.getCol());
+ getRobot().click(getRealTable(), cellRect, ClickOptions.create()
+ .setClickCount(count).setMouseButton(button));
+ } else {
+ super.gdClick(count, button);
+ }
+ }
+
+ /**
+ * Selects a cell relative to the cell at the current mouse position.
+ * If the mouse is not at any cell, the current selected cell is used.
+ * @param direction the direction to move.
+ * @param cellCount the amount of cells to move
+ * @param clickCount the click count to select the new cell.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param extendSelection Should this selection be part of a multiple selection
+ * @throws StepExecutionException if any error occurs
+ */
+ public void gdMove(String direction, int cellCount, int clickCount,
+ final int xPos, final String xUnits,
+ final int yPos, final String yUnits, final String extendSelection)
+ throws StepExecutionException {
+ if (isMouseOnHeader()) {
+ throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
+ }
+ Cell currCell = null;
+ try {
+ currCell = getCellAtMousePosition();
+ } catch (StepExecutionException e) {
+ currCell = getTableAdapter().getSelectedCell();
+ }
+ int newCol = currCell.getCol();
+ int newRow = currCell.getRow();
+ if (CompSystemConstants.TABLE_MOVE_UP
+ .equalsIgnoreCase(direction)) {
+ newRow -= cellCount;
+ } else if (CompSystemConstants.TABLE_MOVE_DOWN
+ .equalsIgnoreCase(direction)) {
+ newRow += cellCount;
+ } else if (CompSystemConstants.TABLE_MOVE_LEFT
+ .equalsIgnoreCase(direction)) {
+ newCol -= cellCount;
+ } else if (CompSystemConstants.TABLE_MOVE_RIGHT
+ .equalsIgnoreCase(direction)) {
+ newCol += cellCount;
+ }
+ newRow = IndexConverter.toUserIndex(newRow);
+ newCol = IndexConverter.toUserIndex(newCol);
+ String row = Integer.toString(newRow);
+ String col = Integer.toString(newCol);
+ gdSelectCell(row, MatchUtil.DEFAULT_OPERATOR , col,
+ MatchUtil.DEFAULT_OPERATOR, clickCount, xPos,
+ xUnits, yPos, yUnits, extendSelection,
+ InputConstants.MOUSE_BUTTON_LEFT);
+// gdSelectCell(newRow, newCol, clickCount,
+// xPos, xUnits, yPos, yUnits, extendSelection);
+ }
+
+ /**
+ * Writes the passed text into the currently selected cell.
+ *
+ * @param text
+ * The text.
+ * @throws StepExecutionException
+ * If there is no selected cell, or if the cell is not editable,
+ * or if the table cell editor permits the text to be written.
+ */
+ public void gdInputText(final String text) throws StepExecutionException {
+ inputText(text, false);
+ }
+
+ /**
+ * Types the text in the specified cell.
+ * @param text The text
+ * @param row The row of the cell.
+ * @param rowOperator The row operator
+ * @param col The column of the cell.
+ * @param colOperator The column operator
+ * @throws StepExecutionException If the text input fails
+ */
+ public void gdInputText(String text, String row, String rowOperator,
+ String col, String colOperator)
+ throws StepExecutionException {
+ //if row is header row
+ if (getTableAdapter().getRowFromString(row, rowOperator) == -1) {
+ throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
+ }
+ gdSelectCell(row, rowOperator, col, colOperator,
+ ClickOptions.create().setClickCount(1),
+ CompSystemConstants.EXTEND_SELECTION_NO);
+ gdInputText(text);
+ }
+
+ /**
+ * Types <code>text</code> into the component. This replaces the shown
+ * content in the current selected cell.
+ *
+ * @param text the text to type in
+ * @throws StepExecutionException
+ * If there is no selected cell, or if the cell is not editable,
+ * or if the table cell editor permits the text to be written.
+ */
+ public void gdReplaceText(String text) throws StepExecutionException {
+ inputText(text, true);
+ }
+
+ /**
+ * Replaces the given text in the given cell coordinates
+ * @param text the text to replace
+ * @param row The row of the cell.
+ * @param rowOperator The row operator
+ * @param col The column of the cell.
+ * @param colOperator The column operator
+ */
+ public void gdReplaceText(String text, String row, String rowOperator,
+ String col, String colOperator) {
+ //if row is header row
+ if (getTableAdapter().getRowFromString(row, rowOperator) == -1) {
+ throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
+ }
+ gdSelectCell(row, rowOperator, col, colOperator,
+ ClickOptions.create().setClickCount(1),
+ CompSystemConstants.EXTEND_SELECTION_NO);
+ inputText(text, true);
+ }
+
+ /**
+ * Drags the cell of the Table.<br>
+ * With the xPos, yPos, xunits and yUnits the click position inside the
+ * cell can be defined.
+ *
+ * @param mouseButton the mouseButton.
+ * @param modifier the modifier.
+ * @param row the row to select
+ * @param rowOperator the row header operator
+ * @param col the column to select
+ * @param colOperator the column header operator
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @throws StepExecutionException
+ * If the row or the column is invalid
+ */
+ public void gdDragCell(final int mouseButton, final String modifier,
+ final String row, final String rowOperator,
+ final String col, final String colOperator, final int xPos,
+ final String xUnits, final int yPos, final String yUnits)
+ throws StepExecutionException {
+
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ dndHelper.setModifier(modifier);
+ dndHelper.setMouseButton(mouseButton);
+ dndHelper.setDragComponent(null);
+ gdSelectCell(row, rowOperator, col, colOperator, 0, xPos, xUnits, yPos,
+ yUnits, CompSystemConstants.EXTEND_SELECTION_NO, 1);
+ pressOrReleaseModifiers(modifier, true);
+ getRobot().mousePress(null, null, mouseButton);
+ }
+
+ /**
+ * Drops on the cell of the JTable.<br>
+ * With the xPos, yPos, xunits and yUnits the click position inside the
+ * cell can be defined.
+ *
+ * @param row the row to select
+ * @param rowOperator the row header operator
+ * @param col the column to select
+ * @param colOperator the column header operator
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ * @throws StepExecutionException
+ * If the row or the column is invalid
+ */
+ public void gdDropCell(final String row, final String rowOperator,
+ final String col, final String colOperator, final int xPos,
+ final String xUnits, final int yPos, final String yUnits,
+ int delayBeforeDrop) throws StepExecutionException {
+
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ try {
+ gdSelectCell(row, rowOperator, col, colOperator, 0, xPos, xUnits,
+ yPos, yUnits, CompSystemConstants.EXTEND_SELECTION_NO, 1);
+ waitBeforeDrop(delayBeforeDrop);
+ } finally {
+ getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(), false);
+ }
+ }
+
+ /**
+ * Finds the first row which contains the value <code>value</code>
+ * in column <code>col</code> and drags this row.
+ *
+ * @param mouseButton the mouse button
+ * @param modifier the modifier
+ * @param col the column
+ * @param colOperator the column header operator
+ * @param value the value
+ * @param regexOp the regex operator
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ */
+ public void gdDragRowByValue(int mouseButton, String modifier, String col,
+ String colOperator, final String value, final String regexOp,
+ final String searchType) {
+
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ dndHelper.setModifier(modifier);
+ dndHelper.setMouseButton(mouseButton);
+ gdSelectRowByValue(col, colOperator, value, regexOp, 1,
+ CompSystemConstants.EXTEND_SELECTION_NO, searchType, 1);
+ pressOrReleaseModifiers(modifier, true);
+ getRobot().mousePress(null, null, mouseButton);
+ }
+
+ /**
+ * Finds the first row which contains the value <code>value</code>
+ * in column <code>col</code> and drops on this row.
+ *
+ * @param col the column to select
+ * @param colOperator the column header operator
+ * @param value the value
+ * @param regexOp the regex operator
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ */
+ public void gdDropRowByValue(String col, String colOperator,
+ final String value, final String regexOp, final String searchType,
+ int delayBeforeDrop) {
+
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ try {
+ gdSelectRowByValue(col, colOperator, value, regexOp,
+ CompSystemConstants.EXTEND_SELECTION_NO,
+ searchType, ClickOptions
+ .create().setClickCount(0));
+ waitBeforeDrop(delayBeforeDrop);
+ } finally {
+ getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(), false);
+ }
+ }
+
+ /**
+ * Finds the first column which contains the value <code>value</code>
+ * in the given row and drags the cell.
+ *
+ * @param mouseButton the mouse button
+ * @param modifier the modifiers
+ * @param row the row to select
+ * @param rowOperator the row header operator
+ * @param value the value
+ * @param regex search using regex
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ */
+ public void gdDragCellByColValue(int mouseButton, String modifier,
+ String row, String rowOperator, final String value,
+ final String regex, final String searchType) {
+
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ dndHelper.setModifier(modifier);
+ dndHelper.setMouseButton(mouseButton);
+
+ gdSelectCellByColValue(row, rowOperator, value, regex,
+ CompSystemConstants.EXTEND_SELECTION_NO, searchType,
+ ClickOptions.create().setClickCount(0));
+ pressOrReleaseModifiers(modifier, true);
+ getRobot().mousePress(null, null, mouseButton);
+ }
+
+ /**
+ * Finds the first column which contains the value <code>value</code>
+ * in the given row and drops on the cell.
+ *
+ * @param row the row to select
+ * @param rowOperator the row header operator
+ * @param value the value
+ * @param regex search using regex
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ */
+ public void gdDropCellByColValue(String row, String rowOperator,
+ final String value, final String regex, final String searchType,
+ int delayBeforeDrop) {
+
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ try {
+ gdSelectCellByColValue(row, rowOperator, value, regex,
+ CompSystemConstants.EXTEND_SELECTION_NO, searchType,
+ ClickOptions.create().setClickCount(0));
+ waitBeforeDrop(delayBeforeDrop);
+ } finally {
+ getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(), false);
+ }
+ }
+
+
+ /**
+ * Gets the text from the specific cell which is given
+ * by the row and the column.
+ * @param row the zero based index of the row
+ * @param column the zero based index of the column
+ * @return the text of the cell of the given coordinates
+ */
+ private String getCellText(final int row, final int column) {
+ return getTableAdapter().getCellText(row, column);
+
+ }
+
+ /**
+ * Checks whether <code>0 <= value < count</code>.
+ * @param value The value to check.
+ * @param count The upper bound.
+ */
+ private void checkBounds(int value, int count) {
+ if (value < 0 || value >= count) {
+ throw new StepExecutionException("Invalid row/column: " + value, //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.INVALID_INDEX_OR_HEADER));
+ }
+ }
+
+ /**
+ * Checks if the passed row and column are inside the bounds of the Table.
+ * @param row The row
+ * @param column The column
+ * @throws StepExecutionException If the row or the column is outside of the Table's bounds.
+ */
+ protected void checkRowColBounds(int row, int column)
+ throws StepExecutionException {
+ ITableAdapter adapter = getTableAdapter();
+ checkBounds(row, adapter.getRowCount());
+
+ // Corner case: Only check the bounds if the table is not being
+ // used as a list or anything other than the first column
+ // is being checked.
+ int colCount = adapter.getColumnCount();
+ if (colCount > 0 || column > 0) {
+ checkBounds(column, colCount);
+ }
+ }
+
+ /**
+ * @param searchType Determines column where the search begins ("relative" or "absolute")
+ * @return The index from which to begin a search, based on the search type
+ * and (if appropriate) the currently selected cell.
+ */
+ private int getStartingColIndex(String searchType) {
+ int startingIndex = 0;
+ if (searchType.equalsIgnoreCase(
+ CompSystemConstants.SEARCH_TYPE_RELATIVE)) {
+ startingIndex = getTableAdapter().getSelectedCell().getCol() + 1;
+ }
+ return startingIndex;
+ }
+
+ /**
+ * @param searchType Determines the row where the search begins ("relative" or "absolute")
+ * @return The index from which to begin a search, based on the search type
+ * and (if appropriate) the currently selected cell.
+ */
+ private int getStartingRowIndex(String searchType) {
+ int startingIndex = 0;
+ if (searchType.equalsIgnoreCase(
+ CompSystemConstants.SEARCH_TYPE_RELATIVE)) {
+ startingIndex = getTableAdapter().getSelectedCell().getRow() + 1;
+ }
+ return startingIndex;
+ }
+
+ /**
+ * inputs/replaces the given text
+ * @param text the text to input
+ * @param replace wheter to replace or not
+ * @throws StepExecutionException If there is no selected cell,
+ * or if the cell is not editable, or if the table cell editor permits
+ * the text to be written.
+ */
+ private void inputText(final String text, boolean replace)
+ throws StepExecutionException {
+ ITableAdapter adapter = getTableAdapter();
+
+ final Cell cell = adapter.getSelectedCell();
+ // Ensure that the cell is visible.
+ Rectangle rectangle =
+ adapter.scrollCellToVisible(cell.getRow(), cell.getCol());
+
+ Object editor = activateEditor(cell, rectangle);
+ editor = setEditorToReplaceMode(editor, replace);
+
+ getRobot().type(editor, text);
+ }
+
+ /**
+ * @return true if the mouse pointer is over any cell, false otherwise.
+ */
+ private boolean isMouseOverCell() {
+ try {
+ getCellAtMousePosition();
+ } catch (StepExecutionException se) {
+ return false;
+ }
+ return true;
+ }
+
+
+
+ /**
+ * Sets the specific editor to an replace mode. Means that the next key
+ * input will override the complete text of the editor.
+ * @param editor
+ * @param replace if <code>true</code> than the editor has to override
+ * the complete text with the next key input. Else the next
+ * key input will append to the end.
+ * @return the editor if it changed
+ */
+ protected abstract Object setEditorToReplaceMode(Object editor,
+ boolean replace);
+
+ /**
+ * Activates the editor of the specific cell.
+ * @param cell
+ * @param rectangle
+ * @return the editor of the cell
+ */
+ protected abstract Object activateEditor(Cell cell, Rectangle rectangle);
+
+
+ /**
+ * Gets The modifier for an extended selection (more than one item)
+ * @return the modifier
+ */
+ protected abstract int getExtendSelectionModifier();
+
+ /**
+ * @return the cell under the current mouse position.
+ * @throws StepExecutionException If no cell is found.
+ */
+ protected abstract Cell getCellAtMousePosition()
+ throws StepExecutionException;
+
+ /**
+ * Verifies if mouse is on header.
+ * @return true if mouse is on header
+ */
+ protected abstract boolean isMouseOnHeader();
+
+
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextComponent.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextComponent.java
new file mode 100644
index 000000000..3a67632f1
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextComponent.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITextComponentAdapter;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.jubula.tools.utils.TimeUtil;
+/**
+ * Implementation of the CAPs from all Text like components.
+ * @author BREDEX GmbH
+ *
+ */
+public class AbstractTextComponent extends AbstractTextInputSupport {
+
+ /**
+ * Gets the specific adapter
+ * @return the specific adapter
+ */
+ private ITextComponentAdapter getTextCompAdapter() {
+ return (ITextComponentAdapter) getComponent();
+ }
+
+ /**
+ * Sets the caret at the position <code>index</code>.
+ * @param index The caret position
+ */
+ private void setCaretPosition(final int index) {
+ if (index < 0) {
+ throw new StepExecutionException("Invalid position: " + index, //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.INPUT_FAILED));
+ }
+ int index2 = 0;
+ String text = getTextCompAdapter().getText();
+ if (text != null) {
+ index2 = index > text.length() ? text.length() : index;
+ }
+ getTextCompAdapter().setSelection(index2);
+ }
+
+ /**
+ * @param text The text to insert at the current caret position
+ */
+ protected void insertText(final String text) {
+ // Scroll it to visible first to ensure that the typing
+ // performs correctly.
+ getRobot().scrollToVisible(getComponent().getRealComponent(), null);
+ getRobot().type(getComponent().getRealComponent(), text);
+ }
+
+ /**
+ * Types <code>text</code> into the component. This replaces the shown
+ * content.
+ *
+ * @param text the text to type in
+ */
+ public void gdReplaceText(String text) {
+ gdSelect();
+ if (StringUtils.EMPTY.equals(text)) {
+ getRobot().keyStroke("DELETE"); //$NON-NLS-1$
+ }
+ insertText(text);
+ }
+
+ /**
+ * Types <code>text</code> into the component.
+ *
+ * @param text the text to type in
+ */
+ public void gdInputText(String text) {
+ if (!getTextCompAdapter().hasFocus()) {
+ TimeUtil.delay(100);
+ gdClick(1, 1);
+ }
+ insertText(text);
+ }
+
+ /**
+ * Inserts <code>text</code> at the position <code>index</code>.
+ *
+ * @param text The text to insert
+ * @param index The position for insertion
+ */
+ public void gdInsertText(String text, int index) {
+ gdClick(1, 1);
+ setCaretPosition(index);
+ insertText(text);
+ }
+
+ /**
+ * Inserts <code>text</code> before or after the first appearance of
+ * <code>pattern</code>.
+ * @param text The text to insert
+ * @param pattern The pattern to find the position for insertion
+ * @param operator Operator to select Matching Algorithm
+ * @param after If <code>true</code>, the text will be inserted after the
+ * pattern, otherwise before the pattern.
+ * @throws StepExecutionException If the pattern is invalid or cannot be found
+ */
+ public void gdInsertText(String text, String pattern, String operator,
+ boolean after)
+ throws StepExecutionException {
+
+ if (text == null) {
+ throw new StepExecutionException(
+ "The text to be inserted must not be null", EventFactory //$NON-NLS-1$
+ .createActionError());
+ }
+ final MatchUtil.FindResult matchedText = MatchUtil.getInstance().
+ find(getTextCompAdapter().getText(), pattern, operator);
+
+ if ((matchedText == null) || (matchedText.getStr() == null)) {
+ throw new StepExecutionException("The pattern '" + pattern //$NON-NLS-1$
+ + "' could not be found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+
+ int index = matchedText.getPos();
+
+ int insertPos = after ? index + matchedText.getStr().length() : index;
+ gdInsertText(text, insertPos);
+ }
+
+
+
+ /**
+ * select the whole text of the textfield by calling "selectAll()".
+ */
+ public void gdSelect() {
+ gdClick(1, 1);
+ // Wait a while. Without this, we got no selectAll sometimes!
+ TimeUtil.delay(100);
+ getTextCompAdapter().selectAll();
+ }
+
+ /**
+ * Verifies the editable property.
+ * @param editable The editable property to verify.
+ */
+ public void gdVerifyEditable(boolean editable) {
+ Verifier.equals(editable, getTextCompAdapter().isEditable());
+ }
+
+ /**
+ * Selects the first (not)appearance of <code>pattern</code> in the text
+ * component's content.
+ *
+ * @param pattern The pattern to select
+ * @param operator operator
+ * @throws StepExecutionException
+ * If the pattern is invalid or cannot be found
+ */
+ public void gdSelect(final String pattern, String operator)
+ throws StepExecutionException {
+ gdClick(1, 1);
+ final MatchUtil.FindResult matchedText = MatchUtil.getInstance().
+ find(getTextCompAdapter().getText(), pattern, operator);
+ if ((matchedText == null) || (matchedText.getStr().length() == 0)) {
+ throw new StepExecutionException("Invalid pattern for insertion", //$NON-NLS-1$
+ EventFactory.createActionError());
+ }
+ final int index = matchedText.getPos();
+ if (operator.startsWith("not")) { //$NON-NLS-1$
+ if (pattern.equals(getTextCompAdapter().getText())) {
+ String msg = "The pattern '" + pattern //$NON-NLS-1$
+ + "' is equal to current text"; //$NON-NLS-1$
+ throw new StepExecutionException(msg, EventFactory
+ .createActionError(TestErrorEvent
+ .EXECUTION_ERROR, new String[] {msg}));
+ } else if (index > 0) {
+ // select part before pattern
+ getTextCompAdapter().setSelection(0, index);
+ } else {
+ // select part after pattern
+ getTextCompAdapter().setSelection(
+ matchedText.getStr().length(),
+ getTextCompAdapter().getText().length());
+ }
+ } else {
+ getTextCompAdapter().setSelection(index,
+ index + matchedText.getStr().length());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ return null;
+ }
+
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextInputSupport.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextInputSupport.java
new file mode 100644
index 000000000..ba91ed623
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextInputSupport.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+
+/**
+ * This class represents the general implmentation for components,
+ * which have text input support.
+ *
+ * @author BREDEX GmbH
+ */
+public abstract class AbstractTextInputSupport extends AbstractTextVerifiable {
+
+ /**
+ * Verifies the editable property of the current component.<br>
+ * If it is a complex component, it is always the selected object.
+ * @param editable The editable property to verify.
+ */
+ public abstract void gdVerifyEditable(boolean editable);
+ // FIXME this is only a pattern because only Tables uses this at the moment
+ /**
+ * Types <code>text</code> into the component. This replaces the shown
+ * content.<br>
+ * If it is a complex component, it is always the selected object.
+ * @param text the text to type in
+ * @throws StepExecutionException
+ * If there is no selected cell, or if the cell is not editable,
+ * or if the table cell editor permits the text to be written.
+ */
+ public abstract void gdReplaceText(String text)
+ throws StepExecutionException;
+ // FIXME this is only a pattern because only Tables uses this at the moment
+ /**
+ * Writes the passed text into the currently component.<br>
+ * If it is a complex component, it is always the selected object.
+ * @param text The text.
+ * @throws StepExecutionException
+ * If there is no selected cell, or if the cell is not editable,
+ * or if the table cell editor permits the text to be written.
+ */
+ public abstract void gdInputText(final String text)
+ throws StepExecutionException;
+ // FIXME this is only a pattern because only Tables uses this at the moment
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextVerifiable.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextVerifiable.java
new file mode 100644
index 000000000..ac23efbf5
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextVerifiable.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITextVerifiable;
+
+/**
+ * This class represents the general implementation for components
+ * which have readable text.
+ *
+ * @author BREDEX GmbH
+ */
+public abstract class AbstractTextVerifiable extends AbstractWidgetCAPs {
+
+ /**
+ * Action to read the value of the current component
+ * to store it in a variable in the Client.<br>
+ * If it is a complex component, it is always the selected object.
+ * @param variable the name of the variable
+ * @return the text value.
+ */
+ public String gdReadValue(String variable) {
+ return ((ITextVerifiable)getComponent()).getText();
+ }
+
+ /**
+ * Verifies the rendered text inside the currently component.<br>
+ * If it is a complex component, it is always the selected object.
+ * @param text The text to verify.
+ * @param operator The operation used to verify
+ * @throws StepExecutionException If the rendered text cannot be extracted.
+ */
+ public void gdVerifyText(String text, String operator)
+ throws StepExecutionException {
+ Verifier.match(((ITextVerifiable)getComponent()).getText(), text,
+ operator);
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTreeCAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTreeCAPs.java
new file mode 100644
index 000000000..b1e153b5a
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTreeCAPs.java
@@ -0,0 +1,754 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.commons.lang.Validate;
+import org.eclipse.jubula.rc.common.CompSystemConstants;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.exception.StepVerifyFailedException;
+import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeNodeTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeOperationContext;
+import org.eclipse.jubula.rc.common.implclasses.tree.ChildTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.ExpandCollapseTreeNodeOperation;
+import org.eclipse.jubula.rc.common.implclasses.tree.INodePath;
+import org.eclipse.jubula.rc.common.implclasses.tree.IndexNodePath;
+import org.eclipse.jubula.rc.common.implclasses.tree.ParentTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.PathBasedTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.SelectTreeNodeOperation;
+import org.eclipse.jubula.rc.common.implclasses.tree.SiblingTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.StringNodePath;
+import org.eclipse.jubula.rc.common.implclasses.tree.TreeNodeOperation;
+import org.eclipse.jubula.rc.common.implclasses.tree.TreeNodeOperationConstraint;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITreeAdapter;
+import org.eclipse.jubula.tools.constants.StringConstants;
+import org.eclipse.jubula.tools.constants.TestDataConstants;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.jubula.tools.utils.StringParsing;
+
+
+/**
+ * General implementation for Trees.
+ *
+ * @author BREDEX GmbH
+ */
+public abstract class AbstractTreeCAPs extends AbstractWidgetCAPs {
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ //FIXME is here an TextArray?
+ return null;
+ }
+
+ /**
+ * This method is only casting the IComponentAdapter to the wanted ITreeAdapter
+ * @return The ITreeAdapter out of the stored IComponentAdapter
+ */
+ private ITreeAdapter getTreeAdapter() {
+ return (ITreeAdapter)getComponent();
+
+ }
+
+ /**
+ * Verifies the text of the Node at mousePosition
+ * @param text the text to check
+ * @param operator the operator for the verification
+ */
+ public abstract void gdVerifyTextAtMousePosition(
+ String text,
+ String operator);
+ /**
+ * Splits the <code>treepath</code> string into an array, one entry for each level in the path
+ *
+ * @param treePath The tree path
+ * @return An array of string representing the tree path
+ */
+ protected String[] splitTextTreePath(String treePath) {
+ return StringParsing.splitToArray(treePath,
+ TestDataConstants.PATH_CHAR_DEFAULT,
+ TestDataConstants.ESCAPE_CHAR_DEFAULT,
+ true);
+ }
+
+ /**
+ * Splits the <code>treepath</code> string into an array, one entry for each level in the path
+ *
+ * @param treePath The tree path
+ * @return An array of indices (type <code>Integer</code>) representing
+ * the tree path
+ * @throws StepExecutionException
+ * If the values of the passed path cannot be parsed
+ */
+ protected Integer[] splitIndexTreePath(String treePath)
+ throws StepExecutionException {
+ Integer[] indexPath = null;
+ String[] path = splitTextTreePath(treePath);
+ if (path != null) {
+ indexPath = new Integer[path.length];
+ for (int i = 0; i < path.length; i++) {
+ indexPath[i] = new Integer(IndexConverter.intValue(path[i]));
+ }
+ }
+ return IndexConverter.toImplementationIndices(indexPath);
+ }
+
+ /**
+ * Splits the <code>treepath</code> string into an array, one entry for each level in the path
+ *
+ * @param treePath The tree path
+ * @param operator The operator
+ * @return An array of string representing the tree path
+ */
+ protected INodePath createStringNodePath(String [] treePath,
+ String operator) {
+ return new StringNodePath(treePath, operator);
+ }
+
+ /**
+ * Splits the <code>treepath</code> string into an array, one entry for each level in the path
+ *
+ * @param treePath The tree path
+ * @return An array of string representing the tree path
+ */
+ protected INodePath createIndexNodePath(Integer [] treePath) {
+ return new IndexNodePath(treePath);
+ }
+
+
+ /**
+ * Traverses the tree by searching for the nodes in the tree
+ * path entry and calling the given operation on each matching node.
+ *
+ * @param treePath The tree path.
+ * @param pathType For example, "relative" or "absolute".
+ * @param preAscend Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param operation The tree node operation.
+ * @throws StepExecutionException If the path traversion fails.
+ */
+ protected void traverseTreeByPath(INodePath treePath, String pathType,
+ int preAscend, TreeNodeOperation operation)
+ throws StepExecutionException {
+
+ Validate.notNull(treePath);
+ Validate.notNull(operation);
+
+ ITreeAdapter adapter = getTreeAdapter();
+ AbstractTreeOperationContext context = adapter.getContext();
+
+ AbstractTreeNodeTraverser traverser =
+ new PathBasedTraverser(context, treePath);
+
+ traverser.traversePath(operation,
+ getStartNode(pathType, preAscend, context));
+
+ }
+
+ /**
+ * Traverses the tree by searching for the nodes in the tree
+ * path entry and calling the given operation on the last element in the path.
+ * @param treePath The tree path.
+ * @param pathType For example, "relative" or "absolute".
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param operation The tree node operation.
+ * @throws StepExecutionException If the path traversion fails.
+ */
+ protected void traverseLastElementByPath(INodePath treePath,
+ String pathType, int preAscend, TreeNodeOperation operation)
+ throws StepExecutionException {
+
+ Validate.notNull(treePath);
+ Validate.notNull(operation);
+
+ AbstractTreeOperationContext context = getTreeAdapter().getContext();
+ Object startNode = getStartNode(pathType, preAscend, context);
+
+ AbstractTreeNodeTraverser traverser = new PathBasedTraverser(
+ context, treePath, new TreeNodeOperationConstraint());
+
+ traverser.traversePath(operation, startNode);
+ }
+
+ /**
+ * @param pathType pathType
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param objectPath objectPath
+ * @param co the click options to use
+ */
+ private void selectByPath(String pathType, int preAscend,
+ INodePath objectPath, ClickOptions co) {
+
+ TreeNodeOperation expOp = new ExpandCollapseTreeNodeOperation(false);
+ TreeNodeOperation selectOp = new SelectTreeNodeOperation(co);
+ INodePath subPath = objectPath.subPath(0, objectPath.getLength() - 1);
+
+ traverseTreeByPath(subPath, pathType, preAscend, expOp);
+ traverseLastElementByPath(objectPath, pathType, preAscend, selectOp);
+ }
+
+ /**
+ * Returns the selected node
+ * @param context context
+ * @return node
+ */
+ protected Object getSelectedNode(AbstractTreeOperationContext context) {
+ return context.getSelectedNode();
+ }
+
+ /**
+ * Clicks the tree.
+ * If the mouse pointer is in the tree no mouse move will be perfomed.
+ * Otherwise, the mouse is first moved to the center of the tree.
+ *
+ * @param count Number of mouse clicks
+ * @param button Pressed button
+ */
+ public void gdClick(int count, int button) {
+ if (getRobot().isMouseInComponent(
+ getTreeAdapter().getRealComponent())) {
+ getRobot().clickAtCurrentPosition(
+ getTreeAdapter().getRealComponent(), count, button);
+ } else {
+ getRobot().click(getTreeAdapter().getRealComponent(), null,
+ ClickOptions.create().setClickCount(count)
+ .setMouseButton(button));
+ }
+ }
+
+ /**
+ * Collapses the JTree. The passed tree path is a slash-seperated list of
+ * nodes that specifies a valid top-down path in the JTree. The last node of
+ * the tree path is collapsed if it is currently expanded. Otherwise, the JTree is
+ * left unchanged.
+ *
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param treePath The tree path.
+ * @param operator
+ * Whether regular expressions are used to determine the tree path.
+ * <code>"matches"</code> for regex, <code>"equals"</code> for simple matching.
+ * @throws StepExecutionException
+ * If the tree path is invalid or the double click to collapse
+ * the node fails.
+ */
+ public void gdCollapse(String pathType, int preAscend,
+ String treePath, String operator) throws StepExecutionException {
+ traverseLastElementByPath(
+ createStringNodePath(splitTextTreePath(treePath), operator),
+ pathType, preAscend,
+ new ExpandCollapseTreeNodeOperation(true));
+ }
+
+ /**
+ * Collapses the tree. This method works like {@link #gdCollapse(String, int, String, String)},
+ * but expects an enumeration of indices representing the top-down tree
+ * path. Any index is the node's position at the current tree level.
+ *
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param indexPath The index path
+ * @throws StepExecutionException
+ * If the tree path is invalid or the double-click to collapse
+ * the node fails.
+ */
+ public void gdCollapseByIndices(String pathType, int preAscend,
+ String indexPath) throws StepExecutionException {
+
+ try {
+ traverseLastElementByPath(
+ createIndexNodePath(splitIndexTreePath(indexPath)),
+ pathType, preAscend,
+ new ExpandCollapseTreeNodeOperation(true));
+ } catch (NumberFormatException e) {
+ throw new StepExecutionException(e.getMessage(), EventFactory
+ .createActionError(TestErrorEvent.INVALID_INDEX));
+ }
+ }
+
+ /**
+ * <p>
+ * Expands the Tree. Any node defined by the passed tree path is expanded,
+ * if it is collapsed. The node is expanded by performing a double click
+ * onto the node. If the node is already expanded, the JTree is left
+ * unchanged. The tree path is a slash-seperated list of nodes that specifies
+ * a valid top-down path in the JTree.
+ * </p>
+ *
+ * An example: Say the passed tree path is <code>animals/birds/kakadu</code>.
+ * To get a valid expansion, the JTree has to look as follows:
+ *
+ * <pre>
+ * animals
+ * |
+ * - -- birds
+ * |
+ * - -- kakadu
+ * </pre>
+ *
+ * <code>animals</code> is the Tree's root node, if the root node has
+ * been set to visible,
+ * or it is one of the root node's children, if the root node has been set
+ * to invisible.
+ *
+ * <p>
+ * It is important to know that the tree path entries have to match the
+ * rendered node texts, but not the underlying user object data etc.
+ * </p>
+ *
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param treePath
+ * The tree path.
+ * @param operator
+ * If regular expressions are used to determine the tree path
+ * @throws StepExecutionException
+ * If the tree path is invalid or the double click fails.
+ */
+ public void gdExpand(String pathType, int preAscend,
+ String treePath, String operator) throws StepExecutionException {
+ traverseTreeByPath(
+ createStringNodePath(splitTextTreePath(treePath), operator),
+ pathType, preAscend,
+ new ExpandCollapseTreeNodeOperation(false));
+ }
+
+ /**
+ * Expands the tree. This method works like {@link #gdExpand(String, int, String, String)}, but
+ * expects an enumeration of indices representing the top-down tree path.
+ * Any index is the node's position at the current tree level.
+ *
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param indexPath The index path
+ * @throws StepExecutionException
+ * If the tree path is invalid or the double-click fails.
+ */
+ public void gdExpandByIndices(String pathType, int preAscend,
+ String indexPath) throws StepExecutionException {
+
+ try {
+ traverseTreeByPath(
+ createIndexNodePath(splitIndexTreePath(indexPath)),
+ pathType, preAscend,
+ new ExpandCollapseTreeNodeOperation(false));
+ } catch (NumberFormatException e) {
+ throw new StepExecutionException(e.getMessage(), EventFactory
+ .createActionError(TestErrorEvent.INVALID_INDEX));
+ }
+ }
+
+
+
+ /**
+ * Selects a node relative to the currently selected node.
+ * @param direction the direction to move.
+ * directions:
+ * UP - Navigates through parents
+ * DOWN - Navigates through children
+ * NEXT - Navigates to next sibling
+ * PREVIOUS - Navigates to previous sibling
+ * @param distance the distance to move
+ * @param clickCount the click count to select the new cell.
+ * @throws StepExecutionException if any error occurs
+ */
+ public void gdMove(String direction, int distance, int clickCount)
+ throws StepExecutionException {
+
+ AbstractTreeOperationContext context = getTreeAdapter().getContext();
+
+ Object selectedNode = getSelectedNode(context);
+
+ TreeNodeOperation selectOp =
+ new SelectTreeNodeOperation(
+ ClickOptions.create().setClickCount(clickCount));
+ TreeNodeOperationConstraint constraint =
+ new TreeNodeOperationConstraint();
+
+ if (CompSystemConstants.TREE_MOVE_UP.equalsIgnoreCase(direction)) {
+ AbstractTreeNodeTraverser traverser =
+ new ParentTraverser(context, distance, constraint);
+ traverser.traversePath(selectOp, selectedNode);
+ } else if (CompSystemConstants
+ .TREE_MOVE_DOWN.equalsIgnoreCase(direction)) {
+ TreeNodeOperation expandOp =
+ new ExpandCollapseTreeNodeOperation(false);
+ AbstractTreeNodeTraverser expandTraverser =
+ new ChildTraverser(context, distance - 1);
+ expandTraverser.traversePath(expandOp, selectedNode);
+
+ AbstractTreeNodeTraverser selectTraverser =
+ new ChildTraverser(context, distance, constraint);
+ selectTraverser.traversePath(selectOp, selectedNode);
+
+ } else if (CompSystemConstants
+ .TREE_MOVE_NEXT.equalsIgnoreCase(direction)) {
+ // Look through siblings
+ AbstractTreeNodeTraverser traverser =
+ new SiblingTraverser(context, distance, true, constraint);
+ traverser.traversePath(selectOp, selectedNode);
+
+ } else if (CompSystemConstants
+ .TREE_MOVE_PREVIOUS.equalsIgnoreCase(direction)) {
+ // Look through siblings
+ AbstractTreeNodeTraverser traverser =
+ new SiblingTraverser(context, distance, false, constraint);
+ traverser.traversePath(selectOp, selectedNode);
+ }
+
+ }
+
+ /**
+ * Selects the node at the end of the <code>treepath</code>.
+ *
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param treePath The tree path.
+ * @param operator If regular expressions are used to match the tree path
+ * @param clickCount the click count
+ * @param button what mouse button should be used
+ * @param extendSelection Whether this selection extends a previous
+ * selection.
+ * @throws StepExecutionException If the tree path is invalid, if the
+ * double-click to expand the node fails, or if the selection is invalid.
+ */
+ public void gdSelect(String pathType, int preAscend, String treePath,
+ String operator, int clickCount, int button,
+ final String extendSelection)
+ throws StepExecutionException {
+ selectByPath(pathType, preAscend,
+ createStringNodePath(splitTextTreePath(treePath), operator),
+ ClickOptions.create()
+ .setClickCount(clickCount)
+ .setMouseButton(button)
+ .setClickModifier(getClickModifier(extendSelection)));
+ }
+ /**
+ * Selects the last node of the path given by <code>indexPath</code>
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param indexPath the index path
+ * @param clickCount the number of times to click
+ * @param button what mouse button should be used
+ * @param extendSelection Whether this selection extends a previous
+ * selection.
+ * @throws StepExecutionException if <code>indexPath</code> is not a valid
+ * path
+ */
+ public void gdSelectByIndices(String pathType, int preAscend,
+ String indexPath, int clickCount, int button,
+ final String extendSelection)
+ throws StepExecutionException {
+
+ selectByPath(pathType, preAscend,
+ createIndexNodePath(splitIndexTreePath(indexPath)),
+ ClickOptions.create()
+ .setClickCount(clickCount)
+ .setMouseButton(button)
+ .setClickModifier(getClickModifier(extendSelection)));
+ }
+
+ /**
+ * Tests whether the given treePath exists or not
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param treePath the path to check
+ * @param operator the RegEx operator
+ * @param exists if true, the verify succeeds if the path DOES exist.
+ * If false, the verify succeeds if the path DOES NOT exist.
+ */
+ public void gdVerifyPath(String pathType, int preAscend,
+ String treePath, String operator, boolean exists) {
+ try {
+ gdExpand(pathType, preAscend, treePath, operator);
+ } catch (StepExecutionException e) {
+ if (exists) {
+ throw new StepVerifyFailedException(
+ "Verify failed on tree-path: " //$NON-NLS-1$
+ + treePath, EventFactory.createVerifyFailed(
+ treePath, StringConstants.EMPTY));
+ }
+ return;
+ }
+ if (!exists) {
+ throw new StepVerifyFailedException("Verify failed on tree-path: ", //$NON-NLS-1$
+ EventFactory.createVerifyFailed(
+ StringConstants.EMPTY, treePath));
+ }
+ }
+
+ /**
+ * Tests whether the given treePath exists or not
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param treePath the path to check
+ * @param exists if true, the verify succeeds if the path DOES exist.
+ * If false, the verify succeeds if the path DOES NOT exist.
+ */
+ public void gdVerifyPathByIndices(String pathType, int preAscend,
+ String treePath, boolean exists) {
+ try {
+ gdExpandByIndices(pathType, preAscend, treePath);
+ } catch (StepExecutionException e) {
+ if (exists) {
+ throw new StepVerifyFailedException("Verify failed on tree-path: " //$NON-NLS-1$
+ + treePath,
+ EventFactory.createVerifyFailed(treePath,
+ StringConstants.EMPTY));
+ }
+ return;
+ }
+ if (!exists) {
+ throw new StepVerifyFailedException("Verify failed on tree-path: ", //$NON-NLS-1$
+ EventFactory.createVerifyFailed(
+ StringConstants.EMPTY, treePath));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String gdStoreSelectedNodeValue(String variable) {
+ AbstractTreeOperationContext context = getTreeAdapter().getContext();
+ Object selectedNode =
+ getSelectedNode(context);
+ if (selectedNode == null) {
+ throw new StepExecutionException("No tree item selected", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NO_SELECTION));
+ }
+
+ return context.getRenderedText(selectedNode);
+ }
+
+ /**
+ * Returns the text from the mouse position.
+ * @param variable -
+ * @return the text from the node at mouse position
+ */
+ public String gdStoreValueAtMousePosition(String variable) {
+ AbstractTreeOperationContext context = getTreeAdapter().getContext();
+
+ return context.getRenderedText(getNodeAtMousePosition());
+ }
+ /**
+ *
+ * @return the tree node at the current mouse position.
+ * @throws StepExecutionException If no tree node can be found at the
+ * current mouse position.
+ */
+ protected abstract Object getNodeAtMousePosition()
+ throws StepExecutionException;
+
+ /**
+ * Verifies whether the first selection in the tree has a rendered text that is
+ * equal to <code>selection</code>.
+ *
+ * @param selection
+ * The selection to verify
+ * @throws StepExecutionException
+ * If no node is selected or the verification fails.
+ */
+ public void gdVerifySelectedValue(String selection)
+ throws StepExecutionException {
+ gdVerifySelectedValue(selection, MatchUtil.DEFAULT_OPERATOR);
+ }
+
+ /**
+ * Verifies whether the first selection in the tree has a rendered text that is
+ * equal to <code>pattern</code>.
+ *
+ * @param pattern
+ * The expected text
+ * @param operator
+ * The operator to use when comparing the expected and
+ * actual values.
+ * @throws StepExecutionException
+ * If no node is selected or the verification fails.
+ */
+ public void gdVerifySelectedValue(String pattern, String operator)
+ throws StepExecutionException {
+
+ AbstractTreeOperationContext context = getTreeAdapter().getContext();
+ checkNodeText(getSelectedNode(context), pattern, operator);
+ }
+
+
+
+ /**
+ * Checks the text for the given node against the given pattern and
+ * operator.
+ *
+ * @param node The node containing the text to check.
+ * @param pattern The expected text.
+ * @param operator The operator to use when comparing the expected and
+ * actual values.
+ * @throws StepVerifyFailedException If the verification fails.
+ */
+ protected void checkNodeText(Object node, String pattern, String operator)
+ throws StepVerifyFailedException {
+
+ AbstractTreeOperationContext context = getTreeAdapter().getContext();
+ Collection nodeTextList = context.getNodeTextList(node);
+ Iterator it = nodeTextList.iterator();
+ boolean isMatched = false;
+ while (it.hasNext() && !isMatched) {
+ try {
+ Verifier.match((String)it.next(), pattern, operator);
+ isMatched = true;
+ } catch (StepVerifyFailedException svfe) {
+ if (!it.hasNext()) {
+ throw svfe;
+ }
+ // Otherwise just try the next element
+ }
+ }
+ }
+
+ /**
+ * @param pathType For example, "relative" or "absolute".
+ * @param preAscend Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param context The context of the traversal.
+ * @return The node at which to begin the traversal or <code>null</code>
+ * if the traversal should begin at the root of the node.
+ */
+ protected Object getStartNode(String pathType, int preAscend,
+ AbstractTreeOperationContext context) {
+ Object startNode;
+ ITreeAdapter tree = getTreeAdapter();
+ if (pathType.equals(
+ CompSystemConstants.TREE_PATH_TYPE_RELATIVE)) {
+ startNode = getSelectedNode(context);
+ Object child = startNode;
+ for (int i = 0; i < preAscend; ++i) {
+ if ((startNode == null) || ((tree.isRootVisible())
+ && (tree.getRootNode() == null))) {
+ TestErrorEvent event = EventFactory
+ .createActionError(TestErrorEvent.TREE_NODE_NOT_FOUND);
+ throw new StepExecutionException(
+ "Tree node not found: Parent of " //$NON-NLS-1$
+ + child.toString(), event);
+ }
+ child = startNode;
+ startNode = context.getParent(startNode);
+
+ }
+ // Extra handling for tree without visible root node
+ if ((startNode == null) || ((tree.isRootVisible())
+ && (tree.getRootNode() == null))) {
+ startNode = null;
+ }
+ } else if (pathType.equals(
+ CompSystemConstants.TREE_PATH_TYPE_ABSOLUTE)) {
+ startNode = null;
+ } else {
+ throw new StepExecutionException(
+ pathType + " is not a valid Path Type", EventFactory //$NON-NLS-1$
+ .createActionError(TestErrorEvent.INVALID_PARAM_VALUE));
+
+ }
+
+ return startNode;
+ }
+
+ /**
+ * @param mouseButton mouseButton
+ * @param modifierSpecification modifierSpecification
+ * @param pathType pathType
+ * @param preAscend preAscend
+ * @param treeTextPath treeTextPath
+ * @param operator operator */
+ public abstract void gdDragByTextPath(
+ int mouseButton,
+ String modifierSpecification,
+ String pathType,
+ int preAscend,
+ String treeTextPath,
+ String operator);
+
+ /**
+ * @param pathType pathType
+ * @param preAscend preAscend
+ * @param treeTextPath treeTextPath
+ * @param operator operator
+ * @param delayBeforeDrop delayBeforeDrop */
+ public abstract void gdDropByTextPath(
+ String pathType,
+ int preAscend,
+ String treeTextPath,
+ String operator,
+ int delayBeforeDrop);
+
+ /**
+ * @param mouseButton mouseButton
+ * @param modifierSpecification modifierSpecification
+ * @param pathType pathType
+ * @param preAscend preAscend
+ * @param treeIndexPath treeIndexPath */
+ public abstract void gdDragByIndexPath(
+ int mouseButton,
+ String modifierSpecification,
+ String pathType,
+ int preAscend,
+ String treeIndexPath);
+
+ /**
+ * @param pathType pathType
+ * @param preAscend preAscend
+ * @param treeIndexPath treeIndexPath
+ * @param delayBeforeDrop delayBeforeDrop */
+ public abstract void gdDropByIndexPath(
+ String pathType,
+ int preAscend,
+ String treeIndexPath,
+ int delayBeforeDrop);
+
+
+
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractUICAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractUICAPs.java
new file mode 100644
index 000000000..ddf4ebecc
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractUICAPs.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+
+import org.eclipse.jubula.rc.common.AUTServer;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.IRobotFactory;
+import org.eclipse.jubula.rc.common.exception.RobotException;
+import org.eclipse.jubula.rc.common.implclasses.IBaseImplementationClass;
+import org.eclipse.jubula.rc.common.uiadapter.factory.GUIAdapterFactoryRegistry;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
+import org.eclipse.jubula.tools.constants.TestDataConstants;
+/**
+ * Implementation of basic functions for all tester classes. This class
+ * gives the basic functions which are needed for testing.
+ *
+ *
+ * @author BREDEX GmbH
+ */
+public abstract class AbstractUICAPs implements IBaseImplementationClass {
+
+ /** constants for communication */
+ protected static final String POS_UNIT_PIXEL = "Pixel"; //$NON-NLS-1$
+
+ /** constants for communication */
+ protected static final String POS_UNI_PERCENT = "Percent"; //$NON-NLS-1$
+
+ /** The default separator for enumerations of list values. */
+ protected static final char INDEX_LIST_SEP_CHAR =
+ TestDataConstants.VALUE_CHAR_DEFAULT;
+
+ /** */
+ private IRobotFactory m_robotFactory;
+
+ /** */
+ private IComponentAdapter m_component;
+
+
+ /**
+ * Gets the Robot.
+ * @return The Robot
+ * @throws RobotException If the Robot cannot be created.
+ */
+ protected IRobot getRobot() throws RobotException {
+ return AUTServer.getInstance().getRobot();
+ }
+ /**
+ * Gets the Robot factory. The factory is created once per instance.
+ * @return The Robot factory.
+ */
+ protected IRobotFactory getRobotFactory() {
+ m_robotFactory = m_component.getRobotFactory();
+ return m_robotFactory;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setComponent(Object graphicsComponent) {
+ GUIAdapterFactoryRegistry afr = GUIAdapterFactoryRegistry.getInstance();
+ m_component = null;
+ IComponentAdapter adapter =
+ (IComponentAdapter)afr.getAdapter(graphicsComponent);
+ m_component = adapter;
+ }
+ /**
+ * Getter for the stored GraphicalComponent
+ * @return gets the stored IComponentAdapter
+ */
+ public IComponentAdapter getComponent() {
+ return m_component;
+ }
+
+
+
+
+
+
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractWidgetCAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractWidgetCAPs.java
new file mode 100644
index 000000000..4f0fb1b9f
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractWidgetCAPs.java
@@ -0,0 +1,539 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import java.util.StringTokenizer;
+
+import org.eclipse.jubula.rc.common.CompSystemConstants;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.ClickOptions.ClickModifier;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IWidgetAdapter;
+import org.eclipse.jubula.rc.common.util.KeyStrokeUtil;
+import org.eclipse.jubula.tools.utils.TimeUtil;
+/**
+ * Implementation of basic functions for a lot of graphics components
+ * except for context menus and menus.
+ *
+ * @author BREDEX GmbH
+ */
+public abstract class AbstractWidgetCAPs extends AbstractUICAPs {
+
+
+ /**
+ * Casts the IComponentAdapter to an IWidgetAdapter for better access
+ * @return The widgetAdapter
+ */
+ private IWidgetAdapter getWidgetAdapter() {
+ return (IWidgetAdapter) getComponent();
+ }
+
+ /**
+ * Verifies that the component exists and is visible.
+ *
+ * @param exists <code>True</code> if the component is expected to exist
+ * and be visible, otherwise <code>false</code>.
+ */
+ public void gdVerifyExists(boolean exists) {
+ Verifier.equals(exists, getWidgetAdapter().isShowing());
+ }
+
+
+ /**
+ * Verifies if the component has the focus.
+ * @param hasFocus <code>True</code> if the component is expected to has
+ * the focus, otherwise <code>false</code>
+ */
+ public void gdVerifyFocus(boolean hasFocus) {
+ Verifier.equals(hasFocus, getWidgetAdapter().hasFocus());
+ }
+ /**
+ * Verifies if the component is enabled
+ * @param enabled <code>True</code> if the component is expected to be
+ * enabled, otherwise <code>false</code>
+ */
+ public void gdVerifyEnabled(boolean enabled) {
+ Verifier.equals(enabled, getWidgetAdapter().isEnabled());
+ }
+
+ /**
+ * Verifies the value of the property with the name <code>name</code>.
+ * The name of the property has be specified according to the JavaBean
+ * specification. The value returned by the property is converted into a
+ * string by calling <code>toString()</code> and is compared to the passed
+ * <code>value</code>.
+ *
+ * @param name The name of the property
+ * @param value The value of the property as a string
+ * @param operator The operator used to verify
+ */
+ public void gdVerifyProperty(final String name, String value,
+ String operator) {
+
+ final IWidgetAdapter bean = (IWidgetAdapter) getComponent();
+ bean.getPropteryValue(name);
+
+ final String propToStr = bean.getPropteryValue(name);
+ Verifier.match(propToStr, value, operator);
+ }
+
+
+ /**
+ * Clicks the center of the component.
+ * @param count Number of mouse clicks
+ * @param button Pressed button
+ */
+ public void gdClick(int count, int button) {
+ getRobot().click(getComponent().getRealComponent(), null,
+ ClickOptions.create()
+ .setClickCount(count)
+ .setMouseButton(button));
+ }
+
+ /**
+ * Clicks the center of the component with the MouseButton 1
+ * @param count Number of mouse clicks
+ */
+ public void gdclick(int count) {
+ gdClick(count, 1);
+ }
+ /**
+ * clicks into a component.
+ *
+ * @param count amount of clicks
+ * @param button what mouse button should be used
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @throws StepExecutionException error
+ */
+ public void gdClickDirect(int count, int button, int xPos, String xUnits,
+ int yPos, String yUnits) throws StepExecutionException {
+
+ getRobot().click(getComponent().getRealComponent(), null,
+ ClickOptions.create()
+ .setClickCount(count)
+ .setMouseButton(button),
+ xPos, xUnits.equalsIgnoreCase(POS_UNIT_PIXEL),
+ yPos, yUnits.equalsIgnoreCase(POS_UNIT_PIXEL));
+ }
+
+ /**
+ * Performs a Drag. Moves into the middle of the Component and presses and
+ * holds the given modifier and the given mouse button.
+ * @param mouseButton the mouse button.
+ * @param modifier the modifier, e.g. shift, ctrl, etc.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ */
+ public void gdDrag(int mouseButton, String modifier, int xPos,
+ String xUnits, int yPos, String yUnits) {
+ getWidgetAdapter().gdDrag(mouseButton, modifier, xPos, xUnits,
+ yPos, yUnits);
+ }
+
+
+ /**
+ * Performs a Drop. Moves into the middle of the Component and releases
+ * the modifier and mouse button pressed by gdDrag.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ */
+ public void gdDrop(int xPos, String xUnits, int yPos, String yUnits,
+ int delayBeforeDrop) {
+
+ getWidgetAdapter().gdDrop(xPos, xUnits, yPos, yUnits,
+ delayBeforeDrop);
+ }
+
+ /**
+ * dummy method for "wait for component"
+ * @param timeout the maximum amount of time to wait for the component
+ * @param delay the time to wait after the component is found
+ * {@inheritDoc}
+ */
+ public void gdWaitForComponent (int timeout, int delay) {
+ // do NOT delete this method!
+ // do nothing, implementation is in class CAPTestCommand.getImplClass
+ // because this action needs a special implementation!
+ }
+
+ /**
+ * Stores the value of the property with the name <code>name</code>.
+ * The name of the property has be specified according to the JavaBean
+ * specification. The value returned by the property is converted into a
+ * string by calling <code>toString()</code> and is stored to the passed
+ * variable.
+ *
+ * @param variableName The name of the variable to store the property value in
+ * @param propertyName The name of the property
+ * @return the property value.
+ */
+ public String gdStorePropertyValue(String variableName,
+ final String propertyName) {
+ IWidgetAdapter bean = (IWidgetAdapter) getComponent();
+
+ return bean.getPropteryValue(propertyName);
+ }
+
+ /**
+ * Select an item in the popup menu
+ * @param indexPath path of item indices
+ * @param button MouseButton
+ * @throws StepExecutionException error
+ */
+ public void gdPopupSelectByIndexPath(String indexPath, int button)
+ throws StepExecutionException {
+
+ AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
+ popup.selectMenuItemByIndexpath(indexPath);
+ }
+ /**
+ * Selects an item in the popup menu
+ * @param textPath path of item texts
+ * @param operator operator used for matching
+ * @param button MouseButton
+ * @throws StepExecutionException error
+ */
+ public void gdPopupSelectByTextPath(String textPath, String operator,
+ int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
+ popup.selectMenuItem(textPath, operator);
+ }
+ /**
+ * Selects an item in the popup menu
+ *
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param textPath path of item texts
+ * @param operator operator used for matching
+ * @param button MouseButton
+ * @throws StepExecutionException error
+ */
+ public void gdPopupSelectByTextPath(final int xPos, final String xUnits,
+ final int yPos, final String yUnits,
+ String textPath, String operator, int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter()
+ .showPopup(xPos, xUnits, yPos, yUnits, button);
+ popup.selectMenuItem(textPath, operator);
+ }
+
+ /**
+ * Opens the popup menu at the given position relative the current component
+ * and selects an item at the given position in the popup menu
+ *
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param indexPath path of item indices
+ * @param button MouseButton
+ * @throws StepExecutionException error
+ */
+ public void gdPopupSelectByIndexPath(
+ int xPos, String xUnits, int yPos, String yUnits,
+ String indexPath, int button) throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
+ popup.selectMenuItemByIndexpath(indexPath);
+ }
+
+ /**
+ * Checks if the specified context menu entry is enabled.
+ * @param indexPath the menu item to verify
+ * @param enabled for checking enabled or disabled
+ * @param button MouseButton
+ */
+ public void gdPopupVerifyEnabledByIndexPath(String indexPath,
+ boolean enabled, int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
+ popup.verifyEnabledByIndexpath(indexPath, enabled);
+ }
+
+
+ /**
+ * Opens the popup menu at the given position relative the current component
+ * and checks if the specified context menu entry is enabled.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param indexPath the menu item to verify
+ * @param enabled for checking enabled or disabled
+ * @param button MouseButton
+ */
+ public void gdPopupVerifyEnabledByIndexPath(int xPos, String xUnits,
+ int yPos, String yUnits, String indexPath,
+ boolean enabled, int button) throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter()
+ .showPopup(xPos, xUnits, yPos, yUnits, button);
+ popup.verifyEnabledByIndexpath(indexPath, enabled);
+ }
+
+ /**
+ * Checks if the specified context menu entry is enabled.
+ * @param textPath the menu item to verify
+ * @param operator operator used for matching
+ * @param enabled for checking enabled or disabled
+ * @param button MouseButton
+ */
+ public void gdPopupVerifyEnabledByTextPath(String textPath,
+ String operator, boolean enabled, int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
+ popup.verifyEnabled(textPath, operator, enabled);
+ }
+
+ /**
+ * Opens the popup menu at the given position relative the current component
+ * and checks if the specified context menu entry is enabled.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param textPath the menu item to verify
+ * @param operator operator used for matching
+ * @param enabled for checking enabled or disabled
+ * @param button MouseButton
+ */
+ public void gdPopupVerifyEnabledByTextPath(final int xPos,
+ final String xUnits, final int yPos,
+ final String yUnits, String textPath, String operator,
+ boolean enabled, int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter()
+ .showPopup(xPos, xUnits, yPos, yUnits, button);
+ popup.verifyEnabled(textPath, operator, enabled);
+ }
+
+ /**
+ * Checks if the specified context menu entry is selected.
+ * @param indexPath the menu item to verify
+ * @param selected for checking if entry is selected
+ * @param button MouseButton
+ */
+ public void gdPopupVerifySelectedByIndexPath(String indexPath,
+ boolean selected, int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
+ popup.verifySelectedByIndexpath(indexPath, selected);
+ }
+
+ /**
+ * Opens the popup menu at the given position relative the current component
+ * and checks if the specified context menu entry is selected.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param indexPath the menu item to verify
+ * @param selected for checking if entry is selected
+ * @param button MouseButton
+ */
+ public void gdPopupVerifySelectedByIndexPath(int xPos, String xUnits,
+ int yPos, String yUnits, String indexPath, boolean selected,
+ int button) throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter()
+ .showPopup(xPos, xUnits, yPos, yUnits, button);
+ popup.verifySelectedByIndexpath(indexPath, selected);
+ }
+
+ /**
+ * Checks if the specified context menu entry is selected.
+ * @param textPath the menu item to verify
+ * @param operator operator used for matching
+ * @param selected for checking if entry is selected
+ * @param button MouseButton
+ */
+ public void gdPopupVerifySelectedByTextPath(String textPath,
+ String operator, boolean selected, int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
+ popup.verifySelected(textPath, operator, selected);
+ }
+
+ /**
+ * Opens the popup menu at the given position relative the current component
+ * and checks if the specified context menu entry is selected.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param textPath the menu item to verify
+ * @param operator operator used for matching
+ * @param selected for checking if entry is selected
+ * @param button MouseButton
+ */
+ public void gdPopupVerifySelectedByTextPath(final int xPos,
+ final String xUnits, final int yPos,
+ final String yUnits, String textPath, String operator,
+ boolean selected, int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter()
+ .showPopup(xPos, xUnits, yPos, yUnits, button);
+ popup.verifySelected(textPath, operator, selected);
+ }
+
+ /**
+ * Checks if the specified context menu entry exists.
+ * @param indexPath the menu item to verify
+ * @param exists for checking if entry exists
+ * @param button MouseButton
+ */
+ public void gdPopupVerifyExistsByIndexPath(String indexPath,
+ boolean exists, int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
+ popup.verifyExistsByIndexpath(indexPath, exists);
+ }
+
+ /**
+ * Opens the popup menu at the given position relative the current component
+ * and checks if the specified context menu entry exists.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param indexPath the menu item to verify
+ * @param exists for checking if entry exists
+ * @param button MouseButton
+ */
+ public void gdPopupVerifyExistsByIndexPath(int xPos, String xUnits,
+ int yPos, String yUnits, String indexPath,
+ boolean exists, int button) throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter()
+ .showPopup(xPos, xUnits, yPos, yUnits, button);
+ popup.verifyExistsByIndexpath(indexPath, exists);
+ }
+
+ /**
+ * Checks if the specified context menu entry exists.
+ * @param textPath the menu item to verify
+ * @param operator operator used for matching
+ * @param exists for checking if entry exists
+ * @param button MouseButton
+ */
+ public void gdPopupVerifyExistsByTextPath(String textPath,
+ String operator, boolean exists, int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
+ popup.verifyExists(textPath, operator, exists);
+ }
+
+ /**
+ * Opens the popup menu at the given position relative the current component
+ * and checks if the specified context menu entry exists.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param textPath the menu item to verify
+ * @param operator operator used for matching
+ * @param exists for checking if entry exists
+ * @param button MouseButton
+ */
+ public void gdPopupVerifyExistsByTextPath(final int xPos,
+ final String xUnits, final int yPos,
+ final String yUnits, String textPath, String operator,
+ boolean exists, int button)
+ throws StepExecutionException {
+ AbstractMenuCAPs popup = getWidgetAdapter()
+ .showPopup(xPos, xUnits, yPos, yUnits, button);
+ popup.verifyExists(textPath, operator, exists);
+ }
+ /**
+ *
+ * @param extendSelection
+ * the string to indicate that the selection should be extended
+ * @return a ClickModifier for the given extend selection
+ */
+ protected ClickModifier getClickModifier(String extendSelection) {
+ // FIXME This is a method which belongs in an upper class
+
+ ClickModifier cm = ClickModifier.create();
+ if (CompSystemConstants.EXTEND_SELECTION_YES
+ .equalsIgnoreCase(extendSelection)) {
+ cm.add(ClickModifier.M1);
+ }
+ return cm;
+ }
+
+ /**
+ * Simulates a tooltip for demonstration purposes.
+ *
+ * @param text The text to show in the tooltip
+ * @param textSize The size of the text in points
+ * @param timePerWord The amount of time, in milliseconds, used to display a
+ * single word. A word is defined as a string surrounded
+ * by whitespace.
+ * @param windowWidth The width of the tooltip window in pixels.
+ */
+ public void gdShowText(final String text, final int textSize,
+ final int timePerWord, final int windowWidth) {
+ getWidgetAdapter().showToolTip(text, textSize,
+ timePerWord, windowWidth);
+ }
+
+ /**
+ * Presses or releases the given modifier.
+ * @param modifier the modifier.
+ * @param press if true, the modifier will be pressed.
+ * if false, the modifier will be released.
+ */
+ protected void pressOrReleaseModifiers(String modifier, boolean press) {
+ final IRobot robot = getRobot();
+ final StringTokenizer modTok = new StringTokenizer(
+ KeyStrokeUtil.getModifierString(modifier), " "); //$NON-NLS-1$
+ while (modTok.hasMoreTokens()) {
+ final String mod = modTok.nextToken();
+ final int keyCode = getKeyCode(mod);
+ if (press) {
+ robot.keyPress(null, keyCode);
+ } else {
+ robot.keyRelease(null, keyCode);
+ }
+ }
+ }
+
+ /**
+ * Gets the key code for a specific modifier
+ * @param mod the modifier
+ * @return the integer key code value
+ */
+ protected int getKeyCode(String mod) {
+ return getWidgetAdapter().getKeyCode(mod);
+ }
+
+ /**
+ * Waits the given amount of time. Logs a drop-related error if interrupted.
+ *
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ */
+ public static void waitBeforeDrop(int delayBeforeDrop) {
+ TimeUtil.delay(delayBeforeDrop);
+ }
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/LabelCAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/LabelCAPs.java
new file mode 100644
index 000000000..c2f806ca8
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/LabelCAPs.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITextVerifiable;
+
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class LabelCAPs extends AbstractTextVerifiable {
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ ITextVerifiable label = (ITextVerifiable) getComponent();
+ return new String[] {label.getText()};
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/TabbedPaneCAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/TabbedPaneCAPs.java
new file mode 100644
index 000000000..9244d5e72
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/TabbedPaneCAPs.java
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.caps;
+
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITabPaneAdapter;
+import org.eclipse.jubula.tools.i18n.I18n;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+
+/**
+ * Implementation of the general actions for TabPanes
+ * @author BREDEX GmbH
+ *
+ */
+public class TabbedPaneCAPs extends AbstractWidgetCAPs {
+
+ /**
+ *
+ * @return the <code>ITabPane</code>
+ */
+ public ITabPaneAdapter getTabPane() {
+ return (ITabPaneAdapter)getComponent();
+ }
+
+ /**
+ * @param title The tab title
+ * @param operator The matching operator
+ * @return The tab index
+ */
+ private int getIndexOfTab(final String title, final String operator) {
+ int index = -1;
+ int tabs = getTabPane().getTabCount();
+ for (int a = 0; a < tabs; a++) {
+ if (MatchUtil.getInstance().match(
+ getTabPane().getTitleofTab(a),
+ title,
+ operator)) {
+
+ index = a;
+ break;
+ }
+ }
+
+ if (index == -1) {
+ throw new StepExecutionException(
+ "Can not find tab: '" + title + "' using operator: '" //$NON-NLS-1$ //$NON-NLS-2$
+ + operator + "'", EventFactory //$NON-NLS-1$
+ .createActionError(TestErrorEvent.NOT_FOUND));
+ }
+ return index;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void verifyIndexExists(final int index) {
+ boolean exists = (index >= 0) && (index < getTabPane().getTabCount());
+
+ if (!exists) {
+ throw new StepExecutionException(
+ "The tab index doesn't exist: " + index, EventFactory //$NON-NLS-1$
+ .createActionError(TestErrorEvent.INVALID_INDEX));
+ }
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ final String[] componentTextArray;
+ componentTextArray = new String[getTabPane().getTabCount()];
+ for (int i = 0; i < componentTextArray.length; i++) {
+ componentTextArray[i] = getTabPane().getTitleofTab(i);
+ }
+ return componentTextArray;
+ }
+
+ /**
+ * Selects the tab with the passed index. The method doesn't care if the tab is enabled or not.
+ * @param index The tab index
+ */
+ private void selectTabByImplIndex(int index) {
+ verifyIndexExists(index);
+
+ // FIXME zeb: We currently ignore the possibility of needing to scroll
+ // or use a pulldown menu to find the tab item. This means
+ // that the user must know when this type of action is
+ // necessary and specify their tests accordingly. We may wish
+ // to change this later so that it is "smarter" (i.e. can
+ // scroll or use a pulldown menu to find tab items in a crowded
+ // tab folder).
+
+ // Some tab items have a close button embedded in them.
+ // In order to reduce the chance of clicking this close button, we click
+ // at x-coordinate 25% rather than 50%.
+ getRobot().click(getTabPane().getRealComponent(),
+ getTabPane().getBoundsAt(index),
+ ClickOptions.create().left(), 25, false, 50, false);
+
+ }
+
+ /**
+ * Selects the tab with the passed index.
+ * The method doesn't care if the tab is enabled or not.
+ *
+ * @param index
+ * The tab index
+ * @throws StepExecutionException
+ * If the tab index is invalid.
+ */
+ public void gdSelectTabByIndex(int index)
+ throws StepExecutionException {
+ int implIdx = IndexConverter.toImplementationIndex(index);
+
+ selectTabByImplIndex(implIdx);
+ }
+ /**
+ * Selects the tab with the passed title. The method doesn't care if the tab
+ * is enabled or not.
+ *
+ * @param title
+ * The tab title
+ * @param operator
+ * using regex
+ * @throws StepExecutionException
+ * If the tab title is invalid.
+ */
+ public void gdSelectTab(final String title, String operator)
+ throws StepExecutionException {
+
+ selectTabByImplIndex(getIndexOfTab(title, operator));
+
+ }
+
+ /**
+ * Verifies the text of the tab by index
+ *
+ * @param index index of tab
+ * @param text The tab title
+ * @param operator Operator to be executed
+ * @throws StepExecutionException
+ * If the tab title is invalid.
+ */
+ public void gdVerifyTextOfTabByIndex(final int index, final String text,
+ final String operator)
+ throws StepExecutionException {
+ final int tabIndex = IndexConverter.toImplementationIndex(index);
+ String tabTitle = getTabPane().getTitleofTab(tabIndex);
+ Verifier.match(tabTitle, text, operator);
+ }
+
+ /**
+ * Verifies existence of tab by index/value
+ *
+ * @param tab index/value of tab
+ * @param operator Operator to be executed
+ * @param exists boolean, tab exists
+ * @throws StepExecutionException if tab does not exist.
+ */
+ public void gdVerifyExistenceOfTab(String tab, String operator,
+ boolean exists)
+ throws StepExecutionException {
+ final int tabIdx = getTabIndexFromString(tab, operator);
+ boolean tabExists = true;
+ try {
+ verifyIndexExists(tabIdx);
+ } catch (StepExecutionException e) {
+ tabExists = false;
+ }
+
+ Verifier.equals(exists, tabExists);
+ }
+
+ /**
+ * @param tab index or title of tab
+ * @param operator Operator to be executed
+ * @return returns index of tab if exists, -1 otherwise
+ */
+ private int getTabIndexFromString(String tab, String operator) {
+ int tabIndex = -1;
+ try {
+ tabIndex = IndexConverter.toImplementationIndex(
+ Integer.parseInt(tab));
+ } catch (NumberFormatException nfe) {
+ for (int i = 0; i < getTabPane().getTabCount(); i++) {
+ String text = getTabPane().getTitleofTab(i);
+ if (MatchUtil.getInstance().match(text, tab, operator)) {
+ return i;
+ }
+ }
+
+ }
+ return tabIndex;
+ }
+
+ /**
+ * Verifies if the tab with the passed title is enabled.
+ *
+ * @param title The tab title
+ * @param operator operation to be executed
+ * @param isEnabled wether to test if the tab is enabled or not
+ * @throws StepExecutionException
+ * If the tab title is invalid.
+ */
+ public void gdVerifyEnabled(String title, String operator,
+ boolean isEnabled)
+
+ throws StepExecutionException {
+ final int tabIndex = getIndexOfTab(title, operator);
+
+ Verifier.equals(isEnabled, getTabPane().isEnabledAt(tabIndex));
+ }
+
+ /**
+ * Verifies if the tab with the passed index is enabled.
+ *
+ * @param index
+ * The tab index
+ * @param enabled
+ * Should the tab be enabled?
+ * @throws StepExecutionException
+ * If the tab index is invalid.
+ */
+ public void gdVerifyEnabledByIndex(int index, boolean enabled)
+ throws StepExecutionException {
+ final int implIdx = IndexConverter.toImplementationIndex(index);
+ verifyIndexExists(implIdx);
+ Verifier.equals(enabled, getTabPane().isEnabledAt(implIdx));
+ }
+
+ /**
+ * Verifies the selection of the tab with the passed index.
+ *
+ * @param index
+ * The tab index
+ * @param selected
+ * Should the tab be selected?
+ * @throws StepExecutionException
+ * If the tab index is invalid.
+ */
+ public void gdVerifySelectedTabByIndex(int index, boolean selected)
+ throws StepExecutionException {
+ int implIdx = IndexConverter.toImplementationIndex(index);
+ int selIndex = getTabPane().getSelectedIndex();
+
+ if (selIndex == -1) {
+ if (!selected) {
+ return;
+ }
+ throw new StepExecutionException(
+ I18n.getString(TestErrorEvent.NO_SELECTION),
+ EventFactory.createActionError(TestErrorEvent.NO_SELECTION));
+ }
+
+ Verifier.equals(selected, selIndex == implIdx);
+ }
+
+ /**
+ * Verifies the selection of the tab with the passed title.
+ *
+ * @param tabTitlePattern
+ * The tab title pattern to use for checking
+ * @param operator
+ * Operator to be executed
+ * @param selected
+ * Should the tab be selected?
+ * @throws StepExecutionException
+ * If the tab title is invalid.
+ */
+ public void gdVerifySelectedTab(String tabTitlePattern, String operator,
+ boolean selected)
+ throws StepExecutionException {
+ String selectedTabTitle = null; // for no Selection
+ int selectedIndex = getTabPane().getSelectedIndex();
+ if (selectedIndex >= 0) {
+ selectedTabTitle = getTabPane().getTitleofTab(selectedIndex);
+ }
+
+ if (selectedTabTitle == null) {
+ if (!selected) {
+ return;
+ }
+ throw new StepExecutionException(
+ I18n.getString(TestErrorEvent.NO_SELECTION),
+ EventFactory.createActionError(TestErrorEvent.NO_SELECTION));
+ }
+ Verifier.match(selectedTabTitle, tabTitlePattern, operator, selected);
+ }
+
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/driver/DragAndDropHelper.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/driver/DragAndDropHelper.java
index 4b4105fe9..c36b01304 100644
--- a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/driver/DragAndDropHelper.java
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/driver/DragAndDropHelper.java
@@ -30,6 +30,10 @@ public class DragAndDropHelper {
/** Flag if the Mouse is in drag mode (pressed key) */
private boolean m_isDragMode = false;
+ /** The Component to drag */
+ private Object m_dragComponent = null;
+
+
/**
* hidden singleton constructor.
*/
@@ -92,4 +96,18 @@ public class DragAndDropHelper {
m_isDragMode = drag;
}
+ /**
+ * @return the dragComponent
+ */
+ public Object getDragComponent() {
+ return m_dragComponent;
+ }
+
+ /**
+ * @param dragComponent the dragComponent to set
+ */
+ public void setDragComponent(Object dragComponent) {
+ m_dragComponent = dragComponent;
+ }
+
}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/factory/GUIAdapterFactoryRegistry.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/factory/GUIAdapterFactoryRegistry.java
new file mode 100644
index 000000000..d89cbd6a4
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/factory/GUIAdapterFactoryRegistry.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.factory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jubula.rc.common.adaptable.IAdapterFactory;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
+/**
+ * This factory registry holds all the toolkit specific factory's.
+ * These factory's holding the classes which are implementing the component
+ * specific interface. It could be an adapter or the specific component
+ * implementing the interface.
+ *
+ * You must register a factory before a test is started.
+ * @author BREDEX GmbH
+ *
+ */
+public class GUIAdapterFactoryRegistry {
+
+ /**
+ * Singleton instance of this class
+ */
+ private static GUIAdapterFactoryRegistry instance =
+ new GUIAdapterFactoryRegistry();
+
+ /**
+ * Map that manages the registration. Key is always a class Value is a
+ * collection of IAdapterFactory
+ */
+ private Map m_registrationMap = new HashMap();
+
+ /**
+ * Call Constructor only by using getInstance
+ */
+ private GUIAdapterFactoryRegistry() {
+ }
+
+ /**
+ * Return the singleton of this class
+ *
+ * @return singleton
+ */
+ public static GUIAdapterFactoryRegistry getInstance() {
+ return instance;
+ }
+
+ /**
+ * Register adapter factory with all its supported classes
+ *
+ * @param factory
+ * adapter factory that should be registered
+ */
+ public void registerFactory(IUIAdapterFactory factory) {
+ Class[] supportedClasses = factory.getSupportedClasses();
+ for (int i = 0; i < supportedClasses.length; i++) {
+ m_registrationMap.put(supportedClasses[i], factory);
+ }
+ }
+
+ /**
+ * Sign off adapter factory from all its supported classes
+ *
+ * @param factory
+ * adapter factory that should be signed off
+ */
+ public void signOffFactory(IAdapterFactory factory) {
+ Class[] supportedClasses = factory.getSupportedClasses();
+ for (int i = 0; i < supportedClasses.length; i++) {
+ m_registrationMap.remove(supportedClasses[i]);
+ }
+ }
+ /**
+ *
+ * @param objectToAdapt
+ * @return -
+ */
+ public IComponentAdapter getAdapter(Object objectToAdapt) {
+ Class adapteeclass = objectToAdapt.getClass();
+ IUIAdapterFactory factory = (IUIAdapterFactory) m_registrationMap.
+ get(adapteeclass);
+ Class superclass = adapteeclass;
+ while (factory == null && superclass != Object.class) {
+ factory = (IUIAdapterFactory) m_registrationMap.
+ get(superclass);
+ superclass = superclass.getSuperclass();
+ }
+ // FIXME Here is missing the right Exception!!!
+ return factory.getAdapter(objectToAdapt);
+
+ }
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/factory/IUIAdapterFactory.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/factory/IUIAdapterFactory.java
new file mode 100644
index 000000000..4d16650bf
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/factory/IUIAdapterFactory.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.factory;
+
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
+
+/**
+ * This is the interface for the factory which is used by the
+ * <code>AbstractUI</code> to get the specific Object which implements the
+ * corresponding interface for the tester class.
+ *
+ * @author BREDEX GmbH
+ */
+public interface IUIAdapterFactory {
+ /**
+ * @return all classes that will be supported by this adapter factory
+ */
+ Class[] getSupportedClasses();
+
+ /**
+ * Adapts object to adapt to a new object of type targetAdapterClass
+ *
+ * @param objectToAdapt
+ * object that should be adapted
+ * @return the adapter for the object to adapt of type targetAdapterClass
+ */
+ IComponentAdapter getAdapter(Object objectToAdapt);
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IButtonAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IButtonAdapter.java
new file mode 100644
index 000000000..cd4bfe67e
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IButtonAdapter.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+
+/**
+ * Interface for all necessary methods to test buttons.
+ * It extends the <code>IWidgetAdapter</code> to add button specific methods.
+ *
+ *
+ * @author BREDEX GmbH
+ */
+
+public interface IButtonAdapter extends ITextVerifiable {
+ /**
+ * Gets the text from the button
+ * @return the text which is saved in the component
+ */
+ public String getText();
+
+ /**
+ * isSelected is mostly for RadioButtons and CheckBoxes
+ * @return <code>true</code> if the component is selected
+ */
+ public boolean isSelected();
+
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComboBoxAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComboBoxAdapter.java
new file mode 100644
index 000000000..0b0270474
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComboBoxAdapter.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+
+/**
+ * This interface holds all methods which are needed to test
+ * ComboBox like components.
+ * @author BREDEX GmbH
+ *
+ */
+public interface IComboBoxAdapter extends ITextVerifiable {
+
+ /**
+ *
+ * @return the value if the Text Component is editable
+ */
+ boolean isEditable();
+ /**
+ * @param value The value to check
+ * @param operator The operator used to verify
+ * @return <code>true</code> if the combobox contains an element rendered with the passed value
+ */
+ public boolean containsValue(String value, String operator);
+ /**
+ * @param value The value to check
+ * @return <code>true</code> if the combobox contains an element rendered with the passed value
+ */
+ public boolean containsValue(String value);
+
+ /**
+ * select the whole text of the textfield by clicking three times.
+ */
+ void selectAll();
+
+
+ /**
+ * @return The currently selected index for the combo box, or -1 if no
+ * index is currently selected.
+ */
+ public int getSelectedIndex();
+
+ /**
+ * Selects the combobox element with the passed index.
+ * @param index The index to select
+ */
+ public void select(int index);
+
+ /**
+ * Selects the specified item in the combobox.
+ * @param values the values which should be (not) selected
+ * @param operator if regular expressions are used
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @throws StepExecutionException if an error occurs during selecting the item
+ * @throws IllegalArgumentException if <code>component</code> or <code>text</code> are null
+ */
+ public void select(final String[] values, String operator,
+ String searchType)
+ throws StepExecutionException, IllegalArgumentException;
+
+ /**
+ * Inputs <code>text</code> to <code>component</code>.<br>
+ * @param text the text to type
+ * @param replace whether to replace the text or not
+ * @throws StepExecutionException if an error occurs during typing <code>text</code>
+ * @throws IllegalArgumentException if <code>component</code> or <code>text</code> are null
+ */
+ public void input(String text, boolean replace)
+ throws StepExecutionException, IllegalArgumentException;
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComponentAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComponentAdapter.java
new file mode 100644
index 000000000..b55809944
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComponentAdapter.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+
+import org.eclipse.jubula.rc.common.driver.IRobotFactory;
+
+/**
+ * This is the main interface for classes which will hold or be the
+ * component that implement the methods we need for this
+ * specific component to test .
+ *
+ * @author BREDEX GmbH
+ */
+public interface IComponentAdapter {
+ /**
+ * Gets the toolkit specific component
+ * @return toolkit specific component
+ */
+ public Object getRealComponent();
+
+ /**
+ * Gets the toolkit specific RobotFactory
+ * @return the RobotFactory
+ */
+ public IRobotFactory getRobotFactory();
+
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IListAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IListAdapter.java
new file mode 100644
index 000000000..97d30cac3
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IListAdapter.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public interface IListAdapter extends ITextVerifiable {
+ /**
+ *
+ * @return The array of selected indices
+ */
+ public int[] getSelectedIndices();
+
+ /**
+ * Clicks on the index of the passed list.
+ * @param i The index to click
+ * @param co the click options to use for selecting an index item
+ */
+ public void clickOnIndex(Integer i, ClickOptions co);
+
+ /**
+ * @return The array of selected values as the renderer shows them
+ */
+ public String[] getSelectedValues();
+
+ /**
+ * Finds the indices of the list elements that are rendered with the passed values.
+ * @param values The values
+ * @param operator operator to use
+ * @param searchType
+ * Determines where the search begins ("relative" or "absolute")
+ * @return The array of indices. It's length is equal to the length of the
+ * values array, but may contains <code>null</code> elements for
+ * all values that are not found in the list
+ */
+ public Integer[] findIndicesOfValues(final String[] values,
+ final String operator, final String searchType);
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IMenuAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IMenuAdapter.java
new file mode 100644
index 000000000..26d159765
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IMenuAdapter.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+
+
+/**
+ * This interface is for the functionality of menus. This is only for the
+ * not visible part of menus which only contains the next menuitems in the
+ * Hierarchy of the menu.
+ *
+ * @author BREDEX GmbH
+ */
+public interface IMenuAdapter extends IComponentAdapter {
+
+ /**
+ *
+ * @return the items of the menu
+ */
+ public IMenuItemAdapter[] getItems();
+
+ /**
+ * Gets the amount of items in the menu
+ *
+ * @return the amount of Items in the menu (with Seperator)
+ */
+ public int getItemCount();
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IMenuItemAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IMenuItemAdapter.java
new file mode 100644
index 000000000..b79ad7330
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IMenuItemAdapter.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+
+/**
+ * Interface for all necessary methods for testing menuitems.
+ *
+ * @author BREDEX GmbH
+ */
+public interface IMenuItemAdapter extends IComponentAdapter {
+
+ /**
+ *
+ * @return the text which is saved in the item
+ */
+ public String getText();
+ /**
+ *
+ * @return <code>true</code> if the component is visible
+ */
+ public boolean isEnabled();
+ /**
+ *
+ * @return <code>true</code> if the component exists
+ * that means there is an item in this wrapper
+ */
+ public boolean isExisting();
+ /**
+ *
+ * @return <code>true</code> if the component is selected
+ *
+ */
+ public boolean isSelected();
+ /**
+ *
+ * @return <code>true</code> if the component is Showing
+ */
+ public boolean isShowing();
+
+ /** Gets the menu of the menuitem
+ * @return the menu which is attached to the item
+ */
+ public IMenuAdapter getMenu();
+
+ /**
+ *
+ * @return <code>true</code> if the menuitem has a menu
+ */
+ public boolean hasSubMenu();
+ /**
+ * Checks whether the given menu item is a separator.
+ * This method runs in the GUI thread.
+ * @return <code>true</code> if <code>menuItem</code> is a separator item.
+ * Otherwise <code>false</code>.
+ */
+ public boolean isSeparator();
+
+ /**
+ * This Methods selects the specific menuItem with an click
+ * or in another toolkit specitif way
+ */
+ public void selectMenuItem();
+
+ /**
+ * This method trys to open the the next Menu in the cascade
+ *
+ * @return the next SubMenu in the Menu
+ */
+ public IMenuAdapter openSubMenu();
+
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITabPaneAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITabPaneAdapter.java
new file mode 100644
index 000000000..90712aff6
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITabPaneAdapter.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+
+/**
+ * Interface for all necessary methods to test TabbedPanes.
+ * It extends the <code>IWidgetAdapter</code> to add Tab Pane specific methods.
+ * @author BREDEX GmbH
+ *
+ */
+public interface ITabPaneAdapter extends IWidgetAdapter {
+ /**
+ *
+ * @return the number of the tabs
+ */
+ public int getTabCount();
+
+ /**
+ *
+ * @param index of the tab
+ * @return the title of the wanted tab.
+ */
+ public String getTitleofTab(int index);
+
+ /**
+ *
+ * @param index of the tab
+ * @return the bounds of the tabs.
+ */
+ public Object getBoundsAt(int index);
+
+ /**
+ *
+ * @param index index of the tab
+ * @return the enablement of the specific tab.
+ */
+ public boolean isEnabledAt(int index);
+
+ /**
+ *
+ * @return the index of the selected tab.
+ */
+ public int getSelectedIndex();
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITableAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITableAdapter.java
new file mode 100644
index 000000000..ab0e65792
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITableAdapter.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+
+import java.awt.Rectangle;
+
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.table.Cell;
+
+/**
+ * Interface for all necessary methods for testing tables.
+ *
+ * @author BREDEX GmbH
+ */
+public interface ITableAdapter extends ITextVerifiable {
+
+
+ /**
+ * Gets the number of columns
+ *
+ * @return the number of columns
+ */
+ public int getColumnCount();
+
+ /**
+ * Gets the number of rows
+ *
+ * @return the number of rows
+ */
+ public int getRowCount();
+
+ /**
+ * @param row the zero based index of the row
+ * @param column the zero based index of the column
+ * @return the text of the cell of the given coordinates
+ */
+ public String getCellText(int row, int column);
+
+ /**
+ * Returns the name of the column appearing in the view at
+ * column position <code>column</code>.
+ *
+ * @param column the column in the view being queried
+ * @return the name of the column at position <code>column</code>
+ in the view where the first column is column 0
+ */
+ public String getColumnName(int column);
+
+ /**
+ * Gets column index from string with header name or index
+ *
+ * @param col Headername or index of column
+ * @param operator The operation used to verify
+ * @return column index
+ */
+ public int getColumnFromString(String col, String operator);
+
+ /**
+ * This is only for a specific case where tables could act
+ * like lists. And the getText is not working.
+ * If this is not the case for the component return <code>null</code>
+ * @param row the row
+ * @return the text of the row
+ */
+ public String getRowName(int row);
+
+ /**
+ * Gets row index from string with index or text of first row
+ *
+ * @param row index or value in first col
+ * @param operator The operation used to verify
+ * @return integer of String of row
+ */
+ public int getRowFromString(String row, String operator);
+
+ /**
+ * gets header bounds for column
+ * @param col The column.
+ * @return The rectangle of the header
+ */
+ public Rectangle getHeaderBounds(int col);
+
+ /**
+ * @return The currently selected cell of the Table.
+ * @throws StepExecutionException If no cell is selected.
+ */
+ public Cell getSelectedCell() throws StepExecutionException;
+
+ /**
+ *
+ * @return <code>true</code> if the Header is visible, <code>false</code> otherwise
+ */
+ public boolean isHeaderVisible();
+
+ /**
+ *
+ * @param row the row
+ * @param col the column
+ * @return <code>true</code> if the Cell is editable, <code>false</code> otherwise
+ */
+ public boolean isCellEditable(int row, int col);
+
+ /**
+ * @return true, if there is any cell selection in the table, false otherwise.
+ */
+ public boolean hasCellSelection();
+
+ /**
+ * Scrolls the passed cell (as row and column) to visible.<br>
+ * This method must return null if there is no scrolling.
+ * @param row The row.
+ * @param col The column.
+ * @return The rectangle of the cell.
+ * @throws StepExecutionException If getting the cell rectangle or the scrolling fails.
+ */
+ public Rectangle scrollCellToVisible (int row , int col)
+ throws StepExecutionException;
+
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITextComponentAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITextComponentAdapter.java
new file mode 100644
index 000000000..4e989c670
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITextComponentAdapter.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+/**
+ * Interface for all needed methods which are needed from TextComponents
+ * @author BREDEX GmbH
+ *
+ */
+public interface ITextComponentAdapter extends ITextVerifiable {
+
+ /**
+ * Sets the caret to a specific position.
+ *
+ * @param start The index at which the selection begins.
+ */
+ void setSelection(int start);
+ /**
+ * Selects text in the component.
+ *
+ * @param start The index at which the selection begins.
+ * @param end The index at which the selection ends.
+ */
+ void setSelection(int start, int end);
+
+
+ /**
+ *
+ * @return the selectes text
+ */
+ String getSelectionText();
+
+ /**
+ * Selects all text in the component.
+ */
+ void selectAll();
+
+ /**
+ *
+ * @return the value if the Text Component is editable
+ */
+ boolean isEditable();
+
+
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITextVerifiable.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITextVerifiable.java
new file mode 100644
index 000000000..84d98dcd7
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITextVerifiable.java
@@ -0,0 +1,15 @@
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public interface ITextVerifiable extends IWidgetAdapter {
+
+ /**
+ * Gets the value of the component, or if there are more
+ * than the first selected.
+ * @return the value of the component
+ */
+ public String getText();
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITreeAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITreeAdapter.java
new file mode 100644
index 000000000..a7f06687d
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITreeAdapter.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+
+import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeOperationContext;
+
+/**
+ * Interface for all necessary methods for testing trees.
+ *
+ * @author BREDEX GmbH
+ */
+public interface ITreeAdapter extends IWidgetAdapter {
+
+ /**
+ * Gets the root node(s) of the tree.
+ * This could be either a single node or multiple nodes
+ * @return The root node(s).
+ */
+ public Object getRootNode();
+
+ /**
+ * Gets the TreeOperationContext which is created through an
+ * toolkit specific implementation.
+ * @return the TreeOperationContext for the tree
+ */
+ public AbstractTreeOperationContext getContext();
+
+ /**
+ *
+ * @return The visibility of the Root Node
+ */
+ public boolean isRootVisible();
+}
diff --git a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IWidgetAdapter.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IWidgetAdapter.java
new file mode 100644
index 000000000..04b360569
--- /dev/null
+++ b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IWidgetAdapter.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.common.uiadapter.interfaces;
+
+import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+
+/**
+ * This interface defines basic functionality for nearly all UI components.
+ *
+ * @author BREDEX GmbH
+ */
+public interface IWidgetAdapter extends IComponentAdapter {
+
+ /**
+ *
+ * @return <code>true</code> if the component is visible
+ */
+ public boolean isShowing();
+ /**
+ *
+ * @return <code>true</code> if the component is enabled
+ */
+ public boolean isEnabled();
+ /**
+ *
+ * @return <code>true</code> if the component has focus
+ */
+ public boolean hasFocus();
+ /**
+ * @param propertyname the name of the property value to return
+ * @return the property value
+ */
+ public String getPropteryValue(String propertyname);
+
+
+ /**
+ * Shows and returns the popup menu
+ *
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param button MouseButton
+ * @return the popup menu
+ * @throws StepExecutionException error
+ */
+ public AbstractMenuCAPs showPopup(final int xPos,
+ final String xUnits, final int yPos,
+ final String yUnits, final int button)
+ throws StepExecutionException;
+
+ /**
+ * Shows and returns the popup menu
+ * @param button MouseButton
+ * @return the popup menu
+ */
+ public AbstractMenuCAPs showPopup(int button);
+
+
+
+ /**
+ * Simulates a tooltip for demonstration purposes.
+ *
+ * @param text The text to show in the tooltip
+ * @param textSize The size of the text in points
+ * @param timePerWord The amount of time, in milliseconds, used to display a
+ * single word. A word is defined as a string surrounded
+ * by whitespace.
+ * @param windowWidth The width of the tooltip window in pixels.
+ */
+ public void showToolTip(final String text, final int textSize,
+ final int timePerWord, final int windowWidth);
+
+ /**
+ * Performs a Drag. Moves into the middle of the Component and presses and
+ * holds the given modifier and the given mouse button.
+ * @param mouseButton the mouse button.
+ * @param modifier the modifier, e.g. shift, ctrl, etc.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ */
+ public void gdDrag(int mouseButton, String modifier, int xPos,
+ String xUnits, int yPos, String yUnits);
+
+ /**
+ * Performs a Drop. Moves into the middle of the Component and releases
+ * the modifier and mouse button pressed by gdDrag.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ */
+ public void gdDrop(int xPos, String xUnits, int yPos, String yUnits,
+ int delayBeforeDrop);
+
+ /**
+ * Gets the key code for a specific modifier
+ * @param mod the modifier
+ * @return the integer key code value
+ */
+ public int getKeyCode(String mod);
+
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/SwingAUTServer.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/SwingAUTServer.java
index f438c6299..053781710 100644
--- a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/SwingAUTServer.java
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/SwingAUTServer.java
@@ -22,12 +22,14 @@ import org.eclipse.jubula.rc.common.AUTServer;
import org.eclipse.jubula.rc.common.driver.IRobot;
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
import org.eclipse.jubula.rc.common.listener.BaseAUTListener;
+import org.eclipse.jubula.rc.common.uiadapter.factory.GUIAdapterFactoryRegistry;
import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
import org.eclipse.jubula.rc.swing.listener.CheckListener;
import org.eclipse.jubula.rc.swing.listener.ComponentHandler;
import org.eclipse.jubula.rc.swing.listener.FocusTracker;
import org.eclipse.jubula.rc.swing.listener.MappingListener;
import org.eclipse.jubula.rc.swing.listener.RecordListener;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.factory.SwingAdapterFactory;
import org.eclipse.jubula.tools.constants.AUTServerExitConstants;
import org.eclipse.jubula.tools.utils.EnvironmentUtils;
import org.slf4j.Logger;
@@ -219,6 +221,10 @@ public class SwingAUTServer extends AUTServer {
}
AUTServer.getInstance().invokeAUT();
+
+ // FIXME don't know where to put
+ GUIAdapterFactoryRegistry.getInstance().
+ registerFactory(new SwingAdapterFactory());
}
/**
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/AbstractButtonCAPs.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/AbstractButtonCAPs.java
new file mode 100644
index 000000000..1ff29f7f3
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/AbstractButtonCAPs.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.caps;
+
+
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IButtonAdapter;
+
+/**
+ * The implementation class for <code>AbstractButton</code> and subclasses. Note
+ * the "Abstract" in the class name implies only that this class can test
+ * <code>AbstractButton</code> components. The class itself should <em>NOT</em>
+ * be designated <code>abstract</code>, as this class is instantiated using
+ * reflection.
+ *
+ * @author BREDEX GmbH
+ */
+public class AbstractButtonCAPs
+ extends org.eclipse.jubula.rc.common.caps.AbstractButtonCAPs {
+
+ /**
+ * Clicks the button <code>count</code> times.
+ *
+ * @param count The number of clicks
+ */
+ public void gdClick(int count) {
+ gdClick(count, 1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ IButtonAdapter returnvalue = ((IButtonAdapter)getComponent());
+ return new String[] { returnvalue.getText() };
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/CapUtil.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/CapUtil.java
new file mode 100644
index 000000000..e46fde641
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/CapUtil.java
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.caps;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.event.ContainerEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.StringTokenizer;
+
+import javax.swing.AbstractButton;
+import javax.swing.JLabel;
+import javax.swing.JPopupMenu;
+import javax.swing.JToggleButton;
+import javax.swing.text.JTextComponent;
+
+import org.eclipse.jubula.rc.common.AUTServer;
+import org.eclipse.jubula.rc.common.adaptable.AdapterFactoryRegistry;
+import org.eclipse.jubula.rc.common.adaptable.ITextRendererAdapter;
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.IRobotFactory;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.util.KeyStrokeUtil;
+import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
+import org.eclipse.jubula.rc.swing.swing.driver.KeyCodeConverter;
+import org.eclipse.jubula.rc.swing.swing.implclasses.EventListener;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+
+/**
+ * Util class for Swing specific aspects.
+ *
+ * @author BREDEX GmbH
+ */
+public class CapUtil {
+
+ /**
+ * <code>RENDERER_FALLBACK_TEXT_GETTER_METHOD_1</code>
+ */
+ public static final String RENDERER_FALLBACK_TEXT_GETTER_METHOD_1 = "getTestableText"; //$NON-NLS-1$
+
+ /**
+ * <code>RENDERER_FALLBACK_TEXT_GETTER_METHOD_2</code>
+ */
+ public static final String RENDERER_FALLBACK_TEXT_GETTER_METHOD_2 = "getText"; //$NON-NLS-1$
+
+
+ /**
+ * Is true, if a popup menu is shown
+ */
+ public static class PopupShownCondition implements
+ EventListener.Condition {
+
+ /**
+ * the popup menu
+ */
+ private JPopupMenu m_popup = null;
+
+ /**
+ *
+ * @return the popup menu
+ */
+ public JPopupMenu getPopup() {
+ return m_popup;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param event event
+ * @return result of the condition
+ */
+ public boolean isTrue(AWTEvent event) {
+ if (event.getID() != ContainerEvent.COMPONENT_ADDED) {
+ return false;
+ }
+ ContainerEvent ce = (ContainerEvent)event;
+ if (ce.getChild() instanceof JPopupMenu) {
+ m_popup = (JPopupMenu)ce.getChild();
+ return true;
+ } else if (ce.getChild() instanceof Container) {
+ Container popupContainer = (Container)ce.getChild();
+ final int length = popupContainer.getComponents().length;
+ for (int i = 0; i < length; i++) {
+ if (popupContainer.getComponents()[i]
+ instanceof JPopupMenu) {
+
+ m_popup = (JPopupMenu)popupContainer.getComponents()[i];
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * The robot factory.
+ */
+ private static IRobotFactory robotFactory;
+
+ /**
+ *
+ */
+ private CapUtil() { }
+
+ /**
+ *
+ * @return the Robot
+ */
+ public static IRobot getRobot() {
+ return AUTServer.getInstance().getRobot();
+ }
+
+ /**
+ * Gets the Robot factory. The factory is created once per instance.
+ *
+ * @return The Robot factory.
+ */
+ protected static IRobotFactory getRobotFactory() {
+ if (robotFactory == null) {
+ robotFactory = new RobotFactoryConfig().getRobotFactory();
+ }
+ return robotFactory;
+ }
+ /**
+ * @return The event thread queuer.
+ */
+ protected static IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+
+ /**
+ * Presses or releases the given modifier.
+ * @param modifier the modifier.
+ * @param press if true, the modifier will be pressed.
+ * if false, the modifier will be released.
+ */
+ public static void pressOrReleaseModifiers(String modifier, boolean press) {
+ final IRobot robot = getRobot();
+ final StringTokenizer modTok = new StringTokenizer(
+ KeyStrokeUtil.getModifierString(modifier), " "); //$NON-NLS-1$
+ while (modTok.hasMoreTokens()) {
+ final String mod = modTok.nextToken();
+ final int keyCode = KeyCodeConverter.getKeyCode(mod);
+ if (press) {
+ robot.keyPress(null, keyCode);
+ } else {
+ robot.keyRelease(null, keyCode);
+ }
+ }
+ }
+
+ /**
+ * Casts the passed renderer component to a known type and extracts the
+ * rendered text.
+ *
+ * @param renderer
+ * The renderer.
+ * @param queueInEventThread
+ * If <code>true</code>, the text extraction is executed in
+ * the event queue thread.
+ * @return The rendered text.
+ * @throws StepExecutionException
+ * If the passed renderer is not supported. Supported types are
+ * <code>JLabel</code>, <code>JToggleButton</code>,
+ * <code>AbstractButton</code> and <code>JTextComponent</code>
+ *
+ */
+ public static String getRenderedText(final Component renderer,
+ boolean queueInEventThread) throws StepExecutionException {
+
+ if (queueInEventThread) {
+ return (String)getEventThreadQueuer().invokeAndWait(
+ "getRenderedText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return getRenderedText(renderer);
+ }
+ });
+ }
+
+ return getRenderedText(renderer);
+ }
+
+ /**
+ * @param renderer
+ * The component which is used as the renderer
+ * @return The string that the renderer displays.
+ * @throws StepExecutionException
+ * If the renderer component is not of type <code>JLabel</code>,
+ * <code>JToggleButton</code>, <code>AbstractButton</code>,
+ * <code>JTextComponent</code> or supports one of the fallback
+ * methods
+ */
+ public static String getRenderedText(Component renderer)
+ throws StepExecutionException {
+ String renderedText = resolveRenderedText(renderer);
+ if (renderedText != null) {
+ return renderedText;
+ }
+ throw new StepExecutionException(
+ "Renderer not supported: " + renderer.getClass(), //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.RENDERER_NOT_SUPPORTED));
+ }
+
+ /**
+ * @param renderer
+ * The component which is used as the renderer
+ * @return The string that the renderer displays or <code>null</code> if it
+ * could not be resolved.
+ */
+ private static String resolveRenderedText(Component renderer) {
+ if (renderer instanceof JLabel) {
+ return ((JLabel)renderer).getText();
+ } else if (renderer instanceof JToggleButton) {
+ return ((JToggleButton)renderer).isSelected() ? Boolean.TRUE
+ .toString() : Boolean.FALSE.toString();
+ } else if (renderer instanceof AbstractButton) {
+ return ((AbstractButton)renderer).getText();
+ } else if (renderer instanceof JTextComponent) {
+ return ((JTextComponent)renderer).getText();
+ }
+ // Check if an adapter exists
+ ITextRendererAdapter textRendererAdapter =
+ ((ITextRendererAdapter) AdapterFactoryRegistry
+ .getInstance().getAdapter(
+ ITextRendererAdapter.class, renderer));
+ if (textRendererAdapter != null) {
+ return textRendererAdapter.getText();
+ } else if (renderer != null) {
+ String[] methodNames = new String[] {
+ RENDERER_FALLBACK_TEXT_GETTER_METHOD_1,
+ RENDERER_FALLBACK_TEXT_GETTER_METHOD_2 };
+ for (int i = 0; i < methodNames.length; i++) {
+ String text = getTextFromComponent(renderer, methodNames[i]);
+ if (text != null) {
+ return text;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @param obj
+ * the object to invoke the method for
+ * @param getterName
+ * the name of the getter Method for string retrival
+ * @return the return value of the given method name or <code>null</code> if
+ * something went wrong during method invocation
+ */
+ private static String getTextFromComponent(Object obj, String getterName) {
+ String text = null;
+ try {
+ Method getter = null;
+ Class objClass = obj.getClass();
+ try {
+ getter = objClass.getDeclaredMethod(getterName, null);
+ } catch (NoSuchMethodException e) {
+ // ignore
+ } catch (SecurityException e) {
+ // ignore
+ }
+ if (getter == null) {
+ try {
+ getter = objClass.getMethod(getterName, null);
+ } catch (NoSuchMethodException e) {
+ return text;
+ } catch (SecurityException e) {
+ return text;
+ }
+ }
+ getter.setAccessible(true);
+ Object returnValue = getter.invoke(obj, null);
+ if (returnValue instanceof String) {
+ text = (String) returnValue;
+ }
+ return text;
+ } catch (SecurityException e) {
+ return text;
+ } catch (IllegalArgumentException e) {
+ return text;
+ } catch (IllegalAccessException e) {
+ return text;
+ } catch (InvocationTargetException e) {
+ return text;
+ }
+ }
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JListCAPs.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JListCAPs.java
new file mode 100644
index 000000000..c8453eb3a
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JListCAPs.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.caps;
+
+import org.eclipse.jubula.rc.common.caps.AbstractListCAPs;
+import org.eclipse.jubula.rc.swing.utils.SwingUtils;
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class JListCAPs extends AbstractListCAPs {
+
+ /**
+ * {@inheritDoc}
+ */
+ protected int getSystemDefaultModifier() {
+ return SwingUtils.getSystemDefaultModifier();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JMenuBarCAPs.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JMenuBarCAPs.java
new file mode 100644
index 000000000..aa1d92138
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JMenuBarCAPs.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.caps;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Window;
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JPopupMenu;
+import javax.swing.MenuElement;
+
+import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
+import org.eclipse.jubula.rc.swing.swing.implclasses.WindowHelper;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuItemAdapter;
+
+/**
+ * Toolkit specific commands for the <code>JMenuBar</code>.
+ *
+ * @author BREDEX GmbH
+ */
+public class JMenuBarCAPs extends AbstractMenuCAPs {
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+
+ return null;
+ }
+
+ /**
+ * Workaround to get the menu bar existing somewhere in the given
+ * container's hierarchy. This method should <b>only</b> be used if
+ * {@link JFrame#getJMenuBar()} / {@link JDialog#getJMenuBar()} return
+ * <code>null</code>, which is a very rare case.
+ *
+ * This method also performs some unorthodox visibility testing in order
+ * to avoid retrieving the wrong menu.
+ *
+ * @param rootPane The root container from which to start the search for
+ * the menu bar.
+ * @return the first menu bar found in the hierarchy that: <ul>
+ * <li>is showing</li>
+ * <li>contains at least one visible menu</li>
+ */
+ private JMenuBar getMenuBarWorkaround(Container rootPane) {
+ JMenuBar menuBar = null;
+ List menuList = new ArrayList();
+ collectMenuBarsWorkaround(rootPane, menuList);
+ Iterator menuIter = menuList.iterator();
+ while (menuIter.hasNext() && menuBar == null) {
+ JMenuBar menu = (JMenuBar)menuIter.next();
+ boolean hasAtLeastOneItem = false;
+ MenuElement [] subElements = menu.getSubElements();
+ for (int i = 0;
+ i < subElements.length && !hasAtLeastOneItem;
+ i++) {
+ if (subElements[i] instanceof JMenu) {
+ JMenu subMenu = (JMenu)subElements[i];
+ hasAtLeastOneItem =
+ subMenu != null && subMenu.isShowing();
+ }
+ }
+ if (hasAtLeastOneItem) {
+ menuBar = menu;
+ }
+ }
+ return menuBar;
+ }
+
+ /**
+ * Adds all menu bars found in the hierarchy <code>container</code> to
+ * <code>menuBarList</code>. This is part of a workaround for finding menus
+ * in AUTs that don't make proper use of
+ * {@link JFrame#setJMenuBar()} / {@link JDialog#setJMenuBar()}.
+ *
+ * @see #getMenuBarWorkaround(Container)
+ *
+ * @param container The root container from which to start the search for
+ * the menu bars.
+ * @param menuBarList The list to which each menu bar found will be added.
+ * Only objects of type {@link JMenuBar} will be added
+ * to this list.
+ */
+ private void collectMenuBarsWorkaround(
+ Container container, List menuBarList) {
+ Component [] children = container.getComponents();
+ for (int i = 0; i < children.length; i++) {
+ if (children[i] instanceof JMenuBar
+ && children[i].isShowing()) {
+ menuBarList.add(children[i]);
+ }
+ }
+
+ for (int i = 0; i < children.length; i++) {
+ if (children[i] instanceof Container
+ && children[i].isVisible()) {
+ collectMenuBarsWorkaround((Container)children[i], menuBarList);
+ }
+ }
+
+ }
+ /**
+ * @return the component
+ */
+ public IComponentAdapter getComponent() {
+ if (super.getComponent().getRealComponent() instanceof JPopupMenu) {
+ return super.getComponent();
+ }
+ Window activeWindow = WindowHelper.getActiveWindow();
+ if (activeWindow == null) {
+ getLog().warn("JMenuBarImplClass.getComponent(): No active window."); //$NON-NLS-1$
+ } else {
+ JMenuBar menuBar = null;
+ Container rootPane = null;
+ if (activeWindow instanceof JDialog) {
+ JDialog dialog = (JDialog)activeWindow;
+ menuBar = dialog.getJMenuBar();
+ rootPane = dialog.getRootPane();
+ } else if (activeWindow instanceof JFrame) {
+ JFrame frame = (JFrame)activeWindow;
+ menuBar = frame.getJMenuBar();
+ rootPane = frame.getRootPane();
+ }
+
+ if (menuBar == null) {
+ menuBar = getMenuBarWorkaround(rootPane);
+ }
+
+ setComponent(menuBar);
+ }
+ return super.getComponent();
+ }
+
+ /**
+ *{@inheritDoc}
+ */
+ protected void closeMenu(IMenuAdapter menuBar, String[] textPath,
+ String operator) {
+ if (menuBar.getRealComponent() instanceof JPopupMenu) {
+ for (int i = 0; i < textPath.length; i++) {
+ getRobot().keyType(menuBar.getRealComponent(),
+ KeyEvent.VK_ESCAPE);
+ }
+ return;
+ }
+ super.closeMenu(menuBar, textPath, operator);
+
+ }
+
+ /**
+ *{@inheritDoc}
+ */
+ protected void closeMenu(IMenuAdapter menuBar, int[] path) {
+ if (menuBar.getRealComponent() instanceof JPopupMenu) {
+ for (int i = 0; i < path.length; i++) {
+ getRobot().keyType(menuBar.getRealComponent(),
+ KeyEvent.VK_ESCAPE);
+ }
+ return;
+ }
+ super.closeMenu(menuBar, path);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected IMenuItemAdapter newMenuItemAdapter(Object component) {
+ return new JMenuItemAdapter(component);
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JTableCAPs.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JTableCAPs.java
new file mode 100644
index 000000000..a20d36e71
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JTableCAPs.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.caps;
+
+import java.awt.Component;
+import java.awt.IllegalComponentStateException;
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import javax.swing.JTable;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+
+import org.eclipse.jubula.rc.common.caps.AbstractTableCAPs;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.table.Cell;
+import org.eclipse.jubula.rc.common.logger.AutServerLogger;
+import org.eclipse.jubula.rc.swing.utils.SwingUtils;
+/**
+ * Toolkit specific commands for the <code>JTable</code>
+ *
+ * @author BREDEX GmbH
+ */
+public class JTableCAPs extends AbstractTableCAPs {
+
+ /** the logger */
+ private static AutServerLogger log = new AutServerLogger(
+ JTableCAPs.class);
+
+ /**
+ * @return the log
+ */
+ public static AutServerLogger getLog() {
+ return log;
+ }
+
+
+ /**
+ *
+ * @return the real AUT JTable
+ */
+ private JTable getTable() {
+ return (JTable) getComponent().getRealComponent();
+ }
+
+ /**
+ * @return The event thread queuer.
+ */
+ public IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ final String[] componentTextArray;
+ TableColumnModel columnModel = getTable().getColumnModel();
+ if (columnModel == null) {
+ componentTextArray = null;
+ } else {
+ componentTextArray = new String[columnModel.getColumnCount()];
+ for (int i = 0; i < componentTextArray.length; i++) {
+ TableColumn tableColumn = columnModel.getColumn(i);
+ if (tableColumn == null) {
+ componentTextArray[i] = null;
+ } else {
+ Object headerValue = tableColumn.getHeaderValue();
+ if (headerValue == null) {
+ componentTextArray[i] = null;
+ } else {
+ componentTextArray[i] = headerValue.toString();
+ }
+ }
+ }
+ }
+ return componentTextArray;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ protected int getExtendSelectionModifier() {
+ return SwingUtils.getSystemDefaultModifier();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Cell getCellAtMousePosition() throws StepExecutionException {
+ JTable table = getTable();
+ Point mousePos = getRobot().getCurrentMousePosition();
+ Point tablePos = table.getLocationOnScreen();
+ Point relativePos = new Point(mousePos.x - tablePos.x,
+ mousePos.y - tablePos.y);
+ final int column = table.columnAtPoint(relativePos);
+ final int row = table.rowAtPoint(relativePos);
+ if (log.isDebugEnabled()) {
+ log.debug("Selected row, col: " + row + ", " + column); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ checkRowColBounds(row, column);
+ return new Cell(row, column);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected boolean isMouseOnHeader() {
+ JTable table = getTable();
+ if (table.getTableHeader() == null
+ || !(table.getTableHeader().isShowing())) {
+ return false;
+ }
+
+ JTableHeader header = table.getTableHeader();
+ Point mousePos = getRobot().getCurrentMousePosition();
+ try {
+ Point headerPos = header.getLocationOnScreen();
+ Point relativePos = new Point(mousePos.x - headerPos.x,
+ mousePos.y - headerPos.y);
+ return header.getBounds().contains(relativePos);
+ } catch (IllegalComponentStateException icse) {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Object setEditorToReplaceMode(Object editor, boolean replace) {
+ Object returnvalue = editor;
+ if (replace) {
+ getRobot().clickAtCurrentPosition(editor, 3, 1);
+ } else {
+ returnvalue = getComponent().getRealComponent();
+ }
+ return returnvalue;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Object activateEditor(Cell cell, Rectangle rectangle) {
+ Object table = getComponent().getRealComponent();
+ getRobot().click(table, rectangle);
+ Component editor = getTableCellEditor(cell);
+ // sometimes the editor only appears after doubleclick!
+ if (editor == null) {
+ ClickOptions co = ClickOptions.create().setClickCount(2);
+ getRobot().click(table, rectangle, co);
+ editor = getTableCellEditor(cell);
+ }
+ return editor;
+ }
+
+ /**
+ * Gets the TableCellEditor of the given cell
+ * @param cell the cell.
+ * @return the TableCellEditor
+ */
+ private Component getTableCellEditor(final Cell cell) {
+ final JTable table = (JTable) getComponent().getRealComponent();
+ return (Component) getEventThreadQueuer()
+ .invokeAndWait("getCellEditor", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ Object value = table.getValueAt(
+ cell.getRow(), cell.getCol());
+ boolean selected = table.isCellSelected(
+ cell.getRow(), cell.getCol());
+ return table.getCellEditor(cell.getRow(),
+ cell.getCol()).getTableCellEditorComponent(table,
+ value, selected, cell.getRow(), cell.getCol());
+ }
+ });
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JTreeCAPs.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JTreeCAPs.java
new file mode 100644
index 000000000..2c7cd0a5b
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JTreeCAPs.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.caps;
+
+import java.awt.Point;
+import javax.swing.JTree;
+import javax.swing.tree.TreePath;
+
+import org.eclipse.jubula.rc.common.CompSystemConstants;
+import org.eclipse.jubula.rc.common.caps.AbstractTreeCAPs;
+import org.eclipse.jubula.rc.common.driver.DragAndDropHelper;
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+/**
+ * Toolkit specific commands for the <code>JTree</code>
+ *
+ * @author BREDEX GmbH
+ */
+public class JTreeCAPs extends AbstractTreeCAPs {
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDragByTextPath(int mouseButton,
+ String modifier, String pathType, int preAscend,
+ String treeTextPath, String operator) {
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ dndHelper.setModifier(modifier);
+ dndHelper.setMouseButton(mouseButton);
+ gdSelect(pathType, preAscend, treeTextPath, operator, 0, 1,
+ CompSystemConstants.EXTEND_SELECTION_NO);
+ pressOrReleaseModifiers(modifier, true);
+ getRobot().mousePress(null, null, mouseButton);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDropByTextPath(String pathType, int preAscend,
+ String treeTextPath, String operator, int delayBeforeDrop) {
+ try {
+ gdSelect(pathType, preAscend, treeTextPath, operator, 0, 1,
+ CompSystemConstants.EXTEND_SELECTION_NO);
+ waitBeforeDrop(delayBeforeDrop);
+ } finally {
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(), false);
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDragByIndexPath(int mouseButton,
+ String modifier, String pathType, int preAscend,
+ String treeIndexPath) {
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ dndHelper.setModifier(modifier);
+ dndHelper.setMouseButton(mouseButton);
+ gdSelectByIndices(pathType, preAscend, treeIndexPath, 0, 1,
+ CompSystemConstants.EXTEND_SELECTION_NO);
+ pressOrReleaseModifiers(modifier, true);
+ getRobot().mousePress(null, null, mouseButton);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDropByIndexPath(String pathType, int preAscend,
+ String treeIndexPath, int delayBeforeDrop) {
+ try {
+ gdSelectByIndices(pathType, preAscend, treeIndexPath, 0, 1,
+ CompSystemConstants.EXTEND_SELECTION_NO);
+ waitBeforeDrop(delayBeforeDrop);
+ } finally {
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(), false);
+ }
+
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public void gdVerifyTextAtMousePosition(String text, String operator) {
+ checkNodeText(getNodeAtMousePosition(), text, operator);
+ }
+ /**
+ *
+ * @return the tree node at the current mouse position.
+ * @throws StepExecutionException If no tree node can be found at the
+ * current mouse position.
+ */
+ protected Object getNodeAtMousePosition() throws StepExecutionException {
+ return getEventThreadQueuer().invokeAndWait("getNodeAtMousePosition", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ Point mousePosition = getRobot().getCurrentMousePosition();
+ Point treeLocation = getTreeComponent().getLocationOnScreen();
+ Point relativePos = new Point(
+ mousePosition.x - treeLocation.x,
+ mousePosition.y - treeLocation.y);
+
+ int rowAtMousePosition =
+ getTreeComponent().
+ getRowForLocation(relativePos.x, relativePos.y);
+
+ if (rowAtMousePosition != -1) {
+ TreePath treePath =
+ getTreeComponent().
+ getPathForLocation(relativePos.x, relativePos.y);
+
+ if (treePath != null
+ && treePath.getLastPathComponent() != null) {
+ return treePath.getLastPathComponent();
+ }
+
+ }
+
+ throw new StepExecutionException("No tree node found at mouse position.", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+
+ });
+
+ }
+ /**
+ *
+ * @return The JTree
+ */
+ private JTree getTreeComponent() {
+ return (JTree) getComponent().getRealComponent();
+ }
+
+ /**
+ * @return The event thread queuer.
+ */
+ protected IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/AbstractButtonAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/AbstractButtonAdapter.java
new file mode 100644
index 000000000..843d91d59
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/AbstractButtonAdapter.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import javax.swing.AbstractButton;
+
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IButtonAdapter;
+/**
+ * Implementation of the button interface as an adapter which holds
+ * the <code>javax.swing.AbstractButton</code>.
+ *
+ * @author BREDEX GmbH
+ */
+public class AbstractButtonAdapter extends WidgetAdapter
+ implements IButtonAdapter {
+
+ /**
+ * Creates an object with the adapted JMenu.
+ * @param objectToAdapt this must be an object of the Type
+ * <code>AbstractButton</code>
+ */
+ public AbstractButtonAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ }
+
+ /**
+ *
+ * @return the casted Object
+ */
+ private AbstractButton getAbstractButton() {
+ return (AbstractButton) getRealComponent();
+ }
+ /**
+ * @return The event thread queuer.
+ */
+ public IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ return (String) getEventThreadQueuer().invokeAndWait(
+ "getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return getAbstractButton().getText();
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnabled() {
+ Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
+ "isEnabled", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return getAbstractButton().getModel().isEnabled()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return (boolean) returnvalue.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSelected() {
+ Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
+ "isSelected", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return getAbstractButton().getModel().isSelected()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return (boolean) returnvalue.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String readValue(String variable) {
+
+ return (String) getEventThreadQueuer().invokeAndWait(
+ "isShowing", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return getAbstractButton().getText();
+ }
+ });
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/AbstractComponentAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/AbstractComponentAdapter.java
new file mode 100644
index 000000000..eb4aff71e
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/AbstractComponentAdapter.java
@@ -0,0 +1,28 @@
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IRobotFactory;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
+import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public abstract class AbstractComponentAdapter implements IComponentAdapter {
+
+ /** the RobotFactory from the AUT */
+ private IRobotFactory m_robotFactory;
+
+ /**
+ * Gets the Robot factory. The factory is created once per instance.
+ *
+ * @return The Robot factory.
+ */
+ public IRobotFactory getRobotFactory() {
+ if (m_robotFactory == null) {
+ m_robotFactory = new RobotFactoryConfig().getRobotFactory();
+ }
+ return m_robotFactory;
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JComboBoxAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JComboBoxAdapter.java
new file mode 100644
index 000000000..3619c9733
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JComboBoxAdapter.java
@@ -0,0 +1,405 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.util.Arrays;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.swing.ComboBoxEditor;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JList;
+import javax.swing.JPopupMenu;
+import javax.swing.SwingUtilities;
+
+import org.apache.commons.lang.Validate;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComboBoxAdapter;
+import org.eclipse.jubula.rc.swing.swing.caps.CapUtil;
+import org.eclipse.jubula.rc.swing.swing.implclasses.JComboBoxHelper;
+import org.eclipse.jubula.rc.swing.swing.implclasses.JComboBoxImplClass;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+/**
+ * Implementation of the Interface <code>IComboBoxAdapter</code> as a
+ * adapter for the <code>JComboBox</code> component.
+ * @author BREDEX GmbH
+ *
+ */
+public class JComboBoxAdapter extends WidgetAdapter implements
+ IComboBoxAdapter {
+ /**
+ * <code>INVALID_MAX_WIDTH</code>
+ */
+ public static final int NO_MAX_WIDTH = -1;
+
+ /** */
+ private JComboBox m_comboBox;
+ /**
+ *
+ * @param objectToAdapt
+ */
+ public JComboBoxAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_comboBox = (JComboBox) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ String comboBoxText;
+ if (m_comboBox.isEditable()) {
+ comboBoxText = CapUtil.getRenderedText(
+ getComboBoxEditorComponent(m_comboBox), true);
+ } else {
+ final int selIndex = m_comboBox.getSelectedIndex();
+ if (selIndex == -1) {
+ comboBoxText = String.valueOf(
+ m_comboBox.getSelectedItem());
+ } else {
+ final JList jlist = new JList(m_comboBox.getModel());
+ Object o = getEventThreadQueuer().invokeAndWait(
+ "getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ Component disp = m_comboBox.getRenderer()
+ .getListCellRendererComponent(jlist,
+ jlist.getModel().getElementAt(selIndex),
+ selIndex, true, m_comboBox.hasFocus());
+ return CapUtil.getRenderedText(disp, false);
+ }
+ });
+ comboBoxText = String.valueOf(o);
+ }
+ }
+ return comboBoxText;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEditable() {
+ Boolean editable = (Boolean)getEventThreadQueuer().invokeAndWait("isEditable", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ // see findBugs
+ return m_comboBox.isEditable()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return editable.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean containsValue(String value, String operator) {
+ JListAdapter list = new JListAdapter(findJList());
+ return list.containsValue(value, operator);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean containsValue(String value) {
+ return containsValue(value, MatchUtil.EQUALS);
+ }
+
+ /**
+ * select the whole text of the textfield by clicking three times.
+ */
+ public void selectAll() {
+ click(new Integer(1));
+ getRobot().keyStroke(getRobot().getSystemModifierSpec() + " A"); //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getSelectedIndex() {
+ Integer actual = (Integer)getEventThreadQueuer()
+ .invokeAndWait(
+ JComboBoxImplClass.class.getName() + ".getSelectedIndex", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return new Integer(m_comboBox.getSelectedIndex());
+ }
+ });
+ return actual.intValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void select(int index) {
+ JListAdapter list = new JListAdapter(findJList());
+ list.clickOnIndex(new Integer(index), ClickOptions
+ .create().setClickCount(1), getMaxWidth());
+ }
+
+ /**
+ * Selects the specified item in the combobox.
+ * @param values the values which should be (not) selected
+ * @param operator if regular expressions are used
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @throws StepExecutionException if an error occurs during selecting the item
+ * @throws IllegalArgumentException if <code>component</code> or <code>text</code> are null
+ */
+ public void select(final String[] values, String operator,
+ String searchType)
+ throws StepExecutionException, IllegalArgumentException {
+ try {
+ for (int i = 0; i < values.length; i++) {
+ String text = values[i];
+ Validate.notNull(text, "text must not be null"); //$NON-NLS-1$
+ }
+ JListAdapter list = new JListAdapter(findJList());
+ Integer[] indices = list.findIndicesOfValues(values,
+ operator, searchType);
+ Arrays.sort(indices);
+ if (indices.length == 0) {
+ throw new StepExecutionException("Text '" + Arrays.asList(values).toString() //$NON-NLS-1$
+ + "' not found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+ list.clickOnIndex(indices[0], ClickOptions
+ .create().setClickCount(1), getMaxWidth());
+ } catch (StepExecutionException e) {
+ m_comboBox.hidePopup();
+ throw e;
+ } catch (IllegalArgumentException e) {
+ m_comboBox.hidePopup();
+ throw e;
+ }
+ }
+
+ /**
+ * Inputs <code>text</code> to <code>component</code>.<br>
+ * @param text the text to type in
+ * @param replace whether to rplace the text or not
+ * @throws StepExecutionException if an error occurs during typing <code>text</code>
+ * @throws IllegalArgumentException if <code>component</code> or <code>text</code> are null
+ */
+ public void input(String text, boolean replace)
+ throws StepExecutionException, IllegalArgumentException {
+
+ Validate.notNull(text, "text must not be null"); //$NON-NLS-1$
+ Component editor = getComboBoxEditorComponent(m_comboBox);
+ if (editor == null) {
+ throw new StepExecutionException("could not find editor", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
+ }
+ if (replace) {
+ selectAll();
+ }
+ getRobot().type(editor, text);
+ }
+
+ /**
+ * performs a <code>count</code> -click on the textfield.
+ * @param count the number of clicks
+ */
+ public void click(Integer count) {
+ Component editor = getComboBoxEditorComponent(m_comboBox);
+ if (editor == null) {
+ throw new StepExecutionException("no editor found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
+ }
+ getRobot().click(editor, null, ClickOptions.create().setClickCount(
+ count.intValue()));
+ }
+
+ /**
+ * @param component
+ * the combobox
+ * @return the editor used to render and edit the selected item in the
+ * JComboBox field.
+ * @throws StepExecutionException
+ * if the editor comonent could not be found
+ */
+ private Component getComboBoxEditorComponent(JComboBox component)
+ throws StepExecutionException {
+
+ ComboBoxEditor cbe = component.getEditor();
+ if (cbe == null) {
+ throw new StepExecutionException("no ComboBoxEditor found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
+ }
+ Component c = cbe.getEditorComponent();
+ if (c == null) {
+ throw new StepExecutionException("no EditorComponent found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
+ }
+ return c;
+ }
+
+ /**
+ * Finds the <code>JList</code> of the combobox.
+ * @return The list
+ */
+ private JList findJList() {
+ JList list = (JList)getComponentViaHierarchy(openPopupMenu(),
+ JList.class);
+ if (list == null) {
+ throw new StepExecutionException("list component not found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
+ }
+ return list;
+ }
+
+ /**
+ * Opens the combobox popup menu and returns the popup instance. May also be
+ * called if the popup is already visible
+ * @return The popup menu
+ */
+ private JPopupMenu openPopupMenu() {
+ if (!isPopupVisible()) {
+ Component c = getComponentViaHierarchy(m_comboBox, JButton.class);
+ Rectangle r = null;
+ if ((c == null) && (!m_comboBox.isEditable())) {
+ c = m_comboBox;
+ } else if ((c == null) && (m_comboBox.isEditable())) {
+ c = m_comboBox;
+ r = findArrowIconArea();
+ }
+// if (log.isDebugEnabled()) {
+// log.debug("Opening popup by clicking on: " + c); //$NON-NLS-1$
+// }
+ getRobot().click(c, r);
+ }
+ if (!isPopupVisible()) {
+// log.debug("Dropdown list still not visible, must be an error"); //$NON-NLS-1$
+ throw new StepExecutionException("dropdown list not visible", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.DROPDOWN_LIST_NOT_FOUND));
+ }
+ return getPopupMenu(m_comboBox);
+ }
+
+ /**
+ * Tries to find the popup menu from the combobox
+ * @param component the combobox
+ * @return the popup of the combobox
+ * @throws StepExecutionException if the popup could not be found
+ */
+ private JPopupMenu getPopupMenu(JComboBox component)
+ throws StepExecutionException {
+
+ AccessibleContext ac = component.getAccessibleContext();
+ for (int i = 0; i < ac.getAccessibleChildrenCount(); i++) {
+ Accessible a = ac.getAccessibleChild(i);
+ if (a instanceof JPopupMenu) {
+ return (JPopupMenu)a;
+ }
+ }
+ throw new StepExecutionException("cannot find dropdown list", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.DROPDOWN_LIST_NOT_FOUND));
+ }
+ /**
+ * Tries to find the component in the component hierarchy
+ * @param component where to search
+ * @param c type of the component which should be found
+ * @return the desired component
+ */
+ private Component getComponentViaHierarchy(Container component, Class c) {
+ Component[] comps = component.getComponents();
+ for (int i = 0; i < comps.length; i++) {
+ if (c.isInstance(comps[i])) {
+ return comps[i];
+ }
+ }
+ for (int i = 0; i < comps.length; i++) {
+ if (comps[i] instanceof Container) {
+ Component ct = getComponentViaHierarchy((Container)comps[i], c);
+ if (ct != null) {
+ return ct;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return true, if the popup of the combobox is visible
+ */
+ private boolean isPopupVisible() {
+ Boolean visible = (Boolean)getEventThreadQueuer().invokeAndWait(
+ JComboBoxHelper.class.getName()
+ + "isPopupVisible", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return m_comboBox.isPopupVisible()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return visible.booleanValue();
+ }
+
+ /**
+ * @return a rectangle, where the arrow icon is expected.
+ */
+ private Rectangle findArrowIconArea() {
+ JComboBox comboBox = m_comboBox;
+ Component editor = getComboBoxEditorComponent(comboBox);
+ Rectangle r = null;
+ if (editor == null) {
+ throw new StepExecutionException("could not find editor", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
+ }
+ Rectangle ra[] =
+ SwingUtilities.computeDifference(comboBox.getBounds(),
+ editor.getBounds());
+ if ((ra == null) || (ra.length < 1)) {
+ throw new StepExecutionException("could not arrow icon", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
+ }
+ r = ra[0];
+ // find the largest area of the returned rectangles.
+ double bestAreaIndex = Double.MAX_VALUE;
+ for (int i = 0; i < ra.length; i++) {
+ if ((ra[i].height > 0) && (ra[i].width > 0)) {
+ double areaIndex = ((double)ra[i].width) / ra[i].height - 1.0;
+ if (areaIndex < 0) {
+ areaIndex *= (-1);
+ }
+ if (areaIndex < bestAreaIndex) {
+ bestAreaIndex = areaIndex;
+ r = ra[i];
+ }
+ }
+ }
+ return r;
+ }
+
+ /**
+ * @return the maximal width for the selection; -1 if none available
+ * e.g. the preferred width of the combo box itself is 100 pixel although
+ * the preferred size of the embedded items is more than two times bigger
+ * --> click outside of component (JList) #3013
+ */
+ private double getMaxWidth() {
+ double maxWidth = NO_MAX_WIDTH;
+ Dimension d = m_comboBox.getPreferredSize();
+ if (d != null) {
+ maxWidth = d.getWidth();
+ }
+ return maxWidth;
+ }
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JLabelAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JLabelAdapter.java
new file mode 100644
index 000000000..405607366
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JLabelAdapter.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import javax.swing.JLabel;
+
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITextVerifiable;
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class JLabelAdapter extends WidgetAdapter implements ITextVerifiable {
+
+ /**
+ *
+ * @param objectToAdapt the component
+ */
+ public JLabelAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ return ((JLabel) getRealComponent()).getText();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JListAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JListAdapter.java
new file mode 100644
index 000000000..48a66c8ed
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JListAdapter.java
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+import javax.swing.ListModel;
+
+import org.eclipse.jubula.rc.common.CompSystemConstants;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IListAdapter;
+import org.eclipse.jubula.rc.swing.swing.caps.CapUtil;
+import org.eclipse.jubula.rc.swing.swing.implclasses.JComboBoxImplClass;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class JListAdapter extends WidgetAdapter implements IListAdapter {
+ /** */
+ private JList m_list;
+
+ /**
+ *
+ * @param objectToAdapt
+ */
+ public JListAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_list = (JList) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ String[] selected = getSelectedValues();
+ if (selected.length > 0) {
+ return selected[0];
+ }
+ throw new StepExecutionException("No list item selected", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NO_SELECTION));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int[] getSelectedIndices() {
+ return (int[])getEventThreadQueuer().invokeAndWait(
+ "getSelectedIndices", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_list.getSelectedIndices();
+ }
+ });
+ }
+
+ /**
+ * Clicks on the index of the passed list.
+ *
+ * @param i The index to click
+ * @param co the click options to use
+ * @param maxWidth the maximal width which is used to select the item
+ */
+ public void clickOnIndex(final Integer i,
+ ClickOptions co, double maxWidth) {
+ final int index = i.intValue();
+ ListModel model = m_list.getModel();
+ if ((model == null) || (index >= model.getSize())
+ || (index < 0)) {
+ throw new StepExecutionException("List index '" + i //$NON-NLS-1$
+ + "' is out of range", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.INVALID_INDEX));
+ }
+ // Call of JList.ensureIndexIsVisible() is not required,
+ // because the Robot scrolls the click rectangle to visible.
+ Rectangle r = (Rectangle) getRobotFactory().getEventThreadQueuer()
+ .invokeAndWait("getCellBounds", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ return m_list.getCellBounds(index, index);
+ }
+ });
+
+ if (r == null) {
+ throw new StepExecutionException(
+ "List index '" + i + "' is not visible", //$NON-NLS-1$ //$NON-NLS-2$
+ EventFactory.createActionError(TestErrorEvent.NOT_VISIBLE));
+ }
+
+ // if possible adjust height and width for items
+ ListCellRenderer lcr = m_list.getCellRenderer();
+ if (lcr != null) {
+ Component listItem = lcr.getListCellRendererComponent(m_list, model
+ .getElementAt(index), index, false, false);
+ Dimension preferredSize = listItem.getPreferredSize();
+ r.setSize(preferredSize);
+ }
+
+ if (maxWidth != JComboBoxImplClass.NO_MAX_WIDTH
+ && r.getWidth() > maxWidth) {
+ Dimension d = new Dimension();
+ d.setSize(maxWidth, r.getHeight());
+ r.setSize(d);
+ }
+
+ getRobot().click(m_list, r,
+ co.setClickType(ClickOptions.ClickType.RELEASED));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getSelectedValues() {
+ final int[] indices = getSelectedIndices();
+
+ return (String[])getEventThreadQueuer().invokeAndWait(
+ "getSelectedValues", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ Object[] values = m_list.getSelectedValues();
+ String[] selected = new String[values.length];
+ ListCellRenderer renderer = m_list.getCellRenderer();
+ for (int i = 0; i < values.length; i++) {
+ Object value = values[i];
+ Component c = renderer.getListCellRendererComponent(
+ m_list, value, indices[i], true, false);
+ selected[i] = CapUtil.getRenderedText(c);
+ }
+ return selected;
+ }
+ });
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public Integer[] findIndicesOfValues(
+ final String[] values, final String operator,
+ final String searchType) {
+
+ final Set indexSet = new HashSet();
+ getEventThreadQueuer().invokeAndWait("findIndices", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ ListCellRenderer renderer = m_list.getCellRenderer();
+ ListModel model = m_list.getModel();
+ for (int i = getStartingIndex(searchType);
+ i < model.getSize(); ++i) {
+ Object obj = model.getElementAt(i);
+ m_list.ensureIndexIsVisible(i);
+ Component comp = renderer
+ .getListCellRendererComponent(
+ m_list, obj, i, false, false);
+ String str = CapUtil.getRenderedText(comp);
+ if (MatchUtil.getInstance().
+ match(str, values, operator)) {
+ indexSet.add(new Integer(i));
+ }
+ }
+ return null; // return value is not used
+ }
+ });
+
+ Integer[] indices = new Integer[indexSet.size()];
+ indexSet.toArray(indices);
+ return indices;
+ }
+
+ /**
+ * Finds the indices of the list elements that are rendered with the passed
+ * values.
+ *
+ * @param values The values
+ * @param operator operator to use
+ * @return The array of indices. It's length is equal to the length of the
+ * values array, but may contains <code>null</code> elements for
+ * all values that are not found in the list
+ */
+ public Integer[] findIndicesOfValues(
+ final String[] values, final String operator) {
+
+ return findIndicesOfValues(values, operator,
+ CompSystemConstants.SEARCH_TYPE_ABSOLUTE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean containsValue(String value, String operator) {
+ Integer[] indices = null;
+ if (operator.equals(MatchUtil.NOT_EQUALS)) {
+ indices = findIndicesOfValues(new String[] { value },
+ MatchUtil.EQUALS);
+ return indices.length == 0;
+ }
+ indices = findIndicesOfValues(new String[] { value },
+ operator);
+ return indices.length > 0;
+ }
+
+ /**
+ * Clicks on the index of the passed list.
+ *
+ * @param i
+ * The index to click
+ * @param co the click options to use
+ */
+ public void clickOnIndex(final Integer i, ClickOptions co) {
+ clickOnIndex(i, co, JComboBoxImplClass.NO_MAX_WIDTH);
+ }
+
+ /**
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @return The index from which to begin a search, based on the search type
+ * and (if appropriate) the currently selected cell.
+ */
+ private int getStartingIndex(final String searchType) {
+ int startingIndex = 0;
+ if (searchType.equalsIgnoreCase(
+ CompSystemConstants.SEARCH_TYPE_RELATIVE)) {
+ int [] selectedIndices = getSelectedIndices();
+ // Start from the last selected item
+ startingIndex = selectedIndices[selectedIndices.length - 1] + 1;
+ }
+ return startingIndex;
+ }
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuAdapter.java
new file mode 100644
index 000000000..1cb35e507
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuAdapter.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
+/**
+ * Implementation of the menu interface for adapting the <code>JMenu</code>.
+ * In Swing we have three implementations of the menu interface because
+ * the Interface is used for the <code>JMenubar</code>, the <code>JPopupMenu</code> and the <code>JMenu</code>.
+ * All these behave same in the implementation.
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class JMenuAdapter extends AbstractComponentAdapter
+ implements IMenuAdapter {
+ /** The JMenu from the AUT */
+ private JMenu m_menu;
+
+ /**
+ * Creates an object with the adapted JMenu.
+ * @param toAdapt graphics component which will be adapted
+ */
+ public JMenuAdapter(Object toAdapt) {
+ m_menu = (JMenu) toAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getRealComponent() {
+ return m_menu;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IMenuItemAdapter[] getItems() {
+ List adapters = new LinkedList();
+
+ for (int i = 0; i < m_menu.getItemCount(); i++) {
+ JMenuItem getted = m_menu.getItem(i);
+ if (getted instanceof JMenuItem) {
+ adapters.add(new JMenuItemAdapter(getted));
+ }
+
+ }
+
+
+ IMenuItemAdapter[] allitems = null;
+ if (adapters.size() > 0) {
+ allitems = new IMenuItemAdapter[adapters.size()];
+ int i = 0;
+ for (Iterator iterator = adapters.iterator(); iterator.hasNext();) {
+ Object object = (Object) iterator.next();
+
+ allitems[i] = (IMenuItemAdapter) object;
+ i++;
+ }
+
+ }
+
+
+ return allitems;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public int getItemCount() {
+ return m_menu.getItemCount();
+ }
+
+
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuBarAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuBarAdapter.java
new file mode 100644
index 000000000..ba1d33fdc
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuBarAdapter.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
+
+/**
+ * Implementation of the menu interface for adapting the <code>JMenuBar</code>.
+ * In Swing we have three implementations of the menu interface because
+ * the Interface is used for the <code>JMenubar</code>, the <code>JPopupMenu</code> and the <code>JMenu</code>.
+ * All these behave same in the implementation.
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class JMenuBarAdapter extends AbstractComponentAdapter
+ implements IMenuAdapter {
+ /** The JMenuBar */
+ private JMenuBar m_menuBar;
+
+ /**
+ * @param objectToAdapt
+ */
+ public JMenuBarAdapter(Object objectToAdapt) {
+ m_menuBar = (JMenuBar) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getRealComponent() {
+
+ return m_menuBar;
+ }
+ /**
+ * {@inheritDoc}
+ */
+
+ public IMenuItemAdapter[] getItems() {
+ Object[] menus = m_menuBar.getSubElements();
+ List adapters = new LinkedList();
+ for (int i = 0; i < menus.length; i++) {
+ if (menus[i] instanceof JMenuItem) {
+ adapters.add(new JMenuItemAdapter(menus[i]));
+ }
+ }
+ IMenuItemAdapter[] allitems = new IMenuItemAdapter[adapters.size()];
+ adapters.toArray(allitems);
+ return allitems;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getItemCount() {
+ return m_menuBar.getMenuCount();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuItemAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuItemAdapter.java
new file mode 100644
index 000000000..dc1ec7943
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuItemAdapter.java
@@ -0,0 +1,225 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.driver.RobotTiming;
+import org.eclipse.jubula.rc.common.exception.RobotException;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+
+/**
+ * Implementation of the MenuItem interface for adapting <code>JMenuItem</code>.
+ * @author BREDEX GmbH
+ *
+ */
+public class JMenuItemAdapter extends AbstractComponentAdapter
+ implements IMenuItemAdapter {
+
+ /** the JMenuItem from the AUT */
+ private JMenuItem m_menuItem;
+
+ /**
+ *
+ * @param objectToAdapt
+ */
+ public JMenuItemAdapter(Object objectToAdapt) {
+ m_menuItem = (JMenuItem) objectToAdapt;
+ }
+
+ /**
+ * Gets the IEventThreadQueuer.
+ *
+ * @return The Robot
+ * @throws RobotException
+ * If the Robot cannot be created.
+ */
+ protected IRobot getRobot() throws RobotException {
+ return getRobotFactory().getRobot();
+ }
+ /**
+ * @return The event thread queuer.
+ */
+ public IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getRealComponent() {
+
+ return m_menuItem;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setComponent(Object element) {
+ m_menuItem = (JMenuItem) element;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnabled() {
+ Boolean actual = (Boolean) getEventThreadQueuer().invokeAndWait(
+ "isEnabled", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ // see findBugs
+ return ((m_menuItem != null)
+ && (m_menuItem instanceof JMenuItem)
+ && m_menuItem.isEnabled())
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+
+ return actual.booleanValue();
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ return (String) getEventThreadQueuer().invokeAndWait(
+ "getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_menuItem.getText();
+ }
+ });
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isShowing() {
+ Boolean actual = (Boolean) getEventThreadQueuer().invokeAndWait(
+ "isShowing", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ // see findBugs
+ return ((m_menuItem != null)
+ && (m_menuItem instanceof JMenuItem)
+ && m_menuItem.isShowing())
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+
+ return actual.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isExisting() {
+ if (m_menuItem != null) {
+ return true;
+ }
+ return false;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSelected() {
+ Boolean actual = (Boolean) getEventThreadQueuer().invokeAndWait(
+ "isSelected", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return ((m_menuItem != null)
+ && (m_menuItem instanceof JMenuItem)
+ && m_menuItem.isSelected())
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+
+ return actual.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IMenuAdapter getMenu() {
+ if (m_menuItem instanceof JMenu) {
+ return new JMenuAdapter(m_menuItem);
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasSubMenu() {
+ if (m_menuItem.getSubElements().length > 0) {
+ return true;
+ }
+ return false;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSeparator() {
+ if (m_menuItem == null) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void selectMenuItem() {
+ clickMenuItem(getRobot(), m_menuItem);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IMenuAdapter openSubMenu() {
+ if (!m_menuItem.isEnabled()) {
+ throw new StepExecutionException("menu item not enabled", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.MENU_ITEM_NOT_ENABLED));
+ }
+ if (!(m_menuItem instanceof JMenu)) {
+ throw new StepExecutionException("unexpected item found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+ JMenu menu = (JMenu) m_menuItem;
+ getRobot().click(m_menuItem, null, ClickOptions.create().setClickType(
+ ClickOptions.ClickType.RELEASED));
+ RobotTiming.sleepPostShowSubMenuItem(menu.getDelay());
+ return getMenu();
+ }
+
+ /**
+ * Clicks on a menu item
+ *
+ * @param robot the robot
+ * @param item the menu item
+ */
+ private void clickMenuItem(IRobot robot, JMenuItem item) {
+ if (!item.isEnabled()) {
+ throw new StepExecutionException("menu item not enabled", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.MENU_ITEM_NOT_ENABLED));
+ }
+ robot.click(item, null, ClickOptions.create().setClickType(
+ ClickOptions.ClickType.RELEASED));
+ }
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JPopupMenuAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JPopupMenuAdapter.java
new file mode 100644
index 000000000..5a5075c3c
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JPopupMenuAdapter.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
+/**
+ * Implementation of the menu interface for adapting the <code>JPopupMenu</code>.
+ * In Swing we have three implementations of the menu interface because
+ * the Interface is used for the <code>JMenubar</code>, the <code>JPopupMenu</code> and the <code>JMenu</code>.
+ * All these behave same in the implementation.
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class JPopupMenuAdapter extends AbstractComponentAdapter
+ implements IMenuAdapter {
+ /** */
+ private JPopupMenu m_contextMenu;
+
+ /**
+ *
+ * @param adaptee
+ */
+ public JPopupMenuAdapter(Object adaptee) {
+ m_contextMenu = (JPopupMenu) adaptee;
+ }
+
+ /** {@inheritDoc} */
+ public Object getRealComponent() {
+ return m_contextMenu;
+ }
+
+ /** {@inheritDoc} */
+ public IMenuItemAdapter[] getItems() {
+ Object[] menuItems = m_contextMenu.getSubElements();
+ List adapters = new LinkedList();
+ for (int i = 0; i < menuItems.length; i++) {
+ if (menuItems[i] instanceof JMenuItem) {
+ adapters.add(new JMenuItemAdapter(menuItems[i]));
+ }
+ }
+ IMenuItemAdapter[] allitems = new IMenuItemAdapter[adapters.size()];
+ adapters.toArray(allitems);
+ return allitems;
+ }
+
+ /** {@inheritDoc} */
+ public int getItemCount() {
+ return m_contextMenu.getSubElements().length;
+ }
+
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTabbedPaneAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTabbedPaneAdapter.java
new file mode 100644
index 000000000..f4fc06205
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTabbedPaneAdapter.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import javax.swing.JTabbedPane;
+
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITabPaneAdapter;
+/**
+ * Implementation of the Interface <code>ITabPaneAdapter</code> as a
+ * adapter for the <code>JTabbedPane</code> component.
+ * @author BREDEX GmbH
+ *
+ */
+public class JTabbedPaneAdapter extends WidgetAdapter
+ implements ITabPaneAdapter {
+
+ /** The JTabbedPane on which the actions are performed. */
+ private JTabbedPane m_pane;
+ /**
+ *
+ * @param objectToAdapt
+ */
+ public JTabbedPaneAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_pane = (JTabbedPane) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getTabCount() {
+ return ((Integer) getEventThreadQueuer().invokeAndWait(
+ "getTabCount", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return new Integer(m_pane.getTabCount());
+ }
+ })).intValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getTitleofTab(final int index) {
+ return (String) getEventThreadQueuer().invokeAndWait(
+ "getTitleOfTab", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_pane.getTitleAt(index);
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getBoundsAt(final int index) {
+
+ return getEventThreadQueuer().invokeAndWait(
+ "getBoundsAt", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_pane.getBoundsAt(index);
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnabledAt(final int index) {
+ return ((Boolean) getEventThreadQueuer().invokeAndWait(
+ "isEnabledAt", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return Boolean.valueOf(m_pane.isEnabledAt(index));
+ }
+ })).booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getSelectedIndex() {
+ return ((Integer) getEventThreadQueuer().invokeAndWait(
+ "getSelectedIndex", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return new Integer(m_pane.getSelectedIndex());
+ }
+ })).intValue();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTableAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTableAdapter.java
new file mode 100644
index 000000000..50b5461e6
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTableAdapter.java
@@ -0,0 +1,385 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import java.awt.Component;
+import java.awt.Rectangle;
+
+import javax.swing.JTable;
+import javax.swing.table.TableCellRenderer;
+
+import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.table.Cell;
+import org.eclipse.jubula.rc.common.logger.AutServerLogger;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITableAdapter;
+import org.eclipse.jubula.rc.swing.swing.caps.CapUtil;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+/**
+ * Implements the table interface as an adapter for the <code>JTable</code>.
+ *
+ * @author BREDEX GmbH
+ */
+public class JTableAdapter extends WidgetAdapter implements ITableAdapter {
+
+ /** the logger */
+ private static AutServerLogger log = new AutServerLogger(
+ AbstractMenuCAPs.class);
+
+ /** The JTable from the AUT */
+ private JTable m_table;
+
+ /**
+ * Creates an object with the adapted JMenu.
+ * @param objectToAdapt the object which needed to be adapted
+ */
+ public JTableAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_table = (JTable) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setComponent(Object element) {
+ m_table = (JTable) element;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getColumnCount() {
+ Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
+ "getColumnCount", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return new Integer(m_table.getColumnCount());
+ }
+ });
+ return returnvalue.intValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getRowCount() {
+ Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
+ "getRowCount", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return new Integer(m_table.getRowCount());
+ }
+ });
+ return returnvalue.intValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getCellText(final int row, final int column) {
+ Object o = getEventThreadQueuer().invokeAndWait("getCellText", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ Object value = m_table.getValueAt(row, column);
+ boolean selected = m_table.isCellSelected(row,
+ column);
+ if (log.isDebugEnabled()) {
+ log.debug("Getting cell text:"); //$NON-NLS-1$
+ log.debug("Row, col: " + row + ", " + column); //$NON-NLS-1$ //$NON-NLS-2$
+ log.debug("Value: " + value); //$NON-NLS-1$
+ }
+ TableCellRenderer renderer = m_table.getCellRenderer(
+ row, column);
+ Component c = renderer.getTableCellRendererComponent(
+ m_table, value, selected, true, row,
+ column);
+
+ return CapUtil.getRenderedText(c);
+ }
+ });
+
+ String current = String.valueOf(o);
+ return current;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getColumnName(final int column) {
+ String returnvalue = (String)getEventThreadQueuer().invokeAndWait(
+ "getColumnName", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return m_table.getColumnName(column);
+ }
+ });
+ return returnvalue;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getColumnFromString(final String col, final String operator) {
+ Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
+ "getColumnFromString", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ int column = -2;
+ try {
+ int usrIdxCol = Integer.parseInt(col);
+ if (usrIdxCol == 0) {
+ usrIdxCol = usrIdxCol + 1;
+ }
+ column = IndexConverter.toImplementationIndex(
+ usrIdxCol);
+ } catch (NumberFormatException nfe) {
+ try {
+ if (m_table.getTableHeader() == null
+ || !(m_table.getTableHeader()
+ .isShowing())) {
+ throw new StepExecutionException("No Header", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.NO_HEADER));
+ }
+ for (int i = 0; i < m_table.getColumnCount();
+ i++) {
+ String header = m_table.getColumnName(i);
+ if (MatchUtil.getInstance().match(
+ header, col, operator)) {
+ column = i;
+ }
+ }
+ } catch (IllegalArgumentException iae) {
+ //do nothing here
+ }
+ }
+
+ return new Integer(column);
+ }
+ });
+ return returnvalue.intValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getRowName(final int row) {
+ // JTable does not act like lists
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getRowFromString(final String row, final String operator) {
+ Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
+ "getRowFromString", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ int rowInt = -2;
+ try {
+ rowInt = IndexConverter.toImplementationIndex(
+ Integer.parseInt(row));
+ if (rowInt == -1) {
+ if (m_table.getTableHeader() == null
+ || !(m_table.getTableHeader()
+ .isShowing())) {
+ throw new StepExecutionException("No Header", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.NO_HEADER));
+ }
+ }
+ } catch (NumberFormatException nfe) {
+ for (int i = 0; i < m_table.getRowCount(); i++) {
+ String cellTxt = getCellText(i, 0);
+ if (MatchUtil.getInstance().match(cellTxt, row,
+ operator)) {
+ return new Integer(i);
+ }
+ }
+ }
+ return new Integer(rowInt);
+ }
+ });
+ return returnvalue.intValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Rectangle getBounds() {
+ Rectangle returnvalue = (Rectangle) getEventThreadQueuer()
+ .invokeAndWait("getBounds", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ return m_table.getBounds();
+ }
+ });
+
+ return returnvalue;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Rectangle getHeaderBounds(int col) {
+ Rectangle returnvalue = (Rectangle) getEventThreadQueuer()
+ .invokeAndWait("getHeaderBounds", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ return m_table.getTableHeader().getBounds();
+ }
+ });
+
+ return returnvalue;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Cell getSelectedCell() throws StepExecutionException {
+
+ Cell returnvalue = (Cell) getEventThreadQueuer().invokeAndWait(
+ "getSelectedCell", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+
+ int row = m_table.getSelectedRow();
+ int col = m_table.getSelectedColumn();
+ if (log.isDebugEnabled()) {
+ log.debug("Selected row, col: " + row + ", " + col); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ try {
+ checkRowColBounds(row, col);
+ } catch (StepExecutionException e) {
+ if ((e.getEvent() != null)
+ && (TestErrorEvent.INVALID_INDEX.equals(
+ e.getEvent()
+ .getProps().get(TestErrorEvent
+ .Property
+ .DESCRIPTION_KEY)))) {
+ // set "invalid index" to "no selection" -> better description!
+ throw new StepExecutionException("No selection", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.NO_SELECTION));
+ }
+ throw e;
+ }
+ return new Cell(row, col);
+ }
+ });
+ return returnvalue;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isHeaderVisible() {
+ Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
+ "isHeaderVisible", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ if (m_table.getTableHeader() != null) {
+ return m_table.getTableHeader().isVisible()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ return Boolean.FALSE;
+ }
+ });
+ return (boolean) returnvalue.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isCellEditable(int row, int col) {
+ Boolean editable = (Boolean) getEventThreadQueuer().invokeAndWait(
+ "isCellEditable", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ Cell cell = getSelectedCell();
+ // see findBugs
+ return (m_table.isCellEditable(cell.getRow(),
+ cell.getCol())) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return editable.booleanValue();
+ }
+
+ /**
+ * Checks wether <code>0 <= value < count</code>.
+ *
+ * @param value
+ * The value to check.
+ * @param count
+ * The upper bound.
+ */
+ private void checkBounds(int value, int count) {
+ if ((value < 0) || (value >= count)) {
+ throw new StepExecutionException("Invalid row/column: " + value, //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.INVALID_INDEX_OR_HEADER));
+ }
+ }
+
+ /**
+ * Checks if the passed row and column are inside the bounds of the JTable.
+ *
+ * @param row
+ * The row
+ * @param column
+ * The column
+ * @throws StepExecutionException
+ * If the row or the column is outside of the JTable's bounds.
+ */
+ private void checkRowColBounds(int row, int column)
+ throws StepExecutionException {
+ checkBounds(row, m_table.getRowCount());
+ checkBounds(column, m_table.getColumnCount());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasCellSelection() {
+ try {
+ getSelectedCell();
+ } catch (StepExecutionException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Rectangle scrollCellToVisible(final int row, final int col)
+ throws StepExecutionException {
+ Rectangle bounds = (Rectangle) getEventThreadQueuer().invokeAndWait(
+ "getCellRect", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return m_table
+ .getCellRect(row, col, true);
+ }
+ });
+
+ getRobot().scrollToVisible(m_table, bounds);
+ return bounds;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ final Cell selectedCell = getSelectedCell();
+ return getCellText(selectedCell.getRow(), selectedCell.getCol());
+ }
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTextComponentAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTextComponentAdapter.java
new file mode 100644
index 000000000..75ed7a5d1
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTextComponentAdapter.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import javax.swing.text.JTextComponent;
+
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITextComponentAdapter;
+/**
+ * Implementation of the Interface <code>ITextComponentAdapter</code> as a
+ * adapter for the <code>JTextComponent</code> component.
+ * @author BREDEX GmbH
+ *
+ */
+public class JTextComponentAdapter extends WidgetAdapter
+ implements ITextComponentAdapter {
+
+ /** */
+ private JTextComponent m_textComponent;
+
+ /**
+ * Creates an object with the adapted JTextComponent.
+ * @param objectToAdapt
+ */
+ public JTextComponentAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_textComponent = (JTextComponent) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ return m_textComponent.getText();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSelection(final int position) {
+ getEventThreadQueuer().invokeAndWait("setSelection", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ m_textComponent.setCaretPosition(position);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSelection(final int start, final int end) {
+ getEventThreadQueuer().invokeAndWait("setSelection", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ m_textComponent.setSelectionStart(start);
+ m_textComponent.setSelectionEnd(end);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSelectionText() {
+ String actual = (String)getEventThreadQueuer().invokeAndWait(
+ "getSelectionText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_textComponent.getSelectedText();
+ }
+ });
+ return actual;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void selectAll() {
+ getRobot().keyStroke(getRobot().getSystemModifierSpec() + " A"); //$NON-NLS-1$
+
+ if (!getText().equals(getSelectionText())) {
+ getEventThreadQueuer().invokeAndWait(
+ "selectAll", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ m_textComponent.selectAll();
+ return null;
+ }
+ });
+ }
+
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEditable() {
+ return ((Boolean) getEventThreadQueuer().
+ invokeAndWait("isEditable", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_textComponent.isEditable()
+ && m_textComponent.isEnabled()
+ ? Boolean.TRUE : Boolean.FALSE; // see findBugs
+ }
+ })).booleanValue();
+ }
+
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTreeAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTreeAdapter.java
new file mode 100644
index 000000000..cd0f716a5
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTreeAdapter.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+import javax.swing.JTree;
+
+//import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeOperationContext;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITreeAdapter;
+import org.eclipse.jubula.rc.swing.swing.implclasses.TreeOperationContext;
+/**
+ * Implementation of the Tree interface as an adapter for <code>JTree</code>.
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class JTreeAdapter extends WidgetAdapter implements ITreeAdapter {
+
+
+ /**
+ * Creates an object with the adapted JTree.
+ * @param objectToAdapt
+ */
+ public JTreeAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ }
+
+ /**
+ * @return the casted Object
+ */
+ private JTree getTable() {
+ return (JTree) getRealComponent();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public AbstractTreeOperationContext getContext() {
+ TreeOperationContext context = new TreeOperationContext(
+ getEventThreadQueuer(), getRobot(), getTable());
+ return context;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public Object getRootNode() {
+
+ return getTable().getModel().getRoot();
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isRootVisible() {
+ return getTable().isRootVisible();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/WidgetAdapter.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/WidgetAdapter.java
new file mode 100644
index 000000000..c91b5dc24
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/WidgetAdapter.java
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter;
+
+
+import java.awt.AWTEvent;
+import java.awt.Toolkit;
+
+import javax.swing.JComponent;
+
+import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.DragAndDropHelper;
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.driver.RobotTiming;
+import org.eclipse.jubula.rc.common.exception.RobotException;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.listener.EventLock;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IWidgetAdapter;
+import org.eclipse.jubula.rc.swing.swing.caps.CapUtil;
+import org.eclipse.jubula.rc.swing.swing.caps.JMenuBarCAPs;
+import org.eclipse.jubula.rc.swing.swing.caps.CapUtil.PopupShownCondition;
+import org.eclipse.jubula.rc.swing.swing.driver.KeyCodeConverter;
+import org.eclipse.jubula.rc.swing.swing.implclasses.EventListener;
+import org.eclipse.jubula.tools.constants.TimeoutConstants;
+import org.eclipse.jubula.tools.i18n.I18n;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.jubula.tools.utils.TimeUtil;
+/**
+ * Implements the interface for widgets and supports basic methods
+ * which are needed for nearly all Swing ui components.
+ * This is a basic adaption for <code>JComponent</code>.
+ *
+ * @author BREDEX GmbH
+ */
+public abstract class WidgetAdapter extends AbstractComponentAdapter
+ implements IWidgetAdapter {
+
+ /** constants for communication */
+ protected static final String POS_UNIT_PIXEL = "Pixel"; //$NON-NLS-1$
+ /** constants for communication */
+ protected static final String POS_UNI_PERCENT = "Percent"; //$NON-NLS-1$
+
+
+
+
+
+ /** */
+ private JComponent m_component;
+
+ /**
+ * Used to store the component into the adapter.
+ * @param objectToAdapt
+ */
+ protected WidgetAdapter(Object objectToAdapt) {
+ m_component = (JComponent) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getRealComponent() {
+ return m_component;
+ }
+
+ /**
+ * Gets the IEventThreadQueuer.
+ *
+ * @return The Robot
+ * @throws RobotException
+ * If the Robot cannot be created.
+ */
+ protected IRobot getRobot() throws RobotException {
+ return getRobotFactory().getRobot();
+ }
+ /**
+ * @return The event thread queuer.
+ */
+ public IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getPropteryValue(final String propertyname) {
+ Object prop = getEventThreadQueuer().invokeAndWait("getProperty", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ try {
+ return getRobot().getPropertyValue(
+ getRealComponent(), propertyname);
+ } catch (RobotException e) {
+ throw new StepExecutionException(
+ e.getMessage(),
+ EventFactory.createActionError(
+ TestErrorEvent.PROPERTY_NOT_ACCESSABLE));
+ }
+ }
+ });
+ return String.valueOf(prop);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isShowing() {
+ Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
+ "isShowing", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_component.isShowing()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return (boolean) returnvalue.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasFocus() {
+ Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
+ "hasFocus", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_component.hasFocus()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return (boolean) returnvalue.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnabled() {
+ Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
+ "isEnabled", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_component.isEnabled()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return (boolean) returnvalue.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public AbstractMenuCAPs showPopup(final int button) {
+ final Object component = m_component;
+ Runnable showPopup = new Runnable() {
+ public void run() {
+ RobotTiming.sleepPreShowPopupDelay();
+ ClassLoader oldCl = Thread.currentThread()
+ .getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(component
+ .getClass().getClassLoader());
+ if ((getRobot()).isMouseInComponent(component)) {
+ getRobot().clickAtCurrentPosition(
+ component, 1, button);
+ } else {
+ getRobot().click(component, null,
+ ClickOptions.create()
+ .setClickCount(1)
+ .setMouseButton(button));
+ }
+ Thread.currentThread().setContextClassLoader(oldCl);
+ }
+ };
+
+ return showPopup(showPopup);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public AbstractMenuCAPs showPopup(
+ final int xPos, final String xUnits,
+ final int yPos, final String yUnits, final int button)
+ throws StepExecutionException {
+ final Object component = m_component;
+ Runnable showPopup = new Runnable() {
+ public void run() {
+ RobotTiming.sleepPreShowPopupDelay();
+ boolean isAbsoluteCoordinatesX =
+ xUnits.equalsIgnoreCase(POS_UNIT_PIXEL);
+ boolean isAbsoluteCoordinatesY =
+ yUnits.equalsIgnoreCase(POS_UNIT_PIXEL);
+ getRobot().click(component, null,
+ ClickOptions.create().setMouseButton(button),
+ xPos, isAbsoluteCoordinatesX,
+ yPos, isAbsoluteCoordinatesY);
+ }
+ };
+ return showPopup(showPopup);
+ }
+
+ /**
+ * Shows a popup menu using the given runnable and waits for the popup
+ * menu to appear.
+ *
+ * @param showPopupOperation The implementation to use for opening the
+ * popup menu.
+ * @return the popup menu.
+ */
+ public AbstractMenuCAPs showPopup(Runnable showPopupOperation) {
+ PopupShownCondition cond = new PopupShownCondition();
+ EventLock lock = new EventLock();
+ EventListener listener = new EventListener(lock, cond);
+ Toolkit.getDefaultToolkit().addAWTEventListener(listener,
+ AWTEvent.CONTAINER_EVENT_MASK);
+
+ // showPopupOperation must run in the current thread in order to
+ // avoid a race condition.
+ showPopupOperation.run();
+
+ synchronized (lock) {
+ try {
+ long timeout = TimeoutConstants.SERVER_TIMEOUT_WAIT_FOR_POPUP;
+ long done = System.currentTimeMillis() + timeout;
+ long now;
+ while ((!lock.isReleased() || (cond.getPopup() == null)
+ || !cond.getPopup().isShowing())
+ && (timeout > 0)) {
+ lock.wait(timeout);
+ now = System.currentTimeMillis();
+ timeout = done - now;
+ }
+ } catch (InterruptedException e) {
+ // ignore
+ } finally {
+ Toolkit.getDefaultToolkit().removeAWTEventListener(listener);
+ }
+ }
+ if (!lock.isReleased() || (cond.getPopup() == null)
+ || !cond.getPopup().isShowing()) {
+ throw new StepExecutionException("popup not shown", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.POPUP_NOT_FOUND));
+ }
+ AbstractMenuCAPs menuCAPs = new JMenuBarCAPs();
+ menuCAPs.setComponent(cond.getPopup());
+ return menuCAPs;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void showToolTip(final String text, final int textSize,
+ final int timePerWord, final int windowWidth) {
+ throw new StepExecutionException(
+ I18n.getString(TestErrorEvent.UNSUPPORTED_OPERATION_ERROR),
+ EventFactory.createActionError(
+ TestErrorEvent.UNSUPPORTED_OPERATION_ERROR));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDrag(int mouseButton, String modifier, int xPos,
+ String xUnits, int yPos, String yUnits) {
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ dndHelper.setMouseButton(mouseButton);
+ dndHelper.setModifier(modifier);
+ final IRobot robot = getRobot();
+ clickDirect(0, mouseButton, xPos, xUnits, yPos, yUnits);
+ CapUtil.pressOrReleaseModifiers(modifier, true);
+ robot.mousePress(null, null, mouseButton);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDrop(int xPos, String xUnits, int yPos, String yUnits,
+ int delayBeforeDrop) {
+
+ final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
+ final String modifier = dndHelper.getModifier();
+ final int mouseButton = dndHelper.getMouseButton();
+ try {
+ clickDirect(0, mouseButton, xPos, xUnits, yPos, yUnits);
+ TimeUtil.delay(delayBeforeDrop);
+ } finally {
+ getRobot().mouseRelease(null, null, mouseButton);
+ CapUtil.pressOrReleaseModifiers(modifier, false);
+ }
+ }
+
+ /**
+ * clicks into the component.
+ *
+ * @param count amount of clicks
+ * @param button what mouse button should be used
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @throws StepExecutionException error
+ */
+ private void clickDirect(int count, int button, int xPos, String xUnits,
+ int yPos, String yUnits) throws StepExecutionException {
+
+ getRobot().click(m_component, null,
+ ClickOptions.create()
+ .setClickCount(count)
+ .setMouseButton(button),
+ xPos, xUnits.equalsIgnoreCase(POS_UNIT_PIXEL),
+ yPos, yUnits.equalsIgnoreCase(POS_UNIT_PIXEL));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getKeyCode(String mod) {
+ return KeyCodeConverter.getKeyCode(mod);
+ }
+}
diff --git a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/factory/SwingAdapterFactory.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/factory/SwingAdapterFactory.java
new file mode 100644
index 000000000..68c690766
--- /dev/null
+++ b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/factory/SwingAdapterFactory.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swing.swing.uiadapter.factory;
+
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JRadioButton;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.JTree;
+import javax.swing.text.JTextComponent;
+
+import org.eclipse.jubula.rc.common.uiadapter.factory.IUIAdapterFactory;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.AbstractButtonAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JComboBoxAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JLabelAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JListAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuBarAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuItemAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JPopupMenuAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JTabbedPaneAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JTableAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JTextComponentAdapter;
+import org.eclipse.jubula.rc.swing.swing.uiadapter.JTreeAdapter;
+/**
+ * This is the adapter factory for all swing components. It is
+ * creating the specific adapter for a swing component.
+ *
+ * Since we are using adapter here, it is a adapter factory. But this must not
+ * be the case. It is only relevant that the object is implementing the
+ * specific interface.
+ * @author BREDEX GmbH
+ *
+ */
+public class SwingAdapterFactory implements IUIAdapterFactory {
+ /**
+ *
+ */
+ private static final Class[] SUPPORTEDCLASSES = new Class[] {
+ JButton.class, JCheckBox.class, JRadioButton.class,
+ JMenuBar.class, JMenuItem.class, JTree.class ,
+ JCheckBox.class, JRadioButton.class, JTable.class, JPopupMenu.class,
+ JList.class, JTextComponent.class, JComboBox.class,
+ JLabel.class , JTabbedPane.class};
+
+ /**
+ * {@inheritDoc}
+ */
+ public Class[] getSupportedClasses() {
+
+ return SUPPORTEDCLASSES;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public IComponentAdapter getAdapter(Object objectToAdapt) {
+ IComponentAdapter returnvalue = null;
+ if (objectToAdapt instanceof JButton) {
+ returnvalue = new AbstractButtonAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JRadioButton) {
+ returnvalue = new AbstractButtonAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JCheckBox) {
+ returnvalue = new AbstractButtonAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JMenuBar) {
+
+ returnvalue = new JMenuBarAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JMenuItem) {
+ returnvalue = new JMenuItemAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JTree) {
+ returnvalue = new JTreeAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JTable) {
+ returnvalue = new JTableAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JList) {
+ returnvalue = new JListAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JPopupMenu) {
+ returnvalue = new JPopupMenuAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JTextComponent) {
+ returnvalue = new JTextComponentAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JComboBox) {
+ returnvalue = new JComboBoxAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JLabel) {
+ returnvalue = new JLabelAdapter(objectToAdapt);
+
+ } else if (objectToAdapt instanceof JTabbedPane) {
+ returnvalue = new JTabbedPaneAdapter(objectToAdapt);
+
+ }
+
+ return returnvalue;
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/SwtAUTServer.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/SwtAUTServer.java
index 23c55e44b..cd040450a 100644
--- a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/SwtAUTServer.java
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/SwtAUTServer.java
@@ -15,6 +15,7 @@ import java.lang.reflect.InvocationTargetException;
import org.eclipse.jubula.rc.common.AUTServer;
import org.eclipse.jubula.rc.common.driver.IRobot;
import org.eclipse.jubula.rc.common.listener.BaseAUTListener;
+import org.eclipse.jubula.rc.common.uiadapter.factory.GUIAdapterFactoryRegistry;
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
import org.eclipse.jubula.rc.swt.driver.RobotFactorySwtImpl;
import org.eclipse.jubula.rc.swt.driver.RobotSwtImpl;
@@ -25,6 +26,7 @@ import org.eclipse.jubula.rc.swt.listener.FocusTracker;
import org.eclipse.jubula.rc.swt.listener.MappingListener;
import org.eclipse.jubula.rc.swt.listener.RecordListener;
import org.eclipse.jubula.rc.swt.listener.TableSelectionTracker;
+import org.eclipse.jubula.rc.swt.uiadapter.factory.SWTAdapterFactory;
import org.eclipse.jubula.tools.constants.AUTServerExitConstants;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
@@ -214,7 +216,11 @@ public class SwtAUTServer extends AUTServer {
*/
protected void startTasks() throws ExceptionInInitializerError,
InvocationTargetException, NoSuchMethodException {
-
+
+ // FIXME Better place to put the registration of the factory
+ GUIAdapterFactoryRegistry.getInstance().
+ registerFactory(new SWTAdapterFactory());
+
super.invokeAUT();
if (getCommunicator() != null) {
getCommunicator().close();
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/ButtonCAPs.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/ButtonCAPs.java
new file mode 100644
index 000000000..d7ffdbde4
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/ButtonCAPs.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.caps;
+
+
+import org.eclipse.jubula.rc.common.caps.AbstractButtonCAPs;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IButtonAdapter;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+
+
+/**
+ * The Toolkit specific implementation for <code>SWTButton</code> and subclasses.
+ *
+ * @author BREDEX GmbH
+ */
+public class ButtonCAPs extends AbstractButtonCAPs {
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ return new String[] {
+ SwtUtils.removeMnemonics(
+ ((IButtonAdapter)getComponent()).getText())};
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/CAPUtil.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/CAPUtil.java
new file mode 100644
index 000000000..c8d1f619d
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/CAPUtil.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.caps;
+
+import java.awt.Point;
+import java.util.StringTokenizer;
+
+import org.eclipse.jubula.rc.common.AUTServer;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.exception.RobotException;
+import org.eclipse.jubula.rc.common.util.KeyStrokeUtil;
+import org.eclipse.jubula.rc.swt.driver.KeyCodeConverter;
+import org.eclipse.jubula.rc.swt.driver.SwtRobot;
+import org.eclipse.jubula.tools.utils.EnvironmentUtils;
+import org.eclipse.swt.widgets.Display;
+/**
+ * Util class for some swt specific commands.
+ *
+ * @author BREDEX GmbH
+ */
+public class CAPUtil {
+
+
+ /**
+ *
+ */
+ private CAPUtil() { }
+
+
+ /**
+ * Gets the Robot.
+ * @return The Robot
+ * @throws RobotException If the Robot cannot be created.
+ */
+ public static IRobot getRobot() throws RobotException {
+ return AUTServer.getInstance().getRobot();
+ }
+
+ /**
+ * Move the mouse pointer from its current position to a few points in
+ * its proximity. This is used to initiate a drag operation.
+ *
+ */
+ public static void shakeMouse() {
+ /** number of pixels by which a "mouse shake" offsets the mouse cursor */
+ final int mouseShakeOffset = 10;
+
+ Point origin = getRobot().getCurrentMousePosition();
+ SwtRobot lowLevelRobot = new SwtRobot(Display.getDefault());
+ lowLevelRobot.mouseMove(
+ origin.x + mouseShakeOffset,
+ origin.y + mouseShakeOffset);
+ lowLevelRobot.mouseMove(
+ origin.x - mouseShakeOffset,
+ origin.y - mouseShakeOffset);
+ lowLevelRobot.mouseMove(origin.x, origin.y);
+ if (!EnvironmentUtils.isWindowsOS()
+ && !EnvironmentUtils.isMacOS()) {
+ boolean moreEvents = true;
+ while (moreEvents) {
+ moreEvents = Display.getDefault().readAndDispatch();
+ }
+ }
+ }
+
+ /**
+ * Presses or releases the given modifier.
+ * @param modifier the modifier.
+ * @param press if true, the modifier will be pressed.
+ * if false, the modifier will be released.
+ */
+ public static void pressOrReleaseModifiers(String modifier, boolean press) {
+ final IRobot robot = getRobot();
+ final StringTokenizer modTok = new StringTokenizer(
+ KeyStrokeUtil.getModifierString(modifier), " "); //$NON-NLS-1$
+ while (modTok.hasMoreTokens()) {
+ final String mod = modTok.nextToken();
+ final int keyCode = KeyCodeConverter.getKeyCode(mod);
+ if (press) {
+ robot.keyPress(null, keyCode);
+ } else {
+ robot.keyRelease(null, keyCode);
+ }
+ }
+ }
+
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/ListCAPs.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/ListCAPs.java
new file mode 100644
index 000000000..c6075b560
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/ListCAPs.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.caps;
+
+import org.eclipse.jubula.rc.common.caps.AbstractListCAPs;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class ListCAPs extends AbstractListCAPs {
+
+
+ /**
+ * {@inheritDoc}
+ */
+ protected int getSystemDefaultModifier() {
+ return SwtUtils.getSystemDefaultModifier();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/MenuCAPs.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/MenuCAPs.java
new file mode 100644
index 000000000..32e82c836
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/MenuCAPs.java
@@ -0,0 +1,305 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.caps;
+
+import org.apache.commons.lang.Validate;
+import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.IBaseImplementationClass;
+import org.eclipse.jubula.rc.common.implclasses.MenuUtilBase;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
+import org.eclipse.jubula.rc.swt.driver.EventThreadQueuerSwtImpl;
+import org.eclipse.jubula.rc.swt.driver.RobotSwtImpl;
+import org.eclipse.jubula.rc.swt.uiadapter.MenuItemAdapter;
+import org.eclipse.jubula.tools.i18n.I18n;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MenuEvent;
+import org.eclipse.swt.events.MenuListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+/**
+ * Toolkit specific commands for the <code>Menu</code>
+ *
+ * @author BREDEX GmbH
+ */
+public class MenuCAPs extends AbstractMenuCAPs
+ implements IBaseImplementationClass {
+
+
+ /** Test variable for contextMenus*/
+ private boolean m_isCM = false;
+
+
+ /**
+ * @return The event thread queuer.
+ */
+ public IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IComponentAdapter getComponent() {
+ if (m_isCM) {
+ return super.getComponent();
+ }
+ final Shell shell = ((RobotSwtImpl)getRobot()).getActiveWindow();
+ if (shell == null) {
+ setComponent(null);
+ } else {
+ final IEventThreadQueuer queuer = new EventThreadQueuerSwtImpl();
+
+ queuer.invokeAndWait("setMenuBarComponent", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ Menu menu = shell.getMenuBar();
+ setComponent(menu);
+
+ return null;
+ }
+ });
+ }
+ return super.getComponent();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ return null;
+ }
+
+ /**
+ * Tries to select a menu item in a menu defined by a Text-Path
+ * @param namePath the menu item to select
+ * @param operator operator used for matching
+ */
+ public void selectMenuItem(String namePath, final String operator) {
+ final String[] pathItems = MenuUtilBase.splitPath(namePath);
+ if (pathItems.length == 0) {
+ throw new StepExecutionException("empty path to menuitem not allowed", //$NON-NLS-1$
+ EventFactory.createActionError());
+ }
+
+ try {
+
+ final MenuItemAdapter itemAdapter =
+ (MenuItemAdapter) navigateToMenuItem(
+ getAndCheckMenu(), pathItems, operator);
+ if (itemAdapter.getRealComponent() == null) {
+ throwMenuItemNotFound();
+ }
+
+ Rectangle bounds = itemAdapter.getMenuItemBounds();
+ Rectangle nullBounds = new Rectangle(0, 0, 0, 0);
+
+ if (bounds.equals(nullBounds)) {
+ itemAdapter.selectProgramatically();
+ } else {
+ itemAdapter.selectMenuItem();
+ }
+ } catch (StepExecutionException e) {
+ try {
+ closeMenu(getAndCheckMenu(), pathItems, operator);
+ } catch (StepExecutionException e1) {
+ if (getLog().isInfoEnabled()) {
+ getLog().info("Tried to close a disabled or already closed menu."); //$NON-NLS-1$
+ }
+ }
+ throw e;
+ }
+
+ }
+
+ /**
+ * Tries to select a menu item in a menu defined by an Index-Path
+ * @param indexPath the menu item to select
+ */
+ public void selectMenuItemByIndexpath(String indexPath) {
+ final int[] indexItems = MenuUtilBase.splitIndexPath(indexPath);
+ if (indexItems.length == 0) {
+ throw new StepExecutionException("empty path to menuitem not allowed", //$NON-NLS-1$
+ EventFactory.createActionError());
+ }
+
+ try {
+ MenuItemAdapter menuItemAdapter = (MenuItemAdapter)
+ navigateToMenuItem(getAndCheckMenu(), indexItems);
+ if (menuItemAdapter.getRealComponent() == null) {
+ throwMenuItemNotFound();
+ }
+
+ Rectangle bounds = menuItemAdapter.getMenuItemBounds();
+ Rectangle nullBounds = new Rectangle(0, 0, 0, 0);
+
+ if (bounds.equals(nullBounds)) {
+ menuItemAdapter.selectProgramatically();
+ } else {
+ menuItemAdapter.selectMenuItem();
+ }
+ } catch (StepExecutionException e) {
+ try {
+ closeMenu(getAndCheckMenu(), indexItems);
+ } catch (StepExecutionException e1) {
+ if (getLog().isInfoEnabled()) {
+ getLog().info("Tried to close a disabled or already closed menu."); //$NON-NLS-1$
+ }
+ }
+ throwMenuItemNotFound();
+ }
+ }
+
+ /**
+ *
+ * @return the IMenuAdapter.
+ * @throws StepExecutionException
+ * if the active window has no menu bar.
+ */
+ protected IMenuAdapter getAndCheckMenu() throws StepExecutionException {
+ // Verify that there is an active window
+ if (((RobotSwtImpl)getRobot()).getActiveWindow() == null) {
+ throw new StepExecutionException(
+ I18n.getString(TestErrorEvent.NO_ACTIVE_WINDOW),
+ EventFactory.createActionError(
+ TestErrorEvent.NO_ACTIVE_WINDOW));
+ }
+ return super.getAndCheckMenu();
+ }
+
+
+ /**
+ *
+ */
+ private void throwMenuItemNotFound() {
+ throw new StepExecutionException("no such menu item found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected IMenuItemAdapter newMenuItemAdapter(Object component) {
+ return new MenuItemAdapter(component);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void closeMenu(IMenuAdapter menuBar, int[] path) {
+ Validate.notNull(getMenu(menuBar));
+ closeMenu(menuBar, path.length);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void closeMenu(IMenuAdapter menuBar, String[] textPath,
+ String operator) {
+ Validate.notNull(getMenu(menuBar));
+ closeMenu(menuBar, textPath.length);
+ }
+
+ /**
+ * Closes the menu cascade with the KEY ESC
+ * @param menuBar menu
+ * @param maxCascadeLength an integer so that the closing operation is not infinite
+ */
+ private void closeMenu(final IMenuAdapter menuBar, int maxCascadeLength) {
+ final MenuHiddenListener menuListener =
+ new MenuHiddenListener();
+ getMenu(menuBar).getDisplay().syncExec(new Runnable() {
+ public void run() {
+ getMenu(menuBar).addMenuListener(menuListener);
+ }
+ });
+ // Press 'ESC' key until the first menu is gone or we reach
+ // the maxCascadeLength. This prevents infinite loops if this
+ // is used on a platform that does not use 'ESC' to close menus.
+ for (int i = 0;
+ i < maxCascadeLength && !menuListener.isMenuHidden();
+ i++) {
+
+ getRobot().keyType(getMenu(menuBar), SWT.ESC);
+ }
+
+ }
+
+ /**
+ *
+ * @param menu the menu adapter
+ * @return the real SWT menu
+ */
+ private Menu getMenu(final IMenuAdapter menu) {
+ return (Menu) menu.getRealComponent();
+ }
+ /**
+ *
+ * @return -
+ */
+ public boolean isContextMenu() {
+ return m_isCM;
+ }
+ /**
+ *
+ * @param isCM
+ */
+ public void setContextMenu(boolean isCM) {
+ this.m_isCM = isCM;
+ }
+
+ /**
+ * Listens for a menu to be hidden, the removes itself from the menu's
+ * listener list.
+ *
+ * @author BREDEX GmbH
+ * @created Nov 01, 2011
+ */
+ private static final class MenuHiddenListener implements MenuListener {
+
+ /** whether the expected event has occurred */
+ private boolean m_eventOccurred = false;
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void menuHidden(MenuEvent e) {
+ m_eventOccurred = true;
+ ((Menu)e.widget).removeMenuListener(this);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void menuShown(MenuEvent e) {
+ // no-op
+ }
+
+ /**
+ *
+ * @return <code>true</code> if the menu has been hidden since this
+ * listener was registered. Otherwise, <code>false</code>.
+ */
+ public boolean isMenuHidden() {
+ return m_eventOccurred;
+ }
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/TableCAPs.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/TableCAPs.java
new file mode 100644
index 000000000..23d8876e3
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/TableCAPs.java
@@ -0,0 +1,714 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.caps;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import org.eclipse.jubula.rc.common.CompSystemConstants;
+import org.eclipse.jubula.rc.common.caps.AbstractTableCAPs;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.table.Cell;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITableAdapter;
+import org.eclipse.jubula.rc.swt.driver.DragAndDropHelperSwt;
+import org.eclipse.jubula.rc.swt.uiadapter.TableAdapter;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.jubula.tools.constants.InputConstants;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Widget;
+/**
+ * Toolkit specific commands for the <code>Table</code>
+ *
+ * @author BREDEX GmbH
+ */
+public class TableCAPs extends AbstractTableCAPs {
+
+
+ /**
+ * Gets the real table component
+ * @return the table
+ */
+ private Table getTable() {
+ return (Table)getComponent().getRealComponent();
+ }
+
+ /**
+ * @return The event thread queuer.
+ */
+ public IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ final String[] componentTextArray;
+ Item[] itemArray = getTable().getColumns();
+ componentTextArray = getTextArrayFromItemArray(itemArray);
+ return componentTextArray;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Object setEditorToReplaceMode(Object editor, boolean replace) {
+ if (replace) {
+ getRobot().clickAtCurrentPosition(editor, 3,
+ InputConstants.MOUSE_BUTTON_LEFT);
+ } else {
+ getRobot().clickAtCurrentPosition(editor, 1,
+ InputConstants.MOUSE_BUTTON_LEFT);
+ }
+ return editor;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Object activateEditor(Cell cell, Rectangle rectangle) {
+ TableAdapter table = (TableAdapter) getComponent();
+ return table.activateEditor(cell);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Rectangle scrollCellToVisible(final int row, final int col)
+ throws StepExecutionException {
+ final Table table = getTable();
+ getEventThreadQueuer().invokeAndWait("scrollCellToVisible", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ if (table.getColumnCount() > 0 || col > 0) {
+ table.showColumn(table.getColumn(col));
+ }
+ table.showItem(table.getItem(row));
+ return null;
+ }
+ });
+
+ final Rectangle cellBoundsRelativeToParent = getCellBounds(row, col);
+
+ getEventThreadQueuer().invokeAndWait("getCellBoundsRelativeToParent", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ org.eclipse.swt.graphics.Point cellOriginRelativeToParent =
+ table.getDisplay().map(
+ table, table.getParent(),
+ new org.eclipse.swt.graphics.Point(
+ cellBoundsRelativeToParent.x,
+ cellBoundsRelativeToParent.y));
+ cellBoundsRelativeToParent.x =
+ cellOriginRelativeToParent.x;
+ cellBoundsRelativeToParent.y =
+ cellOriginRelativeToParent.y;
+ return null;
+ }
+ });
+
+ Control parent = (Control)getEventThreadQueuer().invokeAndWait("getParent", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ table.getParent();
+ return null;
+ }
+ });
+
+
+ getRobot().scrollToVisible(
+ parent, cellBoundsRelativeToParent);
+
+ return getVisibleBounds(getCellBounds(row, col));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected int getExtendSelectionModifier() {
+ return SWT.MOD1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Cell getCellAtMousePosition() throws StepExecutionException {
+
+ final Table table = getTable();
+ final Point awtMousePos = getRobot().getCurrentMousePosition();
+ Cell returnvalue = (Cell) getEventThreadQueuer().invokeAndWait(
+ "getCellAtMousePosition", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ Cell cell = null;
+ final int itemCount = table.getItemCount();
+ for (int rowCount = table.getTopIndex();
+ rowCount < itemCount; rowCount++) {
+ if (cell != null) {
+ break;
+ }
+ final int columnCount = table.getColumnCount();
+ if (columnCount > 0) {
+ for (int col = 0; col < columnCount; col++) {
+ final Rectangle itemBounds = getCellBounds(
+ rowCount, col);
+ final org.eclipse.swt.graphics.Point
+ absItemBounds = table
+ .toDisplay(itemBounds.x,
+ itemBounds.y);
+ final Rectangle absRect = new Rectangle(
+ absItemBounds.x, absItemBounds.y,
+ itemBounds.width,
+ itemBounds.height);
+ if (absRect.contains(awtMousePos)) {
+ cell = new Cell(rowCount, col);
+ break;
+ }
+ }
+ } else {
+ final Rectangle itemBounds = getCellBounds(
+ rowCount, 0);
+ final org.eclipse.swt.graphics.Point
+ absItemBounds = table
+ .toDisplay(itemBounds.x, itemBounds.y);
+ final Rectangle absRect = new Rectangle(
+ absItemBounds.x, absItemBounds.y,
+ itemBounds.width, itemBounds.height);
+ if (absRect.contains(awtMousePos)) {
+ cell = new Cell(rowCount, 0);
+ }
+ }
+ }
+ if (cell == null) {
+ throw new StepExecutionException(
+ "No cell under mouse position found!", //$NON-NLS-1$
+ EventFactory
+ .createActionError(
+ TestErrorEvent.NOT_FOUND));
+ }
+ return cell;
+ }
+ });
+ return returnvalue;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected boolean isMouseOnHeader() {
+ final Table table = getTable();
+ final ITableAdapter adapter = (ITableAdapter)getComponent();
+ Boolean isVisible;
+ isVisible = (Boolean)getEventThreadQueuer().invokeAndWait(
+ "isMouseOnHeader", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return new Boolean(table.getHeaderVisible());
+ }
+ });
+
+ if (!(isVisible.booleanValue())) {
+ return false;
+ }
+
+ Boolean isOnHeader = new Boolean(false);
+ isOnHeader = (Boolean)getEventThreadQueuer().invokeAndWait(
+ "isMouseOnHeader", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ final Point awtMousePos = getRobot()
+ .getCurrentMousePosition();
+ org.eclipse.swt.graphics.Point mousePos =
+ new org.eclipse.swt.graphics.Point(
+ awtMousePos.x, awtMousePos.y);
+
+ for (int j = 0; j < table.getColumnCount(); j++) {
+ final Rectangle constraints =
+ adapter.getHeaderBounds(j);
+
+ org.eclipse.swt.graphics.Rectangle bounds =
+ SwtUtils.getWidgetBounds(
+ table);
+
+ if (constraints != null) {
+ // Use SWT's mapping function, if possible, as it is more
+ // multi-platform than simply adding the x and y values.
+ org.eclipse.swt.graphics.Point
+ convertedLocation = getConvertedLocation(
+ constraints);
+ bounds.x = convertedLocation.x;
+ bounds.y = convertedLocation.y;
+
+ bounds.height = constraints.height;
+ bounds.width = constraints.width;
+ }
+
+ if (bounds.contains(mousePos)) {
+ return new Boolean(true);
+ }
+ }
+ return new Boolean(false);
+ }
+ });
+
+ return isOnHeader.booleanValue();
+ }
+
+ /**
+ * Returns an array of representation strings that corresponds to the given
+ * array of items or null if the given array is null;
+ * @param itemArray the item array whose item texts have to be read
+ * @return array of item texts corresponding to the given item array
+ */
+ protected final String[] getTextArrayFromItemArray(Item[] itemArray) {
+ final String[] itemTextArray;
+ if (itemArray == null) {
+ itemTextArray = null;
+ } else {
+ itemTextArray = new String[itemArray.length];
+ for (int i = 0; i < itemArray.length; i++) {
+ Item item = itemArray[i];
+ if (item == null) {
+ itemTextArray[i] = null;
+ } else {
+ itemTextArray[i] = SwtUtils.removeMnemonics(item.getText());
+ }
+ }
+ }
+
+ return itemTextArray;
+ }
+
+ /**
+ * Computes the visible cellBounds inside the visible bounds of the table.<br>
+ * The result is the intersection of the visible bounds of the table and the
+ * bounds of the cell.
+ * @param cellBounds the bounds of the cell to click in. These bounds must
+ * be relative to the table's location.
+ * @return the visible cell bounds, relative to the table's location.
+ */
+ private Rectangle getVisibleBounds(Rectangle cellBounds) {
+ org.eclipse.swt.graphics.Rectangle r =
+ (org.eclipse.swt.graphics.Rectangle)
+ getEventThreadQueuer().invokeAndWait("getVisibleCellBounds: " + cellBounds, //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() {
+ return getTable().getClientArea();
+ }
+ });
+
+ Rectangle visibleTableBounds = new Rectangle(
+ r.x, r.y, r.width, r.height);
+ Rectangle visibleCellBounds =
+ visibleTableBounds.intersection(cellBounds);
+ return visibleCellBounds;
+ }
+
+ /**
+ * @param constraints Rectangle
+ * @return converted Location of table
+ */
+ private org.eclipse.swt.graphics.Point getConvertedLocation(
+ final Rectangle constraints) {
+ org.eclipse.swt.graphics.Point convertedLocation =
+ (org.eclipse.swt.graphics.Point)getEventThreadQueuer()
+ .invokeAndWait("toDisplay", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return getTable().toDisplay(
+ constraints.x, constraints.y);
+ }
+ });
+ return convertedLocation;
+ }
+
+ /**
+ *
+ * @param row The row of the cell
+ * @param col The column of the cell
+ * @return The bounding rectangle for the cell, relative to the table's
+ * location.
+ */
+ private Rectangle getCellBounds(final int row, final int col) {
+ final Table table = getTable();
+ Rectangle cellBounds = (Rectangle)getEventThreadQueuer().invokeAndWait(
+ "evaluateCellBounds", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ checkRowColBounds(row, col);
+ TableItem ti = table.getItem(row);
+ int column = (table.getColumnCount() > 0 || col > 0)
+ ? col : 0;
+ org.eclipse.swt.graphics.Rectangle r =
+ ti.getBounds(column);
+ String text = ti.getText(column);
+ Image image = ti.getImage(column);
+ if (text != null && text.length() != 0) {
+ GC gc = new GC(table);
+ int charWidth = 0;
+ try {
+ FontMetrics fm = gc.getFontMetrics();
+ charWidth = fm.getAverageCharWidth();
+ } finally {
+ gc.dispose();
+ }
+ r.width = text.length() * charWidth;
+ if (image != null) {
+ r.width += image.getBounds().width;
+ }
+ } else if (image != null) {
+ r.width = image.getBounds().width;
+ }
+ if (column > 0) {
+ TableColumn tc = table.getColumn(column);
+ int alignment = tc.getAlignment();
+ if (alignment == SWT.CENTER) {
+ r.x += ((double)tc.getWidth() / 2)
+ - ((double)r.width / 2);
+ }
+ if (alignment == SWT.RIGHT) {
+ r.x += tc.getWidth() - r.width;
+ }
+ }
+
+ return new Rectangle(r.x, r.y, r.width, r.height);
+ }
+ });
+ return cellBounds;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ protected Object getSpecificRectangle(Rectangle rectangle) {
+ return new org.eclipse.swt.graphics.Rectangle(rectangle.x, rectangle.y,
+ rectangle.width, rectangle.height);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdClickDirect(int count, int button, int xPos, String xUnits,
+ int yPos, String yUnits) throws StepExecutionException {
+
+ int correctedYPos = correctYPos(yPos, yUnits);
+ super.gdClickDirect(count, button, xPos, xUnits, correctedYPos, yUnits);
+ }
+
+ /**
+ * Corrects the given Y position based on the height of the table's header.
+ * This ensures, for example, that test steps don't try to click within the
+ * table header (where we receive no confirmation events).
+ *
+ * @param pos The Y position to correct.
+ * @param units The units used for the Y position.
+ * @return The corrected Y position.
+ */
+ private int correctYPos(int pos, String units) {
+ int correctedPos = pos;
+ int headerHeight = ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getHeaderHeight", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ return new Integer(
+ ((Table)getComponent().getRealComponent())
+ .getHeaderHeight());
+ }
+
+ })).intValue();
+
+ if (POS_UNIT_PIXEL.equalsIgnoreCase(units)) {
+ // Pixel units
+ correctedPos += headerHeight;
+ } else {
+ // Percentage units
+ int totalHeight = ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getWidgetBounds", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ return new Integer(
+ SwtUtils.getWidgetBounds(
+ (Widget) getComponent().
+ getRealComponent()).height);
+ }
+
+ })).intValue();
+ long targetHeight = totalHeight - headerHeight;
+ long targetPos = Math.round((double)targetHeight * (double)pos
+ / 100.0);
+ targetPos += headerHeight;
+ double heightPercentage =
+ (double)targetPos / (double)totalHeight * 100.0;
+ correctedPos = (int)Math.round(heightPercentage);
+ if (correctedPos > 100) { // rounding error
+ correctedPos = 100;
+ }
+ }
+ return correctedPos;
+ }
+
+ /**
+ * Drags the cell of the Table.<br>
+ * With the xPos, yPos, xunits and yUnits the click position inside the
+ * cell can be defined.
+ *
+ * @param mouseButton the mouseButton.
+ * @param modifier the modifier.
+ * @param row The row of the cell.
+ * @param rowOperator the row header operator
+ * @param col The column of the cell.
+ * @param colOperator the column header operator
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @throws StepExecutionException
+ * If the row or the column is invalid
+ */
+ public void gdDragCell(final int mouseButton, final String modifier,
+ final String row, String rowOperator, final String col,
+ final String colOperator, final int xPos, final String xUnits,
+ final int yPos, final String yUnits)
+ throws StepExecutionException {
+
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ dndHelper.setMouseButton(mouseButton);
+ dndHelper.setModifier(modifier);
+ dndHelper.setDragComponent(null);
+
+ gdSelectCell(row, rowOperator, col, colOperator, 0, xPos,
+ xUnits, yPos, yUnits,
+ CompSystemConstants.EXTEND_SELECTION_NO, 1);
+ }
+
+ /**
+ * Drops on the cell of the JTable.<br>
+ * With the xPos, yPos, xunits and yUnits the click position inside the
+ * cell can be defined.
+ *
+ * @param row The row of the cell.
+ * @param rowOperator The row operator
+ * @param col The column of the cell.
+ * @param colOperator The column operator
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ * @throws StepExecutionException
+ * If the row or the column is invalid
+ */
+ public void gdDropCell(final String row, final String rowOperator,
+ final String col, final String colOperator, final int xPos,
+ final String xUnits, final int yPos, final String yUnits,
+ int delayBeforeDrop) throws StepExecutionException {
+
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ final IRobot robot = getRobot();
+
+ pressOrReleaseModifiers(dndHelper.getModifier(), true);
+ try {
+ getEventThreadQueuer().invokeAndWait("gdDropCell", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ // drag
+ robot.mousePress(dndHelper.getDragComponent(), null,
+ dndHelper.getMouseButton());
+
+ CAPUtil.shakeMouse();
+
+ // drop
+ gdSelectCell(row, rowOperator, col, colOperator, 0, xPos,
+ xUnits, yPos, yUnits,
+ CompSystemConstants.EXTEND_SELECTION_NO, 1);
+ return null;
+ }
+ });
+
+ waitBeforeDrop(delayBeforeDrop);
+
+ } finally {
+ robot.mouseRelease(dndHelper.getDragComponent(), null,
+ dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(), false);
+ }
+ }
+
+ /**
+ * Finds the first row which contains the value <code>value</code>
+ * in column <code>col</code> and drags this row.
+ *
+ * @param mouseButton the mouse button
+ * @param modifier the modifier
+ * @param col the column
+ * @param colOperator the column header operator
+ * @param value the value
+ * @param regexOp the regex operator
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ */
+ public void gdDragRowByValue(int mouseButton, String modifier, String col,
+ String colOperator, final String value, final String regexOp,
+ final String searchType) {
+
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ dndHelper.setMouseButton(mouseButton);
+ dndHelper.setModifier(modifier);
+ dndHelper.setDragComponent(null);
+
+ gdSelectRowByValue(col, colOperator, value, regexOp, 1,
+ CompSystemConstants.EXTEND_SELECTION_NO,
+ searchType, 1);
+ }
+
+ /**
+ * Finds the first row which contains the value <code>value</code>
+ * in column <code>col</code> and drops on this row.
+ *
+ * @param col the column
+ * @param colOperator the column operator
+ * @param value the value
+ * @param regexOp the regex operator
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ */
+ public void gdDropRowByValue(final String col, final String colOperator,
+ final String value, final String regexOp, final String searchType,
+ int delayBeforeDrop) {
+
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ final IRobot robot = getRobot();
+ pressOrReleaseModifiers(dndHelper.getModifier(), true);
+
+ try {
+ getEventThreadQueuer().invokeAndWait("gdDropRowByValue", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ // drag
+ robot.mousePress(dndHelper.getDragComponent(), null,
+ dndHelper.getMouseButton());
+
+ CAPUtil.shakeMouse();
+
+ // drop
+ gdSelectRowByValue(col, colOperator, value, regexOp,
+ CompSystemConstants.EXTEND_SELECTION_NO,
+ searchType,
+ ClickOptions.create().setClickCount(0));
+ return null;
+ }
+ });
+
+ waitBeforeDrop(delayBeforeDrop);
+
+ } finally {
+ robot.mouseRelease(dndHelper.getDragComponent(), null,
+ dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(), false);
+ }
+ }
+
+ /**
+ * Finds the first column which contains the value <code>value</code>
+ * in the given row and drags the cell.
+ *
+ * @param mouseButton the mouse button
+ * @param modifier the modifiers
+ * @param row the row
+ * @param rowOperator the row header operator
+ * @param value the value
+ * @param regex search using regex
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ */
+ public void gdDragCellByColValue(int mouseButton, String modifier,
+ String row, String rowOperator, final String value,
+ final String regex, final String searchType) {
+
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ dndHelper.setMouseButton(mouseButton);
+ dndHelper.setModifier(modifier);
+ dndHelper.setDragComponent(null);
+ gdSelectCellByColValue(row, rowOperator, value, regex,
+ CompSystemConstants.EXTEND_SELECTION_NO,
+ searchType, ClickOptions.create().setClickCount(0));
+ }
+
+ /**
+ * Finds the first column which contains the value <code>value</code>
+ * in the given row and drops on the cell.
+ *
+ * @param row the row
+ * @param rowOperator the row header operator
+ * @param value the value
+ * @param regex search using regex
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ */
+ public void gdDropCellByColValue(final String row, final String rowOperator,
+ final String value, final String regex, final String searchType,
+ int delayBeforeDrop) {
+
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ final IRobot robot = getRobot();
+ pressOrReleaseModifiers(dndHelper.getModifier(), true);
+
+ try {
+ getEventThreadQueuer().invokeAndWait("gdDropCellByColValue", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ // drag
+ robot.mousePress(dndHelper.getDragComponent(), null,
+ dndHelper.getMouseButton());
+
+ CAPUtil.shakeMouse();
+
+ // drop
+ gdSelectCellByColValue(row, rowOperator, value, regex,
+ CompSystemConstants.EXTEND_SELECTION_NO,
+ searchType,
+ ClickOptions.create().setClickCount(0));
+ return null;
+ }
+ });
+
+ waitBeforeDrop(delayBeforeDrop);
+
+ } finally {
+ robot.mouseRelease(dndHelper.getDragComponent(), null,
+ dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(), false);
+ }
+ }
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/TreeCAPs.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/TreeCAPs.java
new file mode 100644
index 000000000..c9c535edc
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/TreeCAPs.java
@@ -0,0 +1,901 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.caps;
+
+import java.util.StringTokenizer;
+
+import org.apache.commons.lang.Validate;
+import org.eclipse.jubula.rc.common.CompSystemConstants;
+import org.eclipse.jubula.rc.common.caps.AbstractTreeCAPs;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeNodeOperation;
+import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeNodeTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeOperationContext;
+import org.eclipse.jubula.rc.common.implclasses.tree.ChildTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.ExpandCollapseTreeNodeOperation;
+import org.eclipse.jubula.rc.common.implclasses.tree.INodePath;
+import org.eclipse.jubula.rc.common.implclasses.tree.ParentTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.PathBasedTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.SelectTreeNodeOperation;
+import org.eclipse.jubula.rc.common.implclasses.tree.SiblingTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.StandardDepthFirstTraverser;
+import org.eclipse.jubula.rc.common.implclasses.tree.TreeNodeOperation;
+import org.eclipse.jubula.rc.common.implclasses.tree.TreeNodeOperationConstraint;
+import org.eclipse.jubula.rc.common.util.KeyStrokeUtil;
+import org.eclipse.jubula.rc.swt.driver.DragAndDropHelperSwt;
+import org.eclipse.jubula.rc.swt.driver.KeyCodeConverter;
+import org.eclipse.jubula.rc.swt.implclasses.TableTreeOperationContext;
+import org.eclipse.jubula.rc.swt.implclasses.TreeOperationContext;
+import org.eclipse.jubula.rc.swt.implclasses.tree.ToggleCheckboxOperation;
+import org.eclipse.jubula.rc.swt.implclasses.tree.VerifyCheckboxOperation;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.Tree;
+/**
+ * Toolkit specific commands for the <code>Tree</code>
+ *
+ * @author BREDEX GmbH
+ */
+public class TreeCAPs extends AbstractTreeCAPs {
+
+
+ /**
+ * Finds the item at a given position in the tree.
+ *
+ * @author BREDEX GmbH
+ * @created Jul 28, 2010
+ */
+ private static final class ItemAtPointTreeNodeOperation
+ extends AbstractTreeNodeOperation {
+
+ /** the item that was found at the given position */
+ private TreeItem m_itemAtPoint;
+
+ /** the position (in absolute coordinates) at which to find the item */
+ private Point m_absPoint;
+
+ /**
+ * the bounds (in absolute coordinates) of the tree in which the
+ * search should take place
+ */
+ private Rectangle m_absTreeBounds;
+
+
+ /**
+ * Constructor
+ *
+ * @param absPoint The position (in absolute coordinates) at which to
+ * find the item.
+ * @param absTreeBounds The bounds (in absolute coordinates) of the
+ * tree in which the search should take place.
+ */
+ public ItemAtPointTreeNodeOperation(Point absPoint,
+ Rectangle absTreeBounds) {
+ m_absPoint = absPoint;
+ m_absTreeBounds = absTreeBounds;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean operate(Object node) throws StepExecutionException {
+ if (getContext().isVisible(node) && node instanceof TreeItem) {
+ TreeItem currentItem = (TreeItem)node;
+ final Rectangle absItemBounds =
+ SwtUtils.getBounds(currentItem);
+ absItemBounds.x = m_absTreeBounds.x;
+ absItemBounds.width = m_absTreeBounds.width;
+ if (SwtUtils.containsInclusive(
+ absItemBounds, m_absPoint)) {
+ m_itemAtPoint = currentItem;
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ *
+ * @return the item found at the given position, or <code>null</code> if
+ * no item was found. Note that this method will always return
+ * <code>null</code> if called before or during execution of
+ * {@link #operate(Object)}.
+ */
+ public TreeItem getItemAtPoint() {
+ return m_itemAtPoint;
+ }
+ }
+
+ /**
+ * @return The event thread queuer.
+ */
+ protected IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+ /**
+ *
+ * @return the Tree
+ */
+ private Tree getTree() {
+ return (Tree) getComponent().getRealComponent();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdVerifyTextAtMousePosition(String pattern, String operator) {
+ TreeItem itemAtMousePosition = (TreeItem) getNodeAtMousePosition();
+ int column = getMouseColumn();
+ AbstractTreeOperationContext context;
+
+ if (column != -1) {
+ context =
+ new TableTreeOperationContext(
+ getEventThreadQueuer(), getRobot(),
+ getTree(), column);
+ } else {
+ context =
+ new TableTreeOperationContext(
+ getEventThreadQueuer(), getRobot(),
+ getTree());
+ }
+
+ Verifier.match(context.getRenderedText(itemAtMousePosition),
+ pattern, operator);
+
+ }
+
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDragByTextPath(int mouseButton, String modifier,
+ String pathType, int preAscend, String treePath, String operator) {
+
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+
+ dndHelper.setMouseButton(mouseButton);
+ dndHelper.setModifier(modifier);
+ dndHelper.setDragComponent(null);
+
+ SwtUtils.waitForDisplayIdle(getTree().getDisplay());
+
+ gdSelect(pathType, preAscend, treePath, operator, 0, 1,
+ CompSystemConstants.EXTEND_SELECTION_NO);
+
+ SwtUtils.waitForDisplayIdle(getTree().getDisplay());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDropByTextPath(final String pathType, final int preAscend,
+ final String treePath, final String operator, int delayBeforeDrop) {
+
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ final IRobot robot = getRobot();
+
+ try {
+ pressOrReleaseModifiers(dndHelper.getModifier(), true);
+ getEventThreadQueuer().invokeAndWait("gdDropByTextPath - perform drag", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ // drag
+ robot.mousePress(dndHelper.getDragComponent(), null,
+ dndHelper.getMouseButton());
+
+ CAPUtil.shakeMouse();
+
+ return null;
+ }
+ });
+
+ // Post a MouseMove event in order to break the Display out of its
+ // post-drag "freeze". It appears as though the mouse position
+ // change needs to be extreme in order to nudge the Display back
+ // into action (i.e. (<mouse-location> + 1) was insufficient),
+ // so the default Event values (x, y = 0) are used.
+ Event wakeEvent = new Event();
+ wakeEvent.type = SWT.MouseMove;
+ getTree().getDisplay().post(wakeEvent);
+
+ waitForDisplayUpdate();
+
+ // drop
+ gdSelect(pathType, preAscend, treePath, operator, 0, 1,
+ CompSystemConstants.EXTEND_SELECTION_NO);
+
+ SwtUtils.waitForDisplayIdle(getTree().getDisplay());
+ waitBeforeDrop(delayBeforeDrop);
+
+ } finally {
+ robot.mouseRelease(null, null, dndHelper.getMouseButton());
+ pressOrReleaseModifiers(
+ dndHelper.getModifier(), false);
+ SwtUtils.waitForDisplayIdle(getTree().getDisplay());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDragByIndexPath(int mouseButton, String modifier,
+ String pathType, int preAscend, String indexPath) {
+
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+
+ dndHelper.setMouseButton(mouseButton);
+ dndHelper.setModifier(modifier);
+ dndHelper.setDragComponent(null);
+
+ SwtUtils.waitForDisplayIdle(getTree().getDisplay());
+
+ gdSelectByIndices(pathType, preAscend, indexPath, 0, 1,
+ CompSystemConstants.EXTEND_SELECTION_NO);
+
+ SwtUtils.waitForDisplayIdle(getTree().getDisplay());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDropByIndexPath(final String pathType, final int preAscend,
+ final String indexPath, int delayBeforeDrop) {
+
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ final IRobot robot = getRobot();
+ try {
+ pressOrReleaseModifiers(dndHelper.getModifier(), true);
+ getEventThreadQueuer().invokeAndWait("gdDropByIndexPath - perform drag", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ // drag
+ robot.mousePress(dndHelper.getDragComponent(), null,
+ dndHelper.getMouseButton());
+
+ CAPUtil.shakeMouse();
+
+ return null;
+ }
+ });
+
+ // Post a MouseMove event in order to break the Display out of its
+ // post-drag "freeze". It appears as though the mouse position
+ // change needs to be extreme in order to nudge the Display back
+ // into action (i.e. (<mouse-location> + 1) was insufficient),
+ // so the default Event values (x, y = 0) are used.
+ Event wakeEvent = new Event();
+ wakeEvent.type = SWT.MouseMove;
+ getTree().getDisplay().post(wakeEvent);
+
+ waitForDisplayUpdate();
+
+ // drop
+ gdSelectByIndices(pathType, preAscend, indexPath, 0, 1,
+ CompSystemConstants.EXTEND_SELECTION_NO);
+
+ SwtUtils.waitForDisplayIdle(getTree().getDisplay());
+ waitBeforeDrop(delayBeforeDrop);
+ } finally {
+ robot.mouseRelease(null, null, dndHelper.getMouseButton());
+ pressOrReleaseModifiers(dndHelper.getModifier(),
+ false);
+ SwtUtils.waitForDisplayIdle(getTree().getDisplay());
+ }
+ }
+ /**
+ * {@inheritDoc}
+ */
+ protected Object getNodeAtMousePosition() throws StepExecutionException {
+ return (TreeItem)getEventThreadQueuer().invokeAndWait("getItemAtMousePosition", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ Point mousePos = SwtUtils.convertToSwtPoint(
+ getRobot().getCurrentMousePosition());
+ ItemAtPointTreeNodeOperation op =
+ new ItemAtPointTreeNodeOperation(
+ mousePos, SwtUtils.getWidgetBounds(getTree()));
+
+ TreeItem topItem = getTree().getTopItem();
+ if (topItem != null) {
+
+ // FIXME zeb This may be slow for very large trees, as the
+ // search may continue long past the
+ // visible client area of the tree.
+ // It may also cause problems with regard to
+ // lazy/virtual nodes.
+ StandardDepthFirstTraverser traverser =
+ new StandardDepthFirstTraverser(
+ new TreeOperationContext(
+ getEventThreadQueuer(), getRobot(), getTree()));
+ traverser.traversePath(op, topItem);
+ if (op.getItemAtPoint() != null) {
+ return op.getItemAtPoint();
+ }
+
+ }
+
+ throw new StepExecutionException("No tree node found at mouse position.", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.NOT_FOUND));
+ }
+ });
+ }
+
+ /**
+ * @return the column where the mouse pointer currently rests. Returns -1 if
+ * the mouse pointer is currently outside of the TableTree or if the
+ * TableTree has no columns.
+ */
+ private int getMouseColumn() {
+ final Tree treeTable = getTree();
+ int column = ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getMouseColumn", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ Rectangle treeTableBounds =
+ SwtUtils.getWidgetBounds(getTree());
+ Point cursorPosition =
+ treeTable.getDisplay().getCursorLocation();
+ boolean isCursorInBounds =
+ treeTableBounds.contains(cursorPosition);
+ if (isCursorInBounds) {
+ int horizontalScrollOffset = 0;
+ ScrollBar horizontalBar =
+ getTree().getHorizontalBar();
+ if (horizontalBar != null
+ && !horizontalBar.isDisposed()) {
+ horizontalScrollOffset =
+ horizontalBar.getSelection();
+ }
+ Rectangle columnBounds = new Rectangle(
+ treeTableBounds.x - horizontalScrollOffset,
+ treeTableBounds.y, 0, treeTableBounds.height);
+ for (int i = 0;
+ i < treeTable.getColumnCount(); i++) {
+
+ columnBounds.x += columnBounds.width;
+ columnBounds.width =
+ treeTable.getColumn(i).getWidth();
+ if (columnBounds.contains(cursorPosition)) {
+ return new Integer(i);
+ }
+ }
+ }
+
+ return new Integer(-1);
+ }
+
+ })).intValue();
+
+ return column;
+ }
+ //
+ // Methods for Table Trees following
+ //
+
+ /**
+ * Selects a node relative to the currently selected node.
+ * @param direction the direction to move.
+ * directions:
+ * UP - Navigates through parents
+ * DOWN - Navigates through children
+ * NEXT - Navigates to next sibling
+ * PREVIOUS - Navigates to previous sibling
+ * @param distance the distance to move
+ * @param clickCount the click count to select the new cell.
+ * @throws StepExecutionException if any error occurs
+ */
+ public void gdMove(String direction, int distance, int clickCount)
+ throws StepExecutionException {
+
+ if (getColumnCount() > 0) {
+ TreeOperationContext context;
+ int mouseColumn = getMouseColumn();
+
+ if (mouseColumn == -1) {
+ context =
+ new TableTreeOperationContext(
+ getEventThreadQueuer(), getRobot(), getTree());
+ } else {
+ context =
+ new TableTreeOperationContext(
+ getEventThreadQueuer(), getRobot(), getTree(),
+ mouseColumn);
+ }
+
+ TreeItem selectedNode = (TreeItem) getSelectedNode(context);
+
+ TreeNodeOperation selectOp =
+ new SelectTreeNodeOperation(
+ ClickOptions.create().setClickCount(clickCount));
+ TreeNodeOperationConstraint constraint =
+ new TreeNodeOperationConstraint();
+
+ if (CompSystemConstants
+ .TREE_MOVE_UP.equalsIgnoreCase(direction)) {
+ AbstractTreeNodeTraverser traverser =
+ new ParentTraverser(context, distance, constraint);
+ traverser.traversePath(selectOp, selectedNode);
+ } else if (CompSystemConstants
+ .TREE_MOVE_DOWN.equalsIgnoreCase(direction)) {
+ TreeNodeOperation expandOp =
+ new ExpandCollapseTreeNodeOperation(false);
+ AbstractTreeNodeTraverser expandTraverser =
+ new ChildTraverser(context, distance - 1);
+ expandTraverser.traversePath(expandOp, selectedNode);
+
+ AbstractTreeNodeTraverser selectTraverser =
+ new ChildTraverser(context, distance, constraint);
+ selectTraverser.traversePath(selectOp, selectedNode);
+
+ } else if (CompSystemConstants
+ .TREE_MOVE_NEXT.equalsIgnoreCase(direction)) {
+ // Look through siblings
+ AbstractTreeNodeTraverser traverser =
+ new SiblingTraverser(context, distance, true, constraint);
+ traverser.traversePath(selectOp, selectedNode);
+
+ } else if (CompSystemConstants
+ .TREE_MOVE_PREVIOUS.equalsIgnoreCase(direction)) {
+ // Look through siblings
+ AbstractTreeNodeTraverser traverser =
+ new SiblingTraverser(context, distance, false, constraint);
+ traverser.traversePath(selectOp, selectedNode);
+ }
+ } else {
+ super.gdMove(direction, distance, clickCount);
+ }
+ }
+
+ /**
+ * Runs in the GUI thread.
+ * @return the number of columns in the receivers component.
+ */
+ private int getColumnCount() {
+ return ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getColumnCount", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ return new Integer(getTree().getColumnCount());
+ }
+
+ })).intValue();
+ }
+
+ /**
+ * Selects the item at the end of the <code>treepath</code> at column
+ * <code>column</code>.
+ *
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param treePath The tree path.
+ * @param operator
+ * If regular expressions are used to match the tree path
+ * @param clickCount the click count
+ * @param column the column of the item to select
+ * @param button what mouse button should be used
+ * @throws StepExecutionException If the tree path is invalid, if the
+ * double-click to expand the node fails, or if the selection is invalid.
+ */
+ public void gdSelect(String pathType, int preAscend, String treePath,
+ String operator, int clickCount, int column,
+ int button)
+ throws StepExecutionException {
+ final int implCol = IndexConverter.toImplementationIndex(column);
+ checkColumnIndex(implCol);
+
+ selectByPath(pathType, preAscend,
+ createStringNodePath(splitTextTreePath(treePath), operator),
+ ClickOptions.create()
+ .setClickCount(clickCount)
+ .setMouseButton(button), implCol);
+
+ }
+ /**
+ * Selects the last node of the path given by <code>indexPath</code>
+ * at column <code>column</code>.
+ *
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param indexPath the index path
+ * @param clickCount the number of times to click
+ * @param column the column of the item to select
+ * @param button what mouse button should be used
+ * @throws StepExecutionException if <code>indexPath</code> is not a valid
+ * path
+ */
+ public void gdSelectByIndices(String pathType, int preAscend,
+ String indexPath, int clickCount, int column,
+ int button)
+ throws StepExecutionException {
+ final int implCol = IndexConverter.toImplementationIndex(column);
+ checkColumnIndex(implCol);
+
+ selectByPath(pathType, preAscend,
+ createIndexNodePath(splitIndexTreePath(indexPath)),
+ ClickOptions.create()
+ .setClickCount(clickCount)
+ .setMouseButton(button), implCol);
+ }
+
+ /**
+ * Verifies whether the first selection in the tree has a rendered text at
+ * column <code>column</code> that is equal to <code>pattern</code>.
+ *
+ * @param pattern The pattern
+ * @param column
+ * The column containing the text to verify
+ * @throws StepExecutionException If no node is selected or the verification fails.
+ */
+ public void gdVerifySelectedValue(String pattern, int column)
+ throws StepExecutionException {
+
+ gdVerifySelectedValue(pattern, MatchUtil.DEFAULT_OPERATOR, column);
+ }
+ /**
+ * Verifies if the selected node underneath <code>treePath</code> at column
+ * <code>column</code> has a rendered text which is equal to
+ * <code>selection</code>.
+ *
+ * @param pattern the pattern
+ * @param operator
+ * The operator to use when comparing the expected and
+ * actual values.
+ * @param column
+ * The column containing the text to verify
+ * @throws StepExecutionException If there is no tree node selected, the tree path contains no
+ * selection or the verification fails
+ */
+ public void gdVerifySelectedValue(String pattern, String operator,
+ int column) throws StepExecutionException {
+
+ final int implCol = IndexConverter.toImplementationIndex(column);
+ checkColumnIndex(implCol);
+
+ TableTreeOperationContext context = new TableTreeOperationContext(
+ getEventThreadQueuer(), getRobot(), getTree(), implCol);
+
+ String text = context.getNodeTextAtColumn(context.getSelectedNode());
+
+ Verifier.match(text, pattern, operator);
+
+ }
+
+ /**
+ *
+ * @param index The 0-based column index to check.
+ * @throws StepExecutionException if the column index is invalid.
+ */
+ private void checkColumnIndex(final int index)
+ throws StepExecutionException {
+
+ int numColumns = ((Integer)getEventThreadQueuer().invokeAndWait(
+ "checkColumnIndex", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() {
+ return new Integer(getTree().getColumnCount());
+ }
+
+ })).intValue();
+
+ if ((index < 0 || index >= numColumns) && index != 0) {
+ throw new StepExecutionException("Invalid column: " //$NON-NLS-1$
+ + IndexConverter.toUserIndex(index),
+ EventFactory.createActionError(
+ TestErrorEvent.INVALID_INDEX));
+ }
+ }
+
+ /**
+ * @param pathType pathType
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param objectPath objectPath
+ * @param co the click options to use
+ * @param column the column
+ */
+ private void selectByPath(String pathType, int preAscend,
+ INodePath objectPath, ClickOptions co, int column) {
+
+ TreeNodeOperation expOp =
+ new ExpandCollapseTreeNodeOperation(false);
+ TreeNodeOperation selectOp =
+ new SelectTreeNodeOperation(co);
+ INodePath subPath = objectPath.subPath(0, objectPath.getLength() - 1);
+
+ traverseTreeByPath(subPath, pathType, preAscend, expOp);
+ traverseLastElementByPath(
+ objectPath, pathType, preAscend, selectOp, column);
+
+ }
+
+ /**
+ * Traverses the tree by searching for the nodes in the tree
+ * path entry and calling the given operation on the last element in the path.
+ * @param treePath The tree path.
+ * @param pathType For example, "relative" or "absolute".
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param operation The tree node operation.
+ * @param column The target column for the operation.
+ * @throws StepExecutionException If the path traversion fails.
+ */
+ private void traverseLastElementByPath(INodePath treePath,
+ String pathType, int preAscend, TreeNodeOperation operation,
+ int column)
+ throws StepExecutionException {
+
+ Validate.notNull(treePath);
+ Validate.notNull(operation);
+
+ TableTreeOperationContext context = new TableTreeOperationContext(
+ getEventThreadQueuer(), getRobot(), getTree(), column);
+ TreeItem startNode = (TreeItem) getStartNode(pathType,
+ preAscend, context);
+
+ AbstractTreeNodeTraverser traverser = new PathBasedTraverser(
+ context, treePath, new TreeNodeOperationConstraint());
+ traverser.traversePath(operation, startNode);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String gdStoreValueAtMousePosition(String variable) {
+ TreeItem itemAtMousePosition = (TreeItem) getNodeAtMousePosition();
+ int column = getMouseColumn();
+ AbstractTreeOperationContext context;
+
+ if (column != -1) {
+ context =
+ new TableTreeOperationContext(
+ getEventThreadQueuer(), getRobot(), getTree(), column);
+ } else {
+ context =
+ new TableTreeOperationContext(
+ getEventThreadQueuer(), getRobot(), getTree());
+ }
+
+ return context.getRenderedText(itemAtMousePosition);
+ }
+
+ /**
+ * Selects Checkbox of last node of the path given by <code>treepath</code>.
+ *
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param treePath The tree path.
+ * @param operator
+ * If regular expressions are used to match the tree path
+ * @throws StepExecutionException If the tree path is invalid, if the
+ * double-click to expand the node fails, or if the selection is invalid.
+ */
+ public void gdToggleCheckbox(String pathType, int preAscend, String
+ treePath, String operator)
+ throws StepExecutionException {
+ toggleCheckBoxByPath(pathType, preAscend,
+ createStringNodePath(splitTextTreePath(treePath), operator));
+ }
+
+ /**
+ * Selects Checkbox of last node of the path given by <code>indexPath</code>
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param indexPath the index path
+ * @throws StepExecutionException if <code>indexPath</code> is not a valid
+ * path
+ */
+ public void gdToggleCheckboxByIndices(String pathType, int preAscend,
+ String indexPath)
+ throws StepExecutionException {
+
+ toggleCheckBoxByPath(pathType, preAscend,
+ createIndexNodePath(splitIndexTreePath(indexPath)));
+ }
+
+ /**
+ * Verify Selection of checkbox of the node at the end of the <code>treepath</code>.
+ *
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param treePath The tree path.
+ * @param operator
+ * If regular expressions are used to match the tree path
+ * @param checked true if checkbox of tree node is selected, false otherwise
+ * @throws StepExecutionException If the tree path is invalid, if the
+ * double-click to expand the node fails, or if the selection is invalid.
+ */
+ public void gdVerifyCheckbox(String pathType, int preAscend, String
+ treePath, String operator, boolean checked)
+ throws StepExecutionException {
+ verifyCheckBoxByPath(pathType, preAscend,
+ createStringNodePath(splitTextTreePath(treePath), operator),
+ checked);
+ }
+
+ /**
+ * Verify Selection of checkbox of last node of the path given by <code>indexPath</code>
+ * @param pathType whether the path is relative or absolute
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param indexPath the index path
+ * @param checked true if checkbox of tree node is selected, false otherwise
+ * @throws StepExecutionException if <code>indexPath</code> is not a valid
+ * path
+ */
+ public void gdVerifyCheckboxByIndices(String pathType, int preAscend,
+ String indexPath, boolean checked)
+ throws StepExecutionException {
+
+ verifyCheckBoxByPath(pathType, preAscend,
+ createIndexNodePath(splitIndexTreePath(indexPath)),
+ checked);
+ }
+
+ /**
+ * Verifies whether the checkbox of the first selection in the tree is checked
+ *
+ * @param checked true if checkbox of node is selected, false otherwise
+ * @throws StepExecutionException If no node is selected or the verification fails.
+ */
+ public void gdVerifySelectedCheckbox(boolean checked)
+ throws StepExecutionException {
+ Boolean checkSelected = ((Boolean)getEventThreadQueuer().invokeAndWait(
+ "gdVerifyTreeCheckbox", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ TreeItem node = getTree().getSelection()[0];
+ return new Boolean(node.getChecked());
+ }
+ }));
+
+ Verifier.equals(checked, checkSelected.booleanValue());
+ }
+
+ /**
+ * @param pathType pathType
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param objectPath objectPath
+ * @param checked true if Checkbox should be enabled, false otherwise
+ */
+ private void verifyCheckBoxByPath(String pathType, int preAscend,
+ INodePath objectPath, final boolean checked) {
+
+ TreeNodeOperation expOp =
+ new ExpandCollapseTreeNodeOperation(false);
+ TreeOperationContext context = new TreeOperationContext(
+ getEventThreadQueuer(), getRobot(), getTree());
+ TreeNodeOperation checkboxOp = new VerifyCheckboxOperation(
+ checked, context);
+ INodePath subPath = objectPath.subPath(0, objectPath.getLength() - 1);
+
+ traverseTreeByPath(subPath, pathType, preAscend, expOp);
+ traverseLastElementByPath(objectPath, pathType, preAscend, checkboxOp);
+ }
+
+ /**
+ * @param pathType pathType
+ * @param preAscend
+ * Relative traversals will start this many parent nodes
+ * above the current node. Absolute traversals ignore this
+ * parameter.
+ * @param objectPath objectPath
+ */
+ private void toggleCheckBoxByPath(String pathType, int preAscend,
+ INodePath objectPath) {
+
+ TreeNodeOperation expOp =
+ new ExpandCollapseTreeNodeOperation(false);
+ TreeOperationContext context = new TreeOperationContext(
+ getEventThreadQueuer(), getRobot(), getTree());
+ TreeNodeOperation selCheckboxOp = new ToggleCheckboxOperation(context);
+ INodePath subPath = objectPath.subPath(0, objectPath.getLength() - 1);
+
+ traverseTreeByPath(subPath, pathType, preAscend, expOp);
+ traverseLastElementByPath(objectPath, pathType, preAscend,
+ selCheckboxOp);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdClick(int count, int button) {
+ super.gdClick(count, button);
+
+ }
+
+
+
+ /**
+ * Forces all outstanding paint requests for the receiver's component's
+ * display to be processed before this method returns.
+ *
+ * @see Display#update()
+ */
+ protected void waitForDisplayUpdate() {
+ ((Control)getComponent().getRealComponent())
+ .getDisplay().syncExec(new Runnable() {
+ public void run() {
+ ((Control)getComponent()
+ .getRealComponent()).getDisplay().update();
+ }
+ });
+ }
+
+ /**
+ * Presses or releases the given modifier.
+ * @param modifier the modifier.
+ * @param press if true, the modifier will be pressed.
+ * if false, the modifier will be released.
+ */
+ public void pressOrReleaseModifiers(String modifier, boolean press) {
+ final IRobot robot = getRobot();
+ final StringTokenizer modTok = new StringTokenizer(
+ KeyStrokeUtil.getModifierString(modifier), " "); //$NON-NLS-1$
+ while (modTok.hasMoreTokens()) {
+ final String mod = modTok.nextToken();
+ final int keyCode = KeyCodeConverter.getKeyCode(mod);
+ if (press) {
+ robot.keyPress(null, keyCode);
+ } else {
+ robot.keyRelease(null, keyCode);
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/AbstractComboBoxAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/AbstractComboBoxAdapter.java
new file mode 100644
index 000000000..9ca0e579b
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/AbstractComboBoxAdapter.java
@@ -0,0 +1,318 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.lang.Validate;
+import org.eclipse.jubula.rc.common.CompSystemConstants;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.logger.AutServerLogger;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComboBoxAdapter;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Widget;
+/**
+ * Implementation of the Interface <code>IComboBoxAdapter</code> as a abstract
+ * adapter for the swt comboboxes.
+ * This class needs specific methods of its subclasses therefore it is abstract.
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public abstract class AbstractComboBoxAdapter extends WidgetAdapter
+ implements IComboBoxAdapter {
+
+ /** number of clicks to give focus without selecting any text */
+ public static final int CLICK_COUNT_FOR_SELECTING_NONE = 3;
+
+ /** the logger */
+ private static AutServerLogger log = new AutServerLogger(
+ AbstractComboBoxAdapter.class);
+
+ /**
+ *
+ * @param objectToAdapt
+ */
+ protected AbstractComboBoxAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void select(final String[] values, String operator,
+ final String searchType)
+ throws StepExecutionException, IllegalArgumentException {
+
+ for (int i = 0; i < values.length; i++) {
+ String text = values[i];
+ Validate.notNull(text, "text must not be null"); //$NON-NLS-1$
+ }
+
+ Integer[] indices = findIndicesOfValues(values,
+ operator, searchType);
+ Arrays.sort(indices);
+ if (indices.length == 0) {
+ throw new StepExecutionException("Text '" + Arrays.asList(values).toString() //$NON-NLS-1$
+ + "' not found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+ select(indices[0].intValue());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void select(int index) {
+
+ int comboItemCount = getItemCount();
+
+ if (index >= comboItemCount
+ || index < 0) {
+ throw new StepExecutionException("Combo Box index '" + index //$NON-NLS-1$
+ + "' is out of range", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.INVALID_INDEX));
+ }
+
+ if (isComboEnabled()) {
+ // FIXME zeb: Needs special handling if style is not DROP_DOWN
+ openDropdownList();
+ selectImpl(index);
+ }
+ }
+
+ /**
+ * @return <code>true</code> if the combo box is currently enabled.
+ */
+ protected abstract boolean isComboEnabled();
+
+ /**
+ *
+ * @param index idx
+ */
+ protected abstract void selectImpl(int index);
+
+ /**
+ * Opens the combobox dropdown list. May also be
+ * called if the list is already visible.
+ */
+ protected abstract void openDropdownList();
+
+ /**
+ * Finds the indices of the list elements that are rendered with the passed
+ * values.
+ *
+ * @param values
+ * The values
+ * @param operator
+ * operator to use
+ * @param searchType
+ * Determines where the search begins ("relative" or "absolute")
+ * @return The array of indices. It's length is equal to the length of the
+ * values array, but may contains <code>null</code> elements for
+ * all values that are not found in the list
+ */
+ private Integer[] findIndicesOfValues(final String [] values,
+ final String operator, final String searchType) {
+
+ final Set indexSet = new HashSet();
+
+ for (int i = getStartingIndex(searchType);
+ i < getItemCount();
+ ++i) {
+
+ String str = getItem(i);
+ if (MatchUtil.getInstance().
+ match(str, values, operator)) {
+ indexSet.add(new Integer(i));
+ }
+ }
+
+
+ Integer[] indices = new Integer[indexSet.size()];
+ indexSet.toArray(indices);
+ return indices;
+
+ }
+
+ /**
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @return The index from which to begin a search, based on the search type
+ * and (if appropriate) the currently selected item.
+ */
+ private int getStartingIndex(final String searchType) {
+ int startingIndex = 0;
+ if (searchType.equalsIgnoreCase(
+ CompSystemConstants.SEARCH_TYPE_RELATIVE)) {
+ startingIndex = getSelectedIndex();
+ }
+ return startingIndex;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean containsValue(String value, String operator) {
+ Integer[] indices = null;
+ if (operator.equals(MatchUtil.NOT_EQUALS)) {
+ indices = findIndicesOfValues(new String[] { value },
+ MatchUtil.EQUALS, CompSystemConstants.SEARCH_TYPE_ABSOLUTE);
+ return indices.length == 0;
+ }
+ indices = findIndicesOfValues(new String[] { value },
+ operator, CompSystemConstants.SEARCH_TYPE_ABSOLUTE);
+ return indices.length > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean containsValue(String value) {
+ return containsValue(value, MatchUtil.EQUALS);
+ }
+
+ /**
+ * Returns the number of items contained in the combo list.
+ * @return the number of items.
+ */
+ protected abstract int getItemCount();
+
+ /**
+ * Returns the item at the given, zero-relative index in the combo list.
+ * Throws an exception if the index is out of range.
+ * @param index the index of the item to return
+ * @return the item at the given index
+ */
+ protected abstract String getItem(final int index);
+
+ /**
+ * {@inheritDoc}
+ */
+ public void input(String text, boolean replace)
+ throws StepExecutionException, IllegalArgumentException {
+
+ Validate.notNull(text, "text must not be null"); //$NON-NLS-1$
+ Control editor = (Control) getRealComponent();
+ if (editor == null) {
+ throw new StepExecutionException("could not find editor", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
+ }
+ if (replace) {
+ selectAll();
+ } else {
+ selectNone();
+ }
+ getRobot().type(editor, text);
+ getRobot().keyType(null, SWT.KEYPAD_CR);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void click(Integer count) {
+ Control editor = (Control) getRealComponent();
+ if (editor == null) {
+ throw new StepExecutionException("no editor found", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
+ }
+ getRobot().click(editor, null, ClickOptions.create().setClickCount(
+ count.intValue()));
+ }
+
+ /**
+ * Give the text field focus without selecting any of the text.
+ */
+ public void selectNone() {
+ // FIXME zeb: This places the caret at the center of the component,
+ // which may or may not be correct. Where should the text
+ // be inserted?
+ click(new Integer(
+ CLICK_COUNT_FOR_SELECTING_NONE));
+ }
+ /**
+ * Toggles the combobox dropdown list by clicking on the combo box.
+ */
+ protected void toggleDropdownList() {
+
+ // Click in the center of the pulldown button
+ Rectangle r = findArrowIconArea();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Toggling dropdown by clicking on rectangle: " + r //$NON-NLS-1$
+ + "within component: " + getRealComponent()); //$NON-NLS-1$
+ }
+
+ getRobot().click(getRealComponent(), r,
+ ClickOptions.create().setScrollToVisible(false)
+ .setConfirmClick(false));
+
+ }
+
+ /**
+ * @return a rectangle, where the arrow icon is expected, relative to the
+ * combo box's location.
+ */
+ protected Rectangle findArrowIconArea() {
+ final Control editor = (Control) getRealComponent();
+ Rectangle r = null;
+ if (editor == null) {
+ throw new StepExecutionException("could not find editor", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
+ }
+
+ r = (Rectangle)getEventThreadQueuer().invokeAndWait(
+ AbstractComboBoxAdapter.class.getName()
+ + "findArrowIconArea", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return SwtUtils.getRelativeWidgetBounds(editor, editor);
+ }
+ });
+
+ // Assume that the arrow icon is approximately square
+ r.x += r.width - r.height;
+ r.width = r.height;
+
+ return r;
+ }
+
+ /**
+ * @return true, if combo is not read_only
+ */
+ private boolean isComboEditable() {
+
+ Integer comboStyle = (Integer)getEventThreadQueuer().invokeAndWait(
+ AbstractComboBoxAdapter.class.getName()
+ + "isComboEditable", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return new Integer(((Widget)getRealComponent()).getStyle());
+ }
+ });
+
+ return ((comboStyle.intValue() & SWT.READ_ONLY) == 0);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEditable() {
+ return isComboEditable();
+ }
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/AbstractComponentAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/AbstractComponentAdapter.java
new file mode 100644
index 000000000..1fce2950e
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/AbstractComponentAdapter.java
@@ -0,0 +1,29 @@
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IRobotFactory;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
+import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
+/**
+ *
+ * @author BREDEX GmBH
+ *
+ */
+public abstract class AbstractComponentAdapter implements IComponentAdapter {
+
+ /** the RobotFactory from the AUT */
+ private IRobotFactory m_robotFactory;
+
+
+ /**
+ * Gets the Robot factory. The factory is created once per instance.
+ *
+ * @return The Robot factory.
+ */
+ public IRobotFactory getRobotFactory() {
+ if (m_robotFactory == null) {
+ m_robotFactory = new RobotFactoryConfig().getRobotFactory();
+ }
+ return m_robotFactory;
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ButtonAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ButtonAdapter.java
new file mode 100644
index 000000000..5d9f7effe
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ButtonAdapter.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IButtonAdapter;
+import org.eclipse.swt.widgets.Button;
+/**
+ * Implements the Button interface for adapting a <code>SWT.Button</code>
+ *
+ * @author BREDEX GmbH
+ */
+public class ButtonAdapter extends WidgetAdapter implements IButtonAdapter {
+
+ /** the Button from the AUT */
+ private Button m_button;
+
+ /**
+ *
+ * @param objectToAdapt graphics component which will be adapted
+ */
+ public ButtonAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_button = (Button) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+
+ return (String)getEventThreadQueuer()
+ .invokeAndWait("getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_button.getText(); // see findBugs;
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSelected() {
+ Boolean actual = (Boolean)getEventThreadQueuer()
+ .invokeAndWait("isSelected", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_button.getSelection()
+ ? Boolean.TRUE : Boolean.FALSE; // see findBugs;
+ }
+ });
+ return actual.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ */
+ public String readValue(String variable) {
+
+ return getText();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CComboAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CComboAdapter.java
new file mode 100644
index 000000000..5ce6513ea
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CComboAdapter.java
@@ -0,0 +1,355 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.driver.RobotTiming;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.logger.AutServerLogger;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.jubula.tools.constants.TimeoutConstants;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Shell;
+/**
+ * Implementation of the Interface <code>IComboBoxAdapter</code> as a
+ * adapter for the <code>CCombo</code> component.
+ * This class is sub classing <code>AbstractComboBoxAdapter</code> because
+ * <code>Combo</code> and <code>CCombo</code> have common parts
+ * @author BREDEX GmbH
+ *
+ */
+public class CComboAdapter extends AbstractComboBoxAdapter {
+
+ /** the logger */
+ private static AutServerLogger log = new AutServerLogger(
+ CComboAdapter.class);
+
+ /** */
+ private CCombo m_combobox;
+
+ /**
+ *
+ * @param objectToAdapt
+ */
+ public CComboAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_combobox = (CCombo) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void selectAll() {
+
+ // Get focus
+ selectNone();
+
+ // FIXME zeb: Find a platform-independant way to select all text
+ // without calling CCombo methods directly.
+ // The current problem with clicking twice in the text area
+ // is that if there is any white space, only part of the
+ // text is selected.
+ getEventThreadQueuer().invokeAndWait("selectAll", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+ m_combobox.setSelection(
+ new Point(0, m_combobox.getText().length()));
+
+ // return value is not used
+ return null;
+ }
+
+ });
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getSelectedIndex() {
+ int selectedIndex = ((Integer)getEventThreadQueuer().invokeAndWait(
+ CComboAdapter.class.getName()
+ + "getSelectedIndex", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return new Integer(m_combobox.getSelectionIndex());
+ }
+ })).intValue();
+
+ return selectedIndex;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ Object o = getEventThreadQueuer().invokeAndWait(
+ "getSelectedItem", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_combobox.getText();
+ }
+ });
+ return o != null ? o.toString() : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected boolean isComboEnabled() {
+ boolean isEnabled = ((Boolean)getEventThreadQueuer().invokeAndWait(
+ CComboAdapter.class.getName()
+ + "isComboEnabled", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return m_combobox.isEnabled()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ })).booleanValue();
+
+ return isEnabled;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void selectImpl(final int index) {
+ scrollIndexToVisible(index);
+
+ Rectangle clickConstraints =
+ (Rectangle)getEventThreadQueuer().invokeAndWait(
+ "setClickConstraints", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+ Rectangle constraints =
+ SwtUtils.getRelativeWidgetBounds(
+ getDropdownList(), getDropdownList());
+ int displayedItemCount = getDisplayedItemCount();
+ int numberBelowTop = 0;
+ if (displayedItemCount >= getItemCount()) {
+ numberBelowTop = index;
+ } else {
+ numberBelowTop = Math.max(0, index
+ - getItemCount() + displayedItemCount);
+ }
+
+ // Set the constraints based on the numberBelowTop
+ constraints.height = getDropdownList().getItemHeight();
+ constraints.y += (numberBelowTop * constraints.height);
+
+ return constraints;
+ }
+
+ });
+
+ // Note that we set scrollToVisible false because we have already done
+ // the scrolling.
+ getRobot().click(getDropdownList(), clickConstraints,
+ new ClickOptions().setScrollToVisible(false));
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void openDropdownList() {
+ if (!isDropdownVisible()) {
+ toggleDropdownList();
+ }
+
+ long timeout = TimeoutConstants.SERVER_TIMEOUT_WAIT_FOR_POPUP;
+ long done = System.currentTimeMillis() + timeout;
+ long now;
+ while (!isDropdownVisible() && timeout >= 0) {
+ RobotTiming.sleepPreShowPopupDelay();
+ now = System.currentTimeMillis();
+ timeout = done - now;
+ }
+
+ if (!isDropdownVisible()) {
+ log.debug("Dropdown list still not visible, must be an error"); //$NON-NLS-1$
+ throw new StepExecutionException("dropdown list not visible", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.DROPDOWN_LIST_NOT_FOUND));
+ }
+
+ }
+
+ /**
+ * Returns the number of items contained in the combo list.
+ * @return the number of items.
+ */
+ protected int getItemCount() {
+ return ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getItemCount", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() {
+
+ return new Integer(m_combobox.getItemCount());
+ }
+
+ })).intValue();
+
+ }
+
+ /**
+ * Returns the item at the given, zero-relative index in the combo list.
+ * Throws an exception if the index is out of range.
+ * @param index the index of the item to return
+ * @return the item at the given index
+ */
+ protected String getItem(final int index) {
+ return (String)getEventThreadQueuer().invokeAndWait(
+ "getItem", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() {
+
+ return m_combobox.getItem(index);
+ }
+
+ });
+
+ }
+
+ /**
+ * Tries to find the dropdown list from the combobox
+ * @return the dropdown of the combobox, or <code>null</code> if the
+ * dropdown could not be found
+ */
+ protected List getDropdownList()
+ throws StepExecutionException {
+
+ return (List)getEventThreadQueuer().invokeAndWait(
+ "getDropdownList", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+
+ Shell mainShell = SwtUtils.getShell(m_combobox);
+ Display d = Display.getCurrent();
+ Shell [] shells = d.getShells();
+ for (int i = 0; i < shells.length; i++) {
+ Shell curShell = shells[i];
+ if (mainShell == curShell.getParent()
+ && curShell.getChildren().length == 1
+ && curShell.getChildren()[0] instanceof List) {
+
+ List possibleDropdown =
+ (List)curShell.getChildren()[0];
+ if (!possibleDropdown.isDisposed()
+ && possibleDropdown.isVisible()
+ && isDropdownList(possibleDropdown)) {
+ return possibleDropdown;
+ }
+ }
+ }
+
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Verifies that the given list is the dropdown list for this combo box.
+ *
+ * @param list The list to verify.
+ * @return <code>true</code> if <code>list</code> is the dropdown list for
+ * this combo box. Otherwise <code>false</code>.
+ */
+ private boolean isDropdownList(List list) {
+ /*
+ * Verify that the list is close enough to the combo box.
+ */
+
+ Rectangle comboBounds =
+ SwtUtils.getWidgetBounds(m_combobox);
+ Rectangle listBounds = SwtUtils.getWidgetBounds(list);
+
+ // Expand the bounding rectangle for the combo box by a small amount
+ int posFuzz = 5;
+ int dimFuzz = posFuzz * 2;
+ comboBounds.x -= posFuzz;
+ comboBounds.width += dimFuzz;
+ comboBounds.y -= posFuzz;
+ comboBounds.height += dimFuzz;
+
+ return comboBounds.intersects(listBounds);
+ }
+
+ /**
+ * Tries to set the given index as the top element of the CCombo.
+ * @param index The index to make visible
+ */
+ private void scrollIndexToVisible(final int index) {
+ getEventThreadQueuer().invokeAndWait(
+ "scrollIndexToVisible", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+
+ getDropdownList().setTopIndex(index);
+
+ return null;
+ }
+
+ });
+ }
+
+ /**
+ *
+ * @return the number of items displayed in the dropdown list, or 0 if
+ * the list is not showing.
+ */
+ private int getDisplayedItemCount() {
+ return ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getDisplayedItemCount", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+ List dropdown = getDropdownList();
+ if (dropdown == null) {
+ return new Integer(0);
+ }
+ int listHeight = SwtUtils.getWidgetBounds(dropdown).height;
+ int itemHeight = dropdown.getItemHeight();
+
+ return new Integer(listHeight / itemHeight);
+ }
+
+ })).intValue();
+ }
+
+ /**
+ * @return true, if the dropdown of the combobox is visible
+ */
+ protected boolean isDropdownVisible() {
+ Boolean visible = (Boolean)getEventThreadQueuer().invokeAndWait(
+ CComboAdapter.class.getName()
+ + "isDropdownVisible", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ List dropdownList = getDropdownList();
+ return dropdownList != null
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return visible.booleanValue();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CLabelAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CLabelAdapter.java
new file mode 100644
index 000000000..df9d482a1
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CLabelAdapter.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITextVerifiable;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.swt.custom.CLabel;
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class CLabelAdapter extends WidgetAdapter implements ITextVerifiable {
+
+ /**
+ *
+ * @param objectToAdapt the component to adapt
+ */
+ public CLabelAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ final CLabel label = (CLabel) getRealComponent();
+ return (String)getEventThreadQueuer().invokeAndWait(
+ "getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ try {
+ return SwtUtils.removeMnemonics(label.getText());
+ } catch (NullPointerException e) {
+ throw new StepExecutionException(
+ "component must not be null", //$NON-NLS-1$
+ EventFactory
+ .createComponentNotFoundErrorEvent());
+ }
+ }
+ });
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CTabFolderAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CTabFolderAdapter.java
new file mode 100644
index 000000000..e07fb17d6
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CTabFolderAdapter.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.logger.AutServerLogger;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITabPaneAdapter;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.widgets.Control;
+/**
+ * Implementation of the Interface <code>ITabPane</code> as a
+ * adapter for the <code>CTabFolder</code> component.
+ * @author BREDEX GmbH
+ *
+ */
+public class CTabFolderAdapter extends WidgetAdapter
+ implements ITabPaneAdapter {
+
+ /** the logger */
+ private static AutServerLogger log =
+ new AutServerLogger(CTabFolderAdapter.class);
+
+ /** the CTabFolder from the AUT */
+ private CTabFolder m_ctabFolder;
+
+ /**
+ *
+ * @param objectToAdapt the component from the AUT
+ */
+ public CTabFolderAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_ctabFolder = (CTabFolder) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getTabCount() {
+ return ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getSelectedIndex", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+ return new Integer(m_ctabFolder.getItemCount());
+ }
+ })).intValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getTitleofTab(final int index) {
+ return (String)getEventThreadQueuer().invokeAndWait(
+ "verifyTextOfTabByIndex", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ return m_ctabFolder.getItem(index).getText();
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getBoundsAt(final int index) {
+ return getEventThreadQueuer().invokeAndWait("getBoundsAt", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ return SwtUtils.getRelativeWidgetBounds(
+ m_ctabFolder.getItem(index), m_ctabFolder);
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnabledAt(final int index) {
+ return ((Boolean) getEventThreadQueuer().invokeAndWait("isEnabledAt", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ Control control = m_ctabFolder.getItem(index).getControl();
+ if (control == null) {
+ // FIXME zeb: Strange workaround for CTabFolders,
+ // which somehow never seem to have an associated
+ // Control.
+ log.debug(this + ".getControl() returned null."); //$NON-NLS-1$
+ return Boolean.TRUE;
+ }
+
+ return control.isEnabled() ? Boolean.TRUE : Boolean.FALSE;
+
+ }
+ })).booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getSelectedIndex() {
+ return ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getSelectedIndex", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+ return new Integer(m_ctabFolder.getSelectionIndex());
+ }
+ })).intValue();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ComboAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ComboAdapter.java
new file mode 100644
index 000000000..484ea7ad9
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ComboAdapter.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.tools.utils.EnvironmentUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Event;
+/**
+ * Implementation of the Interface <code>IComboBoxAdapter</code> as a
+ * adapter for the <code>Combo</code> component.
+ * This class is sub classing <code>AbstractComboBoxAdapter</code> because
+ * <code>Combo</code> and <code>CCombo</code> have common parts
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class ComboAdapter extends AbstractComboBoxAdapter {
+
+ /** */
+ private Combo m_combobox;
+
+ /**
+ *
+ * @param objectToAdapt
+ */
+ public ComboAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_combobox = (Combo) objectToAdapt;
+ }
+
+ /**
+ * Select the whole text of the textfield.
+ */
+ public void selectAll() {
+ click(new Integer(1));
+
+ // fix for https://bxapps.bredex.de/bugzilla/show_bug.cgi?id=201
+ // The keystroke "command + a" sometimes causes an "a" to be entered
+ // into the text field instead of selecting all text (or having no
+ // effect).
+ if (EnvironmentUtils.isMacOS()) {
+ getEventThreadQueuer().invokeAndWait("combo.selectAll", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ int textLength = StringUtils.length(
+ m_combobox.getText());
+ m_combobox.setSelection(new Point(0, textLength));
+ return null;
+ }
+ });
+ } else {
+ getRobot().keyStroke(getRobot().getSystemModifierSpec() + " A"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getSelectedIndex() {
+
+ int selectedIndex = ((Integer)getEventThreadQueuer().invokeAndWait(
+ ComboAdapter.class.getName()
+ + "getSelectedIndex", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return new Integer(m_combobox.getSelectionIndex());
+ }
+ })).intValue();
+
+ return selectedIndex;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ Object o = getEventThreadQueuer().invokeAndWait(
+ "getSelectedItem", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_combobox.getText();
+ }
+ });
+ return o != null ? o.toString() : null;
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ protected boolean isComboEnabled() {
+
+ boolean isEnabled = ((Boolean)getEventThreadQueuer().invokeAndWait(
+ ComboAdapter.class.getName()
+ + "isComboEnabled", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return m_combobox.isEnabled()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ })).booleanValue();
+
+ return isEnabled;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void selectImpl(int index) {
+
+ // Press 'Escape' key to close the dropdown list
+
+ getRobot().keyType(m_combobox, SWT.ESC);
+
+ // Currently no method to select elements via mouse clicks
+ selectComboIndex(index);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ protected void openDropdownList() {
+ // FIXME zeb: Figure out a way to check the status of the dropdown list
+ toggleDropdownList();
+ }
+
+ /**
+ * Returns the number of items contained in the combo list.
+ * @return the number of items.
+ */
+ protected int getItemCount() {
+ return ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getItemCount", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() {
+
+ return new Integer(m_combobox.getItemCount());
+ }
+
+ })).intValue();
+
+ }
+
+ /**
+ * Returns the item at the given, zero-relative index in the combo list.
+ * Throws an exception if the index is out of range.
+ * @param index the index of the item to return
+ * @return the item at the given index
+ */
+ protected String getItem(final int index) {
+ return (String)getEventThreadQueuer().invokeAndWait(
+ "getItem", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() {
+
+ return m_combobox.getItem(index);
+ }
+
+ });
+
+ }
+
+ /**
+ *
+ * @param index the index to select.
+ * @see Combo#select(int)
+ */
+ private void selectComboIndex(final int index) {
+ final Combo combo = m_combobox;
+ getEventThreadQueuer().invokeAndWait("selectComboIndex", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ combo.select(index);
+ Event selectionEvent = new Event();
+ selectionEvent.type = SWT.Selection;
+ selectionEvent.widget = combo;
+ combo.notifyListeners(SWT.Selection, selectionEvent);
+
+ return null;
+ }
+ });
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/LabelAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/LabelAdapter.java
new file mode 100644
index 000000000..6be795e9e
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/LabelAdapter.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITextVerifiable;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.swt.widgets.Label;
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class LabelAdapter extends WidgetAdapter implements ITextVerifiable {
+
+ /**
+ *
+ * @param objectToAdapt the component to adapt
+ */
+ public LabelAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ return (String)getEventThreadQueuer().invokeAndWait(
+ "getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ try {
+ Label label = (Label) getRealComponent();
+ return SwtUtils.removeMnemonics(label.getText());
+ } catch (NullPointerException e) {
+ throw new StepExecutionException(
+ "component must not be null", //$NON-NLS-1$
+ EventFactory
+ .createComponentNotFoundErrorEvent());
+ }
+ }
+ });
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ListAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ListAdapter.java
new file mode 100644
index 000000000..2f3deaf7e
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ListAdapter.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import java.util.ArrayList;
+
+import org.eclipse.jubula.rc.common.CompSystemConstants;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IListAdapter;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.List;
+/**
+ *
+ * @author BREDEX GmbH
+ *
+ */
+public class ListAdapter extends WidgetAdapter implements IListAdapter {
+
+ /** */
+ private List m_list;
+ /**
+ *
+ * @param objectToAdapt -
+ */
+ public ListAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_list = (List) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ String[] selected = getSelectedValues();
+ if (selected.length > 0) {
+ return selected[0];
+ }
+ throw new StepExecutionException("No list item selected", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NO_SELECTION));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int[] getSelectedIndices() {
+ return (int[])getEventThreadQueuer().invokeAndWait(
+ "getSelectedIndices", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_list.getSelectionIndices();
+ }
+ });
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public void clickOnIndex(Integer i, ClickOptions co) {
+ final int iVal = i.intValue();
+ scrollIndexToVisible(iVal);
+
+ final Rectangle clickConstraints =
+ (Rectangle)getEventThreadQueuer().invokeAndWait(
+ "setClickConstraints", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+ Rectangle constraints = new Rectangle(0, 0, 0, 0);
+ int displayedItemCount = getDisplayedItemCount();
+ int numberBelowTop = 0;
+ if (displayedItemCount >= m_list.getItemCount()) {
+ numberBelowTop = iVal;
+ } else {
+ numberBelowTop = Math.max(0, iVal
+ - m_list.getItemCount() + displayedItemCount);
+ }
+
+ // Set the constraints based on the numberBelowTop
+ constraints.height = m_list.getItemHeight();
+ constraints.width = m_list.getBounds().width;
+ constraints.y += (numberBelowTop * constraints.height);
+ // explicitly use list relative bounds here - as e.g. on
+ // Mac OS systems list.getClientArea() is not relative
+ // see bug 353905
+ Rectangle actualListBounds =
+ new Rectangle(0, 0, m_list.getClientArea().width,
+ m_list.getClientArea().height);
+ return constraints.intersection(actualListBounds);
+ }
+ });
+
+ // Note that we set scrollToVisible false because we have already done
+ // the scrolling.
+ getRobot().click(m_list, clickConstraints,
+ co.setScrollToVisible(false));
+
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getSelectedValues() {
+ return (String[])getEventThreadQueuer().invokeAndWait(
+ "getSelectedValues", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_list.getSelection();
+ }
+ });
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public Integer[] findIndicesOfValues(final String[] values,
+ final String operator, final String searchType) {
+ final java.util.List indexList = (java.util.List)
+ getEventThreadQueuer().invokeAndWait("findIndices", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ final int valuesLength = values.length;
+ final java.util.List idxList = new ArrayList(
+ values.length);
+ final int listItemCount = m_list.getItemCount();
+ final MatchUtil matchUtil = MatchUtil.getInstance();
+ for (int i = 0; i < valuesLength; i++) {
+ final String value = values[i];
+ for (int j = getStartingIndex(searchType);
+ j < listItemCount; j++) {
+
+ final String listItem = m_list.getItem(j);
+ if (matchUtil.match(listItem, value,
+ operator)) {
+
+ idxList.add(new Integer(j));
+ }
+ }
+ }
+ return idxList;
+ }
+ });
+ Integer[] indices = new Integer[indexList.size()];
+ indexList.toArray(indices);
+ return indices;
+ }
+
+ /**
+ * @return the number of items displayed in the list.
+ */
+ private int getDisplayedItemCount() {
+ return ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getDisplayedItemCount", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+ int listHeight = SwtUtils.getWidgetBounds(m_list).height;
+ int itemHeight = m_list.getItemHeight();
+
+ return new Integer(listHeight / itemHeight);
+ }
+
+ })).intValue();
+ }
+
+ /**
+ * @param index The index to make visible
+ */
+ private void scrollIndexToVisible(final int index) {
+ getEventThreadQueuer().invokeAndWait(
+ "scrollIndexToVisible", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+
+ m_list.setTopIndex(index);
+
+ return null;
+ }
+
+ });
+ }
+ /**
+ * @param searchType Determines where the search begins ("relative" or "absolute")
+ * @return The index from which to begin a search, based on the search type
+ * and (if appropriate) the currently selected cell.
+ */
+ private int getStartingIndex(final String searchType) {
+ int startingIndex = 0;
+ if (searchType.equalsIgnoreCase(
+ CompSystemConstants.SEARCH_TYPE_RELATIVE)) {
+ int [] selectedIndices = getSelectedIndices();
+ // Start from the last selected item, if any item(s) are selected
+ if (selectedIndices.length > 0) {
+ startingIndex = selectedIndices[selectedIndices.length - 1] + 1;
+ }
+ }
+ return startingIndex;
+ }
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/MenuAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/MenuAdapter.java
new file mode 100644
index 000000000..7cecbb143
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/MenuAdapter.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.RobotException;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+/**
+ * Implements the Menu interface for adapting a <code>SWT.Menu</code>
+ *
+ * @author BREDEX GmbH
+ */
+public class MenuAdapter extends AbstractComponentAdapter
+ implements IMenuAdapter {
+ /** the Menu from the AUT */
+ private Menu m_menu;
+
+
+ /**
+ *
+ * @param component graphics component which will be adapted
+ */
+ public MenuAdapter(Object component) {
+ m_menu = (Menu) component;
+ }
+
+ /**
+ * Gets the IEventThreadQueuer.
+ *
+ * @return The Robot
+ * @throws RobotException
+ * If the Robot cannot be created.
+ */
+ protected IRobot getRobot() throws RobotException {
+ return getRobotFactory().getRobot();
+ }
+
+ /**
+ * @return The event thread queuer.
+ */
+ public IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public Object getRealComponent() {
+ return m_menu;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public void setComponent(Object element) {
+ m_menu = (Menu) element;
+
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public IMenuItemAdapter[] getItems() {
+
+ MenuItem[] items =
+ (MenuItem[]) getEventThreadQueuer().invokeAndWait(
+ "getItems", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_menu.getItems();
+ }
+ });
+ IMenuItemAdapter[] adapters = new IMenuItemAdapter[items.length];
+ for (int i = 0; i < items.length; i++) {
+ IMenuItemAdapter menuItem = new MenuItemAdapter(items[i]);
+ adapters[i] = menuItem;
+ }
+ return adapters;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public int getItemCount() {
+ Integer itemCount = (Integer) getEventThreadQueuer().invokeAndWait(
+ "getItemCount", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return new Integer(m_menu.getItemCount());
+ }
+ });
+ return itemCount.intValue();
+ }
+
+
+
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/MenuItemAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/MenuItemAdapter.java
new file mode 100644
index 000000000..bbc1fdf78
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/MenuItemAdapter.java
@@ -0,0 +1,532 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IEventMatcher;
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.IRobotEventConfirmer;
+import org.eclipse.jubula.rc.common.driver.IRobotEventInterceptor;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.driver.InterceptorOptions;
+import org.eclipse.jubula.rc.common.exception.RobotException;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.listener.EventLock;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
+import org.eclipse.jubula.rc.swt.driver.EventThreadQueuerSwtImpl;
+import org.eclipse.jubula.rc.swt.driver.RobotFactorySwtImpl;
+import org.eclipse.jubula.rc.swt.driver.SelectionSwtEventMatcher;
+import org.eclipse.jubula.rc.swt.driver.ShowSwtEventMatcher;
+import org.eclipse.jubula.rc.swt.implclasses.EventListener;
+import org.eclipse.jubula.rc.swt.implclasses.EventListener.Condition;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.jubula.tools.constants.TimeoutConstants;
+import org.eclipse.jubula.tools.i18n.I18n;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+/**
+ * Implements the MenuItem interface for adapting a <code>SWT.MenuItem</code>
+ *
+ * @author BREDEX GmbH
+ */
+public class MenuItemAdapter extends AbstractComponentAdapter
+ implements IMenuItemAdapter {
+
+ /** the MenuItem from the AUT*/
+ private MenuItem m_menuItem;
+
+
+ /**
+ *
+ * @param component graphics component which will be adapted
+ */
+ public MenuItemAdapter(Object component) {
+ super();
+ m_menuItem = (MenuItem) component;
+ }
+
+ /**
+ * Gets the IEventThreadQueuer.
+ *
+ * @return The Robot
+ * @throws RobotException
+ * If the Robot cannot be created.
+ */
+ protected IRobot getRobot() throws RobotException {
+ return getRobotFactory().getRobot();
+ }
+
+ /**
+ * @return The event thread queuer.
+ */
+ public IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getRealComponent() {
+
+ return m_menuItem;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public void setComponent(Object element) {
+ m_menuItem = (MenuItem) element;
+
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ return (String) getEventThreadQueuer().invokeAndWait(
+ "getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_menuItem.getText();
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnabled() {
+ final Boolean isEnabled = (Boolean) getEventThreadQueuer()
+ .invokeAndWait("isEnabled", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return m_menuItem.isEnabled() ? Boolean.TRUE
+ : Boolean.FALSE;
+ }
+ });
+ return isEnabled.booleanValue();
+
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isExisting() {
+ if (m_menuItem != null) {
+ return true;
+ }
+ return false;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSelected() {
+ final Boolean isSelected = (Boolean)getEventThreadQueuer()
+ .invokeAndWait("isSelected", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return m_menuItem.getSelection()
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return isSelected.booleanValue();
+ }
+
+ /**
+ * @return -
+ */
+ public boolean isShowing() {
+
+ return true; //FIXME is here a Showing implementation?
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public IMenuAdapter getMenu() {
+
+ Menu menu =
+ (Menu) getEventThreadQueuer().invokeAndWait(
+ "getItems", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_menuItem.getMenu();
+ }
+ });
+
+
+ return new MenuAdapter(menu);
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasSubMenu() {
+
+
+
+ if (getMenu() != null) {
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Checks whether the given menu item is a separator.
+ * This method runs in the GUI thread.
+ * @return <code>true</code> if <code>menuItem</code> is a separator item.
+ * Otherwise <code>false</code>.
+ */
+ public boolean isSeparator() {
+ final Boolean isSeparator = (Boolean)getEventThreadQueuer()
+ .invokeAndWait(
+ ".isSeparator", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return (m_menuItem.getStyle() & SWT.SEPARATOR) != 0
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ });
+ return isSeparator.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void selectMenuItem() {
+ Rectangle bounds = getMenuItemBounds();
+ Rectangle nullBounds = new Rectangle(0, 0, 0, 0);
+
+ if (bounds.equals(nullBounds)) {
+ selectProgramatically();
+ } else {
+ clickMenuItem(getRobot(), m_menuItem, 1);
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IMenuAdapter openSubMenu() {
+ final MenuItem menuItem = m_menuItem;
+ MenuShownCondition cond = new MenuShownCondition(menuItem);
+ EventLock lock = new EventLock();
+ final EventListener listener = new EventListener(lock, cond);
+ final Display d = menuItem.getDisplay();
+ final IEventThreadQueuer queuer = new EventThreadQueuerSwtImpl();
+
+ queuer.invokeAndWait("addMenuShownListeners", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ d.addFilter(SWT.Show, listener);
+
+ return null;
+ }
+ });
+ try {
+ // Menu bar items require a click in order to open the submenu.
+ // Cascading menus are opened with a mouse-over and
+ // may be closed by a click.
+ int clickCount = isMenuBarItem(menuItem) ? 1 : 0;
+ Menu menu = (Menu)getEventThreadQueuer().invokeAndWait(
+ "openSubMenu", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return menuItem.getMenu();
+ }
+ });
+ Rectangle bounds = getMenuItemBounds();
+ Rectangle nullBounds = new Rectangle(0, 0, 0, 0);
+ if (bounds.equals(nullBounds)) {
+ openSubMenuProgramatically(menu);
+ } else {
+ clickMenuItem(getRobot(), menuItem, clickCount);
+ }
+ synchronized (lock) {
+ long timeout = TimeoutConstants.SERVER_TIMEOUT_WAIT_FOR_POPUP;
+ long done = System.currentTimeMillis() + timeout;
+ long now;
+ while (!lock.isReleased() && timeout > 0) {
+ lock.wait(timeout);
+ now = System.currentTimeMillis();
+ timeout = done - now;
+ }
+ }
+ } catch (InterruptedException e) { // ignore
+ } finally {
+ queuer.invokeAndWait("removeMenuShownListeners", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ d.removeFilter(SWT.Show, listener);
+
+ return null;
+ }
+ });
+ }
+ if (!lock.isReleased()) {
+ String itemText = (String)getEventThreadQueuer().invokeAndWait(
+ "getItemText", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ if (menuItem != null && !menuItem.isDisposed()) {
+ return menuItem.getText();
+ }
+ return "unknown menu item"; //$NON-NLS-1$
+ }
+
+ });
+ itemText = SwtUtils.removeMnemonics(itemText);
+ throw new StepExecutionException(
+ I18n.getString("TestErrorEvent.MenuDidNotAppear", //$NON-NLS-1$
+ new String [] {itemText}),
+ EventFactory.createActionError(
+ "TestErrorEvent.MenuDidNotAppear", //$NON-NLS-1$
+ new String [] {itemText}));
+ }
+ return new MenuAdapter(cond.getMenu());
+ }
+
+ /**
+ * @param menuItem the menu item to check
+ * @return <code>true</code> of the given menu item is part of a menu
+ * bar. Otherwise, <code>false</code>.
+ */
+ private boolean isMenuBarItem(final MenuItem menuItem) {
+ return ((Boolean)getEventThreadQueuer().invokeAndWait(
+ "isMenuBarItem", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ if (menuItem != null && !menuItem.isDisposed()) {
+ Menu parent = menuItem.getParent();
+ if (parent != null && !parent.isDisposed()) {
+ return (parent.getStyle() & SWT.BAR) != 0
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ }
+ return Boolean.FALSE;
+ }
+
+ })).booleanValue();
+ }
+
+
+ /**
+ * Waits for a submenu to appear. Examples of submenus are cascading menus
+ * and pulldown menus.
+ *
+ * @author BREDEX GmbH
+ * @created Oct 30, 2008
+ */
+ public static class MenuShownCondition implements Condition {
+ /** the menu that was shown */
+ private Menu m_shownMenu = null;
+
+ /** the parent item of the expected menu */
+ private MenuItem m_parentItem;
+
+ /**
+ * Constructor
+ *
+ * @param parentItem The parent item of the expected menu. This
+ * condition only matches if a menu with parent item
+ * <code>parentItem</code> appears.
+ */
+ MenuShownCondition(MenuItem parentItem) {
+ m_parentItem = parentItem;
+ }
+
+ /**
+ *
+ * @return the menu that appeared
+ */
+ public Menu getMenu() {
+ return m_shownMenu;
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public boolean isTrue(Event event) {
+ if (event.type == SWT.Show && event.widget instanceof Menu
+ && ((Menu)(event.widget)).getParentItem() == m_parentItem) {
+ m_shownMenu = (Menu)event.widget;
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Clicks on a menu item
+ *
+ * @param robot the robot
+ * @param item the menu item
+ * @param clickCount the number of times to click the menu item
+ */
+ public static void clickMenuItem(IRobot robot, final MenuItem item,
+ int clickCount) {
+ // FIXME existiert so schon und kann man benutzen
+// if (!isMenuItemEnabled(item)) {
+// throw new StepExecutionException("menu item not enabled", //$NON-NLS-1$
+// EventFactory.createActionError(
+// TestErrorEvent.MENU_ITEM_NOT_ENABLED));
+// }
+
+ robot.click(item, null,
+ ClickOptions.create()
+ .setClickType(ClickOptions.ClickType.RELEASED)
+ .setStepMovement(false).setClickCount(clickCount));
+
+ }
+ /**
+ *
+ * @return bounds of MenuItem
+ */
+ public Rectangle getMenuItemBounds() {
+ Rectangle bounds = (Rectangle)getEventThreadQueuer().invokeAndWait(
+ "getMenuItemBounds", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return SwtUtils.getBounds(m_menuItem);
+ }
+ });
+ return bounds;
+ }
+
+ /**
+ * open SubMenu programatically (for Mac OS)
+ * @param menu the Menu
+ */
+ public void openSubMenuProgramatically(final Menu menu) {
+// if (!isMenuEnabled(menu)) {
+// throw new StepExecutionException("menu item not enabled", //$NON-NLS-1$
+// EventFactory.createActionError(
+// TestErrorEvent.MENU_ITEM_NOT_ENABLED));
+// }
+
+ final InterceptorOptions options = new InterceptorOptions(
+ new long[]{SWT.Show});
+ final IEventMatcher matcher =
+ new ShowSwtEventMatcher();
+ RobotFactorySwtImpl robotSwt = new RobotFactorySwtImpl();
+ IRobotEventInterceptor interceptor =
+ robotSwt.getRobotEventInterceptor();
+ final IRobotEventConfirmer confirmer = interceptor
+ .intercept(options);
+
+ final Event event = new Event();
+ event.time = (int) System.currentTimeMillis();
+ event.widget = menu;
+ event.display = menu.getDisplay();
+ event.type = SWT.Show;
+
+ getEventThreadQueuer().invokeAndWait(
+ "openSubMenuProgramatically", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+
+ menu.notifyListeners(SWT.Show, event);
+
+ return null;
+ }
+ });
+
+ try {
+ confirmer.waitToConfirm(menu, matcher);
+ } catch (RobotException re) {
+ final StringBuffer sb = new StringBuffer(
+ "Robot exception occurred while clicking...\n"); //$NON-NLS-1$
+// logRobotException(menuItem, re, sb);
+ sb.append("Component: "); //$NON-NLS-1$
+
+ getEventThreadQueuer().invokeAndWait(
+ "getBounds", new IRunnable() { //$NON-NLS-1$
+ public Object run()
+ throws StepExecutionException {
+ sb.append(menu);
+ // Return value not used
+ return null;
+ }
+ });
+// log.error(sb.toString(), re);
+ throw re;
+ }
+ }
+
+ /**
+ * select MenuItem programatically (for Mac OS)
+ */
+ public void selectProgramatically() {
+// FIXME must implement this check case
+// if (!isMenuItemEnabled(menuItem)) {
+// throw new StepExecutionException("menu item not enabled", //$NON-NLS-1$
+// EventFactory.createActionError(
+// TestErrorEvent.MENU_ITEM_NOT_ENABLED));
+// }
+ final MenuItem menuItem = m_menuItem;
+ final InterceptorOptions options = new InterceptorOptions(
+ new long[]{SWT.Selection});
+ final IEventMatcher matcher =
+ new SelectionSwtEventMatcher();
+ RobotFactorySwtImpl robotSwt = new RobotFactorySwtImpl();
+ IRobotEventInterceptor interceptor =
+ robotSwt.getRobotEventInterceptor();
+ final IRobotEventConfirmer confirmer = interceptor
+ .intercept(options);
+
+ final Event event = new Event();
+ event.time = (int) System.currentTimeMillis();
+ event.widget = menuItem;
+ event.display = menuItem.getDisplay();
+ event.type = SWT.Selection;
+
+ getEventThreadQueuer().invokeLater(
+ "selectProgramatically", new Runnable() { //$NON-NLS-1$
+ public void run() {
+ //if menuitem is checkbox or radiobutton set Selection
+ if ((menuItem.getStyle() & SWT.CHECK) == 0
+ || (menuItem.getStyle() & SWT.RADIO) == 0) {
+ if (menuItem.getSelection()) {
+ menuItem.setSelection(false);
+ } else {
+ menuItem.setSelection(true);
+ }
+ }
+
+ menuItem.notifyListeners(SWT.Selection, event);
+
+ }
+ });
+
+ try {
+ confirmer.waitToConfirm(menuItem, matcher);
+ } catch (RobotException re) {
+ final StringBuffer sb = new StringBuffer(
+ "Robot exception occurred while clicking...\n"); //$NON-NLS-1$
+ //logRobotException(menuItem, re, sb);
+ sb.append("Component: "); //$NON-NLS-1$
+
+ getEventThreadQueuer().invokeAndWait(
+ "getBounds", new IRunnable() { //$NON-NLS-1$
+ public Object run()
+ throws StepExecutionException {
+ sb.append(menuItem);
+ // Return value not used
+ return null;
+ }
+ });
+// FIXME LOG IS MISSING HERE
+// log.error(sb.toString(), re);
+ throw re;
+ }
+
+ }
+
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/StyledTextAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/StyledTextAdapter.java
new file mode 100644
index 000000000..45651e759
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/StyledTextAdapter.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.logger.AutServerLogger;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITextComponentAdapter;
+import org.eclipse.jubula.tools.utils.EnvironmentUtils;
+import org.eclipse.swt.custom.StyledText;
+
+/**
+ * Implementation of the Interface <code>ITextComponentAdapter</code> as a
+ * adapter for the <code>StyledText</code> component.
+ * @author BREDEX GmbH
+ *
+ */
+public class StyledTextAdapter extends WidgetAdapter
+ implements ITextComponentAdapter {
+
+ /** the logger */
+ private static AutServerLogger log = new AutServerLogger(
+ StyledTextAdapter.class);
+ /** */
+ private StyledText m_styledText;
+ /**
+ *
+ * @param objectToAdapt
+ */
+ public StyledTextAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_styledText = (StyledText) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ String actual = (String)getEventThreadQueuer().invokeAndWait(
+ "getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_styledText.getText();
+ }
+ });
+ return actual;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSelection(final int start) {
+ getEventThreadQueuer().invokeAndWait("setSelection", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ m_styledText.setSelection(start);
+ return null;
+ }
+ });
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSelection(final int start, final int end) {
+ getEventThreadQueuer().invokeAndWait("setSelection", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ m_styledText.setSelection(start, end);
+ return null;
+ }
+ });
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSelectionText() {
+ String actual = (String)getEventThreadQueuer().invokeAndWait(
+ "getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_styledText.getSelectionText();
+ }
+ });
+ return actual;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void selectAll() {
+ final String totalText = getText();
+
+ // fix for https://bxapps.bredex.de/bugzilla/show_bug.cgi?id=201
+ // The keystroke "command + a" sometimes causes an "a" to be entered
+ // into the text field instead of selecting all text (or having no
+ // effect).
+ if (!EnvironmentUtils.isMacOS()) {
+ try {
+ getRobot().keyStroke(getRobot().getSystemModifierSpec() + " A"); //$NON-NLS-1$
+ } catch (StepExecutionException see) {
+ /*This might happen under certain circumstances e.g. on MacOS X see
+ bug 342691 */
+ log.warn(see);
+ }
+ }
+
+ if (!totalText.equals(getSelectionText())) {
+ // the selection failed for some reason
+ getEventThreadQueuer().invokeAndWait("text.selectAll", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ m_styledText.selectAll();
+ return null;
+ }
+ });
+ }
+
+ String selectionText = getSelectionText();
+ if (!totalText.equals(selectionText)) {
+ log.warn("SelectAll failed!\n" //$NON-NLS-1$
+ + "Total text: '" + totalText + "'\n" //$NON-NLS-1$//$NON-NLS-2$
+ + "Selected text: '" + selectionText + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEditable() {
+ return ((Boolean)getEventThreadQueuer().invokeAndWait(
+ "isEditable", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return m_styledText.getEditable()
+ && m_styledText.getEnabled()
+ ? Boolean.TRUE : Boolean.FALSE; // see findBugs
+ }
+ })).booleanValue();
+ }
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TabFolderAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TabFolderAdapter.java
new file mode 100644
index 000000000..2e0b4537d
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TabFolderAdapter.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITabPaneAdapter;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.swt.widgets.TabFolder;
+/**
+ * Implementation of the Interface <code>ITabPane</code> as a
+ * adapter for the <code>TabFolder</code> component.
+ * @author BREDEX GmbH
+ *
+ */
+public class TabFolderAdapter extends WidgetAdapter implements ITabPaneAdapter {
+
+ /** the tabFolder from the AUT */
+ private TabFolder m_tabFolder;
+
+ /**
+ *
+ * @param objectToAdapt the component from the AUT
+ */
+ public TabFolderAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_tabFolder = (TabFolder) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getTabCount() {
+ return ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getSelectedIndex", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+ return new Integer(m_tabFolder.getItemCount());
+ }
+ })).intValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getTitleofTab(final int index) {
+ return (String)getEventThreadQueuer().invokeAndWait(
+ "verifyTextOfTabByIndex", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ return m_tabFolder.getItem(index).getText();
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getBoundsAt(final int index) {
+ return getEventThreadQueuer().invokeAndWait("getBoundsAt", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ return SwtUtils.getRelativeWidgetBounds(
+ m_tabFolder.getItem(index), m_tabFolder);
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnabledAt(final int index) {
+ return ((Boolean) getEventThreadQueuer().invokeAndWait("isEnabledAt", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ return m_tabFolder.getItem(index).getControl()
+ .isEnabled() ? Boolean.TRUE : Boolean.FALSE;
+ }
+ })).booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getSelectedIndex() {
+ return ((Integer)getEventThreadQueuer().invokeAndWait(
+ "getSelectedIndex", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+ return new Integer(m_tabFolder.getSelectionIndex());
+ }
+ })).intValue();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TableAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TableAdapter.java
new file mode 100644
index 000000000..a15db0381
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TableAdapter.java
@@ -0,0 +1,534 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import java.awt.Rectangle;
+
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.table.Cell;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITableAdapter;
+import org.eclipse.jubula.rc.swt.listener.TableSelectionTracker;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TableCursor;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+/**
+ * Implements the Table interface for adapting a <code>SWT.Table</code>
+ *
+ * @author BREDEX GmbH
+ */
+public class TableAdapter extends WidgetAdapter implements ITableAdapter {
+ /** */
+ private Table m_table;
+
+ /**
+ *
+ * @param objectToAdapt graphics component which will be adapted
+ */
+ public TableAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_table = (Table) objectToAdapt;
+ }
+
+ /** {@inheritDoc} */
+ public int getColumnCount() {
+ Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
+ "getColumnCount", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return new Integer(m_table.getColumnCount());
+ }
+ });
+ return returnvalue.intValue();
+ }
+
+ /** {@inheritDoc} */
+ public int getRowCount() {
+ Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
+ "getRowCount", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return new Integer(m_table.getItemCount());
+ }
+ });
+ return returnvalue.intValue();
+ }
+
+ /** {@inheritDoc} */
+ public String getCellText(final int row, final int column) {
+ String current = (String)getEventThreadQueuer().invokeAndWait("getCellText", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ String value = m_table.getItem(row).getText(column);
+// if (log.isDebugEnabled()) {
+// log.debug("Getting cell text:"); //$NON-NLS-1$
+// log.debug("Row, col: " + row + ", " + col); //$NON-NLS-1$ //$NON-NLS-2$
+// log.debug("Value: " + value); //$NON-NLS-1$
+// }
+ return value;
+ }
+ });
+ return current;
+ }
+
+ /** {@inheritDoc} */
+ public String getColumnName(final int column) {
+ String current = (String)getEventThreadQueuer().invokeAndWait("getColumnName", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ String value = m_table.getColumn(column).getText();
+ return value;
+ }
+ });
+ return current;
+ }
+
+ /** {@inheritDoc} */
+ public int getColumnFromString(final String col, final String operator) {
+ int column = -2;
+ try {
+ int usrIdxCol = Integer.parseInt(col);
+ if (usrIdxCol == 0) {
+ usrIdxCol = usrIdxCol + 1;
+ }
+ column = IndexConverter.toImplementationIndex(
+ usrIdxCol);
+ } catch (NumberFormatException nfe) {
+ try {
+ Boolean isVisible;
+ isVisible = (Boolean)getEventThreadQueuer().invokeAndWait(
+ "getColumnFromString", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return new Boolean(m_table.getHeaderVisible());
+ }
+ });
+ if (!(isVisible.booleanValue())) {
+ throw new StepExecutionException("No Header", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.NO_HEADER));
+ }
+
+ Integer implCol;
+ implCol = (Integer)getEventThreadQueuer().invokeAndWait(
+ "getColumnFromString", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ for (int i = 0; i < m_table.getColumnCount(); i++) {
+ TableColumn tblCol = m_table.getColumn(i);
+ if (MatchUtil.getInstance().match(
+ tblCol.getText(), col, operator)) {
+ return new Integer (i);
+ }
+ }
+ return new Integer (-2);
+ }
+ });
+ column = implCol.intValue();
+ } catch (IllegalArgumentException iae) {
+ //do nothing here
+ }
+ }
+ return column;
+ }
+
+ /** {@inheritDoc} */
+ public String getRowName(final int row) {
+ String current = (String)getEventThreadQueuer().invokeAndWait("getRowName", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ String value = m_table.getItem(row).getText();
+ return value;
+ }
+ });
+ return current;
+ }
+
+ /** {@inheritDoc} */
+ public int getRowFromString(final String row, final String operator) {
+ int rowInt = -2;
+ try {
+ rowInt = IndexConverter.toImplementationIndex(
+ Integer.parseInt(row));
+ if (rowInt == -1) {
+ Boolean isVisible;
+ isVisible = (Boolean)getEventThreadQueuer().invokeAndWait(
+ "getRowFromString", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return new Boolean(m_table.getHeaderVisible());
+ }
+ });
+ if (!(isVisible.booleanValue())) {
+ throw new StepExecutionException("Header not visible", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.NO_HEADER));
+ }
+ }
+ } catch (NumberFormatException nfe) {
+ Integer implRow;
+ implRow = (Integer)getEventThreadQueuer().invokeAndWait(
+ "getRowFromString", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ for (int i = 0; i < m_table.getItemCount(); i++) {
+ String cellTxt = getCellText(i, 0);
+ if (MatchUtil.getInstance().match(
+ cellTxt, row, operator)) {
+ return new Integer(i);
+ }
+ }
+ return new Integer(-2);
+ }
+ });
+ rowInt = implRow.intValue();
+ }
+ return rowInt;
+ }
+
+ /** {@inheritDoc} */
+ public Rectangle getBounds() {
+ Rectangle returnvalue = (Rectangle) getEventThreadQueuer()
+ .invokeAndWait("getBounds", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ return m_table.getBounds();
+ }
+ });
+
+ return returnvalue;
+ }
+
+ /** {@inheritDoc} */
+ public Rectangle getHeaderBounds(final int col) {
+ Rectangle cellBounds;
+ cellBounds = (Rectangle)getEventThreadQueuer().invokeAndWait(
+ "getHeaderBounds", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ org.eclipse.swt.graphics.Rectangle rect =
+ m_table.getItem(0).getBounds(col);
+ rect.y = m_table.getClientArea().y;
+ return new Rectangle(rect.x, rect.y, rect.width,
+ rect.height);
+ }
+ });
+ return cellBounds;
+ }
+
+ /** {@inheritDoc} */
+ public Cell getSelectedCell() throws StepExecutionException {
+ Cell cell = (Cell) getEventThreadQueuer().invokeAndWait(
+ "getSelectedSell", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ return TableSelectionTracker.getInstance()
+ .getSelectedCell(m_table);
+ }
+ });
+ return cell;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isHeaderVisible() {
+ Boolean isVisible;
+ isVisible = (Boolean)getEventThreadQueuer().invokeAndWait(
+ "isHeaderVisible", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return new Boolean(m_table.getHeaderVisible());
+ }
+ });
+ return isVisible.booleanValue();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isCellEditable(final int row, final int col) {
+ final Control cellEditor = (Control)
+ activateEditor(new Cell(row, col));
+ boolean isEditable = ((Boolean)getEventThreadQueuer().invokeAndWait(
+ "isCellEditable", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+
+ return isEditable(cellEditor)
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ })).booleanValue();
+ return isEditable;
+ }
+
+ /** {@inheritDoc} */
+ public boolean hasCellSelection() {
+ TableItem[] selItems = (TableItem[])getEventThreadQueuer()
+ .invokeAndWait("hasCellSelection", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return m_table.getSelection();
+ }
+ });
+ return selItems.length > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Rectangle scrollCellToVisible(final int row, final int col)
+ throws StepExecutionException {
+ final Table table = m_table;
+ getEventThreadQueuer().invokeAndWait("scrollCellToVisible", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ if (table.getColumnCount() > 0 || col > 0) {
+ table.showColumn(table.getColumn(col));
+ }
+ table.showItem(table.getItem(row));
+ return null;
+ }
+ });
+
+ final Rectangle cellBoundsRelativeToParent = getCellBounds(row, col);
+
+ getEventThreadQueuer().invokeAndWait("getCellBoundsRelativeToParent", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ org.eclipse.swt.graphics.Point cellOriginRelativeToParent =
+ table.getDisplay().map(
+ table, table.getParent(),
+ new org.eclipse.swt.graphics.Point(
+ cellBoundsRelativeToParent.x,
+ cellBoundsRelativeToParent.y));
+ cellBoundsRelativeToParent.x =
+ cellOriginRelativeToParent.x;
+ cellBoundsRelativeToParent.y =
+ cellOriginRelativeToParent.y;
+ return null;
+ }
+ });
+
+ Control parent = (Control)getEventThreadQueuer().invokeAndWait("getParent", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ table.getParent();
+ return null;
+ }
+ });
+
+
+ getRobot().scrollToVisible(
+ parent, cellBoundsRelativeToParent);
+
+ return getVisibleBounds(getCellBounds(row, col));
+ }
+
+ /**
+ *
+ * @param row The row of the cell
+ * @param col The column of the cell
+ * @return The bounding rectangle for the cell, relative to the table's
+ * location.
+ */
+ private Rectangle getCellBounds(final int row, final int col) {
+ Rectangle cellBounds = (Rectangle)getEventThreadQueuer().invokeAndWait(
+ "evaluateCellBounds", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ checkRowColBounds(row, col);
+ TableItem ti = m_table.getItem(row);
+ int column = (m_table.getColumnCount() > 0 || col > 0)
+ ? col : 0;
+ org.eclipse.swt.graphics.Rectangle r =
+ ti.getBounds(column);
+ String text = ti.getText(column);
+ Image image = ti.getImage(column);
+ if (text != null && text.length() != 0) {
+ GC gc = new GC(m_table);
+ int charWidth = 0;
+ try {
+ FontMetrics fm = gc.getFontMetrics();
+ charWidth = fm.getAverageCharWidth();
+ } finally {
+ gc.dispose();
+ }
+ r.width = text.length() * charWidth;
+ if (image != null) {
+ r.width += image.getBounds().width;
+ }
+ } else if (image != null) {
+ r.width = image.getBounds().width;
+ }
+ if (column > 0) {
+ TableColumn tc = m_table.getColumn(column);
+ int alignment = tc.getAlignment();
+ if (alignment == SWT.CENTER) {
+ r.x += ((double)tc.getWidth() / 2)
+ - ((double)r.width / 2);
+ }
+ if (alignment == SWT.RIGHT) {
+ r.x += tc.getWidth() - r.width;
+ }
+ }
+
+ return new Rectangle(r.x, r.y, r.width, r.height);
+ }
+ });
+ return cellBounds;
+ }
+
+ /**
+ * Checks wether <code>0 <= value < count</code>.
+ * @param value The value to check.
+ * @param count The upper bound.
+ */
+ private void checkBounds(int value, int count) {
+ if (value < 0 || value >= count) {
+ throw new StepExecutionException("Invalid row/column: " + value, //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.INVALID_INDEX_OR_HEADER));
+ }
+ }
+
+ /**
+ * Checks if the passed row and column are inside the bounds of the Table.
+ * @param row The row
+ * @param column The column
+ * @throws StepExecutionException If the row or the column is outside of the Table's bounds.
+ */
+ protected void checkRowColBounds(int row, int column)
+ throws StepExecutionException {
+ checkBounds(row, getRowCount());
+
+ // Corner case: Only check the bounds if the table is not being
+ // used as a list or anything other than the first column
+ // is being checked.
+ int colCount = getColumnCount();
+ if (colCount > 0 || column > 0) {
+ checkBounds(column, colCount);
+ }
+ }
+
+ /**
+ * Computes the visible cellBounds inside the visible bounds of the table.<br>
+ * The result is the intersection of the visible bounds of the table and the
+ * bounds of the cell.
+ * @param cellBounds the bounds of the cell to click in. These bounds must
+ * be relative to the table's location.
+ * @return the visible cell bounds, relative to the table's location.
+ */
+ private Rectangle getVisibleBounds(Rectangle cellBounds) {
+ org.eclipse.swt.graphics.Rectangle r =
+ (org.eclipse.swt.graphics.Rectangle)
+ getEventThreadQueuer().invokeAndWait("getVisibleCellBounds: " + cellBounds, //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() {
+ return m_table.getClientArea();
+ }
+ });
+
+ Rectangle visibleTableBounds = new Rectangle(
+ r.x, r.y, r.width, r.height);
+ Rectangle visibleCellBounds =
+ visibleTableBounds.intersection(cellBounds);
+ return visibleCellBounds;
+ }
+
+ /**
+ * @param cellEditor The cell editor to check.
+ * @return <code>true</code> if the given cell editor is editable.
+ */
+ private boolean isEditable(Control cellEditor) {
+
+ if (cellEditor == null || cellEditor instanceof TableCursor
+ || cellEditor == m_table) {
+ // No actual editor found.
+ return false;
+ }
+
+ return (cellEditor.getStyle() & SWT.READ_ONLY) == 0;
+ }
+
+ /**
+ * @param cellEditor The cell editor to check.
+ * @return <code>true</code> if the given editor is editable. Otherwise
+ * <code>false</code>.
+ */
+ private boolean invokeIsEditable(final Control cellEditor) {
+
+ boolean isEditable = ((Boolean)getEventThreadQueuer().invokeAndWait(
+ "getSelectedCell", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return isEditable(cellEditor)
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ })).booleanValue();
+ return isEditable;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object activateEditor(final Cell cell) {
+
+ Rectangle rect = scrollCellToVisible(cell.getRow(), cell.getCol());
+ Control editor = getTableCellEditor(cell, rect);
+ // sometimes the editor only appears after doubleclick!
+
+ if (!invokeIsEditable(editor)) {
+ org.eclipse.swt.graphics.Rectangle cellBounds =
+ new org.eclipse.swt.graphics.Rectangle(
+ rect.x, rect.y, rect.width, rect.height);
+ ClickOptions co = ClickOptions.create().setClickCount(2);
+ Control clickTarget = editor == null
+ || editor instanceof TableCursor ? m_table : editor;
+ getRobot().click(clickTarget, cellBounds, co);
+ editor = getTableCellEditor(cell, rect);
+ }
+
+ return editor;
+
+ }
+ /**
+ * Gets the TableCellEditor of the given cell.
+ * The Cell has to be activated before!
+ * @param cell the cell.
+ * @param rect
+ * @return the TableCellEditor
+ */
+ private Control getTableCellEditor(final Cell cell, Rectangle rect) {
+ org.eclipse.swt.graphics.Rectangle swtRect =
+ new org.eclipse.swt.graphics.Rectangle(rect.x, rect.y,
+ rect.width, rect.height);
+ getRobot().click(m_table,
+ swtRect,
+ ClickOptions.create().setClickCount(1));
+
+
+ return SwtUtils.getCursorControl();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ final Cell selectedCell = getSelectedCell();
+ return getCellText(selectedCell.getRow(), selectedCell.getCol());
+ }
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TextComponentAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TextComponentAdapter.java
new file mode 100644
index 000000000..1d1a55e25
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TextComponentAdapter.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.logger.AutServerLogger;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITextComponentAdapter;
+import org.eclipse.jubula.tools.utils.EnvironmentUtils;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Implementation of the Interface <code>ITextComponentAdapter</code> as a
+ * adapter for the <code>Text</code> component.
+ * @author BREDEX GmbH
+ *
+ */
+public class TextComponentAdapter extends WidgetAdapter implements
+ ITextComponentAdapter {
+
+ /** the logger */
+ private static AutServerLogger log = new AutServerLogger(
+ TextComponentAdapter.class);
+
+ /** */
+ private Text m_textComponent;
+ /**
+ *
+ * @param objectToAdapt
+ */
+ public TextComponentAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ m_textComponent = (Text) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ String actual = (String)getEventThreadQueuer().invokeAndWait(
+ "getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_textComponent.getText();
+ }
+ });
+ return actual;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSelection(final int start) {
+ getEventThreadQueuer().invokeAndWait("setSelection", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ m_textComponent.setSelection(start);
+ return null;
+ }
+ });
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSelection(final int start, final int end) {
+ getEventThreadQueuer().invokeAndWait("setSelection", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ m_textComponent.setSelection(start, end);
+ return null;
+ }
+ });
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSelectionText() {
+ String actual = (String)getEventThreadQueuer().invokeAndWait(
+ "getText", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_textComponent.getSelectionText();
+ }
+ });
+ return actual;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void selectAll() {
+ final String totalText = getText();
+
+ // fix for https://bxapps.bredex.de/bugzilla/show_bug.cgi?id=201
+ // The keystroke "command + a" sometimes causes an "a" to be entered
+ // into the text field instead of selecting all text (or having no
+ // effect).
+ if (!EnvironmentUtils.isMacOS()) {
+ try {
+ getRobot().keyStroke(getRobot().getSystemModifierSpec() + " A"); //$NON-NLS-1$
+ } catch (StepExecutionException see) {
+ /*This might happen under certain circumstances e.g. on MacOS X see
+ bug 342691 */
+ log.warn(see);
+ }
+ }
+
+ if (!totalText.equals(getSelectionText())) {
+ // the selection failed for some reason
+ getEventThreadQueuer().invokeAndWait("text.selectAll", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ m_textComponent.selectAll();
+ return null;
+ }
+ });
+ }
+
+ String selectionText = getSelectionText();
+ if (!totalText.equals(selectionText)) {
+ log.warn("SelectAll failed!\n" //$NON-NLS-1$
+ + "Total text: '" + totalText + "'\n" //$NON-NLS-1$//$NON-NLS-2$
+ + "Selected text: '" + selectionText + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEditable() {
+ return ((Boolean)getEventThreadQueuer().invokeAndWait(
+ "isEditable", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() {
+ return m_textComponent.getEditable()
+ && m_textComponent.getEnabled()
+ ? Boolean.TRUE : Boolean.FALSE; // see findBugs
+ }
+ })).booleanValue();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TreeAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TreeAdapter.java
new file mode 100644
index 000000000..7b78f2dc4
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TreeAdapter.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeOperationContext;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITreeAdapter;
+import org.eclipse.jubula.rc.swt.implclasses.TreeOperationContext;
+import org.eclipse.swt.widgets.Tree;
+/**
+ * Implements the Tree interface for adapting a <code>SWT.Tree</code>
+ *
+ * @author BREDEX GmbH
+ */
+public class TreeAdapter extends WidgetAdapter implements ITreeAdapter {
+
+
+ /**
+ *
+ * @param objectToAdapt graphics component which will be adapted
+ */
+ public TreeAdapter(Object objectToAdapt) {
+ super(objectToAdapt);
+ }
+ /**
+ *
+ * @return the caste object
+ */
+ private Tree getTree() {
+ return (Tree) getRealComponent();
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public Object getRootNode() {
+ return getEventThreadQueuer()
+ .invokeAndWait("getRootNode", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return getTree().getItems();
+ }
+ });
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public AbstractTreeOperationContext getContext() {
+ return new TreeOperationContext(getEventThreadQueuer(),
+ getRobot(), getTree());
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isRootVisible() {
+
+ return true;
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/WidgetAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/WidgetAdapter.java
new file mode 100644
index 000000000..71888de82
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/WidgetAdapter.java
@@ -0,0 +1,420 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter;
+
+import org.eclipse.jubula.rc.common.AUTServer;
+import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
+import org.eclipse.jubula.rc.common.caps.AbstractWidgetCAPs;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.driver.RobotTiming;
+import org.eclipse.jubula.rc.common.exception.RobotException;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.listener.EventLock;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IWidgetAdapter;
+import org.eclipse.jubula.rc.swt.driver.KeyCodeConverter;
+import org.eclipse.jubula.rc.swt.caps.CAPUtil;
+import org.eclipse.jubula.rc.swt.caps.MenuCAPs;
+import org.eclipse.jubula.rc.swt.driver.DragAndDropHelperSwt;
+import org.eclipse.jubula.rc.swt.driver.EventThreadQueuerSwtImpl;
+import org.eclipse.jubula.rc.swt.implclasses.EventListener;
+import org.eclipse.jubula.rc.swt.implclasses.SimulatedTooltip;
+import org.eclipse.jubula.rc.swt.utils.SwtUtils;
+import org.eclipse.jubula.tools.constants.TimeoutConstants;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Widget;
+/**
+ * Implements the interface for widgets and supports basic methods
+ * which are needed for nearly a lot of components.
+ *
+ * @author BREDEX GmbH
+ */
+public abstract class WidgetAdapter extends AbstractComponentAdapter
+ implements IWidgetAdapter {
+
+ /** constants for communication */
+ protected static final String POS_UNIT_PIXEL = "Pixel"; //$NON-NLS-1$
+ /** constants for communication */
+ protected static final String POS_UNI_PERCENT = "Percent"; //$NON-NLS-1$
+
+
+ /** */
+ private Control m_component;
+
+ /**
+ * Is true, if a popup menu is shown
+ */
+ protected static class PopupShownCondition implements
+ EventListener.Condition {
+
+ /**
+ * the popup menu
+ */
+ private Menu m_popup = null;
+
+ /**
+ *
+ * @return the popup menu
+ */
+ public Menu getPopup() {
+ return m_popup;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param event event
+ * @return result of the condition
+ */
+ public boolean isTrue(Event event) {
+
+ if (event.type == SWT.Show && event.widget instanceof Menu) {
+ m_popup = (Menu)event.widget;
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ *
+ * @param objectToAdapt
+ */
+ protected WidgetAdapter(Object objectToAdapt) {
+ m_component = (Control) objectToAdapt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getRealComponent() {
+ return m_component;
+ }
+
+ /**
+ * Gets the Robot.
+ * @return The Robot
+ * @throws RobotException If the Robot cannot be created.
+ */
+ protected IRobot getRobot() throws RobotException {
+ return AUTServer.getInstance().getRobot();
+ }
+ /**
+ * @return The event thread queuer.
+ */
+ public IEventThreadQueuer getEventThreadQueuer() {
+ return getRobotFactory().getEventThreadQueuer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getPropteryValue(final String propertyname) {
+ Object prop = getEventThreadQueuer().invokeAndWait("getProperty", //$NON-NLS-1$
+ new IRunnable() {
+ public Object run() throws StepExecutionException {
+ try {
+ return getRobot().getPropertyValue(
+ getRealComponent(), propertyname);
+ } catch (RobotException e) {
+ throw new StepExecutionException(
+ e.getMessage(),
+ EventFactory.createActionError(
+ TestErrorEvent.PROPERTY_NOT_ACCESSABLE));
+ }
+ }
+ });
+ return String.valueOf(prop);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isShowing() {
+ Boolean actual = (Boolean)getEventThreadQueuer()
+ .invokeAndWait("isShowing", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_component.isVisible()
+ ? Boolean.TRUE : Boolean.FALSE; // see findBugs;
+ }
+ });
+ return actual.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnabled() {
+
+ Boolean actual = (Boolean)getEventThreadQueuer()
+ .invokeAndWait("isEnabled", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_component.isEnabled()
+ ? Boolean.TRUE : Boolean.FALSE; // see findBugs;
+ }
+ });
+ return actual.booleanValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasFocus() {
+ Boolean actual = (Boolean)getEventThreadQueuer()
+ .invokeAndWait("hasFocus", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ return m_component.isFocusControl()
+ ? Boolean.TRUE : Boolean.FALSE; // see findBugs;
+ }
+ });
+ return actual.booleanValue();
+ }
+
+ /**
+ * Shows and returns the popup menu
+ * @param button MouseButton
+ * @return the popup menu
+ */
+ public AbstractMenuCAPs showPopup(
+ final int button) {
+ final Widget component = m_component;
+ if (SwtUtils.isMouseCursorInWidget(component)) {
+ return showPopup(component, new Runnable() {
+ public void run() {
+ RobotTiming.sleepPreShowPopupDelay();
+
+ getRobot().clickAtCurrentPosition(component, 1,
+ button);
+ }
+ });
+ }
+ return showPopup(50, POS_UNI_PERCENT, 50,
+ POS_UNI_PERCENT, button);
+ }
+
+ /**
+ * Shows and returns the popup menu
+ *
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param button MouseButton
+ * @return the popup menu
+ * @throws StepExecutionException error
+ */
+ public AbstractMenuCAPs showPopup(
+ final int xPos, final String xUnits,
+ final int yPos, final String yUnits,
+ final int button) throws StepExecutionException {
+ final Widget component = m_component;
+ return showPopup(component, new Runnable() {
+ public void run() {
+ RobotTiming.sleepPreShowPopupDelay();
+ boolean isAbsoluteUnitsX =
+ POS_UNIT_PIXEL.equalsIgnoreCase(
+ xUnits);
+ boolean isAbsoluteUnitsY =
+ POS_UNIT_PIXEL.equalsIgnoreCase(
+ yUnits);
+ getRobot().click(component, null,
+ ClickOptions.create().setClickCount(1)
+ .setMouseButton(button),
+ xPos, isAbsoluteUnitsX, yPos, isAbsoluteUnitsY);
+ }
+ });
+ }
+
+ /**
+ * Shows and returns the popup menu
+ *
+ * @param component The component for which to open the popup menu.
+ * @param showPopup A <code>Runnable</code> that, when run, should display
+ * a popup menu for the given component.
+ * @return the popup menu
+ * @throws StepExecutionException error
+ */
+ private AbstractMenuCAPs showPopup(final Widget component,
+ final Runnable showPopup) throws StepExecutionException {
+
+ PopupShownCondition cond = new PopupShownCondition();
+ EventLock lock = new EventLock();
+ final EventListener listener = new EventListener(lock, cond);
+ final Display d = component.getDisplay();
+ final IEventThreadQueuer queuer = new EventThreadQueuerSwtImpl();
+
+ queuer.invokeAndWait("addPopupShownListeners", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ d.addFilter(SWT.Show, listener);
+
+ return null;
+ }
+ });
+
+ try {
+ // showPopup must run in the current thread in order to
+ // avoid a race condition.
+ showPopup.run();
+
+ synchronized (lock) {
+ long timeout = TimeoutConstants.SERVER_TIMEOUT_WAIT_FOR_POPUP;
+ long done = System.currentTimeMillis() + timeout;
+ long now;
+ while (!lock.isReleased() && (timeout > 0)) {
+ lock.wait(timeout);
+ now = System.currentTimeMillis();
+ timeout = done - now;
+ }
+ }
+ } catch (InterruptedException e) {
+ // ignore
+ } finally {
+ queuer.invokeAndWait("removePopupShownListeners", new IRunnable() { //$NON-NLS-1$
+ public Object run() {
+ d.removeFilter(SWT.Show, listener);
+
+ return null;
+ }
+ });
+ }
+ if (!lock.isReleased()) {
+ throw new StepExecutionException("popup not shown", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.POPUP_NOT_FOUND));
+ }
+
+ MenuCAPs contextMenu = new MenuCAPs();
+ contextMenu.setComponent(cond.getPopup());
+ contextMenu.setContextMenu(true);
+ return contextMenu;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void showToolTip(final String text, final int textSize,
+ final int timePerWord, final int windowWidth) {
+
+ final Rectangle bounds = (Rectangle)getEventThreadQueuer()
+ .invokeAndWait("gdShowText.getBounds", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() {
+ return SwtUtils.getWidgetBounds(m_component);
+ }
+ });
+
+ SimulatedTooltip sp = (SimulatedTooltip)getEventThreadQueuer()
+ .invokeAndWait("gdShowText.initToolTip", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ return new SimulatedTooltip(timePerWord, text,
+ windowWidth, textSize, bounds);
+ }
+
+ });
+ sp.start();
+ try {
+ sp.join();
+ } catch (InterruptedException e) {
+ throw new StepExecutionException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDrag(int mouseButton, String modifier, int xPos,
+ String xUnits, int yPos, String yUnits) {
+ // Only store the Drag-Information. Otherwise the GUI-Eventqueue
+ // blocks after performed Drag!
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ dndHelper.setMouseButton(mouseButton);
+ dndHelper.setModifier(modifier);
+ dndHelper.setDragComponent(null);
+ clickDirect(0, mouseButton, xPos, xUnits, yPos, yUnits);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void gdDrop(final int xPos, final String xUnits, final int yPos,
+ final String yUnits, int delayBeforeDrop) {
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ final IRobot robot = getRobot();
+ final String modifier = dndHelper.getModifier();
+ final int mouseButton = dndHelper.getMouseButton();
+ // Note: This method performs the drag AND drop action in one runnable
+ // in the GUI-Eventqueue because after the mousePress, the eventqueue
+ // blocks!
+ try {
+ CAPUtil.pressOrReleaseModifiers(modifier, true);
+
+ getEventThreadQueuer().invokeAndWait("gdStartDrag", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ // drag
+ robot.mousePress(dndHelper.getDragComponent(), null,
+ mouseButton);
+
+ CAPUtil.shakeMouse();
+
+ // drop
+ clickDirect(0, mouseButton, xPos, xUnits, yPos, yUnits);
+ return null;
+ }
+ });
+
+ AbstractWidgetCAPs.waitBeforeDrop(delayBeforeDrop);
+ } finally {
+ getRobot().mouseRelease(null, null, mouseButton);
+ CAPUtil.pressOrReleaseModifiers(modifier, false);
+ }
+ }
+
+ /**
+ * clicks into a component.
+ * @param count amount of clicks
+ * @param button what button should be clicked
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @throws StepExecutionException error
+ */
+ protected void clickDirect(int count, int button, int xPos, String xUnits,
+ int yPos, String yUnits)
+ throws StepExecutionException {
+
+ getRobot().click(
+ m_component,
+ null,
+ ClickOptions.create().setClickCount(count).setMouseButton(
+ button), xPos, xUnits.equalsIgnoreCase(POS_UNIT_PIXEL),
+ yPos, yUnits.equalsIgnoreCase(POS_UNIT_PIXEL));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getKeyCode(String mod) {
+ return KeyCodeConverter.getKeyCode(mod);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/factory/SWTAdapterFactory.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/factory/SWTAdapterFactory.java
new file mode 100644
index 000000000..0f9e24d16
--- /dev/null
+++ b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/factory/SWTAdapterFactory.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2012 BREDEX GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BREDEX GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.swt.uiadapter.factory;
+
+import org.eclipse.jubula.rc.common.uiadapter.factory.IUIAdapterFactory;
+import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.ButtonAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.CComboAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.CLabelAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.CTabFolderAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.ComboAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.LabelAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.ListAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.MenuAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.MenuItemAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.StyledTextAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.TabFolderAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.TableAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.TextComponentAdapter;
+import org.eclipse.jubula.rc.swt.uiadapter.TreeAdapter;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+
+/**
+ * This factory constructs the specific adapter out of the incoming
+ * graphics component from the AUT.
+ *
+ * @author BREDEX GmbH
+ */
+public class SWTAdapterFactory implements IUIAdapterFactory {
+ /** */
+ private static final Class[] SUPPORTEDCLASSES =
+ new Class[]{Button.class, Menu.class, MenuItem.class, Tree.class,
+ Table.class, List.class, Text.class, StyledText.class,
+ Combo.class, CCombo.class, Label.class, CLabel.class,
+ TabFolder.class, CTabFolder.class};
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Class[] getSupportedClasses() {
+ return SUPPORTEDCLASSES;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IComponentAdapter getAdapter(Object objectToAdapt) {
+ IComponentAdapter returnvalue = null;
+ if (objectToAdapt instanceof Button) {
+ returnvalue = new ButtonAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof Menu) {
+ returnvalue = new MenuAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof MenuItem) {
+ returnvalue = new MenuItemAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof Tree) {
+ returnvalue = new TreeAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof Table) {
+ returnvalue = new TableAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof List) {
+ returnvalue = new ListAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof Text) {
+ returnvalue = new TextComponentAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof StyledText) {
+ returnvalue = new StyledTextAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof Combo) {
+ returnvalue = new ComboAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof CCombo) {
+ returnvalue = new CComboAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof Label) {
+ returnvalue = new LabelAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof CLabel) {
+ returnvalue = new CLabelAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof TabFolder) {
+ returnvalue = new TabFolderAdapter(objectToAdapt);
+ } else if (objectToAdapt instanceof CTabFolder) {
+ returnvalue = new CTabFolderAdapter(objectToAdapt);
+ }
+
+ return returnvalue;
+ }
+
+}
diff --git a/org.eclipse.jubula.toolkit.provider.swing/resources/xml/ComponentConfiguration.xml b/org.eclipse.jubula.toolkit.provider.swing/resources/xml/ComponentConfiguration.xml
index bd116a528..2d0aafee2 100644
--- a/org.eclipse.jubula.toolkit.provider.swing/resources/xml/ComponentConfiguration.xml
+++ b/org.eclipse.jubula.toolkit.provider.swing/resources/xml/ComponentConfiguration.xml
@@ -27,7 +27,7 @@
<toolkitComponent type="javax.swing.AbstractButton" visible="false">
<realizes>guidancer.concrete.Button</realizes>
- <testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.AbstractButtonImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swing.swing.caps.AbstractButtonCAPs</testerClass>
<componentClass name="javax.swing.AbstractButton" />
</toolkitComponent>
@@ -36,49 +36,49 @@
<typeFactory>org.eclipse.jubula.rc.common.implclasses.DefaultComponentFactory</typeFactory>
</defaultMapping>
<realizes>guidancer.concrete.MenuBar</realizes>
- <testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JMenuBarImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swing.swing.caps.JMenuBarCAPs</testerClass>
<componentClass name="com.bredexsw.guidancer.autserver.swing.implclasses.JMenuBarDefaultMapping" />
</toolkitComponent>
<toolkitComponent type="javax.swing.JComboBox" visible="false">
<realizes>guidancer.concrete.ComboBox</realizes>
- <testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JComboBoxImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.AbstractComboBoxCAPs</testerClass>
<componentClass name="javax.swing.JComboBox" />
</toolkitComponent>
<toolkitComponent type="javax.swing.JList" visible="false">
<realizes>guidancer.concrete.List</realizes>
- <testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JListImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swing.swing.caps.JListCAPs</testerClass>
<componentClass name="javax.swing.JList" />
</toolkitComponent>
<toolkitComponent type="javax.swing.JLabel" visible="false">
<realizes>guidancer.concrete.Label</realizes>
- <testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JLabelImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.LabelCAPs</testerClass>
<componentClass name="javax.swing.JLabel" />
</toolkitComponent>
<toolkitComponent type="javax.swing.JTabbedPane" visible="false">
<realizes>guidancer.concrete.TabbedPane</realizes>
- <testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JTabbedPaneImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.TabbedPaneCAPs</testerClass>
<componentClass name="javax.swing.JTabbedPane" />
</toolkitComponent>
<toolkitComponent type="javax.swing.JTable" visible="false">
<realizes>guidancer.concrete.Table</realizes>
- <testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JTableImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swing.swing.caps.JTableCAPs</testerClass>
<componentClass name="javax.swing.JTable" />
</toolkitComponent>
<toolkitComponent type="javax.swing.text.JTextComponent" visible="false">
<realizes>guidancer.concrete.TextComponent</realizes>
- <testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JTextComponentImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.AbstractTextComponent</testerClass>
<componentClass name="javax.swing.text.JTextComponent" />
</toolkitComponent>
<toolkitComponent type="javax.swing.JTree" visible="false">
<realizes>guidancer.concrete.Tree</realizes>
- <testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JTreeImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swing.swing.caps.JTreeCAPs</testerClass>
<componentClass name="javax.swing.JTree" />
</toolkitComponent>
diff --git a/org.eclipse.jubula.toolkit.provider.swt/resources/xml/ComponentConfiguration.xml b/org.eclipse.jubula.toolkit.provider.swt/resources/xml/ComponentConfiguration.xml
index 069572474..1e2594078 100644
--- a/org.eclipse.jubula.toolkit.provider.swt/resources/xml/ComponentConfiguration.xml
+++ b/org.eclipse.jubula.toolkit.provider.swt/resources/xml/ComponentConfiguration.xml
@@ -160,31 +160,31 @@
<toolkitComponent type="org.eclipse.swt.widgets.Label" visible="false">
<realizes>guidancer.abstract.SwtLabel</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.LabelImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.LabelCAPs</testerClass>
<componentClass name="org.eclipse.swt.widgets.Label" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.custom.CLabel" visible="false">
<realizes>guidancer.abstract.SwtLabel</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.CLabelImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.LabelCAPs</testerClass>
<componentClass name="org.eclipse.swt.custom.CLabel" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.widgets.Text" visible="false">
<realizes>guidancer.abstract.SwtText</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.TextImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.AbstractTextComponent</testerClass>
<componentClass name="org.eclipse.swt.widgets.Text" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.custom.StyledText" visible="false">
<realizes>guidancer.abstract.SwtText</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.StyledTextImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.AbstractTextComponent</testerClass>
<componentClass name="org.eclipse.swt.custom.StyledText" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.widgets.Button" visible="false">
<realizes>guidancer.abstract.SwtButton</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.ButtonImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swt.caps.ButtonCAPs</testerClass>
<componentClass name="org.eclipse.swt.widgets.Button" />
</toolkitComponent>
@@ -203,49 +203,49 @@
<typeFactory>org.eclipse.jubula.rc.common.implclasses.DefaultComponentFactory</typeFactory>
</defaultMapping>
<realizes>guidancer.concrete.MenuBar</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.MenuImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swt.caps.MenuCAPs</testerClass>
<componentClass name="com.bredexsw.guidancer.autswtserver.implclasses.MenuDefaultMapping" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.widgets.Combo" visible="false">
<realizes>guidancer.abstract.SwtCombo</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.ComboImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.AbstractComboBoxCAPs</testerClass>
<componentClass name="org.eclipse.swt.widgets.Combo" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.custom.CCombo" visible="false">
<realizes>guidancer.abstract.SwtCombo</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.CComboImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.AbstractComboBoxCAPs</testerClass>
<componentClass name="org.eclipse.swt.custom.CCombo" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.widgets.List" visible="false">
<realizes>guidancer.concrete.List</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.ListImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swt.caps.ListCAPs</testerClass>
<componentClass name="org.eclipse.swt.widgets.List" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.widgets.TabFolder" visible="false">
<realizes>guidancer.abstract.SwtTabFolder</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.TabFolderImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.TabbedPaneCAPs</testerClass>
<componentClass name="org.eclipse.swt.widgets.TabFolder" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.custom.CTabFolder" visible="false">
<realizes>guidancer.abstract.SwtTabFolder</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.CTabFolderImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.common.caps.TabbedPaneCAPs</testerClass>
<componentClass name="org.eclipse.swt.custom.CTabFolder" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.widgets.Table" visible="false">
<realizes>guidancer.concrete.Table</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.TableImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swt.caps.TableCAPs</testerClass>
<componentClass name="org.eclipse.swt.widgets.Table" />
</toolkitComponent>
<toolkitComponent type="org.eclipse.swt.widgets.Tree" observable="false">
<realizes>guidancer.concrete.Tree</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.TableTreeImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swt.caps.TreeCAPs</testerClass>
<componentClass name="org.eclipse.swt.widgets.Tree" />
<action name="CompSystem.VerifyCheckboxOfSelectedEntry" changed="4.1">
<method>gdVerifySelectedCheckbox</method>
@@ -370,7 +370,7 @@
<toolkitComponent type="org.eclipse.swt.widgets.SwtTree">
<realizes>org.eclipse.swt.widgets.Tree</realizes>
- <testerClass>org.eclipse.jubula.rc.swt.implclasses.TableTreeImplClass</testerClass>
+ <testerClass>org.eclipse.jubula.rc.swt.caps.TreeCAPs</testerClass>
<componentClass name="org.eclipse.swt.widgets.Tree" />
<action name="CompSystem.SelectByTextPathAtColumn" changed="1.22">
<method>gdSelect</method>

Back to the top