001    /*
002     * Created on Jan 31, 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.driver;
017    
018    import static org.fest.swing.query.ComponentShowingQuery.isShowing;
019    
020    import java.awt.Component;
021    
022    import javax.swing.*;
023    
024    import org.fest.swing.annotation.RunsInCurrentThread;
025    import org.fest.swing.annotation.RunsInEDT;
026    
027    /**
028     * Understands the location of a <code>{@link JMenuItem}</code>.
029     *
030     * @author Alex Ruiz
031     */
032    public final class JMenuItemLocation {
033    
034      private Component parentOrInvoker;
035      private JPopupMenu parentPopup;
036    
037      private final boolean inMenuBar;
038    
039      /**
040       * Creates a new </code>{@link JMenuItemLocation}</code>.
041       * <p>
042       * <b>Note:</b> This constructor is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients
043       * are responsible for ensuring that this constructor is executed in the EDT.
044       * </p>
045       * @param menuItem the target <code>JMenuItem</code>.
046       */
047      @RunsInCurrentThread
048      public JMenuItemLocation(JMenuItem menuItem) {
049        parentOrInvoker = menuItem.getParent();
050        if (parentOrInvoker instanceof JPopupMenu) {
051          parentPopup = (JPopupMenu)parentOrInvoker;
052          parentOrInvoker = ((JPopupMenu)parentOrInvoker).getInvoker();
053        }
054        inMenuBar = parentOrInvoker instanceof JMenuBar;
055      }
056    
057      /**
058       * Indicates whether the <code>{@link JMenuItem}</code> is in a <code>{@link JMenuBar}</code>.
059       * @return <code>true</code> if the <code>JMenuItem</code> is in a <code>JMenuBar</code>, <code>false</code>
060       * otherwise.
061       */
062      public boolean inMenuBar() {
063        return inMenuBar;
064      }
065    
066      /**
067       * Indicates whether the parent of the <code>{@link JMenuItem}</code> is another menu.
068       * @return <code>true</code> if the parent of the <code>JMenuItem</code> is another menu, <code>false</code>
069       * otherwise.
070       */
071      @RunsInEDT
072      public boolean isParentAMenu() {
073        if (!(parentOrInvoker instanceof JMenuItem)) return false;
074        return parentPopup == null || !isShowing(parentPopup);
075      }
076    
077      /**
078       * Returns the parent of <code>{@link JMenuItem}</code>, or its invoker (if it is in a pop-up.)
079       * @return the parent or the invoker of the <code>JMenuItem</code>.
080       */
081      public Component parentOrInvoker() {
082        return parentOrInvoker;
083      }
084    
085      /**
086       * Returns the parent pop-up menu, or <code>null</code> if the <code>{@link JMenuItem}</code> is not in a pop-up.
087       * @return the parent pop-up menu, or <code>null</code> if the <code>JMenuItem</code> is not in a pop-up.
088       */
089      public JPopupMenu parentPopup() {
090        return parentPopup;
091      }
092    }