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
26package com.sun.java.swing.plaf.windows;
27
28import javax.swing.plaf.basic.*;
29import javax.swing.*;
30import javax.swing.plaf.ActionMapUIResource;
31import javax.swing.plaf.ComponentUI;
32import java.awt.event.ActionEvent;
33import java.awt.event.HierarchyEvent;
34import java.awt.event.HierarchyListener;
35import java.awt.event.WindowAdapter;
36import java.awt.event.WindowEvent;
37import java.awt.event.WindowListener;
38import java.awt.event.WindowStateListener;
39
40import java.awt.*;
41
42import com.sun.java.swing.plaf.windows.TMSchema.*;
43import 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 */
55public 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}
188