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.Component;
26import java.awt.Container;
27import java.awt.Dialog;
28import java.awt.Window;
29
30import javax.accessibility.AccessibleContext;
31import javax.swing.JDialog;
32import javax.swing.JLayeredPane;
33import javax.swing.JMenuBar;
34import javax.swing.JRootPane;
35
36import org.netbeans.jemmy.ComponentChooser;
37import org.netbeans.jemmy.DialogWaiter;
38import org.netbeans.jemmy.JemmyProperties;
39import org.netbeans.jemmy.TestOut;
40import org.netbeans.jemmy.TimeoutExpiredException;
41import org.netbeans.jemmy.Timeouts;
42
43/**
44 * <BR><BR>Timeouts used: <BR>
45 * DialogWaiter.WaitDialogTimeout - time to wait dialog displayed <BR>
46 * DialogWaiter.AfterDialogTimeout - time to sleep after dialog has been
47 * dispayed <BR>.
48 *
49 * @see org.netbeans.jemmy.Timeouts
50 *
51 * @author Alexandre Iline (alexandre.iline@oracle.com)
52 *
53 */
54public class JDialogOperator extends DialogOperator {
55
56    /**
57     * Constructor.
58     *
59     * @param w a component
60     */
61    public JDialogOperator(JDialog w) {
62        super(w);
63    }
64
65    /**
66     * Constructs a JDialogOperator object.
67     *
68     * @param chooser a component chooser specifying searching criteria.
69     * @param index an index between appropriate ones.
70     * @param env an operator to copy environment from.
71     */
72    public JDialogOperator(ComponentChooser chooser, int index, Operator env) {
73        this(waitJDialog(new JDialogFinder(chooser),
74                index,
75                env.getTimeouts(),
76                env.getOutput()));
77        copyEnvironment(env);
78    }
79
80    /**
81     * Constructs a JDialogOperator object.
82     *
83     * @param chooser a component chooser specifying searching criteria.
84     * @param index an index between appropriate ones.
85     */
86    public JDialogOperator(ComponentChooser chooser, int index) {
87        this(chooser, index, Operator.getEnvironmentOperator());
88    }
89
90    /**
91     * Constructs a JDialogOperator object.
92     *
93     * @param chooser a component chooser specifying searching criteria.
94     */
95    public JDialogOperator(ComponentChooser chooser) {
96        this(chooser, 0);
97    }
98
99    /**
100     * Constructs a JDialogOperator object.
101     *
102     * @param owner window - owner
103     * @param chooser a component chooser specifying searching criteria.
104     * @param index an index between appropriate ones.
105     */
106    public JDialogOperator(WindowOperator owner, ComponentChooser chooser, int index) {
107        this((JDialog) owner.
108                waitSubWindow(new JDialogFinder(chooser),
109                        index));
110        copyEnvironment(owner);
111    }
112
113    /**
114     * Constructs a JDialogOperator object.
115     *
116     * @param owner window - owner
117     * @param chooser a component chooser specifying searching criteria.
118     */
119    public JDialogOperator(WindowOperator owner, ComponentChooser chooser) {
120        this(owner, chooser, 0);
121    }
122
123    /**
124     * Constructor. Waits for the dialog with "title" subtitle. Uses owner's
125     * timeout and output for waiting and to init operator.
126     *
127     * @param owner Operator pointing to a window owner.
128     * @param title The desired title.
129     * @param index Ordinal index. The first dialog has {@code index} 0.
130     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
131     *
132     */
133    public JDialogOperator(WindowOperator owner, String title, int index) {
134        this(waitJDialog(owner,
135                new JDialogFinder(new DialogByTitleFinder(title,
136                        owner.getComparator())),
137                index));
138        copyEnvironment(owner);
139    }
140
141    /**
142     * Constructor. Waits for the dialog with "title" subtitle. Uses owner's
143     * timeout and output for waiting and to init operator.
144     *
145     * @param owner Operator pointing to a window owner.
146     * @param title The desired title.
147     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
148     *
149     */
150    public JDialogOperator(WindowOperator owner, String title) {
151        this(owner, title, 0);
152    }
153
154    /**
155     * Constructor. Waits for the index'th dialog between owner's children. Uses
156     * owner'th timeout and output for waiting and to init operator.
157     *
158     * @param owner Operator pointing to a window owner.
159     * @param index Ordinal component index.
160     *
161     */
162    public JDialogOperator(WindowOperator owner, int index) {
163        this(waitJDialog(owner,
164                new JDialogFinder(),
165                index));
166        copyEnvironment(owner);
167    }
168
169    /**
170     * Constructor. Waits for the first dialog between owner's children. Uses
171     * owner'th timeout and output for waiting and to init operator.
172     *
173     * @param owner Operator pointing to a window owner.
174     *
175     */
176    public JDialogOperator(WindowOperator owner) {
177        this(owner, 0);
178    }
179
180    /**
181     * Constructor. Waits for the dialog with "title" subtitle. Constructor can
182     * be used in complicated cases when output or timeouts should differ from
183     * default.
184     *
185     * @param title a window title
186     * @param index Ordinal component index.
187     * @param env an operator to copy environment from.
188     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
189     *
190     */
191    public JDialogOperator(String title, int index, Operator env) {
192        this(new JDialogFinder(new DialogByTitleFinder(title,
193                env.getComparator())),
194                index, env);
195    }
196
197    /**
198     * Constructor. Waits for the dialog with "title" subtitle. Uses current
199     * timeouts and output values.
200     *
201     * @param title a window title
202     * @param index Ordinal component index.
203     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
204     * @see JemmyProperties#getCurrentTimeouts()
205     * @see JemmyProperties#getCurrentOutput()
206     *
207     */
208    public JDialogOperator(String title, int index) {
209        this(title, index,
210                ComponentOperator.getEnvironmentOperator());
211    }
212
213    /**
214     * Constructor. Waits for the dialog with "title" subtitle. Uses current
215     * timeouts and output values.
216     *
217     * @param title a window title
218     * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean)
219     * @see JemmyProperties#getCurrentTimeouts()
220     * @see JemmyProperties#getCurrentOutput()
221     *
222     */
223    public JDialogOperator(String title) {
224        this(title, 0);
225    }
226
227    /**
228     * Constructor. Waits for the index'th dialog. Uses current timeout and
229     * output for waiting and to init operator.
230     *
231     * @param index Ordinal component index.
232     *
233     */
234    public JDialogOperator(int index) {
235        this(waitJDialog(new JDialogFinder(),
236                index,
237                ComponentOperator.getEnvironmentOperator().getTimeouts(),
238                ComponentOperator.getEnvironmentOperator().getOutput()));
239        copyEnvironment(ComponentOperator.getEnvironmentOperator());
240    }
241
242    /**
243     * Constructor. Waits for the first dialog. Uses current timeout and output
244     * for waiting and to init operator.
245     *
246     */
247    public JDialogOperator() {
248        this(0);
249    }
250
251    /**
252     * Searches an index'th dialog.
253     *
254     * @param chooser a component chooser specifying searching criteria.
255     * @param index an index between appropriate ones.
256     * @return JDialog instance or null if component was not found.
257     */
258    public static JDialog findJDialog(ComponentChooser chooser, int index) {
259        return (JDialog) DialogWaiter.getDialog(new JDialogFinder(chooser), index);
260    }
261
262    /**
263     * Searches a dialog.
264     *
265     * @param chooser a component chooser specifying searching criteria.
266     * @return JDialog instance or null if component was not found.
267     */
268    public static JDialog findJDialog(ComponentChooser chooser) {
269        return findJDialog(chooser, 0);
270    }
271
272    /**
273     * Searches an index'th dialog by title.
274     *
275     * @param title Dialog title
276     * @param ce Compare exactly. If true, text can be a substring of caption.
277     * @param cc Compare case sensitively. If true, both text and caption are
278     * @param index an index between appropriate ones.
279     * @return JDialog instance or null if component was not found.
280     */
281    public static JDialog findJDialog(String title, boolean ce, boolean cc, int index) {
282        return ((JDialog) DialogWaiter.
283                getDialog(new JDialogFinder(new DialogByTitleFinder(title,
284                        new DefaultStringComparator(ce, cc))),
285                        index));
286    }
287
288    /**
289     * Searches a dialog by title.
290     *
291     * @param title Dialog title
292     * @param ce Compare exactly. If true, text can be a substring of caption.
293     * @param cc Compare case sensitively. If true, both text and caption are
294     * @return JDialog instance or null if component was not found.
295     */
296    public static JDialog findJDialog(String title, boolean ce, boolean cc) {
297        return findJDialog(title, ce, cc, 0);
298    }
299
300    /**
301     * Searches an index'th dialog between owner's owned windows.
302     *
303     * @param owner Window - dialog owner.
304     * @param chooser a component chooser specifying searching criteria.
305     * @param index an index between appropriate ones.
306     * @return JDialog instance or null if component was not found.
307     */
308    public static JDialog findJDialog(Window owner, ComponentChooser chooser, int index) {
309        return (JDialog) DialogWaiter.getDialog(owner, new JDialogFinder(chooser), index);
310    }
311
312    /**
313     * Searches a dialog between owner's owned windows.
314     *
315     * @param owner Window - dialog owner.
316     * @param chooser a component chooser specifying searching criteria.
317     * @return JDialog instance or null if component was not found.
318     */
319    public static JDialog findJDialog(Window owner, ComponentChooser chooser) {
320        return findJDialog(owner, chooser, 0);
321    }
322
323    /**
324     * Searches an index'th dialog by title between owner's owned windows.
325     *
326     * @param owner Window - dialog owner.
327     * @param title Dialog title
328     * @param ce Compare exactly. If true, text can be a substring of caption.
329     * @param cc Compare case sensitively. If true, both text and caption are
330     * @param index an index between appropriate ones.
331     * @return JDialog instance or null if component was not found.
332     */
333    public static JDialog findJDialog(Window owner, String title, boolean ce, boolean cc, int index) {
334        return ((JDialog) DialogWaiter.
335                getDialog(owner,
336                        new JDialogFinder(new DialogByTitleFinder(title,
337                                new DefaultStringComparator(ce, cc))),
338                        index));
339    }
340
341    /**
342     * Searches a dialog by title between owner's owned windows.
343     *
344     * @param owner Window - dialog owner.
345     * @param title Dialog title
346     * @param ce Compare exactly. If true, text can be a substring of caption.
347     * @param cc Compare case sensitively. If true, both text and caption are
348     * @return JDialog instance or null if component was not found.
349     */
350    public static JDialog findJDialog(Window owner, String title, boolean ce, boolean cc) {
351        return findJDialog(owner, title, ce, cc, 0);
352    }
353
354    /**
355     * Waits an index'th dialog.
356     *
357     * @param chooser a component chooser specifying searching criteria.
358     * @param index an index between appropriate ones.
359     * @return JDialog instance or null if component was not found.
360     *
361     */
362    public static JDialog waitJDialog(ComponentChooser chooser, int index) {
363        return (waitJDialog(chooser, index,
364                JemmyProperties.getCurrentTimeouts(),
365                JemmyProperties.getCurrentOutput()));
366    }
367
368    /**
369     * Waits a dialog.
370     *
371     * @param chooser a component chooser specifying searching criteria.
372     * @return JDialog instance or null if component was not found.
373     *
374     */
375    public static JDialog waitJDialog(ComponentChooser chooser) {
376        return waitJDialog(chooser, 0);
377    }
378
379    /**
380     * Waits an index'th dialog by title.
381     *
382     * @param title Dialog title
383     * @param ce Compare exactly. If true, text can be a substring of caption.
384     * @param cc Compare case sensitively. If true, both text and caption are
385     * @param index an index between appropriate ones.
386     * @return JDialog instance or null if component was not found.
387     *
388     */
389    public static JDialog waitJDialog(String title, boolean ce, boolean cc, int index) {
390        return (waitJDialog(new JDialogFinder(new DialogByTitleFinder(title,
391                new DefaultStringComparator(ce, cc))),
392                index));
393    }
394
395    /**
396     * Waits a dialog by title.
397     *
398     * @param title Dialog title
399     * @param ce Compare exactly. If true, text can be a substring of caption.
400     * @param cc Compare case sensitively. If true, both text and caption are
401     * @return JDialog instance or null if component was not found.
402     *
403     */
404    public static JDialog waitJDialog(String title, boolean ce, boolean cc) {
405        return waitJDialog(title, ce, cc, 0);
406    }
407
408    /**
409     * Waits an index'th dialog between owner's owned windows.
410     *
411     * @param owner Window - dialog owner.
412     * @param chooser a component chooser specifying searching criteria.
413     * @param index an index between appropriate ones.
414     * @return JDialog instance or null if component was not found.
415     *
416     */
417    public static JDialog waitJDialog(Window owner, ComponentChooser chooser, int index) {
418        return (waitJDialog(owner, chooser, index,
419                JemmyProperties.getCurrentTimeouts(),
420                JemmyProperties.getCurrentOutput()));
421    }
422
423    /**
424     * Waits a dialog between owner's owned windows.
425     *
426     * @param owner Window - dialog owner.
427     * @param chooser a component chooser specifying searching criteria.
428     * @return JDialog instance or null if component was not found.
429     *
430     */
431    public static JDialog waitJDialog(Window owner, ComponentChooser chooser) {
432        return waitJDialog(owner, chooser, 0);
433    }
434
435    /**
436     * Waits an index'th dialog by title between owner's owned windows.
437     *
438     * @param owner Window - dialog owner.
439     * @param title Dialog title
440     * @param ce Compare exactly. If true, text can be a substring of caption.
441     * @param cc Compare case sensitively. If true, both text and caption are
442     * @param index an index between appropriate ones.
443     * @return JDialog instance or null if component was not found.
444     *
445     */
446    public static JDialog waitJDialog(Window owner, String title, boolean ce, boolean cc, int index) {
447        return (waitJDialog(owner, new JDialogFinder(new DialogByTitleFinder(title,
448                new DefaultStringComparator(ce, cc))),
449                index));
450    }
451
452    /**
453     * Waits a dialog by title between owner's owned windows.
454     *
455     * @param owner Window - dialog owner.
456     * @param title Dialog title
457     * @param ce Compare exactly. If true, text can be a substring of caption.
458     * @param cc Compare case sensitively. If true, both text and caption are
459     * @return JDialog instance or null if component was not found.
460     *
461     */
462    public static JDialog waitJDialog(Window owner, String title, boolean ce, boolean cc) {
463        return waitJDialog(owner, title, ce, cc, 0);
464    }
465
466    /**
467     * Searhs for modal dialog currently staying on top.
468     *
469     * @return dialog or null if no modal dialog is currently displayed.
470     */
471    public static Dialog getTopModalDialog() {
472        return (DialogWaiter.getDialog(new ComponentChooser() {
473            @Override
474            public boolean checkComponent(Component comp) {
475                if (comp instanceof Dialog) {
476                    Dialog dialog = (Dialog) comp;
477                    if (dialog.isModal()) {
478                        Window[] ow = dialog.getOwnedWindows();
479                        for (Window anOw : ow) {
480                            if (anOw.isVisible()) {
481                                return false;
482                            }
483                        }
484                        return true;
485                    }
486                }
487                return false;
488            }
489
490            @Override
491            public String getDescription() {
492                return "Upper modal dialog";
493            }
494
495            @Override
496            public String toString() {
497                return "JDialogOperator.getTopModalDialog.ComponentChooser{description = " + getDescription() + '}';
498            }
499        }));
500    }
501
502    ////////////////////////////////////////////////////////
503    //Mapping                                             //
504    /**
505     * Maps {@code JDialog.getAccessibleContext()} through queue
506     */
507    public AccessibleContext getAccessibleContext() {
508        return (runMapping(new MapAction<AccessibleContext>("getAccessibleContext") {
509            @Override
510            public AccessibleContext map() {
511                return getSource().getAccessibleContext();
512            }
513        }));
514    }
515
516    /**
517     * Maps {@code JDialog.getContentPane()} through queue
518     */
519    public Container getContentPane() {
520        return (runMapping(new MapAction<Container>("getContentPane") {
521            @Override
522            public Container map() {
523                return ((JDialog) getSource()).getContentPane();
524            }
525        }));
526    }
527
528    /**
529     * Maps {@code JDialog.getDefaultCloseOperation()} through queue
530     */
531    public int getDefaultCloseOperation() {
532        return (runMapping(new MapIntegerAction("getDefaultCloseOperation") {
533            @Override
534            public int map() {
535                return ((JDialog) getSource()).getDefaultCloseOperation();
536            }
537        }));
538    }
539
540    /**
541     * Maps {@code JDialog.getGlassPane()} through queue
542     */
543    public Component getGlassPane() {
544        return (runMapping(new MapAction<Component>("getGlassPane") {
545            @Override
546            public Component map() {
547                return ((JDialog) getSource()).getGlassPane();
548            }
549        }));
550    }
551
552    /**
553     * Maps {@code JDialog.getJMenuBar()} through queue
554     */
555    public JMenuBar getJMenuBar() {
556        return (runMapping(new MapAction<JMenuBar>("getJMenuBar") {
557            @Override
558            public JMenuBar map() {
559                return ((JDialog) getSource()).getJMenuBar();
560            }
561        }));
562    }
563
564    /**
565     * Maps {@code JDialog.getLayeredPane()} through queue
566     */
567    public JLayeredPane getLayeredPane() {
568        return (runMapping(new MapAction<JLayeredPane>("getLayeredPane") {
569            @Override
570            public JLayeredPane map() {
571                return ((JDialog) getSource()).getLayeredPane();
572            }
573        }));
574    }
575
576    /**
577     * Maps {@code JDialog.getRootPane()} through queue
578     */
579    public JRootPane getRootPane() {
580        return (runMapping(new MapAction<JRootPane>("getRootPane") {
581            @Override
582            public JRootPane map() {
583                return ((JDialog) getSource()).getRootPane();
584            }
585        }));
586    }
587
588    /**
589     * Maps {@code JDialog.setContentPane(Container)} through queue
590     */
591    public void setContentPane(final Container container) {
592        runMapping(new MapVoidAction("setContentPane") {
593            @Override
594            public void map() {
595                ((JDialog) getSource()).setContentPane(container);
596            }
597        });
598    }
599
600    /**
601     * Maps {@code JDialog.setDefaultCloseOperation(int)} through queue
602     */
603    public void setDefaultCloseOperation(final int i) {
604        runMapping(new MapVoidAction("setDefaultCloseOperation") {
605            @Override
606            public void map() {
607                ((JDialog) getSource()).setDefaultCloseOperation(i);
608            }
609        });
610    }
611
612    /**
613     * Maps {@code JDialog.setGlassPane(Component)} through queue
614     */
615    public void setGlassPane(final Component component) {
616        runMapping(new MapVoidAction("setGlassPane") {
617            @Override
618            public void map() {
619                ((JDialog) getSource()).setGlassPane(component);
620            }
621        });
622    }
623
624    /**
625     * Maps {@code JDialog.setJMenuBar(JMenuBar)} through queue
626     */
627    public void setJMenuBar(final JMenuBar jMenuBar) {
628        runMapping(new MapVoidAction("setJMenuBar") {
629            @Override
630            public void map() {
631                ((JDialog) getSource()).setJMenuBar(jMenuBar);
632            }
633        });
634    }
635
636    /**
637     * Maps {@code JDialog.setLayeredPane(JLayeredPane)} through queue
638     */
639    public void setLayeredPane(final JLayeredPane jLayeredPane) {
640        runMapping(new MapVoidAction("setLayeredPane") {
641            @Override
642            public void map() {
643                ((JDialog) getSource()).setLayeredPane(jLayeredPane);
644            }
645        });
646    }
647
648    /**
649     * Maps {@code JDialog.setLocationRelativeTo(Component)} through queue
650     */
651    public void setLocationRelativeTo(final Component component) {
652        runMapping(new MapVoidAction("setLocationRelativeTo") {
653            @Override
654            public void map() {
655                ((JDialog) getSource()).setLocationRelativeTo(component);
656            }
657        });
658    }
659
660    //End of mapping                                      //
661    ////////////////////////////////////////////////////////
662    /**
663     * A method to be used from subclasses. Uses timeouts and output passed as
664     * parameters during the waiting.
665     *
666     * @param chooser org.netbeans.jemmy.ComponentChooser implementation.
667     * @param index Ordinal component index.
668     * @param timeouts timeouts to be used during the waiting.
669     * @param output an output to be used during the waiting.
670     * @return Component instance or null if component was not found.
671     */
672    protected static JDialog waitJDialog(ComponentChooser chooser, int index,
673            Timeouts timeouts, TestOut output) {
674        try {
675            DialogWaiter waiter = new DialogWaiter();
676            waiter.setTimeouts(timeouts);
677            waiter.setOutput(output);
678            return ((JDialog) waiter.
679                    waitDialog(new JDialogFinder(chooser), index));
680        } catch (InterruptedException e) {
681            output.printStackTrace(e);
682            return null;
683        }
684    }
685
686    /**
687     * A method to be used from subclasses. Uses {@code owner}'s timeouts
688     * and output during the waiting.
689     *
690     * @param owner a window - dialog owner.
691     * @param chooser org.netbeans.jemmy.ComponentChooser implementation.
692     * @param index Ordinal component index.
693     * @return Component instance or null if component was not found.
694     * @throws TimeoutExpiredException
695     */
696    protected static JDialog waitJDialog(WindowOperator owner, ComponentChooser chooser, int index) {
697        return (waitJDialog((Window) owner.getSource(),
698                chooser, index,
699                owner.getTimeouts(), owner.getOutput()));
700    }
701
702    /**
703     * A method to be used from subclasses. Uses timeouts and output passed as
704     * parameters during the waiting.
705     *
706     * @param owner a window - dialog owner.
707     * @param chooser org.netbeans.jemmy.ComponentChooser implementation.
708     * @param index Ordinal component index.
709     * @param timeouts timeouts to be used during the waiting.
710     * @param output an output to be used during the waiting.
711     * @return Component instance or null if component was not found.
712     */
713    protected static JDialog waitJDialog(Window owner, ComponentChooser chooser, int index,
714            Timeouts timeouts, TestOut output) {
715        try {
716            DialogWaiter waiter = new DialogWaiter();
717            waiter.setTimeouts(timeouts);
718            waiter.setOutput(output);
719            return ((JDialog) waiter.
720                    waitDialog(owner, new JDialogFinder(chooser), index));
721        } catch (InterruptedException e) {
722            JemmyProperties.getCurrentOutput().printStackTrace(e);
723            return null;
724        }
725    }
726
727    /**
728     * Checks component type.
729     */
730    public static class JDialogFinder extends Finder {
731
732        /**
733         * Constructs JDialogFinder.
734         *
735         * @param sf other searching criteria.
736         */
737        public JDialogFinder(ComponentChooser sf) {
738            super(JDialog.class, sf);
739        }
740
741        /**
742         * Constructs JDialogFinder.
743         */
744        public JDialogFinder() {
745            super(JDialog.class);
746        }
747    }
748}
749