Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 394179 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractComboBoxCAPs.java (+180 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2012 BREDEX GmbH.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     BREDEX GmbH - initial API and implementation 
10
 *******************************************************************************/
11
package org.eclipse.jubula.rc.common.caps;
12
13
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
14
import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
15
import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
16
import org.eclipse.jubula.rc.common.implclasses.Verifier;
17
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComboBoxAdapter;
18
import org.eclipse.jubula.tools.constants.TestDataConstants;
19
import org.eclipse.jubula.tools.utils.StringParsing;
20
21
/**
22
 * General implementation for ComboBoxes and ComboBox like components.
23
 * @author BREDEX GmbH
24
 *
25
 */
26
public class AbstractComboBoxCAPs extends AbstractTextInputSupport {
27
28
    /** The dafault separator of a list of values */
29
    public static final char VALUE_SEPARATOR =
30
        TestDataConstants.VALUE_CHAR_DEFAULT;
31
    
32
    /**
33
     * 
34
     * @return the <code>IComboBoxAdapter</code>
35
     */
36
    private IComboBoxAdapter getCBAdapter() {
37
        return (IComboBoxAdapter) getComponent();
38
    }
39
    
40
    
41
    /**
42
     * {@inheritDoc}
43
     */
44
    public String[] getTextArrayFromComponent() {
45
        return null;
46
    }
47
48
    /**
49
     * Verifies the editable property. 
50
     * @param editable The editable property to verify.
51
     */
52
    public void gdVerifyEditable(boolean editable) {
53
        Verifier.equals(editable, getCBAdapter().isEditable());
54
    }
55
    
56
    /**
57
     * Checks if the component contains the specified text.
58
     * @param text check if this text is in the combobox
59
     */
60
    public void gdVerifyContainsValue(final String text) {
61
        Verifier.equals(true, getCBAdapter().containsValue(text));
62
    }
63
    
64
    /**
65
     * Verifies if the list contains an element that renderes <code>value</code>.
66
     * @param value The text to verify
67
     * @param operator The operator used to verify
68
     * @param exists If the value should exist or not.
69
     */
70
    public void gdVerifyContainsValue(String value, String operator, 
71
            boolean exists) {        
72
        final boolean contains = getCBAdapter().containsValue(value, operator);
73
        Verifier.equals(exists, contains);
74
    }
75
    
76
    /**
77
     * @see org.eclipse.jubula.rc.swing.swing.implclasses.AbstractSwingImplClass#getText()
78
     * @return value from ComboBoxHelper
79
     */
80
    protected String getText() {
81
        return getCBAdapter().getText();
82
    }
83
    
84
    /**
85
     * {@inheritDoc}
86
     */
87
    public void gdInputText(String text) {        
88
        getCBAdapter().input(text, false);
89
    }
90
   
91
    /**
92
     * {@inheritDoc}
93
     */
94
    public void gdReplaceText(String text) throws StepExecutionException {
95
        getCBAdapter().input(text, true);
96
    }
97
    
98
    /**
99
     * Selects <code>index</code> in the combobox.
100
     *
101
     * @param index
102
     *            The index to select
103
     */
104
    public void gdSelectIndex(String index) {
105
        int implIdx = IndexConverter.toImplementationIndex(
106
                IndexConverter.intValue(index)); 
107
        getCBAdapter().select(implIdx);
108
109
    }
110
    
111
    /**
112
     * Selects a value from the list of the combobox
113
     * @param valueList The value or list of values to (not)select
114
     * @param operator if regular expressions are used
115
     * @param searchType Determines where the search begins ("relative" or "absolute")
116
     */
117
    public void gdSelectValue(String valueList, String operator,
118
        final String searchType) {
119
        gdSelectValue(valueList, String.valueOf(VALUE_SEPARATOR), operator,
120
            searchType);
121
    }
122
    
123
    /**
124
     * Selects a value from the list of the combobox
125
     *
126
     * @param valueList
127
     *            the item(s) which should be (not)selected.
128
     * @param separator
129
     *            The seperator if <code>text</code> is an enumeration of
130
     *            values. Not supported by this implementation class
131
     * @param operator
132
     *            if regular expressions are used
133
     * @param searchType
134
     *            Determines where the search begins ("relative" or "absolute")
135
     */
136
    private void gdSelectValue(String valueList, String separator,
137
        String operator, final String searchType) {
138
        String[] values = split(valueList, separator);
139
        getCBAdapter().select(values, operator, searchType);
140
141
    }
142
143
    /**
144
     * Verifies if the combobox has <code>index</code> selected.
145
     * @param index The index to verify
146
     * @param isSelected If the index should be selected or not.
147
     */
148
    public void gdVerifySelectedIndex(String index, boolean isSelected) {
149
        int implIdx = IndexConverter.toImplementationIndex(
150
                IndexConverter.intValue(index));
151
        int actual = getCBAdapter().getSelectedIndex();
152
        Verifier.equals(implIdx, actual, isSelected);
153
    }
154
    
155
    /**
156
     * Verifies if the passed text is currently selected in the combobox.
157
     * @param text The text to verify.
158
     */
159
    public void gdVerifyText(String text) {
160
        gdVerifyText(text, MatchUtil.DEFAULT_OPERATOR);
161
    }
162
    
163
    /**
164
     * Splits the enumeration of values.
165
     *
166
     * @param values
167
     *            The values to split
168
     * @param separator
169
     *            The separator, may be <code>null</code>
170
     * @return The array of values
171
     */
172
    private String[] split(String values, String separator) {
173
        String[] list = StringParsing.splitToArray(values, ((separator == null)
174
            || (separator.length() == 0) ? INDEX_LIST_SEP_CHAR
175
                : separator.charAt(0)),
176
            TestDataConstants.ESCAPE_CHAR_DEFAULT);
177
        return list;
178
    }
179
180
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractUICAPs.java (+5 lines)
Lines 18-23 import org.eclipse.jubula.rc.common.exception.RobotException; Link Here
18
import org.eclipse.jubula.rc.common.implclasses.IBaseImplementationClass;
18
import org.eclipse.jubula.rc.common.implclasses.IBaseImplementationClass;
19
import org.eclipse.jubula.rc.common.uiadapter.factory.GUIAdapterFactoryRegistry;
19
import org.eclipse.jubula.rc.common.uiadapter.factory.GUIAdapterFactoryRegistry;
20
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
20
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
21
import org.eclipse.jubula.tools.constants.TestDataConstants;
21
/**
22
/**
22
 * Implementation of basic functions for all tester classes. This class
23
 * Implementation of basic functions for all tester classes. This class
23
 * gives the basic functions which are needed for testing.
24
 * gives the basic functions which are needed for testing.
Lines 33-38 public abstract class AbstractUICAPs implements IBaseImplementationClass { Link Here
33
    /** constants for communication */
34
    /** constants for communication */
34
    protected static final String POS_UNI_PERCENT = "Percent"; //$NON-NLS-1$
35
    protected static final String POS_UNI_PERCENT = "Percent"; //$NON-NLS-1$
35
    
36
    
37
    /** The default separator for enumerations of list values. */
38
    protected static final char INDEX_LIST_SEP_CHAR = 
39
        TestDataConstants.VALUE_CHAR_DEFAULT;
40
    
36
    /** */
41
    /** */
37
    private IRobotFactory m_robotFactory;    
42
    private IRobotFactory m_robotFactory;    
38
43
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComboBoxAdapter.java (+79 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2012 BREDEX GmbH.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     BREDEX GmbH - initial API and implementation 
10
 *******************************************************************************/
11
package org.eclipse.jubula.rc.common.uiadapter.interfaces;
12
13
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
14
15
/**
16
 * This interface holds all methods which are needed to test
17
 * ComboBox like components.
18
 * @author BREDEX GmbH
19
 *
20
 */
21
public interface IComboBoxAdapter extends ITextVerifiable {
22
23
    /**
24
     * 
25
     * @return the value if the Text Component is editable
26
     */
27
    boolean isEditable();
28
    /**
29
     * @param value The value to check
30
     * @param operator The operator used to verify
31
     * @return <code>true</code> if the combobox contains an element rendered with the passed value
32
     */
33
    public boolean containsValue(String value, String operator);
34
    /**
35
     * @param value The value to check
36
     * @return <code>true</code> if the combobox contains an element rendered with the passed value
37
     */
38
    public boolean containsValue(String value);
39
    
40
    /**
41
     * select the whole text of  the textfield by clicking three times.
42
     */
43
    void selectAll();
44
    
45
    
46
    /**
47
     * @return The currently selected index for the combo box, or -1 if no
48
     *          index is currently selected.
49
     */
50
    public int getSelectedIndex();
51
        
52
    /**
53
     * Selects the combobox element with the passed index.
54
     * @param index The index to select
55
     */
56
    public void select(int index);
57
    
58
    /**
59
     * Selects the specified item in the combobox.
60
     * @param values the values which should be (not) selected
61
     * @param operator if regular expressions are used
62
     * @param searchType Determines where the search begins ("relative" or "absolute")
63
     * @throws StepExecutionException if an error occurs during selecting the item
64
     * @throws IllegalArgumentException if <code>component</code> or <code>text</code> are null
65
     */
66
    public void select(final String[] values, String operator,
67
        String searchType)
68
        throws StepExecutionException, IllegalArgumentException; 
69
    
70
    /**
71
     * Inputs <code>text</code> to <code>component</code>.<br> 
72
     * @param text the text to type
73
     * @param replace whether to replace the text or not
74
     * @throws StepExecutionException if an error occurs during typing <code>text</code>
75
     * @throws IllegalArgumentException if <code>component</code> or <code>text</code> are null
76
     */
77
    public void input(String text, boolean replace)
78
        throws StepExecutionException, IllegalArgumentException;
79
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/CapUtil.java (-1 / +59 lines)
Lines 27-35 import javax.swing.text.JTextComponent; Link Here
27
import org.eclipse.jubula.rc.common.AUTServer;
27
import org.eclipse.jubula.rc.common.AUTServer;
28
import org.eclipse.jubula.rc.common.adaptable.AdapterFactoryRegistry;
28
import org.eclipse.jubula.rc.common.adaptable.AdapterFactoryRegistry;
29
import org.eclipse.jubula.rc.common.adaptable.ITextRendererAdapter;
29
import org.eclipse.jubula.rc.common.adaptable.ITextRendererAdapter;
30
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
30
import org.eclipse.jubula.rc.common.driver.IRobot;
31
import org.eclipse.jubula.rc.common.driver.IRobot;
32
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
33
import org.eclipse.jubula.rc.common.driver.IRunnable;
31
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
34
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
32
import org.eclipse.jubula.rc.common.util.KeyStrokeUtil;
35
import org.eclipse.jubula.rc.common.util.KeyStrokeUtil;
36
import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
33
import org.eclipse.jubula.rc.swing.swing.driver.KeyCodeConverter;
37
import org.eclipse.jubula.rc.swing.swing.driver.KeyCodeConverter;
34
import org.eclipse.jubula.rc.swing.swing.implclasses.EventListener;
38
import org.eclipse.jubula.rc.swing.swing.implclasses.EventListener;
35
import org.eclipse.jubula.tools.objects.event.EventFactory;
39
import org.eclipse.jubula.tools.objects.event.EventFactory;
Lines 100-105 public class CapUtil { Link Here
100
            return false;
104
            return false;
101
        }
105
        }
102
    }
106
    }
107
    
108
    /**
109
     * The robot factory.
110
     */
111
    private static IRobotFactory robotFactory;
112
103
    /**
113
    /**
104
     * 
114
     * 
105
     */
115
     */
Lines 113-119 public class CapUtil { Link Here
113
        return AUTServer.getInstance().getRobot();
123
        return AUTServer.getInstance().getRobot();
114
    }
124
    }
115
125
116
126
    /**
127
     * Gets the Robot factory. The factory is created once per instance.
128
     *
129
     * @return The Robot factory.
130
     */
131
    protected static IRobotFactory getRobotFactory() {
132
        if (robotFactory == null) {
133
            robotFactory = new RobotFactoryConfig().getRobotFactory();
134
        }
135
        return robotFactory;
136
    }
137
    /**
138
     * @return The event thread queuer.
139
     */
140
    protected static IEventThreadQueuer getEventThreadQueuer() {
141
        return getRobotFactory().getEventThreadQueuer();
142
    }
143
    
117
    /**
144
    /**
118
     * Presses or releases the given modifier.
145
     * Presses or releases the given modifier.
119
     * @param modifier the modifier.
146
     * @param modifier the modifier.
Lines 136-141 public class CapUtil { Link Here
136
    }
163
    }
137
     
164
     
138
    /**
165
    /**
166
     * Casts the passed renderer component to a known type and extracts the
167
     * rendered text.
168
     *
169
     * @param renderer
170
     *            The renderer.
171
     * @param queueInEventThread
172
     *            If <code>true</code>, the text extraction is executed in
173
     *            the event queue thread.
174
     * @return The rendered text.
175
     * @throws StepExecutionException
176
     *             If the passed renderer is not supported. Supported types are
177
     *             <code>JLabel</code>, <code>JToggleButton</code>,
178
     *             <code>AbstractButton</code> and <code>JTextComponent</code>
179
     *
180
     */
181
    public static String getRenderedText(final Component renderer,
182
        boolean queueInEventThread) throws StepExecutionException {
183
184
        if (queueInEventThread) {
185
            return (String)getEventThreadQueuer().invokeAndWait(
186
                "getRenderedText", new IRunnable() { //$NON-NLS-1$
187
                    public Object run() {
188
                        return getRenderedText(renderer);
189
                    }
190
                });
191
        }
192
193
        return getRenderedText(renderer);
194
    }
195
    
196
    /**
139
     * @param renderer
197
     * @param renderer
140
     *            The component which is used as the renderer
198
     *            The component which is used as the renderer
141
     * @return The string that the renderer displays.
199
     * @return The string that the renderer displays.
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JComboBoxAdapter.java (+405 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2012 BREDEX GmbH.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     BREDEX GmbH - initial API and implementation 
10
 *******************************************************************************/
11
package org.eclipse.jubula.rc.swing.swing.uiadapter;
12
13
import java.awt.Component;
14
import java.awt.Container;
15
import java.awt.Dimension;
16
import java.awt.Rectangle;
17
import java.util.Arrays;
18
19
import javax.accessibility.Accessible;
20
import javax.accessibility.AccessibleContext;
21
import javax.swing.ComboBoxEditor;
22
import javax.swing.JButton;
23
import javax.swing.JComboBox;
24
import javax.swing.JList;
25
import javax.swing.JPopupMenu;
26
import javax.swing.SwingUtilities;
27
28
import org.apache.commons.lang.Validate;
29
import org.eclipse.jubula.rc.common.driver.ClickOptions;
30
import org.eclipse.jubula.rc.common.driver.IRunnable;
31
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
32
import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
33
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComboBoxAdapter;
34
import org.eclipse.jubula.rc.swing.swing.caps.CapUtil;
35
import org.eclipse.jubula.rc.swing.swing.implclasses.JComboBoxHelper;
36
import org.eclipse.jubula.rc.swing.swing.implclasses.JComboBoxImplClass;
37
import org.eclipse.jubula.tools.objects.event.EventFactory;
38
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
39
/**
40
 * Implementation of the Interface <code>IComboBoxAdapter</code> as a
41
 * adapter for the <code>JComboBox</code> component.
42
 * @author BREDEX GmbH
43
 *
44
 */
45
public class JComboBoxAdapter extends WidgetAdapter implements
46
        IComboBoxAdapter {
47
    /**
48
     * <code>INVALID_MAX_WIDTH</code>
49
     */
50
    public static final int NO_MAX_WIDTH = -1;
51
    
52
    /**   */
53
    private JComboBox m_comboBox;
54
    /**
55
     * 
56
     * @param objectToAdapt 
57
     */
58
    public JComboBoxAdapter(Object objectToAdapt) {
59
        super(objectToAdapt);
60
        m_comboBox = (JComboBox) objectToAdapt;
61
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66
    public String getText() {
67
        String comboBoxText;
68
        if (m_comboBox.isEditable()) { 
69
            comboBoxText = CapUtil.getRenderedText(
70
                    getComboBoxEditorComponent(m_comboBox), true);
71
        } else {
72
            final int selIndex = m_comboBox.getSelectedIndex();
73
            if (selIndex == -1) {
74
                comboBoxText = String.valueOf(
75
                        m_comboBox.getSelectedItem());
76
            } else {
77
                final JList jlist = new JList(m_comboBox.getModel());
78
                Object o = getEventThreadQueuer().invokeAndWait(
79
                        "getText", new IRunnable() { //$NON-NLS-1$
80
                            public Object run() {
81
                                Component disp = m_comboBox.getRenderer()
82
                                    .getListCellRendererComponent(jlist,
83
                                        jlist.getModel().getElementAt(selIndex),
84
                                        selIndex, true, m_comboBox.hasFocus());
85
                                return CapUtil.getRenderedText(disp, false);
86
                            }
87
                        });
88
                comboBoxText = String.valueOf(o);
89
            }
90
        }
91
        return comboBoxText;
92
    
93
    }
94
95
    /**
96
     * {@inheritDoc}
97
     */
98
    public boolean isEditable() {
99
        Boolean editable = (Boolean)getEventThreadQueuer().invokeAndWait("isEditable", //$NON-NLS-1$
100
            new IRunnable() {
101
                public Object run() {
102
                    // see findBugs
103
                    return m_comboBox.isEditable() 
104
                            ? Boolean.TRUE : Boolean.FALSE;
105
                }
106
            });
107
        return editable.booleanValue();
108
    }
109
110
    /**
111
     * {@inheritDoc}
112
     */
113
    public boolean containsValue(String value, String operator) {
114
        JListAdapter list = new JListAdapter(findJList());
115
        return list.containsValue(value, operator);
116
    }
117
    
118
    /**
119
     * {@inheritDoc}
120
     */
121
    public boolean containsValue(String value) {
122
        return containsValue(value, MatchUtil.EQUALS);
123
    }
124
125
    /**
126
     * select the whole text of  the textfield by clicking three times.
127
     */
128
    public void selectAll() {
129
        click(new Integer(1));
130
        getRobot().keyStroke(getRobot().getSystemModifierSpec() + " A"); //$NON-NLS-1$
131
    }
132
133
    /**
134
     * {@inheritDoc}
135
     */
136
    public int getSelectedIndex() {
137
        Integer actual = (Integer)getEventThreadQueuer()
138
                .invokeAndWait(
139
                    JComboBoxImplClass.class.getName() + ".getSelectedIndex", //$NON-NLS-1$
140
                    new IRunnable() {
141
                        public Object run() {
142
                            return new Integer(m_comboBox.getSelectedIndex());
143
                        }
144
                    });
145
        return actual.intValue();
146
    }
147
148
    /**
149
     * {@inheritDoc}
150
     */
151
    public void select(int index) {
152
        JListAdapter list = new JListAdapter(findJList());
153
        list.clickOnIndex(new Integer(index), ClickOptions
154
                .create().setClickCount(1), getMaxWidth());
155
    }
156
157
    /**
158
     * Selects the specified item in the combobox.
159
     * @param values the values which should be (not) selected
160
     * @param operator if regular expressions are used
161
     * @param searchType Determines where the search begins ("relative" or "absolute")
162
     * @throws StepExecutionException if an error occurs during selecting the item
163
     * @throws IllegalArgumentException if <code>component</code> or <code>text</code> are null
164
     */
165
    public void select(final String[] values, String operator,
166
        String searchType)
167
        throws StepExecutionException, IllegalArgumentException {
168
        try {
169
            for (int i = 0; i < values.length; i++) {
170
                String text = values[i];
171
                Validate.notNull(text, "text must not be null"); //$NON-NLS-1$
172
            }
173
            JListAdapter list = new JListAdapter(findJList());
174
            Integer[] indices = list.findIndicesOfValues(values,
175
                    operator, searchType);
176
            Arrays.sort(indices);
177
            if (indices.length == 0) {
178
                throw new StepExecutionException("Text '" + Arrays.asList(values).toString() //$NON-NLS-1$
179
                    + "' not found", //$NON-NLS-1$
180
                    EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
181
            }
182
            list.clickOnIndex(indices[0], ClickOptions
183
                    .create().setClickCount(1), getMaxWidth());
184
        } catch (StepExecutionException e) {
185
            m_comboBox.hidePopup();
186
            throw e;
187
        } catch (IllegalArgumentException e) {
188
            m_comboBox.hidePopup();
189
            throw e;
190
        }
191
    }
192
193
    /**
194
     * Inputs <code>text</code> to <code>component</code>.<br>
195
     * @param text the text to type in
196
     * @param replace whether to rplace the text or not
197
     * @throws StepExecutionException if an error occurs during typing <code>text</code>
198
     * @throws IllegalArgumentException if <code>component</code> or <code>text</code> are null
199
     */
200
    public void input(String text, boolean replace)
201
        throws StepExecutionException, IllegalArgumentException {
202
203
        Validate.notNull(text, "text must not be null"); //$NON-NLS-1$
204
        Component editor = getComboBoxEditorComponent(m_comboBox);
205
        if (editor == null) {
206
            throw new StepExecutionException("could not find editor", //$NON-NLS-1$
207
                EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
208
        }
209
        if (replace) {
210
            selectAll();
211
        }
212
        getRobot().type(editor, text);
213
    }
214
215
    /**
216
     * performs a <code>count</code> -click on the textfield.
217
     * @param count the number of clicks
218
     */
219
    public void click(Integer count) {
220
        Component editor = getComboBoxEditorComponent(m_comboBox);
221
        if (editor == null) {
222
            throw new StepExecutionException("no editor found", //$NON-NLS-1$
223
                EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
224
        }
225
        getRobot().click(editor, null, ClickOptions.create().setClickCount(
226
                count.intValue()));
227
    }
228
    
229
    /**
230
     * @param component
231
     *            the combobox
232
     * @return the editor used to render and edit the selected item in the
233
     *         JComboBox field.
234
     * @throws StepExecutionException
235
     *             if the editor comonent could not be found
236
     */
237
    private Component getComboBoxEditorComponent(JComboBox component)
238
        throws StepExecutionException {
239
240
        ComboBoxEditor cbe = component.getEditor();
241
        if (cbe == null) {
242
            throw new StepExecutionException("no ComboBoxEditor found", //$NON-NLS-1$
243
                EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
244
        }
245
        Component c = cbe.getEditorComponent();
246
        if (c == null) {
247
            throw new StepExecutionException("no EditorComponent found", //$NON-NLS-1$
248
                EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
249
        }
250
        return c;
251
    }
252
    
253
    /**
254
     * Finds the <code>JList</code> of the combobox.
255
     * @return The list
256
     */
257
    private JList findJList() {
258
        JList list = (JList)getComponentViaHierarchy(openPopupMenu(),
259
                JList.class);
260
        if (list == null) {
261
            throw new StepExecutionException("list component not found", //$NON-NLS-1$
262
                EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
263
        }
264
        return list;
265
    }
266
    
267
    /**
268
     * Opens the combobox popup menu and returns the popup instance. May also be
269
     * called if the popup is already visible
270
     * @return The popup menu
271
     */
272
    private JPopupMenu openPopupMenu() {
273
        if (!isPopupVisible()) {
274
            Component c = getComponentViaHierarchy(m_comboBox, JButton.class);
275
            Rectangle r = null;
276
            if ((c == null) && (!m_comboBox.isEditable())) {
277
                c = m_comboBox;
278
            } else if ((c == null) && (m_comboBox.isEditable())) {
279
                c = m_comboBox;
280
                r = findArrowIconArea();
281
            }
282
//            if (log.isDebugEnabled()) {
283
//                log.debug("Opening popup by clicking on: " + c); //$NON-NLS-1$
284
//            }
285
            getRobot().click(c, r);
286
        }
287
        if (!isPopupVisible()) {
288
//            log.debug("Dropdown list still not visible, must be an error"); //$NON-NLS-1$
289
            throw new StepExecutionException("dropdown list not visible", //$NON-NLS-1$
290
                EventFactory.createActionError(
291
                        TestErrorEvent.DROPDOWN_LIST_NOT_FOUND));
292
        }
293
        return getPopupMenu(m_comboBox);
294
    }
295
    
296
    /**
297
     * Tries to find the popup menu from the combobox
298
     * @param component the combobox
299
     * @return the popup of the combobox
300
     * @throws StepExecutionException if the popup could not be found
301
     */
302
    private JPopupMenu getPopupMenu(JComboBox component)
303
        throws StepExecutionException {
304
305
        AccessibleContext ac = component.getAccessibleContext();
306
        for (int i = 0; i < ac.getAccessibleChildrenCount(); i++) {
307
            Accessible a = ac.getAccessibleChild(i);
308
            if (a instanceof JPopupMenu) {
309
                return (JPopupMenu)a;
310
            }
311
        }
312
        throw new StepExecutionException("cannot find dropdown list", //$NON-NLS-1$
313
            EventFactory.createActionError(
314
                    TestErrorEvent.DROPDOWN_LIST_NOT_FOUND));
315
    }
316
    /**
317
     * Tries to find the component in the component hierarchy
318
     * @param component where to search
319
     * @param c type of the component which should be found
320
     * @return the desired component
321
     */
322
    private Component getComponentViaHierarchy(Container component, Class c) {
323
        Component[] comps = component.getComponents();
324
        for (int i = 0; i < comps.length; i++) {
325
            if (c.isInstance(comps[i])) {
326
                return comps[i];
327
            }
328
        }
329
        for (int i = 0; i < comps.length; i++) {
330
            if (comps[i] instanceof Container) {
331
                Component ct = getComponentViaHierarchy((Container)comps[i], c);
332
                if (ct != null) {
333
                    return ct;
334
                }
335
            }
336
        }
337
        return null;
338
    }
339
    
340
    /**
341
     * @return true, if the popup of the combobox is visible
342
     */
343
    private boolean isPopupVisible() {
344
        Boolean visible = (Boolean)getEventThreadQueuer().invokeAndWait(
345
            JComboBoxHelper.class.getName()
346
            + "isPopupVisible", new IRunnable() { //$NON-NLS-1$
347
                public Object run() throws StepExecutionException {
348
                    return m_comboBox.isPopupVisible()
349
                        ? Boolean.TRUE : Boolean.FALSE;
350
                }
351
            });
352
        return visible.booleanValue();
353
    }
354
355
    /**
356
     * @return a rectangle, where the arrow icon is expected.
357
     */
358
    private Rectangle findArrowIconArea() {
359
        JComboBox comboBox = m_comboBox;
360
        Component editor = getComboBoxEditorComponent(comboBox);
361
        Rectangle r = null;
362
        if (editor == null) {
363
            throw new StepExecutionException("could not find editor", //$NON-NLS-1$
364
                EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
365
        }
366
        Rectangle ra[] =
367
            SwingUtilities.computeDifference(comboBox.getBounds(),
368
                editor.getBounds());
369
        if ((ra == null) || (ra.length < 1)) {
370
            throw new StepExecutionException("could not arrow icon", //$NON-NLS-1$
371
                EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
372
        }
373
        r = ra[0];
374
        // find the largest area of the returned rectangles.
375
        double bestAreaIndex = Double.MAX_VALUE;
376
        for (int i = 0; i < ra.length; i++) {
377
            if ((ra[i].height > 0) && (ra[i].width > 0)) {
378
                double areaIndex = ((double)ra[i].width) / ra[i].height - 1.0;
379
                if (areaIndex < 0) {
380
                    areaIndex *= (-1);
381
                }
382
                if (areaIndex < bestAreaIndex) {
383
                    bestAreaIndex = areaIndex;
384
                    r = ra[i];
385
                }
386
            }
387
        }
388
        return r;
389
    }
390
    
391
    /**
392
     * @return the maximal width for the selection; -1 if none available
393
     * e.g. the preferred width of the combo box itself is 100 pixel although
394
     * the preferred size of the embedded items is more than two times bigger
395
     * --> click outside of component (JList) #3013 
396
     */
397
    private double getMaxWidth() {
398
        double maxWidth = NO_MAX_WIDTH;
399
        Dimension d = m_comboBox.getPreferredSize();
400
        if (d != null) {
401
            maxWidth = d.getWidth();
402
        }
403
        return maxWidth;
404
    }
405
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/factory/SwingAdapterFactory.java (-1 / +6 lines)
Lines 13-18 package org.eclipse.jubula.rc.swing.swing.uiadapter.factory; Link Here
13
13
14
import javax.swing.JButton;
14
import javax.swing.JButton;
15
import javax.swing.JCheckBox;
15
import javax.swing.JCheckBox;
16
import javax.swing.JComboBox;
16
import javax.swing.JList;
17
import javax.swing.JList;
17
import javax.swing.JMenuBar;
18
import javax.swing.JMenuBar;
18
import javax.swing.JMenuItem;
19
import javax.swing.JMenuItem;
Lines 25-30 import javax.swing.text.JTextComponent; Link Here
25
import org.eclipse.jubula.rc.common.uiadapter.factory.IUIAdapterFactory;
26
import org.eclipse.jubula.rc.common.uiadapter.factory.IUIAdapterFactory;
26
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
27
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
27
import org.eclipse.jubula.rc.swing.swing.uiadapter.AbstractButtonAdapter;
28
import org.eclipse.jubula.rc.swing.swing.uiadapter.AbstractButtonAdapter;
29
import org.eclipse.jubula.rc.swing.swing.uiadapter.JComboBoxAdapter;
28
import org.eclipse.jubula.rc.swing.swing.uiadapter.JListAdapter;
30
import org.eclipse.jubula.rc.swing.swing.uiadapter.JListAdapter;
29
import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuBarAdapter;
31
import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuBarAdapter;
30
import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuItemAdapter;
32
import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuItemAdapter;
Lines 50-56 public class SwingAdapterFactory implements IUIAdapterFactory { Link Here
50
        JButton.class, JCheckBox.class, JRadioButton.class,
52
        JButton.class, JCheckBox.class, JRadioButton.class,
51
        JMenuBar.class, JMenuItem.class, JTree.class , 
53
        JMenuBar.class, JMenuItem.class, JTree.class , 
52
        JCheckBox.class, JRadioButton.class, JTable.class, JPopupMenu.class,
54
        JCheckBox.class, JRadioButton.class, JTable.class, JPopupMenu.class,
53
        JList.class, JTextComponent.class};
55
        JList.class, JTextComponent.class, JComboBox.class};
54
    
56
    
55
    /**
57
    /**
56
     * {@inheritDoc}
58
     * {@inheritDoc}
Lines 95-100 public class SwingAdapterFactory implements IUIAdapterFactory { Link Here
95
        } else if (objectToAdapt instanceof JTextComponent) {
97
        } else if (objectToAdapt instanceof JTextComponent) {
96
            returnvalue = new JTextComponentAdapter(objectToAdapt);
98
            returnvalue = new JTextComponentAdapter(objectToAdapt);
97
        
99
        
100
        } else if (objectToAdapt instanceof JComboBox) {
101
            returnvalue = new JComboBoxAdapter(objectToAdapt);
102
        
98
        }
103
        }
99
        
104
        
100
        return returnvalue;
105
        return returnvalue;
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/AbstractComboBoxAdapter.java (+318 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2012 BREDEX GmbH.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     BREDEX GmbH - initial API and implementation 
10
 *******************************************************************************/
11
package org.eclipse.jubula.rc.swt.uiadapter;
12
13
import java.util.Arrays;
14
import java.util.HashSet;
15
import java.util.Set;
16
17
import org.apache.commons.lang.Validate;
18
import org.eclipse.jubula.rc.common.CompSystemConstants;
19
import org.eclipse.jubula.rc.common.driver.ClickOptions;
20
import org.eclipse.jubula.rc.common.driver.IRunnable;
21
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
22
import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
23
import org.eclipse.jubula.rc.common.logger.AutServerLogger;
24
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComboBoxAdapter;
25
import org.eclipse.jubula.rc.swt.utils.SwtUtils;
26
import org.eclipse.jubula.tools.objects.event.EventFactory;
27
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
28
import org.eclipse.swt.SWT;
29
import org.eclipse.swt.graphics.Rectangle;
30
import org.eclipse.swt.widgets.Control;
31
import org.eclipse.swt.widgets.Widget;
32
/**
33
 * Implementation of the Interface <code>IComboBoxAdapter</code> as a abstract
34
 * adapter for the swt comboboxes.
35
 * This class needs specific methods of its subclasses therefore it is abstract.
36
 * 
37
 * @author BREDEX GmbH
38
 *
39
 */
40
public abstract class AbstractComboBoxAdapter extends WidgetAdapter 
41
    implements IComboBoxAdapter {
42
    
43
    /** number of clicks to give focus without selecting any text */
44
    public static final int CLICK_COUNT_FOR_SELECTING_NONE = 3;
45
46
    /** the logger */
47
    private static AutServerLogger log = new AutServerLogger(
48
        AbstractComboBoxAdapter.class);
49
50
    /**
51
     * 
52
     * @param objectToAdapt 
53
     */
54
    protected AbstractComboBoxAdapter(Object objectToAdapt) {
55
        super(objectToAdapt);
56
    }
57
    
58
    /**
59
     * {@inheritDoc}
60
     */
61
    public void select(final String[] values, String operator, 
62
        final String searchType) 
63
        throws StepExecutionException, IllegalArgumentException {
64
    
65
        for (int i = 0; i < values.length; i++) {
66
            String text = values[i];
67
            Validate.notNull(text, "text must not be null"); //$NON-NLS-1$
68
        }
69
        
70
        Integer[] indices = findIndicesOfValues(values, 
71
                operator, searchType);
72
        Arrays.sort(indices);
73
        if (indices.length == 0) {
74
            throw new StepExecutionException("Text '" + Arrays.asList(values).toString() //$NON-NLS-1$ 
75
                + "' not found", //$NON-NLS-1$ 
76
                EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
77
        }
78
        select(indices[0].intValue());
79
    }
80
    
81
    /**
82
     * {@inheritDoc}
83
     */
84
    public void select(int index) {
85
        
86
        int comboItemCount = getItemCount();
87
88
        if (index >= comboItemCount
89
            || index < 0) {
90
            throw new StepExecutionException("Combo Box index '" + index //$NON-NLS-1$
91
                + "' is out of range", //$NON-NLS-1$
92
                EventFactory.createActionError(TestErrorEvent.INVALID_INDEX));
93
        }
94
95
        if (isComboEnabled()) {
96
            // FIXME zeb: Needs special handling if style is not DROP_DOWN
97
            openDropdownList();
98
            selectImpl(index);
99
        }
100
    }
101
102
    /**
103
     * @return <code>true</code> if the combo box is currently enabled.
104
     */
105
    protected abstract boolean isComboEnabled();
106
107
    /**
108
     * 
109
     * @param index idx
110
     */
111
    protected abstract void selectImpl(int index);
112
    
113
    /**
114
     * Opens the combobox dropdown list. May also be
115
     * called if the list is already visible.
116
     */
117
    protected abstract void openDropdownList();
118
119
    /**
120
     * Finds the indices of the list elements that are rendered with the passed
121
     * values.
122
     * 
123
     * @param values
124
     *            The values
125
     * @param operator
126
     *            operator to use
127
     * @param searchType 
128
     *            Determines where the search begins ("relative" or "absolute")
129
     * @return The array of indices. It's length is equal to the length of the
130
     *         values array, but may contains <code>null</code> elements for
131
     *         all values that are not found in the list
132
     */
133
    private Integer[] findIndicesOfValues(final String [] values, 
134
            final String operator, final String searchType) {
135
        
136
        final Set indexSet = new HashSet();
137
138
        for (int i = getStartingIndex(searchType); 
139
                i < getItemCount(); 
140
                ++i) {
141
            
142
            String str = getItem(i);
143
            if (MatchUtil.getInstance().
144
                match(str, values, operator)) {
145
                indexSet.add(new Integer(i));
146
            }
147
        }
148
                    
149
        
150
        Integer[] indices = new Integer[indexSet.size()];
151
        indexSet.toArray(indices);
152
        return indices;
153
154
    }
155
156
    /**
157
     * @param searchType Determines where the search begins ("relative" or "absolute")
158
     * @return The index from which to begin a search, based on the search type
159
     *         and (if appropriate) the currently selected item.
160
     */
161
    private int getStartingIndex(final String searchType) {
162
        int startingIndex = 0;
163
        if (searchType.equalsIgnoreCase(
164
                CompSystemConstants.SEARCH_TYPE_RELATIVE)) {
165
            startingIndex = getSelectedIndex();
166
        }
167
        return startingIndex;
168
    }
169
170
    /**
171
     * {@inheritDoc}
172
     */
173
    public boolean containsValue(String value, String operator) {
174
        Integer[] indices = null;
175
        if (operator.equals(MatchUtil.NOT_EQUALS)) {
176
            indices = findIndicesOfValues(new String[] { value },
177
                MatchUtil.EQUALS, CompSystemConstants.SEARCH_TYPE_ABSOLUTE);
178
            return indices.length == 0;
179
        } 
180
        indices = findIndicesOfValues(new String[] { value },
181
            operator, CompSystemConstants.SEARCH_TYPE_ABSOLUTE);
182
        return indices.length > 0;
183
    }
184
185
    /**
186
     * {@inheritDoc}
187
     */
188
    public boolean containsValue(String value) {
189
        return containsValue(value, MatchUtil.EQUALS);
190
    }
191
192
    /**
193
     * Returns the number of items contained in the combo list.
194
     * @return  the number of items.
195
     */
196
    protected abstract int getItemCount();
197
198
    /**
199
     * Returns the item at the given, zero-relative index in the combo list. 
200
     * Throws an exception if the index is out of range.
201
     * @param index the index of the item to return
202
     * @return  the item at the given index
203
     */
204
    protected abstract String getItem(final int index);
205
    
206
    /**
207
     * {@inheritDoc}
208
     */
209
    public void input(String text, boolean replace)
210
        throws StepExecutionException, IllegalArgumentException {
211
    
212
        Validate.notNull(text, "text must not be null"); //$NON-NLS-1$
213
        Control editor = (Control) getRealComponent();
214
        if (editor == null) {
215
            throw new StepExecutionException("could not find editor", //$NON-NLS-1$
216
                EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
217
        }
218
        if (replace) {
219
            selectAll();
220
        } else {
221
            selectNone();
222
        }
223
        getRobot().type(editor, text);
224
        getRobot().keyType(null, SWT.KEYPAD_CR);
225
    }
226
    
227
    /**
228
     * {@inheritDoc}
229
     */
230
    public void click(Integer count) {
231
        Control editor = (Control) getRealComponent();
232
        if (editor == null) {
233
            throw new StepExecutionException("no editor found", //$NON-NLS-1$
234
                EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
235
        }
236
        getRobot().click(editor, null, ClickOptions.create().setClickCount(
237
                count.intValue()));
238
    }
239
    
240
    /**
241
     * Give the text field focus without selecting any of the text.
242
     */
243
    public void selectNone() {
244
        // FIXME zeb: This places the caret at the center of the component, 
245
        //            which may or may not be correct. Where should the text
246
        //            be inserted?
247
        click(new Integer(
248
            CLICK_COUNT_FOR_SELECTING_NONE));
249
    }
250
    /**
251
     * Toggles the combobox dropdown list by clicking on the combo box.
252
     */
253
    protected void toggleDropdownList() {
254
        
255
        // Click in the center of the pulldown button
256
        Rectangle r = findArrowIconArea();
257
            
258
        if (log.isDebugEnabled()) {
259
            log.debug("Toggling dropdown by clicking on rectangle: " + r  //$NON-NLS-1$
260
                + "within component: " + getRealComponent()); //$NON-NLS-1$
261
        }
262
263
        getRobot().click(getRealComponent(), r,
264
            ClickOptions.create().setScrollToVisible(false)
265
                .setConfirmClick(false));
266
267
    }
268
    
269
    /**
270
     * @return a rectangle, where the arrow icon is expected, relative to the
271
     *         combo box's location.
272
     */
273
    protected Rectangle findArrowIconArea() {
274
        final Control editor = (Control) getRealComponent();
275
        Rectangle r = null;
276
        if (editor == null) {
277
            throw new StepExecutionException("could not find editor", //$NON-NLS-1$
278
                EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
279
        }
280
281
        r = (Rectangle)getEventThreadQueuer().invokeAndWait(
282
             AbstractComboBoxAdapter.class.getName()
283
            + "findArrowIconArea", new IRunnable() { //$NON-NLS-1$
284
                public Object run() throws StepExecutionException {
285
                    return SwtUtils.getRelativeWidgetBounds(editor, editor);
286
                }
287
            });
288
        
289
        // Assume that the arrow icon is approximately square
290
        r.x += r.width - r.height;
291
        r.width = r.height;
292
        
293
        return r;
294
    }
295
    
296
    /**
297
     * @return true, if combo is not read_only
298
     */
299
    private boolean isComboEditable() {
300
        
301
        Integer comboStyle = (Integer)getEventThreadQueuer().invokeAndWait(
302
            AbstractComboBoxAdapter.class.getName()
303
            + "isComboEditable", new IRunnable() { //$NON-NLS-1$
304
                public Object run() throws StepExecutionException {
305
                    return new Integer(((Widget)getRealComponent()).getStyle());
306
                }
307
            });
308
309
        return ((comboStyle.intValue() & SWT.READ_ONLY) == 0);
310
    }
311
    
312
    /**
313
     * {@inheritDoc}
314
     */
315
    public boolean isEditable() {
316
        return isComboEditable();
317
    }
318
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/CComboAdapter.java (+355 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2012 BREDEX GmbH.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     BREDEX GmbH - initial API and implementation 
10
 *******************************************************************************/
11
package org.eclipse.jubula.rc.swt.uiadapter;
12
13
import org.eclipse.jubula.rc.common.driver.ClickOptions;
14
import org.eclipse.jubula.rc.common.driver.IRunnable;
15
import org.eclipse.jubula.rc.common.driver.RobotTiming;
16
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
17
import org.eclipse.jubula.rc.common.logger.AutServerLogger;
18
import org.eclipse.jubula.rc.swt.utils.SwtUtils;
19
import org.eclipse.jubula.tools.constants.TimeoutConstants;
20
import org.eclipse.jubula.tools.objects.event.EventFactory;
21
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
22
import org.eclipse.swt.custom.CCombo;
23
import org.eclipse.swt.graphics.Point;
24
import org.eclipse.swt.graphics.Rectangle;
25
import org.eclipse.swt.widgets.Display;
26
import org.eclipse.swt.widgets.List;
27
import org.eclipse.swt.widgets.Shell;
28
/**
29
 * Implementation of the Interface <code>IComboBoxAdapter</code> as a
30
 * adapter for the <code>CCombo</code> component.
31
 * This class is sub classing <code>AbstractComboBoxAdapter</code> because
32
 * <code>Combo</code> and <code>CCombo</code> have common parts
33
 * @author BREDEX GmbH
34
 *
35
 */
36
public class CComboAdapter extends AbstractComboBoxAdapter {
37
38
    /** the logger */
39
    private static AutServerLogger log = new AutServerLogger(
40
        CComboAdapter.class);
41
    
42
    /** */
43
    private CCombo m_combobox;
44
    
45
    /**
46
     * 
47
     * @param objectToAdapt 
48
     */
49
    public CComboAdapter(Object objectToAdapt) {
50
        super(objectToAdapt);
51
        m_combobox = (CCombo) objectToAdapt;
52
    }
53
54
    /**
55
     * {@inheritDoc}
56
     */
57
    public void selectAll() {
58
        
59
        // Get focus
60
        selectNone();
61
62
        // FIXME zeb: Find a platform-independant way to select all text
63
        //            without calling CCombo methods directly.
64
        //            The current problem with clicking twice in the text area
65
        //            is that if there is any white space, only part of the
66
        //            text is selected.
67
        getEventThreadQueuer().invokeAndWait("selectAll",  //$NON-NLS-1$
68
            new IRunnable() {
69
70
                public Object run() throws StepExecutionException {
71
                    m_combobox.setSelection(
72
                            new Point(0, m_combobox.getText().length()));
73
                    
74
                    // return value is not used
75
                    return null;
76
                }
77
            
78
            });
79
80
    }
81
82
    /**
83
     * {@inheritDoc}
84
     */
85
    public int getSelectedIndex() {    
86
        int selectedIndex = ((Integer)getEventThreadQueuer().invokeAndWait(
87
                CComboAdapter.class.getName()
88
                + "getSelectedIndex", new IRunnable() { //$NON-NLS-1$
89
                    public Object run() throws StepExecutionException {
90
                        return new Integer(m_combobox.getSelectionIndex());
91
                    }
92
                })).intValue();
93
94
        return selectedIndex;
95
    }
96
97
98
    /**
99
     * {@inheritDoc}
100
     */
101
    public String getText() {
102
        Object o = getEventThreadQueuer().invokeAndWait(
103
                "getSelectedItem", new IRunnable() { //$NON-NLS-1$
104
                    public Object run() {
105
                        return m_combobox.getText();
106
                    }
107
                });
108
        return o != null ? o.toString() : null;
109
    }
110
111
    /**
112
     * {@inheritDoc}
113
     */
114
    protected boolean isComboEnabled() {        
115
        boolean isEnabled = ((Boolean)getEventThreadQueuer().invokeAndWait(
116
                CComboAdapter.class.getName()
117
                + "isComboEnabled", new IRunnable() { //$NON-NLS-1$
118
                    public Object run() throws StepExecutionException {
119
                        return m_combobox.isEnabled() 
120
                                ? Boolean.TRUE : Boolean.FALSE;
121
                    }
122
                })).booleanValue();
123
124
        return isEnabled;
125
    }
126
127
    /**
128
     * {@inheritDoc}
129
     */
130
    protected void selectImpl(final int index) {
131
        scrollIndexToVisible(index);
132
        
133
        Rectangle clickConstraints = 
134
            (Rectangle)getEventThreadQueuer().invokeAndWait(
135
                "setClickConstraints",  //$NON-NLS-1$
136
                new IRunnable() {
137
138
                    public Object run() throws StepExecutionException {
139
                        Rectangle constraints = 
140
                            SwtUtils.getRelativeWidgetBounds(
141
                                    getDropdownList(), getDropdownList());
142
                        int displayedItemCount = getDisplayedItemCount();
143
                        int numberBelowTop = 0;
144
                        if (displayedItemCount >= getItemCount()) {
145
                            numberBelowTop = index;
146
                        } else {
147
                            numberBelowTop = Math.max(0, index 
148
                                - getItemCount() + displayedItemCount);
149
                        }
150
                        
151
                        // Set the constraints based on the numberBelowTop
152
                        constraints.height = getDropdownList().getItemHeight();
153
                        constraints.y += (numberBelowTop * constraints.height);
154
155
                        return constraints;
156
                    }
157
            
158
                });
159
        
160
        // Note that we set scrollToVisible false because we have already done
161
        // the scrolling.
162
        getRobot().click(getDropdownList(), clickConstraints, 
163
            new ClickOptions().setScrollToVisible(false));
164
165
    }
166
167
    /**
168
     * {@inheritDoc}
169
     */
170
    protected void openDropdownList() {
171
        if (!isDropdownVisible()) {
172
            toggleDropdownList();
173
        }
174
175
        long timeout = TimeoutConstants.SERVER_TIMEOUT_WAIT_FOR_POPUP;
176
        long done = System.currentTimeMillis() + timeout; 
177
        long now;
178
        while (!isDropdownVisible() && timeout >= 0) {
179
            RobotTiming.sleepPreShowPopupDelay();
180
            now = System.currentTimeMillis();
181
            timeout = done - now;
182
        }
183
        
184
        if (!isDropdownVisible()) {
185
            log.debug("Dropdown list still not visible, must be an error"); //$NON-NLS-1$
186
            throw new StepExecutionException("dropdown list not visible", //$NON-NLS-1$
187
                EventFactory.createActionError(
188
                        TestErrorEvent.DROPDOWN_LIST_NOT_FOUND));
189
        }
190
191
    }
192
193
    /**
194
     * Returns the number of items contained in the combo list.
195
     * @return  the number of items.
196
     */
197
    protected int getItemCount() {
198
        return ((Integer)getEventThreadQueuer().invokeAndWait(
199
                "getItemCount", //$NON-NLS-1$
200
                new IRunnable() {
201
                    
202
                    public Object run() {
203
                    
204
                        return new Integer(m_combobox.getItemCount()); 
205
                    }
206
                    
207
                })).intValue();
208
209
    }
210
211
    /**
212
     * Returns the item at the given, zero-relative index in the combo list. 
213
     * Throws an exception if the index is out of range.
214
     * @param index the index of the item to return
215
     * @return  the item at the given index
216
     */
217
    protected String getItem(final int index) {
218
        return (String)getEventThreadQueuer().invokeAndWait(
219
                "getItem", //$NON-NLS-1$
220
                new IRunnable() {
221
                    
222
                    public Object run() {
223
                    
224
                        return m_combobox.getItem(index); 
225
                    }
226
                    
227
                });
228
229
    }
230
    
231
    /**
232
     * Tries to find the dropdown list from the combobox 
233
     * @return the dropdown of the combobox, or <code>null</code> if the 
234
     *          dropdown could not be found
235
     */
236
    protected List getDropdownList()
237
        throws StepExecutionException {
238
        
239
        return (List)getEventThreadQueuer().invokeAndWait(
240
            "getDropdownList",  //$NON-NLS-1$
241
            new IRunnable() {
242
243
                public Object run() throws StepExecutionException {
244
            
245
                    Shell mainShell = SwtUtils.getShell(m_combobox);
246
                    Display d = Display.getCurrent();
247
                    Shell [] shells = d.getShells();
248
                    for (int i = 0; i < shells.length; i++) {
249
                        Shell curShell = shells[i];
250
                        if (mainShell == curShell.getParent() 
251
                            && curShell.getChildren().length == 1
252
                            && curShell.getChildren()[0] instanceof List) {
253
                            
254
                            List possibleDropdown = 
255
                                (List)curShell.getChildren()[0];
256
                            if (!possibleDropdown.isDisposed()
257
                                    && possibleDropdown.isVisible()
258
                                    && isDropdownList(possibleDropdown)) {
259
                                return possibleDropdown;
260
                            }
261
                        }
262
                    }
263
264
                    return null;
265
                }
266
            });
267
    }
268
    
269
    /**
270
     * Verifies that the given list is the dropdown list for this combo box.
271
     * 
272
     * @param list  The list to verify.
273
     * @return <code>true</code> if <code>list</code> is the dropdown list for
274
     *          this combo box. Otherwise <code>false</code>.
275
     */
276
    private boolean isDropdownList(List list) {
277
        /*
278
         * Verify that the list is close enough to the combo box.
279
         */
280
281
        Rectangle comboBounds = 
282
            SwtUtils.getWidgetBounds(m_combobox);
283
        Rectangle listBounds = SwtUtils.getWidgetBounds(list);
284
        
285
        // Expand the bounding rectangle for the combo box by a small amount
286
        int posFuzz = 5;
287
        int dimFuzz = posFuzz * 2;
288
        comboBounds.x -= posFuzz;
289
        comboBounds.width += dimFuzz;
290
        comboBounds.y -= posFuzz;
291
        comboBounds.height += dimFuzz;
292
        
293
        return comboBounds.intersects(listBounds);
294
    }
295
    
296
    /**
297
     * Tries to set the given index as the top element of the CCombo.
298
     * @param index The index to make visible
299
     */
300
    private void scrollIndexToVisible(final int index) {
301
        getEventThreadQueuer().invokeAndWait(
302
            "scrollIndexToVisible",  //$NON-NLS-1$
303
            new IRunnable() {
304
305
                public Object run() throws StepExecutionException {
306
           
307
                    getDropdownList().setTopIndex(index);
308
309
                    return null;
310
                }
311
            
312
            });
313
    }
314
    
315
    /**
316
     * 
317
     * @return  the number of items displayed in the dropdown list, or 0 if
318
     *          the list is not showing.
319
     */
320
    private int getDisplayedItemCount() {
321
        return ((Integer)getEventThreadQueuer().invokeAndWait(
322
                "getDisplayedItemCount",  //$NON-NLS-1$
323
                new IRunnable() {
324
325
                public Object run() throws StepExecutionException {
326
                    List dropdown = getDropdownList();
327
                    if (dropdown == null) {
328
                        return new Integer(0);
329
                    }
330
                    int listHeight = SwtUtils.getWidgetBounds(dropdown).height;
331
                    int itemHeight = dropdown.getItemHeight();
332
                    
333
                    return new Integer(listHeight / itemHeight);
334
                }
335
            
336
            })).intValue();
337
    }
338
    
339
    /**
340
     * @return true, if the dropdown of the combobox is visible
341
     */
342
    protected boolean isDropdownVisible() {
343
        Boolean visible = (Boolean)getEventThreadQueuer().invokeAndWait(
344
            CComboAdapter.class.getName()
345
            + "isDropdownVisible", new IRunnable() { //$NON-NLS-1$
346
                public Object run() throws StepExecutionException {
347
                    List dropdownList = getDropdownList();
348
                    return dropdownList != null
349
                        ? Boolean.TRUE : Boolean.FALSE;
350
                }
351
            });
352
        return visible.booleanValue();
353
    }    
354
355
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ComboAdapter.java (+196 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2012 BREDEX GmbH.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     BREDEX GmbH - initial API and implementation 
10
 *******************************************************************************/
11
package org.eclipse.jubula.rc.swt.uiadapter;
12
13
import org.apache.commons.lang.StringUtils;
14
import org.eclipse.jubula.rc.common.driver.IRunnable;
15
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
16
import org.eclipse.jubula.tools.utils.EnvironmentUtils;
17
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.graphics.Point;
19
import org.eclipse.swt.widgets.Combo;
20
import org.eclipse.swt.widgets.Event;
21
/**
22
 * Implementation of the Interface <code>IComboBoxAdapter</code> as a
23
 * adapter for the <code>Combo</code> component.
24
 * This class is sub classing <code>AbstractComboBoxAdapter</code> because
25
 * <code>Combo</code> and <code>CCombo</code> have common parts
26
 * 
27
 * @author BREDEX GmbH
28
 *
29
 */
30
public class ComboAdapter extends AbstractComboBoxAdapter {
31
32
    /**  */
33
    private Combo m_combobox;
34
35
    /**
36
     * 
37
     * @param objectToAdapt 
38
     */
39
    public ComboAdapter(Object objectToAdapt) {
40
        super(objectToAdapt);
41
        m_combobox = (Combo) objectToAdapt;
42
    }
43
44
    /**
45
     * Select the whole text of the textfield.
46
     */
47
    public void selectAll() {
48
        click(new Integer(1));
49
        
50
        // fix for https://bxapps.bredex.de/bugzilla/show_bug.cgi?id=201
51
        // The keystroke "command + a" sometimes causes an "a" to be entered
52
        // into the text field instead of selecting all text (or having no 
53
        // effect).
54
        if (EnvironmentUtils.isMacOS()) {
55
            getEventThreadQueuer().invokeAndWait("combo.selectAll", //$NON-NLS-1$
56
                new IRunnable() {
57
                    public Object run() {
58
                        int textLength = StringUtils.length(
59
                                m_combobox.getText());
60
                        m_combobox.setSelection(new Point(0, textLength));
61
                        return null;
62
                    }
63
                });
64
        } else {
65
            getRobot().keyStroke(getRobot().getSystemModifierSpec() + " A"); //$NON-NLS-1$
66
        }
67
    }
68
69
    /**
70
     * {@inheritDoc}
71
     */
72
    public int getSelectedIndex() {
73
        
74
        int selectedIndex = ((Integer)getEventThreadQueuer().invokeAndWait(
75
                ComboAdapter.class.getName()
76
                + "getSelectedIndex", new IRunnable() { //$NON-NLS-1$
77
                    public Object run() throws StepExecutionException {
78
                        return new Integer(m_combobox.getSelectionIndex());
79
                    }
80
                })).intValue();
81
82
        return selectedIndex;
83
    }
84
85
    /**
86
     * {@inheritDoc}
87
     */
88
    public String getText() {
89
        Object o = getEventThreadQueuer().invokeAndWait(
90
                "getSelectedItem", new IRunnable() { //$NON-NLS-1$
91
                    public Object run() {
92
                        return m_combobox.getText();
93
                    }
94
                });
95
        return o != null ? o.toString() : null;        
96
    }
97
98
    /**
99
     * 
100
     * {@inheritDoc}
101
     */
102
    protected boolean isComboEnabled() {
103
        
104
        boolean isEnabled = ((Boolean)getEventThreadQueuer().invokeAndWait(
105
                ComboAdapter.class.getName()
106
                + "isComboEnabled", new IRunnable() { //$NON-NLS-1$
107
                    public Object run() throws StepExecutionException {
108
                        return m_combobox.isEnabled() 
109
                                ? Boolean.TRUE : Boolean.FALSE;
110
                    }
111
                })).booleanValue();
112
113
        return isEnabled;
114
    }
115
116
    /**
117
     * {@inheritDoc}
118
     */
119
    protected void selectImpl(int index) {
120
        
121
        // Press 'Escape' key to close the dropdown list
122
123
        getRobot().keyType(m_combobox, SWT.ESC);
124
125
        // Currently no method to select elements via mouse clicks 
126
        selectComboIndex(index);
127
    }
128
129
    /**
130
     * 
131
     * {@inheritDoc}
132
     */
133
    protected void openDropdownList() {
134
        // FIXME zeb: Figure out a way to check the status of the dropdown list
135
        toggleDropdownList();
136
    }
137
138
    /**
139
     * Returns the number of items contained in the combo list.
140
     * @return  the number of items.
141
     */
142
    protected int getItemCount() {
143
        return ((Integer)getEventThreadQueuer().invokeAndWait(
144
                "getItemCount", //$NON-NLS-1$
145
                new IRunnable() {
146
                    
147
                    public Object run() {
148
                    
149
                        return new Integer(m_combobox.getItemCount()); 
150
                    }
151
                    
152
                })).intValue();
153
154
    }
155
156
    /**
157
     * Returns the item at the given, zero-relative index in the combo list. 
158
     * Throws an exception if the index is out of range.
159
     * @param index the index of the item to return
160
     * @return  the item at the given index
161
     */
162
    protected String getItem(final int index) {
163
        return (String)getEventThreadQueuer().invokeAndWait(
164
                "getItem", //$NON-NLS-1$
165
                new IRunnable() {
166
                    
167
                    public Object run() {
168
                    
169
                        return m_combobox.getItem(index); 
170
                    }
171
                    
172
                });
173
174
    }
175
        
176
    /**
177
     * 
178
     * @param index the index to select.
179
     * @see Combo#select(int)
180
     */
181
    private void selectComboIndex(final int index) {
182
        final Combo combo = m_combobox;
183
        getEventThreadQueuer().invokeAndWait("selectComboIndex", new IRunnable() { //$NON-NLS-1$
184
            public Object run() throws StepExecutionException {
185
                combo.select(index);
186
                Event selectionEvent = new Event();
187
                selectionEvent.type = SWT.Selection;
188
                selectionEvent.widget = combo;
189
                combo.notifyListeners(SWT.Selection, selectionEvent);
190
191
                return null;
192
            }
193
        });   
194
    }
195
    
196
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/WidgetAdapter.java (-6 / +4 lines)
Lines 10-15 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jubula.rc.swt.uiadapter;
11
package org.eclipse.jubula.rc.swt.uiadapter;
12
12
13
import org.eclipse.jubula.rc.common.AUTServer;
13
import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
14
import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
14
import org.eclipse.jubula.rc.common.caps.AbstractWidgetCAPs;
15
import org.eclipse.jubula.rc.common.caps.AbstractWidgetCAPs;
15
import org.eclipse.jubula.rc.common.driver.ClickOptions;
16
import org.eclipse.jubula.rc.common.driver.ClickOptions;
Lines 107-122 public abstract class WidgetAdapter extends AbstractComponentAdapter Link Here
107
        return m_component;
108
        return m_component;
108
    }
109
    }
109
    
110
    
110
111
    /**
111
    /**
112
     * Gets the Robot
112
     * Gets the Robot. 
113
     *
114
     * @return The Robot
113
     * @return The Robot
115
     * @throws RobotException
114
     * @throws RobotException If the Robot cannot be created.
116
     *             If the Robot cannot be created.
117
     */
115
     */
118
    protected IRobot getRobot() throws RobotException {
116
    protected IRobot getRobot() throws RobotException {
119
        return getRobotFactory().getRobot();
117
        return AUTServer.getInstance().getRobot();
120
    }
118
    }
121
    /**
119
    /**
122
     * @return The event thread queuer.
120
     * @return The event thread queuer.
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/factory/SWTAdapterFactory.java (-1 / +10 lines)
Lines 13-18 package org.eclipse.jubula.rc.swt.uiadapter.factory; Link Here
13
import org.eclipse.jubula.rc.common.uiadapter.factory.IUIAdapterFactory;
13
import org.eclipse.jubula.rc.common.uiadapter.factory.IUIAdapterFactory;
14
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
14
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
15
import org.eclipse.jubula.rc.swt.uiadapter.ButtonAdapter;
15
import org.eclipse.jubula.rc.swt.uiadapter.ButtonAdapter;
16
import org.eclipse.jubula.rc.swt.uiadapter.CComboAdapter;
17
import org.eclipse.jubula.rc.swt.uiadapter.ComboAdapter;
16
import org.eclipse.jubula.rc.swt.uiadapter.ListAdapter;
18
import org.eclipse.jubula.rc.swt.uiadapter.ListAdapter;
17
import org.eclipse.jubula.rc.swt.uiadapter.MenuAdapter;
19
import org.eclipse.jubula.rc.swt.uiadapter.MenuAdapter;
18
import org.eclipse.jubula.rc.swt.uiadapter.MenuItemAdapter;
20
import org.eclipse.jubula.rc.swt.uiadapter.MenuItemAdapter;
Lines 20-27 import org.eclipse.jubula.rc.swt.uiadapter.StyledTextAdapter; Link Here
20
import org.eclipse.jubula.rc.swt.uiadapter.TableAdapter;
22
import org.eclipse.jubula.rc.swt.uiadapter.TableAdapter;
21
import org.eclipse.jubula.rc.swt.uiadapter.TextComponentAdapter;
23
import org.eclipse.jubula.rc.swt.uiadapter.TextComponentAdapter;
22
import org.eclipse.jubula.rc.swt.uiadapter.TreeAdapter;
24
import org.eclipse.jubula.rc.swt.uiadapter.TreeAdapter;
25
import org.eclipse.swt.custom.CCombo;
23
import org.eclipse.swt.custom.StyledText;
26
import org.eclipse.swt.custom.StyledText;
24
import org.eclipse.swt.widgets.Button;
27
import org.eclipse.swt.widgets.Button;
28
import org.eclipse.swt.widgets.Combo;
25
import org.eclipse.swt.widgets.List;
29
import org.eclipse.swt.widgets.List;
26
import org.eclipse.swt.widgets.Menu;
30
import org.eclipse.swt.widgets.Menu;
27
import org.eclipse.swt.widgets.MenuItem;
31
import org.eclipse.swt.widgets.MenuItem;
Lines 39-45 public class SWTAdapterFactory implements IUIAdapterFactory { Link Here
39
    /** */
43
    /** */
40
    private static final Class[] SUPPORTEDCLASSES = 
44
    private static final Class[] SUPPORTEDCLASSES = 
41
            new Class[]{Button.class, Menu.class, MenuItem.class, Tree.class,
45
            new Class[]{Button.class, Menu.class, MenuItem.class, Tree.class,
42
                Table.class, List.class, Text.class, StyledText.class};
46
                Table.class, List.class, Text.class, StyledText.class,
47
                Combo.class, CCombo.class};
43
    
48
    
44
    
49
    
45
    /**
50
    /**
Lines 70-75 public class SWTAdapterFactory implements IUIAdapterFactory { Link Here
70
            returnvalue = new TextComponentAdapter(objectToAdapt);
75
            returnvalue = new TextComponentAdapter(objectToAdapt);
71
        } else if (objectToAdapt instanceof StyledText) {
76
        } else if (objectToAdapt instanceof StyledText) {
72
            returnvalue = new StyledTextAdapter(objectToAdapt);
77
            returnvalue = new StyledTextAdapter(objectToAdapt);
78
        } else if (objectToAdapt instanceof Combo) {
79
            returnvalue = new ComboAdapter(objectToAdapt);
80
        } else if (objectToAdapt instanceof CCombo) {
81
            returnvalue = new CComboAdapter(objectToAdapt);
73
        }
82
        }
74
        
83
        
75
        
84
        
(-)a/org.eclipse.jubula.toolkit.provider.swing/resources/xml/ComponentConfiguration.xml (-1 / +1 lines)
Lines 42-48 Link Here
42
	
42
	
43
	<toolkitComponent type="javax.swing.JComboBox" visible="false">
43
	<toolkitComponent type="javax.swing.JComboBox" visible="false">
44
		<realizes>guidancer.concrete.ComboBox</realizes>
44
		<realizes>guidancer.concrete.ComboBox</realizes>
45
		<testerClass>org.eclipse.jubula.rc.swing.swing.caps.JComboBoxCAPs</testerClass>
45
		<testerClass>org.eclipse.jubula.rc.common.caps.AbstractComboBoxCAPs</testerClass>
46
		<componentClass name="javax.swing.JComboBox" />
46
		<componentClass name="javax.swing.JComboBox" />
47
	</toolkitComponent>
47
	</toolkitComponent>
48
	
48
	
(-)a/org.eclipse.jubula.toolkit.provider.swt/resources/xml/ComponentConfiguration.xml (-3 / +2 lines)
Lines 209-221 Link Here
209
	
209
	
210
	<toolkitComponent type="org.eclipse.swt.widgets.Combo" visible="false">
210
	<toolkitComponent type="org.eclipse.swt.widgets.Combo" visible="false">
211
		<realizes>guidancer.abstract.SwtCombo</realizes>
211
		<realizes>guidancer.abstract.SwtCombo</realizes>
212
		<testerClass>org.eclipse.jubula.rc.swt.implclasses.ComboImplClass</testerClass>
212
		<testerClass>org.eclipse.jubula.rc.common.caps.AbstractComboBoxCAPs</testerClass>
213
		<componentClass name="org.eclipse.swt.widgets.Combo" />
213
		<componentClass name="org.eclipse.swt.widgets.Combo" />
214
	</toolkitComponent>
214
	</toolkitComponent>
215
	
215
	
216
	<toolkitComponent type="org.eclipse.swt.custom.CCombo" visible="false">
216
	<toolkitComponent type="org.eclipse.swt.custom.CCombo" visible="false">
217
		<realizes>guidancer.abstract.SwtCombo</realizes>
217
		<realizes>guidancer.abstract.SwtCombo</realizes>
218
		<testerClass>org.eclipse.jubula.rc.swt.implclasses.CComboImplClass</testerClass>
218
		<testerClass>org.eclipse.jubula.rc.common.caps.AbstractComboBoxCAPs</testerClass>
219
		<componentClass name="org.eclipse.swt.custom.CCombo" />
219
		<componentClass name="org.eclipse.swt.custom.CCombo" />
220
	</toolkitComponent>
220
	</toolkitComponent>
221
	
221
	
222
- 

Return to bug 394179