mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-15 16:09:44 +00:00
291 lines
9.4 KiB
Java
291 lines
9.4 KiB
Java
/*
|
|
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
package com.apple.laf;
|
|
|
|
import sun.lwawt.macosx.CMenuBar;
|
|
|
|
import java.awt.*;
|
|
import java.awt.event.*;
|
|
import java.util.*;
|
|
|
|
import javax.swing.*;
|
|
|
|
import static sun.awt.AWTAccessor.*;
|
|
|
|
@SuppressWarnings("serial") // JDK implementation class
|
|
public final class ScreenMenuBar extends MenuBar
|
|
implements ContainerListener, ScreenMenuPropertyHandler,
|
|
ComponentListener {
|
|
|
|
static boolean sJMenuBarHasHelpMenus = false; //$ could check by calling getHelpMenu in a try block
|
|
|
|
JMenuBar fSwingBar;
|
|
Hashtable<JMenu, ScreenMenu> fSubmenus;
|
|
|
|
ScreenMenuPropertyListener fPropertyListener;
|
|
ScreenMenuPropertyListener fAccessibleListener;
|
|
|
|
public ScreenMenuBar(final JMenuBar swingBar) {
|
|
fSwingBar = swingBar;
|
|
fSubmenus = new Hashtable<JMenu, ScreenMenu>(fSwingBar.getMenuCount());
|
|
}
|
|
|
|
@Override
|
|
public void addNotify() {
|
|
super.addNotify();
|
|
|
|
fSwingBar.addContainerListener(this);
|
|
fPropertyListener = new ScreenMenuPropertyListener(this);
|
|
fSwingBar.addPropertyChangeListener(fPropertyListener);
|
|
fAccessibleListener = new ScreenMenuPropertyListener(this);
|
|
fSwingBar.getAccessibleContext().addPropertyChangeListener(fAccessibleListener);
|
|
|
|
// We disable component events when the menu bar is not parented. So now we need to
|
|
// sync back up with the current state of the JMenuBar. We first add the menus we
|
|
// don't have and then remove the items that are no longer on the JMenuBar.
|
|
final int count = fSwingBar.getMenuCount();
|
|
for(int i = 0; i < count ; i++) {
|
|
final JMenu m = fSwingBar.getMenu(i);
|
|
if (m != null) {
|
|
addSubmenu(m);
|
|
}
|
|
}
|
|
|
|
final Enumeration<JMenu> e = fSubmenus.keys();
|
|
while (e.hasMoreElements()) {
|
|
final JMenu m = e.nextElement();
|
|
if (fSwingBar.getComponentIndex(m) == -1) {
|
|
removeSubmenu(m);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void removeNotify() {
|
|
// KCH - 3974930 - We do null checks for fSwingBar and fSubmenus because some people are using
|
|
// reflection to muck about with our ivars
|
|
if (fSwingBar != null) {
|
|
fSwingBar.removePropertyChangeListener(fPropertyListener);
|
|
fSwingBar.getAccessibleContext().removePropertyChangeListener(fAccessibleListener);
|
|
fSwingBar.removeContainerListener(this);
|
|
}
|
|
|
|
fPropertyListener = null;
|
|
fAccessibleListener = null;
|
|
|
|
if (fSubmenus != null) {
|
|
// We don't listen to events when the menu bar is not parented.
|
|
// Remove all the component listeners.
|
|
final Enumeration<JMenu> e = fSubmenus.keys();
|
|
while (e.hasMoreElements()) {
|
|
final JMenu m = e.nextElement();
|
|
m.removeComponentListener(this);
|
|
}
|
|
}
|
|
|
|
super.removeNotify();
|
|
}
|
|
|
|
/**
|
|
* Invoked when a component has been added to the container.
|
|
*/
|
|
@Override
|
|
public void componentAdded(final ContainerEvent e) {
|
|
final Component child = e.getChild();
|
|
if (!(child instanceof JMenu)) return;
|
|
addSubmenu((JMenu)child);
|
|
}
|
|
|
|
/**
|
|
* Invoked when a component has been removed from the container.
|
|
*/
|
|
@Override
|
|
public void componentRemoved(final ContainerEvent e) {
|
|
final Component child = e.getChild();
|
|
if (!(child instanceof JMenu)) return;
|
|
removeSubmenu((JMenu)child);
|
|
}
|
|
|
|
/**
|
|
* Invoked when the component's size changes.
|
|
*/
|
|
@Override
|
|
public void componentResized(final ComponentEvent e) {}
|
|
|
|
/**
|
|
* Invoked when the component's position changes.
|
|
*/
|
|
@Override
|
|
public void componentMoved(final ComponentEvent e) {}
|
|
|
|
/**
|
|
* Invoked when the component has been made visible.
|
|
* See componentHidden - we should still have a MenuItem
|
|
* it just isn't inserted
|
|
*/
|
|
@Override
|
|
public void componentShown(final ComponentEvent e) {
|
|
final Object source = e.getSource();
|
|
if (!(source instanceof JMenuItem)) return;
|
|
setChildVisible((JMenuItem)source, true);
|
|
}
|
|
|
|
/**
|
|
* Invoked when the component has been made invisible.
|
|
* MenuComponent.setVisible does nothing,
|
|
* so we remove the ScreenMenuItem from the ScreenMenu
|
|
* but leave it in fItems
|
|
*/
|
|
@Override
|
|
public void componentHidden(final ComponentEvent e) {
|
|
final Object source = e.getSource();
|
|
if (!(source instanceof JMenuItem)) return;
|
|
setChildVisible((JMenuItem)source, false);
|
|
}
|
|
|
|
/*
|
|
* MenuComponent.setVisible does nothing,
|
|
* so we just add or remove the child from the ScreenMenuBar
|
|
* but leave it in the list
|
|
*/
|
|
@Override
|
|
public void setChildVisible(final JMenuItem child, final boolean b) {
|
|
if (child instanceof JMenu) {
|
|
if (b) {
|
|
addSubmenu((JMenu)child);
|
|
} else {
|
|
final ScreenMenu sm = fSubmenus.get(child);
|
|
if (sm != null)
|
|
remove(sm);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void removeAll() {
|
|
synchronized (getTreeLock()) {
|
|
final int nitems = getMenuCount();
|
|
for (int i = nitems-1 ; i >= 0 ; i--) {
|
|
remove(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setIcon(final Icon i) {}
|
|
@Override
|
|
public void setLabel(final String s) {}
|
|
|
|
@Override
|
|
public void setEnabled(final boolean b) {
|
|
final int count = fSwingBar.getMenuCount();
|
|
for (int i = 0; i < count; i++) {
|
|
fSwingBar.getMenu(i).setEnabled(b);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setAccelerator(final KeyStroke ks) {}
|
|
@Override
|
|
public void setToolTipText(final String tooltip) {}
|
|
|
|
// only check and radio items can be indeterminate
|
|
@Override
|
|
public void setIndeterminate(boolean indeterminate) { }
|
|
|
|
ScreenMenu addSubmenu(final JMenu m) {
|
|
ScreenMenu sm = fSubmenus.get(m);
|
|
|
|
if (sm == null) {
|
|
sm = new ScreenMenu(m);
|
|
m.addComponentListener(this);
|
|
fSubmenus.put(m, sm);
|
|
}
|
|
|
|
sm.setEnabled(m.isEnabled());
|
|
|
|
// MenuComponents don't support setVisible, so we just don't add it to the menubar
|
|
if (m.isVisible() && sm.getParent() == null) {
|
|
int newIndex = 0, currVisibleIndex = 0;
|
|
JMenu menu = null;
|
|
final int menuCount = fSwingBar.getMenuCount();
|
|
for (int i = 0; i < menuCount; i++) {
|
|
menu = fSwingBar.getMenu(i);
|
|
if (menu == m) {
|
|
newIndex = currVisibleIndex;
|
|
break;
|
|
}
|
|
if (menu != null && menu.isVisible()) {
|
|
currVisibleIndex++;
|
|
}
|
|
}
|
|
add(sm, newIndex);
|
|
}
|
|
|
|
return sm;
|
|
}
|
|
|
|
/**
|
|
* Remove the screen menu associated with the specifiec menu. This
|
|
* also removes any associated component listener on the screen menu
|
|
* and removes the key/value (menu/screen menu) from the fSubmenus cache.
|
|
*
|
|
* @param menu The swing menu we want to remove the screen menu for.
|
|
*/
|
|
private void removeSubmenu(final JMenu menu) {
|
|
final ScreenMenu screenMenu = fSubmenus.get(menu);
|
|
if (screenMenu == null) return;
|
|
|
|
menu.removeComponentListener(this);
|
|
remove(screenMenu);
|
|
fSubmenus.remove(menu);
|
|
}
|
|
|
|
public Menu add(final Menu m, final int index) {
|
|
synchronized (getTreeLock()) {
|
|
if (m.getParent() != null) {
|
|
m.getParent().remove(m);
|
|
}
|
|
|
|
final Vector<Menu> menus = getMenuBarAccessor().getMenus(this);
|
|
menus.insertElementAt(m, index);
|
|
final MenuComponentAccessor acc = getMenuComponentAccessor();
|
|
acc.setParent(m, this);
|
|
|
|
final CMenuBar peer = acc.getPeer(this);
|
|
if (peer == null) return m;
|
|
|
|
peer.setNextInsertionIndex(index);
|
|
final CMenuBar mPeer = acc.getPeer(m);
|
|
if (mPeer == null) {
|
|
m.addNotify();
|
|
}
|
|
|
|
peer.setNextInsertionIndex(-1);
|
|
return m;
|
|
}
|
|
}
|
|
}
|