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. Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package org.netbeans.jemmy.operators;
26 
27 import java.awt.Container;
28 import java.awt.Scrollbar;
29 import java.awt.event.AdjustmentListener;
30 
31 import org.netbeans.jemmy.Action;
32 import org.netbeans.jemmy.ComponentChooser;
33 import org.netbeans.jemmy.ComponentSearcher;
34 import org.netbeans.jemmy.Outputable;
35 import org.netbeans.jemmy.TestOut;
36 import org.netbeans.jemmy.TimeoutExpiredException;
37 import org.netbeans.jemmy.Timeoutable;
38 import org.netbeans.jemmy.Timeouts;
39 import org.netbeans.jemmy.Waitable;
40 import org.netbeans.jemmy.drivers.DriverManager;
41 import org.netbeans.jemmy.drivers.ScrollDriver;
42 import org.netbeans.jemmy.drivers.scrolling.ScrollAdjuster;
43 
44 /**
45  * <BR><BR>Timeouts used: <BR>
46  * ScrollbarOperator.WholeScrollTimeout - time for one scroll click <BR>
47  * ComponentOperator.WaitComponentTimeout - time to wait component displayed
48  * <BR>.
49  *
50  * @see org.netbeans.jemmy.Timeouts
51  *
52  * @author Alexandre Iline (alexandre.iline@oracle.com)
53  *
54  */
55 public class ScrollbarOperator extends ComponentOperator
56         implements Timeoutable, Outputable {
57 
58     private final static long ONE_SCROLL_CLICK_TIMEOUT = 0;
59     private final static long WHOLE_SCROLL_TIMEOUT = 60000;
60     private final static long BEFORE_DROP_TIMEOUT = 0;
61     private final static long DRAG_AND_DROP_SCROLLING_DELTA = 0;
62 
63     private Timeouts timeouts;
64     private TestOut output;
65 
66     private ScrollDriver driver;
67 
68     /**
69      * Constructs a ScrollbarOperator object.
70      *
71      * @param b a component
72      */
ScrollbarOperator(Scrollbar b)73     public ScrollbarOperator(Scrollbar b) {
74         super(b);
75         driver = DriverManager.getScrollDriver(getClass());
76     }
77 
78     /**
79      * Constructs a ScrollbarOperator object.
80      *
81      * @param cont a container
82      * @param chooser a component chooser specifying searching criteria.
83      * @param index an index between appropriate ones.
84      */
ScrollbarOperator(ContainerOperator<?> cont, ComponentChooser chooser, int index)85     public ScrollbarOperator(ContainerOperator<?> cont, ComponentChooser chooser, int index) {
86         this((Scrollbar) cont.
87                 waitSubComponent(new ScrollbarFinder(chooser),
88                         index));
89         copyEnvironment(cont);
90     }
91 
92     /**
93      * Constructs a ScrollbarOperator object.
94      *
95      * @param cont a container
96      * @param chooser a component chooser specifying searching criteria.
97      */
ScrollbarOperator(ContainerOperator<?> cont, ComponentChooser chooser)98     public ScrollbarOperator(ContainerOperator<?> cont, ComponentChooser chooser) {
99         this(cont, chooser, 0);
100     }
101 
102     /**
103      * Constructs a ScrollbarOperator object.
104      *
105      * @param cont a container
106      * @param index an index between appropriate ones.
107      */
ScrollbarOperator(ContainerOperator<?> cont, int index)108     public ScrollbarOperator(ContainerOperator<?> cont, int index) {
109         this((Scrollbar) waitComponent(cont,
110                 new ScrollbarFinder(),
111                 index));
112         copyEnvironment(cont);
113     }
114 
115     /**
116      * Constructs a ScrollbarOperator object.
117      *
118      * @param cont a container
119      */
ScrollbarOperator(ContainerOperator<?> cont)120     public ScrollbarOperator(ContainerOperator<?> cont) {
121         this(cont, 0);
122     }
123 
124     /**
125      * Finds a scrollbar.
126      *
127      * @param cont a container
128      * @param chooser a component chooser specifying searching criteria.
129      * @param index an index between appropriate ones.
130      * @return the scrollbar fitting searching criteria
131      */
findScrollbar(Container cont, ComponentChooser chooser, int index)132     public static Scrollbar findScrollbar(Container cont, ComponentChooser chooser, int index) {
133         return (Scrollbar) findComponent(cont, new ScrollbarFinder(chooser), index);
134     }
135 
136     /**
137      * Finds a scrollbar.
138      *
139      * @param cont a container
140      * @param chooser a component chooser specifying searching criteria.
141      * @return the scrollbar fitting searching criteria
142      */
findScrollbar(Container cont, ComponentChooser chooser)143     public static Scrollbar findScrollbar(Container cont, ComponentChooser chooser) {
144         return findScrollbar(cont, chooser, 0);
145     }
146 
147     /**
148      * Finds a scrollbar.
149      *
150      * @param cont a container
151      * @param index an index between appropriate ones.
152      * @return the scrollbar fitting searching criteria
153      */
findScrollbar(Container cont, int index)154     public static Scrollbar findScrollbar(Container cont, int index) {
155         return findScrollbar(cont, ComponentSearcher.getTrueChooser(Integer.toString(index) + "'th Scrollbar instance"), index);
156     }
157 
158     /**
159      * Finds a scrollbar.
160      *
161      * @param cont a container
162      * @return the scrollbar fitting searching criteria
163      */
findScrollbar(Container cont)164     public static Scrollbar findScrollbar(Container cont) {
165         return findScrollbar(cont, 0);
166     }
167 
168     /**
169      * Waits a scrollbar.
170      *
171      * @param cont a container
172      * @param chooser a component chooser specifying searching criteria.
173      * @param index an index between appropriate ones.
174      * @return the scrollbar fitting searching criteria
175      */
waitScrollbar(Container cont, ComponentChooser chooser, int index)176     public static Scrollbar waitScrollbar(Container cont, ComponentChooser chooser, int index) {
177         return (Scrollbar) waitComponent(cont, new ScrollbarFinder(chooser), index);
178     }
179 
180     /**
181      * Waits a scrollbar.
182      *
183      * @param cont a container
184      * @param chooser a component chooser specifying searching criteria.
185      * @return the scrollbar fitting searching criteria
186      */
waitScrollbar(Container cont, ComponentChooser chooser)187     public static Scrollbar waitScrollbar(Container cont, ComponentChooser chooser) {
188         return waitScrollbar(cont, chooser, 0);
189     }
190 
191     /**
192      * Waits a scrollbar.
193      *
194      * @param cont a container
195      * @param index an index between appropriate ones.
196      * @return the scrollbar fitting searching criteria
197      */
waitScrollbar(Container cont, int index)198     public static Scrollbar waitScrollbar(Container cont, int index) {
199         return waitScrollbar(cont, ComponentSearcher.getTrueChooser(Integer.toString(index) + "'th Scrollbar instance"), index);
200     }
201 
202     /**
203      * Waits a scrollbar.
204      *
205      * @param cont a container
206      * @return the scrollbar fitting searching criteria
207      */
waitScrollbar(Container cont)208     public static Scrollbar waitScrollbar(Container cont) {
209         return waitScrollbar(cont, 0);
210     }
211 
212     static {
213         Timeouts.initDefault("ScrollbarOperator.OneScrollClickTimeout", ONE_SCROLL_CLICK_TIMEOUT);
214         Timeouts.initDefault("ScrollbarOperator.WholeScrollTimeout", WHOLE_SCROLL_TIMEOUT);
215         Timeouts.initDefault("ScrollbarOperator.BeforeDropTimeout", BEFORE_DROP_TIMEOUT);
216         Timeouts.initDefault("ScrollbarOperator.DragAndDropScrollingDelta", DRAG_AND_DROP_SCROLLING_DELTA);
217     }
218 
219     @Override
setOutput(TestOut out)220     public void setOutput(TestOut out) {
221         output = out;
222         super.setOutput(output.createErrorOutput());
223     }
224 
225     @Override
getOutput()226     public TestOut getOutput() {
227         return output;
228     }
229 
230     @Override
setTimeouts(Timeouts timeouts)231     public void setTimeouts(Timeouts timeouts) {
232         this.timeouts = timeouts;
233         super.setTimeouts(timeouts);
234     }
235 
236     @Override
getTimeouts()237     public Timeouts getTimeouts() {
238         return timeouts;
239     }
240 
241     @Override
copyEnvironment(Operator anotherOperator)242     public void copyEnvironment(Operator anotherOperator) {
243         super.copyEnvironment(anotherOperator);
244         driver
245                 = (ScrollDriver) DriverManager.
246                 getDriver(DriverManager.SCROLL_DRIVER_ID,
247                         getClass(),
248                         anotherOperator.getProperties());
249     }
250 
251     /**
252      * Scrolls scrollbar to the position defined by w parameter. Uses
253      * ScrollDriver registered to this operator type.
254      *
255      * @param w Scrolling is stopped when w.actionProduced(waiterParam) != null
256      * @param waiterParam a waiting parameter.
257      * @param increase a scrolling direction.
258      * @throws TimeoutExpiredException
259      */
scrollTo(Waitable<?, P> w, P waiterParam, boolean increase)260     public <P> void scrollTo(Waitable<?, P> w, P waiterParam, boolean increase) {
261         scrollTo(new WaitableChecker<>(w, waiterParam, increase, this));
262     }
263 
264     /**
265      * Scrolls scrollbar to the position defined by a ScrollAdjuster
266      * implementation.
267      *
268      * @param adj defines scrolling direction, and so on.
269      * @throws TimeoutExpiredException
270      */
scrollTo(final ScrollAdjuster adj)271     public void scrollTo(final ScrollAdjuster adj) {
272         produceTimeRestricted(new Action<Void, Void>() {
273             @Override
274             public Void launch(Void obj) {
275                 driver.scroll(ScrollbarOperator.this, adj);
276                 return null;
277             }
278 
279             @Override
280             public String getDescription() {
281                 return "Scrolling";
282             }
283 
284             @Override
285             public String toString() {
286                 return "ScrollbarOperator.scrollTo.Action{description = " + getDescription() + '}';
287             }
288         }, "ScrollbarOperator.WholeScrollTimeout");
289     }
290 
291     /**
292      * Scrolls scroll bar to necessary value.
293      *
294      * @param value Scroll bar value to scroll to.
295      * @throws TimeoutExpiredException
296      */
scrollToValue(int value)297     public void scrollToValue(int value) {
298         output.printTrace("Scroll Scrollbar to " + Integer.toString(value)
299                 + " value\n" + toStringSource());
300         output.printGolden("Scroll Scrollbar to " + Integer.toString(value) + " value");
301         scrollTo(new ValueScrollAdjuster(value));
302     }
303 
304     /**
305      * Scrolls scroll bar to necessary proportional value.
306      *
307      * @param proportionalValue Proportional scroll to. Must be >= 0 and <= 1.
308      * @throws TimeoutExpiredException
309      */
scrollToValue(double proportionalValue)310     public void scrollToValue(double proportionalValue) {
311         output.printTrace("Scroll Scrollbar to " + Double.toString(proportionalValue)
312                 + " proportional value\n" + toStringSource());
313         output.printGolden("Scroll Scrollbar to " + Double.toString(proportionalValue) + " proportional value");
314         scrollTo(new ValueScrollAdjuster((int) (getMinimum()
315                 + (getMaximum()
316                 - getVisibleAmount()
317                 - getMinimum()) * proportionalValue)));
318     }
319 
320     /**
321      * Scrolls to minimum value.
322      *
323      * @throws TimeoutExpiredException
324      */
scrollToMinimum()325     public void scrollToMinimum() {
326         output.printTrace("Scroll Scrollbar to minimum value\n"
327                 + toStringSource());
328         output.printGolden("Scroll Scrollbar to minimum value");
329         produceTimeRestricted(new Action<Void, Void>() {
330             @Override
331             public Void launch(Void obj) {
332                 driver.scrollToMinimum(ScrollbarOperator.this, getOrientation());
333                 return null;
334             }
335 
336             @Override
337             public String getDescription() {
338                 return "Scrolling";
339             }
340 
341             @Override
342             public String toString() {
343                 return "ScrollbarOperator.scrollToMinimum.Action{description = " + getDescription() + '}';
344             }
345         }, "ScrollbarOperator.WholeScrollTimeout");
346     }
347 
348     /**
349      * Scrolls to maximum value.
350      *
351      * @throws TimeoutExpiredException
352      */
scrollToMaximum()353     public void scrollToMaximum() {
354         output.printTrace("Scroll Scrollbar to maximum value\n"
355                 + toStringSource());
356         output.printGolden("Scroll Scrollbar to maximum value");
357         produceTimeRestricted(new Action<Void, Void>() {
358             @Override
359             public Void launch(Void obj) {
360                 driver.scrollToMaximum(ScrollbarOperator.this, getOrientation());
361                 return null;
362             }
363 
364             @Override
365             public String getDescription() {
366                 return "Scrolling";
367             }
368 
369             @Override
370             public String toString() {
371                 return "ScrollbarOperator.scrollToMaximum.Action{description = " + getDescription() + '}';
372             }
373         }, "ScrollbarOperator.WholeScrollTimeout");
374     }
375     ////////////////////////////////////////////////////////
376     //Mapping                                             //
377 
378     /**
379      * Maps {@code Scrollbar.addAdjustmentListener(AdjustmentListener)}
380      * through queue
381      */
addAdjustmentListener(final AdjustmentListener adjustmentListener)382     public void addAdjustmentListener(final AdjustmentListener adjustmentListener) {
383         runMapping(new MapVoidAction("addAdjustmentListener") {
384             @Override
385             public void map() {
386                 ((Scrollbar) getSource()).addAdjustmentListener(adjustmentListener);
387             }
388         });
389     }
390 
391     /**
392      * Maps {@code Scrollbar.getBlockIncrement()} through queue
393      */
getBlockIncrement()394     public int getBlockIncrement() {
395         return (runMapping(new MapIntegerAction("getBlockIncrement") {
396             @Override
397             public int map() {
398                 return ((Scrollbar) getSource()).getBlockIncrement();
399             }
400         }));
401     }
402 
403     /**
404      * Maps {@code Scrollbar.getMaximum()} through queue
405      */
406     public int getMaximum() {
407         return (runMapping(new MapIntegerAction("getMaximum") {
408             @Override
409             public int map() {
410                 return ((Scrollbar) getSource()).getMaximum();
411             }
412         }));
413     }
414 
415     /**
416      * Maps {@code Scrollbar.getMinimum()} through queue
417      */
418     public int getMinimum() {
419         return (runMapping(new MapIntegerAction("getMinimum") {
420             @Override
421             public int map() {
422                 return ((Scrollbar) getSource()).getMinimum();
423             }
424         }));
425     }
426 
427     /**
428      * Maps {@code Scrollbar.getOrientation()} through queue
429      */
430     public int getOrientation() {
431         return (runMapping(new MapIntegerAction("getOrientation") {
432             @Override
433             public int map() {
434                 return ((Scrollbar) getSource()).getOrientation();
435             }
436         }));
437     }
438 
439     /**
440      * Maps {@code Scrollbar.getUnitIncrement()} through queue
441      */
442     public int getUnitIncrement() {
443         return (runMapping(new MapIntegerAction("getUnitIncrement") {
444             @Override
445             public int map() {
446                 return ((Scrollbar) getSource()).getUnitIncrement();
447             }
448         }));
449     }
450 
451     /**
452      * Maps {@code Scrollbar.getValue()} through queue
453      */
454     public int getValue() {
455         return (runMapping(new MapIntegerAction("getValue") {
456             @Override
457             public int map() {
458                 return ((Scrollbar) getSource()).getValue();
459             }
460         }));
461     }
462 
463     /**
464      * Maps {@code Scrollbar.getVisibleAmount()} through queue
465      */
466     public int getVisibleAmount() {
467         return (runMapping(new MapIntegerAction("getVisibleAmount") {
468             @Override
469             public int map() {
470                 return ((Scrollbar) getSource()).getVisibleAmount();
471             }
472         }));
473     }
474 
475     /**
476      * Maps {@code Scrollbar.removeAdjustmentListener(AdjustmentListener)}
477      * through queue
478      */
479     public void removeAdjustmentListener(final AdjustmentListener adjustmentListener) {
480         runMapping(new MapVoidAction("removeAdjustmentListener") {
481             @Override
482             public void map() {
483                 ((Scrollbar) getSource()).removeAdjustmentListener(adjustmentListener);
484             }
485         });
486     }
487 
488     /**
489      * Maps {@code Scrollbar.setBlockIncrement(int)} through queue
490      */
491     public void setBlockIncrement(final int i) {
492         runMapping(new MapVoidAction("setBlockIncrement") {
493             @Override
494             public void map() {
495                 ((Scrollbar) getSource()).setBlockIncrement(i);
496             }
497         });
498     }
499 
500     /**
501      * Maps {@code Scrollbar.setMaximum(int)} through queue
502      */
503     public void setMaximum(final int i) {
504         runMapping(new MapVoidAction("setMaximum") {
505             @Override
506             public void map() {
507                 ((Scrollbar) getSource()).setMaximum(i);
508             }
509         });
510     }
511 
512     /**
513      * Maps {@code Scrollbar.setMinimum(int)} through queue
514      */
515     public void setMinimum(final int i) {
516         runMapping(new MapVoidAction("setMinimum") {
517             @Override
518             public void map() {
519                 ((Scrollbar) getSource()).setMinimum(i);
520             }
521         });
522     }
523 
524     /**
525      * Maps {@code Scrollbar.setOrientation(int)} through queue
526      */
527     public void setOrientation(final int i) {
528         runMapping(new MapVoidAction("setOrientation") {
529             @Override
530             public void map() {
531                 ((Scrollbar) getSource()).setOrientation(i);
532             }
533         });
534     }
535 
536     /**
537      * Maps {@code Scrollbar.setUnitIncrement(int)} through queue
538      */
539     public void setUnitIncrement(final int i) {
540         runMapping(new MapVoidAction("setUnitIncrement") {
541             @Override
542             public void map() {
543                 ((Scrollbar) getSource()).setUnitIncrement(i);
544             }
545         });
546     }
547 
548     /**
549      * Maps {@code Scrollbar.setValue(int)} through queue
550      */
551     public void setValue(final int i) {
552         runMapping(new MapVoidAction("setValue") {
553             @Override
554             public void map() {
555                 ((Scrollbar) getSource()).setValue(i);
556             }
557         });
558     }
559 
560     /**
561      * Maps {@code Scrollbar.setValues(int, int, int, int)} through queue
562      */
563     public void setValues(final int i, final int i1, final int i2, final int i3) {
564         runMapping(new MapVoidAction("setValues") {
565             @Override
566             public void map() {
567                 ((Scrollbar) getSource()).setValues(i, i1, i2, i3);
568             }
569         });
570     }
571 
572     /**
573      * Maps {@code Scrollbar.setVisibleAmount(int)} through queue
574      */
575     public void setVisibleAmount(final int i) {
576         runMapping(new MapVoidAction("setVisibleAmount") {
577             @Override
578             public void map() {
579                 ((Scrollbar) getSource()).setVisibleAmount(i);
580             }
581         });
582     }
583 
584     //End of mapping                                      //
585     ////////////////////////////////////////////////////////
586     private class ValueScrollAdjuster implements ScrollAdjuster {
587 
588         int value;
589 
590         public ValueScrollAdjuster(int value) {
591             this.value = value;
592         }
593 
594         @Override
595         public int getScrollDirection() {
596             if (getValue() == value) {
597                 return ScrollAdjuster.DO_NOT_TOUCH_SCROLL_DIRECTION;
598             } else {
599                 return ((getValue() < value)
600                         ? ScrollAdjuster.INCREASE_SCROLL_DIRECTION
601                         : ScrollAdjuster.DECREASE_SCROLL_DIRECTION);
602             }
603         }
604 
605         @Override
606         public int getScrollOrientation() {
607             return getOrientation();
608         }
609 
610         @Override
611         public String getDescription() {
612             return "Scroll to " + Integer.toString(value) + " value";
613         }
614 
615         @Override
616         public String toString() {
617             return "ValueScrollAdjuster{" + "value=" + value + '}';
618         }
619     }
620 
621     private class WaitableChecker<R, P> implements ScrollAdjuster {
622 
623         Waitable<R, P> w;
624         P waitParam;
625         boolean increase;
626         boolean reached = false;
627 
628         public WaitableChecker(Waitable<R, P> w, P waitParam, boolean increase, ScrollbarOperator oper) {
629             this.w = w;
630             this.waitParam = waitParam;
631             this.increase = increase;
632         }
633 
634         @Override
635         public int getScrollDirection() {
636             if (!reached && w.actionProduced(waitParam) != null) {
637                 reached = true;
638             }
639             if (reached) {
640                 return ScrollAdjuster.DO_NOT_TOUCH_SCROLL_DIRECTION;
641             } else {
642                 return (increase
643                         ? ScrollAdjuster.INCREASE_SCROLL_DIRECTION
644                         : ScrollAdjuster.DECREASE_SCROLL_DIRECTION);
645             }
646         }
647 
648         @Override
649         public int getScrollOrientation() {
650             return getOrientation();
651         }
652 
653         @Override
654         public String getDescription() {
655             return w.getDescription();
656         }
657 
658         @Override
659         public String toString() {
660             return "WaitableChecker{" + "w=" + w + ", waitParam=" + waitParam + ", increase=" + increase + ", reached=" + reached + '}';
661         }
662     }
663 
664     /**
665      * Checks component type.
666      */
667     public static class ScrollbarFinder extends Finder {
668 
669         /**
670          * Constructs ScrollbarFinder.
671          *
672          * @param sf other searching criteria.
673          */
674         public ScrollbarFinder(ComponentChooser sf) {
675             super(Scrollbar.class, sf);
676         }
677 
678         /**
679          * Constructs ScrollbarFinder.
680          */
681         public ScrollbarFinder() {
682             super(Scrollbar.class);
683         }
684     }
685 }
686