1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.java.swing.plaf.windows;
  27 
  28 import javax.swing.plaf.basic.*;
  29 import javax.swing.*;
  30 import javax.swing.plaf.ActionMapUIResource;
  31 import javax.swing.plaf.ComponentUI;
  32 import java.awt.event.ActionEvent;
  33 import java.awt.event.HierarchyEvent;
  34 import java.awt.event.HierarchyListener;
  35 import java.awt.event.WindowAdapter;
  36 import java.awt.event.WindowEvent;
  37 import java.awt.event.WindowListener;
  38 import java.awt.event.WindowStateListener;
  39 
  40 import java.awt.*;
  41 
  42 import com.sun.java.swing.plaf.windows.TMSchema.*;
  43 import com.sun.java.swing.plaf.windows.XPStyle.*;
  44 
  45 /**
  46  * Windows rendition of the component.
  47  * <p>
  48  * <strong>Warning:</strong>
  49  * Serialized objects of this class will not be compatible with
  50  * future Swing releases.  The current serialization support is appropriate
  51  * for short term storage or RMI between applications running the same
  52  * version of Swing.  A future release of Swing will provide support for
  53  * long term persistence.
  54  */
  55 public class WindowsMenuBarUI extends BasicMenuBarUI
  56 {
  57     /* to be accessed on the EDT only */
  58     private WindowListener windowListener = null;
  59     private HierarchyListener hierarchyListener = null;
  60     private Window window = null;
  61 
  62     public static ComponentUI createUI(JComponent x) {
  63         return new WindowsMenuBarUI();
  64     }
  65 
  66     @Override
  67     protected void uninstallListeners() {
  68         uninstallWindowListener();
  69         if (hierarchyListener != null) {
  70             menuBar.removeHierarchyListener(hierarchyListener);
  71             hierarchyListener = null;
  72         }
  73         super.uninstallListeners();
  74     }
  75     private void installWindowListener() {
  76         if (windowListener == null) {
  77             Component component = menuBar.getTopLevelAncestor();
  78             if (component instanceof Window) {
  79                 window = (Window) component;
  80                 windowListener = new WindowAdapter() {
  81                     @Override
  82                     public void windowActivated(WindowEvent e) {
  83                         menuBar.repaint();
  84                     }
  85                     @Override
  86                     public void windowDeactivated(WindowEvent e) {
  87                         menuBar.repaint();
  88                     }
  89                 };
  90                 ((Window) component).addWindowListener(windowListener);
  91             }
  92         }
  93     }
  94     private void uninstallWindowListener() {
  95         if (windowListener != null && window != null) {
  96             window.removeWindowListener(windowListener);
  97         }
  98         window = null;
  99         windowListener = null;
 100     }
 101     @Override
 102     protected void installListeners() {
 103         if (WindowsLookAndFeel.isOnVista()) {
 104             installWindowListener();
 105             hierarchyListener =
 106                 new HierarchyListener() {
 107                     public void hierarchyChanged(HierarchyEvent e) {
 108                         if ((e.getChangeFlags()
 109                                 & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
 110                             if (menuBar.isDisplayable()) {
 111                                 installWindowListener();
 112                             } else {
 113                                 uninstallWindowListener();
 114                             }
 115                         }
 116                     }
 117             };
 118             menuBar.addHierarchyListener(hierarchyListener);
 119         }
 120         super.installListeners();
 121     }
 122 
 123     protected void installKeyboardActions() {
 124         super.installKeyboardActions();
 125         ActionMap map = SwingUtilities.getUIActionMap(menuBar);
 126         if (map == null) {
 127             map = new ActionMapUIResource();
 128             SwingUtilities.replaceUIActionMap(menuBar, map);
 129         }
 130         map.put("takeFocus", new TakeFocus());
 131     }
 132 
 133     /**
 134      * Action that activates the menu (e.g. when F10 is pressed).
 135      * Unlike BasicMenuBarUI.TakeFocus, this Action will not show menu popup.
 136      */
 137     @SuppressWarnings("serial") // Superclass is not serializable across versions
 138     private static class TakeFocus extends AbstractAction {
 139         public void actionPerformed(ActionEvent e) {
 140             JMenuBar menuBar = (JMenuBar)e.getSource();
 141             JMenu menu = menuBar.getMenu(0);
 142             if (menu != null) {
 143                 MenuSelectionManager msm =
 144                     MenuSelectionManager.defaultManager();
 145                 MenuElement path[] = new MenuElement[2];
 146                 path[0] = (MenuElement)menuBar;
 147                 path[1] = (MenuElement)menu;
 148                 msm.setSelectedPath(path);
 149 
 150                 // show mnemonics
 151                 WindowsLookAndFeel.setMnemonicHidden(false);
 152                 WindowsLookAndFeel.repaintRootPane(menuBar);
 153             }
 154         }
 155     }
 156 
 157     @Override
 158     public void paint(Graphics g, JComponent c) {
 159         XPStyle xp = XPStyle.getXP();
 160         if (WindowsMenuItemUI.isVistaPainting(xp)) {
 161             Skin skin;
 162             skin = xp.getSkin(c, Part.MP_BARBACKGROUND);
 163             int width = c.getWidth();
 164             int height = c.getHeight();
 165             State state =  isActive(c) ? State.ACTIVE : State.INACTIVE;
 166             skin.paintSkin(g, 0, 0, width, height, state);
 167         } else {
 168             super.paint(g, c);
 169         }
 170     }
 171 
 172     /**
 173      * Checks if component belongs to an active window.
 174      * @param c component to check
 175      * @return true if component belongs to an active window
 176      */
 177     static boolean isActive(JComponent c) {
 178         JRootPane rootPane = c.getRootPane();
 179         if (rootPane != null) {
 180             Component component = rootPane.getParent();
 181             if (component instanceof Window) {
 182                 return ((Window) component).isActive();
 183             }
 184         }
 185         return true;
 186     }
 187 }