001 /*
002 * Created on Sep 5, 2007
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 @2007-2010 the original author or authors.
014 */
015 package org.fest.swing.driver;
016
017 import static org.fest.swing.driver.AbstractButtonTextQuery.textOf;
018 import static org.fest.util.Objects.areEqual;
019 import static org.fest.util.Strings.*;
020
021 import java.awt.Component;
022
023 import javax.swing.JMenuItem;
024 import javax.swing.JPopupMenu;
025
026 import org.fest.swing.annotation.RunsInCurrentThread;
027 import org.fest.swing.core.ComponentMatcher;
028
029 /**
030 * Matches a <code>{@link JMenuItem}</code> given a simple label or a menu path of the format "menu|submenu|menuitem",
031 * for example "File|Open|Can of worms". Adapted from Abbot's own <code>JMenuItemMatcher</code>.
032 *
033 * @author Yvonne Wang
034 * @author Alex Ruiz
035 */
036 public class JMenuItemMatcher implements ComponentMatcher {
037
038 private static final String SEPARATOR = "|";
039
040 private final String label;
041
042 /**
043 * Creates a new </code>{@link JMenuItemMatcher}</code>.
044 * @param path the path of the menu to match.
045 */
046 public JMenuItemMatcher(String... path) {
047 this.label = join(path).with(SEPARATOR);
048 }
049
050 /**
051 * Indicates whether the given component is a <code>{@link JMenuItem}</code> whose text matches the path specified
052 * in this matcher.
053 * <p>
054 * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
055 * responsible for calling this method from the EDT.
056 * </p>
057 * @param c the component to verify.
058 * @return <code>true</code> if the component matches, <code>false</code> otherwise.
059 */
060 @RunsInCurrentThread
061 public boolean matches(Component c) {
062 if (!(c instanceof JMenuItem)) return false;
063 JMenuItem menuItem = (JMenuItem) c;
064 String text = menuItem.getText();
065 return areEqual(label, text) || areEqual(label, pathOf(menuItem));
066 }
067
068 @RunsInCurrentThread
069 private String pathOf(JMenuItem menuItem) {
070 Component parent = parentOrInvokerOf(menuItem);
071 if (parent instanceof JMenuItem)
072 return concat(pathOf((JMenuItem)parent), SEPARATOR, textOf(menuItem));
073 return textOf(menuItem);
074 }
075
076 @RunsInCurrentThread
077 private Component parentOrInvokerOf(JMenuItem menuItem) {
078 Component parent = menuItem.getParent();
079 if (parent instanceof JPopupMenu)
080 parent = ((JPopupMenu)parent).getInvoker();
081 return parent;
082 }
083
084 @Override public String toString() {
085 return concat(getClass().getName(), "[", "label=", quote(label), "]");
086 }
087 }