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 }