All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.roydesign.ui.ScreenMenu Maven / Gradle / Ivy

Go to download

MRJ Adapter is a wrapper around built in Java Virtual Machine APIs provided by Apple.

The newest version!
/*******************************************************************************

	File:		ScreenMenu.java
	Author:		Steve Roy 
				
	Part of MRJ Adapter, a unified API for easy integration of Mac OS specific
	functionality within your cross-platform Java application.
	
	This library is open source and can be modified and/or distributed under
	the terms of the Artistic License.
	
	
	Change History:
	02/23/03	Created this file - Steve
	02/26/04    Merged into MRJ Adapter - Steve
	04/13/04	Added support for MenuItem Actions in addNotify() - Steve
	04/16/04    Renamed from Menu to ScreenMenu - Steve

*******************************************************************************/

package net.roydesign.ui;

import net.roydesign.mac.MRJAdapter;

import javax.swing.Action;
import javax.swing.JFrame;
import java.awt.Frame;
import java.awt.Menu;
import java.awt.MenuComponent;
import java.awt.MenuContainer;
import java.awt.MenuItem;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

/**
 * 

A subclass of {@code Menu} that adds the logistics needed to make menu * bars conform to the Mac OS screen menu bar requirements without sacrificing * the usual way of presenting menu bars on other platforms. See the class * {@code ScreenMenuBar} for more details.

* *

Additionally, if an instance of this class is populated with instances * of ScreenMenuItem, or simply other {@code ScreenMenus}, * then the menu will automatically disable itself when all its items are * disabled, and automatically enable itself back when one of the items becomes * enabled. This is the kind of behavior expected by users from a quality * desktop application and this class takes care of the work for you.

* * @see ScreenMenuBar * * @version MRJ Adapter 1.2 */ public class ScreenMenu extends Menu implements PropertyChangeListener { /** * The user frames of this menu. */ private final List> userFrames = new ArrayList<>(); /** * Construct a menu. */ public ScreenMenu() { super(""); } /** * Construct a menu with the given text as the title. * @param text the menu title */ public ScreenMenu(String text) { super(text); } /** * Construct a menu with the given text as the title. * @param text the menu title * @param tearOff whether the menu can be torn off or not */ public ScreenMenu(String text, boolean tearOff) { super(text, tearOff); } /** * This method is overriden to support automatic enabling and * disabling. * @param menuItem the menu item to be added * @return the menu item added */ @Override public MenuItem add(MenuItem menuItem) { if (menuItem instanceof ScreenMenuItem) ((ScreenMenuItem)menuItem).addPropertyChangeListener(this); return super.add(menuItem); } /** * This method is overriden to support automatic enabling and * disabling. * @param menuItem the menu item to be added * @param index the index where to insert the menu item */ @Override public void insert(MenuItem menuItem, int index) { if (menuItem instanceof ScreenMenuItem) ((ScreenMenuItem)menuItem).addPropertyChangeListener(this); super.insert(menuItem, index); } /** * This method is overriden to support automatic enabling and * disabling. * @param index the index of the menu item to be removed */ @Override public void remove(int index) { MenuItem it = getItem(index); if (it instanceof ScreenMenuItem) ((ScreenMenuItem)it).removePropertyChangeListener(this); super.remove(index); } /** * This method is overriden to disable or hide the items that don't * belong in the menu for the parent frame. */ @Override public void addNotify() { // Get the parent frame Frame f = getParentFrame(); // Loop through all menu items and check if the frame // makes any use of each one boolean disabled = true; boolean hasSeparator = true; int n = getItemCount(); for (int i = n - 1; i >= 0; i--) { MenuItem it = getItem(i); if ("-".equals(it.getLabel())) { if (hasSeparator) { remove(i); continue; } hasSeparator = true; } else if (it instanceof ScreenMenuItem) { ScreenMenuItem mi = (ScreenMenuItem)it; Action a = mi.getAction(); if (a != null && a instanceof AbstractScreenAction && ((AbstractScreenAction)a).isNotUsedBy(f) || !mi.isUsedBy(f)) { mi.setEnabled(false); hasSeparator = false; } else { hasSeparator = false; } } else if (it instanceof ScreenMenu) { ScreenMenu m = (ScreenMenu)it; if (m.isUsedBy(f)) { hasSeparator = false; } else { m.setEnabled(false); hasSeparator = false; } // m.addNotify(); /** @todo Why was this here? Causes missing menu in 1.4.2 on OS X */ } else { hasSeparator = false; } if (it.getParent() != null && it.isEnabled() && !"-".equals(it.getLabel())) disabled = false; } // Disable the menu if all its items are invisible or disabled if (disabled) setEnabled(false); super.addNotify(); } /** * Add the given {@code Frame} subclass as a user * of the menu. When a menu has no user frames, then all * frames get the menu. * * @param frameClass the {@code Frame} subclass */ public void addUserFrame(Class frameClass) { userFrames.add(frameClass); } /** * Remove the given {@code Frame} subclass from the users * of the menu. * * @param frameClass the {@code Frame} subclass */ public void removeUserFrame(Class frameClass) { userFrames.remove(frameClass); } /** * Get whether the menu is used by the given frame instance. * @return whether the menu is used by the given frame */ public boolean isUsedBy(Frame frame) { return userFrames.contains(frame.getClass()); } /** * Get the parent frame of the menu. * @return the parent {@code Frame} */ protected Frame getParentFrame() { MenuContainer cont = getParent(); while (cont != null && !(cont instanceof Frame)) cont = ((MenuComponent)cont).getParent(); return (Frame)cont; } /** * Implementation of the property listener interface. This method * disables the menu when all its items are disabled. Conversely, * it enables the menu when at least one of its items is enabled. * @param e the property change event */ @Override public void propertyChange(PropertyChangeEvent e) { if ("enabled".equals(e.getPropertyName())) { if ((Boolean) e.getNewValue()) { setEnabled(true); /** @todo With MRJ 3.x, the UI is not repainted */ } else { int n = getItemCount(); for (int i = 0; i < n; i++) { MenuItem it = getItem(i); if (it.isEnabled() && !"-".equals(it.getLabel())) return; } setEnabled(false); /** @todo With MRJ 3.x, the UI is not repainted */ } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy