001    /*
002     * Created on Jan 27, 2008
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     *
013     * Copyright @2008-2010 the original author or authors.
014     */
015    package org.fest.swing.driver;
016    
017    import static org.fest.swing.driver.ComponentStateValidator.validateIsEnabledAndShowing;
018    import static org.fest.swing.driver.JSliderSetValueTask.setValue;
019    import static org.fest.swing.edt.GuiActionRunner.execute;
020    import static org.fest.util.Strings.concat;
021    
022    import java.awt.Point;
023    
024    import javax.swing.JSlider;
025    
026    import org.fest.swing.annotation.RunsInCurrentThread;
027    import org.fest.swing.annotation.RunsInEDT;
028    import org.fest.swing.core.Robot;
029    import org.fest.swing.edt.GuiQuery;
030    import org.fest.swing.util.GenericRange;
031    import org.fest.swing.util.Pair;
032    
033    /**
034     * Understands functional testing of <code>{@link JSlider}</code>s:
035     * <ul>
036     * <li>user input simulation</li>
037     * <li>state verification</li>
038     * <li>property value query</li>
039     * </ul>
040     * This class is intended for internal use only. Please use the classes in the package
041     * <code>{@link org.fest.swing.fixture}</code> in your tests.
042     *
043     * @author Alex Ruiz
044     * @author Yvonne Wang
045     */
046    public class JSliderDriver extends JComponentDriver {
047    
048      private final JSliderLocation location;
049    
050      /**
051       * Creates a new </code>{@link JSliderDriver}</code>.
052       * @param robot the robot to use to simulate user input.
053       */
054      public JSliderDriver(Robot robot) {
055        super(robot);
056        location = new JSliderLocation();
057      }
058    
059      /**
060       * Slides the knob to its maximum.
061       * @param slider the target <code>JSlider</code>.
062       * @throws IllegalStateException if the <code>JSlider</code> is disabled.
063       * @throws IllegalStateException if the <code>JSlider</code> is not showing on the screen.
064       */
065      @RunsInEDT
066      public void slideToMaximum(JSlider slider) {
067        slide(slider, validateAndFindSlideToMaximumInfo(slider, location));
068      }
069    
070      @RunsInEDT
071      private static Pair<Integer, GenericRange<Point>> validateAndFindSlideToMaximumInfo(final JSlider slider,
072          final JSliderLocation location) {
073        return execute(new GuiQuery<Pair<Integer, GenericRange<Point>>>() {
074          protected Pair<Integer, GenericRange<Point>> executeInEDT() {
075            validateIsEnabledAndShowing(slider);
076            int value = slider.getMaximum();
077            GenericRange<Point> fromAndTo = slideInfo(slider, location, value);
078            return new Pair<Integer, GenericRange<Point>>(value, fromAndTo);
079          }
080        });
081      }
082    
083      /**
084       * Slides the knob to its minimum.
085       * @param slider the target <code>JSlider</code>.
086       * @throws IllegalStateException if the <code>JSlider</code> is disabled.
087       * @throws IllegalStateException if the <code>JSlider</code> is not showing on the screen.
088       */
089      @RunsInEDT
090      public void slideToMinimum(JSlider slider) {
091        slide(slider, validateAndFindSlideToMinimumInfo(slider, location));
092      }
093    
094      @RunsInEDT
095      private static Pair<Integer, GenericRange<Point>> validateAndFindSlideToMinimumInfo(final JSlider slider,
096          final JSliderLocation location) {
097        return execute(new GuiQuery<Pair<Integer, GenericRange<Point>>>() {
098          protected Pair<Integer, GenericRange<Point>> executeInEDT() {
099            validateIsEnabledAndShowing(slider);
100            int value = slider.getMinimum();
101            GenericRange<Point> fromAndTo = slideInfo(slider, location, value);
102            return new Pair<Integer, GenericRange<Point>>(value, fromAndTo);
103          }
104        });
105      }
106    
107      @RunsInEDT
108      private void slide(JSlider slider, Pair<Integer, GenericRange<Point>> slideInfo) {
109        slide(slider, slideInfo.i, slideInfo.ii);
110      }
111    
112      /**
113       * Slides the knob to the requested value.
114       * @param slider the target <code>JSlider</code>.
115       * @param value the requested value.
116       * @throws IllegalStateException if the <code>JSlider</code> is disabled.
117       * @throws IllegalStateException if the <code>JSlider</code> is not showing on the screen.
118       * @throws IllegalArgumentException if the given position is not within the <code>JSlider</code> bounds.
119       */
120      @RunsInEDT
121      public void slide(JSlider slider, int value) {
122        GenericRange<Point> slideInfo = validateAndFindSlideInfo(slider, location, value);
123        slide(slider, value, slideInfo);
124      }
125    
126      @RunsInEDT
127      private void slide(JSlider slider, int value, GenericRange<Point> fromAndTo) {
128        moveMouseIgnoringAnyError(slider, fromAndTo.from);
129        moveMouseIgnoringAnyError(slider, fromAndTo.to);
130        setValue(slider, value);
131        robot.waitForIdle();
132      }
133    
134      @RunsInEDT
135      private static GenericRange<Point> validateAndFindSlideInfo(final JSlider slider, final JSliderLocation location,
136          final int value) {
137        return execute(new GuiQuery<GenericRange<Point>>() {
138          protected GenericRange<Point> executeInEDT() {
139            validateValue(slider, value);
140            validateIsEnabledAndShowing(slider);
141            return slideInfo(slider, location, value);
142          }
143        });
144      }
145    
146      @RunsInCurrentThread
147      private static void validateValue(JSlider slider, int value) {
148        int min = slider.getMinimum();
149        int max = slider.getMaximum();
150        if (value >= min && value <= max) return;
151        throw new IllegalArgumentException(
152            concat("Value <", value, "> is not within the JSlider bounds of <", min, "> and <", max, ">"));
153      }
154    
155      @RunsInCurrentThread
156      private static GenericRange<Point> slideInfo(JSlider slider, JSliderLocation location, int value) {
157        Point from = location.pointAt(slider, slider.getValue());
158        Point to = location.pointAt(slider, value);
159        return new GenericRange<Point>(from, to);
160      }
161    }