001 /* 002 * Created on Mar 4, 2008 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with 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 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 * 014 * Copyright @2008-2010 the original author or authors. 015 */ 016 package org.fest.swing.core; 017 018 import java.awt.Component; 019 import java.awt.Container; 020 import java.util.Collection; 021 022 import javax.swing.JLabel; 023 024 import org.fest.swing.annotation.RunsInEDT; 025 import org.fest.swing.exception.ComponentLookupException; 026 027 /** 028 * Understands GUI <code>{@link java.awt.Component}</code> lookup. 029 * 030 * @author Alex Ruiz 031 */ 032 @RunsInEDT 033 public interface ComponentFinder { 034 035 /** 036 * Returns the <code>{@link ComponentPrinter}</code> in this finder. 037 * @return the <code>ComponentPrinter</code> in this finder. 038 */ 039 ComponentPrinter printer(); 040 041 /** 042 * Finds a <code>{@link Component}</code> by type. If this finder is attached to a <code>{@link Robot}</code>, it will 043 * use the component lookup scope in the <code>Robot</code>'s <code>{@link Settings}</code> to determine whether the 044 * component to find should be showing or not. If this finder is <em>not</em> attached to any <code>Robot</code>, the 045 * component to find does not have to be showing. 046 * <p> 047 * Example: 048 * <pre> 049 * JTextField textbox = finder.findByType(JTextField.class); 050 * </pre> 051 * </p> 052 * @param <T> the parameterized type of the component to find. 053 * @param type the type of the component to find. 054 * @return the found component. 055 * @throws ComponentLookupException if a matching component could not be found. 056 * @throws ComponentLookupException if more than one matching component is found. 057 * @see Robot#settings() 058 * @see Settings#componentLookupScope() 059 * @see ComponentLookupScope 060 */ 061 <T extends Component> T findByType(Class<T> type); 062 063 /** 064 * Finds a <code>{@link Component}</code> by type. For example: 065 * @param <T> the parameterized type of the component to find. 066 * @param type the type of the component to find. 067 * @param showing indicates whether the component to find should be visible (or showing) or not. 068 * @return the found component. 069 * @throws ComponentLookupException if a matching component could not be found. 070 * @throws ComponentLookupException if more than one matching component is found. 071 * @see #findByType(Class) 072 */ 073 <T extends Component> T findByType(Class<T> type, boolean showing); 074 075 /** 076 * <p> 077 * Finds a <code>{@link Component}</code> by type in the hierarchy under the given root. If this finder is attached to 078 * a <code>{@link Robot}</code>, it will use the component lookup scope in the <code>Robot</code>'s 079 * <code>{@link Settings}</code> to determine whether the component to find should be showing or not. If this finder 080 * is <em>not</em> attached to any <code>Robot</code>, the component to find does not have to be showing. 081 * </p> 082 * <p> 083 * Let's assume we have the following <code>{@link javax.swing.JFrame}</code> containing a 084 * <code>{@link javax.swing.JTextField}</code>: 085 * 086 * <pre> 087 * JFrame myFrame = new JFrame(); 088 * myFrame.add(new JTextField()); 089 * </pre> 090 * 091 * </p> 092 * <p> 093 * If we want to get a reference to the <code>{@link javax.swing.JTextField}</code> in that particular 094 * <code>{@link javax.swing.JFrame}</code> without going through the whole AWT component hierarchy, we could simply 095 * specify: 096 * 097 * <pre> 098 * JTextField textbox = finder.findByType(myFrame, JTextField.class); 099 * </pre> 100 * 101 * </p> 102 * @param <T> the parameterized type of the component to find. 103 * @param root the root used as the starting point of the search. 104 * @param type the type of the component to find. 105 * @return the found component. 106 * @throws ComponentLookupException if a matching component could not be found. 107 * @throws ComponentLookupException if more than one matching component is found. 108 * @see Robot#settings() 109 * @see Settings#componentLookupScope() 110 * @see ComponentLookupScope 111 */ 112 <T extends Component> T findByType(Container root, Class<T> type); 113 114 /** 115 * Finds a <code>{@link Component}</code> by type in the hierarchy under the given root. 116 * @param <T> the parameterized type of the component to find. 117 * @param root the root used as the starting point of the search. 118 * @param showing indicates whether the component to find should be visible (or showing) or not. 119 * @param type the type of the component to find. 120 * @return the found component. 121 * @throws ComponentLookupException if a matching component could not be found. 122 * @throws ComponentLookupException if more than one matching component is found. 123 * @see #findByType(Container, Class) 124 */ 125 <T extends Component> T findByType(Container root, Class<T> type, boolean showing); 126 127 /** 128 * <p> 129 * Finds a <code>{@link Component}</code> by by the text of its associated <code>{@link JLabel}</code>. If this finder 130 * is attached to a <code>{@link Robot}</code>, it will use the component lookup scope in the <code>Robot</code>'s 131 * <code>{@link Settings}</code> to determine whether the component to find should be showing or not. If this finder 132 * is <em>not</em> attached to any <code>Robot</code>, the component to find does not have to be showing. 133 * </p> 134 * <p> 135 * Let's assume we have the <code>{@link javax.swing.JTextField}</code> with a <code>{@link JLabel}</code> with text 136 * "Name"; 137 * 138 * <pre> 139 * JLabel label = new JLabel("Name"); 140 * JTextField textbox = new JTextField(); 141 * label.setLabelFor(textBox); 142 * </pre> 143 * 144 * </p> 145 * <p> 146 * To get a reference to this <code>{@link javax.swing.JTextField}</code> by the text of its associated 147 * <code>JLabel</code>, we can specify: 148 * 149 * <pre> 150 * JTextField textBox = (JTextField) finder.findByLabel("Name"); 151 * </pre> 152 * 153 * </p> 154 * <p> 155 * Please note that you need to cast the result of the lookup to the right type. To avoid casting, please use one of 156 * following: 157 * <ol> 158 * <li><code>{@link #findByLabel(String, Class)}</code></li> 159 * <li><code>{@link #findByLabel(String, Class, boolean)}</code></li> 160 * <li><code>{@link #findByLabel(Container, String, Class)}</code></li> 161 * <li><code>{@link #findByLabel(Container, String, Class, boolean)}</code></li> 162 * </ol> 163 * </p> 164 * @param label the text of the <code>JLabel</code> associated to the component to find. 165 * @return the found component. 166 * @throws ComponentLookupException if a matching component could not be found. 167 * @throws ComponentLookupException if more than one matching component is found. 168 * @see JLabel#getLabelFor() 169 * @see JLabel#setLabelFor(Component) 170 * @see Robot#settings() 171 * @see Settings#componentLookupScope() 172 * @see ComponentLookupScope 173 */ 174 Component findByLabel(String label); 175 176 /** 177 * Finds a <code>{@link Component}</code> by the text of its associated <code>{@link JLabel}</code> and type. If this 178 * finder is attached to a <code>{@link Robot}</code>, it will use the component lookup scope in the 179 * <code>Robot</code>'s <code>{@link Settings}</code> to determine whether the component to find should be showing or 180 * not. If this finder is <em>not</em> attached to any <code>Robot</code>, the component to find does not have to be 181 * showing. 182 * @param <T> the parameterized type of the component to find. 183 * @param label the text of the <code>JLabel</code> associated to the component to find. 184 * @param type the type of the component to find. 185 * @return the found component. 186 * @throws ComponentLookupException if a matching component could not be found. 187 * @throws ComponentLookupException if more than one matching component is found. 188 * @see #findByLabel(String) 189 * @see JLabel#getLabelFor() 190 * @see JLabel#setLabelFor(Component) 191 * @see Robot#settings() 192 * @see Settings#componentLookupScope() 193 * @see ComponentLookupScope 194 */ 195 <T extends Component> T findByLabel(String label, Class<T> type); 196 197 /** 198 * Finds a <code>{@link Component}</code> by the text of its associated <code>{@link JLabel}</code> and type. 199 * @param <T> the parameterized type of the component to find. 200 * @param label the text of the <code>JLabel</code> associated to the component to find. 201 * @param type the type of the component to find. 202 * @param showing indicates whether the component to find should be visible (or showing) or not. 203 * @return the found component. 204 * @throws ComponentLookupException if a matching component could not be found. 205 * @throws ComponentLookupException if more than one matching component is found. 206 * @see #findByLabel(String) 207 * @see JLabel#getLabelFor() 208 * @see JLabel#setLabelFor(Component) 209 */ 210 <T extends Component> T findByLabel(String label, Class<T> type, boolean showing); 211 212 /** 213 * Finds a <code>{@link Component}</code> by by the text of its associated <code>{@link JLabel}</code>. 214 * @param label the text of the <code>JLabel</code> associated to the component to find. 215 * @param showing indicates whether the component to find should be visible (or showing) or not. 216 * @return the found component. 217 * @throws ComponentLookupException if a matching component could not be found. 218 * @throws ComponentLookupException if more than one matching component is found. 219 * @see #findByLabel(String) 220 * @see JLabel#getLabelFor() 221 * @see JLabel#setLabelFor(Component) 222 */ 223 Component findByLabel(String label, boolean showing); 224 225 /** 226 * Finds a <code>{@link Component}</code> by the text of its associated <code>{@link JLabel}</code>, in the hierarchy 227 * under the given root. If this finder is attached to a <code>{@link Robot}</code>, it will use the component lookup 228 * scope in the <code>Robot</code>'s <code>{@link Settings}</code> to determine whether the component to find should 229 * be showing or not. If this finder is <em>not</em> attached to any <code>Robot</code>, the component to find does 230 * not have to be showing. 231 * @param root the root used as the starting point of the search. 232 * @param label the text of the <code>JLabel</code> associated to the component to find. 233 * @return the found component. 234 * @throws ComponentLookupException if a matching component could not be found. 235 * @throws ComponentLookupException if more than one matching component is found. 236 * @see #findByLabel(String) 237 * @see JLabel#getLabelFor() 238 * @see JLabel#setLabelFor(Component) 239 * @see Robot#settings() 240 * @see Settings#componentLookupScope() 241 * @see ComponentLookupScope 242 */ 243 Component findByLabel(Container root, String label); 244 245 /** 246 * Finds a <code>{@link Component}</code> by the text of its associated <code>{@link JLabel}</code>, in the hierarchy 247 * under the given root. 248 * @param root the root used as the starting point of the search. 249 * @param label the text of the <code>JLabel</code> associated to the component to find. 250 * @param showing indicates whether the component to find should be visible (or showing) or not. 251 * @return the found component. 252 * @throws ComponentLookupException if a matching component could not be found. 253 * @throws ComponentLookupException if more than one matching component is found. 254 * @see #findByLabel(String) 255 * @see JLabel#getLabelFor() 256 * @see JLabel#setLabelFor(Component) 257 */ 258 Component findByLabel(Container root, String label, boolean showing); 259 260 /** 261 * Finds a <code>{@link Component}</code> by the text of its associated <code>{@link JLabel}</code> and type, in the 262 * hierarchy under the given root. If this finder is attached to a <code>{@link Robot}</code>, it will use the 263 * component lookup scope in the <code>Robot</code>'s <code>{@link Settings}</code> to determine whether the component 264 * to find should be showing or not. If this finder is <em>not</em> attached to any <code>Robot</code>, the component 265 * to find does not have to be showing. 266 * @param <T> the parameterized type of the component to find. 267 * @param root the root used as the starting point of the search. 268 * @param label the text of the <code>JLabel</code> associated to the component to find. 269 * @param type the type of the component to find. 270 * @return the found component. 271 * @throws ComponentLookupException if a matching component could not be found. 272 * @throws ComponentLookupException if more than one matching component is found. 273 * @see #findByLabel(String) 274 * @see JLabel#getLabelFor() 275 * @see JLabel#setLabelFor(Component) 276 * @see Robot#settings() 277 * @see Settings#componentLookupScope() 278 * @see ComponentLookupScope 279 */ 280 <T extends Component> T findByLabel(Container root, String label, Class<T> type); 281 282 /** 283 * Finds a <code>{@link Component}</code> by the text of its associated <code>{@link JLabel}</code> and type, in the 284 * hierarchy under the given root. 285 * @param <T> the parameterized type of the component to find. 286 * @param root the root used as the starting point of the search. 287 * @param label the text of the <code>JLabel</code> associated to the component to find. 288 * @param type the type of the component to find. 289 * @param showing indicates whether the component to find should be visible (or showing) or not. 290 * @return the found component. 291 * @throws ComponentLookupException if a matching component could not be found. 292 * @throws ComponentLookupException if more than one matching component is found. 293 * @see #findByLabel(String) 294 * @see JLabel#getLabelFor() 295 * @see JLabel#setLabelFor(Component) 296 */ 297 <T extends Component> T findByLabel(Container root, String label, Class<T> type, boolean showing); 298 299 /** 300 * <p> 301 * Finds a <code>{@link Component}</code> by name. If this finder is attached to a <code>{@link Robot}</code>, it 302 * will use the component lookup scope in the <code>Robot</code>'s <code>{@link Settings}</code> to determine whether 303 * the component to find should be showing or not. If this finder is <em>not</em> attached to any <code>Robot</code>, 304 * the component to find does not have to be showing. 305 * </p> 306 * <p> 307 * Let's assume we have the <code>{@link javax.swing.JTextField}</code> with name "myTextBox"; 308 * 309 * <pre> 310 * JTextField textbox = new JTextField(); 311 * textBox.setName("myTextBox"); 312 * </pre> 313 * 314 * </p> 315 * <p> 316 * To get a reference to this <code>{@link javax.swing.JTextField}</code> by its name, we can specify: 317 * 318 * <pre> 319 * JTextField textBox = (JTextField) finder.findByName("myTextBox"); 320 * </pre> 321 * 322 * </p> 323 * <p> 324 * Please note that you need to cast the result of the lookup to the right type. To avoid casting, please use one of 325 * following: 326 * <ol> 327 * <li><code>{@link #findByName(String, Class)}</code></li> 328 * <li><code>{@link #findByName(String, Class, boolean)}</code></li> 329 * <li><code>{@link #findByName(Container, String, Class)}</code></li> 330 * <li><code>{@link #findByName(Container, String, Class, boolean)}</code></li> 331 * </ol> 332 * </p> 333 * @param name the name of the component to find. 334 * @return the found component. 335 * @throws ComponentLookupException if a matching component could not be found. 336 * @throws ComponentLookupException if more than one matching component is found. 337 * @see Robot#settings() 338 * @see Settings#componentLookupScope() 339 * @see ComponentLookupScope 340 */ 341 Component findByName(String name); 342 343 /** 344 * Finds a <code>{@link Component}</code> by name and type. If this finder is attached to a 345 * <code>{@link Robot}</code>, it will use the component lookup scope in the <code>Robot</code>'s 346 * <code>{@link Settings}</code> to determine whether the component to find should be showing or not. If this finder 347 * is <em>not</em> attached to any <code>Robot</code>, the component to find does not have to be showing. 348 * @param <T> the parameterized type of the component to find. 349 * @param name the name of the component to find. 350 * @param type the type of the component to find. 351 * @return the found component. 352 * @throws ComponentLookupException if a matching component could not be found. 353 * @throws ComponentLookupException if more than one matching component is found. 354 * @see Robot#settings() 355 * @see Settings#componentLookupScope() 356 * @see ComponentLookupScope 357 * @see #findByName(String) 358 */ 359 <T extends Component> T findByName(String name, Class<T> type); 360 361 /** 362 * Finds a <code>{@link Component}</code> by name and type. 363 * @param <T> the parameterized type of the component to find. 364 * @param name the name of the component to find. 365 * @param type the type of the component to find. 366 * @param showing indicates whether the component to find should be visible (or showing) or not. 367 * @return the found component. 368 * @throws ComponentLookupException if a matching component could not be found. 369 * @throws ComponentLookupException if more than one matching component is found. 370 * @see #findByName(String) 371 */ 372 <T extends Component> T findByName(String name, Class<T> type, boolean showing); 373 374 /** 375 * Finds a <code>{@link Component}</code> by name. 376 * @param name the name of the component to find. 377 * @param showing indicates whether the component to find should be visible (or showing) or not. 378 * @return the found component. 379 * @throws ComponentLookupException if a matching component could not be found. 380 * @throws ComponentLookupException if more than one matching component is found. 381 * @see #findByName(String) 382 */ 383 Component findByName(String name, boolean showing); 384 385 /** 386 * Finds a <code>{@link Component}</code> by name, in the hierarchy under the given root. If this finder is attached 387 * to a <code>{@link Robot}</code>, it will use the component lookup scope in the <code>Robot</code>'s 388 * <code>{@link Settings}</code> to determine whether the component to find should be showing or not. If this finder 389 * is <em>not</em> attached to any <code>Robot</code>, the component to find does not have to be showing. 390 * @param root the root used as the starting point of the search. 391 * @param name the name of the component to find. 392 * @return the found component. 393 * @throws ComponentLookupException if a matching component could not be found. 394 * @throws ComponentLookupException if more than one matching component is found. 395 * @see Robot#settings() 396 * @see Settings#componentLookupScope() 397 * @see ComponentLookupScope 398 * @see #findByName(String) 399 */ 400 Component findByName(Container root, String name); 401 402 /** 403 * Finds a <code>{@link Component}</code> by name, in the hierarchy under the given root. 404 * @param root the root used as the starting point of the search. 405 * @param name the name of the component to find. 406 * @param showing indicates whether the component to find should be visible (or showing) or not. 407 * @return the found component. 408 * @throws ComponentLookupException if a matching component could not be found. 409 * @throws ComponentLookupException if more than one matching component is found. 410 * @see #findByName(String) 411 */ 412 Component findByName(Container root, String name, boolean showing); 413 414 /** 415 * Finds a <code>{@link Component}</code> by name and type, in the hierarchy under the given root. If this finder is 416 * attached to a <code>{@link Robot}</code>, it will use the component lookup scope in the <code>Robot</code>'s 417 * <code>{@link Settings}</code> to determine whether the component to find should be showing or not. If this finder 418 * is <em>not</em> attached to any <code>Robot</code>, the component to find does not have to be showing. 419 * @param <T> the parameterized type of the component to find. 420 * @param root the root used as the starting point of the search. 421 * @param name the name of the component to find. 422 * @param type the type of the component to find. 423 * @return the found component. 424 * @throws ComponentLookupException if a matching component could not be found. 425 * @throws ComponentLookupException if more than one matching component is found. 426 * @see Robot#settings() 427 * @see Settings#componentLookupScope() 428 * @see ComponentLookupScope 429 * @see #findByName(String) 430 */ 431 <T extends Component> T findByName(Container root, String name, Class<T> type); 432 433 /** 434 * Finds a <code>{@link Component}</code> by name and type, in the hierarchy under the given root. 435 * @param <T> the parameterized type of the component to find. 436 * @param root the root used as the starting point of the search. 437 * @param name the name of the component to find. 438 * @param type the type of the component to find. 439 * @param showing indicates whether the component to find should be visible (or showing) or not. 440 * @return the found component. 441 * @throws ComponentLookupException if a matching component could not be found. 442 * @throws ComponentLookupException if more than one matching component is found. 443 * @see #findByName(String) 444 */ 445 <T extends Component> T findByName(Container root, String name, Class<T> type, boolean showing); 446 447 /** 448 * Finds a <code>{@link Component}</code> using the given <code>{@link ComponentMatcher}</code>. The given matcher 449 * will be evaluated in the event dispatch thread. Implementations of <code>ComponentMatcher</code> do not need to 450 * be concerned about the event dispatch thread. 451 * @param m the matcher to use to find the component of interest. 452 * @return the found component. 453 * @throws ComponentLookupException if a matching component could not be found. 454 * @throws ComponentLookupException if more than one matching component is found. 455 */ 456 Component find(ComponentMatcher m); 457 458 /** 459 * Finds a <code>{@link Component}</code> using the given <code>{@link GenericTypeMatcher}</code>. The given matcher 460 * will be evaluated in the event dispatch thread. Implementations of <code>GenericTypeMatcher</code> do not need to 461 * be concerned about the event dispatch thread. 462 * @param <T> the type of component the given matcher can handle. 463 * @param m the matcher to use to find the component of interest. 464 * @return the found component. 465 * @throws ComponentLookupException if a matching component could not be found. 466 * @throws ComponentLookupException if more than one matching component is found. 467 */ 468 <T extends Component> T find(GenericTypeMatcher<T> m); 469 470 /** 471 * Finds a <code>{@link Component}</code> using the given <code>{@link GenericTypeMatcher}</code> in the hierarchy 472 * under the given root. The given matcher will be evaluated in the event dispatch thread. Implementations of 473 * <code>GenericTypeMatcher</code> do not need to be concerned about the event dispatch thread. 474 * @param <T> the type of component the given matcher can handle. 475 * @param root the root used as the starting point of the search. 476 * @param m the matcher to use to find the component. 477 * @return the found component. 478 * @throws ComponentLookupException if a matching component could not be found. 479 * @throws ComponentLookupException if more than one matching component is found. 480 */ 481 <T extends Component> T find(Container root, GenericTypeMatcher<T> m); 482 483 /** 484 * Finds a <code>{@link Component}</code> using the given <code>{@link ComponentMatcher}</code> in the hierarchy 485 * under the given root. The given matcher will be evaluated in the event dispatch thread. Implementations of 486 * <code>ComponentMatcher</code> do not need to be concerned about the event dispatch thread. 487 * @param root the root used as the starting point of the search. 488 * @param m the matcher to use to find the component. 489 * @return the found component. 490 * @throws ComponentLookupException if a matching component could not be found. 491 * @throws ComponentLookupException if more than one matching component is found. 492 */ 493 Component find(Container root, ComponentMatcher m); 494 495 /** 496 * Returns all the <code>{@link Component}</code>s that match the search criteria specified in the given 497 * <code>{@link ComponentMatcher}</code>. 498 * @param m the matcher to use to find the component. 499 * @return all the <code>Component</code>s that match the search criteria specified in the given 500 * <code>ComponentMatcher</code>; or an empty collection, if there are no matching components. 501 */ 502 Collection<Component> findAll(ComponentMatcher m); 503 504 /** 505 * Returns all the <code>{@link Component}</code>s under the given root that match the search criteria specified in 506 * the given <code>{@link ComponentMatcher}</code>. 507 * @param root the root used as the starting point of the search. 508 * @param m the matcher to use to find the component. 509 * @return all the <code>Component</code>s under the given root that match the search criteria specified in the given 510 * <code>ComponentMatcher</code>; or an empty collection, if there are no matching components. 511 */ 512 Collection<Component> findAll(Container root, ComponentMatcher m); 513 514 /** 515 * Returns all the <code>{@link Component}</code>s that match the search criteria specified in the given 516 * <code>{@link GenericTypeMatcher}</code>. 517 * @param <T> the generic type of component that this search supports. 518 * @param m the matcher to use to find the component. 519 * @return all the <code>Component</code>s that match the search criteria specified in the given 520 * <code>GenericTypeMatcher</code>; or an empty collection, if there are no matching components. 521 */ 522 <T extends Component> Collection<T> findAll(GenericTypeMatcher<T> m); 523 524 /** 525 * Returns all the <code>{@link Component}</code>s under the given root that match the search criteria specified in 526 * the given <code>{@link GenericTypeMatcher}</code>. 527 * @param <T> the generic type of component that this search supports. 528 * @param root the root used as the starting point of the search. 529 * @param m the matcher to use to find the component. 530 * @return all the <code>Component</code>s under the given root that match the search criteria specified in the given 531 * <code>GenericTypeMatcher</code>; or an empty collection, if there are no matching components. 532 */ 533 <T extends Component> Collection<T> findAll(Container root, GenericTypeMatcher<T> m); 534 535 /** 536 * Returns whether the message in a <code>{@link ComponentLookupException}</code> should include the current component 537 * hierarchy. The default value is <code>true</code>. 538 * @return <code>true</code> if the component hierarchy is included as part of the 539 * <code>ComponentLookupException</code> message, <code>false</code> otherwise. 540 */ 541 boolean includeHierarchyIfComponentNotFound(); 542 543 /** 544 * Updates whether the message in a <code>{@link ComponentLookupException}</code> should include the current component 545 * hierarchy. The default value is <code>true</code>. 546 * @param newValue the new value to set. 547 */ 548 void includeHierarchyIfComponentNotFound(boolean newValue); 549 }