001 /*
002 * Created on Dec 2, 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 static java.lang.String.valueOf;
019 import static org.fest.util.Objects.areEqual;
020 import static org.fest.util.Strings.*;
021
022 import java.awt.Component;
023
024 import javax.swing.JLabel;
025
026 import org.fest.swing.annotation.RunsInCurrentThread;
027
028 /**
029 * Understands <code>{@link java.awt.Component}</code> matching by the text of the associated
030 * <code>{@link JLabel}</code> and (optionally) by type.
031 * @see JLabel#getLabelFor()
032 * @see JLabel#setLabelFor(Component)
033 *
034 * @author Alex Ruiz
035 */
036 public class LabelMatcher extends AbstractComponentMatcher {
037
038 private final String label;
039 private final Class<? extends Component> type;
040
041 /**
042 * Creates a new <code>{@link LabelMatcher}</code>. The component to match does not have to be showing.
043 * @param label the text of the label associated to the component we are looking for.
044 * @throws NullPointerException if the given label is <code>null</code>.
045 * @throws IllegalArgumentException if the given label is empty.
046 */
047 public LabelMatcher(String label) {
048 this(label, false);
049 }
050
051 /**
052 * Creates a new <code>{@link LabelMatcher}</code>.
053 * @param label the text of the label associated to the component we are looking for.
054 * @param requireShowing indicates if the component to match should be showing or not.
055 * @throws NullPointerException if the given label is <code>null</code>.
056 * @throws IllegalArgumentException if the given label is empty.
057 */
058 public LabelMatcher(String label, boolean requireShowing) {
059 this(label, Component.class, requireShowing);
060 }
061
062 /**
063 * Creates a new <code>{@link LabelMatcher}</code>. The component to match does not have to be showing.
064 * @param label the text of the label associated to the component we are looking for.
065 * @param type the type of the component we are looking for.
066 * @throws NullPointerException if the given label is <code>null</code>.
067 * @throws IllegalArgumentException if the given label is empty.
068 * @throws NullPointerException if the given type is <code>null</code>.
069 */
070 public LabelMatcher(String label, Class<? extends Component> type) {
071 this(label, type, false);
072 }
073
074 /**
075 * Creates a new <code>{@link LabelMatcher}</code>.
076 * @param label the text of the label associated to the component we are looking for.
077 * @param type the type of the component we are looking for.
078 * @param requireShowing indicates if the component to match should be showing or not.
079 * @throws NullPointerException if the given label is <code>null</code>.
080 * @throws IllegalArgumentException if the given label is empty.
081 * @throws NullPointerException if the given type is <code>null</code>.
082 */
083 public LabelMatcher(String label, Class<? extends Component> type, boolean requireShowing) {
084 super(requireShowing);
085 if (label == null)
086 throw new NullPointerException("The text of the label associated to the component to find should not be null");
087 if (isEmpty(label))
088 throw new IllegalArgumentException("The text of the label associated to the component to find should not be empty");
089 if (type == null) throw new NullPointerException("The type of component to find should not be null");
090 this.label = label;
091 this.type = type;
092 }
093
094 /**
095 * Indicates whether the given <code>{@link java.awt.Component}</code> matches the criteria specified in this
096 * matcher:
097 * <ol>
098 * <li>the text of the <code>{@link JLabel}</code></li> attached to the component to look for matches the text
099 * specified in this matcher
100 * <li>the component to look for is of the type specified in this matcher (if specified)</li>
101 * <li>visibility of the given <code>{@link java.awt.Component}</code> matches the value specified in this matcher
102 * </li>
103 * </ol>
104 * <p>
105 * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
106 * responsible for calling this method from the EDT.
107 * </p>
108 * @return <code>true</code> if the name and visibility of the given <code>Component</code> matches the values
109 * specified in this matcher, <code>false</code> otherwise.
110 */
111 @RunsInCurrentThread
112 public boolean matches(Component c) {
113 if (!(c instanceof JLabel)) return false;
114 JLabel labelForComponent = (JLabel)c;
115 if (!areEqual(labelForComponent.getText(), label)) return false;
116 Component labeled = labelForComponent.getLabelFor();
117 return type.isInstance(labeled) && requireShowingMatches(labeled);
118 }
119
120 @Override public String toString() {
121 return concat(
122 getClass().getName(), "[",
123 "label=", quote(label), ", ",
124 "type=", type.getName(), ", ",
125 "requireShowing=", valueOf(requireShowing()),
126 "]"
127 );
128 }
129 }