001 /* 002 * Created on Feb 2, 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.assertions.Assertions.assertThat; 018 import static org.fest.swing.driver.ComponentStateValidator.validateIsEnabledAndShowing; 019 import static org.fest.swing.driver.JScrollBarSetValueTask.setValue; 020 import static org.fest.swing.driver.JScrollBarValueQuery.valueOf; 021 import static org.fest.swing.edt.GuiActionRunner.execute; 022 import static org.fest.util.Strings.concat; 023 024 import java.awt.Point; 025 026 import javax.swing.JScrollBar; 027 028 import org.fest.swing.annotation.RunsInCurrentThread; 029 import org.fest.swing.annotation.RunsInEDT; 030 import org.fest.swing.core.Robot; 031 import org.fest.swing.edt.GuiQuery; 032 import org.fest.swing.util.GenericRange; 033 import org.fest.swing.util.Pair; 034 035 /** 036 * Understands functional testing of <code>{@link JScrollBar}</code>s: 037 * <ul> 038 * <li>user input simulation</li> 039 * <li>state verification</li> 040 * <li>property value query</li> 041 * </ul> 042 * This class is intended for internal use only. Please use the classes in the package 043 * <code>{@link org.fest.swing.fixture}</code> in your tests. 044 * 045 * @author Yvonne Wang 046 * @author Alex Ruiz 047 */ 048 public class JScrollBarDriver extends JComponentDriver { 049 050 private static final String VALUE_PROPERTY = "value"; 051 052 private final JScrollBarLocation location = new JScrollBarLocation(); 053 054 /** 055 * Creates a new </code>{@link JScrollBarDriver}</code>. 056 * @param robot the robot to use to simulate user input. 057 */ 058 public JScrollBarDriver(Robot robot) { 059 super(robot); 060 } 061 062 /** 063 * Scrolls up (or left) one unit (usually a line). 064 * @param scrollBar the target <code>JScrollBar</code>. 065 */ 066 public void scrollUnitUp(JScrollBar scrollBar) { 067 scrollUnitUp(scrollBar, 1); 068 } 069 070 /** 071 * Scrolls up (or left) one unit (usually a line,) the given number of times. 072 * @param scrollBar the target <code>JScrollBar</code>. 073 * @param times the number of times to scroll up one unit. 074 * @throws IllegalArgumentException if <code>times</code> is less than or equal to zero. 075 * @throws IllegalStateException if the <code>JScrollBar</code> is disabled. 076 * @throws IllegalStateException if the <code>JScrollBar</code> is not showing on the screen. 077 */ 078 public void scrollUnitUp(JScrollBar scrollBar, int times) { 079 validateTimes(times, "scroll up one unit"); 080 Pair<Point, Integer> scrollInfo = validateAndFindScrollUnitInfo(scrollBar, location, times * -1); 081 scroll(scrollBar, scrollInfo); 082 } 083 084 /** 085 * Scrolls down (or right) one unit (usually a line). 086 * @param scrollBar the target <code>JScrollBar</code>. 087 */ 088 public void scrollUnitDown(JScrollBar scrollBar) { 089 scrollUnitDown(scrollBar, 1); 090 } 091 092 /** 093 * Scrolls down (or right) one unit (usually a line,) the given number of times. 094 * @param scrollBar the target <code>JScrollBar</code>. 095 * @param times the number of times to scroll down one unit. 096 * @throws IllegalArgumentException if <code>times</code> is less than or equal to zero. 097 * @throws IllegalStateException if the <code>JScrollBar</code> is disabled. 098 * @throws IllegalStateException if the <code>JScrollBar</code> is not showing on the screen. 099 */ 100 public void scrollUnitDown(JScrollBar scrollBar, int times) { 101 validateTimes(times, "scroll down one unit"); 102 Pair<Point, Integer> scrollInfo = validateAndFindScrollUnitInfo(scrollBar, location, times); 103 scroll(scrollBar, scrollInfo); 104 } 105 106 @RunsInEDT 107 private static Pair<Point, Integer> validateAndFindScrollUnitInfo(final JScrollBar scrollBar, 108 final JScrollBarLocation location, final int times) { 109 return execute(new GuiQuery<Pair<Point, Integer>>() { 110 protected Pair<Point, Integer> executeInEDT() { 111 validateIsEnabledAndShowing(scrollBar); 112 return scrollUnitInfo(scrollBar, location, times); 113 } 114 }); 115 } 116 117 @RunsInCurrentThread 118 private static Pair<Point, Integer> scrollUnitInfo(JScrollBar scrollBar, JScrollBarLocation location, int times) { 119 Point where = blockLocation(scrollBar, location, times); 120 int count = times * scrollBar.getUnitIncrement(); 121 return new Pair<Point, Integer>(where, scrollBar.getValue() + count); 122 } 123 124 /** 125 * Scrolls up (or left) one block (usually a page). 126 * @param scrollBar the target <code>JScrollBar</code>. 127 */ 128 @RunsInEDT 129 public void scrollBlockUp(JScrollBar scrollBar) { 130 scrollBlockUp(scrollBar, 1); 131 } 132 133 /** 134 * Scrolls up (or left) one block (usually a page,) the given number of times. 135 * @param scrollBar the target <code>JScrollBar</code>. 136 * @param times the number of times to scroll up one block. 137 * @throws IllegalArgumentException if <code>times</code> is less than or equal to zero. 138 * @throws IllegalStateException if the <code>JScrollBar</code> is disabled. 139 * @throws IllegalStateException if the <code>JScrollBar</code> is not showing on the screen. 140 */ 141 @RunsInEDT 142 public void scrollBlockUp(JScrollBar scrollBar, int times) { 143 validateTimes(times, "scroll up one block"); 144 Pair<Point, Integer> scrollInfo = validateAndFindScrollBlockInfo(scrollBar, location, times * -1); 145 scroll(scrollBar, scrollInfo); 146 } 147 148 /** 149 * Scrolls down (or right) one block (usually a page). 150 * @param scrollBar the target <code>JScrollBar</code>. 151 */ 152 @RunsInEDT 153 public void scrollBlockDown(JScrollBar scrollBar) { 154 scrollBlockDown(scrollBar, 1); 155 } 156 157 /** 158 * Scrolls down (or right) one block (usually a page,) the given number of times. 159 * @param scrollBar the target <code>JScrollBar</code>. 160 * @param times the number of times to scroll down one block. 161 * @throws IllegalArgumentException if <code>times</code> is less than or equal to zero. 162 * @throws IllegalStateException if the <code>JScrollBar</code> is disabled. 163 * @throws IllegalStateException if the <code>JScrollBar</code> is not showing on the screen. 164 */ 165 @RunsInEDT 166 public void scrollBlockDown(JScrollBar scrollBar, int times) { 167 validateTimes(times, "scroll down one block"); 168 Pair<Point, Integer> scrollInfo = validateAndFindScrollBlockInfo(scrollBar, location, times); 169 scroll(scrollBar, scrollInfo); 170 } 171 172 private void validateTimes(int times, String action) { 173 if (times > 0) return; 174 String message = concat( 175 "The number of times to ", action, " should be greater than zero, but was <", times, ">"); 176 throw new IllegalArgumentException(message); 177 } 178 179 @RunsInEDT 180 private static Pair<Point, Integer> validateAndFindScrollBlockInfo(final JScrollBar scrollBar, 181 final JScrollBarLocation location, final int times) { 182 return execute(new GuiQuery<Pair<Point, Integer>>() { 183 protected Pair<Point, Integer> executeInEDT() { 184 validateIsEnabledAndShowing(scrollBar); 185 return scrollBlockInfo(scrollBar, location, times); 186 } 187 }); 188 } 189 190 @RunsInCurrentThread 191 private static Pair<Point, Integer> scrollBlockInfo(JScrollBar scrollBar, JScrollBarLocation location, int times) { 192 Point where = blockLocation(scrollBar, location, times); 193 int count = times * scrollBar.getBlockIncrement(); 194 return new Pair<Point, Integer>(where, scrollBar.getValue() + count); 195 } 196 197 @RunsInCurrentThread 198 private static Point blockLocation(JScrollBar scrollBar, JScrollBarLocation location, int times) { 199 if (times > 0) return location.blockLocationToScrollDown(scrollBar); 200 return location.blockLocationToScrollUp(scrollBar); 201 } 202 203 @RunsInEDT 204 private void scroll(JScrollBar scrollBar, Pair<Point, Integer> scrollInfo) { 205 // For now, do it programmatically, faking the mouse movement and clicking 206 robot.moveMouse(scrollBar, scrollInfo.i); 207 setValueProperty(scrollBar, scrollInfo.ii); 208 } 209 210 /** 211 * Scrolls to the maximum position of the given <code>{@link JScrollBar}</code>. 212 * @param scrollBar the target <code>JScrollBar</code>. 213 * @throws IllegalStateException if the <code>JScrollBar</code> is disabled. 214 * @throws IllegalStateException if the <code>JScrollBar</code> is not showing on the screen. 215 */ 216 @RunsInEDT 217 public void scrollToMaximum(JScrollBar scrollBar) { 218 Pair<Integer, GenericRange<Point>> scrollInfo = validateAndFindScrollToMaximumInfo(scrollBar, location); 219 scroll(scrollBar, scrollInfo.i, scrollInfo.ii); 220 } 221 222 @RunsInEDT 223 private static Pair<Integer, GenericRange<Point>> validateAndFindScrollToMaximumInfo(final JScrollBar scrollBar, 224 final JScrollBarLocation location) { 225 return execute(new GuiQuery<Pair<Integer, GenericRange<Point>>>() { 226 protected Pair<Integer, GenericRange<Point>> executeInEDT() { 227 validateIsEnabledAndShowing(scrollBar); 228 int position = scrollBar.getMaximum(); 229 GenericRange<Point> scrollInfo = scrollInfo(scrollBar, location, position); 230 return new Pair<Integer, GenericRange<Point>>(position, scrollInfo); 231 } 232 }); 233 } 234 235 /** 236 * Scrolls to the minimum position of the given <code>{@link JScrollBar}</code>. 237 * @param scrollBar the target <code>JScrollBar</code>. 238 * @throws IllegalStateException if the <code>JScrollBar</code> is disabled. 239 * @throws IllegalStateException if the <code>JScrollBar</code> is not showing on the screen. 240 */ 241 @RunsInEDT 242 public void scrollToMinimum(JScrollBar scrollBar) { 243 Pair<Integer, GenericRange<Point>> scrollInfo = validateAndFindScrollToMinimumInfo(scrollBar, location); 244 scroll(scrollBar, scrollInfo.i, scrollInfo.ii); 245 } 246 247 @RunsInEDT 248 private static Pair<Integer, GenericRange<Point>> validateAndFindScrollToMinimumInfo(final JScrollBar scrollBar, 249 final JScrollBarLocation location) { 250 return execute(new GuiQuery<Pair<Integer, GenericRange<Point>>>() { 251 protected Pair<Integer, GenericRange<Point>> executeInEDT() { 252 validateIsEnabledAndShowing(scrollBar); 253 int position = scrollBar.getMinimum(); 254 GenericRange<Point> scrollInfo = scrollInfo(scrollBar, location, position); 255 return new Pair<Integer, GenericRange<Point>>(position, scrollInfo); 256 } 257 }); 258 } 259 260 /** 261 * Scrolls to the given position. 262 * @param scrollBar the target <code>JScrollBar</code>. 263 * @param position the position to scroll to. 264 * @throws IllegalStateException if the <code>JScrollBar</code> is disabled. 265 * @throws IllegalStateException if the <code>JScrollBar</code> is not showing on the screen. 266 * @throws IllegalArgumentException if the given position is not within the <code>JScrollBar</code> bounds. 267 */ 268 @RunsInEDT 269 public void scrollTo(JScrollBar scrollBar, int position) { 270 GenericRange<Point> scrollInfo = validateAndFindScrollInfo(scrollBar, location, position); 271 scroll(scrollBar, position, scrollInfo); 272 } 273 274 @RunsInEDT 275 private static GenericRange<Point> validateAndFindScrollInfo(final JScrollBar scrollBar, 276 final JScrollBarLocation location, final int position) { 277 return execute(new GuiQuery<GenericRange<Point>>() { 278 protected GenericRange<Point> executeInEDT() { 279 validatePosition(scrollBar, position); 280 validateIsEnabledAndShowing(scrollBar); 281 return scrollInfo(scrollBar, location, position); 282 } 283 }); 284 } 285 286 @RunsInCurrentThread 287 private static void validatePosition(JScrollBar scrollBar, int position) { 288 int min = scrollBar.getMinimum(); 289 int max = scrollBar.getMaximum(); 290 if (position >= min && position <= max) return; 291 throw new IllegalArgumentException(concat( 292 "Position <", position, "> is not within the JScrollBar bounds of <", min, "> and <", max, ">")); 293 } 294 295 @RunsInCurrentThread 296 private static GenericRange<Point> scrollInfo(JScrollBar scrollBar, JScrollBarLocation location, int position) { 297 Point from = location.thumbLocation(scrollBar, scrollBar.getValue()); 298 Point to = location.thumbLocation(scrollBar, position); 299 return new GenericRange<Point>(from, to); 300 } 301 302 private void scroll(JScrollBar scrollBar, int position, GenericRange<Point> points) { 303 simulateScrolling(scrollBar, points); 304 setValueProperty(scrollBar, position); 305 } 306 307 @RunsInEDT 308 private void simulateScrolling(JScrollBar scrollBar, GenericRange<Point> points) { 309 robot.moveMouse(scrollBar, points.from); 310 robot.moveMouse(scrollBar, points.to); 311 } 312 313 @RunsInEDT 314 private void setValueProperty(JScrollBar scrollBar, int value) { 315 setValue(scrollBar, value); 316 robot.waitForIdle(); 317 } 318 319 /** 320 * Asserts that the value of the <code>{@link JScrollBar}</code> is equal to the given one. 321 * @param scrollBar the target <code>JScrollBar</code>. 322 * @param value the expected value. 323 * @throws AssertionError if the value of the <code>JScrollBar</code> is not equal to the given one. 324 */ 325 @RunsInEDT 326 public void requireValue(JScrollBar scrollBar, int value) { 327 assertThat(valueOf(scrollBar)).as(propertyName(scrollBar, VALUE_PROPERTY)).isEqualTo(value); 328 } 329 }