1 /*
2  * Copyright (c) 1997, 2006, 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 
createUI(JComponent x)62     public static ComponentUI createUI(JComponent x) {
63         return new WindowsMenuBarUI();
64     }
65 
66     @Override
uninstallListeners()67     protected void uninstallListeners() {
68         uninstallWindowListener();
69         if (hierarchyListener != null) {
70             menuBar.removeHierarchyListener(hierarchyListener);
71             hierarchyListener = null;
72         }
73         super.uninstallListeners();
74     }
installWindowListener()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     }
uninstallWindowListener()94     private void uninstallWindowListener() {
95         if (windowListener != null && window != null) {
96             window.removeWindowListener(windowListener);
97         }
98         window = null;
99         windowListener = null;
100     }
101     @Override
installListeners()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 
installKeyboardActions()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     private static class TakeFocus extends AbstractAction {
actionPerformed(ActionEvent e)138         public void actionPerformed(ActionEvent e) {
139             JMenuBar menuBar = (JMenuBar)e.getSource();
140             JMenu menu = menuBar.getMenu(0);
141             if (menu != null) {
142                 MenuSelectionManager msm =
143                     MenuSelectionManager.defaultManager();
144                 MenuElement path[] = new MenuElement[2];
145                 path[0] = (MenuElement)menuBar;
146                 path[1] = (MenuElement)menu;
147                 msm.setSelectedPath(path);
148 
149                 // show mnemonics
150                 WindowsLookAndFeel.setMnemonicHidden(false);
151                 WindowsLookAndFeel.repaintRootPane(menuBar);
152             }
153         }
154     }
155 
156     @Override
paint(Graphics g, JComponent c)157     public void paint(Graphics g, JComponent c) {
158         XPStyle xp = XPStyle.getXP();
159         if (WindowsMenuItemUI.isVistaPainting(xp)) {
160             Skin skin;
161             skin = xp.getSkin(c, Part.MP_BARBACKGROUND);
162             int width = c.getWidth();
163             int height = c.getHeight();
164             State state =  isActive(c) ? State.ACTIVE : State.INACTIVE;
165             skin.paintSkin(g, 0, 0, width, height, state);
166         } else {
167             super.paint(g, c);
168         }
169     }
170 
171     /**
172      * Checks if component belongs to an active window.
173      * @param c component to check
174      * @return true if component belongs to an active window
175      */
isActive(JComponent c)176     static boolean isActive(JComponent c) {
177         JRootPane rootPane = c.getRootPane();
178         if (rootPane != null) {
179             Component component = rootPane.getParent();
180             if (component instanceof Window) {
181                 return ((Window) component).isActive();
182             }
183         }
184         return true;
185     }
186 }
187