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/META-INF/MANIFEST.MF (+3 lines)
Lines 7-12 Bundle-Vendor: Eclipse Jubula Link Here
7
Export-Package: org.eclipse.jubula.rc.common,
7
Export-Package: org.eclipse.jubula.rc.common,
8
 org.eclipse.jubula.rc.common.adaptable,
8
 org.eclipse.jubula.rc.common.adaptable,
9
 org.eclipse.jubula.rc.common.businessprocess,
9
 org.eclipse.jubula.rc.common.businessprocess,
10
 org.eclipse.jubula.rc.common.caps,
10
 org.eclipse.jubula.rc.common.classloader,
11
 org.eclipse.jubula.rc.common.classloader,
11
 org.eclipse.jubula.rc.common.commands,
12
 org.eclipse.jubula.rc.common.commands,
12
 org.eclipse.jubula.rc.common.components,
13
 org.eclipse.jubula.rc.common.components,
Lines 18-23 Export-Package: org.eclipse.jubula.rc.common, Link Here
18
 org.eclipse.jubula.rc.common.listener,
19
 org.eclipse.jubula.rc.common.listener,
19
 org.eclipse.jubula.rc.common.logger,
20
 org.eclipse.jubula.rc.common.logger,
20
 org.eclipse.jubula.rc.common.registration,
21
 org.eclipse.jubula.rc.common.registration,
22
 org.eclipse.jubula.rc.common.uiadapter.factory,
23
 org.eclipse.jubula.rc.common.uiadapter.interfaces,
21
 org.eclipse.jubula.rc.common.util
24
 org.eclipse.jubula.rc.common.util
22
Require-Bundle: org.apache.commons.beanutils;bundle-version="[1.7.0,2.0.0)",
25
Require-Bundle: org.apache.commons.beanutils;bundle-version="[1.7.0,2.0.0)",
23
 org.apache.commons.lang;bundle-version="[2.4.0,3.0.0)",
26
 org.apache.commons.lang;bundle-version="[2.4.0,3.0.0)",
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractButtonCAPs.java (+83 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.implclasses.MatchUtil;
14
import org.eclipse.jubula.rc.common.implclasses.Verifier;
15
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IButtonAdapter;
16
17
18
/**
19
 * Implementation for all Button like classes, it holds the
20
 * general methods for the testing of buttons.
21
 * 
22
 * @author BREDEX GmbH
23
 *
24
 */
25
public abstract class AbstractButtonCAPs extends AbstractWidgetCAPs {
26
27
    /**
28
     * Action to read the value of a JButton to store it in a variable in the
29
     * Client
30
     * 
31
     * @param variable the name of the variable
32
     * @return the text value.
33
     */
34
    public String gdReadValue(String variable) {
35
        return ((IButtonAdapter) this.getComponent()).getText();
36
    }
37
    /**
38
     * 
39
     * @return the IButtonAdapter for the component. 
40
     */
41
    private IButtonAdapter getButtonAdapter() {
42
        return (IButtonAdapter)getComponent();
43
    }
44
45
    /**
46
     * Verifies the selected property.
47
     * 
48
     * @param selected The selected property value to verify.
49
     */
50
    public void gdVerifySelected(boolean selected) {
51
52
        Verifier.equals(selected, getButtonAdapter().isSelected());
53
    }
54
    
55
    /**
56
     * Verifies the passed text.
57
     * 
58
     * @param text The text to verify
59
     * @param operator The RegEx operator used to verify
60
     */
61
    public void gdVerifyText(String text, String operator) {
62
        verifyText(text, operator);
63
    }
64
65
    /**
66
     * Verifies the passed text.
67
     * 
68
     * @param text The text to verify
69
     */
70
    public void gdVerifyText(String text) {
71
        gdVerifyText(text, MatchUtil.DEFAULT_OPERATOR);
72
    }
73
    /**
74
     * Verifies the passed text.
75
     * @param text The text to verify
76
     * @param operator The operator used to verify
77
     */
78
    public void verifyText(String text, String operator) {
79
        String value = getButtonAdapter().getText();
80
        Verifier.match(value, text, operator);
81
    }
82
83
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractMenuCAPs.java (+584 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 java.util.ArrayList;
14
import java.util.List;
15
16
import org.eclipse.jubula.rc.common.driver.ClickOptions;
17
import org.eclipse.jubula.rc.common.driver.RobotTiming;
18
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
19
import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
20
import org.eclipse.jubula.rc.common.implclasses.MenuUtilBase;
21
import org.eclipse.jubula.rc.common.implclasses.Verifier;
22
import org.eclipse.jubula.rc.common.logger.AutServerLogger;
23
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
24
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
25
import org.eclipse.jubula.tools.i18n.I18n;
26
import org.eclipse.jubula.tools.objects.event.EventFactory;
27
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
28
import org.eclipse.jubula.tools.utils.TimeUtil;
29
30
/**
31
 * General implementation for Menus. Also used for context menus
32
 * if they behave the same.
33
 * 
34
 * @author BREDEX GmbH
35
 * 
36
 */
37
public abstract class AbstractMenuCAPs extends AbstractUICAPs {
38
39
    /** the logger */
40
    private static AutServerLogger log = new AutServerLogger(
41
            AbstractMenuCAPs.class);
42
43
    /**
44
     * @return the log
45
     */
46
    public static AutServerLogger getLog() {
47
        return log;
48
    }
49
50
    /**
51
     * This method gets the object which should implementet the menu Interface.
52
     * It is saved as Component so it must be casted.
53
     * @return the MenuAdapter
54
     */
55
    public IMenuAdapter getMenuAdapter() {
56
        return (IMenuAdapter) getComponent(); 
57
    }
58
    /**
59
     * Checks if the specified menu item is enabled.
60
     * 
61
     * @param menuItem the menu item as a text path to verify against
62
     * @param operator operator used for matching
63
     * @param enabled is the specified menu item enabled?
64
     */
65
    public void verifyEnabled(String menuItem, String operator, boolean enabled)
66
    {
67
        verifyEnabled(MenuUtilBase.splitPath(menuItem), operator, enabled);
68
    }
69
70
    /**
71
     * Checks if the specified menu item is enabled.
72
     * 
73
     * @param menuItem the menu item to verify against
74
     * @param operator operator used for matching
75
     * @param enabled is the specified menu item enabled?
76
     */
77
    public void verifyEnabled(String[] menuItem, String operator,
78
            boolean enabled) {
79
        checkPathLength(menuItem.length);
80
        final IMenuItemAdapter item = navigateToMenuItem(
81
                getAndCheckMenu(), menuItem, operator);
82
        checkIsNull(item);
83
        try {
84
            Verifier.equals(enabled, item.isEnabled());
85
        } finally {
86
            closeMenu(getAndCheckMenu(), menuItem, operator);
87
        }
88
89
    }
90
    /**
91
     * Checks if the given MenuItemAdapter is null and thorws an Exception
92
     * 
93
     * @param item the MenuItemAdapter which should be checked
94
     */
95
    private void checkIsNull(final IMenuItemAdapter item) {
96
        if (item.getRealComponent() == null) {
97
            throwMenuItemNotFound();
98
        }
99
    }
100
101
    /**
102
     * Checks if the specified menu item is enabled.
103
     * 
104
     * @param menuItem the menu item as a text path to verify against
105
     * @param enabled is the specified menu item enabled?
106
     */
107
    public void verifyEnabledByIndexpath(String menuItem, boolean enabled) {
108
        verifyEnabledByIndexpath(MenuUtilBase.splitIndexPath(menuItem),
109
                enabled);
110
    }
111
112
    /**
113
     * Checks if the specified menu item is enabled.
114
     * 
115
     * @param menuItem the menu item to verify against
116
     * @param enabled is the specified menu item enabled?
117
     */
118
    public void verifyEnabledByIndexpath(int[] menuItem, boolean enabled) {
119
        checkPathLength(menuItem.length);
120
        final IMenuItemAdapter item = navigateToMenuItem(
121
                getAndCheckMenu(), menuItem);
122
        checkIsNull(item);
123
        try {
124
            Verifier.equals(enabled, item.isEnabled());
125
        } finally {
126
            closeMenu(getAndCheckMenu(), menuItem);
127
        }
128
    }
129
130
131
132
    /**
133
     * Verifies if the specified menu item exists
134
     * 
135
     * @param menuItem the menu item to verifiy against
136
     * @param operator operator used for matching
137
     * @param exists  should the menu item exist?
138
     */
139
    public void verifyExists(String menuItem, String operator, boolean exists) {
140
        verifyExists(MenuUtilBase.splitPath(menuItem), operator, exists);
141
    }
142
143
    /**
144
     * Verifies if the specified menu item exists
145
     * 
146
     * @param menuItem the menu item to verify against
147
     * @param operator operator used for matching
148
     * @param exists should the menu item exist?
149
     */
150
    public void verifyExists(String[] menuItem, String operator, boolean exists)
151
    {
152
        checkPathLength(menuItem.length);
153
        final IMenuItemAdapter item = navigateToMenuItem(
154
                getAndCheckMenu(), menuItem, operator);
155
        try {
156
            Verifier.equals(exists, item.isExisting());
157
        } finally {
158
            closeMenu(getAndCheckMenu(), menuItem, operator);
159
        }
160
    }
161
162
163
    /**
164
     * Verifies if the specified menu item exists
165
     * @param menuItem the menu item to verifiy against
166
     * @param exists should the menu item exist?
167
     */
168
    public void verifyExistsByIndexpath(String menuItem, boolean exists) {
169
        verifyExistsByIndexpath(MenuUtilBase.splitIndexPath(menuItem), exists);
170
    }
171
172
    /**
173
     * Verifies if the specified menu item exists
174
     * 
175
     * @param menuItem the menu item to verify against
176
     * @param exists should the menu item exist?
177
     */
178
    public void verifyExistsByIndexpath(int[] menuItem, boolean exists) {
179
        checkPathLength(menuItem.length);
180
        final IMenuItemAdapter item = navigateToMenuItem(
181
                        getAndCheckMenu(), menuItem);
182
        try {
183
            Verifier.equals(exists, item.isExisting());
184
        } finally {
185
            closeMenu(getAndCheckMenu(), menuItem);
186
        }
187
188
    }
189
190
    /**
191
     * Checks if the specified menu item is selected.
192
     * 
193
     * @param menuItem the menu item to verify against
194
     * @param operator operator used for matching
195
     * @param selected is the specified menu item selected?
196
     */
197
    public void verifySelected(String menuItem, String operator,
198
            boolean selected) {
199
        verifySelected(MenuUtilBase.splitPath(menuItem), operator, selected);
200
    }
201
202
    /**
203
     * Checks if the specified menu item is selected.
204
     * 
205
     * @param menuItem the menu item to verify against
206
     * @param operator operator used for matching
207
     * @param selected is the specified menu item selected?
208
     */
209
    public void verifySelected(String[] menuItem, String operator,
210
            boolean selected) {
211
        checkPathLength(menuItem.length);
212
        final IMenuItemAdapter item = navigateToMenuItem(
213
                getAndCheckMenu(), menuItem, operator);
214
        checkIsNull(item);
215
        try {
216
            Verifier.equals(selected, item.isSelected());
217
218
        } finally {
219
            closeMenu(getAndCheckMenu(), menuItem, operator);
220
        }
221
222
    }
223
224
    /**
225
     * Checks if the specified menu item is selected.
226
     * 
227
     * @param menuItem the menu item to verify against
228
     * @param selected is the specified menu item selected?
229
     */
230
    public void verifySelectedByIndexpath(String menuItem, boolean selected) {
231
        verifySelectedByIndexpath(MenuUtilBase.splitIndexPath(menuItem),
232
                selected);
233
    }
234
235
    /**
236
     * Checks if the specified menu item is selected.
237
     * 
238
     * @param menuItem the menu item to verify against
239
     * @param selected is the specified menu item selected?
240
     */
241
    public void verifySelectedByIndexpath(int[] menuItem, boolean selected) {
242
        checkPathLength(menuItem.length);
243
        final IMenuItemAdapter item = navigateToMenuItem(
244
                getAndCheckMenu(), menuItem);
245
        checkIsNull(item);
246
        try {
247
            Verifier.equals(selected, item.isSelected());
248
249
        } finally {
250
            closeMenu(getAndCheckMenu(), menuItem);
251
252
        }
253
254
    }
255
    
256
    /**
257
     * Tries to select a menu item in a menu defined by an Index-Path
258
     * @param indexPath the menu item to select
259
     */
260
    public void selectMenuItemByIndexpath(String indexPath) {
261
        int[] indexItems = MenuUtilBase.splitIndexPath(indexPath);
262
        checkPathLength(indexItems.length);
263
        
264
        try {
265
            final IMenuItemAdapter item = navigateToMenuItem(
266
                    getAndCheckMenu(), indexItems);
267
        
268
            checkIsNull(item);
269
            
270
            item.selectMenuItem();
271
        } catch (StepExecutionException e) {
272
            try {
273
                closeMenu(getAndCheckMenu(), indexItems);
274
            } catch (StepExecutionException e1) {
275
                // Menu item is disabled or menu is already closed
276
                // Do nothing
277
                if (getLog().isInfoEnabled()) {
278
                    getLog().info("Tried to close a disabled or already closed menu."); //$NON-NLS-1$
279
                }
280
            }
281
            throwMenuItemNotFound();
282
        }
283
        
284
    }
285
    
286
    /**
287
     * Tries to select a menu item in a menu defined by a Text-Path
288
     * @param namePath the menu item to select
289
     * @param operator operator used for matching
290
     */
291
    public void selectMenuItem(String namePath, final String operator) {
292
        String[] menuItems = MenuUtilBase.splitPath(namePath);
293
        if (menuItems.length == 0) {
294
            throw new StepExecutionException("empty path to menuitem not allowed", //$NON-NLS-1$
295
                EventFactory.createActionError());
296
        }
297
        IMenuItemAdapter item = navigateToMenuItem(getAndCheckMenu(), 
298
                menuItems, operator);
299
        if (item == null) {
300
            try {
301
                closeMenu(getAndCheckMenu(), menuItems, operator);
302
            } catch (StepExecutionException see) {
303
                // Menu item is disabled or menu is already closed
304
                // Do nothing
305
                getLog().info("Tried to close a disabled or already closed menu."); //$NON-NLS-1$
306
            }
307
            throw new StepExecutionException("no such menu item found", //$NON-NLS-1$
308
                EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
309
        }
310
        item.selectMenuItem();
311
    }
312
    
313
314
    /**
315
     * 
316
     * @return the IMenuAdapter.
317
     * @throws StepExecutionException
318
     *             if the active window has no menu bar.
319
     */
320
    protected IMenuAdapter getAndCheckMenu() throws StepExecutionException {
321
        Object menu = getMenuAdapter().getRealComponent();
322
        // Verify that the active window has a menu bar
323
        if (menu == null) {
324
            throw new StepExecutionException(
325
                    I18n.getString(TestErrorEvent.NO_MENU_BAR),
326
                    EventFactory.createActionError(TestErrorEvent.NO_MENU_BAR));
327
        }
328
        return getMenuAdapter();
329
    }
330
331
    /**
332
     * 
333
     */
334
    private void throwMenuItemNotFound() {
335
        throw new StepExecutionException("no such menu item found", //$NON-NLS-1$
336
                EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
337
    }
338
    
339
340
    /**
341
     * this methods closes the hole menu. It is clicking on the parent item in the menu bar.
342
     * 
343
     * If you need another implementation override this method.
344
     * @param menuBar the main menu
345
     * @param textPath the text path used for opening the menu
346
     * @param operator the operator which was used for opening the menu
347
     */
348
    protected void closeMenu(IMenuAdapter menuBar, String[] textPath,
349
            String operator) {
350
        IMenuItemAdapter menuitem = findMenu(menuBar,
351
                getIndexForName(menuBar, textPath[0], operator));
352
        if (menuitem.getRealComponent() != null) {
353
            getRobot().click(
354
                    menuitem.getRealComponent(),
355
                    null,
356
                    ClickOptions.create().setClickType(
357
                            ClickOptions.ClickType.RELEASED));
358
        
359
        }
360
    
361
    }
362
    /**
363
     * this methods closes the hole menu. It is clicking on the parent item in the menu bar.
364
     * 
365
     * If you need another implementation override this method. 
366
     * @param menuBar the main menu
367
     * @param path the integer based path used for opening the menu
368
     */
369
    protected void closeMenu(IMenuAdapter menuBar, int[] path) {
370
        IMenuItemAdapter menuitem = findMenu(menuBar, path[0]);
371
        if (menuitem.getRealComponent() != null) {
372
            getRobot().click(
373
                menuitem.getRealComponent(),
374
                null,
375
                ClickOptions.create().setClickType(
376
                        ClickOptions.ClickType.RELEASED));
377
            
378
        }
379
    }
380
    
381
    /**
382
     * Gets the index of the specific menu entry with the name
383
     * 
384
     * @param menu the menu in which all items are stored
385
     * @param name the name of the item we want the index from
386
     * @param operator the operator for the matching
387
     * @return the index for the specific menu entry
388
     */
389
    protected int getIndexForName(IMenuAdapter menu, String name,
390
            String operator) {
391
        IMenuItemAdapter [] subElements = menu.getItems();
392
        int downcount = 0;
393
        for (int j = 0; j < subElements.length; j++) {               
394
            IMenuItemAdapter tempMenu = (IMenuItemAdapter)subElements[j];
395
            if (tempMenu.isSeparator()) {
396
                downcount++;
397
            }
398
            if (tempMenu.isShowing()
399
                    && MatchUtil.getInstance().match(
400
                            tempMenu.getText(), name, operator)) {
401
                return j - downcount;
402
            }
403
        }
404
        return Integer.MAX_VALUE;
405
    }
406
    
407
    
408
    /**
409
     * implementation for "wait for component"
410
     * @param timeout the maximum amount of time to wait for the component
411
     * @param delay the time to wait after the component is found
412
     */
413
    public void waitForComponent(int timeout, int delay) {
414
        if (getComponent().getRealComponent() == null) {
415
            long start = System.currentTimeMillis();
416
            do {
417
                RobotTiming.sleepWaitForComponentPollingDelay();
418
            } while (System.currentTimeMillis() - start < timeout
419
                    && getComponent().getRealComponent() == null);
420
            if (getComponent().getRealComponent() == null) {
421
                throw new StepExecutionException("No Menubar found.", //$NON-NLS-1$
422
                        EventFactory.createComponentNotFoundErrorEvent());
423
            }
424
        }
425
        TimeUtil.delay(delay);
426
    }
427
    
428
    /**
429
     * Tries to navigate through the menu to the specified menu item.
430
     * This method should be overridden if there is a need for a faster implementation.
431
     * 
432
     * @param menuBar the menubar
433
     * @param path the path where to navigate in the menu.
434
     * @param operator operator used for matching
435
     * @return the adapter at the end of the specified path or a adapter that contains no component.
436
     */
437
    protected IMenuItemAdapter navigateToMenuItem(
438
            IMenuAdapter menuBar, String[] path, String operator) {
439
        checkPathLength(path.length);
440
        IMenuAdapter currentmenu = menuBar;
441
        IMenuItemAdapter currentMenuItem = null;
442
        final int pathLength = path.length;
443
        final int beforeLast = pathLength - 1;
444
        
445
        for (int i = 0; i < path.length; i++) {
446
            int pathIndex = getIndexForName(currentmenu, path[i], operator);
447
            currentMenuItem = getNextMenuItem(currentmenu, pathIndex);
448
            
449
            if ((currentMenuItem.getRealComponent() == null) 
450
                    && (i < beforeLast)) {                
451
                return currentMenuItem;
452
            }
453
            
454
            if (i < beforeLast) {            
455
                if (!currentMenuItem.hasSubMenu()) {
456
                    // the given path is longer than the menu levels
457
                    return newMenuItemAdapter(null);
458
                }
459
                currentmenu = currentMenuItem.openSubMenu();
460
            }
461
        }
462
        return currentMenuItem;
463
    }
464
    
465
    /**
466
     * Tries to navigate through the menu to the specified menu item.
467
     * This method should be overridden if there is a need for a faster implementation.
468
     * 
469
     * @param menubar the menubar
470
     * @param path the path where to navigate in the menu.
471
     * @return -the adapter at the end of the specified path or a adapter that contains no component.
472
     */
473
    protected IMenuItemAdapter navigateToMenuItem(
474
            IMenuAdapter menubar, int[] path) {
475
        checkPathLength(path.length);
476
        
477
        IMenuAdapter currentmenu = menubar;
478
        IMenuItemAdapter currentMenuItem = null;
479
        final int pathLength = path.length;
480
        final int beforeLast = pathLength - 1;
481
            
482
        for (int i = 0; i < path.length; i++) {
483
            final int pathIndex = path[i];
484
            currentMenuItem = getNextMenuItem(currentmenu, pathIndex);
485
            
486
            if ((currentMenuItem.getRealComponent() == null) 
487
                    && (i < beforeLast)) {                
488
                return currentMenuItem;
489
            }
490
            
491
            if (i < beforeLast) {            
492
                if (!currentMenuItem.hasSubMenu()) {
493
                    // the given path is longer than the menu levels
494
                    return newMenuItemAdapter(null);
495
                }
496
                currentmenu = currentMenuItem.openSubMenu();
497
            }
498
            
499
                
500
                
501
        }
502
     
503
        return currentMenuItem;
504
    }
505
    /**
506
     * gets the next menu item adapter from its specific index
507
     * @param currentmenu the current menu
508
     * @param pathIndex the index from the next menu item
509
     * @return the wanted menu item in a adapter
510
     */
511
    private IMenuItemAdapter getNextMenuItem(IMenuAdapter currentmenu,
512
            final int pathIndex) {
513
        IMenuItemAdapter currentMenuItem;
514
        if (pathIndex < 0) {
515
            throwInvalidPathException();            
516
        }
517
        currentMenuItem = findMenu(currentmenu, pathIndex);
518
        return currentMenuItem;
519
    }
520
521
    
522
    
523
524
    
525
526
527
528
529
    /**
530
     * @param menu menu 
531
     * @param idx index of the current wanted item
532
     * @return the next IMenuItemAdapter from the next cascade
533
     */
534
    private IMenuItemAdapter findMenu(IMenuAdapter menu, int idx) {
535
        List visibleSubMenus = new ArrayList();
536
        IMenuItemAdapter[] subElements = menu.getItems();
537
        
538
        for (int i = 0; i < subElements.length; ++i) {
539
            
540
            IMenuItemAdapter menuitem = subElements[i];
541
            if (menuitem.getRealComponent() != null && !menuitem.isSeparator() 
542
                    && menuitem.isShowing()) {
543
                visibleSubMenus.add(menuitem);
544
            }
545
            
546
        }
547
        
548
        if (idx >= visibleSubMenus.size() || idx < 0) {
549
            return newMenuItemAdapter(null);
550
        }
551
        
552
        return (IMenuItemAdapter) visibleSubMenus.get(idx);
553
        
554
    }
555
    
556
    
557
    /**
558
     * Checks the path for it length and throws and StepExecutionExecption if it is 0
559
     * @param length the path length to be checked
560
     */
561
    private void checkPathLength(int length) {
562
        if (length < 1) { 
563
            throw new StepExecutionException("empty path to menuitem is not allowed", EventFactory //$NON-NLS-1$
564
                    .createActionError(
565
                            TestErrorEvent.INVALID_PARAM_VALUE));            
566
        }
567
    }
568
    
569
    /**
570
     * 
571
     */
572
    private static void throwInvalidPathException() {
573
        throw new StepExecutionException("invalid path", EventFactory //$NON-NLS-1$
574
          .createActionError(TestErrorEvent.INVALID_PARAM_VALUE));
575
    }
576
    /**
577
     * This adapts or puts the new MenuItem in the context which is needed for
578
     * the algorithms.
579
     * @param component the new MenuItem which is used by the next step
580
     * @return the adapted or casted MenuItem
581
     */
582
    protected abstract IMenuItemAdapter newMenuItemAdapter(Object component);
583
584
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTableCAPs.java (+1196 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 java.awt.Rectangle;
14
import java.util.StringTokenizer;
15
16
import org.eclipse.jubula.rc.common.CompSystemConstants;
17
import org.eclipse.jubula.rc.common.driver.ClickOptions;
18
import org.eclipse.jubula.rc.common.driver.DragAndDropHelper;
19
import org.eclipse.jubula.rc.common.driver.IRobot;
20
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
21
import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
22
import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
23
import org.eclipse.jubula.rc.common.implclasses.Verifier;
24
import org.eclipse.jubula.rc.common.implclasses.table.Cell;
25
import org.eclipse.jubula.rc.common.logger.AutServerLogger;
26
import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITableAdapter;
27
import org.eclipse.jubula.rc.common.util.KeyStrokeUtil;
28
import org.eclipse.jubula.tools.constants.InputConstants;
29
import org.eclipse.jubula.tools.objects.event.EventFactory;
30
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
31
import org.eclipse.jubula.tools.utils.TimeUtil;
32
33
/**
34
 * General implementation for tables.
35
 * 
36
 * @author BREDEX GmbH
37
 */
38
public abstract class AbstractTableCAPs extends AbstractTextInputSupport {
39
    
40
    /** the logger */
41
    private static AutServerLogger log = new AutServerLogger(
42
            AbstractMenuCAPs.class);
43
44
    /**
45
     * @return the log
46
     */
47
    public static AutServerLogger getLog() {
48
        return log;
49
    }
50
    
51
    /**
52
     * This method is mostly needed for clicks
53
     * @return the real table as object
54
     */
55
    private Object getRealTable() {
56
        return getComponent().getRealComponent();
57
    }
58
    /**
59
     * 
60
     * @return the ITableAdapter of this table
61
     */
62
    private ITableAdapter getTableAdapter() {
63
        return (ITableAdapter) getComponent();
64
    }
65
    
66
    /**
67
     * Verifies the rendered text inside the currently selected cell.
68
     *
69
     * @param text The cell text to verify.
70
     * @throws StepExecutionException
71
     *      If there is no selected cell, or if the rendered text cannot
72
     *      be extracted.
73
     */
74
    public void gdVerifyText(String text)
75
        throws StepExecutionException {
76
77
        gdVerifyText(text, MatchUtil.DEFAULT_OPERATOR);
78
    }
79
    
80
    /**
81
     * Verifies the rendered text inside the currently selected cell.
82
     * @param text The cell text to verify.
83
     * @param operator The operation used to verify
84
     * @throws StepExecutionException If there is no selected cell, or if the rendered text cannot be extracted.
85
     */
86
    public void gdVerifyText(String text, String operator)
87
        throws StepExecutionException {
88
        ITableAdapter adapter = getTableAdapter();
89
        Cell cell = adapter.getSelectedCell();
90
        final int implRow = cell.getRow();
91
        final int implCol = cell.getCol();
92
        checkRowColBounds(implRow, implCol);
93
94
        adapter.scrollCellToVisible(implRow, implCol);
95
        final String current = getCellText(implRow, implCol);
96
        Verifier.match(current, text, operator);
97
    }
98
    
99
    /**
100
     * Verifies the rendered text inside the passed cell.
101
     * @param row The row of the cell.
102
     * @param rowOperator The row header operator
103
     * @param col The column of the cell.
104
     * @param colOperator The column header operator
105
     * @param text The cell text to verify.
106
     * @param operator The operation used to verify
107
     * @throws StepExecutionException If the row or the column is invalid, or if the rendered text cannot be extracted.
108
     */
109
    public void gdVerifyText(String text, String operator, final String row,
110
            final String rowOperator, final String col,
111
            final String colOperator) throws StepExecutionException {
112
        ITableAdapter adapter = getTableAdapter();
113
        final int implRow = adapter.getRowFromString(row, rowOperator);
114
        final int implCol = adapter.getColumnFromString(col, colOperator);
115
        String current;
116
        //if row is header and column is existing
117
        if (implRow == -1 && implCol > -1) {
118
            current = adapter.getColumnName(implCol);        
119
        } else {
120
            checkRowColBounds(implRow, implCol);
121
            adapter.scrollCellToVisible(implRow, implCol);
122
            current = getCellText(implRow, implCol);
123
        }
124
        
125
        
126
127
        
128
        Verifier.match(current, text, operator);
129
    }
130
    
131
    /**
132
     * Selects the cell of the Table.<br>
133
     * With the xPos, yPos, xunits and yUnits the click position inside the cell can be defined.
134
     * @param row The row of the cell.
135
     * @param rowOperator The row header operator
136
     * @param col The column of the cell.
137
     * @param colOperator The column header operator
138
     * @param clickCount The number of clicks with the right mouse button
139
     * @param xPos what x position
140
     * @param xUnits should x position be pixel or percent values
141
     * @param yPos what y position
142
     * @param yUnits should y position be pixel or percent values
143
     * @param extendSelection Should this selection be part of a multiple selection
144
     * @param button what mouse button should be used
145
     * @throws StepExecutionException If the row or the column is invalid
146
     */
147
    public void gdSelectCell(final String row, final String rowOperator,
148
        final String col, final String colOperator,
149
        final int clickCount, final int xPos, final String xUnits,
150
        final int yPos, final String yUnits, final String extendSelection,
151
        int button) 
152
        throws StepExecutionException {
153
        ITableAdapter adapter = getTableAdapter();
154
        final int implRow = adapter.getRowFromString(row, rowOperator);
155
        final int implCol = adapter.getColumnFromString(col, colOperator);
156
        final boolean isExtendSelection = extendSelection.equals(
157
                CompSystemConstants.EXTEND_SELECTION_YES); 
158
        if (log.isDebugEnabled()) {
159
            log.debug("Selecting row, col: " + row + ", " + col); //$NON-NLS-1$//$NON-NLS-2$
160
        }
161
        
162
        Rectangle cellBounds;
163
        //if row is header and col is existing
164
        if (implRow == -1 && implCol > -1) {
165
            cellBounds = adapter.getHeaderBounds(implCol);
166
        } else {
167
            cellBounds = adapter.scrollCellToVisible(implRow, implCol);
168
        }        
169
        Object o = getSpecificRectangle(cellBounds);
170
        ClickOptions clickOptions = ClickOptions.create();
171
        clickOptions.setClickCount(clickCount).setScrollToVisible(false);
172
        clickOptions.setMouseButton(button);
173
        try {
174
            if (isExtendSelection) {
175
                getRobot().keyPress(getRealTable(),
176
                        getExtendSelectionModifier());
177
            }
178
            getRobot().click(getRealTable(), o, clickOptions, 
179
                    xPos, xUnits.equalsIgnoreCase(POS_UNIT_PIXEL), 
180
                    yPos, yUnits.equalsIgnoreCase(POS_UNIT_PIXEL));
181
        } finally {
182
            if (isExtendSelection) {
183
                getRobot().keyRelease(getRealTable(),
184
                        getExtendSelectionModifier());
185
            }
186
        }
187
    }
188
    /**
189
     * This is a workaround because the toolkit specific
190
     * Robot implementation are using different rectangle types.
191
     * @param rectangle the java.awt.rectangle which needs to 
192
     *          casted
193
     * @return the rectangle in the type for the specific robot
194
     */
195
    protected Object getSpecificRectangle(Rectangle rectangle) {
196
        //FIXME changing the Robots might be useful here
197
        return rectangle;
198
    }
199
    /**
200
     * Verifies, if value exists in column.
201
     *
202
     * @param col The column of the cell.
203
     * @param colOperator the column header operator
204
     * @param value The cell text to verify.
205
     * @param operator The operation used to verify
206
     * @param searchType Determines where the search begins ("relative" or "absolute")
207
     * @param exists true if value exists, false otherwise
208
     * @throws StepExecutionException
209
     *             If the row or the column is invalid, or if the rendered text
210
     *             cannot be extracted.
211
     */
212
    public void gdVerifyValueInColumn(final String col,
213
            final String colOperator, final String value,
214
            final String operator, final String searchType, boolean exists)
215
        throws StepExecutionException {
216
        ITableAdapter adapter = getTableAdapter();
217
        final int implCol = adapter.getColumnFromString(col, colOperator);
218
        
219
        
220
        boolean valueExists = isValueExisting(adapter, implCol,
221
                value, operator, searchType);
222
223
        Verifier.equals(exists, valueExists);
224
    }
225
    /**
226
     * Looks if value exists in the Column.
227
     * 
228
     * @param adapter the teble adapter working on.
229
     * @param implCol the implementation column of the cell.
230
     * @param value the cellt text to verify.
231
     * @param operator The operation used to verify.
232
     * @param searchType searchType Determines where the search begins ("relative" or "absolute")
233
     * @return <code>true</code> it the value exists in the column
234
     */
235
    private boolean isValueExisting(ITableAdapter adapter, int implCol, 
236
            String value, String operator, final String searchType) {
237
        final int rowCount = adapter.getRowCount();
238
        for (int i = getStartingRowIndex(searchType);
239
                i < rowCount; ++i) {
240
            if (MatchUtil.getInstance().match(getCellText(i,
241
                            implCol), value, operator)) {
242
                return true;
243
            }
244
        }
245
        if (adapter.isHeaderVisible()) {
246
            String header = adapter.getColumnName(implCol);
247
            if (MatchUtil.getInstance().match(header, value,
248
                                operator)) {
249
                return true;
250
            }
251
        }
252
        return false;
253
    }
254
    
255
    
256
    
257
    /**
258
     * Verifies, if value exists in row..
259
     *
260
     * @param row The row of the cell.
261
     * @param rowOperator the row header operator
262
     * @param value The cell text to verify.
263
     * @param operator The operation used to verify
264
     * @param searchType Determines where the search begins ("relative" or "absolute")
265
     * @param exists true if value exists, false otherwise
266
     * @throws StepExecutionException
267
     *             If the row or the column is invalid, or if the rendered text
268
     *             cannot be extracted.
269
     */
270
    public void gdVerifyValueInRow(final String row, final String rowOperator,
271
            final String value, final String operator, final String searchType,
272
            boolean exists)
273
        throws StepExecutionException {
274
        final ITableAdapter adapter = getTableAdapter();
275
        final int implRow = adapter.getRowFromString(row, rowOperator);
276
        boolean valueIsExisting = false;
277
        //if row is header
278
        if (implRow == -1) {
279
            
280
            for (int k = getStartingColIndex(searchType); 
281
                                    k < adapter.getColumnCount(); ++k) {
282
                if (MatchUtil.getInstance().match(
283
                        adapter.getColumnName(k),
284
                        value, operator)) {
285
                    valueIsExisting = true;
286
                    break;
287
                }
288
            }
289
                            
290
                        
291
        } else {
292
            
293
            final int columnCount = adapter.getColumnCount();
294
            if (columnCount > 0) {
295
                for (int i = getStartingColIndex(searchType); 
296
                        i < columnCount; ++i) {
297
                    if (MatchUtil.getInstance().match(
298
                            getCellText(implRow, i), value, operator)) {
299
                        valueIsExisting = true;
300
                        break;
301
                    }
302
                }
303
            } else {
304
                // No columns found. This table is used to present a
305
                // list-like component.
306
                if (MatchUtil.getInstance().match(
307
                        adapter.getRowName(implRow),
308
                            value, operator)) {
309
                    valueIsExisting = true;
310
                    
311
                }
312
            }             
313
  
314
        }
315
        Verifier.equals(exists, valueIsExisting);
316
    }
317
    
318
    /**
319
     * Verifies the editable property of the given indices.
320
     *
321
     * @param editable
322
     *            The editable property to verify.
323
     * @param row the row to select
324
     * @param rowOperator the row header operator
325
     * @param col the column to select
326
     * @param colOperator the column header operator
327
     */
328
    public void gdVerifyEditable(boolean editable, String row,
329
            String rowOperator, String col, String colOperator) {
330
        //if row is header row
331
        
332
        if (getTableAdapter().getRowFromString(row, rowOperator) == -1) {
333
            throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
334
                    EventFactory.createActionError(
335
                            TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
336
        }        
337
        gdSelectCell(row, rowOperator, col, colOperator, ClickOptions.create(),
338
                CompSystemConstants.EXTEND_SELECTION_NO);
339
        gdVerifyEditable(editable);
340
    }
341
    
342
    
343
    /**
344
     * Selects a table cell in the given row and column via click in the midle of the cell.
345
     * @param row The row of the cell.
346
     * @param rowOperator The row header operator
347
     * @param col The column of the cell.
348
     * @param colOperator The column header operator
349
     * @param co the click options to use
350
     * @param extendSelection Should this selection be part of a multiple selection
351
     */
352
    private void gdSelectCell(final String row, final String rowOperator,
353
            final String col, final String colOperator,
354
            final ClickOptions co, final String extendSelection) {
355
            
356
        gdSelectCell(row, rowOperator, col, colOperator, co.getClickCount(),
357
                    50, POS_UNI_PERCENT, 50, POS_UNI_PERCENT, extendSelection, 
358
                    co.getMouseButton());
359
    }
360
    
361
    
362
    /**
363
     * Verifies the rendered text inside cell at the mouse position on screen.
364
     *
365
     * @param text The cell text to verify.
366
     * @param operator The operation used to verify
367
     * @throws StepExecutionException If there is no selected cell, or if the
368
     *                              rendered text cannot be extracted.
369
     */
370
    public void gdVerifyTextAtMousePosition(String text, String operator)
371
        throws StepExecutionException {        
372
        if (isMouseOnHeader()) {
373
            throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
374
                    EventFactory.createActionError(
375
                            TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
376
        }        
377
        Cell cell = getCellAtMousePosition();
378
        gdVerifyText(text, operator, 
379
                Integer.toString(IndexConverter.toUserIndex(cell.getRow())),
380
                MatchUtil.EQUALS, 
381
                Integer.toString(IndexConverter.toUserIndex(cell.getCol())),
382
                MatchUtil.EQUALS);
383
    }
384
    
385
    /**
386
     * Verifies the editable property of the selected cell.
387
     *
388
     * @param editable the editable property to verify.
389
     */
390
    public void gdVerifyEditableSelected(boolean editable) {
391
        gdVerifyEditable(editable);
392
    }
393
    
394
    /**
395
     * Verifies the editable property of the current selected cell.
396
     *
397
     * @param editable The editable property to verify.
398
     */
399
    public void gdVerifyEditable(boolean editable) {
400
        Cell cell = getTableAdapter().getSelectedCell();
401
        
402
        Verifier.equals(editable, getTableAdapter()
403
                .isCellEditable(cell.getRow(), cell.getCol()));
404
    }
405
    
406
    /**
407
     * Verifies the editable property of the cell under current mouse position.
408
     *
409
     * @param editable the editable property to verify.
410
     */
411
    public void gdVerifyEditableMousePosition(boolean editable) {
412
        //if row is header row
413
        if (isMouseOnHeader()) {
414
            throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
415
                    EventFactory.createActionError(
416
                            TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
417
        }
418
        Cell cell = getCellAtMousePosition();
419
        boolean isEditable = getTableAdapter().isCellEditable(
420
                cell.getRow(), cell.getCol());
421
        Verifier.equals(editable, isEditable);
422
    }
423
    /**
424
     * Finds the first row which contains the value <code>value</code>
425
     * in column <code>col</code> and selects this row.
426
     * @param col the column
427
     * @param colOperator the column header operator
428
     * @param value the value
429
     * @param clickCount the number of clicks.
430
     * @param regexOp the regex operator
431
     * @param extendSelection Should this selection be part of a multiple selection
432
     * @param searchType Determines where the search begins ("relative" or "absolute")
433
     * @param button what mouse button should be used
434
     */
435
    public void gdSelectRowByValue(String col, String colOperator,
436
            final String value, final String regexOp, int clickCount,
437
            final String extendSelection, final String searchType, int button) {
438
        gdSelectRowByValue(col, colOperator, value, regexOp, extendSelection,
439
                searchType, ClickOptions.create()
440
                        .setClickCount(clickCount)
441
                        .setMouseButton(button));
442
    }
443
    
444
    /**
445
     * Finds the first row which contains the value <code>value</code>
446
     * in column <code>col</code> and selects this row.
447
     *
448
     * @param col the column
449
     * @param colOperator the column header operator
450
     * @param value the value
451
     * @param regexOp the regex operator
452
     * @param extendSelection Should this selection be part of a multiple selection
453
     * @param searchType Determines where the search begins ("relative" or "absolute")
454
     * @param co the clickOptions to use
455
     */
456
    protected void gdSelectRowByValue(String col, String colOperator,
457
        final String value, final String regexOp, final String extendSelection,
458
        final String searchType, ClickOptions co) {
459
        ITableAdapter adapter = getTableAdapter();
460
        final int implCol = adapter.getColumnFromString(col, colOperator);
461
        Integer implRow = null;
462
        final int rowCount = adapter.getRowCount();
463
        
464
        for (int i = getStartingRowIndex(searchType); i < rowCount; ++i) {
465
            if (MatchUtil.getInstance().match(getCellText(i, implCol), 
466
                    value, regexOp)) {
467
468
                implRow = new Integer(i);
469
                break;
470
            }
471
        }
472
        if (implRow == null) {
473
            String header = adapter.getColumnName(implCol);
474
            if (MatchUtil.getInstance().match(header, value, regexOp)) {
475
                implRow = new Integer(-1);
476
            }
477
        }
478
479
        if (implRow == null) {
480
            throw new StepExecutionException("no such row found", //$NON-NLS-1$
481
                    EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
482
        }
483
        
484
        String  userIdxRow = new Integer(IndexConverter.toUserIndex(
485
                implRow.intValue())).toString();
486
        String  userIdxCol = new Integer(IndexConverter.toUserIndex(
487
                implCol)).toString();            
488
        
489
        gdSelectCell(userIdxRow, MatchUtil.EQUALS, userIdxCol, colOperator, co,
490
                extendSelection);
491
    }
492
    
493
    /**
494
     * Finds the first column which contains the value <code>value</code>
495
     * in the given row and selects the cell.
496
     *
497
     * @param row the row to select
498
     * @param rowOperator the row header operator
499
     * @param value the value
500
     * @param clickCount the number of clicks
501
     * @param regex search using regex
502
     * @param extendSelection Should this selection be part of a multiple selection
503
     * @param searchType Determines where the search begins ("relative" or "absolute")
504
     * @param button what mouse button should be used
505
     */
506
    public void gdSelectCellByColValue(String row, String rowOperator,
507
        final String value, final String regex, int clickCount,
508
        final String extendSelection, final String searchType, int button) {
509
        gdSelectCellByColValue(row, rowOperator, value, regex, extendSelection,
510
                searchType, ClickOptions.create()
511
                    .setClickCount(clickCount)
512
                    .setMouseButton(button));
513
    }
514
    
515
    /**
516
     * Finds the first column which contains the value <code>value</code>
517
     * in the given row and selects the cell.
518
     *
519
     * @param row the row
520
     * @param rowOperator the row header operator
521
     * @param value the value
522
     * @param regex search using regex
523
     * @param extendSelection Should this selection be part of a multiple selection
524
     * @param searchType Determines where the search begins ("relative" or "absolute")
525
     * @param co the click options to use
526
     */
527
    protected void gdSelectCellByColValue(String row, String rowOperator,
528
        final String value, final String regex, final String extendSelection,
529
        final String searchType, ClickOptions co) { 
530
        ITableAdapter adapter = getTableAdapter();
531
        final int implRow = adapter.getRowFromString(row, rowOperator);
532
        int colCount = adapter.getColumnCount();
533
        Integer implCol = null;
534
        if (implRow == -1) {
535
            
536
            for (int i = getStartingColIndex(searchType); i < colCount; ++i) {
537
                if (MatchUtil.getInstance().match(adapter.getColumnName(i), 
538
                        value, regex)) {
539
                    implCol = new Integer(i);
540
                    break;
541
                }
542
            }           
543
        } else {
544
            for (int i = getStartingColIndex(searchType); i < colCount; ++i) {
545
                if (MatchUtil.getInstance().match(getCellText(implRow, i), 
546
                        value, regex)) {
547
548
                    implCol = new Integer(i);
549
                    break;
550
                }
551
            } 
552
        }
553
        if (implCol == null) {
554
            throw new StepExecutionException("no such cell found", EventFactory //$NON-NLS-1$
555
                    .createActionError(TestErrorEvent.NOT_FOUND));
556
        }
557
        
558
        String usrIdxRowStr = new Integer(IndexConverter.toUserIndex(
559
                implRow)).toString();
560
        String usrIdxColStr = new Integer(IndexConverter.toUserIndex(
561
                implCol.intValue())).toString();
562
        
563
        gdSelectCell(usrIdxRowStr, rowOperator, usrIdxColStr, MatchUtil.EQUALS,
564
                co, extendSelection);
565
        
566
    }
567
    
568
    /**
569
     * Action to read the value of the current selected cell of the JTable 
570
     * to store it in a variable in the Client
571
     * @param variable the name of the variable
572
     * @return the text value.
573
     */
574
    public String gdReadValue(String variable) {
575
        final Cell selectedCell = getTableAdapter().getSelectedCell();
576
        return getCellText(selectedCell.getRow(), selectedCell.getCol());
577
    }
578
    
579
    /**
580
     * Action to read the value of the passed cell of the JTable
581
     * to store it in a variable in the Client
582
     * @param variable the name of the variable
583
     * @param row the row to select
584
     * @param rowOperator the row header operator
585
     * @param col the column to select
586
     * @param colOperator the column header operator
587
     * @return the text value.
588
     */
589
    public String gdReadValue(String variable, String row, String rowOperator,
590
            String col, String colOperator) {
591
        ITableAdapter adapter = getTableAdapter();
592
        final int implRow = adapter.getRowFromString(row, rowOperator);
593
        final int implCol = adapter.getColumnFromString(col, colOperator);
594
        
595
        //if row is header and column is existing
596
        if (implRow == -1 && implCol > -1) {
597
            return adapter.getColumnName(implCol); 
598
        }
599
        
600
        checkRowColBounds(implRow, implCol);
601
602
        adapter.scrollCellToVisible(implRow, implCol);
603
        return getCellText(implRow, implCol);
604
    }
605
    
606
    /**
607
     * {@inheritDoc}
608
     */
609
    public String gdReadValueAtMousePosition(String variable) {
610
        Cell cellAtMousePosition = getTableAdapter().getSelectedCell();
611
        return getCellText(cellAtMousePosition.getRow(), 
612
                cellAtMousePosition.getCol());
613
    }
614
    
615
    /**
616
     * Tries to click in the cell under the mouse position. If the mouse is not
617
     * over a cell, the current selected cell will be clicked on. If there is no
618
     * selected cell, the middle of the table is used to click on.
619
     * @param count Number of clicks
620
     * @param button The mouse button
621
     */
622
    public void gdClick(int count, int button) {
623
        ITableAdapter adapter = getTableAdapter();
624
        Cell cell = null;
625
        if (isMouseOverCell()) {
626
            cell = getCellAtMousePosition();
627
        } else if (adapter.hasCellSelection()) {
628
            cell = adapter.getSelectedCell();
629
        } 
630
        if (cell != null) {
631
            Rectangle cellRect = 
632
                    adapter.scrollCellToVisible(cell.getRow(), cell.getCol());
633
            getRobot().click(getRealTable(), cellRect, ClickOptions.create()
634
                .setClickCount(count).setMouseButton(button));
635
        } else {
636
            super.gdClick(count, button);
637
        }
638
    }
639
   
640
    /**
641
     * Selects a cell relative to the cell at the current mouse position.
642
     * If the mouse is not at any cell, the current selected cell is used.
643
     * @param direction the direction to move.
644
     * @param cellCount the amount of cells to move
645
     * @param clickCount the click count to select the new cell.
646
     * @param xPos what x position
647
     * @param xUnits should x position be pixel or percent values
648
     * @param yPos what y position
649
     * @param yUnits should y position be pixel or percent values
650
     * @param extendSelection Should this selection be part of a multiple selection
651
     * @throws StepExecutionException if any error occurs
652
     */
653
    public void gdMove(String direction, int cellCount, int clickCount,
654
        final int xPos, final String xUnits,
655
        final int yPos, final String yUnits, final String extendSelection)
656
        throws StepExecutionException {
657
        if (isMouseOnHeader()) {
658
            throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
659
                    EventFactory.createActionError(
660
                            TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
661
        }
662
        Cell currCell = null;
663
        try {
664
            currCell = getCellAtMousePosition();
665
        } catch (StepExecutionException e) {
666
            currCell = getTableAdapter().getSelectedCell();
667
        }
668
        int newCol = currCell.getCol();
669
        int newRow = currCell.getRow();
670
        if (CompSystemConstants.TABLE_MOVE_UP
671
                .equalsIgnoreCase(direction)) {
672
            newRow -= cellCount;
673
        } else if (CompSystemConstants.TABLE_MOVE_DOWN
674
                .equalsIgnoreCase(direction)) {
675
            newRow += cellCount;
676
        } else if (CompSystemConstants.TABLE_MOVE_LEFT
677
                .equalsIgnoreCase(direction)) {
678
            newCol -= cellCount;
679
        } else if (CompSystemConstants.TABLE_MOVE_RIGHT
680
                .equalsIgnoreCase(direction)) {
681
            newCol += cellCount;
682
        }
683
        newRow = IndexConverter.toUserIndex(newRow);
684
        newCol = IndexConverter.toUserIndex(newCol);
685
        String row = Integer.toString(newRow);
686
        String col = Integer.toString(newCol);
687
        gdSelectCell(row, MatchUtil.DEFAULT_OPERATOR , col, 
688
                MatchUtil.DEFAULT_OPERATOR, clickCount, xPos,
689
                xUnits, yPos, yUnits, extendSelection, 
690
                InputConstants.MOUSE_BUTTON_LEFT);
691
//        gdSelectCell(newRow, newCol, clickCount,
692
//                     xPos, xUnits, yPos, yUnits, extendSelection);
693
    }
694
    
695
    /**
696
     * Writes the passed text into the currently selected cell.
697
     * 
698
     * @param text
699
     *            The text.
700
     * @throws StepExecutionException
701
     *             If there is no selected cell, or if the cell is not editable,
702
     *             or if the table cell editor permits the text to be written.
703
     */
704
    public void gdInputText(final String text) throws StepExecutionException {
705
        inputText(text, false);
706
    }
707
    
708
    /**
709
     * Types the text in the specified cell.
710
     * @param text The text
711
     * @param row The row of the cell.
712
     * @param rowOperator The row operator
713
     * @param col The column of the cell.
714
     * @param colOperator The column operator
715
     * @throws StepExecutionException If the text input fails
716
     */
717
    public void gdInputText(String text, String row, String rowOperator,
718
            String col, String colOperator)
719
        throws StepExecutionException {
720
        //if row is header row
721
        if (getTableAdapter().getRowFromString(row, rowOperator) == -1) {
722
            throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
723
                    EventFactory.createActionError(
724
                            TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
725
        }
726
        gdSelectCell(row, rowOperator, col, colOperator, 
727
                ClickOptions.create().setClickCount(1), 
728
                CompSystemConstants.EXTEND_SELECTION_NO);
729
        gdInputText(text);
730
    }
731
    
732
    /**
733
     * Types <code>text</code> into the component. This replaces the shown
734
     * content in the current selected cell.
735
     * 
736
     * @param text the text to type in
737
     * @throws StepExecutionException
738
     *  If there is no selected cell, or if the cell is not editable,
739
     *  or if the table cell editor permits the text to be written.
740
     */
741
    public void gdReplaceText(String text) throws StepExecutionException {
742
        inputText(text, true);
743
    }
744
    
745
    /**
746
     * Replaces the given text in the given cell coordinates
747
     * @param text the text to replace
748
     * @param row The row of the cell.
749
     * @param rowOperator The row operator
750
     * @param col The column of the cell.
751
     * @param colOperator The column operator
752
     */
753
    public void gdReplaceText(String text, String row, String rowOperator,
754
            String col, String colOperator) {
755
        //if row is header row
756
        if (getTableAdapter().getRowFromString(row, rowOperator) == -1) {
757
            throw new StepExecutionException("Unsupported Header Action", //$NON-NLS-1$
758
                    EventFactory.createActionError(
759
                            TestErrorEvent.UNSUPPORTED_HEADER_ACTION));
760
        }
761
        gdSelectCell(row, rowOperator, col, colOperator, 
762
                ClickOptions.create().setClickCount(1), 
763
                CompSystemConstants.EXTEND_SELECTION_NO);
764
        inputText(text, true);
765
    }
766
    
767
    /**
768
     * Drags the cell of the Table.<br>
769
     * With the xPos, yPos, xunits and yUnits the click position inside the
770
     * cell can be defined.
771
     *
772
     * @param mouseButton the mouseButton.
773
     * @param modifier the modifier.
774
     * @param row the row to select
775
     * @param rowOperator the row header operator
776
     * @param col the column to select
777
     * @param colOperator the column header operator
778
     * @param xPos what x position
779
     * @param xUnits should x position be pixel or percent values
780
     * @param yPos what y position
781
     * @param yUnits should y position be pixel or percent values
782
     * @throws StepExecutionException
783
     *             If the row or the column is invalid
784
     */
785
    public void gdDragCell(final int mouseButton, final String modifier,
786
            final String row, final String rowOperator,
787
            final String col, final String colOperator, final int xPos,
788
            final String xUnits, final int yPos, final String yUnits)
789
        throws StepExecutionException {
790
791
        final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
792
        dndHelper.setModifier(modifier);
793
        dndHelper.setMouseButton(mouseButton);
794
        dndHelper.setDragComponent(null);
795
        gdSelectCell(row, rowOperator, col, colOperator, 0, xPos, xUnits, yPos,
796
                yUnits, CompSystemConstants.EXTEND_SELECTION_NO, 1);
797
        pressOrReleaseModifiers(modifier, true);
798
        getRobot().mousePress(null, null, mouseButton);
799
    }
800
    
801
    /**
802
     * Drops on the cell of the JTable.<br>
803
     * With the xPos, yPos, xunits and yUnits the click position inside the
804
     * cell can be defined.
805
     *
806
     * @param row the row to select
807
     * @param rowOperator the row header operator
808
     * @param col the column to select
809
     * @param colOperator the column header operator
810
     * @param xPos what x position
811
     * @param xUnits should x position be pixel or percent values
812
     * @param yPos what y position
813
     * @param yUnits should y position be pixel or percent values
814
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
815
     *                        between moving the mouse to the drop point and
816
     *                        releasing the mouse button
817
     * @throws StepExecutionException
818
     *             If the row or the column is invalid
819
     */
820
    public void gdDropCell(final String row, final String rowOperator,
821
            final String col, final String colOperator, final int xPos,
822
            final String xUnits, final int yPos, final String yUnits,
823
            int delayBeforeDrop) throws StepExecutionException {
824
825
        final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
826
        try {
827
            gdSelectCell(row, rowOperator, col, colOperator, 0, xPos, xUnits,
828
                    yPos, yUnits, CompSystemConstants.EXTEND_SELECTION_NO, 1);
829
            waitBeforeDrop(delayBeforeDrop);
830
        } finally {
831
            getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
832
            pressOrReleaseModifiers(dndHelper.getModifier(), false);
833
        }
834
    }
835
    
836
    /**
837
     * Finds the first row which contains the value <code>value</code>
838
     * in column <code>col</code> and drags this row.
839
     *
840
     * @param mouseButton the mouse button
841
     * @param modifier the modifier
842
     * @param col the column
843
     * @param colOperator the column header operator
844
     * @param value the value
845
     * @param regexOp the regex operator
846
     * @param searchType Determines where the search begins ("relative" or "absolute")
847
     */
848
    public void gdDragRowByValue(int mouseButton, String modifier, String col,
849
            String colOperator, final String value, final String regexOp,
850
            final String searchType) {
851
852
        final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
853
        dndHelper.setModifier(modifier);
854
        dndHelper.setMouseButton(mouseButton);
855
        gdSelectRowByValue(col, colOperator, value, regexOp, 1,
856
                CompSystemConstants.EXTEND_SELECTION_NO, searchType, 1);
857
        pressOrReleaseModifiers(modifier, true);
858
        getRobot().mousePress(null, null, mouseButton);
859
    }
860
    
861
    /**
862
     * Finds the first row which contains the value <code>value</code>
863
     * in column <code>col</code> and drops on this row.
864
     *
865
     * @param col the column to select
866
     * @param colOperator the column header operator
867
     * @param value the value
868
     * @param regexOp the regex operator
869
     * @param searchType Determines where the search begins ("relative" or "absolute")
870
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
871
     *                        between moving the mouse to the drop point and
872
     *                        releasing the mouse button
873
     */
874
    public void gdDropRowByValue(String col, String colOperator,
875
            final String value, final String regexOp, final String searchType,
876
            int delayBeforeDrop) {
877
        
878
        final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
879
        try {
880
            gdSelectRowByValue(col, colOperator, value, regexOp,
881
                    CompSystemConstants.EXTEND_SELECTION_NO, 
882
                    searchType, ClickOptions
883
                    .create().setClickCount(0));
884
            waitBeforeDrop(delayBeforeDrop);
885
        } finally {
886
            getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
887
            pressOrReleaseModifiers(dndHelper.getModifier(), false);
888
        }
889
    }
890
    
891
    /**
892
     * Finds the first column which contains the value <code>value</code>
893
     * in the given row and drags the cell.
894
     *
895
     * @param mouseButton the mouse button
896
     * @param modifier the modifiers
897
     * @param row the row to select
898
     * @param rowOperator the row header operator
899
     * @param value the value
900
     * @param regex search using regex
901
     * @param searchType Determines where the search begins ("relative" or "absolute")
902
     */
903
    public void gdDragCellByColValue(int mouseButton, String modifier,
904
            String row, String rowOperator, final String value,
905
            final String regex, final String searchType) {
906
907
        final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
908
        dndHelper.setModifier(modifier);
909
        dndHelper.setMouseButton(mouseButton);
910
911
        gdSelectCellByColValue(row, rowOperator, value, regex,
912
                CompSystemConstants.EXTEND_SELECTION_NO, searchType, 
913
                ClickOptions.create().setClickCount(0));
914
        pressOrReleaseModifiers(modifier, true);
915
        getRobot().mousePress(null, null, mouseButton);
916
    }
917
    
918
    /**
919
     * Finds the first column which contains the value <code>value</code>
920
     * in the given row and drops on the cell.
921
     *
922
     * @param row the row to select
923
     * @param rowOperator the row header operator
924
     * @param value the value
925
     * @param regex search using regex
926
     * @param searchType Determines where the search begins ("relative" or "absolute")
927
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
928
     *                        between moving the mouse to the drop point and
929
     *                        releasing the mouse button
930
     */
931
    public void gdDropCellByColValue(String row, String rowOperator,
932
            final String value, final String regex, final String searchType,
933
            int delayBeforeDrop) {
934
935
        final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
936
        try {
937
            gdSelectCellByColValue(row, rowOperator, value, regex, 
938
                    CompSystemConstants.EXTEND_SELECTION_NO, searchType, 
939
                    ClickOptions.create().setClickCount(0));
940
            waitBeforeDrop(delayBeforeDrop);
941
        } finally {
942
            getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
943
            pressOrReleaseModifiers(dndHelper.getModifier(), false);
944
        }
945
    }
946
    
947
948
    /**
949
     * Gets the text from the specific cell which is given
950
     * by the row and the column.
951
     * @param row the zero based index of the row
952
     * @param column the zero based index of the column
953
     * @return the text of the cell of the given coordinates
954
     */
955
    private String getCellText(final int row, final int column) {
956
        return getTableAdapter().getCellText(row, column);
957
958
    }
959
    
960
    /**
961
     * Presses or releases the given modifier.
962
     * @param modifier the modifier.
963
     * @param press if true, the modifier will be pressed.
964
     * if false, the modifier will be released.
965
     */
966
    protected void pressOrReleaseModifiers(String modifier, boolean press) {
967
        final IRobot robot = getRobot();
968
        final StringTokenizer modTok = new StringTokenizer(
969
                KeyStrokeUtil.getModifierString(modifier), " "); //$NON-NLS-1$
970
        while (modTok.hasMoreTokens()) {
971
            final String mod = modTok.nextToken();
972
            final int keyCode = getKeyCode(mod);
973
            if (press) {
974
                robot.keyPress(null, keyCode);
975
            } else {
976
                robot.keyRelease(null, keyCode);
977
            }
978
        }
979
    }
980
    
981
    /**
982
     * Gets the key code for a specific modifier
983
     * @param mod the modifier
984
     * @return the integer key code value
985
     */
986
    protected abstract int getKeyCode(String mod);
987
    
988
    /**
989
     * Checks whether <code>0 <= value < count</code>. 
990
     * @param value The value to check.
991
     * @param count The upper bound.
992
     */
993
    private void checkBounds(int value, int count) {
994
        if (value < 0 || value >= count) {
995
            throw new StepExecutionException("Invalid row/column: " + value, //$NON-NLS-1$
996
                EventFactory.createActionError(
997
                        TestErrorEvent.INVALID_INDEX_OR_HEADER));
998
        }
999
    }
1000
    
1001
    /**
1002
     * Checks if the passed row and column are inside the bounds of the Table. 
1003
     * @param row The row
1004
     * @param column The column
1005
     * @throws StepExecutionException If the row or the column is outside of the Table's bounds.
1006
     */
1007
    protected void checkRowColBounds(int row, int column)
1008
        throws StepExecutionException {
1009
        ITableAdapter adapter = getTableAdapter();
1010
        checkBounds(row, adapter.getRowCount());
1011
        
1012
        // Corner case: Only check the bounds if the table is not being
1013
        //              used as a list or anything other than the first column
1014
        //              is being checked.
1015
        int colCount = adapter.getColumnCount();
1016
        if (colCount > 0 || column > 0) {
1017
            checkBounds(column, colCount);
1018
        }
1019
    }
1020
    
1021
    /**
1022
     * @param searchType Determines column where the search begins ("relative" or "absolute")
1023
     * @return The index from which to begin a search, based on the search type
1024
     *         and (if appropriate) the currently selected cell.
1025
     */
1026
    private int getStartingColIndex(String searchType) {
1027
        int startingIndex = 0;
1028
        if (searchType.equalsIgnoreCase(
1029
                CompSystemConstants.SEARCH_TYPE_RELATIVE)) {
1030
            startingIndex = getTableAdapter().getSelectedCell().getCol() + 1;
1031
        }
1032
        return startingIndex;
1033
    }
1034
1035
    /**
1036
     * @param searchType Determines the row where the search begins ("relative" or "absolute")
1037
     * @return The index from which to begin a search, based on the search type
1038
     *         and (if appropriate) the currently selected cell.
1039
     */
1040
    private int getStartingRowIndex(String searchType) {
1041
        int startingIndex = 0;
1042
        if (searchType.equalsIgnoreCase(
1043
                CompSystemConstants.SEARCH_TYPE_RELATIVE)) {
1044
            startingIndex = getTableAdapter().getSelectedCell().getRow() + 1;
1045
        }
1046
        return startingIndex;
1047
    }
1048
    
1049
    /**
1050
     * inputs/replaces the given text
1051
     * @param text the text to input
1052
     * @param replace wheter to replace or not
1053
     * @throws StepExecutionException If there is no selected cell,
1054
     * or if the cell is not editable, or if the table cell editor permits
1055
     * the text to be written.
1056
     */
1057
    private void inputText(final String text, boolean replace) 
1058
        throws StepExecutionException {
1059
        ITableAdapter adapter = getTableAdapter();
1060
        
1061
        final Cell cell = adapter.getSelectedCell();
1062
        // Ensure that the cell is visible.
1063
        Rectangle rectangle = 
1064
                adapter.scrollCellToVisible(cell.getRow(), cell.getCol());
1065
        
1066
        Object editor = activateEditor(cell, rectangle);
1067
        editor = setEditorToReplaceMode(editor, replace);
1068
        
1069
        getRobot().type(editor, text);
1070
    }
1071
    
1072
    /**
1073
     * @return true if the mouse pointer is over any cell, false otherwise.
1074
     */
1075
    private boolean isMouseOverCell() {
1076
        try {
1077
            getCellAtMousePosition();
1078
        } catch (StepExecutionException se) {
1079
            return false;
1080
        }
1081
        return true;
1082
    }
1083
    
1084
    /**
1085
     * Waits the given amount of time. Logs a drop-related error if interrupted.
1086
     *
1087
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
1088
     *                        between moving the mouse to the drop point and
1089
     *                        releasing the mouse button
1090
     */
1091
    static void waitBeforeDrop(int delayBeforeDrop) {
1092
        TimeUtil.delay(delayBeforeDrop);
1093
    }
1094
    
1095
    /**
1096
     * Sets the specific editor to an replace mode. Means that the next key
1097
     * input will override the complete text of the editor.
1098
     * @param editor 
1099
     * @param replace if <code>true</code> than the editor has to override
1100
     *              the complete text with the next key input. Else the next
1101
     *              key input will append to the end.
1102
     * @return the editor if it changed
1103
     */
1104
    protected abstract Object setEditorToReplaceMode(Object editor,
1105
            boolean replace);
1106
   
1107
    /**
1108
     * Activates the editor of the specific cell.
1109
     * @param cell 
1110
     * @param rectangle 
1111
     * @return the editor of the cell
1112
     */
1113
    protected abstract Object activateEditor(Cell cell, Rectangle rectangle);
1114
    
1115
1116
    /**
1117
     * Gets The modifier for an extended selection (more than one item)
1118
     * @return the modifier
1119
     */
1120
    protected abstract int getExtendSelectionModifier();
1121
    
1122
    /**
1123
     * @return the cell under the current mouse position.
1124
     * @throws StepExecutionException If no cell is found.
1125
     */
1126
    protected abstract Cell getCellAtMousePosition() 
1127
        throws StepExecutionException;
1128
   
1129
    /**
1130
     * Verifies if mouse is on header.
1131
     * @return true if mouse is on header
1132
     */
1133
    protected abstract boolean isMouseOnHeader();
1134
1135
    /**
1136
     * Selects the passed row of the JTable. This is actually a selection of the
1137
     * cell <code>(row, 0)</code>.
1138
     *
1139
     * @param row
1140
     *            The row
1141
     * @param extendSelection Should this selection be part of a multiple selection
1142
     * @throws StepExecutionException
1143
     *             If the row is invalid
1144
     * @deprecated the same as gdSelectCell
1145
     * Will be removed!
1146
     */
1147
    public void gdSelectRow(int row, String extendSelection)
1148
        throws StepExecutionException {
1149
        // FIXME this is only here for testing purpose (to get all CaA tests running)
1150
        gdSelectCell(String.valueOf(row), MatchUtil.DEFAULT_OPERATOR, "1", //$NON-NLS-1$
1151
                MatchUtil.DEFAULT_OPERATOR, 
1152
                ClickOptions.create().setClickCount(1), extendSelection);
1153
    }
1154
    
1155
    /**
1156
     * Finds the first column which contains the value <code>value</code>
1157
     * in the given row and selects the cell.
1158
     * 
1159
     * @param row the row
1160
     * @param value the value
1161
     * @param clickCount the mouse clicks.
1162
     * @param regex search using regex
1163
     * @param extendSelection Should this selection be part of a multiple selection
1164
     * @param searchType Determines where the search begins ("relative" or "absolute")
1165
     * @deprecated Will be removed with gdSelectCellByColValue with String parameter
1166
     * for Row/Column
1167
     */
1168
    public void gdSelectCellByColValue(int row, final String value, 
1169
        final String regex, int clickCount, final String extendSelection, 
1170
        final String searchType) {
1171
        // FIXME this is only here for testing purpose (to get all CaA tests running)
1172
        gdSelectCellByColValue(String.valueOf(row), MatchUtil.DEFAULT_OPERATOR,
1173
                value, regex, clickCount, extendSelection, searchType, 1);
1174
1175
    }
1176
    
1177
    /**
1178
     * Finds the first row which contains the value <code>value</code>
1179
     * in column <code>col</code> and selects this row.
1180
     * @param col the column
1181
     * @param value the value
1182
     * @param clickCount the number of clicks.
1183
     * @param regexOp the regex operator
1184
     * @param extendSelection Should this selection be part of a multiple selection
1185
     * @param searchType Determines where the search begins ("relative" or "absolute")
1186
     * @deprecated Will be removed with gdSelectRowByValue with String parameter
1187
     * for Row/Column
1188
     */
1189
    public void gdSelectRowByValue(int col, final String value,
1190
        int clickCount, final String regexOp, final String extendSelection, 
1191
        final String searchType) {
1192
        // FIXME this is only here for testing purpose (to get all CaA tests running)
1193
        gdSelectRowByValue(String.valueOf(col), MatchUtil.DEFAULT_OPERATOR,
1194
                value, regexOp, clickCount, extendSelection, searchType, 1);
1195
    }
1196
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextInputSupport.java (+53 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
15
/**
16
 * This class represents the general implmentation for components,
17
 *  which have text input support.
18
 * 
19
 * @author BREDEX GmbH
20
 */
21
public abstract class AbstractTextInputSupport extends AbstractTextVerifiable {
22
23
    /**
24
     * Verifies the editable property of the current component.<br>
25
     * If it is a complex component, it is always the selected object.
26
     * @param editable The editable property to verify.
27
     */
28
    public abstract void gdVerifyEditable(boolean editable);
29
 // FIXME this is only a pattern because only Tables uses this at the moment
30
    /**
31
     * Types <code>text</code> into the component. This replaces the shown
32
     * content.<br>
33
     * If it is a complex component, it is always the selected object.
34
     * @param text the text to type in
35
     * @throws StepExecutionException
36
     *  If there is no selected cell, or if the cell is not editable,
37
     *  or if the table cell editor permits the text to be written.
38
     */
39
    public abstract void gdReplaceText(String text) 
40
        throws StepExecutionException;
41
 // FIXME this is only a pattern because only Tables uses this at the moment
42
    /**
43
     * Writes the passed text into the currently component.<br>
44
     * If it is a complex component, it is always the selected object.
45
     * @param text The text.
46
     * @throws StepExecutionException
47
     *             If there is no selected cell, or if the cell is not editable,
48
     *             or if the table cell editor permits the text to be written.
49
     */
50
    public abstract void gdInputText(final String text) 
51
        throws StepExecutionException;
52
 // FIXME this is only a pattern because only Tables uses this at the moment
53
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTextVerifiable.java (+43 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
15
/**
16
 * This class represents the general implementation for components
17
 * which have readable text.
18
 * 
19
 * @author BREDEX GmbH
20
 */
21
public abstract class AbstractTextVerifiable extends AbstractWidgetCAPs {
22
23
    /**
24
     * Action to read the value of the current component 
25
     * to store it in a variable in the Client.<br>
26
     * If it is a complex component, it is always the selected object.
27
     * @param variable the name of the variable
28
     * @return the text value.
29
     */
30
    public abstract String gdReadValue(String variable);
31
    // FIXME this is only a pattern because only Tables uses this at the moment
32
33
    /**
34
     * Verifies the rendered text inside the currently component.<br>
35
     * If it is a complex component, it is always the selected object.
36
     * @param text The text to verify.
37
     * @param operator The operation used to verify
38
     * @throws StepExecutionException If the rendered text cannot be extracted.
39
     */
40
    public abstract void gdVerifyText(String text, String operator)
41
        throws StepExecutionException;
42
    // FIXME this is only a pattern because only Tables uses this at the moment
43
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractTreeCAPs.java (+754 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 java.util.Collection;
14
import java.util.Iterator;
15
16
import org.apache.commons.lang.Validate;
17
import org.eclipse.jubula.rc.common.CompSystemConstants;
18
import org.eclipse.jubula.rc.common.driver.ClickOptions;
19
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
20
import org.eclipse.jubula.rc.common.exception.StepVerifyFailedException;
21
import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
22
import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
23
import org.eclipse.jubula.rc.common.implclasses.Verifier;
24
import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeNodeTraverser;
25
import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeOperationContext;
26
import org.eclipse.jubula.rc.common.implclasses.tree.ChildTraverser;
27
import org.eclipse.jubula.rc.common.implclasses.tree.ExpandCollapseTreeNodeOperation;
28
import org.eclipse.jubula.rc.common.implclasses.tree.INodePath;
29
import org.eclipse.jubula.rc.common.implclasses.tree.IndexNodePath;
30
import org.eclipse.jubula.rc.common.implclasses.tree.ParentTraverser;
31
import org.eclipse.jubula.rc.common.implclasses.tree.PathBasedTraverser;
32
import org.eclipse.jubula.rc.common.implclasses.tree.SelectTreeNodeOperation;
33
import org.eclipse.jubula.rc.common.implclasses.tree.SiblingTraverser;
34
import org.eclipse.jubula.rc.common.implclasses.tree.StringNodePath;
35
import org.eclipse.jubula.rc.common.implclasses.tree.TreeNodeOperation;
36
import org.eclipse.jubula.rc.common.implclasses.tree.TreeNodeOperationConstraint;
37
import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITreeAdapter;
38
import org.eclipse.jubula.tools.constants.StringConstants;
39
import org.eclipse.jubula.tools.constants.TestDataConstants;
40
import org.eclipse.jubula.tools.objects.event.EventFactory;
41
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
42
import org.eclipse.jubula.tools.utils.StringParsing;
43
44
45
/**
46
 * General implementation for Trees.
47
 * 
48
 * @author BREDEX GmbH
49
 */
50
public abstract class AbstractTreeCAPs extends AbstractWidgetCAPs {
51
52
    /**
53
     * {@inheritDoc}
54
     */
55
    public String[] getTextArrayFromComponent() {
56
        //FIXME is here an TextArray?
57
        return null;
58
    }
59
60
    /**
61
     *  This method is only casting the IComponentAdapter to the wanted ITreeAdapter
62
     * @return The ITreeAdapter out of the stored IComponentAdapter
63
     */
64
    private ITreeAdapter getTreeAdapter() {
65
        return (ITreeAdapter)getComponent();
66
        
67
    }
68
    
69
    /**
70
     * Verifies the text of the Node at mousePosition
71
     * @param text the text to check
72
     * @param operator the operator for the verification
73
     */
74
    public abstract void gdVerifyTextAtMousePosition(
75
            String text, 
76
            String operator);
77
    /**
78
     * Splits the <code>treepath</code> string into an array, one entry for each level in the path
79
     *
80
     * @param treePath The tree path
81
     * @return An array of string representing the tree path
82
     */
83
    protected String[] splitTextTreePath(String treePath) {
84
        return StringParsing.splitToArray(treePath,
85
                TestDataConstants.PATH_CHAR_DEFAULT,
86
                TestDataConstants.ESCAPE_CHAR_DEFAULT, 
87
                true);
88
    }
89
    
90
    /**
91
     * Splits the <code>treepath</code> string into an array, one entry for each level in the path
92
     *
93
     * @param treePath The tree path
94
     * @return An array of indices (type <code>Integer</code>) representing
95
     *         the tree path
96
     * @throws StepExecutionException
97
     *             If the values of the passed path cannot be parsed
98
     */
99
    protected Integer[] splitIndexTreePath(String treePath)
100
        throws StepExecutionException {
101
        Integer[] indexPath = null;
102
        String[] path = splitTextTreePath(treePath);
103
        if (path != null) {
104
            indexPath = new Integer[path.length];
105
            for (int i = 0; i < path.length; i++) {
106
                indexPath[i] = new Integer(IndexConverter.intValue(path[i]));
107
            }
108
        }
109
        return IndexConverter.toImplementationIndices(indexPath);
110
    }
111
    
112
    /**
113
     * Splits the <code>treepath</code> string into an array, one entry for each level in the path
114
     * 
115
     * @param treePath The tree path
116
     * @param operator The operator
117
     * @return An array of string representing the tree path
118
     */
119
    protected INodePath createStringNodePath(String [] treePath, 
120
            String operator) {
121
        return new StringNodePath(treePath, operator);
122
    }
123
    
124
    /**
125
     * Splits the <code>treepath</code> string into an array, one entry for each level in the path
126
     *
127
     * @param treePath The tree path
128
     * @return An array of string representing the tree path
129
     */
130
    protected INodePath createIndexNodePath(Integer [] treePath) {
131
        return new IndexNodePath(treePath);
132
    }
133
134
    
135
    /**
136
     * Traverses the tree by searching for the nodes in the tree
137
     * path entry and calling the given operation on each matching node.
138
     *
139
     * @param treePath The tree path.
140
     * @param pathType For example, "relative" or "absolute".
141
     * @param preAscend Relative traversals will start this many parent nodes
142
     *            above the current node. Absolute traversals ignore this
143
     *            parameter.
144
     * @param operation The tree node operation.
145
     * @throws StepExecutionException If the path traversion fails.
146
     */
147
    protected void traverseTreeByPath(INodePath treePath, String pathType,
148
            int preAscend, TreeNodeOperation operation)
149
        throws StepExecutionException {
150
151
        Validate.notNull(treePath);
152
        Validate.notNull(operation);
153
154
        ITreeAdapter adapter = getTreeAdapter();
155
        AbstractTreeOperationContext context = adapter.getContext();
156
157
        AbstractTreeNodeTraverser traverser =
158
            new PathBasedTraverser(context, treePath);
159
160
        traverser.traversePath(operation, 
161
                getStartNode(pathType, preAscend, context));
162
163
    }
164
   
165
    /**
166
     * Traverses the tree by searching for the nodes in the tree
167
     * path entry and calling the given operation on the last element in the path.
168
     * @param treePath The tree path.
169
     * @param pathType For example, "relative" or "absolute".
170
     * @param preAscend
171
     *            Relative traversals will start this many parent nodes 
172
     *            above the current node. Absolute traversals ignore this 
173
     *            parameter.
174
     * @param operation The tree node operation.
175
     * @throws StepExecutionException If the path traversion fails.
176
     */
177
    protected void traverseLastElementByPath(INodePath treePath, 
178
            String pathType, int preAscend, TreeNodeOperation operation) 
179
        throws StepExecutionException {
180
181
        Validate.notNull(treePath);
182
        Validate.notNull(operation);
183
184
        AbstractTreeOperationContext context = getTreeAdapter().getContext();
185
        Object startNode = getStartNode(pathType, preAscend, context);
186
187
        AbstractTreeNodeTraverser traverser = new PathBasedTraverser(
188
                context, treePath, new TreeNodeOperationConstraint());
189
        
190
        traverser.traversePath(operation, startNode);
191
    }
192
    
193
    /**
194
     * @param pathType pathType
195
     * @param preAscend
196
     *            Relative traversals will start this many parent nodes 
197
     *            above the current node. Absolute traversals ignore this 
198
     *            parameter.
199
     * @param objectPath objectPath
200
     * @param co the click options to use
201
     */
202
    private void selectByPath(String pathType, int preAscend, 
203
            INodePath objectPath, ClickOptions co) {
204
205
        TreeNodeOperation expOp = new ExpandCollapseTreeNodeOperation(false);
206
        TreeNodeOperation selectOp = new SelectTreeNodeOperation(co);
207
        INodePath subPath = objectPath.subPath(0, objectPath.getLength() - 1);
208
209
        traverseTreeByPath(subPath, pathType, preAscend, expOp);
210
        traverseLastElementByPath(objectPath, pathType, preAscend, selectOp);
211
    }
212
    
213
    /**
214
     * Returns the selected node
215
     * @param context context
216
     * @return node
217
     */
218
    protected Object getSelectedNode(AbstractTreeOperationContext context) {
219
        return context.getSelectedNode();
220
    }
221
    
222
    /**
223
     * Clicks the tree.
224
     * If the mouse pointer is in the tree no mouse move will be perfomed.
225
     * Otherwise, the mouse is first moved to the center of the tree.
226
     *
227
     * @param count Number of mouse clicks
228
     * @param button Pressed button
229
     */
230
    public void gdClick(int count, int button) {
231
        if (getRobot().isMouseInComponent(
232
                getTreeAdapter().getRealComponent())) {
233
            getRobot().clickAtCurrentPosition(
234
                    getTreeAdapter().getRealComponent(), count, button);
235
        } else {
236
            getRobot().click(getTreeAdapter().getRealComponent(), null, 
237
                ClickOptions.create().setClickCount(count)
238
                    .setMouseButton(button));
239
        }       
240
    }
241
    
242
    /**
243
     * Collapses the JTree. The passed tree path is a slash-seperated list of
244
     * nodes that specifies a valid top-down path in the JTree. The last node of
245
     * the tree path is collapsed if it is currently expanded. Otherwise, the JTree is
246
     * left unchanged.
247
     *
248
     * @param pathType whether the path is relative or absolute
249
     * @param preAscend Relative traversals will start this many parent nodes
250
     *            above the current node. Absolute traversals ignore this
251
     *            parameter.
252
     * @param treePath The tree path.
253
     * @param operator
254
     *            Whether regular expressions are used to determine the tree path.
255
     *            <code>"matches"</code> for regex, <code>"equals"</code> for simple matching.
256
     * @throws StepExecutionException
257
     *             If the tree path is invalid or the double click to collapse
258
     *             the node fails.
259
     */
260
    public void gdCollapse(String pathType, int preAscend,
261
        String treePath, String operator) throws StepExecutionException {
262
        traverseLastElementByPath(
263
                createStringNodePath(splitTextTreePath(treePath), operator),
264
                pathType, preAscend,
265
                new ExpandCollapseTreeNodeOperation(true));
266
    }
267
    
268
    /**
269
     * Collapses the tree. This method works like {@link #gdCollapse(String, int, String, String)},
270
     * but expects an enumeration of indices representing the top-down tree
271
     * path. Any index is the node's position at the current tree level.
272
     *
273
     * @param pathType whether the path is relative or absolute
274
     * @param preAscend Relative traversals will start this many parent nodes
275
     *            above the current node. Absolute traversals ignore this
276
     *            parameter.
277
     * @param indexPath  The index path
278
     * @throws StepExecutionException
279
     *             If the tree path is invalid or the double-click to collapse
280
     *             the node fails.
281
     */
282
    public void gdCollapseByIndices(String pathType, int preAscend,
283
        String indexPath) throws StepExecutionException {
284
285
        try {
286
            traverseLastElementByPath(
287
                    createIndexNodePath(splitIndexTreePath(indexPath)),
288
                    pathType, preAscend,
289
                    new ExpandCollapseTreeNodeOperation(true));
290
        } catch (NumberFormatException e) {
291
            throw new StepExecutionException(e.getMessage(), EventFactory
292
                    .createActionError(TestErrorEvent.INVALID_INDEX));
293
        }
294
    }
295
    
296
    /**
297
     * <p>
298
     * Expands the Tree. Any node defined by the passed tree path is expanded,
299
     * if it is collapsed. The node is expanded by performing a double click
300
     * onto the node. If the node is already expanded, the JTree is left
301
     * unchanged. The tree path is a slash-seperated list of nodes that specifies
302
     * a valid top-down path in the JTree.
303
     * </p>
304
     *
305
     * An example: Say the passed tree path is <code>animals/birds/kakadu</code>.
306
     * To get a valid expansion, the JTree has to look as follows:
307
     *
308
     * <pre>
309
     * animals
310
     * |
311
     * - -- birds
312
     *      |
313
     *      - -- kakadu
314
     * </pre>
315
     *
316
     * <code>animals</code> is the Tree's root node, if the root node has
317
     * been set to visible,
318
     * or it is one of the root node's children, if the root node has been set
319
     * to invisible.
320
     *
321
     * <p>
322
     * It is important to know that the tree path entries have to match the
323
     * rendered node texts, but not the underlying user object data etc.
324
     * </p>
325
     *
326
     * @param pathType whether the path is relative or absolute
327
     * @param preAscend
328
     *            Relative traversals will start this many parent nodes
329
     *            above the current node. Absolute traversals ignore this
330
     *            parameter.
331
     * @param treePath
332
     *            The tree path.
333
     * @param operator
334
     *            If regular expressions are used to determine the tree path
335
     * @throws StepExecutionException
336
     *             If the tree path is invalid or the double click fails.
337
     */
338
    public void gdExpand(String pathType, int preAscend,
339
        String treePath, String operator) throws StepExecutionException {
340
        traverseTreeByPath(
341
                createStringNodePath(splitTextTreePath(treePath), operator),
342
                pathType, preAscend,
343
                new ExpandCollapseTreeNodeOperation(false));
344
    }
345
    
346
    /**
347
     * Expands the tree. This method works like {@link #gdExpand(String, int, String, String)}, but
348
     * expects an enumeration of indices representing the top-down tree path.
349
     * Any index is the node's position at the current tree level.
350
     *
351
     * @param pathType whether the path is relative or absolute
352
     * @param preAscend
353
     *            Relative traversals will start this many parent nodes
354
     *            above the current node. Absolute traversals ignore this
355
     *            parameter.
356
     * @param indexPath The index path
357
     * @throws StepExecutionException
358
     *             If the tree path is invalid or the double-click fails.
359
     */
360
    public void gdExpandByIndices(String pathType, int preAscend,
361
        String indexPath) throws StepExecutionException {
362
363
        try {
364
            traverseTreeByPath(
365
                    createIndexNodePath(splitIndexTreePath(indexPath)),
366
                    pathType, preAscend,
367
                    new ExpandCollapseTreeNodeOperation(false));
368
        } catch (NumberFormatException e) {
369
            throw new StepExecutionException(e.getMessage(), EventFactory
370
                    .createActionError(TestErrorEvent.INVALID_INDEX));
371
        }
372
    }
373
    
374
    
375
    
376
    /**
377
     * Selects a node relative to the currently selected node.
378
     * @param direction the direction to move.
379
     *                  directions:
380
     *                      UP - Navigates through parents
381
     *                      DOWN - Navigates through children
382
     *                      NEXT - Navigates to next sibling
383
     *                      PREVIOUS - Navigates to previous sibling
384
     * @param distance the distance to move
385
     * @param clickCount the click count to select the new cell.
386
     * @throws StepExecutionException if any error occurs
387
     */
388
    public void gdMove(String direction, int distance, int clickCount) 
389
        throws StepExecutionException {
390
        
391
        AbstractTreeOperationContext context = getTreeAdapter().getContext();
392
393
        Object selectedNode = getSelectedNode(context);
394
        
395
        TreeNodeOperation selectOp = 
396
            new SelectTreeNodeOperation(
397
                    ClickOptions.create().setClickCount(clickCount));
398
        TreeNodeOperationConstraint constraint = 
399
            new TreeNodeOperationConstraint();
400
401
        if (CompSystemConstants.TREE_MOVE_UP.equalsIgnoreCase(direction)) {
402
            AbstractTreeNodeTraverser traverser = 
403
                new ParentTraverser(context, distance, constraint);
404
            traverser.traversePath(selectOp, selectedNode);
405
        } else if (CompSystemConstants
406
                .TREE_MOVE_DOWN.equalsIgnoreCase(direction)) {
407
            TreeNodeOperation expandOp = 
408
                new ExpandCollapseTreeNodeOperation(false);
409
            AbstractTreeNodeTraverser expandTraverser = 
410
                new ChildTraverser(context, distance - 1);
411
            expandTraverser.traversePath(expandOp, selectedNode);
412
413
            AbstractTreeNodeTraverser selectTraverser = 
414
                new ChildTraverser(context, distance, constraint);
415
            selectTraverser.traversePath(selectOp, selectedNode);
416
            
417
        } else if (CompSystemConstants
418
                .TREE_MOVE_NEXT.equalsIgnoreCase(direction)) {
419
            // Look through siblings
420
            AbstractTreeNodeTraverser traverser = 
421
                new SiblingTraverser(context, distance, true, constraint);
422
            traverser.traversePath(selectOp, selectedNode);
423
            
424
        } else if (CompSystemConstants
425
                .TREE_MOVE_PREVIOUS.equalsIgnoreCase(direction)) {
426
            // Look through siblings
427
            AbstractTreeNodeTraverser traverser = 
428
                new SiblingTraverser(context, distance, false, constraint);
429
            traverser.traversePath(selectOp, selectedNode);
430
        }
431
432
    }
433
    
434
    /**
435
     * Selects the node at the end of the <code>treepath</code>.
436
     *
437
     * @param pathType whether the path is relative or absolute
438
     * @param preAscend
439
     *            Relative traversals will start this many parent nodes
440
     *            above the current node. Absolute traversals ignore this
441
     *            parameter.
442
     * @param treePath The tree path.
443
     * @param operator If regular expressions are used to match the tree path
444
     * @param clickCount the click count
445
     * @param button what mouse button should be used
446
     * @param extendSelection Whether this selection extends a previous 
447
     *                        selection.
448
     * @throws StepExecutionException If the tree path is invalid, if the
449
     * double-click to expand the node fails, or if the selection is invalid.
450
     */
451
    public void gdSelect(String pathType, int preAscend, String treePath,
452
            String operator, int clickCount, int button, 
453
            final String extendSelection)
454
        throws StepExecutionException {
455
        selectByPath(pathType, preAscend,
456
                createStringNodePath(splitTextTreePath(treePath), operator),
457
                ClickOptions.create()
458
                    .setClickCount(clickCount)
459
                    .setMouseButton(button)
460
                    .setClickModifier(getClickModifier(extendSelection)));
461
    }
462
    /**
463
     * Selects the last node of the path given by <code>indexPath</code>
464
     * @param pathType whether the path is relative or absolute
465
     * @param preAscend
466
     *            Relative traversals will start this many parent nodes
467
     *            above the current node. Absolute traversals ignore this
468
     *            parameter.
469
     * @param indexPath the index path
470
     * @param clickCount the number of times to click
471
     * @param button what mouse button should be used
472
     * @param extendSelection Whether this selection extends a previous 
473
     *                        selection.
474
     * @throws StepExecutionException if <code>indexPath</code> is not a valid
475
     * path
476
     */
477
    public void gdSelectByIndices(String pathType, int preAscend,
478
            String indexPath, int clickCount, int button,
479
            final String extendSelection) 
480
        throws StepExecutionException {
481
        
482
        selectByPath(pathType, preAscend,
483
                createIndexNodePath(splitIndexTreePath(indexPath)),
484
                ClickOptions.create()
485
                .setClickCount(clickCount)
486
                .setMouseButton(button)
487
                .setClickModifier(getClickModifier(extendSelection)));
488
    }
489
    
490
    /**
491
     * Tests whether the given treePath exists or not
492
     * @param pathType whether the path is relative or absolute
493
     * @param preAscend
494
     *            Relative traversals will start this many parent nodes
495
     *            above the current node. Absolute traversals ignore this
496
     *            parameter.
497
     * @param treePath the path to check
498
     * @param operator the RegEx operator
499
     * @param exists if true, the verify succeeds if the path DOES exist.
500
     *  If false, the verify succeeds if the path DOES NOT exist.
501
     */
502
    public void gdVerifyPath(String pathType, int preAscend,
503
            String treePath, String operator, boolean exists) {
504
        try {
505
            gdExpand(pathType, preAscend, treePath, operator);
506
        } catch (StepExecutionException e) {
507
            if (exists) {
508
                throw new StepVerifyFailedException(
509
                        "Verify failed on tree-path: " //$NON-NLS-1$
510
                                + treePath, EventFactory.createVerifyFailed(
511
                                        treePath, StringConstants.EMPTY));
512
            }
513
            return;
514
        }
515
        if (!exists) {
516
            throw new StepVerifyFailedException("Verify failed on tree-path: ",  //$NON-NLS-1$
517
                EventFactory.createVerifyFailed(
518
                        StringConstants.EMPTY, treePath));
519
        }
520
    }
521
522
    /**
523
     * Tests whether the given treePath exists or not
524
     * @param pathType whether the path is relative or absolute
525
     * @param preAscend
526
     *            Relative traversals will start this many parent nodes
527
     *            above the current node. Absolute traversals ignore this
528
     *            parameter.
529
     * @param treePath the path to check
530
     * @param exists if true, the verify succeeds if the path DOES exist.
531
     *  If false, the verify succeeds if the path DOES NOT exist.
532
     */
533
    public void gdVerifyPathByIndices(String pathType, int preAscend,
534
            String treePath, boolean exists) {
535
        try {
536
            gdExpandByIndices(pathType, preAscend, treePath);
537
        } catch (StepExecutionException e) {
538
            if (exists) {
539
                throw new StepVerifyFailedException("Verify failed on tree-path: " //$NON-NLS-1$
540
                    + treePath,
541
                    EventFactory.createVerifyFailed(treePath, 
542
                            StringConstants.EMPTY));
543
            }
544
            return;
545
        }
546
        if (!exists) {
547
            throw new StepVerifyFailedException("Verify failed on tree-path: ",  //$NON-NLS-1$
548
                EventFactory.createVerifyFailed(
549
                        StringConstants.EMPTY, treePath));
550
        }
551
    }
552
    
553
    /**
554
     * {@inheritDoc}
555
     */
556
    public String gdStoreSelectedNodeValue(String variable) {
557
        AbstractTreeOperationContext context = getTreeAdapter().getContext();
558
        Object selectedNode = 
559
            getSelectedNode(context);
560
        if (selectedNode == null) {
561
            throw new StepExecutionException("No tree item selected", //$NON-NLS-1$ 
562
                EventFactory.createActionError(TestErrorEvent.NO_SELECTION));
563
        }
564
        
565
        return context.getRenderedText(selectedNode);
566
    }
567
    
568
    /**
569
     * Returns the text from the mouse position.
570
     * @param variable -
571
     * @return the text from the node at mouse position
572
     */
573
    public String gdStoreValueAtMousePosition(String variable) {
574
        AbstractTreeOperationContext context = getTreeAdapter().getContext();
575
        
576
        return context.getRenderedText(getNodeAtMousePosition());
577
    }
578
    /**
579
     * 
580
     * @return the tree node at the current mouse position.
581
     * @throws StepExecutionException If no tree node can be found at the 
582
     *                                current mouse position.
583
     */
584
    protected abstract Object getNodeAtMousePosition() 
585
        throws StepExecutionException;
586
587
    /**
588
     * Verifies whether the first selection in the tree has a rendered text that is
589
     * equal to <code>selection</code>.
590
     *
591
     * @param selection
592
     *            The selection to verify
593
     * @throws StepExecutionException
594
     *             If no node is selected or the verification fails.
595
     */
596
    public void gdVerifySelectedValue(String selection)
597
        throws StepExecutionException {
598
        gdVerifySelectedValue(selection, MatchUtil.DEFAULT_OPERATOR);
599
    }
600
601
    /**
602
     * Verifies whether the first selection in the tree has a rendered text that is
603
     * equal to <code>pattern</code>.
604
     *
605
     * @param pattern
606
     *            The expected text
607
     * @param operator
608
     *            The operator to use when comparing the expected and
609
     *            actual values.
610
     * @throws StepExecutionException
611
     *             If no node is selected or the verification fails.
612
     */
613
    public void gdVerifySelectedValue(String pattern, String operator)
614
        throws StepExecutionException {
615
616
        AbstractTreeOperationContext context = getTreeAdapter().getContext();
617
        checkNodeText(getSelectedNode(context), pattern, operator);
618
    }
619
    
620
621
622
    /**
623
     * Checks the text for the given node against the given pattern and 
624
     * operator.
625
     * 
626
     * @param node The node containing the text to check.
627
     * @param pattern The expected text.
628
     * @param operator The operator to use when comparing the expected and
629
     *          actual values.
630
     * @throws StepVerifyFailedException If the verification fails.
631
     */
632
    protected void checkNodeText(Object node, String pattern, String operator) 
633
        throws StepVerifyFailedException {
634
        
635
        AbstractTreeOperationContext context = getTreeAdapter().getContext();
636
        Collection nodeTextList = context.getNodeTextList(node);
637
        Iterator it = nodeTextList.iterator();
638
        boolean isMatched = false;
639
        while (it.hasNext() && !isMatched) {
640
            try {
641
                Verifier.match((String)it.next(), pattern, operator);
642
                isMatched = true;
643
            } catch (StepVerifyFailedException svfe) {
644
                if (!it.hasNext()) {
645
                    throw svfe;
646
                }
647
                // Otherwise just try the next element
648
            }
649
        }
650
    }
651
    
652
    /**
653
     * @param pathType  For example, "relative" or "absolute".
654
     * @param preAscend Relative traversals will start this many parent nodes
655
     *            above the current node. Absolute traversals ignore this
656
     *            parameter.
657
     * @param context The context of the traversal.
658
     * @return The node at which to begin the traversal or <code>null</code>
659
     *         if the traversal should begin at the root of the node.
660
     */
661
    protected Object getStartNode(String pathType, int preAscend,
662
            AbstractTreeOperationContext context) {
663
        Object startNode;
664
        ITreeAdapter tree = getTreeAdapter();
665
        if (pathType.equals(
666
                CompSystemConstants.TREE_PATH_TYPE_RELATIVE)) {
667
            startNode = getSelectedNode(context);
668
            Object child = startNode;
669
            for (int i = 0; i < preAscend; ++i) {
670
                if ((startNode == null) || ((tree.isRootVisible()) 
671
                        && (tree.getRootNode() == null))) {
672
                    TestErrorEvent event = EventFactory
673
                        .createActionError(TestErrorEvent.TREE_NODE_NOT_FOUND);
674
                    throw new StepExecutionException(
675
                        "Tree node not found: Parent of " //$NON-NLS-1$
676
                        + child.toString(), event);
677
                }
678
                child = startNode;
679
                startNode = context.getParent(startNode);
680
                
681
            }
682
         // Extra handling for tree without visible root node
683
            if ((startNode == null) || ((tree.isRootVisible()) 
684
                    && (tree.getRootNode() == null))) {
685
                startNode = null;
686
            }
687
        } else if (pathType.equals(
688
                CompSystemConstants.TREE_PATH_TYPE_ABSOLUTE)) {
689
            startNode = null;
690
        } else {
691
            throw new StepExecutionException(
692
                    pathType + " is not a valid Path Type", EventFactory //$NON-NLS-1$
693
                    .createActionError(TestErrorEvent.INVALID_PARAM_VALUE));
694
695
        }
696
        
697
        return startNode;
698
    }
699
    
700
    /**
701
     * @param mouseButton mouseButton
702
     * @param modifierSpecification modifierSpecification
703
     * @param pathType pathType
704
     * @param preAscend preAscend
705
     * @param treeTextPath treeTextPath
706
     * @param operator operator */ 
707
    public abstract void gdDragByTextPath(
708
        int mouseButton, 
709
        String modifierSpecification, 
710
        String pathType, 
711
        int preAscend, 
712
        String treeTextPath, 
713
        String operator);
714
715
    /**
716
     * @param pathType pathType
717
     * @param preAscend preAscend
718
     * @param treeTextPath treeTextPath
719
     * @param operator operator
720
     * @param delayBeforeDrop delayBeforeDrop */ 
721
    public abstract void gdDropByTextPath(
722
        String pathType, 
723
        int preAscend, 
724
        String treeTextPath, 
725
        String operator, 
726
        int delayBeforeDrop);
727
728
    /**
729
     * @param mouseButton mouseButton
730
     * @param modifierSpecification modifierSpecification
731
     * @param pathType pathType
732
     * @param preAscend preAscend
733
     * @param treeIndexPath treeIndexPath */ 
734
    public abstract void gdDragByIndexPath(
735
        int mouseButton, 
736
        String modifierSpecification, 
737
        String pathType, 
738
        int preAscend, 
739
        String treeIndexPath);
740
741
    /**
742
     * @param pathType pathType
743
     * @param preAscend preAscend
744
     * @param treeIndexPath treeIndexPath
745
     * @param delayBeforeDrop delayBeforeDrop */ 
746
    public abstract void gdDropByIndexPath(
747
        String pathType, 
748
        int preAscend, 
749
        String treeIndexPath, 
750
        int delayBeforeDrop);
751
752
    
753
    
754
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractUICAPs.java (+78 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
14
import org.eclipse.jubula.rc.common.AUTServer;
15
import org.eclipse.jubula.rc.common.driver.IRobot;
16
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
17
import org.eclipse.jubula.rc.common.exception.RobotException;
18
import org.eclipse.jubula.rc.common.implclasses.IBaseImplementationClass;
19
import org.eclipse.jubula.rc.common.uiadapter.factory.GUIAdapterFactoryRegistry;
20
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
21
/**
22
 * Implementation of basic functions for all tester classes. This class
23
 * gives the basic functions which are needed for testing.
24
 * 
25
 * 
26
 * @author BREDEX GmbH
27
 */
28
public abstract class AbstractUICAPs implements IBaseImplementationClass {
29
30
    
31
    
32
    /** constants for communication */
33
    protected static final String POS_UNIT_PIXEL = "Pixel"; //$NON-NLS-1$
34
    
35
    /** constants for communication */
36
    protected static final String POS_UNI_PERCENT = "Percent"; //$NON-NLS-1$
37
    /**    */
38
    private IComponentAdapter m_component;
39
40
41
    /**
42
     * Gets the Robot. 
43
     * @return The Robot
44
     * @throws RobotException If the Robot cannot be created.
45
     */
46
    protected IRobot getRobot() throws RobotException {
47
        return AUTServer.getInstance().getRobot();
48
    }
49
    /**
50
     * Gets the Robot factory. The factory is created once per instance.
51
     * @return The Robot factory.
52
     */
53
    protected abstract IRobotFactory getRobotFactory();
54
    
55
    /**
56
     * {@inheritDoc}
57
     */
58
    public void setComponent(Object graphicsComponent) {
59
        GUIAdapterFactoryRegistry afr = GUIAdapterFactoryRegistry.getInstance();
60
        m_component = null;
61
        IComponentAdapter adapter = 
62
                (IComponentAdapter)afr.getAdapter(graphicsComponent);
63
        m_component = adapter;
64
    }
65
    /**
66
     * Getter for the stored GraphicalComponent
67
     * @return gets the stored IComponentAdapter
68
     */
69
    public IComponentAdapter getComponent() {
70
        return m_component;
71
    }
72
73
    
74
    
75
    
76
77
    
78
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/caps/AbstractWidgetCAPs.java (+486 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.CompSystemConstants;
14
import org.eclipse.jubula.rc.common.driver.ClickOptions;
15
import org.eclipse.jubula.rc.common.driver.ClickOptions.ClickModifier;
16
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
17
import org.eclipse.jubula.rc.common.implclasses.Verifier;
18
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IWidgetAdapter;
19
/**
20
 * Implementation of basic functions for a lot of graphics components
21
 * except for context menus and menus. 
22
 * 
23
 * @author BREDEX GmbH
24
 */
25
public abstract class AbstractWidgetCAPs extends AbstractUICAPs {
26
27
    
28
    /**
29
     * Casts the IComponentAdapter to an IWidgetAdapter for better access
30
     * @return The widgetAdapter
31
     */
32
    private IWidgetAdapter getWidgetAdapter() {
33
        return (IWidgetAdapter) getComponent();
34
    }
35
    
36
    /**
37
     * Verifies that the component exists and is visible.
38
     *
39
     * @param exists  <code>True</code> if the component is expected to exist
40
     *            and be visible, otherwise <code>false</code>.
41
     */
42
    public void gdVerifyExists(boolean exists) {
43
        Verifier.equals(exists, getWidgetAdapter().isShowing());
44
    }
45
46
47
    /**
48
     * Verifies if the component has the focus.
49
     * @param hasFocus <code>True</code> if the component is expected to has 
50
     *                  the focus, otherwise <code>false</code>
51
     */
52
    public void gdVerifyFocus(boolean hasFocus) {
53
        Verifier.equals(hasFocus, getWidgetAdapter().hasFocus());
54
    }
55
    /**
56
     * Verifies if the component is enabled
57
     * @param enabled <code>True</code> if the component is expected to be 
58
     *                  enabled, otherwise <code>false</code>
59
     */
60
    public void gdVerifyEnabled(boolean enabled) {
61
        Verifier.equals(enabled, getWidgetAdapter().isEnabled());
62
    }
63
    
64
    /**
65
     * Verifies the value of the property with the name <code>name</code>.
66
     * The name of the property has be specified according to the JavaBean
67
     * specification. The value returned by the property is converted into a
68
     * string by calling <code>toString()</code> and is compared to the passed
69
     * <code>value</code>.
70
     * 
71
     * @param name The name of the property
72
     * @param value The value of the property as a string
73
     * @param operator The operator used to verify
74
     */
75
    public void gdVerifyProperty(final String name, String value,
76
            String operator) {
77
        
78
        final IWidgetAdapter bean = (IWidgetAdapter) getComponent();
79
        bean.getPropteryValue(name);
80
81
        final String propToStr = bean.getPropteryValue(name);
82
        Verifier.match(propToStr, value, operator);
83
    }
84
85
    
86
    /**
87
     * Clicks the center of the component.
88
     * @param count Number of mouse clicks
89
     * @param button Pressed button
90
     */
91
    public void gdClick(int count, int button) {
92
        getRobot().click(getComponent().getRealComponent(), null,
93
                ClickOptions.create()
94
                    .setClickCount(count)
95
                    .setMouseButton(button));
96
    }
97
    /**
98
     * clicks into a component.
99
     *
100
     * @param count amount of clicks
101
     * @param button what mouse button should be used
102
     * @param xPos what x position
103
     * @param xUnits should x position be pixel or percent values
104
     * @param yPos what y position
105
     * @param yUnits should y position be pixel or percent values
106
     * @throws StepExecutionException error
107
     */
108
    public void gdClickDirect(int count, int button, int xPos, String xUnits,
109
            int yPos, String yUnits) throws StepExecutionException {
110
111
        getRobot().click(getComponent().getRealComponent(), null,
112
                ClickOptions.create()
113
                    .setClickCount(count)
114
                    .setMouseButton(button),
115
                xPos, xUnits.equalsIgnoreCase(POS_UNIT_PIXEL),
116
                yPos, yUnits.equalsIgnoreCase(POS_UNIT_PIXEL));
117
    }
118
    
119
    /**
120
     * Performs a Drag. Moves into the middle of the Component and presses and
121
     * holds the given modifier and the given mouse button.
122
     * @param mouseButton the mouse button.
123
     * @param modifier the modifier, e.g. shift, ctrl, etc.
124
     * @param xPos what x position
125
     * @param xUnits should x position be pixel or percent values
126
     * @param yPos what y position
127
     * @param yUnits should y position be pixel or percent values
128
     */
129
    public void gdDrag(int mouseButton, String modifier, int xPos,
130
            String xUnits, int yPos, String yUnits) {
131
        getWidgetAdapter().gdDrag(mouseButton, modifier, xPos, xUnits,
132
                yPos, yUnits);
133
    }
134
135
136
    /**
137
     * Performs a Drop. Moves into the middle of the Component and releases
138
     * the modifier and mouse button pressed by gdDrag.
139
     * @param xPos what x position
140
     * @param xUnits should x position be pixel or percent values
141
     * @param yPos what y position
142
     * @param yUnits should y position be pixel or percent values
143
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
144
     *                        between moving the mouse to the drop point and
145
     *                        releasing the mouse button
146
     */
147
    public void gdDrop(int xPos, String xUnits, int yPos, String yUnits,
148
            int delayBeforeDrop) {
149
150
        getWidgetAdapter().gdDrop(xPos, xUnits, yPos, yUnits,
151
               delayBeforeDrop);
152
    }
153
    
154
    /**
155
     * dummy method for "wait for component"
156
     * @param timeout the maximum amount of time to wait for the component
157
     * @param delay the time to wait after the component is found
158
     * {@inheritDoc}
159
     */
160
    public void gdWaitForComponent (int timeout, int delay) {
161
        // do NOT delete this method!
162
        // do nothing, implementation is in class CAPTestCommand.getImplClass
163
        // because this action needs a special implementation!
164
    }
165
    
166
    /**
167
     * Stores the value of the property with the name <code>name</code>.
168
     * The name of the property has be specified according to the JavaBean
169
     * specification. The value returned by the property is converted into a
170
     * string by calling <code>toString()</code> and is stored to the passed
171
     * variable.
172
     * 
173
     * @param variableName The name of the variable to store the property value in
174
     * @param propertyName The name of the property
175
     * @return the property value.
176
     */
177
    public String gdStorePropertyValue(String variableName, 
178
        final String propertyName) {
179
        IWidgetAdapter bean = (IWidgetAdapter) getComponent();
180
181
        return bean.getPropteryValue(propertyName);
182
    }
183
    
184
    /**
185
     * Select an item in the popup menu
186
     * @param indexPath path of item indices
187
     * @param button MouseButton
188
     * @throws StepExecutionException error
189
     */
190
    public void gdPopupSelectByIndexPath(String indexPath, int button)
191
        throws StepExecutionException {
192
193
        AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
194
        popup.selectMenuItemByIndexpath(indexPath);
195
    }
196
    /**
197
     * Selects an item in the popup menu
198
     * @param textPath path of item texts
199
     * @param operator operator used for matching
200
     * @param button MouseButton
201
     * @throws StepExecutionException error
202
     */
203
    public void gdPopupSelectByTextPath(String textPath, String operator,
204
            int button)
205
        throws StepExecutionException {
206
        AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
207
        popup.selectMenuItem(textPath, operator);
208
    }
209
    /**
210
     * Selects an item in the popup menu
211
     *
212
     * @param xPos what x position
213
     * @param xUnits should x position be pixel or percent values
214
     * @param yPos what y position
215
     * @param yUnits should y position be pixel or percent values
216
     * @param textPath path of item texts
217
     * @param operator operator used for matching
218
     * @param button MouseButton
219
     * @throws StepExecutionException error
220
     */
221
    public void gdPopupSelectByTextPath(final int xPos, final String xUnits, 
222
            final int yPos, final String yUnits, 
223
            String textPath, String operator, int button)
224
        throws StepExecutionException {
225
        AbstractMenuCAPs popup = getWidgetAdapter()
226
                .showPopup(xPos, xUnits, yPos, yUnits, button);
227
        popup.selectMenuItem(textPath, operator);
228
    }
229
    
230
    /**
231
     * Opens the popup menu at the given position relative the current component
232
     * and selects an item at the given position in the popup menu
233
     *
234
     * @param xPos what x position
235
     * @param xUnits should x position be pixel or percent values
236
     * @param yPos what y position
237
     * @param yUnits should y position be pixel or percent values
238
     * @param indexPath path of item indices
239
     * @param button MouseButton
240
     * @throws StepExecutionException error
241
     */
242
    public void gdPopupSelectByIndexPath(
243
            int xPos, String xUnits, int yPos, String yUnits, 
244
            String indexPath, int button) throws StepExecutionException {
245
        AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
246
        popup.selectMenuItemByIndexpath(indexPath);
247
    }
248
    
249
    /**
250
     * Checks if the specified context menu entry is enabled.
251
     * @param indexPath the menu item to verify
252
     * @param enabled for checking enabled or disabled
253
     * @param button MouseButton
254
     */
255
    public void gdPopupVerifyEnabledByIndexPath(String indexPath,
256
            boolean enabled, int button)
257
        throws StepExecutionException {
258
        AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);        
259
        popup.verifyEnabledByIndexpath(indexPath, enabled);
260
    }
261
    
262
  
263
    /**
264
     * Opens the popup menu at the given position relative the current component
265
     * and checks if the specified context menu entry is enabled.
266
     * @param xPos what x position
267
     * @param xUnits should x position be pixel or percent values
268
     * @param yPos what y position
269
     * @param yUnits should y position be pixel or percent values
270
     * @param indexPath the menu item to verify
271
     * @param enabled for checking enabled or disabled
272
     * @param button MouseButton
273
     */
274
    public void gdPopupVerifyEnabledByIndexPath(int xPos, String xUnits, 
275
            int yPos, String yUnits, String indexPath, 
276
            boolean enabled, int button) throws StepExecutionException {
277
        AbstractMenuCAPs popup = getWidgetAdapter()
278
                .showPopup(xPos, xUnits, yPos, yUnits, button);
279
        popup.verifyEnabledByIndexpath(indexPath, enabled);
280
    }
281
    
282
    /**
283
     * Checks if the specified context menu entry is enabled.
284
     * @param textPath the menu item to verify
285
     * @param operator operator used for matching
286
     * @param enabled for checking enabled or disabled
287
     * @param button MouseButton
288
     */
289
    public void gdPopupVerifyEnabledByTextPath(String textPath,
290
            String operator, boolean enabled, int button)
291
        throws StepExecutionException {
292
        AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
293
        popup.verifyEnabled(textPath, operator, enabled);
294
    }
295
    
296
    /**
297
     * Opens the popup menu at the given position relative the current component
298
     * and checks if the specified context menu entry is enabled.
299
     * @param xPos what x position
300
     * @param xUnits should x position be pixel or percent values
301
     * @param yPos what y position
302
     * @param yUnits should y position be pixel or percent values
303
     * @param textPath the menu item to verify
304
     * @param operator operator used for matching
305
     * @param enabled for checking enabled or disabled
306
     * @param button MouseButton
307
     */
308
    public void gdPopupVerifyEnabledByTextPath(final int xPos, 
309
            final String xUnits, final int yPos,
310
            final String yUnits, String textPath, String operator,
311
                boolean enabled, int button)
312
        throws StepExecutionException {
313
        AbstractMenuCAPs popup = getWidgetAdapter()
314
                .showPopup(xPos, xUnits, yPos, yUnits, button);
315
        popup.verifyEnabled(textPath, operator, enabled);
316
    }
317
    
318
    /**
319
     * Checks if the specified context menu entry is selected.
320
     * @param indexPath the menu item to verify
321
     * @param selected for checking if entry is selected
322
     * @param button MouseButton
323
     */
324
    public void gdPopupVerifySelectedByIndexPath(String indexPath,
325
            boolean selected, int button)
326
        throws StepExecutionException {
327
        AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
328
        popup.verifySelectedByIndexpath(indexPath, selected);
329
    }
330
    
331
    /**
332
     * Opens the popup menu at the given position relative the current component
333
     * and checks if the specified context menu entry is selected.
334
     * @param xPos what x position
335
     * @param xUnits should x position be pixel or percent values
336
     * @param yPos what y position
337
     * @param yUnits should y position be pixel or percent values
338
     * @param indexPath the menu item to verify
339
     * @param selected for checking if entry is selected
340
     * @param button MouseButton
341
     */
342
    public void gdPopupVerifySelectedByIndexPath(int xPos, String xUnits, 
343
            int yPos, String yUnits, String indexPath, boolean selected, 
344
            int button) throws StepExecutionException {
345
        AbstractMenuCAPs popup = getWidgetAdapter()
346
                .showPopup(xPos, xUnits, yPos, yUnits, button);
347
        popup.verifySelectedByIndexpath(indexPath, selected);
348
    }
349
    
350
    /**
351
     * Checks if the specified context menu entry is selected.
352
     * @param textPath the menu item to verify
353
     * @param operator operator used for matching
354
     * @param selected for checking if entry is selected
355
     * @param button MouseButton
356
     */
357
    public void gdPopupVerifySelectedByTextPath(String textPath,
358
            String operator, boolean selected, int button)
359
        throws StepExecutionException {
360
        AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
361
        popup.verifySelected(textPath, operator, selected);
362
    }
363
    
364
    /**
365
     * Opens the popup menu at the given position relative the current component
366
     * and checks if the specified context menu entry is selected.
367
     * @param xPos what x position
368
     * @param xUnits should x position be pixel or percent values
369
     * @param yPos what y position
370
     * @param yUnits should y position be pixel or percent values
371
     * @param textPath the menu item to verify
372
     * @param operator operator used for matching
373
     * @param selected for checking if entry is selected
374
     * @param button MouseButton
375
     */
376
    public void gdPopupVerifySelectedByTextPath(final int xPos, 
377
            final String xUnits, final int yPos,
378
            final String yUnits, String textPath, String operator,
379
                boolean selected, int button)
380
        throws StepExecutionException {
381
        AbstractMenuCAPs popup = getWidgetAdapter()
382
                .showPopup(xPos, xUnits, yPos, yUnits, button);
383
        popup.verifySelected(textPath, operator, selected);
384
    }
385
    
386
    /**
387
     * Checks if the specified context menu entry exists.
388
     * @param indexPath the menu item to verify
389
     * @param exists for checking if entry exists
390
     * @param button MouseButton
391
     */
392
    public void gdPopupVerifyExistsByIndexPath(String indexPath,
393
            boolean exists, int button)
394
        throws StepExecutionException {
395
        AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
396
        popup.verifyExistsByIndexpath(indexPath, exists);      
397
    }
398
    
399
    /**
400
     * Opens the popup menu at the given position relative the current component
401
     * and checks if the specified context menu entry exists.
402
     * @param xPos what x position
403
     * @param xUnits should x position be pixel or percent values
404
     * @param yPos what y position
405
     * @param yUnits should y position be pixel or percent values
406
     * @param indexPath the menu item to verify
407
     * @param exists for checking if entry exists
408
     * @param button MouseButton
409
     */
410
    public void gdPopupVerifyExistsByIndexPath(int xPos, String xUnits, 
411
            int yPos, String yUnits, String indexPath, 
412
            boolean exists, int button) throws StepExecutionException {
413
        AbstractMenuCAPs popup = getWidgetAdapter()
414
                .showPopup(xPos, xUnits, yPos, yUnits, button);
415
        popup.verifyExistsByIndexpath(indexPath, exists);
416
    }
417
    
418
    /**
419
     * Checks if the specified context menu entry exists.
420
     * @param textPath the menu item to verify
421
     * @param operator operator used for matching
422
     * @param exists for checking if entry exists
423
     * @param button MouseButton
424
     */
425
    public void gdPopupVerifyExistsByTextPath(String textPath,
426
            String operator, boolean exists, int button)
427
        throws StepExecutionException {
428
        AbstractMenuCAPs popup = getWidgetAdapter().showPopup(button);
429
        popup.verifyExists(textPath, operator, exists);
430
    }
431
    
432
    /**
433
     * Opens the popup menu at the given position relative the current component
434
     * and checks if the specified context menu entry exists.
435
     * @param xPos what x position
436
     * @param xUnits should x position be pixel or percent values
437
     * @param yPos what y position
438
     * @param yUnits should y position be pixel or percent values
439
     * @param textPath the menu item to verify
440
     * @param operator operator used for matching
441
     * @param exists for checking if entry exists
442
     * @param button MouseButton
443
     */
444
    public void gdPopupVerifyExistsByTextPath(final int xPos, 
445
            final String xUnits, final int yPos,
446
            final String yUnits, String textPath, String operator,
447
            boolean exists, int button)
448
        throws StepExecutionException {
449
        AbstractMenuCAPs popup = getWidgetAdapter()
450
                .showPopup(xPos, xUnits, yPos, yUnits, button);
451
        popup.verifyExists(textPath, operator, exists);
452
    }
453
    /**
454
     * 
455
     * @param extendSelection
456
     *            the string to indicate that the selection should be extended
457
     * @return a ClickModifier for the given extend selection
458
     */
459
    protected ClickModifier getClickModifier(String extendSelection) {
460
        // FIXME This is a method which belongs in an upper class
461
        
462
        ClickModifier cm = ClickModifier.create();
463
        if (CompSystemConstants.EXTEND_SELECTION_YES
464
                .equalsIgnoreCase(extendSelection)) {
465
            cm.add(ClickModifier.M1);
466
        }
467
        return cm;
468
    }
469
    
470
    /**
471
     * Simulates a tooltip for demonstration purposes.
472
     *
473
     * @param text The text to show in the tooltip
474
     * @param textSize The size of the text in points
475
     * @param timePerWord The amount of time, in milliseconds, used to display a
476
     *                    single word. A word is defined as a string surrounded
477
     *                    by whitespace.
478
     * @param windowWidth The width of the tooltip window in pixels.
479
     */
480
    public void gdShowText(final String text, final int textSize,
481
        final int timePerWord, final int windowWidth) {
482
        getWidgetAdapter().showToolTip(text, textSize,
483
                timePerWord, windowWidth);
484
    }
485
486
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/driver/DragAndDropHelper.java (+18 lines)
Lines 30-35 public class DragAndDropHelper { Link Here
30
    /** Flag if the Mouse is in drag mode (pressed key) */
30
    /** Flag if the Mouse is in drag mode (pressed key) */
31
    private boolean m_isDragMode = false;
31
    private boolean m_isDragMode = false;
32
    
32
    
33
    /** The Component to drag */
34
    private Object m_dragComponent = null;
35
    
36
    
33
    /**
37
    /**
34
     * hidden singleton constructor.
38
     * hidden singleton constructor.
35
     */
39
     */
Lines 92-95 public class DragAndDropHelper { Link Here
92
        m_isDragMode = drag;
96
        m_isDragMode = drag;
93
    }
97
    }
94
    
98
    
99
    /**
100
     * @return the dragComponent
101
     */
102
    public Object getDragComponent() {
103
        return m_dragComponent;
104
    }
105
106
    /**
107
     * @param dragComponent the dragComponent to set
108
     */
109
    public void setDragComponent(Object dragComponent) {
110
        m_dragComponent = dragComponent;
111
    }
112
    
95
}
113
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/factory/GUIAdapterFactoryRegistry.java (+99 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.factory;
12
13
import java.util.HashMap;
14
import java.util.Map;
15
16
import org.eclipse.jubula.rc.common.adaptable.IAdapterFactory;
17
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
18
/**
19
 * This factory registry holds all the toolkit specific factory's.
20
 * These factory's holding the classes which are implementing the component
21
 * specific interface. It could be an adapter or the specific component
22
 * implementing the interface.
23
 * 
24
 * You must register a factory before a test is started.
25
 * @author BREDEX GmbH
26
 *
27
 */
28
public class GUIAdapterFactoryRegistry {
29
30
    /**
31
     * Singleton instance of this class
32
     */
33
    private static GUIAdapterFactoryRegistry instance = 
34
        new GUIAdapterFactoryRegistry();
35
36
    /**
37
     * Map that manages the registration. Key is always a class Value is a
38
     * collection of IAdapterFactory
39
     */
40
    private Map m_registrationMap = new HashMap();
41
42
    /**
43
     * Call Constructor only by using getInstance
44
     */
45
    private GUIAdapterFactoryRegistry() {
46
    }
47
48
    /**
49
     * Return the singleton of this class
50
     * 
51
     * @return singleton
52
     */
53
    public static GUIAdapterFactoryRegistry getInstance() {
54
        return instance;
55
    }
56
57
    /**
58
     * Register adapter factory with all its supported classes
59
     * 
60
     * @param factory
61
     *            adapter factory that should be registered
62
     */
63
    public void registerFactory(IUIAdapterFactory factory) {
64
        Class[] supportedClasses = factory.getSupportedClasses();
65
        for (int i = 0; i < supportedClasses.length; i++) {
66
            m_registrationMap.put(supportedClasses[i], factory);
67
        }
68
    }
69
70
    /**
71
     * Sign off adapter factory from all its supported classes
72
     * 
73
     * @param factory
74
     *            adapter factory that should be signed off
75
     */
76
    public void signOffFactory(IAdapterFactory factory) {
77
        Class[] supportedClasses = factory.getSupportedClasses();
78
        for (int i = 0; i < supportedClasses.length; i++) {
79
            m_registrationMap.remove(supportedClasses[i]);
80
        }
81
    }
82
    /**
83
     * 
84
     * @param objectToAdapt 
85
     * @return -
86
     */
87
    public IComponentAdapter getAdapter(Object objectToAdapt) {
88
        Class adapteeclass = objectToAdapt.getClass();
89
        IUIAdapterFactory factory = (IUIAdapterFactory) m_registrationMap.
90
                get(adapteeclass);
91
        while (factory == null && adapteeclass != Object.class) {
92
            factory = (IUIAdapterFactory) m_registrationMap.
93
                get(adapteeclass.getSuperclass());
94
        }
95
        
96
        return factory.getAdapter(objectToAdapt);
97
        
98
    }
99
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/factory/IUIAdapterFactory.java (+36 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.factory;
12
13
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
14
15
/**
16
 * This is the interface for the factory which is used by the 
17
 * <code>AbstractUI</code> to get the specific Object which implements the
18
 * corresponding interface for the tester class.
19
 * 
20
 * @author BREDEX GmbH
21
 */
22
public interface IUIAdapterFactory {
23
    /**
24
     * @return all classes that will be supported by this adapter factory
25
     */
26
    Class[] getSupportedClasses();
27
28
    /**
29
     * Adapts object to adapt to a new object of type targetAdapterClass
30
     * 
31
     * @param objectToAdapt
32
     *            object that should be adapted
33
     * @return the adapter for the object to adapt of type targetAdapterClass
34
     */
35
    IComponentAdapter getAdapter(Object objectToAdapt);
36
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IButtonAdapter.java (+41 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
/**
14
 * Interface for all necessary methods to test buttons.
15
 * It extends the <code>IWidgetAdapter</code> to add button specific methods.
16
 * 
17
 * 
18
 * @author BREDEX GmbH
19
 */
20
21
public interface IButtonAdapter extends IWidgetAdapter {
22
    /**
23
     * Gets the text from the button
24
     * @return the text which is saved in the component
25
     */
26
    public String getText();
27
28
    /**
29
     * isSelected is mostly for RadioButtons and CheckBoxes
30
     * @return <code>true</code> if the component is selected
31
     */
32
    public boolean isSelected();
33
    /**
34
     * Action to read the value of a Button to store it in a variable
35
     * in the Client
36
     * @param variable the name of the variable
37
     * @return the text value.
38
     */
39
    public String  readValue(String variable);
40
   
41
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IComponentAdapter.java (+26 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
 * This is the main interface for classes which will hold or be the
14
 * component that implement the methods we need for this
15
 * specific component to test .
16
 * 
17
 * @author BREDEX GmbH
18
 */
19
public interface IComponentAdapter {
20
    /**
21
     * Gets the toolkit specific component
22
     * @return toolkit specific component
23
     */
24
    public Object getRealComponent();
25
   
26
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IMenuAdapter.java (+35 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
14
/**
15
 * This interface is for the functionality of menus. This is only for the
16
 * not visible part of menus which only contains the next menuitems in the
17
 * Hierarchy of the menu.
18
 * 
19
 * @author BREDEX GmbH
20
 */
21
public interface IMenuAdapter extends IComponentAdapter {
22
23
    /**
24
     * 
25
     * @return the items of the menu
26
     */
27
    public IMenuItemAdapter[] getItems();
28
29
    /**
30
     * Gets the amount of items in the menu
31
     * 
32
     * @return the amount of Items in the menu (with Seperator)
33
     */
34
    public int getItemCount();
35
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IMenuItemAdapter.java (+80 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
/**
14
 * Interface for all necessary methods for testing menuitems.
15
 * 
16
 * @author BREDEX GmbH
17
 */
18
public interface IMenuItemAdapter extends IComponentAdapter {
19
20
    /**
21
     * 
22
     * @return the text which is saved in the item
23
     */
24
    public String getText();
25
    /**
26
     * 
27
     * @return <code>true</code> if the component is visible
28
     */
29
    public boolean isEnabled();
30
    /**
31
     * 
32
     * @return <code>true</code> if the component exists
33
     *         that means there is an item in this wrapper 
34
     */
35
    public boolean isExisting();
36
    /**
37
     * 
38
     * @return <code>true</code> if the component is selected
39
     * 
40
     */
41
    public boolean isSelected();
42
    /**
43
     * 
44
     * @return <code>true</code> if the component is Showing
45
     */
46
    public boolean isShowing();
47
    
48
    /** Gets the menu of the menuitem 
49
     * @return the menu which is attached to the item
50
     */
51
    public IMenuAdapter getMenu();
52
    
53
    /**
54
     * 
55
     * @return <code>true</code> if the menuitem has a menu
56
     */
57
    public boolean hasSubMenu();
58
    /**
59
     * Checks whether the given menu item is a separator. 
60
     * This method runs in the GUI thread.
61
     * @return <code>true</code> if <code>menuItem</code> is a separator item.
62
     *         Otherwise <code>false</code>.
63
     */
64
    public boolean isSeparator();
65
    
66
    /**
67
     * This Methods selects the specific menuItem with an click
68
     * or in another toolkit specitif way
69
     */
70
    public void selectMenuItem();
71
    
72
    /**
73
     * This method trys to open the the next Menu in the cascade
74
     * 
75
     * @return the next SubMenu in the Menu
76
     */
77
    public IMenuAdapter openSubMenu();
78
   
79
    
80
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITableAdapter.java (+128 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 java.awt.Rectangle;
14
15
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
16
import org.eclipse.jubula.rc.common.implclasses.table.Cell;
17
18
/**
19
 * Interface for all necessary methods for testing tables.
20
 * 
21
 * @author BREDEX GmbH
22
 */
23
public interface ITableAdapter extends IWidgetAdapter {
24
    
25
    
26
    /**
27
     * Gets the number of columns
28
     * 
29
     * @return the number of columns
30
     */
31
    public int getColumnCount();
32
    
33
    /**
34
     * Gets the number of rows
35
     * 
36
     * @return the number of rows
37
     */
38
    public int getRowCount();
39
    
40
    /**
41
     * @param row the zero based index of the row
42
     * @param column the zero based index of the column
43
     * @return the text of the cell of the given coordinates
44
     */
45
    public String getCellText(int row, int column);
46
     
47
    /**
48
     * Returns the name of the column appearing in the view at
49
     * column position <code>column</code>.
50
     *
51
     * @param  column    the column in the view being queried
52
     * @return the name of the column at position <code>column</code>
53
            in the view where the first column is column 0
54
     */
55
    public String getColumnName(int column);
56
    
57
    /**
58
     * Gets column index from string with header name or index
59
     *
60
     * @param col Headername or index of column 
61
     * @param operator The operation used to verify
62
     * @return column index 
63
     */
64
    public int getColumnFromString(String col, String operator);
65
    
66
    /**
67
     * This is only for a specific case where tables could act
68
     * like lists. And the getText is not working.
69
     * If this is not the case for the component return <code>null</code>
70
     * @param row the row
71
     * @return the text of the row
72
     */
73
    public String getRowName(int row);
74
    
75
    /**
76
     * Gets row index from string with index or text of first row
77
     *
78
     * @param row index or value in first col
79
     * @param operator The operation used to verify
80
     * @return integer of String of row 
81
     */
82
    public int getRowFromString(String row, String operator);
83
    
84
    /**
85
     * gets header bounds for column
86
     * @param col The column.
87
     * @return The rectangle of the header
88
     */
89
    public Rectangle getHeaderBounds(int col);
90
91
    /**
92
     * @return The currently selected cell of the Table.
93
     * @throws StepExecutionException If no cell is selected.
94
     */
95
    public Cell getSelectedCell() throws StepExecutionException;
96
    
97
    /**
98
     * 
99
     * @return <code>true</code> if the Header is visible, <code>false</code> otherwise
100
     */
101
    public boolean isHeaderVisible();
102
103
    /**
104
     * 
105
     * @param row the row
106
     * @param col the column
107
     * @return <code>true</code> if the Cell is editable, <code>false</code> otherwise
108
     */
109
    public boolean isCellEditable(int row, int col);
110
111
    /**
112
     * @return true, if there is any cell selection in the table, false otherwise.
113
     */
114
    public boolean hasCellSelection();
115
    
116
    /**
117
     * Scrolls the passed cell (as row and column) to visible.<br>
118
     * This method must return null if there is no scrolling.
119
     * @param row The row.
120
     * @param col The column.
121
     * @return The rectangle of the cell.
122
     * @throws StepExecutionException If getting the cell rectangle or the scrolling fails.
123
     */
124
    public Rectangle scrollCellToVisible (int row , int col)
125
        throws StepExecutionException;
126
    
127
128
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/ITreeAdapter.java (+41 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.implclasses.tree.AbstractTreeOperationContext;
14
15
/**
16
 * Interface for all necessary methods for testing trees.
17
 * 
18
 * @author BREDEX GmbH
19
 */
20
public interface ITreeAdapter extends IWidgetAdapter {
21
22
    /**
23
     * Gets the root node(s) of the tree.
24
     * This could be either a single node or multiple nodes
25
     * @return The root node(s).
26
     */ 
27
    public Object getRootNode();
28
    
29
    /**
30
     * Gets the TreeOperationContext which is created through an
31
     * toolkit specific implementation.
32
     * @return the TreeOperationContext for the tree
33
     */
34
    public AbstractTreeOperationContext getContext();
35
    
36
    /**
37
     * 
38
     * @return The visibility of the Root Node
39
     */
40
    public boolean isRootVisible();
41
}
(-)a/org.eclipse.jubula.rc.common/src/org/eclipse/jubula/rc/common/uiadapter/interfaces/IWidgetAdapter.java (+110 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.caps.AbstractMenuCAPs;
14
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
15
16
/**
17
 * This interface defines basic functionality for nearly all UI components.
18
 * 
19
 * @author BREDEX GmbH
20
 */
21
public interface IWidgetAdapter extends IComponentAdapter {
22
23
    /**
24
     * 
25
     * @return <code>true</code> if the component is visible
26
     */
27
    public boolean isShowing();
28
    /**
29
     * 
30
     * @return <code>true</code> if the component is enabled
31
     */
32
    public boolean isEnabled();
33
    /**
34
     * 
35
     * @return <code>true</code> if the component has focus
36
     */
37
    public boolean hasFocus();
38
    /**
39
     * @param propertyname the name of the property value to return
40
     * @return the property value
41
     */
42
    public String getPropteryValue(String propertyname);
43
    
44
    
45
    /**
46
     * Shows and returns the popup menu
47
     *
48
     * @param xPos what x position
49
     * @param xUnits should x position be pixel or percent values
50
     * @param yPos what y position
51
     * @param yUnits should y position be pixel or percent values
52
     * @param button MouseButton
53
     * @return the popup menu
54
     * @throws StepExecutionException error
55
     */
56
    public AbstractMenuCAPs showPopup(final int xPos, 
57
            final String xUnits, final int yPos,
58
            final String yUnits, final int button)
59
        throws StepExecutionException;
60
    
61
    /**
62
     * Shows and returns the popup menu
63
     * @param button MouseButton
64
     * @return the popup menu
65
     */
66
    public AbstractMenuCAPs showPopup(int button);
67
    
68
    
69
    
70
    /**
71
     * Simulates a tooltip for demonstration purposes.
72
     *
73
     * @param text The text to show in the tooltip
74
     * @param textSize The size of the text in points
75
     * @param timePerWord The amount of time, in milliseconds, used to display a
76
     *                    single word. A word is defined as a string surrounded
77
     *                    by whitespace.
78
     * @param windowWidth The width of the tooltip window in pixels.
79
     */
80
    public void showToolTip(final String text, final int textSize,
81
            final int timePerWord, final int windowWidth);
82
    
83
    /**
84
     * Performs a Drag. Moves into the middle of the Component and presses and
85
     * holds the given modifier and the given mouse button.
86
     * @param mouseButton the mouse button.
87
     * @param modifier the modifier, e.g. shift, ctrl, etc.
88
     * @param xPos what x position
89
     * @param xUnits should x position be pixel or percent values
90
     * @param yPos what y position
91
     * @param yUnits should y position be pixel or percent values
92
     */
93
    public void gdDrag(int mouseButton, String modifier, int xPos,
94
            String xUnits, int yPos, String yUnits);
95
    
96
    /**
97
     * Performs a Drop. Moves into the middle of the Component and releases
98
     * the modifier and mouse button pressed by gdDrag.
99
     * @param xPos what x position
100
     * @param xUnits should x position be pixel or percent values
101
     * @param yPos what y position
102
     * @param yUnits should y position be pixel or percent values
103
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
104
     *                        between moving the mouse to the drop point and
105
     *                        releasing the mouse button
106
     */
107
    public void gdDrop(int xPos, String xUnits, int yPos, String yUnits,
108
            int delayBeforeDrop);
109
110
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/SwingAUTServer.java (+7 lines)
Lines 22-33 import org.eclipse.jubula.rc.common.AUTServer; Link Here
22
import org.eclipse.jubula.rc.common.driver.IRobot;
22
import org.eclipse.jubula.rc.common.driver.IRobot;
23
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
23
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
24
import org.eclipse.jubula.rc.common.listener.BaseAUTListener;
24
import org.eclipse.jubula.rc.common.listener.BaseAUTListener;
25
import org.eclipse.jubula.rc.common.uiadapter.factory.GUIAdapterFactoryRegistry;
25
import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
26
import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
26
import org.eclipse.jubula.rc.swing.listener.CheckListener;
27
import org.eclipse.jubula.rc.swing.listener.CheckListener;
27
import org.eclipse.jubula.rc.swing.listener.ComponentHandler;
28
import org.eclipse.jubula.rc.swing.listener.ComponentHandler;
28
import org.eclipse.jubula.rc.swing.listener.FocusTracker;
29
import org.eclipse.jubula.rc.swing.listener.FocusTracker;
29
import org.eclipse.jubula.rc.swing.listener.MappingListener;
30
import org.eclipse.jubula.rc.swing.listener.MappingListener;
30
import org.eclipse.jubula.rc.swing.listener.RecordListener;
31
import org.eclipse.jubula.rc.swing.listener.RecordListener;
32
import org.eclipse.jubula.rc.swing.swing.uiadapter.factory.SwingAdapterFactory;
31
import org.eclipse.jubula.tools.constants.AUTServerExitConstants;
33
import org.eclipse.jubula.tools.constants.AUTServerExitConstants;
32
import org.eclipse.jubula.tools.constants.DebugConstants;
34
import org.eclipse.jubula.tools.constants.DebugConstants;
33
import org.eclipse.jubula.tools.utils.EnvironmentUtils;
35
import org.eclipse.jubula.tools.utils.EnvironmentUtils;
Lines 220-225 public class SwingAUTServer extends AUTServer { Link Here
220
        }
222
        }
221
        
223
        
222
        AUTServer.getInstance().invokeAUT();
224
        AUTServer.getInstance().invokeAUT();
225
        
226
        // FIXME dont know where to put
227
        GUIAdapterFactoryRegistry.getInstance().
228
            registerFactory(new SwingAdapterFactory());
229
        System.out.println("AdapterFactory registered"); //$NON-NLS-1$
223
    }
230
    }
224
231
225
    /**
232
    /**
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/AbstractButtonCAPs.java (+60 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.caps;
12
13
14
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
15
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IButtonAdapter;
16
import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
17
18
/**
19
 * The implementation class for <code>AbstractButton</code> and subclasses. Note
20
 * the "Abstract" in the class name implies only that this class can test
21
 * <code>AbstractButton</code> components. The class itself should <em>NOT</em>
22
 * be designated <code>abstract</code>, as this class is instantiated using
23
 * reflection.
24
 * 
25
 * @author BREDEX GmbH
26
 */
27
public class AbstractButtonCAPs 
28
    extends org.eclipse.jubula.rc.common.caps.AbstractButtonCAPs {
29
30
    /** Robot Factory*/
31
    private IRobotFactory m_robotFactory;
32
33
    /**
34
     * Clicks the button <code>count</code> times.
35
     * 
36
     * @param count The number of clicks
37
     */
38
    public void gdClick(int count) {
39
        gdClick(count, 1);
40
    }
41
42
    /**
43
     * {@inheritDoc}
44
     */
45
    public String[] getTextArrayFromComponent() {
46
        IButtonAdapter returnvalue = ((IButtonAdapter)getComponent());
47
        return new String[] { returnvalue.getText() };
48
    }
49
50
    /** 
51
     * {@inheritDoc}
52
     */
53
    protected IRobotFactory getRobotFactory() {
54
        if (m_robotFactory == null) {
55
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
56
        }
57
        return m_robotFactory;
58
    }
59
60
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/CapUtil.java (+243 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.caps;
12
13
import java.awt.AWTEvent;
14
import java.awt.Component;
15
import java.awt.Container;
16
import java.awt.event.ContainerEvent;
17
import java.lang.reflect.InvocationTargetException;
18
import java.lang.reflect.Method;
19
import java.util.StringTokenizer;
20
21
import javax.swing.AbstractButton;
22
import javax.swing.JLabel;
23
import javax.swing.JPopupMenu;
24
import javax.swing.JToggleButton;
25
import javax.swing.text.JTextComponent;
26
27
import org.eclipse.jubula.rc.common.AUTServer;
28
import org.eclipse.jubula.rc.common.adaptable.AdapterFactoryRegistry;
29
import org.eclipse.jubula.rc.common.adaptable.ITextRendererAdapter;
30
import org.eclipse.jubula.rc.common.driver.IRobot;
31
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
32
import org.eclipse.jubula.rc.common.util.KeyStrokeUtil;
33
import org.eclipse.jubula.rc.swing.swing.driver.KeyCodeConverter;
34
import org.eclipse.jubula.rc.swing.swing.implclasses.EventListener;
35
import org.eclipse.jubula.tools.objects.event.EventFactory;
36
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
37
38
/**
39
 * Util class for Swing specific aspects.
40
 * 
41
 * @author BREDEX GmbH
42
 */
43
public class CapUtil {
44
45
    /**
46
     * <code>RENDERER_FALLBACK_TEXT_GETTER_METHOD_1</code>
47
     */
48
    public static final String RENDERER_FALLBACK_TEXT_GETTER_METHOD_1 = "getTestableText"; //$NON-NLS-1$
49
50
    /**
51
     * <code>RENDERER_FALLBACK_TEXT_GETTER_METHOD_2</code>
52
     */
53
    public static final String RENDERER_FALLBACK_TEXT_GETTER_METHOD_2 = "getText"; //$NON-NLS-1$
54
      
55
   
56
    /**
57
     * Is true, if a popup menu is shown
58
     */
59
    public static class PopupShownCondition implements
60
        EventListener.Condition {
61
62
    /**
63
     * the popup menu
64
     */
65
        private JPopupMenu m_popup = null;
66
        
67
    /**
68
     *
69
     * @return the popup menu
70
     */
71
        public JPopupMenu getPopup() {
72
            return m_popup;
73
        }
74
75
    /**
76
     * {@inheritDoc}
77
     * @param event event
78
     * @return result of the condition
79
     */
80
        public boolean isTrue(AWTEvent event) {
81
            if (event.getID() != ContainerEvent.COMPONENT_ADDED) {
82
                return false;
83
            }
84
            ContainerEvent ce = (ContainerEvent)event;
85
            if (ce.getChild() instanceof JPopupMenu) {
86
                m_popup = (JPopupMenu)ce.getChild();
87
                return true;
88
            } else if (ce.getChild() instanceof Container) {
89
                Container popupContainer = (Container)ce.getChild();
90
                final int length = popupContainer.getComponents().length;
91
                for (int i = 0; i < length; i++) {
92
                    if (popupContainer.getComponents()[i]
93
                                                       instanceof JPopupMenu) {
94
        
95
                        m_popup = (JPopupMenu)popupContainer.getComponents()[i];
96
                        return true;
97
                    }
98
                }
99
            }
100
            return false;
101
        }
102
    }
103
    /**
104
     * 
105
     */
106
    private CapUtil() { }
107
    
108
    /**
109
     * 
110
     * @return the Robot
111
     */
112
    public static IRobot getRobot() {
113
        return AUTServer.getInstance().getRobot();
114
    }
115
116
117
    /**
118
     * Presses or releases the given modifier.
119
     * @param modifier the modifier.
120
     * @param press if true, the modifier will be pressed.
121
     * if false, the modifier will be released.
122
     */
123
    public static void pressOrReleaseModifiers(String modifier, boolean press) {
124
        final IRobot robot = getRobot();
125
        final StringTokenizer modTok = new StringTokenizer(
126
                KeyStrokeUtil.getModifierString(modifier), " "); //$NON-NLS-1$
127
        while (modTok.hasMoreTokens()) {
128
            final String mod = modTok.nextToken();
129
            final int keyCode = KeyCodeConverter.getKeyCode(mod);
130
            if (press) {
131
                robot.keyPress(null, keyCode);
132
            } else {
133
                robot.keyRelease(null, keyCode);
134
            }
135
        }
136
    }
137
     
138
    /**
139
     * @param renderer
140
     *            The component which is used as the renderer
141
     * @return The string that the renderer displays.
142
     * @throws StepExecutionException
143
     *             If the renderer component is not of type <code>JLabel</code>,
144
     *             <code>JToggleButton</code>, <code>AbstractButton</code>,
145
     *             <code>JTextComponent</code> or supports one of the fallback 
146
     *             methods
147
     */
148
    public static String getRenderedText(Component renderer)
149
        throws StepExecutionException {
150
        String renderedText = resolveRenderedText(renderer);
151
        if (renderedText != null) {
152
            return renderedText;
153
        }
154
        throw new StepExecutionException(
155
            "Renderer not supported: " + renderer.getClass(), //$NON-NLS-1$
156
            EventFactory.createActionError(
157
                    TestErrorEvent.RENDERER_NOT_SUPPORTED));
158
    }
159
    
160
    /**
161
     * @param renderer
162
     *            The component which is used as the renderer
163
     * @return The string that the renderer displays or <code>null</code> if it
164
     *         could not be resolved.
165
     */
166
    private static String resolveRenderedText(Component renderer) {
167
        if (renderer instanceof JLabel) {
168
            return ((JLabel)renderer).getText();
169
        } else if (renderer instanceof JToggleButton) {
170
            return ((JToggleButton)renderer).isSelected() ? Boolean.TRUE
171
                .toString() : Boolean.FALSE.toString();
172
        } else if (renderer instanceof AbstractButton) {
173
            return ((AbstractButton)renderer).getText();
174
        } else if (renderer instanceof JTextComponent) {
175
            return ((JTextComponent)renderer).getText();
176
        } 
177
        // Check if an adapter exists
178
        ITextRendererAdapter textRendererAdapter = 
179
            ((ITextRendererAdapter) AdapterFactoryRegistry
180
                .getInstance().getAdapter(
181
                        ITextRendererAdapter.class, renderer));
182
        if (textRendererAdapter != null) {
183
            return textRendererAdapter.getText();
184
        } else if (renderer != null) {
185
            String[] methodNames = new String[] {
186
                RENDERER_FALLBACK_TEXT_GETTER_METHOD_1,
187
                RENDERER_FALLBACK_TEXT_GETTER_METHOD_2 };
188
            for (int i = 0; i < methodNames.length; i++) {
189
                String text = getTextFromComponent(renderer, methodNames[i]);
190
                if (text != null) {
191
                    return text;
192
                }
193
            }
194
        }
195
        return null;
196
    }
197
    
198
    /**
199
     * @param obj
200
     *            the object to invoke the method for
201
     * @param getterName
202
     *            the name of the getter Method for string retrival
203
     * @return the return value of the given method name or <code>null</code> if
204
     *         something went wrong during method invocation
205
     */
206
    private static String getTextFromComponent(Object obj, String getterName) {
207
        String text = null;
208
        try {
209
            Method getter = null;
210
            Class objClass = obj.getClass();
211
            try {
212
                getter = objClass.getDeclaredMethod(getterName, null);
213
            } catch (NoSuchMethodException e) {
214
                // ignore
215
            } catch (SecurityException e) {
216
                // ignore
217
            }
218
            if (getter == null) {
219
                try {
220
                    getter = objClass.getMethod(getterName, null);
221
                } catch (NoSuchMethodException e) {
222
                    return text;
223
                } catch (SecurityException e) {
224
                    return text;
225
                }
226
            }
227
            getter.setAccessible(true);
228
            Object returnValue = getter.invoke(obj, null);
229
            if (returnValue instanceof String) {
230
                text = (String) returnValue;
231
            }
232
            return text;
233
        } catch (SecurityException e) {
234
            return text;
235
        } catch (IllegalArgumentException e) {
236
            return text;
237
        } catch (IllegalAccessException e) {
238
            return text;
239
        } catch (InvocationTargetException e) {
240
            return text;
241
        }
242
    }
243
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JMenuBarCAPs.java (+207 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.caps;
12
13
import java.awt.Component;
14
import java.awt.Container;
15
import java.awt.Window;
16
import java.awt.event.KeyEvent;
17
import java.util.ArrayList;
18
import java.util.Iterator;
19
import java.util.List;
20
21
import javax.swing.JDialog;
22
import javax.swing.JFrame;
23
import javax.swing.JMenu;
24
import javax.swing.JMenuBar;
25
import javax.swing.JPopupMenu;
26
import javax.swing.MenuElement;
27
28
import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
29
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
30
import org.eclipse.jubula.rc.common.implclasses.IBaseImplementationClass;
31
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
32
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
33
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
34
import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
35
import org.eclipse.jubula.rc.swing.swing.implclasses.WindowHelper;
36
import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuItemAdapter;
37
38
/**
39
 * Toolkit specific commands for the <code>JMenuBar</code>.
40
 * 
41
 * @author BREDEX GmbH
42
 */
43
public class JMenuBarCAPs extends AbstractMenuCAPs 
44
    implements IBaseImplementationClass {
45
    
46
    /** The robot factory.  */
47
    private IRobotFactory m_robotFactory;
48
    /**
49
     * {@inheritDoc}
50
     */
51
    protected IRobotFactory getRobotFactory() {
52
        if (m_robotFactory == null) {
53
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
54
        }
55
        return m_robotFactory;
56
    }
57
        
58
    /**
59
     * {@inheritDoc}
60
     */
61
    public String[] getTextArrayFromComponent() {
62
        
63
        return null;
64
    }
65
    
66
    /**
67
     * Workaround to get the menu bar existing somewhere in the given 
68
     * container's hierarchy. This method should <b>only</b> be used if 
69
     * {@link JFrame#getJMenuBar()} / {@link JDialog#getJMenuBar()} return 
70
     * <code>null</code>, which is a very rare case.
71
     * 
72
     * This method also performs some unorthodox visibility testing in order
73
     * to avoid retrieving the wrong menu.
74
     * 
75
     * @param rootPane The root container from which to start the search for
76
     *                 the menu bar.
77
     * @return the first menu bar found in the hierarchy that: <ul>
78
     *          <li>is showing</li>
79
     *          <li>contains at least one visible menu</li>
80
     */
81
    private JMenuBar getMenuBarWorkaround(Container rootPane) {
82
        JMenuBar menuBar = null;
83
        List menuList = new ArrayList();
84
        collectMenuBarsWorkaround(rootPane, menuList);
85
        Iterator menuIter = menuList.iterator();
86
        while (menuIter.hasNext() && menuBar == null) {
87
            JMenuBar menu = (JMenuBar)menuIter.next();
88
            boolean hasAtLeastOneItem = false;
89
            MenuElement [] subElements = menu.getSubElements();
90
            for (int i = 0; 
91
                    i < subElements.length && !hasAtLeastOneItem; 
92
                    i++) {
93
                if (subElements[i] instanceof JMenu) {
94
                    JMenu subMenu = (JMenu)subElements[i];
95
                    hasAtLeastOneItem = 
96
                        subMenu != null && subMenu.isShowing();
97
                }
98
            }
99
            if (hasAtLeastOneItem) {
100
                menuBar = menu;
101
            }
102
        }
103
        return menuBar;
104
    }
105
    
106
    /**
107
     * Adds all menu bars found in the hierarchy <code>container</code> to 
108
     * <code>menuBarList</code>. This is part of a workaround for finding menus
109
     * in AUTs that don't make proper use of 
110
     * {@link JFrame#setJMenuBar()} / {@link JDialog#setJMenuBar()}.
111
     * 
112
     * @see #getMenuBarWorkaround(Container)
113
     * 
114
     * @param container The root container from which to start the search for
115
     *                  the menu bars. 
116
     * @param menuBarList The list to which each menu bar found will be added.
117
     *                    Only objects of type {@link JMenuBar} will be added
118
     *                    to this list.
119
     */
120
    private void collectMenuBarsWorkaround(
121
            Container container, List menuBarList) {
122
        Component [] children = container.getComponents();
123
        for (int i = 0; i < children.length; i++) {
124
            if (children[i] instanceof JMenuBar
125
                    && children[i].isShowing()) {
126
                menuBarList.add(children[i]);
127
            }
128
        }
129
        
130
        for (int i = 0; i < children.length; i++) {
131
            if (children[i] instanceof Container
132
                    && children[i].isVisible()) {
133
                collectMenuBarsWorkaround((Container)children[i], menuBarList);
134
            }
135
        }
136
        
137
    }
138
    /**
139
     * @return the component
140
     */
141
    public IComponentAdapter getComponent() {
142
        if (super.getComponent().getRealComponent() instanceof JPopupMenu) {
143
            return super.getComponent();
144
        }
145
        Window activeWindow = WindowHelper.getActiveWindow();
146
        if (activeWindow == null) {
147
            getLog().warn("JMenuBarImplClass.getComponent(): No active window."); //$NON-NLS-1$
148
        } else {
149
            JMenuBar menuBar = null;
150
            Container rootPane = null;
151
            if (activeWindow instanceof JDialog) {
152
                JDialog dialog = (JDialog)activeWindow;
153
                menuBar = dialog.getJMenuBar();
154
                rootPane = dialog.getRootPane();
155
            } else if (activeWindow instanceof JFrame) {
156
                JFrame frame = (JFrame)activeWindow;
157
                menuBar = frame.getJMenuBar();
158
                rootPane = frame.getRootPane();
159
            }
160
161
            if (menuBar == null) {
162
                menuBar = getMenuBarWorkaround(rootPane);
163
            }
164
165
            setComponent(menuBar);
166
        }
167
        return super.getComponent();
168
    }
169
170
    /**
171
     *{@inheritDoc}
172
     */
173
    protected void closeMenu(IMenuAdapter menuBar, String[] textPath,
174
            String operator) {
175
        if (menuBar.getRealComponent() instanceof JPopupMenu) {
176
            for (int i = 0; i < textPath.length; i++) {
177
                getRobot().keyType(menuBar.getRealComponent(),
178
                        KeyEvent.VK_ESCAPE);
179
            }
180
            return;
181
        }
182
        super.closeMenu(menuBar, textPath, operator);
183
            
184
    }
185
    
186
    /**
187
     *{@inheritDoc}
188
     */
189
    protected void closeMenu(IMenuAdapter menuBar, int[] path) {
190
        if (menuBar.getRealComponent() instanceof JPopupMenu) {
191
            for (int i = 0; i < path.length; i++) {
192
                getRobot().keyType(menuBar.getRealComponent(),
193
                        KeyEvent.VK_ESCAPE);
194
            }
195
            return;
196
        }
197
        super.closeMenu(menuBar, path);
198
    }
199
    
200
    /**
201
     * {@inheritDoc}
202
     */
203
    protected IMenuItemAdapter newMenuItemAdapter(Object component) {
204
        return new JMenuItemAdapter(component);
205
    }
206
207
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JTableCAPs.java (+213 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.caps;
12
13
import java.awt.Component;
14
import java.awt.IllegalComponentStateException;
15
import java.awt.Point;
16
import java.awt.Rectangle;
17
18
import javax.swing.JTable;
19
import javax.swing.table.JTableHeader;
20
import javax.swing.table.TableColumn;
21
import javax.swing.table.TableColumnModel;
22
23
import org.eclipse.jubula.rc.common.caps.AbstractTableCAPs;
24
import org.eclipse.jubula.rc.common.driver.ClickOptions;
25
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
26
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
27
import org.eclipse.jubula.rc.common.driver.IRunnable;
28
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
29
import org.eclipse.jubula.rc.common.implclasses.table.Cell;
30
import org.eclipse.jubula.rc.common.logger.AutServerLogger;
31
import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
32
import org.eclipse.jubula.rc.swing.swing.driver.KeyCodeConverter;
33
import org.eclipse.jubula.rc.swing.utils.SwingUtils;
34
/**
35
 * Toolkit specific commands for the <code>JTable</code>
36
 * 
37
 * @author BREDEX GmbH
38
 */
39
public class JTableCAPs extends AbstractTableCAPs {
40
41
    /** the logger */
42
    private static AutServerLogger log = new AutServerLogger(
43
            JTableCAPs.class);
44
45
    /** the RobotFactory from the AUT */
46
    private IRobotFactory m_robotFactory;
47
    
48
    /**
49
     * @return the log
50
     */
51
    public static AutServerLogger getLog() {
52
        return log;
53
    }    
54
55
    /**
56
     * {@inheritDoc}
57
     */
58
    protected IRobotFactory getRobotFactory() {
59
        if (m_robotFactory == null) {
60
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
61
        }
62
        return m_robotFactory;
63
    }
64
    
65
    /**
66
     * 
67
     * @return the real AUT JTable
68
     */
69
    private JTable getTable() {
70
        return (JTable) getComponent().getRealComponent();
71
    }
72
    
73
    /**
74
     * @return The event thread queuer.
75
     */
76
    public IEventThreadQueuer getEventThreadQueuer() {
77
        return getRobotFactory().getEventThreadQueuer();
78
    }
79
    
80
81
    /**
82
     * {@inheritDoc}
83
     */
84
    public String[] getTextArrayFromComponent() {
85
        final String[] componentTextArray;
86
        TableColumnModel columnModel = getTable().getColumnModel();
87
        if (columnModel == null) {
88
            componentTextArray = null;
89
        } else {
90
            componentTextArray = new String[columnModel.getColumnCount()];
91
            for (int i = 0; i < componentTextArray.length; i++) {
92
                TableColumn tableColumn = columnModel.getColumn(i);
93
                if (tableColumn == null) {
94
                    componentTextArray[i] = null;
95
                } else {
96
                    Object headerValue = tableColumn.getHeaderValue();
97
                    if (headerValue == null) {
98
                        componentTextArray[i] = null;
99
                    } else {
100
                        componentTextArray[i] = headerValue.toString();
101
                    }
102
                }
103
            }
104
        }
105
        return componentTextArray;
106
    }
107
    /**
108
     * {@inheritDoc}
109
     */
110
    protected int getExtendSelectionModifier() {
111
        return SwingUtils.getSystemDefaultModifier();
112
    }
113
114
    /**
115
     * {@inheritDoc}
116
     */
117
    protected Cell getCellAtMousePosition() throws StepExecutionException {
118
        JTable table = getTable();
119
        Point mousePos = getRobot().getCurrentMousePosition();
120
        Point tablePos = table.getLocationOnScreen();
121
        Point relativePos = new Point(mousePos.x - tablePos.x,
122
            mousePos.y - tablePos.y);
123
        final int column = table.columnAtPoint(relativePos);
124
        final int row = table.rowAtPoint(relativePos);
125
        if (log.isDebugEnabled()) {
126
            log.debug("Selected row, col: " + row + ", " + column); //$NON-NLS-1$ //$NON-NLS-2$
127
        }
128
        checkRowColBounds(row, column);
129
        return new Cell(row, column);
130
    }
131
132
    /**
133
     * {@inheritDoc}
134
     */
135
    protected boolean isMouseOnHeader() {
136
        JTable table = getTable();
137
        if (table.getTableHeader() == null
138
                || !(table.getTableHeader().isShowing())) {
139
            return false;
140
        }
141
        
142
        JTableHeader header = table.getTableHeader();
143
        Point mousePos = getRobot().getCurrentMousePosition();        
144
        try {
145
            Point headerPos = header.getLocationOnScreen();
146
            Point relativePos = new Point(mousePos.x - headerPos.x,
147
                mousePos.y - headerPos.y);            
148
            return header.getBounds().contains(relativePos);
149
        } catch (IllegalComponentStateException icse) {
150
            return false;
151
        } 
152
    }
153
154
    /**
155
     * {@inheritDoc}
156
     */
157
    protected Object setEditorToReplaceMode(Object editor, boolean replace) {
158
        Object returnvalue = editor;
159
        if (replace) {
160
            getRobot().clickAtCurrentPosition(editor, 3, 1);
161
        } else {
162
            returnvalue = getComponent().getRealComponent();
163
        }
164
        return returnvalue;
165
    }
166
167
    /**
168
     * {@inheritDoc}
169
     */
170
    protected Object activateEditor(Cell cell, Rectangle rectangle) {
171
        Object table = getComponent().getRealComponent();
172
        getRobot().click(table, rectangle);
173
        Component editor = getTableCellEditor(cell);
174
        // sometimes the editor only appears after doubleclick!
175
        if (editor == null) {
176
            ClickOptions co = ClickOptions.create().setClickCount(2);
177
            getRobot().click(table, rectangle, co);
178
            editor = getTableCellEditor(cell);
179
        }
180
        return editor;
181
    }
182
    
183
    /**
184
     * Gets the TableCellEditor of the given cell
185
     * @param cell the cell.
186
     * @return the TableCellEditor
187
     */
188
    private Component getTableCellEditor(final Cell cell) {
189
        final JTable table = (JTable) getComponent().getRealComponent();
190
        return (Component) getEventThreadQueuer()
191
            .invokeAndWait("getCellEditor", //$NON-NLS-1$
192
                new IRunnable() {
193
                    public Object run() {
194
                        Object value = table.getValueAt(
195
                            cell.getRow(), cell.getCol());
196
                        boolean selected = table.isCellSelected(
197
                            cell.getRow(), cell.getCol());
198
                        return table.getCellEditor(cell.getRow(),
199
                            cell.getCol()).getTableCellEditorComponent(table,
200
                                value, selected, cell.getRow(), cell.getCol());
201
                    }
202
                });
203
    }
204
205
206
    /**
207
     * {@inheritDoc}
208
     */
209
    protected int getKeyCode(String key) {
210
        return KeyCodeConverter.getKeyCode(key);
211
    }
212
213
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/caps/JTreeCAPs.java (+194 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.caps;
12
13
import java.awt.Point;
14
import javax.swing.JTree;
15
import javax.swing.tree.TreePath;
16
17
import org.eclipse.jubula.rc.common.CompSystemConstants;
18
import org.eclipse.jubula.rc.common.caps.AbstractTreeCAPs;
19
import org.eclipse.jubula.rc.common.driver.DragAndDropHelper;
20
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
21
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
22
import org.eclipse.jubula.rc.common.driver.IRunnable;
23
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
24
import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
25
import org.eclipse.jubula.tools.objects.event.EventFactory;
26
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
27
import org.eclipse.jubula.tools.utils.TimeUtil;
28
/**
29
 * Toolkit specific commands for the <code>JTree</code>
30
 * 
31
 * @author BREDEX GmbH
32
 */
33
public class JTreeCAPs extends AbstractTreeCAPs {
34
35
    /** Robot Factory*/
36
    private IRobotFactory m_robotFactory;
37
38
    
39
    /**
40
     * Waits the given amount of time. Logs a drop-related error if interrupted.
41
     *
42
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
43
     *                        between moving the mouse to the drop point and
44
     *                        releasing the mouse button
45
     */
46
    static void waitBeforeDrop(int delayBeforeDrop) {
47
        TimeUtil.delay(delayBeforeDrop);
48
    }
49
    
50
    /**
51
     * {@inheritDoc}
52
     */
53
    public void gdDragByTextPath(int mouseButton,
54
            String modifier, String pathType, int preAscend,
55
            String treeTextPath, String operator) {
56
        final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
57
        dndHelper.setModifier(modifier);
58
        dndHelper.setMouseButton(mouseButton);
59
        gdSelect(pathType, preAscend, treeTextPath, operator, 0, 1, 
60
                CompSystemConstants.EXTEND_SELECTION_NO);
61
        pressOrReleaseModifiers(modifier, true);
62
        getRobot().mousePress(null, null, mouseButton);
63
64
    }
65
66
    /**
67
     * {@inheritDoc}
68
     */
69
    public void gdDropByTextPath(String pathType, int preAscend,
70
            String treeTextPath, String operator, int delayBeforeDrop) {
71
        try {
72
            gdSelect(pathType, preAscend, treeTextPath, operator, 0, 1,
73
                    CompSystemConstants.EXTEND_SELECTION_NO);
74
            waitBeforeDrop(delayBeforeDrop);
75
        } finally {
76
            final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
77
            getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
78
            pressOrReleaseModifiers(dndHelper.getModifier(), false);
79
        }
80
81
    }
82
83
    /**
84
     * {@inheritDoc}
85
     */
86
    public void gdDragByIndexPath(int mouseButton,
87
            String modifier, String pathType, int preAscend,
88
            String treeIndexPath) {
89
        final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
90
        dndHelper.setModifier(modifier);
91
        dndHelper.setMouseButton(mouseButton);
92
        gdSelectByIndices(pathType, preAscend, treeIndexPath, 0, 1,
93
                CompSystemConstants.EXTEND_SELECTION_NO);
94
        pressOrReleaseModifiers(modifier, true);
95
        getRobot().mousePress(null, null, mouseButton);
96
97
    }
98
99
    /**
100
     * {@inheritDoc}
101
     */
102
    public void gdDropByIndexPath(String pathType, int preAscend,
103
            String treeIndexPath, int delayBeforeDrop) {
104
        try {
105
            gdSelectByIndices(pathType, preAscend, treeIndexPath, 0, 1,
106
                    CompSystemConstants.EXTEND_SELECTION_NO);
107
            waitBeforeDrop(delayBeforeDrop);
108
        } finally {
109
            final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
110
            getRobot().mouseRelease(null, null, dndHelper.getMouseButton());
111
            pressOrReleaseModifiers(dndHelper.getModifier(), false);
112
        }
113
        
114
    }
115
    /**
116
     * {@inheritDoc}
117
     */
118
    public void gdVerifyTextAtMousePosition(String text, String operator) {
119
        checkNodeText(getNodeAtMousePosition(), text, operator);
120
    }
121
    /**
122
     * 
123
     * @return the tree node at the current mouse position.
124
     * @throws StepExecutionException If no tree node can be found at the 
125
     *                                current mouse position.
126
     */
127
    protected Object getNodeAtMousePosition() throws StepExecutionException {
128
        return getEventThreadQueuer().invokeAndWait("getNodeAtMousePosition", new IRunnable() { //$NON-NLS-1$
129
            
130
            public Object run() throws StepExecutionException {
131
                Point mousePosition = getRobot().getCurrentMousePosition();
132
                Point treeLocation = getTreeComponent().getLocationOnScreen();
133
                Point relativePos = new Point(
134
                        mousePosition.x - treeLocation.x,
135
                        mousePosition.y - treeLocation.y);
136
137
                int rowAtMousePosition = 
138
                    getTreeComponent().
139
                        getRowForLocation(relativePos.x, relativePos.y);
140
                
141
                if (rowAtMousePosition != -1) {
142
                    TreePath treePath = 
143
                        getTreeComponent().
144
                            getPathForLocation(relativePos.x, relativePos.y);
145
                    
146
                    if (treePath != null 
147
                            && treePath.getLastPathComponent() != null) {
148
                        return treePath.getLastPathComponent();
149
                    }
150
                    
151
                }
152
                
153
                throw new StepExecutionException("No tree node found at mouse position.", //$NON-NLS-1$
154
                    EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
155
            }
156
            
157
        });
158
159
    }
160
    /**
161
     * 
162
     * @return The JTree
163
     */
164
    private JTree getTreeComponent() {
165
        return (JTree) getComponent().getRealComponent();
166
    }
167
168
    /** 
169
     * {@inheritDoc}
170
     */
171
    protected IRobotFactory getRobotFactory() {
172
        if (m_robotFactory == null) {
173
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
174
        }
175
        return m_robotFactory;
176
    }
177
    
178
    /**
179
     * Presses or releases the given modifier.
180
     * @param modifier the modifier.
181
     * @param press if true, the modifier will be pressed.
182
     * if false, the modifier will be released.
183
     */
184
    protected void pressOrReleaseModifiers(String modifier, boolean press) {
185
        CapUtil.pressOrReleaseModifiers(modifier, press);
186
    }
187
    
188
    /**
189
     * @return The event thread queuer.
190
     */
191
    protected IEventThreadQueuer getEventThreadQueuer() {
192
        return getRobotFactory().getEventThreadQueuer();
193
    }
194
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/AbstractButtonAdapter.java (+103 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 javax.swing.AbstractButton;
14
15
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
16
import org.eclipse.jubula.rc.common.driver.IRunnable;
17
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IButtonAdapter;
18
/**
19
 * Implementation of the button interface as an adapter which holds
20
 * the <code>javax.swing.AbstractButton</code>.
21
 * 
22
 * @author BREDEX GmbH
23
 */
24
public class AbstractButtonAdapter extends WidgetAdapter
25
    implements IButtonAdapter {
26
27
    /**
28
     * Creates an object with the adapted JMenu.
29
     * @param objectToAdapt this must be an object of the Type 
30
     *      <code>AbstractButton</code>
31
     */
32
    public AbstractButtonAdapter(Object objectToAdapt) {
33
        super(objectToAdapt);
34
    }
35
    
36
    /**
37
     * 
38
     * @return the casted Object 
39
     */
40
    private AbstractButton getAbstractButton() {
41
        return (AbstractButton) getRealComponent();
42
    }
43
    /**
44
     * @return The event thread queuer.
45
     */
46
    public IEventThreadQueuer getEventThreadQueuer() {
47
        return getRobotFactory().getEventThreadQueuer();
48
    }
49
   
50
    /**
51
     * {@inheritDoc}
52
     */
53
    public String getText() {
54
        return (String) getEventThreadQueuer().invokeAndWait(
55
                "getText", new IRunnable() { //$NON-NLS-1$
56
                    public Object run() {
57
                        return getAbstractButton().getText();
58
                    }
59
                });
60
    }
61
62
    /**
63
     * {@inheritDoc}
64
     */
65
    public boolean isEnabled() {
66
        Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
67
                "isEnabled", new IRunnable() { //$NON-NLS-1$
68
                    public Object run() {
69
                        return getAbstractButton().getModel().isEnabled()
70
                                ? Boolean.TRUE : Boolean.FALSE;
71
                    }
72
                });
73
        return (boolean) returnvalue.booleanValue();
74
    }
75
76
    /**
77
     * {@inheritDoc}
78
     */
79
    public boolean isSelected() {
80
        Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
81
                "isSelected", new IRunnable() { //$NON-NLS-1$
82
                    public Object run() {
83
                        return getAbstractButton().getModel().isSelected()
84
                                ? Boolean.TRUE : Boolean.FALSE;
85
                    }
86
                });
87
        return (boolean) returnvalue.booleanValue();
88
    }
89
    
90
    /**
91
     * {@inheritDoc}
92
     */
93
    public String readValue(String variable) {
94
95
        return (String) getEventThreadQueuer().invokeAndWait(
96
                "isShowing", new IRunnable() { //$NON-NLS-1$
97
                    public Object run() {
98
                        return getAbstractButton().getText();
99
                    }
100
                });
101
    }
102
103
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuAdapter.java (+90 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.util.Iterator;
14
import java.util.LinkedList;
15
import java.util.List;
16
17
import javax.swing.JMenu;
18
import javax.swing.JMenuItem;
19
20
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
21
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
22
/**
23
 * Implementation of the menu interface for adapting the <code>JMenu</code>.
24
 * In Swing we have three implementations of the menu interface because
25
 * the Interface is used for the <code>JMenubar</code>, the <code>JPopupMenu</code> and the <code>JMenu</code>.
26
 * All these behave same in the implementation.
27
 * 
28
 * @author BREDEX GmbH
29
 *
30
 */
31
public class JMenuAdapter implements IMenuAdapter {
32
    /** The JMenu from the AUT */
33
    private JMenu m_menu;
34
    
35
    /**
36
     * Creates an object with the adapted JMenu.
37
     * @param toAdapt graphics component which will be adapted
38
     */
39
    public JMenuAdapter(Object toAdapt) { 
40
        m_menu = (JMenu) toAdapt;
41
    }
42
    
43
    /**
44
     * {@inheritDoc}
45
     */
46
    public Object getRealComponent() {
47
        return m_menu;
48
    }
49
    
50
    /**
51
     * {@inheritDoc}
52
     */
53
    public IMenuItemAdapter[] getItems() {
54
        List adapters = new LinkedList();
55
        
56
        for (int i = 0; i < m_menu.getItemCount(); i++) {
57
            JMenuItem getted = m_menu.getItem(i);
58
            if (getted instanceof JMenuItem) {
59
                adapters.add(new JMenuItemAdapter(getted));
60
            }
61
            
62
        }
63
        
64
65
        IMenuItemAdapter[] allitems = null;
66
        if (adapters.size() > 0) {
67
            allitems = new IMenuItemAdapter[adapters.size()];
68
            int i = 0;
69
            for (Iterator iterator = adapters.iterator(); iterator.hasNext();) {
70
                Object object = (Object) iterator.next();
71
                
72
                allitems[i] = (IMenuItemAdapter) object;
73
                i++;
74
            }
75
76
        }
77
        
78
        
79
        return allitems;
80
    }
81
    /**
82
     * {@inheritDoc}
83
     */
84
    public int getItemCount() {
85
        return m_menu.getItemCount();
86
    }
87
    
88
89
90
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuBarAdapter.java (+73 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.util.LinkedList;
14
import java.util.List;
15
16
import javax.swing.JMenuBar;
17
import javax.swing.JMenuItem;
18
19
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
20
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
21
22
/**
23
 * Implementation of the menu interface for adapting the <code>JMenuBar</code>.
24
 * In Swing we have three implementations of the menu interface because
25
 * the Interface is used for the <code>JMenubar</code>, the <code>JPopupMenu</code> and the <code>JMenu</code>.
26
 * All these behave same in the implementation.
27
 * 
28
 * @author BREDEX GmbH
29
 *
30
 */
31
public class JMenuBarAdapter implements IMenuAdapter {
32
    /** The JMenuBar */
33
    private JMenuBar m_menuBar;
34
    
35
    /**
36
     * @param objectToAdapt 
37
     */
38
    public JMenuBarAdapter(Object objectToAdapt) {
39
        m_menuBar = (JMenuBar) objectToAdapt;
40
    }
41
        
42
    /**
43
     * {@inheritDoc}
44
     */
45
    public Object getRealComponent() {
46
47
        return m_menuBar;
48
    }
49
    /**
50
     * {@inheritDoc}
51
     */
52
53
    public IMenuItemAdapter[] getItems() {
54
        Object[] menus = m_menuBar.getSubElements();
55
        List adapters = new LinkedList();
56
        for (int i = 0; i < menus.length; i++) {
57
            if (menus[i] instanceof JMenuItem) {
58
                adapters.add(new JMenuItemAdapter(menus[i]));
59
            }
60
        }
61
        IMenuItemAdapter[] allitems = new IMenuItemAdapter[adapters.size()];
62
        adapters.toArray(allitems);
63
        return allitems;
64
    }
65
66
    /**
67
     * {@inheritDoc}
68
     */
69
    public int getItemCount() {
70
        return m_menuBar.getMenuCount();
71
    }
72
73
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JMenuItemAdapter.java (+240 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 javax.swing.JMenu;
14
import javax.swing.JMenuItem;
15
16
import org.eclipse.jubula.rc.common.driver.ClickOptions;
17
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
18
import org.eclipse.jubula.rc.common.driver.IRobot;
19
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
20
import org.eclipse.jubula.rc.common.driver.IRunnable;
21
import org.eclipse.jubula.rc.common.driver.RobotTiming;
22
import org.eclipse.jubula.rc.common.exception.RobotException;
23
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
24
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
25
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
26
import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
27
import org.eclipse.jubula.tools.objects.event.EventFactory;
28
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
29
30
/**
31
 * Implementation of the MenuItem interface for adapting <code>JMenuItem</code>.
32
 * @author BREDEX GmbH
33
 * 
34
 */
35
public class JMenuItemAdapter 
36
    implements IMenuItemAdapter {
37
38
    /** the JMenuItem from the AUT    */
39
    private JMenuItem m_menuItem;
40
41
    /** the RobotFactory from the AUT */
42
    private IRobotFactory m_robotFactory;
43
  
44
    /**
45
     * 
46
     * @param objectToAdapt 
47
     */
48
    public JMenuItemAdapter(Object objectToAdapt) {
49
        m_menuItem = (JMenuItem) objectToAdapt;        
50
    }
51
    /**
52
     * Gets the Robot factory. The factory is created once per instance.
53
     *
54
     * @return The Robot factory.
55
     */
56
    protected IRobotFactory getRobotFactory() {
57
        if (m_robotFactory == null) {
58
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
59
        }
60
        return m_robotFactory;
61
    }
62
    /**
63
     * Gets the IEventThreadQueuer.
64
     *
65
     * @return The Robot
66
     * @throws RobotException
67
     *             If the Robot cannot be created.
68
     */
69
    protected IRobot getRobot() throws RobotException {
70
        return getRobotFactory().getRobot();
71
    }
72
    /**
73
     * @return The event thread queuer.
74
     */
75
    public IEventThreadQueuer getEventThreadQueuer() {
76
        return getRobotFactory().getEventThreadQueuer();
77
    }
78
    
79
80
    /**
81
     * {@inheritDoc}
82
     */
83
    public Object getRealComponent() {
84
85
        return m_menuItem;
86
    }
87
88
    /**
89
     * {@inheritDoc}
90
     */
91
    public void setComponent(Object element) {
92
        m_menuItem = (JMenuItem) element;
93
94
    }
95
96
    /**
97
     * {@inheritDoc}
98
     */
99
    public boolean isEnabled() {
100
        Boolean actual = (Boolean) getEventThreadQueuer().invokeAndWait(
101
                "isEnabled", new IRunnable() { //$NON-NLS-1$
102
                    public Object run() {
103
                        // see findBugs
104
                        return ((m_menuItem != null)
105
                                && (m_menuItem instanceof JMenuItem)
106
                                && m_menuItem.isEnabled()) 
107
                                ? Boolean.TRUE : Boolean.FALSE;
108
                    }
109
                });
110
111
        return actual.booleanValue();
112
    }
113
    /**
114
     * {@inheritDoc}
115
     */
116
    public String getText() {
117
        return (String) getEventThreadQueuer().invokeAndWait(
118
                "getText", new IRunnable() { //$NON-NLS-1$
119
                    public Object run() {
120
                        return m_menuItem.getText();
121
                    }
122
                });
123
    }
124
    /**
125
     * {@inheritDoc}
126
     */
127
    public boolean isShowing() {
128
        Boolean actual = (Boolean) getEventThreadQueuer().invokeAndWait(
129
                "isShowing", new IRunnable() { //$NON-NLS-1$
130
                    public Object run() {
131
                        // see findBugs
132
                        return ((m_menuItem != null)
133
                                && (m_menuItem instanceof JMenuItem)
134
                                && m_menuItem.isShowing()) 
135
                                ? Boolean.TRUE : Boolean.FALSE;
136
                    }
137
                });
138
139
        return actual.booleanValue();
140
    }
141
    
142
    /**
143
     * {@inheritDoc}
144
     */
145
    public boolean isExisting() {
146
        if (m_menuItem != null) {
147
            return true;
148
        }
149
        return false;
150
    }
151
    /**
152
     * {@inheritDoc}
153
     */
154
    public boolean isSelected() {
155
        Boolean actual = (Boolean) getEventThreadQueuer().invokeAndWait(
156
                "isSelected", new IRunnable() { //$NON-NLS-1$
157
                    public Object run() {
158
                        return ((m_menuItem != null)
159
                                && (m_menuItem instanceof JMenuItem)
160
                                && m_menuItem.isSelected()) 
161
                                ? Boolean.TRUE : Boolean.FALSE;
162
                    }
163
                });
164
165
        return actual.booleanValue();
166
    }
167
    
168
    /**
169
     * {@inheritDoc}
170
     */
171
    public IMenuAdapter getMenu() {
172
        if (m_menuItem instanceof JMenu) {
173
            return new JMenuAdapter(m_menuItem);
174
        }
175
        return null;
176
    }
177
    
178
    /**
179
     * {@inheritDoc}
180
     */
181
    public boolean hasSubMenu() {
182
        if (m_menuItem.getSubElements().length > 0) {
183
            return true;
184
        }
185
        return false;
186
    }
187
    /**
188
     * {@inheritDoc}
189
     */
190
    public boolean isSeparator() {
191
        if (m_menuItem == null) {
192
            return true;
193
        }
194
        return false;
195
    }
196
    
197
    /**
198
     * {@inheritDoc}
199
     */
200
    public void selectMenuItem() {
201
        clickMenuItem(getRobot(), m_menuItem);
202
        
203
    }
204
    
205
    /**
206
     * {@inheritDoc}
207
     */
208
    public IMenuAdapter openSubMenu() {
209
        if (!m_menuItem.isEnabled()) {
210
            throw new StepExecutionException("menu item not enabled", //$NON-NLS-1$
211
                    EventFactory.createActionError(
212
                            TestErrorEvent.MENU_ITEM_NOT_ENABLED));
213
        }
214
        if (!(m_menuItem instanceof JMenu)) {
215
            throw new StepExecutionException("unexpected item found", //$NON-NLS-1$
216
                    EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
217
        }
218
        JMenu menu = (JMenu) m_menuItem;        
219
        getRobot().click(m_menuItem, null, ClickOptions.create().setClickType(
220
            ClickOptions.ClickType.RELEASED));
221
        RobotTiming.sleepPostShowSubMenuItem(menu.getDelay());
222
        return getMenu();
223
    }
224
    
225
    /**
226
     * Clicks on a menu item
227
     * 
228
     * @param robot the robot
229
     * @param item  the menu item
230
     */
231
    private void clickMenuItem(IRobot robot, JMenuItem item) {
232
        if (!item.isEnabled()) {
233
            throw new StepExecutionException("menu item not enabled", //$NON-NLS-1$
234
                    EventFactory.createActionError(
235
                            TestErrorEvent.MENU_ITEM_NOT_ENABLED));
236
        }
237
        robot.click(item, null, ClickOptions.create().setClickType(
238
            ClickOptions.ClickType.RELEASED));
239
    }
240
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JPopupMenuAdapter.java (+67 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.util.LinkedList;
14
import java.util.List;
15
16
import javax.swing.JMenuItem;
17
import javax.swing.JPopupMenu;
18
19
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
20
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
21
/**
22
 * Implementation of the menu interface for adapting the <code>JPopupMenu</code>.
23
 * In Swing we have three implementations of the menu interface because
24
 * the Interface is used for the <code>JMenubar</code>, the <code>JPopupMenu</code> and the <code>JMenu</code>.
25
 * All these behave same in the implementation.
26
 * 
27
 * @author BREDEX GmbH
28
 *
29
 */
30
public class JPopupMenuAdapter implements IMenuAdapter {
31
    /** */
32
    private JPopupMenu m_contextMenu;
33
    
34
    /**
35
     * 
36
     * @param adaptee 
37
     */
38
    public JPopupMenuAdapter(Object adaptee) {
39
        m_contextMenu = (JPopupMenu) adaptee;
40
    }
41
    
42
    /** {@inheritDoc} */
43
    public Object getRealComponent() {
44
        return m_contextMenu;
45
    }
46
47
    /** {@inheritDoc} */
48
    public IMenuItemAdapter[] getItems() {
49
        Object[] menuItems = m_contextMenu.getSubElements();
50
        List adapters = new LinkedList();
51
        for (int i = 0; i < menuItems.length; i++) {
52
            if (menuItems[i] instanceof JMenuItem) {
53
                adapters.add(new JMenuItemAdapter(menuItems[i]));
54
            }
55
        }
56
        IMenuItemAdapter[] allitems = new IMenuItemAdapter[adapters.size()];
57
        adapters.toArray(allitems);
58
        return allitems;
59
    }
60
61
    /** {@inheritDoc} */
62
    public int getItemCount() {
63
        return m_contextMenu.getSubElements().length;
64
    }
65
66
    
67
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTableAdapter.java (+377 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.Rectangle;
15
16
import javax.swing.JTable;
17
import javax.swing.table.TableCellRenderer;
18
19
import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
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.IndexConverter;
23
import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
24
import org.eclipse.jubula.rc.common.implclasses.table.Cell;
25
import org.eclipse.jubula.rc.common.logger.AutServerLogger;
26
import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITableAdapter;
27
import org.eclipse.jubula.rc.swing.swing.caps.CapUtil;
28
import org.eclipse.jubula.tools.objects.event.EventFactory;
29
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
30
/**
31
 * Implements the table interface as an adapter for the <code>JTable</code>.
32
 *
33
 * @author BREDEX GmbH
34
 */
35
public class JTableAdapter extends WidgetAdapter implements ITableAdapter {
36
37
    /** the logger */
38
    private static AutServerLogger log = new AutServerLogger(
39
            AbstractMenuCAPs.class);
40
41
    /** The JTable from the AUT   */
42
    private JTable m_table;
43
    
44
    /**
45
     * Creates an object with the adapted JMenu.
46
     * @param objectToAdapt the object which needed to be adapted
47
     */
48
    public JTableAdapter(Object objectToAdapt) {
49
        super(objectToAdapt);
50
        m_table = (JTable) objectToAdapt;
51
    }
52
   
53
    /**
54
     * {@inheritDoc}
55
     */
56
    public void setComponent(Object element) {
57
        m_table = (JTable) element;
58
59
    }
60
61
    /**
62
     * {@inheritDoc}
63
     */
64
    public int getColumnCount() {
65
        Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
66
                "getColumnCount", new IRunnable() { //$NON-NLS-1$
67
                    public Object run() {
68
                        return new Integer(m_table.getColumnCount());
69
                    }
70
                });
71
        return returnvalue.intValue();
72
    }
73
74
    /**
75
     * {@inheritDoc}
76
     */
77
    public int getRowCount() {
78
        Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
79
                "getRowCount", new IRunnable() { //$NON-NLS-1$
80
                    public Object run() {
81
                        return new Integer(m_table.getRowCount());
82
                    }
83
                });
84
        return returnvalue.intValue();
85
    }
86
87
    /**
88
     * {@inheritDoc}
89
     */
90
    public String getCellText(final int row, final int column) {
91
        Object o = getEventThreadQueuer().invokeAndWait("getCellText", //$NON-NLS-1$
92
                new IRunnable() {
93
                    public Object run() {
94
                        Object value = m_table.getValueAt(row, column);
95
                        boolean selected = m_table.isCellSelected(row,
96
                                column);
97
                        if (log.isDebugEnabled()) {
98
                            log.debug("Getting cell text:"); //$NON-NLS-1$
99
                            log.debug("Row, col: " + row + ", " + column); //$NON-NLS-1$ //$NON-NLS-2$
100
                            log.debug("Value: " + value); //$NON-NLS-1$
101
                        }
102
                        TableCellRenderer renderer = m_table.getCellRenderer(
103
                                row, column);
104
                        Component c = renderer.getTableCellRendererComponent(
105
                                m_table, value, selected, true, row,
106
                                column);
107
108
                        return CapUtil.getRenderedText(c);
109
                    }
110
                });
111
112
        String current = String.valueOf(o);
113
        return current;
114
    }
115
    
116
    /**
117
     * {@inheritDoc}
118
     */
119
    public String getColumnName(final int column) {
120
        String returnvalue = (String)getEventThreadQueuer().invokeAndWait(
121
                "getColumnName", //$NON-NLS-1$
122
                new IRunnable() {
123
                    public Object run() {
124
                        return m_table.getColumnName(column);
125
                    }
126
                });
127
        return returnvalue;
128
    }
129
130
    /**
131
     * {@inheritDoc}
132
     */
133
    public int getColumnFromString(final String col, final String operator) {
134
        Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
135
                "getColumnFromString", new IRunnable() { //$NON-NLS-1$
136
                    public Object run() {
137
                        int column = -2;
138
                        try {
139
                            int usrIdxCol = Integer.parseInt(col);
140
                            if (usrIdxCol == 0) {
141
                                usrIdxCol = usrIdxCol + 1;
142
                            }
143
                            column = IndexConverter.toImplementationIndex(
144
                                    usrIdxCol);
145
                        } catch (NumberFormatException nfe) {
146
                            try {
147
                                if (m_table.getTableHeader() == null
148
                                        || !(m_table.getTableHeader()
149
                                                .isShowing())) {
150
                                    throw new StepExecutionException("No Header", //$NON-NLS-1$
151
                                            EventFactory.createActionError(
152
                                                TestErrorEvent.NO_HEADER));
153
                                }
154
                                for (int i = 0; i < m_table.getColumnCount();
155
                                        i++) {
156
                                    String header = m_table.getColumnName(i);
157
                                    if (MatchUtil.getInstance().match(
158
                                            header, col, operator)) {
159
                                        column = i;
160
                                    }
161
                                }
162
                            } catch (IllegalArgumentException iae) {
163
                                //do nothing here                
164
                            }
165
                        }
166
                        
167
                        return new Integer(column);
168
                    }
169
                });
170
        return returnvalue.intValue();
171
    }
172
173
    /**
174
     * {@inheritDoc}
175
     */
176
    public String getRowName(final int row) {
177
        // JTable does not act like lists
178
        return null;
179
    }
180
181
    /**
182
     * {@inheritDoc}
183
     */
184
    public int getRowFromString(final String row, final String operator) {
185
        Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
186
                "getRowFromString", new IRunnable() { //$NON-NLS-1$
187
                    public Object run() {
188
                        int rowInt = -2;        
189
                        try {
190
                            rowInt = IndexConverter.toImplementationIndex(
191
                                    Integer.parseInt(row));
192
                            if (rowInt == -1) {
193
                                if (m_table.getTableHeader() == null
194
                                        || !(m_table.getTableHeader()
195
                                                .isShowing())) {
196
                                    throw new StepExecutionException("No Header", //$NON-NLS-1$
197
                                            EventFactory.createActionError(
198
                                                TestErrorEvent.NO_HEADER));
199
                                }                
200
                            }
201
                        } catch (NumberFormatException nfe) {
202
                            for (int i = 0; i < m_table.getRowCount(); i++) {
203
                                String cellTxt = getCellText(i, 0);
204
                                if (MatchUtil.getInstance().match(cellTxt, row,
205
                                        operator)) {
206
                                    return new Integer(i);
207
                                }
208
                            }
209
                        }        
210
                        return new Integer(rowInt);
211
                    }
212
                });
213
        return returnvalue.intValue();
214
    }
215
216
    /**
217
     * {@inheritDoc}
218
     */
219
    public Rectangle getBounds() {
220
        Rectangle returnvalue = (Rectangle) getEventThreadQueuer()
221
                .invokeAndWait("getBounds", //$NON-NLS-1$
222
                    new IRunnable() {                     
223
                        public Object run() throws StepExecutionException {
224
                            return m_table.getBounds();
225
                        }
226
                    });
227
        
228
        return returnvalue;
229
    }
230
231
    /**
232
     * {@inheritDoc}
233
     */
234
    public Rectangle getHeaderBounds(int col) {
235
        Rectangle returnvalue = (Rectangle) getEventThreadQueuer()
236
                .invokeAndWait("getHeaderBounds", //$NON-NLS-1$
237
                    new IRunnable() {                     
238
                        public Object run() throws StepExecutionException {
239
                            return m_table.getTableHeader().getBounds();
240
                        }
241
                    });
242
        
243
        return returnvalue;
244
    }
245
246
    /**
247
     * {@inheritDoc}
248
     */
249
    public Cell getSelectedCell() throws StepExecutionException {
250
        
251
        Cell returnvalue = (Cell) getEventThreadQueuer().invokeAndWait(
252
                "getSelectedCell", new IRunnable() { //$NON-NLS-1$
253
                    public Object run() {
254
                
255
                        int row = m_table.getSelectedRow();
256
                        int col = m_table.getSelectedColumn();
257
                        if (log.isDebugEnabled()) {
258
                            log.debug("Selected row, col: " + row + ", " + col); //$NON-NLS-1$ //$NON-NLS-2$
259
                        }
260
                        try {
261
                            checkRowColBounds(row, col);
262
                        } catch (StepExecutionException e) {
263
                            if ((e.getEvent() != null)
264
                                    && (TestErrorEvent.INVALID_INDEX.equals(
265
                                            e.getEvent()
266
                                            .getProps().get(TestErrorEvent
267
                                                    .Property
268
                                                    .DESCRIPTION_KEY)))) {
269
                // set "invalid index" to "no selection" -> better description!
270
                                throw new StepExecutionException("No selection", //$NON-NLS-1$
271
                                        EventFactory.createActionError(
272
                                                TestErrorEvent.NO_SELECTION));
273
                            }
274
                            throw e;
275
                        }
276
                        return new Cell(row, col);
277
                    }
278
                });
279
        return returnvalue;
280
    }
281
282
    /**
283
     * {@inheritDoc}
284
     */
285
    public boolean isHeaderVisible() {
286
        Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
287
                "isHeaderVisible", new IRunnable() { //$NON-NLS-1$
288
                    public Object run() {
289
                        if (m_table.getTableHeader() != null) {
290
                            return m_table.getTableHeader().isVisible()
291
                                    ? Boolean.TRUE : Boolean.FALSE;
292
                        }
293
                        return Boolean.FALSE;
294
                    }
295
                });
296
        return (boolean) returnvalue.booleanValue();
297
    }
298
299
    /**
300
     * {@inheritDoc}
301
     */
302
    public boolean isCellEditable(int row, int col) {
303
        Boolean editable = (Boolean) getEventThreadQueuer().invokeAndWait(
304
                "isCellEditable", //$NON-NLS-1$
305
                new IRunnable() {
306
                    public Object run() {
307
                        Cell cell = getSelectedCell();
308
                        // see findBugs
309
                        return (m_table.isCellEditable(cell.getRow(),
310
                                cell.getCol())) ? Boolean.TRUE : Boolean.FALSE;
311
                    }
312
                });
313
        return editable.booleanValue();
314
    }
315
316
    /**
317
     * Checks wether <code>0 <= value < count</code>.
318
     *
319
     * @param value
320
     *            The value to check.
321
     * @param count
322
     *            The upper bound.
323
     */
324
    private void checkBounds(int value, int count) {
325
        if ((value < 0) || (value >= count)) {
326
            throw new StepExecutionException("Invalid row/column: " + value, //$NON-NLS-1$
327
                EventFactory.createActionError(
328
                        TestErrorEvent.INVALID_INDEX_OR_HEADER));
329
        }
330
    }
331
332
    /**
333
     * Checks if the passed row and column are inside the bounds of the JTable.
334
     *
335
     * @param row
336
     *            The row
337
     * @param column
338
     *            The column
339
     * @throws StepExecutionException
340
     *             If the row or the column is outside of the JTable's bounds.
341
     */
342
    private void checkRowColBounds(int row, int column)
343
        throws StepExecutionException {
344
        checkBounds(row, m_table.getRowCount());
345
        checkBounds(column, m_table.getColumnCount());
346
    }
347
    
348
    /**
349
     * {@inheritDoc}
350
     */
351
    public boolean hasCellSelection() {
352
        try {
353
            getSelectedCell();
354
        } catch (StepExecutionException e) {
355
            return false;
356
        }
357
        return true;
358
    }
359
    
360
    /**
361
     * {@inheritDoc}
362
     */
363
    public Rectangle scrollCellToVisible(final int row, final int col)
364
        throws StepExecutionException {
365
        Rectangle bounds = (Rectangle) getEventThreadQueuer().invokeAndWait(
366
                "getCellRect", //$NON-NLS-1$
367
                new IRunnable() {
368
                    public Object run() {
369
                        return m_table
370
                                .getCellRect(row, col, true);
371
                    }
372
                });
373
374
        getRobot().scrollToVisible(m_table, bounds);
375
        return bounds;
376
    }
377
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/JTreeAdapter.java (+65 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 javax.swing.JTree;
14
15
//import org.eclipse.jubula.rc.common.driver.IRunnable;
16
import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeOperationContext;
17
import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITreeAdapter;
18
import org.eclipse.jubula.rc.swing.swing.implclasses.TreeOperationContext;
19
/**
20
 * Implementation of the Tree interface as an adapter for <code>JTree</code>.
21
 * 
22
 * @author BREDEX GmbH
23
 *
24
 */
25
public class JTreeAdapter extends WidgetAdapter implements ITreeAdapter {
26
    
27
   
28
    /**
29
     * Creates an object with the adapted JMenu.
30
     * @param objectToAdapt 
31
     */
32
    public JTreeAdapter(Object objectToAdapt) {
33
        super(objectToAdapt);
34
    }
35
    
36
    /**
37
     * @return the casted Object 
38
     */
39
    private JTree getTable() {
40
        return (JTree) getRealComponent();
41
    }
42
        
43
    /**
44
     * {@inheritDoc}
45
     */
46
    public AbstractTreeOperationContext getContext() {
47
        TreeOperationContext context = new TreeOperationContext(
48
                getEventThreadQueuer(), getRobot(), getTable());
49
        return context;
50
    }
51
    /**
52
     * {@inheritDoc}
53
     */
54
    public Object getRootNode() {
55
        
56
        return getTable().getModel().getRoot();
57
    }
58
    /**
59
     * {@inheritDoc}
60
     */
61
    public boolean isRootVisible() {
62
        return getTable().isRootVisible();
63
    }
64
    
65
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/WidgetAdapter.java (+334 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
14
import java.awt.AWTEvent;
15
import java.awt.Toolkit;
16
17
import javax.swing.JComponent;
18
19
import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
20
import org.eclipse.jubula.rc.common.driver.ClickOptions;
21
import org.eclipse.jubula.rc.common.driver.DragAndDropHelper;
22
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
23
import org.eclipse.jubula.rc.common.driver.IRobot;
24
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
25
import org.eclipse.jubula.rc.common.driver.IRunnable;
26
import org.eclipse.jubula.rc.common.driver.RobotTiming;
27
import org.eclipse.jubula.rc.common.exception.RobotException;
28
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
29
import org.eclipse.jubula.rc.common.listener.EventLock;
30
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IWidgetAdapter;
31
import org.eclipse.jubula.rc.swing.driver.RobotFactoryConfig;
32
import org.eclipse.jubula.rc.swing.swing.caps.CapUtil;
33
import org.eclipse.jubula.rc.swing.swing.caps.JMenuBarCAPs;
34
import org.eclipse.jubula.rc.swing.swing.caps.CapUtil.PopupShownCondition;
35
import org.eclipse.jubula.rc.swing.swing.implclasses.EventListener;
36
import org.eclipse.jubula.tools.constants.TimeoutConstants;
37
import org.eclipse.jubula.tools.i18n.I18n;
38
import org.eclipse.jubula.tools.objects.event.EventFactory;
39
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
40
import org.eclipse.jubula.tools.utils.TimeUtil;
41
/**
42
 * Implements the interface for widgets and supports basic methods
43
 * which are needed for nearly all Swing ui components.
44
 * This is a basic adaption for <code>JComponent</code>.
45
 * 
46
 * @author BREDEX GmbH 
47
 */
48
public abstract class WidgetAdapter implements IWidgetAdapter {
49
      
50
    /** constants for communication */
51
    protected static final String POS_UNIT_PIXEL = "Pixel"; //$NON-NLS-1$
52
    /** constants for communication */
53
    protected static final String POS_UNI_PERCENT = "Percent"; //$NON-NLS-1$
54
    
55
    /** the RobotFactory from the AUT */
56
    private IRobotFactory m_robotFactory;
57
    
58
59
     
60
    /** */
61
    private JComponent m_component;
62
63
    /**
64
     * Used to store the component into the adapter.
65
     * @param objectToAdapt 
66
     */
67
    protected WidgetAdapter(Object objectToAdapt) {
68
        m_component = (JComponent) objectToAdapt;
69
    }
70
    
71
    /**
72
     * {@inheritDoc}
73
     */
74
    public Object getRealComponent() {
75
        return m_component;
76
    }
77
    
78
    /**
79
     * Gets the Robot factory. The factory is created once per instance.
80
     *
81
     * @return The Robot factory.
82
     */
83
    protected IRobotFactory getRobotFactory() {
84
        if (m_robotFactory == null) {
85
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
86
        }
87
        return m_robotFactory;
88
    }
89
    /**
90
     * Gets the IEventThreadQueuer.
91
     *
92
     * @return The Robot
93
     * @throws RobotException
94
     *             If the Robot cannot be created.
95
     */
96
    protected IRobot getRobot() throws RobotException {
97
        return getRobotFactory().getRobot();
98
    }
99
    /**
100
     * @return The event thread queuer.
101
     */
102
    public IEventThreadQueuer getEventThreadQueuer() {
103
        return getRobotFactory().getEventThreadQueuer();
104
    }
105
    
106
    /**
107
     * {@inheritDoc}
108
     */
109
    public String getPropteryValue(final String propertyname) {
110
        Object prop = getEventThreadQueuer().invokeAndWait("getProperty",  //$NON-NLS-1$
111
                new IRunnable() {
112
                    public Object run() throws StepExecutionException {
113
                        try {
114
                            return getRobot().getPropertyValue(
115
                                    getRealComponent(), propertyname);
116
                        } catch (RobotException e) {
117
                            throw new StepExecutionException(
118
                                e.getMessage(), 
119
                                EventFactory.createActionError(
120
                                    TestErrorEvent.PROPERTY_NOT_ACCESSABLE));
121
                        }
122
                    }
123
                });
124
        return String.valueOf(prop);
125
    }
126
127
    /**
128
     * {@inheritDoc}
129
     */
130
    public boolean isShowing() {
131
        Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
132
                "isShowing", new IRunnable() { //$NON-NLS-1$
133
                    public Object run() {
134
                        return m_component.isShowing()
135
                                ? Boolean.TRUE : Boolean.FALSE;
136
                    }
137
                });
138
        return (boolean) returnvalue.booleanValue();
139
    }
140
141
    /**
142
     * {@inheritDoc}
143
     */
144
    public boolean hasFocus() {
145
        Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
146
                "hasFocus", new IRunnable() { //$NON-NLS-1$
147
                    public Object run() {
148
                        return m_component.hasFocus()
149
                                ? Boolean.TRUE : Boolean.FALSE;
150
                    }
151
                });
152
        return (boolean) returnvalue.booleanValue();
153
    }
154
    
155
    /**
156
     * {@inheritDoc}
157
     */
158
    public boolean isEnabled() {
159
        Boolean returnvalue = (Boolean) getEventThreadQueuer().invokeAndWait(
160
                "isEnabled", new IRunnable() { //$NON-NLS-1$
161
                    public Object run() {
162
                        return m_component.isEnabled()
163
                                ? Boolean.TRUE : Boolean.FALSE;
164
                    }
165
                });
166
        return (boolean) returnvalue.booleanValue();
167
    }
168
    
169
    /**
170
     * {@inheritDoc}
171
     */
172
    public AbstractMenuCAPs showPopup(final int button) {
173
        final Object component = m_component;
174
        Runnable showPopup = new Runnable() {
175
            public void run() {
176
                RobotTiming.sleepPreShowPopupDelay();
177
                ClassLoader oldCl = Thread.currentThread()
178
                    .getContextClassLoader();
179
                Thread.currentThread().setContextClassLoader(component
180
                        .getClass().getClassLoader());
181
                if ((getRobot()).isMouseInComponent(component)) {
182
                    getRobot().clickAtCurrentPosition(
183
                            component, 1, button);
184
                } else {
185
                    getRobot().click(component, null, 
186
                        ClickOptions.create()
187
                            .setClickCount(1)
188
                            .setMouseButton(button));
189
                }
190
                Thread.currentThread().setContextClassLoader(oldCl);
191
            }
192
        };
193
194
        return showPopup(showPopup);
195
    }
196
    
197
    /**
198
     * {@inheritDoc}
199
     */
200
    public AbstractMenuCAPs showPopup(
201
            final int xPos, final String xUnits, 
202
            final int yPos, final String yUnits, final int button)
203
        throws StepExecutionException {
204
        final Object component = m_component;
205
        Runnable showPopup = new Runnable() {
206
            public void run() {
207
                RobotTiming.sleepPreShowPopupDelay();
208
                boolean isAbsoluteCoordinatesX = 
209
                    xUnits.equalsIgnoreCase(POS_UNIT_PIXEL); 
210
                boolean isAbsoluteCoordinatesY = 
211
                    yUnits.equalsIgnoreCase(POS_UNIT_PIXEL); 
212
                getRobot().click(component, null, 
213
                    ClickOptions.create().setMouseButton(button),
214
                    xPos, isAbsoluteCoordinatesX, 
215
                    yPos, isAbsoluteCoordinatesY);
216
            }
217
        };
218
        return showPopup(showPopup);
219
    }
220
    
221
    /**
222
     * Shows a popup menu using the given runnable and waits for the popup
223
     * menu to appear.
224
     *
225
     * @param showPopupOperation The implementation to use for opening the
226
     *                           popup menu.
227
     * @return the popup menu.
228
     */
229
    public AbstractMenuCAPs showPopup(Runnable showPopupOperation) {
230
        PopupShownCondition cond = new PopupShownCondition();
231
        EventLock lock = new EventLock();
232
        EventListener listener = new EventListener(lock, cond);
233
        Toolkit.getDefaultToolkit().addAWTEventListener(listener,
234
                AWTEvent.CONTAINER_EVENT_MASK);
235
236
        // showPopupOperation must run in the current thread in order to
237
        // avoid a race condition.
238
        showPopupOperation.run();
239
240
        synchronized (lock) {
241
            try {
242
                long timeout = TimeoutConstants.SERVER_TIMEOUT_WAIT_FOR_POPUP;
243
                long done = System.currentTimeMillis() + timeout;
244
                long now;
245
                while ((!lock.isReleased() || (cond.getPopup() == null)
246
                        || !cond.getPopup().isShowing())
247
                        && (timeout > 0)) {
248
                    lock.wait(timeout);
249
                    now = System.currentTimeMillis();
250
                    timeout = done - now;
251
                }
252
            } catch (InterruptedException e) {
253
                // ignore
254
            } finally {
255
                Toolkit.getDefaultToolkit().removeAWTEventListener(listener);
256
            }
257
        }
258
        if (!lock.isReleased() || (cond.getPopup() == null)
259
                || !cond.getPopup().isShowing()) {
260
            throw new StepExecutionException("popup not shown", //$NON-NLS-1$
261
                    EventFactory.createActionError(
262
                            TestErrorEvent.POPUP_NOT_FOUND));
263
        }
264
        AbstractMenuCAPs menuCAPs = new JMenuBarCAPs();
265
        menuCAPs.setComponent(cond.getPopup());
266
        return menuCAPs;
267
    }
268
    
269
    /**
270
     * {@inheritDoc}
271
     */
272
    public void showToolTip(final String text, final int textSize,
273
            final int timePerWord, final int windowWidth) {
274
        throw new StepExecutionException(
275
                I18n.getString(TestErrorEvent.UNSUPPORTED_OPERATION_ERROR),
276
                EventFactory.createActionError(
277
                    TestErrorEvent.UNSUPPORTED_OPERATION_ERROR));
278
    }
279
    
280
    /**
281
     * {@inheritDoc}
282
     */
283
    public void gdDrag(int mouseButton, String modifier, int xPos,
284
            String xUnits, int yPos, String yUnits) {
285
        final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
286
        dndHelper.setMouseButton(mouseButton);
287
        dndHelper.setModifier(modifier);
288
        final IRobot robot = getRobot();
289
        clickDirect(0, mouseButton, xPos, xUnits, yPos, yUnits);
290
        CapUtil.pressOrReleaseModifiers(modifier, true);
291
        robot.mousePress(null, null, mouseButton);
292
    }
293
294
295
    /**
296
     * {@inheritDoc}
297
     */
298
    public void gdDrop(int xPos, String xUnits, int yPos, String yUnits,
299
            int delayBeforeDrop) {
300
301
        final DragAndDropHelper dndHelper = DragAndDropHelper.getInstance();
302
        final String modifier = dndHelper.getModifier();
303
        final int mouseButton = dndHelper.getMouseButton();
304
        try {
305
            clickDirect(0, mouseButton, xPos, xUnits, yPos, yUnits);
306
            TimeUtil.delay(delayBeforeDrop);
307
        } finally {
308
            getRobot().mouseRelease(null, null, mouseButton);
309
            CapUtil.pressOrReleaseModifiers(modifier, false);
310
        }
311
    }
312
    
313
        /**
314
         * clicks into the component.
315
         *
316
         * @param count amount of clicks
317
         * @param button what mouse button should be used
318
         * @param xPos what x position
319
         * @param xUnits should x position be pixel or percent values
320
         * @param yPos what y position
321
         * @param yUnits should y position be pixel or percent values
322
         * @throws StepExecutionException error
323
         */
324
    private void clickDirect(int count, int button, int xPos, String xUnits,
325
            int yPos, String yUnits) throws StepExecutionException {
326
327
        getRobot().click(m_component, null,
328
                ClickOptions.create()
329
                    .setClickCount(count)
330
                    .setMouseButton(button),
331
                xPos, xUnits.equalsIgnoreCase(POS_UNIT_PIXEL),
332
                yPos, yUnits.equalsIgnoreCase(POS_UNIT_PIXEL));
333
    }
334
}
(-)a/org.eclipse.jubula.rc.swing/src/org/eclipse/jubula/rc/swing/swing/uiadapter/factory/SwingAdapterFactory.java (+92 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.factory;
12
13
14
import javax.swing.JButton;
15
import javax.swing.JCheckBox;
16
import javax.swing.JMenuBar;
17
import javax.swing.JMenuItem;
18
import javax.swing.JPopupMenu;
19
import javax.swing.JRadioButton;
20
import javax.swing.JTable;
21
import javax.swing.JTree;
22
23
import org.eclipse.jubula.rc.common.uiadapter.factory.IUIAdapterFactory;
24
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
25
import org.eclipse.jubula.rc.swing.swing.uiadapter.AbstractButtonAdapter;
26
import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuBarAdapter;
27
import org.eclipse.jubula.rc.swing.swing.uiadapter.JMenuItemAdapter;
28
import org.eclipse.jubula.rc.swing.swing.uiadapter.JPopupMenuAdapter;
29
import org.eclipse.jubula.rc.swing.swing.uiadapter.JTableAdapter;
30
import org.eclipse.jubula.rc.swing.swing.uiadapter.JTreeAdapter;
31
/**
32
 * This is the adapter factory for all swing components. It is
33
 * creating the specific adapter for a swing component.
34
 * 
35
 * Since we are using adapter here, it is a adapter factory. But this must not
36
 * be the case. It is only relevant that the object is implementing the
37
 * specific interface.
38
 * @author BREDEX GmbH
39
 *
40
 */
41
public class SwingAdapterFactory implements IUIAdapterFactory {
42
    /**
43
     * 
44
     */
45
    private static final Class[] SUPPORTEDCLASSES = new Class[] { 
46
        JButton.class, JCheckBox.class, JRadioButton.class,
47
        JMenuBar.class, JMenuItem.class, JTree.class , 
48
        JCheckBox.class, JRadioButton.class, JTable.class, JPopupMenu.class};
49
    
50
    /**
51
     * {@inheritDoc}
52
     */
53
    public Class[] getSupportedClasses() {
54
55
        return SUPPORTEDCLASSES;
56
    }
57
    /**
58
     * {@inheritDoc}
59
     */
60
    public IComponentAdapter getAdapter(Object objectToAdapt) {
61
        IComponentAdapter returnvalue = null;
62
        if (objectToAdapt instanceof JButton) {
63
            returnvalue = new AbstractButtonAdapter(objectToAdapt);
64
            
65
        } else if (objectToAdapt instanceof JRadioButton) {
66
            returnvalue = new AbstractButtonAdapter(objectToAdapt);
67
            
68
        } else if (objectToAdapt instanceof JCheckBox) {
69
            returnvalue = new AbstractButtonAdapter(objectToAdapt);
70
            
71
        } else if (objectToAdapt instanceof JMenuBar) {
72
        
73
            returnvalue = new JMenuBarAdapter(objectToAdapt); 
74
            
75
        } else if (objectToAdapt instanceof JMenuItem) {
76
            returnvalue = new JMenuItemAdapter(objectToAdapt);            
77
            
78
        } else if (objectToAdapt instanceof JTree) {
79
            returnvalue = new JTreeAdapter(objectToAdapt);
80
            
81
        } else if (objectToAdapt instanceof JTable) {
82
            returnvalue = new JTableAdapter(objectToAdapt);
83
            
84
        } else if (objectToAdapt instanceof JPopupMenu) {
85
            returnvalue = new JPopupMenuAdapter(objectToAdapt);
86
        
87
        }
88
        
89
        return returnvalue;
90
    }
91
92
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/SwtAUTServer.java (-1 / +9 lines)
Lines 15-20 import java.lang.reflect.InvocationTargetException; Link Here
15
import org.eclipse.jubula.rc.common.AUTServer;
15
import org.eclipse.jubula.rc.common.AUTServer;
16
import org.eclipse.jubula.rc.common.driver.IRobot;
16
import org.eclipse.jubula.rc.common.driver.IRobot;
17
import org.eclipse.jubula.rc.common.listener.BaseAUTListener;
17
import org.eclipse.jubula.rc.common.listener.BaseAUTListener;
18
import org.eclipse.jubula.rc.common.uiadapter.factory.GUIAdapterFactoryRegistry;
18
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
19
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
19
import org.eclipse.jubula.rc.swt.driver.RobotFactorySwtImpl;
20
import org.eclipse.jubula.rc.swt.driver.RobotFactorySwtImpl;
20
import org.eclipse.jubula.rc.swt.driver.RobotSwtImpl;
21
import org.eclipse.jubula.rc.swt.driver.RobotSwtImpl;
Lines 25-30 import org.eclipse.jubula.rc.swt.listener.FocusTracker; Link Here
25
import org.eclipse.jubula.rc.swt.listener.MappingListener;
26
import org.eclipse.jubula.rc.swt.listener.MappingListener;
26
import org.eclipse.jubula.rc.swt.listener.RecordListener;
27
import org.eclipse.jubula.rc.swt.listener.RecordListener;
27
import org.eclipse.jubula.rc.swt.listener.TableSelectionTracker;
28
import org.eclipse.jubula.rc.swt.listener.TableSelectionTracker;
29
import org.eclipse.jubula.rc.swt.uiadapter.factory.SWTAdapterFactory;
28
import org.eclipse.jubula.tools.constants.AUTServerExitConstants;
30
import org.eclipse.jubula.tools.constants.AUTServerExitConstants;
29
import org.eclipse.jubula.tools.constants.DebugConstants;
31
import org.eclipse.jubula.tools.constants.DebugConstants;
30
import org.eclipse.swt.widgets.Display;
32
import org.eclipse.swt.widgets.Display;
Lines 215-225 public class SwtAUTServer extends AUTServer { Link Here
215
     */
217
     */
216
    protected void startTasks() throws ExceptionInInitializerError, 
218
    protected void startTasks() throws ExceptionInInitializerError, 
217
        InvocationTargetException, NoSuchMethodException {
219
        InvocationTargetException, NoSuchMethodException {
218
220
        
221
        // FIXME Better place to put the registration of the factory
222
        GUIAdapterFactoryRegistry.getInstance().
223
            registerFactory(new SWTAdapterFactory());
224
        System.out.println("AdapterFactory registered"); //$NON-NLS-1$
225
        
219
        super.invokeAUT();
226
        super.invokeAUT();
220
        if (getCommunicator() != null) {
227
        if (getCommunicator() != null) {
221
            getCommunicator().close();
228
            getCommunicator().close();
222
        }
229
        }
230
        
223
    }
231
    }
224
232
225
    /**
233
    /**
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/ButtonCAPs.java (+52 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.caps;
12
13
14
import org.eclipse.jubula.rc.common.caps.AbstractButtonCAPs;
15
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
16
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IButtonAdapter;
17
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
18
import org.eclipse.jubula.rc.swt.utils.SwtUtils;
19
20
21
/**
22
 * The Toolkit specific implementation for <code>SWTButton</code> and subclasses.
23
 *
24
 * @author BREDEX GmbH
25
 */
26
public class ButtonCAPs extends AbstractButtonCAPs {
27
    
28
    /** The robot factory. */
29
    private IRobotFactory m_robotFactory;
30
    
31
    /**
32
     * {@inheritDoc}
33
     */
34
    public String[] getTextArrayFromComponent() {
35
        return new String[] {
36
                SwtUtils.removeMnemonics(
37
                        ((IButtonAdapter)getComponent()).getText())};
38
    }
39
    
40
    /**
41
     * Gets the Robot factory. The factory is created once per instance.
42
     * @return The Robot factory.
43
     */
44
    protected IRobotFactory getRobotFactory() {
45
        if (m_robotFactory == null) {
46
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
47
        }
48
        return m_robotFactory;
49
    }
50
51
52
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/CAPUtil.java (+108 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.caps;
12
13
import java.awt.Point;
14
import java.util.StringTokenizer;
15
16
import org.eclipse.jubula.rc.common.AUTServer;
17
import org.eclipse.jubula.rc.common.driver.IRobot;
18
import org.eclipse.jubula.rc.common.exception.RobotException;
19
import org.eclipse.jubula.rc.common.util.KeyStrokeUtil;
20
import org.eclipse.jubula.rc.swt.driver.KeyCodeConverter;
21
import org.eclipse.jubula.rc.swt.driver.SwtRobot;
22
import org.eclipse.jubula.tools.utils.EnvironmentUtils;
23
import org.eclipse.jubula.tools.utils.TimeUtil;
24
import org.eclipse.swt.widgets.Display;
25
/**
26
 * Util class for some swt specific commands.
27
 * 
28
 * @author BREDEX GmbH
29
 */
30
public class CAPUtil {
31
32
       
33
    /**
34
     * 
35
     */
36
    private CAPUtil() { }
37
    
38
    
39
    /**
40
     * Gets the Robot. 
41
     * @return The Robot
42
     * @throws RobotException If the Robot cannot be created.
43
     */
44
    public static IRobot getRobot() throws RobotException {
45
        return AUTServer.getInstance().getRobot();
46
    }
47
    
48
    /**
49
     * Waits the given amount of time. Logs a drop-related error if interrupted.
50
     * 
51
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
52
     *                        between moving the mouse to the drop point and
53
     *                        releasing the mouse button                       
54
     */
55
    public static void waitBeforeDrop(int delayBeforeDrop) {
56
        TimeUtil.delay(delayBeforeDrop);
57
    }
58
    
59
    /**
60
     * Move the mouse pointer from its current position to a few points in
61
     * its proximity. This is used to initiate a drag operation.
62
     * 
63
     */
64
    public static void shakeMouse() {
65
        /** number of pixels by which a "mouse shake" offsets the mouse cursor */
66
        final int mouseShakeOffset = 10;
67
        
68
        Point origin = getRobot().getCurrentMousePosition();
69
        SwtRobot lowLevelRobot = new SwtRobot(Display.getDefault());
70
        lowLevelRobot.mouseMove(
71
                origin.x + mouseShakeOffset, 
72
                origin.y + mouseShakeOffset);
73
        lowLevelRobot.mouseMove(
74
                origin.x - mouseShakeOffset, 
75
                origin.y - mouseShakeOffset);
76
        lowLevelRobot.mouseMove(origin.x, origin.y);
77
        if (!EnvironmentUtils.isWindowsOS() 
78
                && !EnvironmentUtils.isMacOS()) {
79
            boolean moreEvents = true;
80
            while (moreEvents) {
81
                moreEvents = Display.getDefault().readAndDispatch();
82
            }
83
        }
84
    }
85
    
86
    /**
87
     * Presses or releases the given modifier.
88
     * @param modifier the modifier.
89
     * @param press if true, the modifier will be pressed.
90
     * if false, the modifier will be released.
91
     */
92
    public static void pressOrReleaseModifiers(String modifier, boolean press) {
93
        final IRobot robot = getRobot();
94
        final StringTokenizer modTok = new StringTokenizer(
95
                KeyStrokeUtil.getModifierString(modifier), " "); //$NON-NLS-1$
96
        while (modTok.hasMoreTokens()) {
97
            final String mod = modTok.nextToken();
98
            final int keyCode = KeyCodeConverter.getKeyCode(mod);
99
            if (press) {
100
                robot.keyPress(null, keyCode);
101
            } else {
102
                robot.keyRelease(null, keyCode);
103
            }
104
        }
105
    }
106
    
107
108
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/MenuCAPs.java (+328 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.caps;
12
13
import org.apache.commons.lang.Validate;
14
import org.eclipse.jubula.rc.common.caps.AbstractMenuCAPs;
15
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
16
import org.eclipse.jubula.rc.common.driver.IRobot;
17
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
18
import org.eclipse.jubula.rc.common.driver.IRunnable;
19
import org.eclipse.jubula.rc.common.exception.RobotException;
20
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
21
import org.eclipse.jubula.rc.common.implclasses.IBaseImplementationClass;
22
import org.eclipse.jubula.rc.common.implclasses.MenuUtilBase;
23
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
24
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
25
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
26
import org.eclipse.jubula.rc.swt.driver.EventThreadQueuerSwtImpl;
27
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
28
import org.eclipse.jubula.rc.swt.driver.RobotSwtImpl;
29
import org.eclipse.jubula.rc.swt.uiadapter.MenuItemAdapter;
30
import org.eclipse.jubula.tools.i18n.I18n;
31
import org.eclipse.jubula.tools.objects.event.EventFactory;
32
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
33
import org.eclipse.swt.SWT;
34
import org.eclipse.swt.events.MenuEvent;
35
import org.eclipse.swt.events.MenuListener;
36
import org.eclipse.swt.graphics.Rectangle;
37
import org.eclipse.swt.widgets.Menu;
38
import org.eclipse.swt.widgets.Shell;
39
/**
40
 * Toolkit specific commands for the <code>Menu</code>
41
 * 
42
 * @author BREDEX GmbH
43
 */
44
public class MenuCAPs extends AbstractMenuCAPs 
45
    implements IBaseImplementationClass {
46
    /** the RobotFactory from the AUT */
47
    private IRobotFactory m_robotFactory;
48
    
49
    /** Test variable for contextMenus*/
50
    private boolean m_isCM = false;
51
    /**
52
     * Gets the IEventThreadQueuer.
53
     * 
54
     * @return The Robot
55
     * @throws RobotException
56
     *             If the Robot cannot be created.
57
     */
58
    protected IRobot getRobot() throws RobotException {
59
        return getRobotFactory().getRobot();
60
    }
61
62
    /**
63
     * @return The event thread queuer.
64
     */
65
    public IEventThreadQueuer getEventThreadQueuer() {
66
        return getRobotFactory().getEventThreadQueuer();
67
    }
68
    
69
    /**
70
     * {@inheritDoc}
71
     */
72
    public IComponentAdapter getComponent() {
73
        if (m_isCM) {
74
            return super.getComponent();
75
        }
76
        final Shell shell = ((RobotSwtImpl)getRobot()).getActiveWindow();
77
        if (shell == null) {
78
            setComponent(null);
79
        } else {
80
            final IEventThreadQueuer queuer = new EventThreadQueuerSwtImpl();
81
            
82
            queuer.invokeAndWait("setMenuBarComponent", new IRunnable() { //$NON-NLS-1$
83
                public Object run() {
84
                    Menu menu = shell.getMenuBar();
85
                    setComponent(menu);
86
                    
87
                    return null;
88
                }
89
            });
90
        }
91
        return super.getComponent();
92
    }
93
    
94
    /**
95
     * {@inheritDoc}
96
     */
97
    public String[] getTextArrayFromComponent() {
98
        return null;
99
    }
100
    /**
101
     * {@inheritDoc}
102
     */
103
    protected IRobotFactory getRobotFactory() {
104
        if (m_robotFactory == null) {
105
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
106
        }
107
        return m_robotFactory;
108
    }
109
    
110
    /**
111
     * Tries to select a menu item in a menu defined by a Text-Path
112
     * @param namePath the menu item to select
113
     * @param operator operator used for matching
114
     */
115
    public void selectMenuItem(String namePath, final String operator) {        
116
        final String[] pathItems = MenuUtilBase.splitPath(namePath);
117
        if (pathItems.length == 0) {
118
            throw new StepExecutionException("empty path to menuitem not allowed", //$NON-NLS-1$
119
                EventFactory.createActionError());
120
        }
121
        
122
        try {
123
124
            final MenuItemAdapter itemAdapter = 
125
                    (MenuItemAdapter) navigateToMenuItem(
126
                            getAndCheckMenu(), pathItems, operator);
127
            if (itemAdapter.getRealComponent() == null) {
128
                throwMenuItemNotFound();
129
            }
130
            
131
            Rectangle bounds = itemAdapter.getMenuItemBounds();
132
            Rectangle nullBounds = new Rectangle(0, 0, 0, 0);
133
            
134
            if (bounds.equals(nullBounds)) {
135
                itemAdapter.selectProgramatically();
136
            } else {
137
                itemAdapter.selectMenuItem();
138
            }
139
        } catch (StepExecutionException e) {
140
            try {
141
                closeMenu(getAndCheckMenu(), pathItems, operator);
142
            } catch (StepExecutionException e1) {
143
                if (getLog().isInfoEnabled()) {
144
                    getLog().info("Tried to close a disabled or already closed menu."); //$NON-NLS-1$
145
                }
146
            }
147
            throw e;
148
        }
149
        
150
    }
151
    
152
    /**
153
     * Tries to select a menu item in a menu defined by an Index-Path
154
     * @param indexPath the menu item to select
155
     */
156
    public void selectMenuItemByIndexpath(String indexPath) {
157
        final int[] indexItems = MenuUtilBase.splitIndexPath(indexPath);
158
        if (indexItems.length == 0) {
159
            throw new StepExecutionException("empty path to menuitem not allowed", //$NON-NLS-1$
160
                EventFactory.createActionError());
161
        }
162
163
        try {
164
            MenuItemAdapter menuItemAdapter = (MenuItemAdapter) 
165
                    navigateToMenuItem(getAndCheckMenu(), indexItems);
166
            if (menuItemAdapter.getRealComponent() == null) {
167
                throwMenuItemNotFound();
168
            }
169
            
170
            Rectangle bounds = menuItemAdapter.getMenuItemBounds();
171
            Rectangle nullBounds = new Rectangle(0, 0, 0, 0);
172
            
173
            if (bounds.equals(nullBounds)) {
174
                menuItemAdapter.selectProgramatically();
175
            } else {
176
                menuItemAdapter.selectMenuItem();
177
            }
178
        } catch (StepExecutionException e) {
179
            try {
180
                closeMenu(getAndCheckMenu(), indexItems);
181
            } catch (StepExecutionException e1) {
182
                if (getLog().isInfoEnabled()) {
183
                    getLog().info("Tried to close a disabled or already closed menu."); //$NON-NLS-1$
184
                }
185
            }
186
            throwMenuItemNotFound();
187
        }
188
    }
189
190
    /**
191
     * 
192
     * @return the IMenuAdapter.
193
     * @throws StepExecutionException
194
     *             if the active window has no menu bar.
195
     */
196
    protected IMenuAdapter getAndCheckMenu() throws StepExecutionException {
197
        // Verify that there is an active window
198
        if (((RobotSwtImpl)getRobot()).getActiveWindow() == null) {
199
            throw new StepExecutionException(
200
                I18n.getString(TestErrorEvent.NO_ACTIVE_WINDOW), 
201
                EventFactory.createActionError(
202
                    TestErrorEvent.NO_ACTIVE_WINDOW));
203
        }
204
        return super.getAndCheckMenu();
205
    }
206
    
207
    
208
    /**
209
     * 
210
     */
211
    private void throwMenuItemNotFound() {
212
        throw new StepExecutionException("no such menu item found", //$NON-NLS-1$
213
            EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
214
    }
215
 
216
    /**
217
     * {@inheritDoc}
218
     */
219
    protected IMenuItemAdapter newMenuItemAdapter(Object component) {
220
        return new MenuItemAdapter(component);
221
    }
222
    
223
    /**
224
     * {@inheritDoc}
225
     */
226
    protected void closeMenu(IMenuAdapter menuBar, int[] path) {
227
        Validate.notNull(getMenu(menuBar));
228
        closeMenu(menuBar, path.length);
229
        
230
    }
231
    
232
    /**
233
     * {@inheritDoc}
234
     */
235
    protected void closeMenu(IMenuAdapter menuBar, String[] textPath,
236
            String operator) {
237
        Validate.notNull(getMenu(menuBar));
238
        closeMenu(menuBar, textPath.length);
239
    }
240
    
241
    /**
242
     * Closes the menu cascade with the KEY ESC
243
     * @param menuBar menu
244
     * @param maxCascadeLength an integer so that the closing operation is not infinite
245
     */
246
    private void closeMenu(final IMenuAdapter menuBar, int maxCascadeLength) {
247
        final MenuHiddenListener menuListener = 
248
                new MenuHiddenListener();
249
        getMenu(menuBar).getDisplay().syncExec(new Runnable() {
250
            public void run() {
251
                getMenu(menuBar).addMenuListener(menuListener);
252
            }
253
        });
254
        // Press 'ESC' key until the first menu is gone or we reach
255
        // the maxCascadeLength. This prevents infinite loops if this
256
        // is used on a platform that does not use 'ESC' to close menus.
257
        for (int i = 0; 
258
            i < maxCascadeLength && !menuListener.isMenuHidden();
259
            i++) {
260
261
            getRobot().keyType(getMenu(menuBar), SWT.ESC);
262
        }
263
        
264
    }
265
266
    /**
267
     * 
268
     * @param menu the menu adapter
269
     * @return the real SWT menu 
270
     */
271
    private Menu getMenu(final IMenuAdapter menu) {
272
        return (Menu) menu.getRealComponent();
273
    }
274
    /**
275
     * 
276
     * @return -
277
     */
278
    public boolean isContextMenu() {
279
        return m_isCM;
280
    }
281
    /**
282
     * 
283
     * @param isCM 
284
     */
285
    public void setContextMenu(boolean isCM) {
286
        this.m_isCM = isCM;
287
    }
288
289
    /**
290
     * Listens for a menu to be hidden, the removes itself from the menu's
291
     * listener list.
292
     * 
293
     * @author BREDEX GmbH
294
     * @created Nov 01, 2011
295
     */
296
    private static final class MenuHiddenListener implements MenuListener {
297
298
        /** whether the expected event has occurred */
299
        private boolean m_eventOccurred = false;
300
        
301
        /**
302
         * 
303
         * {@inheritDoc}
304
         */
305
        public void menuHidden(MenuEvent e) {
306
            m_eventOccurred = true;
307
            ((Menu)e.widget).removeMenuListener(this);
308
        }
309
310
        /**
311
         * 
312
         * {@inheritDoc}
313
         */
314
        public void menuShown(MenuEvent e) {
315
            // no-op
316
        }
317
318
        /**
319
         * 
320
         * @return <code>true</code> if the menu has been hidden since this 
321
         *         listener was registered. Otherwise, <code>false</code>.
322
         */
323
        public boolean isMenuHidden() {
324
            return m_eventOccurred;
325
        }
326
    }
327
    
328
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/TableCAPs.java (+737 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.caps;
12
13
import java.awt.Point;
14
import java.awt.Rectangle;
15
16
import org.eclipse.jubula.rc.common.CompSystemConstants;
17
import org.eclipse.jubula.rc.common.caps.AbstractTableCAPs;
18
import org.eclipse.jubula.rc.common.driver.ClickOptions;
19
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
20
import org.eclipse.jubula.rc.common.driver.IRobot;
21
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
22
import org.eclipse.jubula.rc.common.driver.IRunnable;
23
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
24
import org.eclipse.jubula.rc.common.implclasses.table.Cell;
25
import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITableAdapter;
26
import org.eclipse.jubula.rc.swt.driver.DragAndDropHelperSwt;
27
import org.eclipse.jubula.rc.swt.driver.KeyCodeConverter;
28
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
29
import org.eclipse.jubula.rc.swt.uiadapter.TableAdapter;
30
import org.eclipse.jubula.rc.swt.utils.SwtUtils;
31
import org.eclipse.jubula.tools.constants.InputConstants;
32
import org.eclipse.jubula.tools.objects.event.EventFactory;
33
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
34
import org.eclipse.swt.SWT;
35
import org.eclipse.swt.graphics.FontMetrics;
36
import org.eclipse.swt.graphics.GC;
37
import org.eclipse.swt.graphics.Image;
38
import org.eclipse.swt.widgets.Control;
39
import org.eclipse.swt.widgets.Item;
40
import org.eclipse.swt.widgets.Table;
41
import org.eclipse.swt.widgets.TableColumn;
42
import org.eclipse.swt.widgets.TableItem;
43
import org.eclipse.swt.widgets.Widget;
44
/**
45
 * Toolkit specific commands for the <code>Table</code>
46
 *
47
 * @author BREDEX GmbH
48
 */
49
public class TableCAPs extends AbstractTableCAPs {
50
    
51
    /**  */
52
    private IRobotFactory m_robotFactory;
53
54
    /**
55
     *  Gets the real table component
56
     * @return the table
57
     */
58
    private Table getTable() {
59
        return (Table)getComponent().getRealComponent();
60
    }
61
    
62
    /**
63
     * @return The event thread queuer.
64
     */
65
    public IEventThreadQueuer getEventThreadQueuer() {
66
        return getRobotFactory().getEventThreadQueuer();
67
    }
68
    
69
    /**
70
     * {@inheritDoc}
71
     */
72
    public String[] getTextArrayFromComponent() {
73
        final String[] componentTextArray;
74
        Item[] itemArray = getTable().getColumns();
75
        componentTextArray = getTextArrayFromItemArray(itemArray);         
76
        return componentTextArray;
77
    }
78
79
    /**
80
     * {@inheritDoc}
81
     */
82
    protected int getKeyCode(String mod) {
83
        return KeyCodeConverter.getKeyCode(mod);
84
    }
85
    
86
    /**
87
     * {@inheritDoc}
88
     */
89
    protected Object setEditorToReplaceMode(Object editor, boolean replace) {
90
        if (replace) {
91
            getRobot().clickAtCurrentPosition(editor, 3, 
92
                    InputConstants.MOUSE_BUTTON_LEFT);
93
        } else {
94
            getRobot().clickAtCurrentPosition(editor, 1, 
95
                    InputConstants.MOUSE_BUTTON_LEFT);
96
        }
97
        return editor;
98
    }
99
100
    /**
101
     * {@inheritDoc}
102
     */
103
    protected Object activateEditor(Cell cell, Rectangle rectangle) {
104
        TableAdapter table = (TableAdapter) getComponent();
105
        return table.activateEditor(cell);
106
    }
107
108
    /**
109
     * {@inheritDoc}
110
     */
111
    protected Rectangle scrollCellToVisible(final int row, final int col)
112
        throws StepExecutionException {
113
        final Table table = getTable();
114
        getEventThreadQueuer().invokeAndWait("scrollCellToVisible", //$NON-NLS-1$
115
                new IRunnable() {
116
                    public Object run() {
117
                        if (table.getColumnCount() > 0 || col > 0) {
118
                            table.showColumn(table.getColumn(col));
119
                        }
120
                        table.showItem(table.getItem(row));
121
                        return null;
122
                    }
123
                });
124
125
        final Rectangle cellBoundsRelativeToParent = getCellBounds(row, col);
126
            
127
        getEventThreadQueuer().invokeAndWait("getCellBoundsRelativeToParent", //$NON-NLS-1$
128
            new IRunnable() {
129
                public Object run() {
130
                    org.eclipse.swt.graphics.Point cellOriginRelativeToParent = 
131
                        table.getDisplay().map(
132
                                table, table.getParent(), 
133
                                new org.eclipse.swt.graphics.Point(
134
                                        cellBoundsRelativeToParent.x, 
135
                                        cellBoundsRelativeToParent.y));
136
                    cellBoundsRelativeToParent.x = 
137
                        cellOriginRelativeToParent.x;
138
                    cellBoundsRelativeToParent.y = 
139
                        cellOriginRelativeToParent.y;
140
                    return null;
141
                }
142
            });
143
144
        Control parent = (Control)getEventThreadQueuer().invokeAndWait("getParent", //$NON-NLS-1$
145
                new IRunnable() {
146
                public Object run() {
147
                    table.getParent();
148
                    return null;
149
                }
150
            });
151
152
            
153
        getRobot().scrollToVisible(
154
                parent, cellBoundsRelativeToParent);
155
        
156
        return getVisibleBounds(getCellBounds(row, col));
157
    }
158
159
    /**
160
     * {@inheritDoc}
161
     */
162
    protected int getExtendSelectionModifier() {
163
        return SWT.MOD1;
164
    }
165
166
    /**
167
     * {@inheritDoc}
168
     */
169
    protected Cell getCellAtMousePosition() throws StepExecutionException {
170
        
171
        final Table table = getTable();
172
        final Point awtMousePos = getRobot().getCurrentMousePosition();
173
        Cell returnvalue = (Cell) getEventThreadQueuer().invokeAndWait(
174
                "getCellAtMousePosition",  //$NON-NLS-1$
175
                new IRunnable() {
176
                    public Object run() throws StepExecutionException {
177
                        Cell cell = null;
178
                        final int itemCount = table.getItemCount();
179
                        for (int rowCount = table.getTopIndex(); 
180
                                rowCount < itemCount; rowCount++) {
181
                            if (cell != null) {
182
                                break;
183
                            }
184
                            final int columnCount = table.getColumnCount();
185
                            if (columnCount > 0) {
186
                                for (int col = 0; col < columnCount; col++) {
187
                                    final Rectangle itemBounds = getCellBounds(
188
                                            rowCount, col);
189
                                    final org.eclipse.swt.graphics.Point 
190
                                        absItemBounds = table
191
                                            .toDisplay(itemBounds.x,
192
                                                    itemBounds.y);
193
                                    final Rectangle absRect = new Rectangle(
194
                                            absItemBounds.x, absItemBounds.y,
195
                                            itemBounds.width,
196
                                            itemBounds.height);
197
                                    if (absRect.contains(awtMousePos)) {
198
                                        cell = new Cell(rowCount, col);
199
                                        break;
200
                                    }
201
                                }
202
                            } else {
203
                                final Rectangle itemBounds = getCellBounds(
204
                                        rowCount, 0);
205
                                final org.eclipse.swt.graphics.Point 
206
                                    absItemBounds = table
207
                                        .toDisplay(itemBounds.x, itemBounds.y);
208
                                final Rectangle absRect = new Rectangle(
209
                                        absItemBounds.x, absItemBounds.y,
210
                                        itemBounds.width, itemBounds.height);
211
                                if (absRect.contains(awtMousePos)) {
212
                                    cell = new Cell(rowCount, 0);
213
                                }
214
                            }
215
                        }
216
                        if (cell == null) {
217
                            throw new StepExecutionException(
218
                                    "No cell under mouse position found!", //$NON-NLS-1$
219
                                    EventFactory
220
                                            .createActionError(
221
                                                    TestErrorEvent.NOT_FOUND));
222
                        }
223
                        return cell;
224
                    }
225
                });
226
        return returnvalue;
227
    }
228
229
    /**
230
     * {@inheritDoc}
231
     */
232
    protected boolean isMouseOnHeader() {
233
        final Table table = getTable();
234
        final ITableAdapter adapter = (ITableAdapter)getComponent();
235
        Boolean isVisible;
236
        isVisible = (Boolean)getEventThreadQueuer().invokeAndWait(
237
                "isMouseOnHeader", //$NON-NLS-1$
238
                new IRunnable() {
239
                    public Object run() {
240
                        return new Boolean(table.getHeaderVisible());
241
                    }
242
                });
243
        
244
        if (!(isVisible.booleanValue())) {
245
            return false;
246
        }
247
        
248
        Boolean isOnHeader = new Boolean(false);
249
        isOnHeader = (Boolean)getEventThreadQueuer().invokeAndWait(
250
                "isMouseOnHeader", //$NON-NLS-1$
251
                new IRunnable() {
252
                    public Object run() {
253
                        final Point awtMousePos = getRobot()
254
                            .getCurrentMousePosition();
255
                        org.eclipse.swt.graphics.Point mousePos =
256
                            new org.eclipse.swt.graphics.Point(
257
                                awtMousePos.x, awtMousePos.y);
258
259
                        for (int j = 0; j < table.getColumnCount(); j++) {
260
                            final Rectangle constraints = 
261
                                    adapter.getHeaderBounds(j);
262
                            
263
                            org.eclipse.swt.graphics.Rectangle bounds = 
264
                                    SwtUtils.getWidgetBounds(
265
                                    table);
266
                            
267
                            if (constraints != null) {
268
                                // Use SWT's mapping function, if possible, as it is more
269
                                // multi-platform than simply adding the x and y values.
270
                                org.eclipse.swt.graphics.Point
271
                                convertedLocation = getConvertedLocation(
272
                                        constraints);
273
                                bounds.x = convertedLocation.x;
274
                                bounds.y = convertedLocation.y;
275
                                
276
                                bounds.height = constraints.height;
277
                                bounds.width = constraints.width;
278
                            }
279
280
                            if (bounds.contains(mousePos)) {
281
                                return new Boolean(true);
282
                            }
283
                        }      
284
                        return new Boolean(false);
285
                    }
286
                });                  
287
        
288
        return isOnHeader.booleanValue();
289
    }
290
291
    /**
292
     * {@inheritDoc}
293
     */
294
    protected IRobotFactory getRobotFactory() {
295
        if (m_robotFactory == null) {
296
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
297
        }
298
        return m_robotFactory;
299
    }
300
301
    
302
    /**
303
     * Returns an array of representation strings that corresponds to the given
304
     * array of items or null if the given array is null;
305
     * @param itemArray the item array whose item texts have to be read
306
     * @return array of item texts corresponding to the given item array
307
     */
308
    protected final String[] getTextArrayFromItemArray(Item[] itemArray) {
309
        final String[] itemTextArray;
310
        if (itemArray == null) {
311
            itemTextArray = null;
312
        } else {
313
            itemTextArray = new String[itemArray.length];
314
            for (int i = 0; i < itemArray.length; i++) {
315
                Item item = itemArray[i];
316
                if (item == null) {
317
                    itemTextArray[i] = null;
318
                } else {
319
                    itemTextArray[i] = SwtUtils.removeMnemonics(item.getText());
320
                }
321
            }
322
        }
323
        
324
        return itemTextArray;
325
    }
326
    
327
    /**
328
     * Computes the visible cellBounds inside the visible bounds of the table.<br>
329
     * The result is the intersection of the visible bounds of the table and the 
330
     * bounds of the cell.
331
     * @param cellBounds the bounds of the cell to click in. These bounds must
332
     *                  be relative to the table's location.
333
     * @return the visible cell bounds, relative to the table's location.
334
     */
335
    private Rectangle getVisibleBounds(Rectangle cellBounds) {
336
        org.eclipse.swt.graphics.Rectangle r = 
337
            (org.eclipse.swt.graphics.Rectangle)
338
            getEventThreadQueuer().invokeAndWait("getVisibleCellBounds: " + cellBounds,  //$NON-NLS-1$
339
                    new IRunnable() {
340
341
                    public Object run() {
342
                        return getTable().getClientArea();
343
                    }
344
                });
345
        
346
        Rectangle visibleTableBounds = new Rectangle(
347
            r.x, r.y, r.width, r.height);
348
        Rectangle visibleCellBounds = 
349
            visibleTableBounds.intersection(cellBounds);
350
        return visibleCellBounds;
351
    }
352
    
353
    /**
354
     * @param constraints Rectangle
355
     * @return converted Location of table
356
     */
357
    private org.eclipse.swt.graphics.Point getConvertedLocation(
358
            final Rectangle constraints) {
359
        org.eclipse.swt.graphics.Point convertedLocation =
360
            (org.eclipse.swt.graphics.Point)getEventThreadQueuer()
361
                .invokeAndWait("toDisplay", new IRunnable() { //$NON-NLS-1$
362
                    public Object run() throws StepExecutionException {
363
                        return getTable().toDisplay(
364
                                constraints.x, constraints.y);
365
                    }
366
                });
367
        return convertedLocation;
368
    }
369
        
370
    /**
371
     * 
372
     * @param row   The row of the cell
373
     * @param col   The column of the cell
374
     * @return The bounding rectangle for the cell, relative to the table's 
375
     *         location.
376
     */
377
    private Rectangle getCellBounds(final int row, final int col) {
378
        final Table table = getTable();
379
        Rectangle cellBounds = (Rectangle)getEventThreadQueuer().invokeAndWait(
380
                "evaluateCellBounds", //$NON-NLS-1$
381
                new IRunnable() {
382
                    public Object run() {
383
                        checkRowColBounds(row, col);
384
                        TableItem ti = table.getItem(row);
385
                        int column = (table.getColumnCount() > 0 || col > 0) 
386
                            ? col : 0;
387
                        org.eclipse.swt.graphics.Rectangle r = 
388
                                ti.getBounds(column);
389
                        String text = ti.getText(column);
390
                        Image image = ti.getImage(column);
391
                        if (text != null && text.length() != 0) {
392
                            GC gc = new GC(table);
393
                            int charWidth = 0; 
394
                            try {
395
                                FontMetrics fm = gc.getFontMetrics();
396
                                charWidth = fm.getAverageCharWidth();
397
                            } finally {
398
                                gc.dispose();
399
                            }
400
                            r.width = text.length() * charWidth;
401
                            if (image != null) {
402
                                r.width += image.getBounds().width;
403
                            }
404
                        } else if (image != null) {
405
                            r.width = image.getBounds().width;
406
                        }
407
                        if (column > 0) {
408
                            TableColumn tc = table.getColumn(column);
409
                            int alignment = tc.getAlignment();
410
                            if (alignment == SWT.CENTER) {
411
                                r.x += ((double)tc.getWidth() / 2) 
412
                                        - ((double)r.width / 2);
413
                            }
414
                            if (alignment == SWT.RIGHT) {
415
                                r.x += tc.getWidth() - r.width;
416
                            }
417
                        }
418
                        
419
                        return new Rectangle(r.x, r.y, r.width, r.height);
420
                    }
421
                });
422
        return cellBounds;
423
    }
424
    /**
425
     * {@inheritDoc}
426
     */
427
    protected Object getSpecificRectangle(Rectangle rectangle) {
428
        return new org.eclipse.swt.graphics.Rectangle(rectangle.x, rectangle.y,
429
                rectangle.width, rectangle.height);
430
    }
431
    
432
    /**
433
     * {@inheritDoc}
434
     */
435
    public void gdClickDirect(int count, int button, int xPos, String xUnits, 
436
        int yPos, String yUnits) throws StepExecutionException {
437
        
438
        int correctedYPos = correctYPos(yPos, yUnits);
439
        super.gdClickDirect(count, button, xPos, xUnits, correctedYPos, yUnits);
440
    }
441
    
442
    /**
443
     * Corrects the given Y position based on the height of the table's header.
444
     * This ensures, for example, that test steps don't try to click within the
445
     * table header (where we receive no confirmation events).
446
     * 
447
     * @param pos The Y position to correct.
448
     * @param units The units used for the Y position.
449
     * @return The corrected Y position.
450
     */
451
    private int correctYPos(int pos, String units) {
452
        int correctedPos = pos;
453
        int headerHeight = ((Integer)getEventThreadQueuer().invokeAndWait(
454
                "getHeaderHeight", new IRunnable() { //$NON-NLS-1$
455
456
                    public Object run() throws StepExecutionException {
457
                        return new Integer(
458
                            ((Table)getComponent().getRealComponent())
459
                            .getHeaderHeight());
460
                    }
461
            
462
                })).intValue();
463
464
        if (POS_UNIT_PIXEL.equalsIgnoreCase(units)) {
465
            // Pixel units
466
            correctedPos += headerHeight;
467
        } else {
468
            // Percentage units
469
            int totalHeight = ((Integer)getEventThreadQueuer().invokeAndWait(
470
                    "getWidgetBounds", new IRunnable() { //$NON-NLS-1$
471
472
                        public Object run() throws StepExecutionException {
473
                            return new Integer(
474
                                SwtUtils.getWidgetBounds(
475
                                    (Widget) getComponent().
476
                                        getRealComponent()).height);
477
                        }
478
            
479
                    })).intValue();
480
            long targetHeight = totalHeight - headerHeight;
481
            long targetPos = Math.round((double)targetHeight * (double)pos
482
                / 100.0);
483
            targetPos += headerHeight;
484
            double heightPercentage = 
485
                (double)targetPos / (double)totalHeight * 100.0;
486
            correctedPos = (int)Math.round(heightPercentage);
487
            if (correctedPos > 100) { // rounding error
488
                correctedPos = 100;
489
            }
490
        }
491
        return correctedPos;
492
    }
493
    
494
    /**
495
     * Drags the cell of the Table.<br>
496
     * With the xPos, yPos, xunits and yUnits the click position inside the 
497
     * cell can be defined.
498
     * 
499
     * @param mouseButton the mouseButton.
500
     * @param modifier the modifier.
501
     * @param row The row of the cell.
502
     * @param rowOperator the row header operator
503
     * @param col The column of the cell.
504
     * @param colOperator the column header operator
505
     * @param xPos what x position
506
     * @param xUnits should x position be pixel or percent values
507
     * @param yPos what y position
508
     * @param yUnits should y position be pixel or percent values
509
     * @throws StepExecutionException
510
     *             If the row or the column is invalid
511
     */
512
    public void gdDragCell(final int mouseButton, final String modifier, 
513
            final String row, String rowOperator, final String col,
514
            final String colOperator, final int xPos, final String xUnits,
515
            final int yPos, final String yUnits) 
516
        throws StepExecutionException {
517
        
518
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
519
            .getInstance();
520
        dndHelper.setMouseButton(mouseButton);
521
        dndHelper.setModifier(modifier);
522
        dndHelper.setDragComponent(null);
523
        
524
        gdSelectCell(row, rowOperator, col, colOperator, 0, xPos,
525
                xUnits, yPos, yUnits, 
526
                CompSystemConstants.EXTEND_SELECTION_NO, 1);
527
    }
528
    
529
    /**
530
     * Drops on the cell of the JTable.<br>
531
     * With the xPos, yPos, xunits and yUnits the click position inside the 
532
     * cell can be defined.
533
     * 
534
     * @param row The row of the cell.
535
     * @param rowOperator The row operator
536
     * @param col The column of the cell.
537
     * @param colOperator The column operator
538
     * @param xPos what x position
539
     * @param xUnits should x position be pixel or percent values
540
     * @param yPos what y position
541
     * @param yUnits should y position be pixel or percent values
542
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
543
     *                        between moving the mouse to the drop point and
544
     *                        releasing the mouse button                       
545
     * @throws StepExecutionException
546
     *             If the row or the column is invalid
547
     */
548
    public void gdDropCell(final String row, final String rowOperator,
549
            final String col, final String colOperator, final int xPos, 
550
            final String xUnits, final int yPos, final String yUnits,
551
            int delayBeforeDrop) throws StepExecutionException {
552
        
553
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
554
            .getInstance();
555
        final IRobot robot = getRobot();
556
        
557
        pressOrReleaseModifiers(dndHelper.getModifier(), true);
558
        try {
559
            getEventThreadQueuer().invokeAndWait("gdDropCell", new IRunnable() { //$NON-NLS-1$
560
561
                public Object run() throws StepExecutionException {
562
                    // drag
563
                    robot.mousePress(dndHelper.getDragComponent(), null, 
564
                            dndHelper.getMouseButton());
565
566
                    CAPUtil.shakeMouse();
567
568
                    // drop
569
                    gdSelectCell(row, rowOperator, col, colOperator, 0, xPos,
570
                            xUnits, yPos, yUnits, 
571
                            CompSystemConstants.EXTEND_SELECTION_NO, 1);
572
                    return null;
573
                }            
574
            });
575
576
            CAPUtil.waitBeforeDrop(delayBeforeDrop);
577
            
578
        } finally {
579
            robot.mouseRelease(dndHelper.getDragComponent(), null, 
580
                    dndHelper.getMouseButton());
581
            pressOrReleaseModifiers(dndHelper.getModifier(), false);
582
        }
583
    }
584
    
585
    /**
586
     * Finds the first row which contains the value <code>value</code>
587
     * in column <code>col</code> and drags this row.
588
     * 
589
     * @param mouseButton the mouse button
590
     * @param modifier the modifier
591
     * @param col the column
592
     * @param colOperator the column header operator
593
     * @param value the value
594
     * @param regexOp the regex operator
595
     * @param searchType Determines where the search begins ("relative" or "absolute")
596
     */
597
    public void gdDragRowByValue(int mouseButton, String modifier, String col,
598
            String colOperator, final String value, final String regexOp,
599
            final String searchType) {
600
        
601
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
602
            .getInstance();
603
        dndHelper.setMouseButton(mouseButton);
604
        dndHelper.setModifier(modifier);
605
        dndHelper.setDragComponent(null);
606
        
607
        gdSelectRowByValue(col, colOperator, value, regexOp, 1, 
608
                CompSystemConstants.EXTEND_SELECTION_NO,
609
                searchType, 1);
610
    }
611
    
612
    /**
613
     * Finds the first row which contains the value <code>value</code>
614
     * in column <code>col</code> and drops on this row.
615
     * 
616
     * @param col the column
617
     * @param colOperator the column operator
618
     * @param value the value
619
     * @param regexOp the regex operator
620
     * @param searchType Determines where the search begins ("relative" or "absolute")
621
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
622
     *                        between moving the mouse to the drop point and
623
     *                        releasing the mouse button                       
624
     */
625
    public void gdDropRowByValue(final String col, final String colOperator,
626
            final String value, final String regexOp, final String searchType, 
627
            int delayBeforeDrop) {
628
        
629
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
630
            .getInstance();
631
        final IRobot robot = getRobot();
632
        pressOrReleaseModifiers(dndHelper.getModifier(), true);
633
        
634
        try {
635
            getEventThreadQueuer().invokeAndWait("gdDropRowByValue", new IRunnable() { //$NON-NLS-1$
636
637
                public Object run() throws StepExecutionException {
638
                    // drag
639
                    robot.mousePress(dndHelper.getDragComponent(), null, 
640
                            dndHelper.getMouseButton());
641
642
                    CAPUtil.shakeMouse();
643
644
                    // drop
645
                    gdSelectRowByValue(col, colOperator, value, regexOp,
646
                            CompSystemConstants.EXTEND_SELECTION_NO, 
647
                            searchType, 
648
                            ClickOptions.create().setClickCount(0));
649
                    return null;
650
                }            
651
            });
652
            
653
            CAPUtil.waitBeforeDrop(delayBeforeDrop);
654
            
655
        } finally {
656
            robot.mouseRelease(dndHelper.getDragComponent(), null, 
657
                    dndHelper.getMouseButton());
658
            pressOrReleaseModifiers(dndHelper.getModifier(), false);
659
        }
660
    }
661
    
662
    /**
663
     * Finds the first column which contains the value <code>value</code>
664
     * in the given row and drags the cell.
665
     * 
666
     * @param mouseButton the mouse button
667
     * @param modifier the modifiers
668
     * @param row the row
669
     * @param rowOperator the row header operator
670
     * @param value the value
671
     * @param regex search using regex
672
     * @param searchType Determines where the search begins ("relative" or "absolute")
673
     */
674
    public void gdDragCellByColValue(int mouseButton, String modifier,
675
            String row, String rowOperator, final String value,
676
            final String regex, final String searchType) {
677
        
678
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
679
            .getInstance();
680
        dndHelper.setMouseButton(mouseButton);
681
        dndHelper.setModifier(modifier);
682
        dndHelper.setDragComponent(null);
683
        gdSelectCellByColValue(row, rowOperator, value, regex, 
684
                CompSystemConstants.EXTEND_SELECTION_NO,
685
                searchType, ClickOptions.create().setClickCount(0));
686
    }
687
    
688
    /**
689
     * Finds the first column which contains the value <code>value</code>
690
     * in the given row and drops on the cell.
691
     * 
692
     * @param row the row
693
     * @param rowOperator the row header operator
694
     * @param value the value
695
     * @param regex search using regex
696
     * @param searchType Determines where the search begins ("relative" or "absolute")
697
     * @param delayBeforeDrop the amount of time (in milliseconds) to wait
698
     *                        between moving the mouse to the drop point and
699
     *                        releasing the mouse button                       
700
     */
701
    public void gdDropCellByColValue(final String row, final String rowOperator,
702
            final String value, final String regex, final String searchType,
703
            int delayBeforeDrop) {
704
        
705
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
706
            .getInstance();
707
        final IRobot robot = getRobot();
708
        pressOrReleaseModifiers(dndHelper.getModifier(), true);
709
710
        try {
711
            getEventThreadQueuer().invokeAndWait("gdDropCellByColValue", new IRunnable() { //$NON-NLS-1$
712
713
                public Object run() throws StepExecutionException {
714
                    // drag
715
                    robot.mousePress(dndHelper.getDragComponent(), null, 
716
                            dndHelper.getMouseButton());
717
718
                    CAPUtil.shakeMouse();
719
720
                    // drop
721
                    gdSelectCellByColValue(row, rowOperator, value, regex,
722
                            CompSystemConstants.EXTEND_SELECTION_NO, 
723
                            searchType, 
724
                            ClickOptions.create().setClickCount(0));
725
                    return null;
726
                }            
727
            });
728
729
            CAPUtil.waitBeforeDrop(delayBeforeDrop);
730
        
731
        } finally {
732
            robot.mouseRelease(dndHelper.getDragComponent(), null, 
733
                    dndHelper.getMouseButton());
734
            pressOrReleaseModifiers(dndHelper.getModifier(), false);
735
        }
736
    }
737
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/caps/TreeCAPs.java (+927 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.caps;
12
13
import java.util.StringTokenizer;
14
15
import org.apache.commons.lang.Validate;
16
import org.eclipse.jubula.rc.common.AUTServer;
17
import org.eclipse.jubula.rc.common.CompSystemConstants;
18
import org.eclipse.jubula.rc.common.caps.AbstractTreeCAPs;
19
import org.eclipse.jubula.rc.common.driver.ClickOptions;
20
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
21
import org.eclipse.jubula.rc.common.driver.IRobot;
22
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
23
import org.eclipse.jubula.rc.common.driver.IRunnable;
24
import org.eclipse.jubula.rc.common.exception.RobotException;
25
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
26
import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
27
import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
28
import org.eclipse.jubula.rc.common.implclasses.Verifier;
29
import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeNodeOperation;
30
import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeNodeTraverser;
31
import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeOperationContext;
32
import org.eclipse.jubula.rc.common.implclasses.tree.ChildTraverser;
33
import org.eclipse.jubula.rc.common.implclasses.tree.ExpandCollapseTreeNodeOperation;
34
import org.eclipse.jubula.rc.common.implclasses.tree.INodePath;
35
import org.eclipse.jubula.rc.common.implclasses.tree.ParentTraverser;
36
import org.eclipse.jubula.rc.common.implclasses.tree.PathBasedTraverser;
37
import org.eclipse.jubula.rc.common.implclasses.tree.SelectTreeNodeOperation;
38
import org.eclipse.jubula.rc.common.implclasses.tree.SiblingTraverser;
39
import org.eclipse.jubula.rc.common.implclasses.tree.StandardDepthFirstTraverser;
40
import org.eclipse.jubula.rc.common.implclasses.tree.TreeNodeOperation;
41
import org.eclipse.jubula.rc.common.implclasses.tree.TreeNodeOperationConstraint;
42
import org.eclipse.jubula.rc.common.util.KeyStrokeUtil;
43
import org.eclipse.jubula.rc.swt.driver.DragAndDropHelperSwt;
44
import org.eclipse.jubula.rc.swt.driver.KeyCodeConverter;
45
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
46
import org.eclipse.jubula.rc.swt.implclasses.TableTreeOperationContext;
47
import org.eclipse.jubula.rc.swt.implclasses.TreeOperationContext;
48
import org.eclipse.jubula.rc.swt.implclasses.tree.ToggleCheckboxOperation;
49
import org.eclipse.jubula.rc.swt.implclasses.tree.VerifyCheckboxOperation;
50
import org.eclipse.jubula.rc.swt.utils.SwtUtils;
51
import org.eclipse.jubula.tools.objects.event.EventFactory;
52
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
53
import org.eclipse.swt.SWT;
54
import org.eclipse.swt.graphics.Point;
55
import org.eclipse.swt.graphics.Rectangle;
56
import org.eclipse.swt.widgets.Control;
57
import org.eclipse.swt.widgets.Event;
58
import org.eclipse.swt.widgets.ScrollBar;
59
import org.eclipse.swt.widgets.TreeItem;
60
import org.eclipse.swt.widgets.Tree;
61
/**
62
 * Toolkit specific commands for the <code>Tree</code>
63
 *
64
 * @author BREDEX GmbH
65
 */
66
public class TreeCAPs extends AbstractTreeCAPs {
67
68
    
69
    /**
70
     * Finds the item at a given position in the tree.
71
     *
72
     * @author BREDEX GmbH
73
     * @created Jul 28, 2010
74
     */
75
    private static final class ItemAtPointTreeNodeOperation 
76
            extends AbstractTreeNodeOperation {
77
78
        /** the item that was found at the given position */
79
        private TreeItem m_itemAtPoint;
80
        
81
        /** the position (in absolute coordinates) at which to find the item */
82
        private Point m_absPoint;
83
        
84
        /** 
85
         * the bounds (in absolute coordinates) of the tree in which the 
86
         * search should take place 
87
         */
88
        private Rectangle m_absTreeBounds;
89
        
90
    
91
    /**
92
     * Constructor
93
     * 
94
     * @param absPoint The position (in absolute coordinates) at which to 
95
     *                 find the item.
96
     * @param absTreeBounds The bounds (in absolute coordinates) of the 
97
     *                      tree in which the search should take place. 
98
     */
99
        public ItemAtPointTreeNodeOperation(Point absPoint, 
100
            Rectangle absTreeBounds) {
101
            m_absPoint = absPoint;
102
            m_absTreeBounds = absTreeBounds;
103
        }
104
    
105
    /**
106
     * {@inheritDoc}
107
     */
108
        public boolean operate(Object node) throws StepExecutionException {
109
            if (getContext().isVisible(node) && node instanceof TreeItem) {
110
                TreeItem currentItem = (TreeItem)node;
111
                final Rectangle absItemBounds = 
112
                        SwtUtils.getBounds(currentItem);
113
                absItemBounds.x = m_absTreeBounds.x;
114
                absItemBounds.width = m_absTreeBounds.width;
115
                if (SwtUtils.containsInclusive(
116
                        absItemBounds, m_absPoint)) {
117
                    m_itemAtPoint = currentItem;
118
                    return false;
119
                }
120
            }
121
        
122
            return true;
123
        }
124
    
125
    /**
126
     * 
127
     * @return the item found at the given position, or <code>null</code> if
128
     *         no item was found. Note that this method will always return 
129
     *         <code>null</code> if called before or during execution of
130
     *         {@link #operate(Object)}.
131
     */
132
        public TreeItem getItemAtPoint() {
133
            return m_itemAtPoint;
134
        }
135
    }
136
    
137
    /** The robot factory. */
138
    private IRobotFactory m_robotFactory;
139
    
140
    /**
141
     * Gets the Robot factory. The factory is created once per instance.
142
     * @return The Robot factory.
143
     */
144
    protected IRobotFactory getRobotFactory() {
145
        if (m_robotFactory == null) {
146
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
147
        }
148
        return m_robotFactory;
149
    }
150
    /**
151
     * Gets the Robot. 
152
     * @return The Robot
153
     * @throws RobotException If the Robot cannot be created.
154
     */
155
    protected IRobot getRobot() throws RobotException {
156
        return AUTServer.getInstance().getRobot();
157
    }
158
    
159
    /**
160
     * @return The event thread queuer.
161
     */
162
    protected IEventThreadQueuer getEventThreadQueuer() {
163
        return getRobotFactory().getEventThreadQueuer();
164
    }
165
    /**
166
     * 
167
     * @return the Tree
168
     */
169
    private Tree getTree() {
170
        return (Tree) getComponent().getRealComponent();
171
    }
172
    
173
    /**
174
     * {@inheritDoc}
175
     */
176
    public void gdVerifyTextAtMousePosition(String pattern, String operator) {
177
        TreeItem itemAtMousePosition = (TreeItem) getNodeAtMousePosition();
178
        int column = getMouseColumn();
179
        AbstractTreeOperationContext context;
180
        
181
        if (column != -1) {
182
            context = 
183
                new TableTreeOperationContext(
184
                    getEventThreadQueuer(), getRobot(),
185
                    getTree(), column);
186
        } else {
187
            context =
188
                new TableTreeOperationContext(
189
                    getEventThreadQueuer(), getRobot(), 
190
                    getTree());
191
        }
192
193
        Verifier.match(context.getRenderedText(itemAtMousePosition), 
194
                pattern, operator);
195
196
    }
197
    
198
199
200
201
    /**
202
     * {@inheritDoc}
203
     */
204
    public void gdDragByTextPath(int mouseButton, String modifier, 
205
            String pathType, int preAscend, String treePath, String operator) {
206
        
207
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
208
            .getInstance();
209
        
210
        dndHelper.setMouseButton(mouseButton);
211
        dndHelper.setModifier(modifier);
212
        dndHelper.setDragComponent(null);
213
214
        SwtUtils.waitForDisplayIdle(getTree().getDisplay());
215
216
        gdSelect(pathType, preAscend, treePath, operator, 0, 1, 
217
                CompSystemConstants.EXTEND_SELECTION_NO);
218
219
        SwtUtils.waitForDisplayIdle(getTree().getDisplay());
220
    }
221
222
    /**
223
     * {@inheritDoc}
224
     */
225
    public void gdDropByTextPath(final String pathType, final int preAscend, 
226
            final String treePath, final String operator, int delayBeforeDrop) {
227
        
228
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
229
            .getInstance();
230
        final IRobot robot = getRobot();
231
232
        try {
233
            pressOrReleaseModifiers(dndHelper.getModifier(), true);
234
            getEventThreadQueuer().invokeAndWait("gdDropByTextPath - perform drag", new IRunnable() { //$NON-NLS-1$
235
236
                public Object run() throws StepExecutionException {
237
                    // drag
238
                    robot.mousePress(dndHelper.getDragComponent(), null, 
239
                            dndHelper.getMouseButton());                    
240
                    
241
                    CAPUtil.shakeMouse();
242
243
                    return null;
244
                }            
245
            });
246
247
            // Post a MouseMove event in order to break the Display out of its
248
            // post-drag "freeze". It appears as though the mouse position 
249
            // change needs to be extreme in order to nudge the Display back 
250
            // into action (i.e. (<mouse-location> + 1) was insufficient), 
251
            // so the default Event values (x, y = 0) are used.
252
            Event wakeEvent = new Event();
253
            wakeEvent.type = SWT.MouseMove;
254
            getTree().getDisplay().post(wakeEvent);
255
256
            waitForDisplayUpdate();
257
258
            // drop
259
            gdSelect(pathType, preAscend, treePath, operator, 0, 1,
260
                    CompSystemConstants.EXTEND_SELECTION_NO);
261
262
            SwtUtils.waitForDisplayIdle(getTree().getDisplay());
263
            CAPUtil.waitBeforeDrop(delayBeforeDrop);
264
            
265
        } finally {
266
            robot.mouseRelease(null, null, dndHelper.getMouseButton());
267
            pressOrReleaseModifiers(
268
                    dndHelper.getModifier(), false);
269
            SwtUtils.waitForDisplayIdle(getTree().getDisplay());
270
        }
271
    }
272
273
    /**
274
     * {@inheritDoc}
275
     */
276
    public void gdDragByIndexPath(int mouseButton, String modifier, 
277
            String pathType, int preAscend, String indexPath) {
278
        
279
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
280
            .getInstance();
281
        
282
        dndHelper.setMouseButton(mouseButton);
283
        dndHelper.setModifier(modifier);
284
        dndHelper.setDragComponent(null);
285
        
286
        SwtUtils.waitForDisplayIdle(getTree().getDisplay());
287
288
        gdSelectByIndices(pathType, preAscend, indexPath, 0, 1, 
289
                CompSystemConstants.EXTEND_SELECTION_NO);
290
        
291
        SwtUtils.waitForDisplayIdle(getTree().getDisplay());
292
    }
293
294
    /**
295
     * {@inheritDoc}
296
     */
297
    public void gdDropByIndexPath(final String pathType, final int preAscend, 
298
            final String indexPath, int delayBeforeDrop) {
299
        
300
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
301
            .getInstance();
302
        final IRobot robot = getRobot();
303
        try {
304
            pressOrReleaseModifiers(dndHelper.getModifier(), true);
305
            getEventThreadQueuer().invokeAndWait("gdDropByIndexPath - perform drag", new IRunnable() { //$NON-NLS-1$
306
307
                public Object run() throws StepExecutionException {
308
                    // drag
309
                    robot.mousePress(dndHelper.getDragComponent(), null, 
310
                            dndHelper.getMouseButton());
311
312
                    CAPUtil.shakeMouse();
313
314
                    return null;
315
                }            
316
            });
317
318
            // Post a MouseMove event in order to break the Display out of its
319
            // post-drag "freeze". It appears as though the mouse position 
320
            // change needs to be extreme in order to nudge the Display back 
321
            // into action (i.e. (<mouse-location> + 1) was insufficient), 
322
            // so the default Event values (x, y = 0) are used.
323
            Event wakeEvent = new Event();
324
            wakeEvent.type = SWT.MouseMove;
325
            getTree().getDisplay().post(wakeEvent);
326
            
327
            waitForDisplayUpdate();
328
329
            // drop
330
            gdSelectByIndices(pathType, preAscend, indexPath, 0, 1, 
331
                    CompSystemConstants.EXTEND_SELECTION_NO);
332
333
            SwtUtils.waitForDisplayIdle(getTree().getDisplay());
334
            CAPUtil.waitBeforeDrop(delayBeforeDrop);
335
        } finally {
336
            robot.mouseRelease(null, null, dndHelper.getMouseButton());
337
            pressOrReleaseModifiers(dndHelper.getModifier(),
338
                    false);
339
            SwtUtils.waitForDisplayIdle(getTree().getDisplay());
340
        }
341
    }
342
    /**
343
     * {@inheritDoc}
344
     */
345
    protected Object getNodeAtMousePosition() throws StepExecutionException {
346
        return (TreeItem)getEventThreadQueuer().invokeAndWait("getItemAtMousePosition", new IRunnable() { //$NON-NLS-1$
347
            
348
            public Object run() throws StepExecutionException {
349
                Point mousePos = SwtUtils.convertToSwtPoint(
350
                        getRobot().getCurrentMousePosition());
351
                ItemAtPointTreeNodeOperation op = 
352
                    new ItemAtPointTreeNodeOperation(
353
                            mousePos, SwtUtils.getWidgetBounds(getTree()));
354
355
                TreeItem topItem = getTree().getTopItem();
356
                if (topItem != null) {
357
                    
358
                    // FIXME zeb This may be slow for very large trees, as the 
359
                    //           search may continue long past the
360
                    //           visible client area of the tree.
361
                    //           It may also cause problems with regard to 
362
                    //           lazy/virtual nodes. 
363
                    StandardDepthFirstTraverser traverser = 
364
                        new StandardDepthFirstTraverser(
365
                            new TreeOperationContext(
366
                                getEventThreadQueuer(), getRobot(), getTree()));
367
                    traverser.traversePath(op, topItem);
368
                    if (op.getItemAtPoint() != null) {
369
                        return op.getItemAtPoint();
370
                    }
371
                    
372
                }
373
374
                throw new StepExecutionException("No tree node found at mouse position.", //$NON-NLS-1$
375
                        EventFactory.createActionError(
376
                                TestErrorEvent.NOT_FOUND));
377
            }
378
        });
379
    }
380
    
381
    /**
382
     * @return the column where the mouse pointer currently rests. Returns -1 if
383
     *         the mouse pointer is currently outside of the TableTree or if the
384
     *         TableTree has no columns.
385
     */
386
    private int getMouseColumn() {
387
        final Tree treeTable = getTree();
388
        int column = ((Integer)getEventThreadQueuer().invokeAndWait(
389
                "getMouseColumn", new IRunnable() { //$NON-NLS-1$
390
391
                    public Object run() throws StepExecutionException {
392
                        Rectangle treeTableBounds = 
393
                            SwtUtils.getWidgetBounds(getTree());
394
                        Point cursorPosition = 
395
                            treeTable.getDisplay().getCursorLocation();
396
                        boolean isCursorInBounds = 
397
                            treeTableBounds.contains(cursorPosition);
398
                        if (isCursorInBounds) {
399
                            int horizontalScrollOffset = 0;
400
                            ScrollBar horizontalBar = 
401
                                getTree().getHorizontalBar();
402
                            if (horizontalBar != null 
403
                                    && !horizontalBar.isDisposed()) {
404
                                horizontalScrollOffset = 
405
                                    horizontalBar.getSelection();
406
                            }
407
                            Rectangle columnBounds = new Rectangle(
408
                                treeTableBounds.x - horizontalScrollOffset, 
409
                                treeTableBounds.y, 0, treeTableBounds.height);
410
                            for (int i = 0; 
411
                                i < treeTable.getColumnCount(); i++) {
412
                                
413
                                columnBounds.x += columnBounds.width;
414
                                columnBounds.width = 
415
                                    treeTable.getColumn(i).getWidth();
416
                                if (columnBounds.contains(cursorPosition)) {
417
                                    return new Integer(i);
418
                                }
419
                            }
420
                        }
421
422
                        return new Integer(-1);
423
                    }
424
425
                })).intValue();
426
        
427
        return column;
428
    }
429
    // 
430
    // Methods for Table Trees following
431
    // 
432
    
433
    /**
434
     * Selects a node relative to the currently selected node.
435
     * @param direction the direction to move.
436
     *                  directions:
437
     *                      UP - Navigates through parents
438
     *                      DOWN - Navigates through children
439
     *                      NEXT - Navigates to next sibling
440
     *                      PREVIOUS - Navigates to previous sibling
441
     * @param distance the distance to move
442
     * @param clickCount the click count to select the new cell.
443
     * @throws StepExecutionException if any error occurs
444
     */
445
    public void gdMove(String direction, int distance, int clickCount) 
446
        throws StepExecutionException {
447
448
        if (getColumnCount() > 0) {
449
            TreeOperationContext context;
450
            int mouseColumn = getMouseColumn();
451
            
452
            if (mouseColumn == -1) {
453
                context = 
454
                    new TableTreeOperationContext(
455
                        getEventThreadQueuer(), getRobot(), getTree());
456
            } else {
457
                context = 
458
                    new TableTreeOperationContext(
459
                        getEventThreadQueuer(), getRobot(), getTree(), 
460
                        mouseColumn);
461
            }
462
            
463
            TreeItem selectedNode = (TreeItem) getSelectedNode(context);
464
            
465
            TreeNodeOperation selectOp = 
466
                new SelectTreeNodeOperation(
467
                        ClickOptions.create().setClickCount(clickCount));
468
            TreeNodeOperationConstraint constraint = 
469
                new TreeNodeOperationConstraint();
470
            
471
            if (CompSystemConstants
472
                    .TREE_MOVE_UP.equalsIgnoreCase(direction)) {
473
                AbstractTreeNodeTraverser traverser = 
474
                    new ParentTraverser(context, distance, constraint);
475
                traverser.traversePath(selectOp, selectedNode);
476
            } else if (CompSystemConstants
477
                    .TREE_MOVE_DOWN.equalsIgnoreCase(direction)) {
478
                TreeNodeOperation expandOp = 
479
                    new ExpandCollapseTreeNodeOperation(false);
480
                AbstractTreeNodeTraverser expandTraverser = 
481
                    new ChildTraverser(context, distance - 1);
482
                expandTraverser.traversePath(expandOp, selectedNode);
483
                
484
                AbstractTreeNodeTraverser selectTraverser = 
485
                    new ChildTraverser(context, distance, constraint);
486
                selectTraverser.traversePath(selectOp, selectedNode);
487
                
488
            } else if (CompSystemConstants
489
                    .TREE_MOVE_NEXT.equalsIgnoreCase(direction)) {
490
                // Look through siblings
491
                AbstractTreeNodeTraverser traverser = 
492
                    new SiblingTraverser(context, distance, true, constraint);
493
                traverser.traversePath(selectOp, selectedNode);
494
                
495
            } else if (CompSystemConstants
496
                    .TREE_MOVE_PREVIOUS.equalsIgnoreCase(direction)) {
497
                // Look through siblings
498
                AbstractTreeNodeTraverser traverser = 
499
                    new SiblingTraverser(context, distance, false, constraint);
500
                traverser.traversePath(selectOp, selectedNode);
501
            }
502
        } else {
503
            super.gdMove(direction, distance, clickCount);
504
        }
505
    }
506
507
        /**
508
         * Runs in the GUI thread.
509
         * @return the number of columns in the receivers component.
510
         */
511
    private int getColumnCount() {
512
        return ((Integer)getEventThreadQueuer().invokeAndWait(
513
                    "getColumnCount", new IRunnable() { //$NON-NLS-1$
514
515
                        public Object run() throws StepExecutionException {
516
                            return new Integer(getTree().getColumnCount());
517
                        }
518
                
519
                    })).intValue();
520
    }
521
    
522
    /**
523
     * Selects the item at the end of the <code>treepath</code> at column 
524
     * <code>column</code>.
525
     * 
526
     * @param pathType whether the path is relative or absolute
527
     * @param preAscend
528
     *            Relative traversals will start this many parent nodes 
529
     *            above the current node. Absolute traversals ignore this 
530
     *            parameter.
531
     * @param treePath The tree path.
532
     * @param operator
533
     *  If regular expressions are used to match the tree path
534
     * @param clickCount the click count
535
     * @param column the column of the item to select
536
     * @param button what mouse button should be used
537
     * @throws StepExecutionException If the tree path is invalid, if the
538
     * double-click to expand the node fails, or if the selection is invalid.
539
     */
540
    public void gdSelect(String pathType, int preAscend, String treePath, 
541
                         String operator, int clickCount, int column,
542
                         int button)
543
        throws StepExecutionException {
544
        final int implCol = IndexConverter.toImplementationIndex(column);
545
        checkColumnIndex(implCol);
546
        
547
        selectByPath(pathType, preAscend, 
548
            createStringNodePath(splitTextTreePath(treePath), operator), 
549
            ClickOptions.create()
550
                .setClickCount(clickCount)
551
                .setMouseButton(button), implCol);
552
553
    }
554
    /**
555
     * Selects the last node of the path given by <code>indexPath</code>
556
     * at column <code>column</code>.
557
     * 
558
     * @param pathType whether the path is relative or absolute
559
     * @param preAscend
560
     *            Relative traversals will start this many parent nodes 
561
     *            above the current node. Absolute traversals ignore this 
562
     *            parameter.
563
     * @param indexPath the index path
564
     * @param clickCount the number of times to click
565
     * @param column the column of the item to select
566
     * @param button what mouse button should be used
567
     * @throws StepExecutionException if <code>indexPath</code> is not a valid
568
     * path
569
     */
570
    public void gdSelectByIndices(String pathType, int preAscend, 
571
                                  String indexPath, int clickCount, int column,
572
                                  int button)
573
        throws StepExecutionException {
574
        final int implCol = IndexConverter.toImplementationIndex(column);
575
        checkColumnIndex(implCol);
576
577
        selectByPath(pathType, preAscend, 
578
            createIndexNodePath(splitIndexTreePath(indexPath)),
579
                ClickOptions.create()
580
                    .setClickCount(clickCount)
581
                    .setMouseButton(button), implCol);
582
    }
583
    
584
    /**
585
     * Verifies whether the first selection in the tree has a rendered text at 
586
     * column <code>column</code> that is equal to <code>pattern</code>.
587
     * 
588
     * @param pattern The pattern
589
     * @param column
590
     *            The column containing the text to verify
591
     * @throws StepExecutionException If no node is selected or the verification fails.
592
     */
593
    public void gdVerifySelectedValue(String pattern, int column)
594
        throws StepExecutionException {
595
596
        gdVerifySelectedValue(pattern, MatchUtil.DEFAULT_OPERATOR, column);
597
    }
598
    /**
599
     * Verifies if the selected node underneath <code>treePath</code> at column
600
     * <code>column</code> has a rendered text which is equal to 
601
     * <code>selection</code>.
602
     * 
603
     * @param pattern the pattern
604
     * @param operator
605
     *            The operator to use when comparing the expected and 
606
     *            actual values.
607
     * @param column
608
     *            The column containing the text to verify
609
     * @throws StepExecutionException If there is no tree node selected, the tree path contains no
610
     *             selection or the verification fails
611
     */
612
    public void gdVerifySelectedValue(String pattern, String operator, 
613
        int column) throws StepExecutionException {
614
        
615
        final int implCol = IndexConverter.toImplementationIndex(column);
616
        checkColumnIndex(implCol);
617
618
        TableTreeOperationContext context = new TableTreeOperationContext(
619
            getEventThreadQueuer(), getRobot(), getTree(), implCol);
620
621
        String text = context.getNodeTextAtColumn(context.getSelectedNode());
622
        
623
        Verifier.match(text, pattern, operator);
624
625
    }
626
    
627
    /**
628
     * 
629
     * @param index The 0-based column index to check.
630
     * @throws StepExecutionException if the column index is invalid.
631
     */
632
    private void checkColumnIndex(final int index) 
633
        throws StepExecutionException {
634
       
635
        int numColumns = ((Integer)getEventThreadQueuer().invokeAndWait(
636
                "checkColumnIndex",  //$NON-NLS-1$
637
                new IRunnable() {
638
639
                    public Object run() {
640
                        return new Integer(getTree().getColumnCount());
641
                    }
642
            
643
                })).intValue();
644
645
        if ((index < 0 || index >= numColumns) && index != 0) {
646
            throw new StepExecutionException("Invalid column: " //$NON-NLS-1$
647
                + IndexConverter.toUserIndex(index), 
648
                EventFactory.createActionError(
649
                    TestErrorEvent.INVALID_INDEX));
650
        }
651
    }
652
    
653
    /**
654
     * @param pathType pathType
655
     * @param preAscend
656
     *            Relative traversals will start this many parent nodes 
657
     *            above the current node. Absolute traversals ignore this 
658
     *            parameter.
659
     * @param objectPath objectPath
660
     * @param co the click options to use
661
     * @param column the column
662
     */
663
    private void selectByPath(String pathType, int preAscend, 
664
            INodePath objectPath, ClickOptions co, int column) {
665
666
        TreeNodeOperation expOp = 
667
            new ExpandCollapseTreeNodeOperation(false);
668
        TreeNodeOperation selectOp = 
669
            new SelectTreeNodeOperation(co);
670
        INodePath subPath = objectPath.subPath(0, objectPath.getLength() - 1);
671
672
        traverseTreeByPath(subPath, pathType, preAscend, expOp);
673
        traverseLastElementByPath(
674
            objectPath, pathType, preAscend, selectOp, column);
675
            
676
    }
677
    
678
    /**
679
     * Traverses the tree by searching for the nodes in the tree
680
     * path entry and calling the given operation on the last element in the path.
681
     * @param treePath The tree path.
682
     * @param pathType For example, "relative" or "absolute".
683
     * @param preAscend
684
     *            Relative traversals will start this many parent nodes 
685
     *            above the current node. Absolute traversals ignore this 
686
     *            parameter.
687
     * @param operation The tree node operation.
688
     * @param column The target column for the operation.
689
     * @throws StepExecutionException If the path traversion fails.
690
     */
691
    private void traverseLastElementByPath(INodePath treePath, 
692
            String pathType, int preAscend, TreeNodeOperation operation,
693
            int column) 
694
        throws StepExecutionException {
695
696
        Validate.notNull(treePath);
697
        Validate.notNull(operation);
698
699
        TableTreeOperationContext context = new TableTreeOperationContext(
700
                getEventThreadQueuer(), getRobot(), getTree(), column);
701
        TreeItem startNode = (TreeItem) getStartNode(pathType,
702
                preAscend, context);
703
704
        AbstractTreeNodeTraverser traverser = new PathBasedTraverser(
705
                context, treePath, new TreeNodeOperationConstraint());
706
        traverser.traversePath(operation, startNode);
707
    }
708
    
709
    /**
710
     * {@inheritDoc}
711
     */
712
    public String gdStoreValueAtMousePosition(String variable) {
713
        TreeItem itemAtMousePosition = (TreeItem) getNodeAtMousePosition();
714
        int column = getMouseColumn();
715
        AbstractTreeOperationContext context;
716
        
717
        if (column != -1) {
718
            context = 
719
                new TableTreeOperationContext(
720
                    getEventThreadQueuer(), getRobot(), getTree(), column);
721
        } else {
722
            context =
723
                new TableTreeOperationContext(
724
                    getEventThreadQueuer(), getRobot(), getTree());
725
        }
726
727
        return context.getRenderedText(itemAtMousePosition);
728
    }
729
    
730
    /**
731
     * Selects Checkbox of last node of the path given by <code>treepath</code>.
732
     * 
733
     * @param pathType whether the path is relative or absolute
734
     * @param preAscend
735
     *            Relative traversals will start this many parent nodes 
736
     *            above the current node. Absolute traversals ignore this 
737
     *            parameter.
738
     * @param treePath The tree path.
739
     * @param operator
740
     *  If regular expressions are used to match the tree path
741
     * @throws StepExecutionException If the tree path is invalid, if the
742
     * double-click to expand the node fails, or if the selection is invalid.
743
     */
744
    public void gdToggleCheckbox(String pathType, int preAscend, String
745
            treePath, String operator)
746
        throws StepExecutionException {
747
        toggleCheckBoxByPath(pathType, preAscend, 
748
                createStringNodePath(splitTextTreePath(treePath), operator));
749
    }
750
    
751
    /**
752
     * Selects Checkbox of last node of the path given by <code>indexPath</code>
753
     * @param pathType whether the path is relative or absolute
754
     * @param preAscend
755
     *            Relative traversals will start this many parent nodes 
756
     *            above the current node. Absolute traversals ignore this 
757
     *            parameter.
758
     * @param indexPath the index path
759
     * @throws StepExecutionException if <code>indexPath</code> is not a valid
760
     * path
761
     */
762
    public void gdToggleCheckboxByIndices(String pathType, int preAscend, 
763
                    String indexPath)
764
        throws StepExecutionException {
765
    
766
        toggleCheckBoxByPath(pathType, preAscend,
767
                createIndexNodePath(splitIndexTreePath(indexPath)));
768
    }
769
    
770
    /**
771
     * Verify Selection of checkbox of the node at the end of the <code>treepath</code>.
772
     * 
773
     * @param pathType whether the path is relative or absolute
774
     * @param preAscend
775
     *            Relative traversals will start this many parent nodes 
776
     *            above the current node. Absolute traversals ignore this 
777
     *            parameter.
778
     * @param treePath The tree path.
779
     * @param operator
780
     *  If regular expressions are used to match the tree path
781
     * @param checked true if checkbox of tree node is selected, false otherwise
782
     * @throws StepExecutionException If the tree path is invalid, if the
783
     * double-click to expand the node fails, or if the selection is invalid.
784
     */
785
    public void gdVerifyCheckbox(String pathType, int preAscend, String
786
            treePath, String operator, boolean checked)
787
        throws StepExecutionException {
788
        verifyCheckBoxByPath(pathType, preAscend, 
789
                createStringNodePath(splitTextTreePath(treePath), operator), 
790
                checked);    
791
    }
792
    
793
    /**
794
     * Verify Selection of checkbox of last node of the path given by <code>indexPath</code>
795
     * @param pathType whether the path is relative or absolute
796
     * @param preAscend
797
     *            Relative traversals will start this many parent nodes 
798
     *            above the current node. Absolute traversals ignore this 
799
     *            parameter.
800
     * @param indexPath the index path
801
     * @param checked true if checkbox of tree node is selected, false otherwise
802
     * @throws StepExecutionException if <code>indexPath</code> is not a valid
803
     * path
804
     */
805
    public void gdVerifyCheckboxByIndices(String pathType, int preAscend, 
806
                    String indexPath, boolean checked)
807
        throws StepExecutionException {
808
    
809
        verifyCheckBoxByPath(pathType, preAscend,
810
                createIndexNodePath(splitIndexTreePath(indexPath)), 
811
                    checked);    
812
    }
813
    
814
    /**
815
     * Verifies whether the checkbox of the first selection in the tree is checked
816
     * 
817
     * @param checked true if checkbox of node is selected, false otherwise
818
     * @throws StepExecutionException If no node is selected or the verification fails.
819
     */
820
    public void gdVerifySelectedCheckbox(boolean checked)
821
        throws StepExecutionException {        
822
        Boolean checkSelected = ((Boolean)getEventThreadQueuer().invokeAndWait(
823
                "gdVerifyTreeCheckbox", new IRunnable() { //$NON-NLS-1$
824
                    public Object run() {             
825
                        TreeItem node = getTree().getSelection()[0];
826
                        return new Boolean(node.getChecked());
827
                    }            
828
                }));       
829
        
830
        Verifier.equals(checked, checkSelected.booleanValue());
831
    }
832
833
    /**
834
     * @param pathType pathType
835
     * @param preAscend
836
     *            Relative traversals will start this many parent nodes 
837
     *            above the current node. Absolute traversals ignore this 
838
     *            parameter.
839
     * @param objectPath objectPath
840
     * @param checked true if Checkbox should be enabled, false otherwise
841
     */
842
    private void verifyCheckBoxByPath(String pathType, int preAscend, 
843
            INodePath objectPath, final boolean checked) {
844
845
        TreeNodeOperation expOp = 
846
            new ExpandCollapseTreeNodeOperation(false);
847
        TreeOperationContext context = new TreeOperationContext(
848
                getEventThreadQueuer(), getRobot(), getTree());
849
        TreeNodeOperation checkboxOp = new VerifyCheckboxOperation(
850
                checked, context);
851
        INodePath subPath = objectPath.subPath(0, objectPath.getLength() - 1);
852
        
853
        traverseTreeByPath(subPath, pathType, preAscend, expOp);
854
        traverseLastElementByPath(objectPath, pathType, preAscend, checkboxOp);
855
    }
856
    
857
    /**
858
     * @param pathType pathType
859
     * @param preAscend
860
     *            Relative traversals will start this many parent nodes 
861
     *            above the current node. Absolute traversals ignore this 
862
     *            parameter.
863
     * @param objectPath objectPath
864
     */
865
    private void toggleCheckBoxByPath(String pathType, int preAscend, 
866
            INodePath objectPath) {
867
868
        TreeNodeOperation expOp = 
869
            new ExpandCollapseTreeNodeOperation(false);
870
        TreeOperationContext context = new TreeOperationContext(
871
                getEventThreadQueuer(), getRobot(), getTree());
872
        TreeNodeOperation selCheckboxOp = new ToggleCheckboxOperation(context);
873
        INodePath subPath = objectPath.subPath(0, objectPath.getLength() - 1);
874
        
875
        traverseTreeByPath(subPath, pathType, preAscend, expOp);
876
        traverseLastElementByPath(objectPath, pathType, preAscend,
877
                selCheckboxOp);      
878
    }
879
    
880
    /**
881
     * {@inheritDoc}
882
     */
883
    public void gdClick(int count, int button) {
884
        super.gdClick(count, button);
885
        
886
    }
887
    
888
889
    
890
    /**
891
     * Forces all outstanding paint requests for the receiver's component's 
892
     * display to be processed before this method returns.
893
     * 
894
     * @see Display#update()
895
     */
896
    protected void waitForDisplayUpdate() {
897
        ((Control)getComponent().getRealComponent())
898
        .getDisplay().syncExec(new Runnable() {
899
            public void run() {
900
                ((Control)getComponent()
901
                        .getRealComponent()).getDisplay().update();
902
            }
903
        });
904
    }
905
    
906
    /**
907
     * Presses or releases the given modifier.
908
     * @param modifier the modifier.
909
     * @param press if true, the modifier will be pressed.
910
     * if false, the modifier will be released.
911
     */
912
    public void pressOrReleaseModifiers(String modifier, boolean press) {
913
        final IRobot robot = getRobot();
914
        final StringTokenizer modTok = new StringTokenizer(
915
                KeyStrokeUtil.getModifierString(modifier), " "); //$NON-NLS-1$
916
        while (modTok.hasMoreTokens()) {
917
            final String mod = modTok.nextToken();
918
            final int keyCode = KeyCodeConverter.getKeyCode(mod);
919
            if (press) {
920
                robot.keyPress(null, keyCode);
921
            } else {
922
                robot.keyRelease(null, keyCode);
923
            }
924
        }
925
    }
926
927
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/ButtonAdapter.java (+70 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.IRunnable;
14
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IButtonAdapter;
15
import org.eclipse.swt.widgets.Button;
16
/**
17
 * Implements the Button interface for adapting a <code>SWT.Button</code>
18
 * 
19
 *  @author BREDEX GmbH
20
 */
21
public class ButtonAdapter extends WidgetAdapter implements IButtonAdapter {
22
    
23
    /** the Button from the AUT */
24
    private Button m_button;
25
    
26
    /**
27
     * 
28
     * @param objectToAdapt graphics component which will be adapted
29
     */
30
    public ButtonAdapter(Object objectToAdapt) {
31
        super(objectToAdapt);
32
        m_button = (Button) objectToAdapt;
33
    }
34
35
    /**
36
     * {@inheritDoc}
37
     */
38
    public String getText() {
39
        
40
        return (String)getEventThreadQueuer()
41
                .invokeAndWait("getText", new IRunnable() { //$NON-NLS-1$
42
                    public Object run() {
43
                        return m_button.getText(); // see findBugs;
44
                    }
45
                });
46
    }
47
48
    /**
49
     * {@inheritDoc}
50
     */
51
    public boolean isSelected() {
52
        Boolean actual = (Boolean)getEventThreadQueuer()
53
                .invokeAndWait("isSelected", new IRunnable() { //$NON-NLS-1$
54
                    public Object run() {
55
                        return m_button.getSelection() 
56
                            ? Boolean.TRUE : Boolean.FALSE; // see findBugs;
57
                    }
58
                });
59
        return actual.booleanValue();
60
    }
61
    
62
    /**
63
     * {@inheritDoc}
64
     * 
65
     */
66
    public String readValue(String variable) {
67
        
68
        return getText();
69
    }
70
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/MenuAdapter.java (+121 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.IEventThreadQueuer;
14
import org.eclipse.jubula.rc.common.driver.IRobot;
15
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
16
import org.eclipse.jubula.rc.common.driver.IRunnable;
17
import org.eclipse.jubula.rc.common.exception.RobotException;
18
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
19
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
20
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
21
import org.eclipse.swt.widgets.Menu;
22
import org.eclipse.swt.widgets.MenuItem;
23
24
/**
25
 * Implements the Menu interface for adapting a <code>SWT.Menu</code>
26
 * 
27
 * @author BREDEX GmbH
28
 */
29
public class MenuAdapter implements IMenuAdapter {
30
    /** the Menu from the AUT */
31
    private Menu m_menu;
32
    
33
    /** the RobotFactory from the AUT */
34
    private IRobotFactory m_robotFactory;
35
36
    /**
37
     * 
38
     * @param component graphics component which will be adapted
39
     */
40
    public MenuAdapter(Object component) {
41
        m_menu = (Menu) component;
42
    }
43
44
    /**
45
     * Gets the Robot factory. The factory is created once per instance.
46
     * 
47
     * @return The Robot factory.
48
     */
49
    protected IRobotFactory getRobotFactory() {
50
        if (m_robotFactory == null) {
51
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
52
        }
53
        return m_robotFactory;
54
    }
55
56
    /**
57
     * Gets the IEventThreadQueuer.
58
     * 
59
     * @return The Robot
60
     * @throws RobotException
61
     *             If the Robot cannot be created.
62
     */
63
    protected IRobot getRobot() throws RobotException {
64
        return getRobotFactory().getRobot();
65
    }
66
67
    /**
68
     * @return The event thread queuer.
69
     */
70
    public IEventThreadQueuer getEventThreadQueuer() {
71
        return getRobotFactory().getEventThreadQueuer();
72
    }
73
    /**
74
     * {@inheritDoc}
75
     */   
76
    public Object getRealComponent() {
77
        return m_menu;
78
    }
79
    /**
80
     * {@inheritDoc}
81
     */  
82
    public void setComponent(Object element) {
83
        m_menu = (Menu) element;
84
        
85
    }
86
    /**
87
     * {@inheritDoc}
88
     */
89
    public IMenuItemAdapter[] getItems() {
90
        
91
        MenuItem[] items =
92
                (MenuItem[]) getEventThreadQueuer().invokeAndWait(
93
                        "getItems", new IRunnable() { //$NON-NLS-1$
94
                            public Object run() {
95
                                return m_menu.getItems();
96
                            }
97
                        });
98
        IMenuItemAdapter[] adapters = new IMenuItemAdapter[items.length];
99
        for (int i = 0; i < items.length; i++) {
100
            IMenuItemAdapter menuItem = new MenuItemAdapter(items[i]);
101
            adapters[i] = menuItem;
102
        }
103
        return adapters;
104
    }
105
    /**
106
     * {@inheritDoc}
107
     */
108
    public int getItemCount() {
109
        Integer itemCount = (Integer) getEventThreadQueuer().invokeAndWait(
110
                "getItemCount", new IRunnable() { //$NON-NLS-1$
111
                    public Object run() {
112
                        return new Integer(m_menu.getItemCount());
113
                    }
114
                });
115
        return itemCount.intValue();
116
    }
117
118
119
    
120
121
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/MenuItemAdapter.java (+548 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.IEventMatcher;
15
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
16
import org.eclipse.jubula.rc.common.driver.IRobot;
17
import org.eclipse.jubula.rc.common.driver.IRobotEventConfirmer;
18
import org.eclipse.jubula.rc.common.driver.IRobotEventInterceptor;
19
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
20
import org.eclipse.jubula.rc.common.driver.IRunnable;
21
import org.eclipse.jubula.rc.common.driver.InterceptorOptions;
22
import org.eclipse.jubula.rc.common.exception.RobotException;
23
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
24
import org.eclipse.jubula.rc.common.listener.EventLock;
25
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuAdapter;
26
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IMenuItemAdapter;
27
import org.eclipse.jubula.rc.swt.driver.EventThreadQueuerSwtImpl;
28
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
29
import org.eclipse.jubula.rc.swt.driver.RobotFactorySwtImpl;
30
import org.eclipse.jubula.rc.swt.driver.SelectionSwtEventMatcher;
31
import org.eclipse.jubula.rc.swt.driver.ShowSwtEventMatcher;
32
import org.eclipse.jubula.rc.swt.implclasses.EventListener;
33
import org.eclipse.jubula.rc.swt.implclasses.EventListener.Condition;
34
import org.eclipse.jubula.rc.swt.utils.SwtUtils;
35
import org.eclipse.jubula.tools.constants.TimeoutConstants;
36
import org.eclipse.jubula.tools.i18n.I18n;
37
import org.eclipse.jubula.tools.objects.event.EventFactory;
38
import org.eclipse.swt.SWT;
39
import org.eclipse.swt.graphics.Rectangle;
40
import org.eclipse.swt.widgets.Display;
41
import org.eclipse.swt.widgets.Event;
42
import org.eclipse.swt.widgets.Menu;
43
import org.eclipse.swt.widgets.MenuItem;
44
45
/**
46
 * Implements the MenuItem interface for adapting a <code>SWT.MenuItem</code>
47
 * 
48
 *  @author BREDEX GmbH
49
 */
50
public class MenuItemAdapter implements IMenuItemAdapter {
51
52
    /** the MenuItem from the AUT*/
53
    private MenuItem m_menuItem;
54
    
55
56
    /** the RobotFactory from the AUT */
57
    private IRobotFactory m_robotFactory;
58
59
    /**
60
     * 
61
     * @param component graphics component which will be adapted
62
     */
63
    public MenuItemAdapter(Object component) {
64
        super();
65
        m_menuItem = (MenuItem) component;
66
    }
67
    
68
    /**
69
     * Gets the Robot factory. The factory is created once per instance.
70
     * 
71
     * @return The Robot factory.
72
     */
73
    protected IRobotFactory getRobotFactory() {
74
        if (m_robotFactory == null) {
75
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
76
        }
77
        return m_robotFactory;
78
    }
79
80
    /**
81
     * Gets the IEventThreadQueuer.
82
     * 
83
     * @return The Robot
84
     * @throws RobotException
85
     *             If the Robot cannot be created.
86
     */
87
    protected IRobot getRobot() throws RobotException {
88
        return getRobotFactory().getRobot();
89
    }
90
91
    /**
92
     * @return The event thread queuer.
93
     */
94
    public IEventThreadQueuer getEventThreadQueuer() {
95
        return getRobotFactory().getEventThreadQueuer();
96
    }
97
    
98
    
99
    /**
100
     * {@inheritDoc}
101
     */
102
    public Object getRealComponent() {
103
       
104
        return m_menuItem;
105
    }
106
    /**
107
     * {@inheritDoc}
108
     */
109
    public void setComponent(Object element) {
110
        m_menuItem = (MenuItem) element;
111
112
    }
113
    /**
114
     * {@inheritDoc}
115
     */
116
    public String getText() {
117
        return (String) getEventThreadQueuer().invokeAndWait(
118
                "getText", new IRunnable() { //$NON-NLS-1$
119
                    public Object run() {
120
                        return m_menuItem.getText();
121
                    }
122
                });
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128
    public boolean isEnabled() {
129
        final Boolean isEnabled = (Boolean) getEventThreadQueuer()
130
                .invokeAndWait("isEnabled", new IRunnable() { //$NON-NLS-1$
131
                        public Object run() throws StepExecutionException {
132
                            return m_menuItem.isEnabled() ? Boolean.TRUE
133
                                        : Boolean.FALSE;
134
                        }
135
                    });
136
        return isEnabled.booleanValue();
137
138
    }
139
    /**
140
     * {@inheritDoc}
141
     */
142
    public boolean isExisting() {
143
        if (m_menuItem != null) {
144
            return true;
145
        }
146
        return false;
147
    }
148
    /**
149
     * {@inheritDoc}
150
     */
151
    public boolean isSelected() {
152
        final Boolean isSelected = (Boolean)getEventThreadQueuer()
153
                .invokeAndWait("isSelected", new IRunnable() { //$NON-NLS-1$
154
                    public Object run() throws StepExecutionException {
155
                        return m_menuItem.getSelection() 
156
                            ? Boolean.TRUE : Boolean.FALSE;
157
                    }
158
                });
159
        return isSelected.booleanValue();
160
    }
161
162
    /**
163
     * @return -
164
     */
165
    public boolean isShowing() {
166
167
        return true; //FIXME is here a Showing implementation?
168
    }
169
    /**
170
     * {@inheritDoc}
171
     */
172
    public IMenuAdapter getMenu() {
173
        
174
        Menu menu =
175
                (Menu) getEventThreadQueuer().invokeAndWait(
176
                        "getItems", new IRunnable() { //$NON-NLS-1$
177
                            public Object run() {
178
                                return m_menuItem.getMenu();
179
                            }
180
                        });
181
        
182
        
183
        return new MenuAdapter(menu);
184
    }
185
    /**
186
     * {@inheritDoc}
187
     */
188
    public boolean hasSubMenu() {
189
        
190
191
        
192
        if (getMenu() != null) {
193
            return true;
194
        }
195
        return false;
196
    }
197
198
199
    /**
200
     * Checks whether the given menu item is a separator. 
201
     * This method runs in the GUI thread.
202
     * @return <code>true</code> if <code>menuItem</code> is a separator item.
203
     *         Otherwise <code>false</code>.
204
     */
205
    public boolean isSeparator() {
206
        final Boolean isSeparator = (Boolean)getEventThreadQueuer()
207
                .invokeAndWait(
208
                ".isSeparator", new IRunnable() { //$NON-NLS-1$
209
                    public Object run() throws StepExecutionException {
210
                        return (m_menuItem.getStyle() & SWT.SEPARATOR) != 0 
211
                                            ? Boolean.TRUE : Boolean.FALSE;
212
                    }
213
                });
214
        return isSeparator.booleanValue();
215
    }
216
    
217
    /**
218
     * {@inheritDoc}
219
     */
220
    public void selectMenuItem() {
221
        Rectangle bounds = getMenuItemBounds();
222
        Rectangle nullBounds = new Rectangle(0, 0, 0, 0);
223
        
224
        if (bounds.equals(nullBounds)) {
225
            selectProgramatically();
226
        } else {
227
            clickMenuItem(getRobot(), m_menuItem, 1);
228
        }
229
        
230
    }
231
    
232
    /**
233
     * {@inheritDoc}
234
     */
235
    public IMenuAdapter openSubMenu() {
236
        final MenuItem menuItem = m_menuItem;
237
        MenuShownCondition cond = new MenuShownCondition(menuItem);
238
        EventLock lock = new EventLock();
239
        final EventListener listener = new EventListener(lock, cond);
240
        final Display d = menuItem.getDisplay();
241
        final IEventThreadQueuer queuer = new EventThreadQueuerSwtImpl();
242
        
243
        queuer.invokeAndWait("addMenuShownListeners", new IRunnable() { //$NON-NLS-1$
244
            public Object run() {
245
                d.addFilter(SWT.Show, listener);
246
                
247
                return null;
248
            }
249
        });
250
        try {
251
            // Menu bar items require a click in order to open the submenu.
252
            // Cascading menus are opened with a mouse-over and 
253
            // may be closed by a click.
254
            int clickCount = isMenuBarItem(menuItem) ? 1 : 0;
255
            Menu menu = (Menu)getEventThreadQueuer().invokeAndWait(
256
                    "openSubMenu", new IRunnable() { //$NON-NLS-1$
257
                        public Object run() {
258
                            return menuItem.getMenu();
259
                        }            
260
                    });
261
            Rectangle bounds = getMenuItemBounds();
262
            Rectangle nullBounds = new Rectangle(0, 0, 0, 0);            
263
            if (bounds.equals(nullBounds)) {                               
264
                openSubMenuProgramatically(menu);
265
            } else {
266
                clickMenuItem(getRobot(), menuItem, clickCount);
267
            }
268
            synchronized (lock) {
269
                long timeout = TimeoutConstants.SERVER_TIMEOUT_WAIT_FOR_POPUP;
270
                long done = System.currentTimeMillis() + timeout; 
271
                long now;                
272
                while (!lock.isReleased() && timeout > 0) {
273
                    lock.wait(timeout);
274
                    now = System.currentTimeMillis();
275
                    timeout = done - now;
276
                }
277
            } 
278
        } catch (InterruptedException e) { // ignore
279
        } finally {
280
            queuer.invokeAndWait("removeMenuShownListeners", new IRunnable() { //$NON-NLS-1$
281
                public Object run() {
282
                    d.removeFilter(SWT.Show, listener);
283
                    
284
                    return null;
285
                }
286
            });
287
        }
288
        if (!lock.isReleased()) {
289
            String itemText = (String)getEventThreadQueuer().invokeAndWait(
290
                    "getItemText", new IRunnable() { //$NON-NLS-1$
291
292
                        public Object run() throws StepExecutionException {
293
                            if (menuItem != null && !menuItem.isDisposed()) {
294
                                return menuItem.getText();
295
                            }
296
                            return "unknown menu item"; //$NON-NLS-1$
297
                        }
298
                
299
                    });
300
            itemText = SwtUtils.removeMnemonics(itemText);
301
            throw new StepExecutionException(
302
                    I18n.getString("TestErrorEvent.MenuDidNotAppear",  //$NON-NLS-1$
303
                            new String [] {itemText}), 
304
                    EventFactory.createActionError(
305
                            "TestErrorEvent.MenuDidNotAppear", //$NON-NLS-1$ 
306
                            new String [] {itemText}));
307
        }        
308
        return new MenuAdapter(cond.getMenu());
309
    }
310
    
311
    /**
312
     * @param menuItem the menu item to check
313
     * @return <code>true</code> of the given menu item is part of a menu
314
     *         bar. Otherwise, <code>false</code>.
315
     */
316
    private boolean isMenuBarItem(final MenuItem menuItem) {
317
        return ((Boolean)getEventThreadQueuer().invokeAndWait(
318
                "isMenuBarItem", new IRunnable() { //$NON-NLS-1$
319
320
                    public Object run() throws StepExecutionException {
321
                        if (menuItem != null && !menuItem.isDisposed()) {
322
                            Menu parent = menuItem.getParent();
323
                            if (parent != null && !parent.isDisposed()) {
324
                                return (parent.getStyle() & SWT.BAR) != 0 
325
                                    ? Boolean.TRUE : Boolean.FALSE;
326
                            }
327
                        }
328
                        return Boolean.FALSE;
329
                    }
330
            
331
                })).booleanValue();
332
    }
333
    
334
    
335
    /**
336
     * Waits for a submenu to appear. Examples of submenus are cascading menus
337
     * and pulldown menus.
338
     *
339
     * @author BREDEX GmbH
340
     * @created Oct 30, 2008
341
     */
342
    public static class MenuShownCondition implements Condition {
343
        /** the menu that was shown */
344
        private Menu m_shownMenu = null;
345
346
        /** the parent item of the expected menu */
347
        private MenuItem m_parentItem;
348
349
        /**
350
         * Constructor
351
         *  
352
         * @param parentItem The parent item of the expected menu. This 
353
         *                   condition only matches if a menu with parent item
354
         *                   <code>parentItem</code> appears.
355
         */
356
        MenuShownCondition(MenuItem parentItem) {
357
            m_parentItem = parentItem;
358
        }
359
        
360
        /**
361
         * 
362
         * @return the menu that appeared
363
         */
364
        public Menu getMenu() {
365
            return m_shownMenu;
366
        }
367
        
368
        /**
369
         * 
370
         * {@inheritDoc}
371
         */
372
        public boolean isTrue(Event event) {
373
            if (event.type == SWT.Show && event.widget instanceof Menu
374
                    && ((Menu)(event.widget)).getParentItem() == m_parentItem) {
375
                m_shownMenu = (Menu)event.widget;
376
                return true;
377
            } 
378
            
379
            return false;
380
        }
381
    }
382
    
383
    /**
384
     * Clicks on a menu item
385
     * 
386
     * @param robot the robot
387
     * @param item the menu item
388
     * @param clickCount the number of times to click the menu item
389
     */
390
    public static void clickMenuItem(IRobot robot, final MenuItem item, 
391
            int clickCount) {
392
        // FIXME existiert so schon und kann man benutzen
393
//        if (!isMenuItemEnabled(item)) {
394
//            throw new StepExecutionException("menu item not enabled", //$NON-NLS-1$
395
//                    EventFactory.createActionError(
396
//                            TestErrorEvent.MENU_ITEM_NOT_ENABLED));
397
//        }
398
399
        robot.click(item, null, 
400
            ClickOptions.create()
401
                .setClickType(ClickOptions.ClickType.RELEASED)
402
                .setStepMovement(false).setClickCount(clickCount));
403
        
404
    }
405
    /**
406
     * 
407
     * @return bounds of MenuItem
408
     */
409
    public Rectangle getMenuItemBounds() {
410
        Rectangle bounds = (Rectangle)getEventThreadQueuer().invokeAndWait(
411
                "getMenuItemBounds", new IRunnable() { //$NON-NLS-1$
412
                    public Object run() {
413
                        return SwtUtils.getBounds(m_menuItem);
414
                    }            
415
                });        
416
        return bounds;
417
    }
418
    
419
    /**
420
     * open SubMenu programatically (for Mac OS)
421
     * @param menu the Menu
422
     */
423
    public void openSubMenuProgramatically(final Menu menu) {
424
//        if (!isMenuEnabled(menu)) {
425
//            throw new StepExecutionException("menu item not enabled", //$NON-NLS-1$
426
//                    EventFactory.createActionError(
427
//                            TestErrorEvent.MENU_ITEM_NOT_ENABLED));
428
//        }
429
        
430
        final InterceptorOptions options = new InterceptorOptions(
431
                new long[]{SWT.Show});
432
        final IEventMatcher matcher = 
433
            new ShowSwtEventMatcher();  
434
        RobotFactorySwtImpl robotSwt = new RobotFactorySwtImpl();
435
        IRobotEventInterceptor interceptor =
436
            robotSwt.getRobotEventInterceptor();
437
        final IRobotEventConfirmer confirmer = interceptor
438
            .intercept(options);
439
        
440
        final Event event = new Event();
441
        event.time = (int) System.currentTimeMillis();
442
        event.widget = menu;
443
        event.display = menu.getDisplay();
444
        event.type = SWT.Show;
445
        
446
        getEventThreadQueuer().invokeAndWait(
447
                "openSubMenuProgramatically", new IRunnable() { //$NON-NLS-1$
448
                    public Object run() {
449
                        
450
                        menu.notifyListeners(SWT.Show, event);
451
                        
452
                        return null;
453
                    }            
454
                });
455
456
        try {
457
            confirmer.waitToConfirm(menu, matcher);
458
        } catch (RobotException re) {
459
            final StringBuffer sb = new StringBuffer(
460
                "Robot exception occurred while clicking...\n"); //$NON-NLS-1$
461
//            logRobotException(menuItem, re, sb);
462
            sb.append("Component: "); //$NON-NLS-1$
463
464
            getEventThreadQueuer().invokeAndWait(
465
                    "getBounds", new IRunnable() { //$NON-NLS-1$
466
                        public Object run()
467
                            throws StepExecutionException {
468
                            sb.append(menu);
469
                            // Return value not used
470
                            return null;
471
                        }
472
                    });
473
//            log.error(sb.toString(), re);
474
            throw re;
475
        }
476
    }
477
    
478
    /**
479
     * select MenuItem programatically (for Mac OS)
480
     */
481
    public void selectProgramatically() {
482
//        FIXME must implement this check case
483
//        if (!isMenuItemEnabled(menuItem)) {
484
//            throw new StepExecutionException("menu item not enabled", //$NON-NLS-1$
485
//                    EventFactory.createActionError(
486
//                            TestErrorEvent.MENU_ITEM_NOT_ENABLED));
487
//        }
488
        final MenuItem menuItem = m_menuItem;
489
        final InterceptorOptions options = new InterceptorOptions(
490
                new long[]{SWT.Selection});
491
        final IEventMatcher matcher = 
492
            new SelectionSwtEventMatcher();        
493
        RobotFactorySwtImpl robotSwt = new RobotFactorySwtImpl();
494
        IRobotEventInterceptor interceptor =
495
            robotSwt.getRobotEventInterceptor();        
496
        final IRobotEventConfirmer confirmer = interceptor
497
            .intercept(options);
498
        
499
        final Event event = new Event();
500
        event.time = (int) System.currentTimeMillis();
501
        event.widget = menuItem;
502
        event.display = menuItem.getDisplay();
503
        event.type = SWT.Selection;
504
        
505
        getEventThreadQueuer().invokeLater(
506
                "selectProgramatically", new Runnable() { //$NON-NLS-1$
507
                    public void run() {  
508
                        //if menuitem is checkbox or radiobutton set Selection
509
                        if ((menuItem.getStyle() & SWT.CHECK) == 0
510
                                || (menuItem.getStyle() & SWT.RADIO) == 0) {
511
                            if (menuItem.getSelection()) {
512
                                menuItem.setSelection(false);
513
                            } else {
514
                                menuItem.setSelection(true);
515
                            }                            
516
                        }
517
518
                        menuItem.notifyListeners(SWT.Selection, event);
519
                        
520
                    }            
521
                });
522
523
        try {
524
            confirmer.waitToConfirm(menuItem, matcher);
525
        } catch (RobotException re) {
526
            final StringBuffer sb = new StringBuffer(
527
                "Robot exception occurred while clicking...\n"); //$NON-NLS-1$
528
            //logRobotException(menuItem, re, sb);
529
            sb.append("Component: "); //$NON-NLS-1$
530
531
            getEventThreadQueuer().invokeAndWait(
532
                "getBounds", new IRunnable() { //$NON-NLS-1$
533
                    public Object run()
534
                        throws StepExecutionException {
535
                        sb.append(menuItem);
536
                        // Return value not used
537
                        return null;
538
                    }
539
                });
540
//  FIXME LOG IS MISSING HERE
541
//            log.error(sb.toString(), re);
542
            throw re;
543
        }
544
    
545
    }
546
    
547
    
548
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TableAdapter.java (+526 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.awt.Rectangle;
14
15
import org.eclipse.jubula.rc.common.driver.ClickOptions;
16
import org.eclipse.jubula.rc.common.driver.IRunnable;
17
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
18
import org.eclipse.jubula.rc.common.implclasses.IndexConverter;
19
import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
20
import org.eclipse.jubula.rc.common.implclasses.table.Cell;
21
import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITableAdapter;
22
import org.eclipse.jubula.rc.swt.listener.TableSelectionTracker;
23
import org.eclipse.jubula.rc.swt.utils.SwtUtils;
24
import org.eclipse.jubula.tools.objects.event.EventFactory;
25
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
26
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.custom.TableCursor;
28
import org.eclipse.swt.graphics.FontMetrics;
29
import org.eclipse.swt.graphics.GC;
30
import org.eclipse.swt.graphics.Image;
31
import org.eclipse.swt.widgets.Control;
32
import org.eclipse.swt.widgets.Table;
33
import org.eclipse.swt.widgets.TableColumn;
34
import org.eclipse.swt.widgets.TableItem;
35
/**
36
 * Implements the Table interface for adapting a <code>SWT.Table</code>
37
 * 
38
 * @author BREDEX GmbH
39
 */
40
public class TableAdapter extends WidgetAdapter implements ITableAdapter {
41
    /**   */
42
    private Table m_table;
43
    
44
    /**
45
     * 
46
     * @param objectToAdapt graphics component which will be adapted
47
     */
48
    public TableAdapter(Object objectToAdapt) {
49
        super(objectToAdapt);
50
        m_table = (Table) objectToAdapt;
51
    }
52
53
    /** {@inheritDoc} */
54
    public int getColumnCount() {
55
        Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
56
                "getColumnCount", new IRunnable() { //$NON-NLS-1$
57
                    public Object run() {
58
                        return  new Integer(m_table.getColumnCount());
59
                    }
60
                });
61
        return returnvalue.intValue();
62
    }
63
64
    /** {@inheritDoc} */
65
    public int getRowCount() {
66
        Integer returnvalue = (Integer) getEventThreadQueuer().invokeAndWait(
67
                "getRowCount", new IRunnable() { //$NON-NLS-1$
68
                    public Object run() {
69
                        return new Integer(m_table.getItemCount());
70
                    }
71
                });
72
        return returnvalue.intValue();
73
    }
74
75
    /** {@inheritDoc} */
76
    public String getCellText(final int row, final int column) {
77
        String current = (String)getEventThreadQueuer().invokeAndWait("getCellText", //$NON-NLS-1$
78
                new IRunnable() {
79
                    public Object run() {
80
                        String value = m_table.getItem(row).getText(column);
81
//                        if (log.isDebugEnabled()) {
82
//                            log.debug("Getting cell text:"); //$NON-NLS-1$
83
//                            log.debug("Row, col: " + row + ", " + col); //$NON-NLS-1$ //$NON-NLS-2$
84
//                            log.debug("Value: " + value); //$NON-NLS-1$
85
//                        }
86
                        return value;
87
                    }
88
                });
89
        return current;
90
    }
91
92
    /** {@inheritDoc} */
93
    public String getColumnName(final int column) {
94
        String current = (String)getEventThreadQueuer().invokeAndWait("getColumnName", //$NON-NLS-1$
95
                new IRunnable() {
96
                    public Object run() {
97
                        String value = m_table.getColumn(column).getText();
98
                        return value;
99
                    }
100
                });
101
        return current;
102
    }
103
104
    /** {@inheritDoc} */
105
    public int getColumnFromString(final String col, final String operator) {
106
        int column = -2;
107
        try {
108
            int usrIdxCol = Integer.parseInt(col);
109
            if (usrIdxCol == 0) {
110
                usrIdxCol = usrIdxCol + 1;
111
            }
112
            column = IndexConverter.toImplementationIndex(
113
                    usrIdxCol);
114
        } catch (NumberFormatException nfe) {
115
            try {
116
                Boolean isVisible;
117
                isVisible = (Boolean)getEventThreadQueuer().invokeAndWait(
118
                        "getColumnFromString", //$NON-NLS-1$
119
                        new IRunnable() {
120
                            public Object run() {
121
                                return new Boolean(m_table.getHeaderVisible());
122
                            }
123
                        });  
124
                if (!(isVisible.booleanValue())) {
125
                    throw new StepExecutionException("No Header", //$NON-NLS-1$
126
                            EventFactory.createActionError(
127
                                TestErrorEvent.NO_HEADER));
128
                }
129
                
130
                Integer implCol;
131
                implCol = (Integer)getEventThreadQueuer().invokeAndWait(
132
                    "getColumnFromString", new IRunnable() { //$NON-NLS-1$
133
                        public Object run() throws StepExecutionException {
134
                            for (int i = 0; i < m_table.getColumnCount(); i++) {
135
                                TableColumn tblCol = m_table.getColumn(i);
136
                                if (MatchUtil.getInstance().match(
137
                                        tblCol.getText(), col, operator)) {
138
                                    return new Integer (i);
139
                                }
140
                            }
141
                            return new Integer (-2);
142
                        }
143
                    });                
144
                column = implCol.intValue();                
145
            } catch (IllegalArgumentException iae) {
146
                //do nothing here
147
            }
148
        }        
149
        return column;
150
    }
151
152
    /** {@inheritDoc} */
153
    public String getRowName(final int row) {
154
        String current = (String)getEventThreadQueuer().invokeAndWait("getRowName", //$NON-NLS-1$
155
                new IRunnable() {
156
                    public Object run() {
157
                        String value = m_table.getItem(row).getText();
158
                        return value;
159
                    }
160
                });
161
        return current;
162
    }
163
164
    /** {@inheritDoc} */
165
    public int getRowFromString(final String row, final String operator) {
166
        int rowInt = -2;        
167
        try {
168
            rowInt = IndexConverter.toImplementationIndex(
169
                    Integer.parseInt(row));                       
170
            if (rowInt == -1) {
171
                Boolean isVisible;
172
                isVisible = (Boolean)getEventThreadQueuer().invokeAndWait(
173
                        "getRowFromString", //$NON-NLS-1$
174
                        new IRunnable() {
175
                            public Object run() {
176
                                return new Boolean(m_table.getHeaderVisible());
177
                            }
178
                        }); 
179
                if (!(isVisible.booleanValue())) {
180
                    throw new StepExecutionException("Header not visible", //$NON-NLS-1$
181
                            EventFactory.createActionError(
182
                                TestErrorEvent.NO_HEADER));
183
                }                
184
            }
185
        } catch (NumberFormatException nfe) {
186
            Integer implRow;
187
            implRow = (Integer)getEventThreadQueuer().invokeAndWait(
188
                "getRowFromString", //$NON-NLS-1$
189
                new IRunnable() {
190
                    public Object run() throws StepExecutionException {
191
                        for (int i = 0; i < m_table.getItemCount(); i++) {
192
                            String cellTxt = getCellText(i, 0);
193
                            if (MatchUtil.getInstance().match(
194
                                    cellTxt, row, operator)) {
195
                                return new Integer(i);
196
                            }
197
                        }
198
                        return new Integer(-2);
199
                    }
200
                });
201
            rowInt = implRow.intValue();
202
        }        
203
        return rowInt;
204
    }
205
206
    /** {@inheritDoc} */
207
    public Rectangle getBounds() {
208
        Rectangle returnvalue = (Rectangle) getEventThreadQueuer()
209
                .invokeAndWait("getBounds", //$NON-NLS-1$
210
                    new IRunnable() {                     
211
                        public Object run() throws StepExecutionException {
212
                            return m_table.getBounds();
213
                        }
214
                    });
215
        
216
        return returnvalue;
217
    }
218
219
    /** {@inheritDoc} */
220
    public Rectangle getHeaderBounds(final int col) {
221
        Rectangle cellBounds;
222
        cellBounds = (Rectangle)getEventThreadQueuer().invokeAndWait(
223
            "getHeaderBounds", //$NON-NLS-1$
224
            new IRunnable() {
225
                public Object run() throws StepExecutionException {
226
                    org.eclipse.swt.graphics.Rectangle rect =
227
                            m_table.getItem(0).getBounds(col);
228
                    rect.y = m_table.getClientArea().y;
229
                    return new Rectangle(rect.x, rect.y, rect.width,
230
                            rect.height);
231
                }
232
            });
233
        return cellBounds;
234
    }
235
236
    /** {@inheritDoc} */
237
    public Cell getSelectedCell() throws StepExecutionException {
238
        Cell cell = (Cell) getEventThreadQueuer().invokeAndWait(
239
                "getSelectedSell", new IRunnable() {   //$NON-NLS-1$         
240
                    public Object run() throws StepExecutionException {
241
                        return TableSelectionTracker.getInstance()
242
                                .getSelectedCell(m_table);
243
                    }
244
                });
245
        return cell;
246
    } 
247
248
    /** {@inheritDoc} */
249
    public boolean isHeaderVisible() {
250
        Boolean isVisible;
251
        isVisible = (Boolean)getEventThreadQueuer().invokeAndWait(
252
                "isHeaderVisible", //$NON-NLS-1$
253
                new IRunnable() {
254
                    public Object run() {
255
                        return new Boolean(m_table.getHeaderVisible());
256
                    }
257
                });
258
        return isVisible.booleanValue();
259
    }
260
261
    /** {@inheritDoc} */
262
    public boolean isCellEditable(final int row, final int col) {
263
        final Control cellEditor = (Control) 
264
                activateEditor(new Cell(row, col));
265
        boolean isEditable = ((Boolean)getEventThreadQueuer().invokeAndWait(
266
                "isCellEditable", //$NON-NLS-1$
267
                new IRunnable() {
268
                    public Object run() {
269
270
                        return isEditable(cellEditor) 
271
                            ? Boolean.TRUE : Boolean.FALSE;
272
                    }
273
                })).booleanValue();
274
        return isEditable;
275
    }
276
277
    /** {@inheritDoc} */
278
    public boolean hasCellSelection() {
279
        TableItem[] selItems = (TableItem[])getEventThreadQueuer()
280
                .invokeAndWait("hasCellSelection", //$NON-NLS-1$
281
                    new IRunnable() {
282
                        public Object run() {
283
                            return m_table.getSelection();
284
                        }
285
                    });
286
        return selItems.length > 0;
287
    }
288
    
289
    /**
290
     * {@inheritDoc}
291
     */
292
    public Rectangle scrollCellToVisible(final int row, final int col)
293
        throws StepExecutionException {
294
        final Table table = m_table;
295
        getEventThreadQueuer().invokeAndWait("scrollCellToVisible", //$NON-NLS-1$
296
                new IRunnable() {
297
                    public Object run() {
298
                        if (table.getColumnCount() > 0 || col > 0) {
299
                            table.showColumn(table.getColumn(col));
300
                        }
301
                        table.showItem(table.getItem(row));
302
                        return null;
303
                    }
304
                });
305
306
        final Rectangle cellBoundsRelativeToParent = getCellBounds(row, col);
307
            
308
        getEventThreadQueuer().invokeAndWait("getCellBoundsRelativeToParent", //$NON-NLS-1$
309
            new IRunnable() {
310
                public Object run() {
311
                    org.eclipse.swt.graphics.Point cellOriginRelativeToParent = 
312
                        table.getDisplay().map(
313
                                table, table.getParent(), 
314
                                new org.eclipse.swt.graphics.Point(
315
                                        cellBoundsRelativeToParent.x, 
316
                                        cellBoundsRelativeToParent.y));
317
                    cellBoundsRelativeToParent.x = 
318
                        cellOriginRelativeToParent.x;
319
                    cellBoundsRelativeToParent.y = 
320
                        cellOriginRelativeToParent.y;
321
                    return null;
322
                }
323
            });
324
325
        Control parent = (Control)getEventThreadQueuer().invokeAndWait("getParent", //$NON-NLS-1$
326
                new IRunnable() {
327
                public Object run() {
328
                    table.getParent();
329
                    return null;
330
                }
331
            });
332
333
            
334
        getRobot().scrollToVisible(
335
                parent, cellBoundsRelativeToParent);
336
        
337
        return getVisibleBounds(getCellBounds(row, col));
338
    }
339
    
340
    /**
341
     * 
342
     * @param row   The row of the cell
343
     * @param col   The column of the cell
344
     * @return The bounding rectangle for the cell, relative to the table's 
345
     *         location.
346
     */
347
    private Rectangle getCellBounds(final int row, final int col) {
348
        Rectangle cellBounds = (Rectangle)getEventThreadQueuer().invokeAndWait(
349
                "evaluateCellBounds", //$NON-NLS-1$
350
                new IRunnable() {
351
                    public Object run() {
352
                        checkRowColBounds(row, col);
353
                        TableItem ti = m_table.getItem(row);
354
                        int column = (m_table.getColumnCount() > 0 || col > 0) 
355
                            ? col : 0;
356
                        org.eclipse.swt.graphics.Rectangle r = 
357
                                ti.getBounds(column);
358
                        String text = ti.getText(column);
359
                        Image image = ti.getImage(column);
360
                        if (text != null && text.length() != 0) {
361
                            GC gc = new GC(m_table);
362
                            int charWidth = 0; 
363
                            try {
364
                                FontMetrics fm = gc.getFontMetrics();
365
                                charWidth = fm.getAverageCharWidth();
366
                            } finally {
367
                                gc.dispose();
368
                            }
369
                            r.width = text.length() * charWidth;
370
                            if (image != null) {
371
                                r.width += image.getBounds().width;
372
                            }
373
                        } else if (image != null) {
374
                            r.width = image.getBounds().width;
375
                        }
376
                        if (column > 0) {
377
                            TableColumn tc = m_table.getColumn(column);
378
                            int alignment = tc.getAlignment();
379
                            if (alignment == SWT.CENTER) {
380
                                r.x += ((double)tc.getWidth() / 2) 
381
                                        - ((double)r.width / 2);
382
                            }
383
                            if (alignment == SWT.RIGHT) {
384
                                r.x += tc.getWidth() - r.width;
385
                            }
386
                        }
387
                        
388
                        return new Rectangle(r.x, r.y, r.width, r.height);
389
                    }
390
                });
391
        return cellBounds;
392
    }
393
394
    /**
395
     * Checks wether <code>0 <= value < count</code>. 
396
     * @param value The value to check.
397
     * @param count The upper bound.
398
     */
399
    private void checkBounds(int value, int count) {
400
        if (value < 0 || value >= count) {
401
            throw new StepExecutionException("Invalid row/column: " + value, //$NON-NLS-1$
402
                EventFactory.createActionError(
403
                        TestErrorEvent.INVALID_INDEX_OR_HEADER));
404
        }
405
    }
406
    
407
    /**
408
     * Checks if the passed row and column are inside the bounds of the Table. 
409
     * @param row The row
410
     * @param column The column
411
     * @throws StepExecutionException If the row or the column is outside of the Table's bounds.
412
     */
413
    protected void checkRowColBounds(int row, int column)
414
        throws StepExecutionException {
415
        checkBounds(row, getRowCount());
416
        
417
        // Corner case: Only check the bounds if the table is not being
418
        //              used as a list or anything other than the first column
419
        //              is being checked.
420
        int colCount = getColumnCount();
421
        if (colCount > 0 || column > 0) {
422
            checkBounds(column, colCount);
423
        }
424
    }
425
    
426
    /**
427
     * Computes the visible cellBounds inside the visible bounds of the table.<br>
428
     * The result is the intersection of the visible bounds of the table and the 
429
     * bounds of the cell.
430
     * @param cellBounds the bounds of the cell to click in. These bounds must
431
     *                  be relative to the table's location.
432
     * @return the visible cell bounds, relative to the table's location.
433
     */
434
    private Rectangle getVisibleBounds(Rectangle cellBounds) {
435
        org.eclipse.swt.graphics.Rectangle r = 
436
            (org.eclipse.swt.graphics.Rectangle)
437
            getEventThreadQueuer().invokeAndWait("getVisibleCellBounds: " + cellBounds,  //$NON-NLS-1$
438
                    new IRunnable() {
439
440
                    public Object run() {
441
                        return m_table.getClientArea();
442
                    }
443
                });
444
        
445
        Rectangle visibleTableBounds = new Rectangle(
446
            r.x, r.y, r.width, r.height);
447
        Rectangle visibleCellBounds = 
448
            visibleTableBounds.intersection(cellBounds);
449
        return visibleCellBounds;
450
    }
451
    
452
    /**
453
     * @param cellEditor The cell editor to check.
454
     * @return <code>true</code> if the given cell editor is editable.
455
     */
456
    private boolean isEditable(Control cellEditor) {
457
458
        if (cellEditor == null || cellEditor instanceof TableCursor
459
            || cellEditor == m_table) {
460
            // No actual editor found.
461
            return false;
462
        }
463
        
464
        return (cellEditor.getStyle() & SWT.READ_ONLY) == 0;
465
    } 
466
    
467
    /**
468
     * @param cellEditor The cell editor to check.
469
     * @return <code>true</code> if the given editor is editable. Otherwise
470
     *         <code>false</code>.
471
     */
472
    private boolean invokeIsEditable(final Control cellEditor) {
473
474
        boolean isEditable = ((Boolean)getEventThreadQueuer().invokeAndWait(
475
                "getSelectedCell", //$NON-NLS-1$
476
                new IRunnable() {
477
                    public Object run() {
478
                        return isEditable(cellEditor) 
479
                            ? Boolean.TRUE : Boolean.FALSE;
480
                    }
481
                })).booleanValue();
482
        return isEditable;
483
    }
484
    
485
    /**
486
     * {@inheritDoc}
487
     */
488
    public Object activateEditor(final Cell cell) {
489
490
        Rectangle rect = scrollCellToVisible(cell.getRow(), cell.getCol());
491
        Control editor = getTableCellEditor(cell, rect);
492
        // sometimes the editor only appears after doubleclick!
493
494
        if (!invokeIsEditable(editor)) {
495
            org.eclipse.swt.graphics.Rectangle cellBounds = 
496
                    new org.eclipse.swt.graphics.Rectangle(
497
                    rect.x, rect.y, rect.width, rect.height);
498
            ClickOptions co = ClickOptions.create().setClickCount(2);
499
            Control clickTarget = editor == null
500
                    || editor instanceof TableCursor ? m_table : editor;
501
            getRobot().click(clickTarget, cellBounds, co);
502
            editor = getTableCellEditor(cell, rect);
503
        }
504
505
        return editor;
506
507
    }
508
    /**
509
     * Gets the TableCellEditor of the given cell.
510
     * The Cell has to be activated before!
511
     * @param cell the cell.
512
     * @param rect 
513
     * @return the TableCellEditor
514
     */
515
    private Control getTableCellEditor(final Cell cell, Rectangle rect) {
516
        org.eclipse.swt.graphics.Rectangle swtRect = 
517
                new org.eclipse.swt.graphics.Rectangle(rect.x, rect.y, 
518
                        rect.width, rect.height);
519
        getRobot().click(m_table, 
520
            swtRect,
521
            ClickOptions.create().setClickCount(1));
522
523
        
524
        return SwtUtils.getCursorControl();
525
    }
526
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/TreeAdapter.java (+66 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.IRunnable;
14
import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeOperationContext;
15
import org.eclipse.jubula.rc.common.uiadapter.interfaces.ITreeAdapter;
16
import org.eclipse.jubula.rc.swt.implclasses.TreeOperationContext;
17
import org.eclipse.swt.widgets.Tree;
18
/**
19
 * Implements the Tree interface for adapting a <code>SWT.Tree</code>
20
 * 
21
 *  @author BREDEX GmbH
22
 */
23
public class TreeAdapter extends WidgetAdapter implements ITreeAdapter {
24
25
26
    /**
27
     * 
28
     * @param objectToAdapt graphics component which will be adapted
29
     */
30
    public TreeAdapter(Object objectToAdapt) {
31
        super(objectToAdapt);
32
    }
33
    /**
34
     * 
35
     * @return the caste object
36
     */
37
    private Tree getTree() {
38
        return (Tree) getRealComponent();
39
    }
40
    /**
41
     * {@inheritDoc}
42
     */
43
    public Object getRootNode() {
44
        return getEventThreadQueuer()
45
                .invokeAndWait("getRootNode", new IRunnable() { //$NON-NLS-1$
46
                    public Object run() {
47
                        return getTree().getItems();
48
                    }
49
                });
50
    }
51
    /**
52
     * {@inheritDoc}
53
     */
54
    public AbstractTreeOperationContext getContext() {
55
        return new TreeOperationContext(getEventThreadQueuer(),
56
                getRobot(), getTree());
57
    }
58
    /**
59
     * {@inheritDoc}
60
     */
61
    public boolean isRootVisible() {
62
        
63
        return true;
64
    }
65
66
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/WidgetAdapter.java (+427 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.caps.AbstractMenuCAPs;
14
import org.eclipse.jubula.rc.common.driver.ClickOptions;
15
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
16
import org.eclipse.jubula.rc.common.driver.IRobot;
17
import org.eclipse.jubula.rc.common.driver.IRobotFactory;
18
import org.eclipse.jubula.rc.common.driver.IRunnable;
19
import org.eclipse.jubula.rc.common.driver.RobotTiming;
20
import org.eclipse.jubula.rc.common.exception.RobotException;
21
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
22
import org.eclipse.jubula.rc.common.listener.EventLock;
23
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IWidgetAdapter;
24
import org.eclipse.jubula.rc.swt.caps.CAPUtil;
25
import org.eclipse.jubula.rc.swt.caps.MenuCAPs;
26
import org.eclipse.jubula.rc.swt.driver.DragAndDropHelperSwt;
27
import org.eclipse.jubula.rc.swt.driver.EventThreadQueuerSwtImpl;
28
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
29
import org.eclipse.jubula.rc.swt.implclasses.EventListener;
30
import org.eclipse.jubula.rc.swt.implclasses.SimulatedTooltip;
31
import org.eclipse.jubula.rc.swt.utils.SwtUtils;
32
import org.eclipse.jubula.tools.constants.TimeoutConstants;
33
import org.eclipse.jubula.tools.objects.event.EventFactory;
34
import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
35
import org.eclipse.swt.SWT;
36
import org.eclipse.swt.graphics.Rectangle;
37
import org.eclipse.swt.widgets.Control;
38
import org.eclipse.swt.widgets.Display;
39
import org.eclipse.swt.widgets.Event;
40
import org.eclipse.swt.widgets.Menu;
41
import org.eclipse.swt.widgets.Widget;
42
/**
43
 * Implements the interface for widgets and supports basic methods
44
 * which are needed for nearly a lot of components.
45
 * 
46
 *  @author BREDEX GmbH
47
 */
48
public abstract class WidgetAdapter implements IWidgetAdapter {
49
    
50
    /** constants for communication */
51
    protected static final String POS_UNIT_PIXEL = "Pixel"; //$NON-NLS-1$
52
    /** constants for communication */
53
    protected static final String POS_UNI_PERCENT = "Percent"; //$NON-NLS-1$
54
55
56
    /** the RobotFactory from the AUT */
57
    private IRobotFactory m_robotFactory;
58
     
59
    /**   */
60
    private Control m_component;
61
    
62
    /**
63
     * Is true, if a popup menu is shown 
64
     */
65
    protected static class PopupShownCondition implements
66
            EventListener.Condition {
67
68
        /**
69
         * the popup menu
70
         */
71
        private Menu m_popup = null;
72
        
73
        /**
74
         * 
75
         * @return the popup menu
76
         */
77
        public Menu getPopup() {
78
            return m_popup;
79
        }
80
        
81
        /**
82
         * {@inheritDoc}
83
         * @param event event
84
         * @return result of the condition
85
         */
86
        public boolean isTrue(Event event) {
87
88
            if (event.type == SWT.Show && event.widget instanceof Menu) {
89
                m_popup = (Menu)event.widget;
90
                return true;
91
            } 
92
            
93
            return false;
94
        }
95
    }
96
    
97
    /**
98
     * 
99
     * @param objectToAdapt 
100
     */
101
    protected WidgetAdapter(Object objectToAdapt) {
102
        m_component = (Control) objectToAdapt;
103
    }
104
    
105
    /**
106
     * {@inheritDoc}
107
     */
108
    public Object getRealComponent() {
109
        return m_component;
110
    }
111
    
112
    /**
113
     * Gets the Robot factory. The factory is created once per instance.
114
     *
115
     * @return The Robot factory.
116
     */
117
    protected IRobotFactory getRobotFactory() {
118
        if (m_robotFactory == null) {
119
            m_robotFactory = new RobotFactoryConfig().getRobotFactory();
120
        }
121
        return m_robotFactory;
122
    }
123
    /**
124
     * Gets the Robot
125
     *
126
     * @return The Robot
127
     * @throws RobotException
128
     *             If the Robot cannot be created.
129
     */
130
    protected IRobot getRobot() throws RobotException {
131
        return getRobotFactory().getRobot();
132
    }
133
    /**
134
     * @return The event thread queuer.
135
     */
136
    public IEventThreadQueuer getEventThreadQueuer() {
137
        return getRobotFactory().getEventThreadQueuer();
138
    }
139
    
140
    /**
141
     * {@inheritDoc}
142
     */
143
    public String getPropteryValue(final String propertyname) {
144
        Object prop = getEventThreadQueuer().invokeAndWait("getProperty",  //$NON-NLS-1$
145
                new IRunnable() {
146
                    public Object run() throws StepExecutionException {
147
                        try {
148
                            return getRobot().getPropertyValue(
149
                                    getRealComponent(), propertyname);
150
                        } catch (RobotException e) {
151
                            throw new StepExecutionException(
152
                                e.getMessage(), 
153
                                EventFactory.createActionError(
154
                                    TestErrorEvent.PROPERTY_NOT_ACCESSABLE));
155
                        }
156
                    }
157
                });
158
        return String.valueOf(prop);
159
    }
160
    
161
    /**
162
     * {@inheritDoc}
163
     */
164
    public boolean isShowing() {
165
        Boolean actual = (Boolean)getEventThreadQueuer()
166
                .invokeAndWait("isShowing", new IRunnable() { //$NON-NLS-1$
167
                    public Object run() {
168
                        return m_component.isVisible() 
169
                            ? Boolean.TRUE : Boolean.FALSE; // see findBugs;
170
                    }
171
                });
172
        return actual.booleanValue();
173
    }
174
    
175
    /**
176
     * {@inheritDoc}
177
     */
178
    public boolean isEnabled() {
179
180
        Boolean actual = (Boolean)getEventThreadQueuer()
181
                .invokeAndWait("isEnabled", new IRunnable() { //$NON-NLS-1$
182
                    public Object run() {
183
                        return m_component.isEnabled() 
184
                            ? Boolean.TRUE : Boolean.FALSE; // see findBugs;
185
                    }
186
                });
187
        return actual.booleanValue();
188
    }
189
    
190
    /**
191
     * {@inheritDoc}
192
     */
193
    public boolean hasFocus() {
194
        Boolean actual = (Boolean)getEventThreadQueuer()
195
                .invokeAndWait("hasFocus", new IRunnable() { //$NON-NLS-1$
196
                    public Object run() {
197
                        return m_component.isFocusControl() 
198
                            ? Boolean.TRUE : Boolean.FALSE; // see findBugs;
199
                    }
200
                });
201
        return actual.booleanValue();
202
    }
203
    
204
    /**
205
     * Shows and returns the popup menu
206
     * @param button MouseButton
207
     * @return the popup menu
208
     */
209
    public AbstractMenuCAPs showPopup(
210
            final int button) {
211
        final Widget component = m_component;
212
        if (SwtUtils.isMouseCursorInWidget(component)) {
213
            return showPopup(component, new Runnable() {
214
                public void run() {
215
                    RobotTiming.sleepPreShowPopupDelay();
216
                    
217
                    getRobot().clickAtCurrentPosition(component, 1, 
218
                            button);
219
                }
220
            });
221
        }
222
        return showPopup(50, POS_UNI_PERCENT, 50, 
223
            POS_UNI_PERCENT, button);
224
    }
225
226
    /**
227
     * Shows and returns the popup menu
228
     * 
229
     * @param xPos what x position
230
     * @param xUnits should x position be pixel or percent values
231
     * @param yPos what y position
232
     * @param yUnits should y position be pixel or percent values
233
     * @param button MouseButton
234
     * @return the popup menu
235
     * @throws StepExecutionException error
236
     */
237
    public AbstractMenuCAPs showPopup(
238
            final int xPos, final String xUnits,
239
            final int yPos, final String yUnits, 
240
            final int button) throws StepExecutionException {
241
        final Widget component = m_component;
242
        return showPopup(component, new Runnable() {
243
            public void run() {
244
                RobotTiming.sleepPreShowPopupDelay();
245
                boolean isAbsoluteUnitsX = 
246
                    POS_UNIT_PIXEL.equalsIgnoreCase(
247
                            xUnits);
248
                boolean isAbsoluteUnitsY = 
249
                    POS_UNIT_PIXEL.equalsIgnoreCase(
250
                            yUnits);
251
                getRobot().click(component, null, 
252
                    ClickOptions.create().setClickCount(1)
253
                        .setMouseButton(button), 
254
                    xPos, isAbsoluteUnitsX, yPos, isAbsoluteUnitsY);
255
            }
256
        });
257
    }
258
259
    /**
260
     * Shows and returns the popup menu
261
     * 
262
     * @param component The component for which to open the popup menu.
263
     * @param showPopup A <code>Runnable</code> that, when run, should display
264
     *                  a popup menu for the given component.
265
     * @return the popup menu
266
     * @throws StepExecutionException error
267
     */
268
    private AbstractMenuCAPs showPopup(final Widget component, 
269
        final Runnable showPopup) throws StepExecutionException {
270
271
        PopupShownCondition cond = new PopupShownCondition();
272
        EventLock lock = new EventLock();
273
        final EventListener listener = new EventListener(lock, cond);
274
        final Display d = component.getDisplay();
275
        final IEventThreadQueuer queuer = new EventThreadQueuerSwtImpl();
276
        
277
        queuer.invokeAndWait("addPopupShownListeners", new IRunnable() { //$NON-NLS-1$
278
            public Object run() {
279
                d.addFilter(SWT.Show, listener);
280
                
281
                return null;
282
            }
283
        });
284
        
285
        try {
286
            // showPopup must run in the current thread in order to
287
            // avoid a race condition.
288
            showPopup.run();
289
290
            synchronized (lock) {
291
                long timeout = TimeoutConstants.SERVER_TIMEOUT_WAIT_FOR_POPUP;
292
                long done = System.currentTimeMillis() + timeout; 
293
                long now;
294
                while (!lock.isReleased() && (timeout > 0)) {
295
                    lock.wait(timeout);
296
                    now = System.currentTimeMillis();
297
                    timeout = done - now;
298
                }
299
            } 
300
        } catch (InterruptedException e) {
301
            // ignore
302
        } finally {
303
            queuer.invokeAndWait("removePopupShownListeners", new IRunnable() { //$NON-NLS-1$
304
                public Object run() {
305
                    d.removeFilter(SWT.Show, listener);
306
                    
307
                    return null;
308
                }
309
            });
310
        }
311
        if (!lock.isReleased()) {
312
            throw new StepExecutionException("popup not shown", //$NON-NLS-1$
313
                    EventFactory.createActionError(
314
                            TestErrorEvent.POPUP_NOT_FOUND));
315
        }
316
        
317
        MenuCAPs contextMenu = new MenuCAPs();
318
        contextMenu.setComponent(cond.getPopup());
319
        contextMenu.setContextMenu(true);
320
        return contextMenu;
321
    }
322
    
323
    /**
324
     * {@inheritDoc}
325
     */
326
    public void showToolTip(final String text, final int textSize, 
327
        final int timePerWord, final int windowWidth) {
328
329
        final Rectangle bounds = (Rectangle)getEventThreadQueuer()
330
            .invokeAndWait("gdShowText.getBounds", new IRunnable() { //$NON-NLS-1$
331
332
                public Object run() {
333
                    return SwtUtils.getWidgetBounds(m_component);
334
                }
335
            });
336
337
        SimulatedTooltip sp = (SimulatedTooltip)getEventThreadQueuer()
338
            .invokeAndWait("gdShowText.initToolTip", new IRunnable() { //$NON-NLS-1$
339
340
                public Object run() throws StepExecutionException {
341
                    return new SimulatedTooltip(timePerWord, text,
342
                        windowWidth, textSize, bounds);
343
                }
344
            
345
            });
346
        sp.start();
347
        try {
348
            sp.join();
349
        } catch (InterruptedException e) {
350
            throw new StepExecutionException(e);
351
        }
352
    }
353
    
354
    /**
355
     * {@inheritDoc}
356
     */
357
    public void gdDrag(int mouseButton, String modifier, int xPos, 
358
            String xUnits, int yPos, String yUnits) {
359
        // Only store the Drag-Information. Otherwise the GUI-Eventqueue
360
        // blocks after performed Drag!
361
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
362
            .getInstance();
363
        dndHelper.setMouseButton(mouseButton);
364
        dndHelper.setModifier(modifier);
365
        dndHelper.setDragComponent(null);
366
        clickDirect(0, mouseButton, xPos, xUnits, yPos, yUnits);
367
    }
368
    
369
    /**
370
     * {@inheritDoc}                  
371
     */
372
    public void gdDrop(final int xPos, final String xUnits, final int yPos, 
373
            final String yUnits, int delayBeforeDrop) {
374
        final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
375
            .getInstance();
376
        final IRobot robot = getRobot();
377
        final String modifier = dndHelper.getModifier();
378
        final int mouseButton = dndHelper.getMouseButton();
379
        // Note: This method performs the drag AND drop action in one runnable
380
        // in the GUI-Eventqueue because after the mousePress, the eventqueue
381
        // blocks!
382
        try {
383
            CAPUtil.pressOrReleaseModifiers(modifier, true);
384
385
            getEventThreadQueuer().invokeAndWait("gdStartDrag", new IRunnable() { //$NON-NLS-1$
386
                public Object run() throws StepExecutionException {
387
                    // drag
388
                    robot.mousePress(dndHelper.getDragComponent(), null, 
389
                            mouseButton);
390
391
                    CAPUtil.shakeMouse();
392
                    
393
                    // drop
394
                    clickDirect(0, mouseButton, xPos, xUnits, yPos, yUnits);
395
                    return null;
396
                }            
397
            });
398
            
399
            CAPUtil.waitBeforeDrop(delayBeforeDrop);
400
        } finally {
401
            getRobot().mouseRelease(null, null, mouseButton);
402
            CAPUtil.pressOrReleaseModifiers(modifier, false);
403
        }
404
    }
405
406
    /**
407
     * clicks into a component. 
408
     * @param count amount of clicks
409
     * @param button what button should be clicked
410
     * @param xPos what x position
411
     * @param xUnits should x position be pixel or percent values
412
     * @param yPos what y position
413
     * @param yUnits should y position be pixel or percent values
414
     * @throws StepExecutionException error
415
     */
416
    protected void clickDirect(int count, int button, int xPos, String xUnits,
417
            int yPos, String yUnits)
418
        throws StepExecutionException {
419
420
        getRobot().click(
421
                m_component,
422
                null,
423
                ClickOptions.create().setClickCount(count).setMouseButton(
424
                        button), xPos, xUnits.equalsIgnoreCase(POS_UNIT_PIXEL),
425
                yPos, yUnits.equalsIgnoreCase(POS_UNIT_PIXEL));
426
    }
427
}
(-)a/org.eclipse.jubula.rc.swt/src/org/eclipse/jubula/rc/swt/uiadapter/factory/SWTAdapterFactory.java (+67 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.factory;
12
13
import org.eclipse.jubula.rc.common.uiadapter.factory.IUIAdapterFactory;
14
import org.eclipse.jubula.rc.common.uiadapter.interfaces.IComponentAdapter;
15
import org.eclipse.jubula.rc.swt.uiadapter.ButtonAdapter;
16
import org.eclipse.jubula.rc.swt.uiadapter.MenuAdapter;
17
import org.eclipse.jubula.rc.swt.uiadapter.MenuItemAdapter;
18
import org.eclipse.jubula.rc.swt.uiadapter.TableAdapter;
19
import org.eclipse.jubula.rc.swt.uiadapter.TreeAdapter;
20
import org.eclipse.swt.widgets.Button;
21
import org.eclipse.swt.widgets.Menu;
22
import org.eclipse.swt.widgets.MenuItem;
23
import org.eclipse.swt.widgets.Table;
24
import org.eclipse.swt.widgets.Tree;
25
26
/**
27
 * This factory constructs the specific adapter out of the incoming
28
 * graphics component from the AUT.
29
 * 
30
 * @author BREDEX GmbH
31
 */
32
public class SWTAdapterFactory implements IUIAdapterFactory {
33
    /** */
34
    private static final Class[] SUPPORTEDCLASSES = 
35
            new Class[]{Button.class, Menu.class, MenuItem.class, Tree.class,
36
                Table.class};
37
    
38
    
39
    /**
40
     * {@inheritDoc}
41
     */
42
    public Class[] getSupportedClasses() {
43
        return SUPPORTEDCLASSES;
44
    }
45
46
    /**
47
     * {@inheritDoc}
48
     */
49
    public IComponentAdapter getAdapter(Object objectToAdapt) {
50
        IComponentAdapter returnvalue = null;
51
        if (objectToAdapt instanceof Button) {
52
            returnvalue = new ButtonAdapter(objectToAdapt);
53
        } else if (objectToAdapt instanceof Menu) {
54
            returnvalue = new MenuAdapter(objectToAdapt);
55
        } else if (objectToAdapt instanceof MenuItem) {
56
            returnvalue = new MenuItemAdapter(objectToAdapt);
57
        } else if (objectToAdapt instanceof Tree) {
58
            returnvalue = new TreeAdapter(objectToAdapt);
59
        } else if (objectToAdapt instanceof Table) {
60
            returnvalue = new TableAdapter(objectToAdapt);
61
        }
62
        
63
        
64
        return returnvalue;
65
    }
66
67
}
(-)a/org.eclipse.jubula.toolkit.provider.swing/resources/xml/ComponentConfiguration.xml (-5 / +5 lines)
Lines 27-33 Link Here
27
	
27
	
28
	<toolkitComponent type="javax.swing.AbstractButton" visible="false">
28
	<toolkitComponent type="javax.swing.AbstractButton" visible="false">
29
		<realizes>guidancer.concrete.Button</realizes>
29
		<realizes>guidancer.concrete.Button</realizes>
30
		<testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.AbstractButtonImplClass</testerClass>
30
		<testerClass>org.eclipse.jubula.rc.swing.swing.caps.AbstractButtonCAPs</testerClass>
31
		<componentClass name="javax.swing.AbstractButton" />
31
		<componentClass name="javax.swing.AbstractButton" />
32
	</toolkitComponent>
32
	</toolkitComponent>
33
33
Lines 36-48 Link Here
36
			<typeFactory>org.eclipse.jubula.rc.common.implclasses.DefaultComponentFactory</typeFactory>
36
			<typeFactory>org.eclipse.jubula.rc.common.implclasses.DefaultComponentFactory</typeFactory>
37
		</defaultMapping>
37
		</defaultMapping>
38
		<realizes>guidancer.concrete.MenuBar</realizes>
38
		<realizes>guidancer.concrete.MenuBar</realizes>
39
		<testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JMenuBarImplClass</testerClass>
39
		<testerClass>org.eclipse.jubula.rc.swing.swing.caps.JMenuBarCAPs</testerClass>
40
		<componentClass name="com.bredexsw.guidancer.autserver.swing.implclasses.JMenuBarDefaultMapping" />
40
		<componentClass name="com.bredexsw.guidancer.autserver.swing.implclasses.JMenuBarDefaultMapping" />
41
	</toolkitComponent>
41
	</toolkitComponent>
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.implclasses.JComboBoxImplClass</testerClass>
45
		<testerClass>org.eclipse.jubula.rc.swing.swing.caps.JComboBoxCAPs</testerClass>
46
		<componentClass name="javax.swing.JComboBox" />
46
		<componentClass name="javax.swing.JComboBox" />
47
	</toolkitComponent>
47
	</toolkitComponent>
48
	
48
	
Lines 66-72 Link Here
66
	
66
	
67
	<toolkitComponent type="javax.swing.JTable" visible="false">
67
	<toolkitComponent type="javax.swing.JTable" visible="false">
68
		<realizes>guidancer.concrete.Table</realizes>
68
		<realizes>guidancer.concrete.Table</realizes>
69
		<testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JTableImplClass</testerClass>
69
		<testerClass>org.eclipse.jubula.rc.swing.swing.caps.JTableCAPs</testerClass>
70
		<componentClass name="javax.swing.JTable" />
70
		<componentClass name="javax.swing.JTable" />
71
	</toolkitComponent>
71
	</toolkitComponent>
72
	
72
	
Lines 78-84 Link Here
78
	
78
	
79
	<toolkitComponent type="javax.swing.JTree" visible="false">
79
	<toolkitComponent type="javax.swing.JTree" visible="false">
80
		<realizes>guidancer.concrete.Tree</realizes>
80
		<realizes>guidancer.concrete.Tree</realizes>
81
		<testerClass>org.eclipse.jubula.rc.swing.swing.implclasses.JTreeImplClass</testerClass>
81
		<testerClass>org.eclipse.jubula.rc.swing.swing.caps.JTreeCAPs</testerClass>
82
		<componentClass name="javax.swing.JTree" />
82
		<componentClass name="javax.swing.JTree" />
83
	</toolkitComponent>
83
	</toolkitComponent>
84
	
84
	
(-)a/org.eclipse.jubula.toolkit.provider.swt/resources/xml/ComponentConfiguration.xml (-6 / +5 lines)
Lines 184-190 Link Here
184
	
184
	
185
	<toolkitComponent type="org.eclipse.swt.widgets.Button" visible="false">
185
	<toolkitComponent type="org.eclipse.swt.widgets.Button" visible="false">
186
		<realizes>guidancer.abstract.SwtButton</realizes>
186
		<realizes>guidancer.abstract.SwtButton</realizes>
187
		<testerClass>org.eclipse.jubula.rc.swt.implclasses.ButtonImplClass</testerClass>
187
		<testerClass>org.eclipse.jubula.rc.swt.caps.ButtonCAPs</testerClass>
188
		<componentClass name="org.eclipse.swt.widgets.Button" />
188
		<componentClass name="org.eclipse.swt.widgets.Button" />
189
	</toolkitComponent>
189
	</toolkitComponent>
190
	
190
	
Lines 203-209 Link Here
203
			<typeFactory>org.eclipse.jubula.rc.common.implclasses.DefaultComponentFactory</typeFactory>
203
			<typeFactory>org.eclipse.jubula.rc.common.implclasses.DefaultComponentFactory</typeFactory>
204
		</defaultMapping>
204
		</defaultMapping>
205
		<realizes>guidancer.concrete.MenuBar</realizes>
205
		<realizes>guidancer.concrete.MenuBar</realizes>
206
		<testerClass>org.eclipse.jubula.rc.swt.implclasses.MenuImplClass</testerClass>
206
		<testerClass>org.eclipse.jubula.rc.swt.caps.MenuCAPs</testerClass>
207
		<componentClass name="com.bredexsw.guidancer.autswtserver.implclasses.MenuDefaultMapping" />
207
		<componentClass name="com.bredexsw.guidancer.autswtserver.implclasses.MenuDefaultMapping" />
208
	</toolkitComponent>
208
	</toolkitComponent>
209
	
209
	
Lines 239-251 Link Here
239
	
239
	
240
	<toolkitComponent type="org.eclipse.swt.widgets.Table" visible="false">
240
	<toolkitComponent type="org.eclipse.swt.widgets.Table" visible="false">
241
		<realizes>guidancer.concrete.Table</realizes>
241
		<realizes>guidancer.concrete.Table</realizes>
242
		<testerClass>org.eclipse.jubula.rc.swt.implclasses.TableImplClass</testerClass>
242
		<testerClass>org.eclipse.jubula.rc.swt.caps.TableCAPs</testerClass>
243
		<componentClass name="org.eclipse.swt.widgets.Table" />
243
		<componentClass name="org.eclipse.swt.widgets.Table" />
244
	</toolkitComponent>
244
	</toolkitComponent>
245
	
245
	
246
	<toolkitComponent type="org.eclipse.swt.widgets.Tree" observable="false">
246
	<toolkitComponent type="org.eclipse.swt.widgets.Tree" observable="false">
247
		<realizes>guidancer.concrete.Tree</realizes>
247
		<realizes>guidancer.concrete.Tree</realizes>
248
		<testerClass>org.eclipse.jubula.rc.swt.implclasses.TableTreeImplClass</testerClass>
248
		<testerClass>org.eclipse.jubula.rc.swt.caps.TreeCAPs</testerClass>
249
		<componentClass name="org.eclipse.swt.widgets.Tree" />
249
		<componentClass name="org.eclipse.swt.widgets.Tree" />
250
		<action name="CompSystem.VerifyCheckboxOfSelectedEntry" changed="4.1">
250
		<action name="CompSystem.VerifyCheckboxOfSelectedEntry" changed="4.1">
251
			<method>gdVerifySelectedCheckbox</method>
251
			<method>gdVerifySelectedCheckbox</method>
Lines 370-376 Link Here
370
	
370
	
371
	<toolkitComponent type="org.eclipse.swt.widgets.SwtTree">
371
	<toolkitComponent type="org.eclipse.swt.widgets.SwtTree">
372
		<realizes>org.eclipse.swt.widgets.Tree</realizes>
372
		<realizes>org.eclipse.swt.widgets.Tree</realizes>
373
		<testerClass>org.eclipse.jubula.rc.swt.implclasses.TableTreeImplClass</testerClass>
373
		<testerClass>org.eclipse.jubula.rc.swt.caps.TreeCAPs</testerClass>
374
		<componentClass name="org.eclipse.swt.widgets.Tree" />
374
		<componentClass name="org.eclipse.swt.widgets.Tree" />
375
		<action name="CompSystem.SelectByTextPathAtColumn" changed="1.22">
375
		<action name="CompSystem.SelectByTextPathAtColumn" changed="1.22">
376
			<method>gdSelect</method>
376
			<method>gdSelect</method>
377
- 

Return to bug 394179