1/*
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.netbeans.jemmy.operators;
24
25import java.awt.Checkbox;
26import java.awt.CheckboxGroup;
27import java.awt.Component;
28import java.awt.Container;
29import java.awt.event.ItemListener;
30import java.util.Hashtable;
31
32import org.netbeans.jemmy.ComponentChooser;
33import org.netbeans.jemmy.JemmyException;
34import org.netbeans.jemmy.Outputable;
35import org.netbeans.jemmy.TestOut;
36import org.netbeans.jemmy.TimeoutExpiredException;
37import org.netbeans.jemmy.drivers.ButtonDriver;
38import org.netbeans.jemmy.drivers.DriverManager;
39
40/**
41 *
42 * <BR><BR>Timeouts used: <BR>
43 * ButtonOperator.PushButtonTimeout - time between checkbox pressing and
44 * releasing<BR>
45 * ComponentOperator.WaitComponentTimeout - time to wait checkbox displayed <BR>
46 * ComponentOperator.WaitComponentEnabledTimeout - time to wait checkbox enabled
47 * <BR>.
48 *
49 * @see org.netbeans.jemmy.Timeouts
50 *
51 * @author Alexandre Iline (alexandre.iline@oracle.com)
52 *
53 */
54public class CheckboxOperator extends ComponentOperator implements Outputable {
55
56    /**
57     * Identifier for a label property.
58     *
59     * @see #getDump
60     */
61    public static final String TEXT_DPROP = "Label";
62
63    private TestOut output;
64    ButtonDriver driver;
65
66    /**
67     * Constructor.
68     *
69     * @param b a component
70     */
71    public CheckboxOperator(Checkbox b) {
72        super(b);
73        driver = DriverManager.getButtonDriver(getClass());
74    }
75
76    /**
77     * Constructs an CheckboxOperator object.
78     *
79     * @param cont container
80     * @param chooser a component chooser specifying searching criteria.
81     * @param index an index between appropriate ones.
82     */
83    public CheckboxOperator(ContainerOperator<?> cont, ComponentChooser chooser, int index) {
84        this((Checkbox) cont.
85                waitSubComponent(new CheckboxFinder(chooser),
86                        index));
87        copyEnvironment(cont);
88    }
89
90    /**
91     * Constructs an CheckboxOperator object.
92     *
93     * @param cont container
94     * @param chooser a component chooser specifying searching criteria.
95     */
96    public CheckboxOperator(ContainerOperator<?> cont, ComponentChooser chooser) {
97        this(cont, chooser, 0);
98    }
99
100    /**
101     * Constructor. Waits component in container first. Uses cont's timeout and
102     * output for waiting and to init operator.
103     *
104     * @param cont container
105     * @param text Checkbox text.
106     * @param index Ordinal component index.
107     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
108     * @throws TimeoutExpiredException
109     */
110    public CheckboxOperator(ContainerOperator<?> cont, String text, int index) {
111        this((Checkbox) waitComponent(cont,
112                new CheckboxByLabelFinder(text,
113                        cont.getComparator()),
114                index));
115        copyEnvironment(cont);
116    }
117
118    /**
119     * Constructor. Waits component in container first. Uses cont's timeout and
120     * output for waiting and to init operator.
121     *
122     * @param cont container
123     * @param text Checkbox text.
124     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
125     * @throws TimeoutExpiredException
126     */
127    public CheckboxOperator(ContainerOperator<?> cont, String text) {
128        this(cont, text, 0);
129    }
130
131    /**
132     * Constructor. Waits component in container first. Uses cont's timeout and
133     * output for waiting and to init operator.
134     *
135     * @param cont container
136     * @param index Ordinal component index.
137     * @throws TimeoutExpiredException
138     */
139    public CheckboxOperator(ContainerOperator<?> cont, int index) {
140        this((Checkbox) waitComponent(cont,
141                new CheckboxFinder(),
142                index));
143        copyEnvironment(cont);
144    }
145
146    /**
147     * Constructor. Waits component in container first. Uses cont's timeout and
148     * output for waiting and to init operator.
149     *
150     * @param cont container
151     * @throws TimeoutExpiredException
152     */
153    public CheckboxOperator(ContainerOperator<?> cont) {
154        this(cont, 0);
155    }
156
157    /**
158     * Searches Checkbox in container.
159     *
160     * @param cont Container to search component in.
161     * @param chooser org.netbeans.jemmy.ComponentChooser implementation.
162     * @param index Ordinal component index.
163     * @return Checkbox instance or null if component was not found.
164     */
165    public static Checkbox findCheckbox(Container cont, ComponentChooser chooser, int index) {
166        return (Checkbox) findComponent(cont, new CheckboxFinder(chooser), index);
167    }
168
169    /**
170     * Searches 0'th Checkbox in container.
171     *
172     * @param cont Container to search component in.
173     * @param chooser org.netbeans.jemmy.ComponentChooser implementation.
174     * @return Checkbox instance or null if component was not found.
175     */
176    public static Checkbox findCheckbox(Container cont, ComponentChooser chooser) {
177        return findCheckbox(cont, chooser, 0);
178    }
179
180    /**
181     * Searches Checkbox by text.
182     *
183     * @param cont Container to search component in.
184     * @param text Checkbox text. If null, contents is not checked.
185     * @param ce Compare text exactly.
186     * @param ccs Compare text case sensitively.
187     * @param index Ordinal component index.
188     * @return Checkbox instance or null if component was not found.
189     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
190     */
191    public static Checkbox findCheckbox(Container cont, String text, boolean ce, boolean ccs, int index) {
192        return (findCheckbox(cont,
193                new CheckboxByLabelFinder(text,
194                        new DefaultStringComparator(ce, ccs)),
195                index));
196    }
197
198    /**
199     * Searches Checkbox by text.
200     *
201     * @param cont Container to search component in.
202     * @param text Checkbox text. If null, contents is not checked.
203     * @param ce Compare text exactly.
204     * @param ccs Compare text case sensitively.
205     * @return Checkbox instance or null if component was not found.
206     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
207     */
208    public static Checkbox findCheckbox(Container cont, String text, boolean ce, boolean ccs) {
209        return findCheckbox(cont, text, ce, ccs, 0);
210    }
211
212    /**
213     * Waits Checkbox in container.
214     *
215     * @param cont Container to search component in.
216     * @param chooser org.netbeans.jemmy.ComponentChooser implementation.
217     * @param index Ordinal component index.
218     * @return Checkbox instance.
219     * @throws TimeoutExpiredException
220     */
221    public static Checkbox waitCheckbox(Container cont, ComponentChooser chooser, int index) {
222        return (Checkbox) waitComponent(cont, new CheckboxFinder(chooser), index);
223    }
224
225    /**
226     * Waits 0'th Checkbox in container.
227     *
228     * @param cont Container to search component in.
229     * @param chooser org.netbeans.jemmy.ComponentChooser implementation.
230     * @return Checkbox instance.
231     * @throws TimeoutExpiredException
232     */
233    public static Checkbox waitCheckbox(Container cont, ComponentChooser chooser) {
234        return waitCheckbox(cont, chooser, 0);
235    }
236
237    /**
238     * Waits Checkbox by text.
239     *
240     * @param cont Container to search component in.
241     * @param text Checkbox text. If null, contents is not checked.
242     * @param ce Compare text exactly.
243     * @param ccs Compare text case sensitively.
244     * @param index Ordinal component index.
245     * @return Checkbox instance.
246     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
247     * @throws TimeoutExpiredException
248     */
249    public static Checkbox waitCheckbox(Container cont, String text, boolean ce, boolean ccs, int index) {
250        return (waitCheckbox(cont,
251                new CheckboxByLabelFinder(text,
252                        new DefaultStringComparator(ce, ccs)),
253                index));
254    }
255
256    /**
257     * Waits Checkbox by text.
258     *
259     * @param cont Container to search component in.
260     * @param text Checkbox text. If null, contents is not checked.
261     * @param ce Compare text exactly.
262     * @param ccs Compare text case sensitively.
263     * @return Checkbox instance.
264     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
265     * @throws TimeoutExpiredException
266     */
267    public static Checkbox waitCheckbox(Container cont, String text, boolean ce, boolean ccs) {
268        return waitCheckbox(cont, text, ce, ccs, 0);
269    }
270
271    @Override
272    public void setOutput(TestOut out) {
273        output = out;
274        super.setOutput(output.createErrorOutput());
275    }
276
277    @Override
278    public TestOut getOutput() {
279        return output;
280    }
281
282    @Override
283    public void copyEnvironment(Operator anotherOperator) {
284        super.copyEnvironment(anotherOperator);
285        driver
286                = (ButtonDriver) DriverManager.
287                getDriver(DriverManager.BUTTON_DRIVER_ID,
288                        getClass(),
289                        anotherOperator.getProperties());
290    }
291
292    /**
293     * Changes selection if necessary. Uses a ButtonDriver registered for this
294     * operator.
295     *
296     * @param newValue a button selection.
297     */
298    public void changeSelection(boolean newValue) {
299        makeComponentVisible();
300        if (getState() != newValue) {
301            try {
302                waitComponentEnabled();
303            } catch (InterruptedException e) {
304                throw (new JemmyException("Interrupted!", e));
305            }
306            output.printLine("Change checkbox selection to " + (newValue ? "true" : "false")
307                    + "\n    :" + toStringSource());
308            output.printGolden("Change checkbox selection to " + (newValue ? "true" : "false"));
309            driver.push(this);
310            if (getVerification()) {
311                waitSelected(newValue);
312            }
313        }
314    }
315
316    /**
317     * Runs {@code changeSelection(boolean)} method in a separate thread.
318     *
319     * @param selected a button selection.
320     */
321    public void changeSelectionNoBlock(boolean selected) {
322        produceNoBlocking(new NoBlockingAction<Void, Boolean>("Button selection changing") {
323            @Override
324            public Void doAction(Boolean param) {
325                changeSelection(param);
326                return null;
327            }
328        }, selected ? Boolean.TRUE : Boolean.FALSE);
329    }
330
331    /**
332     * Waits for button to be selected.
333     *
334     * @param selected selection.
335     */
336    public void waitSelected(final boolean selected) {
337        getOutput().printLine("Wait button to be selected \n    : "
338                + toStringSource());
339        getOutput().printGolden("Wait button to be selected");
340        waitState(new ComponentChooser() {
341            @Override
342            public boolean checkComponent(Component comp) {
343                return getState() == selected;
344            }
345
346            @Override
347            public String getDescription() {
348                return ("Items has been "
349                        + (selected ? "" : "un") + "selected");
350            }
351
352            @Override
353            public String toString() {
354                return "CheckboxOperator.waitSelected.ComponentChooser{description = " + getDescription() + '}';
355            }
356        });
357    }
358
359    /**
360     * Returns information about component.
361     */
362    @Override
363    public Hashtable<String, Object> getDump() {
364        Hashtable<String, Object> result = super.getDump();
365        result.put(TEXT_DPROP, ((Checkbox) getSource()).getLabel());
366        return result;
367    }
368
369    ////////////////////////////////////////////////////////
370    //Mapping                                             //
371    /**
372     * Maps {@code Checkbox.addItemListener(ItemListener)} through queue
373     */
374    public void addItemListener(final ItemListener itemListener) {
375        runMapping(new MapVoidAction("addItemListener") {
376            @Override
377            public void map() {
378                ((Checkbox) getSource()).addItemListener(itemListener);
379            }
380        });
381    }
382
383    /**
384     * Maps {@code Checkbox.getCheckboxGroup()} through queue
385     */
386    public CheckboxGroup getCheckboxGroup() {
387        return (runMapping(new MapAction<CheckboxGroup>("getCheckboxGroup") {
388            @Override
389            public CheckboxGroup map() {
390                return ((Checkbox) getSource()).getCheckboxGroup();
391            }
392        }));
393    }
394
395    /**
396     * Maps {@code Checkbox.getLabel()} through queue
397     */
398    public String getLabel() {
399        return (runMapping(new MapAction<String>("getLabel") {
400            @Override
401            public String map() {
402                return ((Checkbox) getSource()).getLabel();
403            }
404        }));
405    }
406
407    /**
408     * Maps {@code Checkbox.getState()} through queue
409     */
410    public boolean getState() {
411        return (runMapping(new MapBooleanAction("getState") {
412            @Override
413            public boolean map() {
414                return ((Checkbox) getSource()).getState();
415            }
416        }));
417    }
418
419    /**
420     * Maps {@code Checkbox.removeItemListener(ItemListener)} through queue
421     */
422    public void removeItemListener(final ItemListener itemListener) {
423        runMapping(new MapVoidAction("removeItemListener") {
424            @Override
425            public void map() {
426                ((Checkbox) getSource()).removeItemListener(itemListener);
427            }
428        });
429    }
430
431    /**
432     * Maps {@code Checkbox.setCheckboxGroup(CheckboxGroup)} through queue
433     */
434    public void setCheckboxGroup(final CheckboxGroup grp) {
435        runMapping(new MapVoidAction("setCheckboxGroup") {
436            @Override
437            public void map() {
438                ((Checkbox) getSource()).setCheckboxGroup(grp);
439            }
440        });
441    }
442
443    /**
444     * Maps {@code Checkbox.setLabel(String)} through queue
445     */
446    public void setLabel(final String string) {
447        runMapping(new MapVoidAction("setLabel") {
448            @Override
449            public void map() {
450                ((Checkbox) getSource()).setLabel(string);
451            }
452        });
453    }
454
455    /**
456     * Maps {@code Checkbox.setState(boolean)} through queue
457     */
458    public void setState(final boolean state) {
459        runMapping(new MapVoidAction("setState") {
460            @Override
461            public void map() {
462                ((Checkbox) getSource()).setState(state);
463            }
464        });
465    }
466
467    //End of mapping                                      //
468    ////////////////////////////////////////////////////////
469    /**
470     * Allows to find component by label.
471     */
472    public static class CheckboxByLabelFinder implements ComponentChooser {
473
474        String label;
475        StringComparator comparator;
476
477        /**
478         * Constructs CheckboxByLabelFinder.
479         *
480         * @param lb a label pattern
481         * @param comparator specifies string comparision algorithm.
482         */
483        public CheckboxByLabelFinder(String lb, StringComparator comparator) {
484            label = lb;
485            this.comparator = comparator;
486        }
487
488        /**
489         * Constructs CheckboxByLabelFinder.
490         *
491         * @param lb a label pattern
492         */
493        public CheckboxByLabelFinder(String lb) {
494            this(lb, Operator.getDefaultStringComparator());
495        }
496
497        @Override
498        public boolean checkComponent(Component comp) {
499            if (comp instanceof Checkbox) {
500                if (((Checkbox) comp).getLabel() != null) {
501                    return (comparator.equals(((Checkbox) comp).getLabel(),
502                            label));
503                }
504            }
505            return false;
506        }
507
508        @Override
509        public String getDescription() {
510            return "Checkbox with label \"" + label + "\"";
511        }
512
513        @Override
514        public String toString() {
515            return "CheckboxByLabelFinder{" + "label=" + label + ", comparator=" + comparator + '}';
516        }
517    }
518
519    /**
520     * Checks component type.
521     */
522    public static class CheckboxFinder extends Finder {
523
524        /**
525         * Constructs CheckboxFinder.
526         *
527         * @param sf other searching criteria.
528         */
529        public CheckboxFinder(ComponentChooser sf) {
530            super(Checkbox.class, sf);
531        }
532
533        /**
534         * Constructs CheckboxFinder.
535         */
536        public CheckboxFinder() {
537            super(Checkbox.class);
538        }
539    }
540}
541