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 javax.swing.SwingUtilities.getWindowAncestor; 018 import static org.fest.reflect.core.Reflection.field; 019 import static org.fest.swing.driver.ComponentStateValidator.validateIsEnabledAndShowing; 020 import static org.fest.swing.driver.JToolBarIsFloatingQuery.isJToolBarFloating; 021 import static org.fest.swing.edt.GuiActionRunner.execute; 022 import static org.fest.swing.exception.ActionFailedException.actionFailure; 023 import static org.fest.swing.format.Formatting.format; 024 import static org.fest.util.Strings.concat; 025 import static org.fest.util.Strings.quote; 026 027 import java.awt.*; 028 029 import javax.swing.JToolBar; 030 031 import org.fest.swing.annotation.RunsInCurrentThread; 032 import org.fest.swing.annotation.RunsInEDT; 033 import org.fest.swing.core.Robot; 034 import org.fest.swing.edt.GuiQuery; 035 import org.fest.swing.edt.GuiTask; 036 import org.fest.swing.exception.ActionFailedException; 037 import org.fest.swing.util.GenericRange; 038 import org.fest.swing.util.Pair; 039 040 /** 041 * Understands functional testing of <code>{@link JToolBar}</code>s: 042 * <ul> 043 * <li>user input simulation</li> 044 * <li>state verification</li> 045 * <li>property value query</li> 046 * </ul> 047 * This class is intended for internal use only. Please use the classes in the package 048 * <code>{@link org.fest.swing.fixture}</code> in your tests. 049 * 050 * @author Yvonne Wang 051 * @author Alex Ruiz 052 */ 053 public class JToolBarDriver extends JComponentDriver { 054 055 private final JToolBarLocation location = new JToolBarLocation(); 056 057 /** 058 * Creates a new </code>{@link JToolBarDriver}</code>. 059 * @param robot the robot to use to simulate user input. 060 */ 061 public JToolBarDriver(Robot robot) { 062 super(robot); 063 } 064 065 /** 066 * Indicates whether the given <code>{@link JToolBar}</code> is floating or not. 067 * @param toolBar the target <code>JToolBar</code>. 068 * @return <code>true</code> if the <code>JToolBar</code> is floating, <code>false</code> otherwise. 069 */ 070 @RunsInEDT 071 public boolean isFloating(JToolBar toolBar) { 072 return floating(toolBar); 073 } 074 075 private static boolean floating(final JToolBar toolBar) { 076 return execute(new GuiQuery<Boolean>() { 077 protected Boolean executeInEDT() { 078 return isJToolBarFloating(toolBar); 079 } 080 }); 081 } 082 083 /** 084 * Makes the given <code>{@link JToolBar}</code> float. 085 * @param toolBar the target <code>JToolBar</code>. 086 * @throws IllegalStateException if the <code>JToolBar</code> is disabled. 087 * @throws IllegalStateException if the <code>JToolBar</code> is not showing on the screen. 088 * @throws IllegalStateException if the <code>JToolBar</code> is not floatable. 089 * @throws ActionFailedException if the <code>JToolBar</code> cannot be dragged. 090 */ 091 public void makeFloat(JToolBar toolBar) { 092 Pair<Point, Pair<Window, Point>> floatInfo = floatInfo(toolBar, location); 093 Point p = floatInfo.ii.ii; // ancestor location 094 doFloat(toolBar, p.x, p.y, floatInfo); 095 } 096 097 /** 098 * Drags the <code>{@link JToolBar}</code> to the given location, causing it to float. 099 * @param toolBar the target <code>JToolBar</code>. 100 * @param x the horizontal coordinate of the location to drag the <code>JToolBar</code> to. 101 * @param y the vertical coordinate of the location to drag the <code>JToolBar</code> to. 102 * @throws IllegalStateException if the <code>JToolBar</code> is disabled. 103 * @throws IllegalStateException if the <code>JToolBar</code> is not showing on the screen. 104 * @throws IllegalStateException if the <code>JToolBar</code> is not floatable. 105 * @throws ActionFailedException if the <code>JToolBar</code> cannot be dragged. 106 */ 107 @RunsInEDT 108 public void floatTo(JToolBar toolBar, int x, int y) { 109 doFloat(toolBar, x, y, floatInfo(toolBar, location)); 110 } 111 112 @RunsInEDT 113 private static Pair<Point, Pair<Window, Point>> floatInfo(final JToolBar toolBar, final JToolBarLocation location) { 114 return execute(new GuiQuery<Pair<Point, Pair<Window, Point>>>() { 115 protected Pair<Point, Pair<Window, Point>> executeInEDT() { 116 validateIsEnabledAndShowing(toolBar); 117 validateIsFloatable(toolBar); 118 Pair<Window, Point> windowAndLocation = ancestorAndLocation(toolBar); 119 return new Pair<Point, Pair<Window,Point>>(location.pointToGrab(toolBar), windowAndLocation); 120 } 121 }); 122 } 123 124 @RunsInCurrentThread 125 private static void validateIsFloatable(JToolBar toolBar) { 126 if (!toolBar.isFloatable()) 127 throw new IllegalStateException(concat("JToolbar <", format(toolBar), "> is not floatable")); 128 } 129 130 @RunsInCurrentThread 131 private static Pair<Window, Point> ancestorAndLocation(final JToolBar toolBar) { 132 Window window = getWindowAncestor(toolBar); 133 return new Pair<Window, Point>(window, window.getLocation()); 134 } 135 136 @RunsInEDT 137 private void doFloat(JToolBar toolBar, int x, int y, Pair<Point, Pair<Window, Point>> floatInfo) { 138 drag(toolBar, floatInfo.i); 139 Pair<Window, Point> locationAndAncestor = floatInfo.ii; 140 Point ancestorLocation = locationAndAncestor.ii; 141 drop(locationAndAncestor.i, new Point(x - ancestorLocation.x, y - ancestorLocation.y)); 142 validateFloated(toolBar); 143 } 144 145 @RunsInEDT 146 private static void validateFloated(final JToolBar toolBar) { 147 execute(new GuiTask() { 148 protected void executeInEDT() { 149 if (!isJToolBarFloating(toolBar)) 150 throw actionFailure(concat("Unable to float JToolbar <", format(toolBar), ">")); 151 } 152 }); 153 } 154 155 /** 156 * Drop the {@link JToolBar} to the requested constraint position. The constraint position must be one of the 157 * constants <code>{@link BorderLayout#NORTH NORTH}</code>, <code>{@link BorderLayout#EAST EAST}</code>, 158 * <code>{@link BorderLayout#SOUTH SOUTH}</code>, or <code>{@link BorderLayout#WEST WEST}</code>. 159 * @param toolBar the target <code>JToolBar</code>. 160 * @param constraint the constraint position. 161 * @throws IllegalStateException if the <code>JToolBar</code> is disabled. 162 * @throws IllegalStateException if the <code>JToolBar</code> is not showing on the screen. 163 * @throws IllegalArgumentException if the constraint has an invalid value. 164 * @throws ActionFailedException if the dock container cannot be found. 165 */ 166 @RunsInEDT 167 public void unfloat(JToolBar toolBar, String constraint) { 168 Pair<GenericRange<Point>, Container> unfloatInfo = unfloatInfo(toolBar, constraint, location); 169 GenericRange<Point> fromAndTo = unfloatInfo.i; 170 drag(toolBar, fromAndTo.from); 171 drop(unfloatInfo.ii, fromAndTo.to); 172 validateIsNotFloating(toolBar, constraint); 173 } 174 175 @RunsInEDT 176 private static Pair<GenericRange<Point>, Container> unfloatInfo(final JToolBar toolBar, final String constraint, 177 final JToolBarLocation location) { 178 return execute(new GuiQuery<Pair<GenericRange<Point>, Container>>() { 179 protected Pair<GenericRange<Point>, Container> executeInEDT() { 180 validateIsEnabledAndShowing(toolBar); 181 Container dock = dockFor(toolBar); 182 Point from = location.pointToGrab(toolBar); 183 Point to = location.dockLocation(toolBar, dock, constraint); 184 return new Pair<GenericRange<Point>, Container>(new GenericRange<Point>(from, to), dock); 185 } 186 }); 187 } 188 189 @RunsInEDT 190 private static void validateIsNotFloating(final JToolBar toolBar, final String constraint) { 191 execute(new GuiTask() { 192 protected void executeInEDT() { 193 if (isJToolBarFloating(toolBar)) 194 throw actionFailure(concat("Failed to dock <", format(toolBar), "> using constraint ", quote(constraint))); 195 } 196 }); 197 } 198 199 @RunsInCurrentThread 200 private static Container dockFor(final JToolBar toolBar) { 201 try { 202 return field("dockingSource").ofType(Container.class).in(toolBar.getUI()).get(); 203 } catch (RuntimeException e) { 204 throw actionFailure("Unabled to determine dock for JToolBar"); 205 } 206 } 207 208 /** 209 * Closes a floating <code>{@link JToolBar}</code>, making it go back to its original container in its last known 210 * location. 211 * @param toolBar the target <code>JToolBar</code>. 212 * @throws IllegalStateException if the <code>JToolBar</code> is disabled. 213 * @throws IllegalStateException if the <code>JToolBar</code> is not showing on the screen. 214 */ 215 @RunsInEDT 216 public void unfloat(JToolBar toolBar) { 217 Window w = windowAncestorOf(toolBar); 218 robot.close(w); 219 } 220 221 @RunsInEDT 222 private static Window windowAncestorOf(final JToolBar toolBar) { 223 return execute(new GuiQuery<Window>() { 224 protected Window executeInEDT() { 225 validateIsEnabledAndShowing(toolBar); 226 return getWindowAncestor(toolBar); 227 } 228 }); 229 } 230 }