Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 224096 Details for
Bug 394179
Enhancement: Refactoring and generalization of the RC Swing and SWT
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
Implementing the testability of ComboBoxes (Swing and SWT)
ComboBoxes.patch (text/plain), 70.74 KB, created by
Marvin Mueller
on 2012-11-29 06:13:38 EST
(
hide
)
Description:
Implementing the testability of ComboBoxes (Swing and SWT)
Filename:
MIME Type:
Creator:
Marvin Mueller
Created:
2012-11-29 06:13:38 EST
Size:
70.74 KB
patch
obsolete
>From e1b4cd6d9301e4a14264041203d37acd33185908 Mon Sep 17 00:00:00 2001 >From: Marvin Mueller <marvin.mueller@bredex.de> >Date: Mon, 26 Nov 2012 16:35:02 +0100 >Subject: [PATCH] Generalizing ComboBoxes > >--- > .../rc/common/caps/AbstractComboBoxCAPs.java | 180 +++++++++ > .../jubula/rc/common/caps/AbstractUICAPs.java | 5 + > .../uiadapter/interfaces/IComboBoxAdapter.java | 79 ++++ > .../jubula/rc/swing/swing/caps/CapUtil.java | 60 ++- > .../rc/swing/swing/uiadapter/JComboBoxAdapter.java | 405 +++++++++++++++++++++ > .../uiadapter/factory/SwingAdapterFactory.java | 7 +- > .../rc/swt/uiadapter/AbstractComboBoxAdapter.java | 318 ++++++++++++++++ > .../jubula/rc/swt/uiadapter/CComboAdapter.java | 355 ++++++++++++++++++ > .../jubula/rc/swt/uiadapter/ComboAdapter.java | 196 ++++++++++ > .../jubula/rc/swt/uiadapter/WidgetAdapter.java | 10 +- > .../swt/uiadapter/factory/SWTAdapterFactory.java | 11 +- > .../resources/xml/ComponentConfiguration.xml | 2 +- > .../resources/xml/ComponentConfiguration.xml | 4 +- > 13 files changed, 1620 insertions(+), 12 deletions(-) > create mode 100644 org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractComboBoxCAPs.java > create mode 100644 org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComboBoxAdapter.java > create mode 100644 org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JComboBoxAdapter.java > create mode 100644 org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/AbstractComboBoxAdapter.java > create mode 100644 org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CComboAdapter.java > create mode 100644 org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ComboAdapter.java > >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 0000000..d8ba160 >--- /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/AbstractUICAPs.java b/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractUICAPs.java >index 6680c38..ddf4ebe 100644 >--- 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 >@@ -18,6 +18,7 @@ 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. >@@ -33,6 +34,10 @@ public abstract class AbstractUICAPs implements IBaseImplementationClass { > /** 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; > >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 0000000..0b02704 >--- /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.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 >index ac2e378..e46fde6 100644 >--- 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 >@@ -27,9 +27,13 @@ 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; >@@ -100,6 +104,12 @@ public class CapUtil { > return false; > } > } >+ >+ /** >+ * The robot factory. >+ */ >+ private static IRobotFactory robotFactory; >+ > /** > * > */ >@@ -113,7 +123,24 @@ public class CapUtil { > 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. >@@ -136,6 +163,37 @@ public class CapUtil { > } > > /** >+ * 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. >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 0000000..3619c97 >--- /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/factory/SwingAdapterFactory.java b/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/factory/SwingAdapterFactory.java >index 8a3c387..052437e 100644 >--- 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 >@@ -13,6 +13,7 @@ package org.eclipse.jubula.rc.swing.swing.uiadapter.factory; > > import javax.swing.JButton; > import javax.swing.JCheckBox; >+import javax.swing.JComboBox; > import javax.swing.JList; > import javax.swing.JMenuBar; > import javax.swing.JMenuItem; >@@ -25,6 +26,7 @@ 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.JListAdapter; > import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuBarAdapter; > import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuItemAdapter; >@@ -50,7 +52,7 @@ public class SwingAdapterFactory implements IUIAdapterFactory { > JButton.class, JCheckBox.class, JRadioButton.class, > JMenuBar.class, JMenuItem.class, JTree.class , > JCheckBox.class, JRadioButton.class, JTable.class, JPopupMenu.class, >- JList.class, JTextComponent.class}; >+ JList.class, JTextComponent.class, JComboBox.class}; > > /** > * {@inheritDoc} >@@ -95,6 +97,9 @@ public class SwingAdapterFactory implements IUIAdapterFactory { > } else if (objectToAdapt instanceof JTextComponent) { > returnvalue = new JTextComponentAdapter(objectToAdapt); > >+ } else if (objectToAdapt instanceof JComboBox) { >+ returnvalue = new JComboBoxAdapter(objectToAdapt); >+ > } > > return returnvalue; >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 0000000..9ca0e57 >--- /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/CComboAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CComboAdapter.java >new file mode 100644 >index 0000000..5ce6513 >--- /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/ComboAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ComboAdapter.java >new file mode 100644 >index 0000000..484ea7a >--- /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/WidgetAdapter.java b/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/WidgetAdapter.java >index da7a13a..71888de 100644 >--- 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 >@@ -10,6 +10,7 @@ > *******************************************************************************/ > 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; >@@ -107,16 +108,13 @@ public abstract class WidgetAdapter extends AbstractComponentAdapter > return m_component; > } > >- > /** >- * Gets the Robot >- * >+ * Gets the Robot. > * @return The Robot >- * @throws RobotException >- * If the Robot cannot be created. >+ * @throws RobotException If the Robot cannot be created. > */ > protected IRobot getRobot() throws RobotException { >- return getRobotFactory().getRobot(); >+ return AUTServer.getInstance().getRobot(); > } > /** > * @return The event thread queuer. >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 >index 4079a78..0957634 100644 >--- 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 >@@ -13,6 +13,8 @@ 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.ComboAdapter; > import org.eclipse.jubula.rc.swt.uiadapter.ListAdapter; > import org.eclipse.jubula.rc.swt.uiadapter.MenuAdapter; > import org.eclipse.jubula.rc.swt.uiadapter.MenuItemAdapter; >@@ -20,8 +22,10 @@ import org.eclipse.jubula.rc.swt.uiadapter.StyledTextAdapter; > 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.StyledText; > import org.eclipse.swt.widgets.Button; >+import org.eclipse.swt.widgets.Combo; > import org.eclipse.swt.widgets.List; > import org.eclipse.swt.widgets.Menu; > import org.eclipse.swt.widgets.MenuItem; >@@ -39,7 +43,8 @@ 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}; >+ Table.class, List.class, Text.class, StyledText.class, >+ Combo.class, CCombo.class}; > > > /** >@@ -70,6 +75,10 @@ public class SWTAdapterFactory implements IUIAdapterFactory { > 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); > } > > >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 30abd14..c20f598 100644 >--- a/org.eclipse.jubula.toolkit.provider.swing/resources/xml/ComponentConfiguration.xml >+++ b/org.eclipse.jubula.toolkit.provider.swing/resources/xml/ComponentConfiguration.xml >@@ -42,7 +42,7 @@ > > <toolkitComponent type="javax.swing.JComboBox" visible="false"> > <realizes>guidancer.concrete.ComboBox</realizes> >- <testerClass>org.eclipse.jubula.rc.swing.swing.caps.JComboBoxCAPs</testerClass> >+ <testerClass>org.eclipse.jubula.rc.common.caps.AbstractComboBoxCAPs</testerClass> > <componentClass name="javax.swing.JComboBox" /> > </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 9978b8c..5896921 100644 >--- a/org.eclipse.jubula.toolkit.provider.swt/resources/xml/ComponentConfiguration.xml >+++ b/org.eclipse.jubula.toolkit.provider.swt/resources/xml/ComponentConfiguration.xml >@@ -209,13 +209,13 @@ > > <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> > >-- >1.7.11 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 394179
:
223499
|
223848
|
223948
|
223950
|
224096
|
224662
|
225163