|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectcom.holub.ui.MenuSite
public final class MenuSite
A MenuSite is a frame that holds a menu bar. Other objects in the system (which do not have to be visual objects) can negotiate with the MenuSite to have menu's placed on the site's menu bar (or within submenus already found on the menu bar). These objects can easily remove the menu modifications they've made.
The MenuSite is a static Singleton. You cannot create one
with new
---It's made up entirely of static
methods which you can access globally.
The first thing you must do is tell the system
which JFrame will host the menu bar by calling
MenuSite.establish(mainFrame)
. For example:
public class mainFrame extends JFrame { public mainFrame() { MenuSite.establish( this ); //... } }Once a menu site is established, objects that create user interfaces can add items to the menu site by calling
addLine(...)
(or more rarely, addMenu(...)
). In the
following example, an EmployeeManager
object
adds an "Employee" menu that has two submenus: "Hire" and
"Fire"
public class EmployeeManager { public EmployeeManager() { MenuSite.addLine( this, "Employee", null ) MenuSite.addLine( this, "Employee:Hire," HireListener ); MenuSite.addLine( this, "Employee:Fire," FireListener ); } }The
HireListener
and FireListener
objects implement ActionListener
, and
are notified when the menu item is selected.
There's (deliberatly) no way to remove individual menu items.
When the object that added items shuts down it's user interface,
it issues a single call to removeMyMenus
to remove all the menus and line items it added.
The creating object can also issue a
setEnable(java.lang.Object, boolean)
call to disable (or enable) all
menu and menus it created.
Important: A referece to the object that asked for
the menu item to be inserted is passed into most of the methods
of this class as the requester
argument. The
requester is used as a "key" in a hash table, and the hash-table
lookup method uses both the object's equals()
and
hashcode()
methods to do the lookup. For things
to work properly, the object used as a requester should
not implement equals()
. Java visual objects
like JComponent work fine as a requester, but be careful if
you use an object of a class of your own devising. Solve the
problem as follows:
class MyClass { public boolean equals() { ... } private final Object requesterId = new Object(); public f() { // Use requesterId instead of "this." MenuSite.addLine( requesterId, ... ); } }
If you haven't worked with menus before, bear in mind that
menu items and menus have both a "name" and also a "label."
The label is visible to the program's user, the name is
an arbitrary internal string. In an internationalized application,
the label will change with the local, but the name will
be fixed. The current classes use only the menu "name." If you don't
do anything special, the name is used as the label. You can provide
a file that maps names to arbitrary strings (and also defines
menu shortcuts) by calling mapNames(...)
.
Nested Class Summary | |
---|---|
static class |
MenuSite.Test
This inner class tests the MenuSite. |
Method Summary | |
---|---|
static void |
addLine(Object requester,
String toThisMenu,
String name,
ActionListener listener)
Adds a line item to a menu. |
static void |
addMapping(String name,
String label,
String shortcut)
Add a name-to-label mapping manually. |
static void |
addMenu(Object requester,
String menuSpecifier)
Create and add an empty menu to the menu bar. |
static void |
establish(JFrame container)
Establish a JFrame as the program's menu site. |
static JMenuItem |
getMyMenuItem(Object requester,
String menuSpecifier,
String name)
Get a menu item for external modification. |
static void |
mapNames(URL table)
Establishes a "map" of (hidden) names to (visible) labels and shortcuts. |
static void |
removeMyMenus(Object requester)
Remove all items that were added by this requester. |
static void |
setEnable(Object requester,
boolean enable)
Disable or enable all menus and menu items added by a specific requester. |
Methods inherited from class java.lang.Object |
---|
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Method Detail |
---|
public static void establish(JFrame container)
NullPointerException
if you try to use them when no menu site has been established.)
public static void addMenu(Object requester, String menuSpecifier)
addLine(...)
.
This method
is provided for situations where one "requester" creates
a menu structure and other requesters will add line items
to this structure. By using one requester for the main
menu, and other requesters for the line items on the menu,
the requesters that added the line items can remove those
items without removing the menu that contained the items.
Menus are inserted on the menu bar just to the left of the "Help" menu. (The "help" menu [a menu whose name is the string "help"---case is ignored] is special in that it always appears on the far right of the menu bar.)
Use addLine(...)
to add line items to the menu created by the current call.
The name-to-label substitution described in
addLine(...)
is
done here as well. As in that method, the name
string
also defines the (visible) label if no mapping is found.
If the requested menu already exists, this method silently does nothing.
requester
- The object that requested that this menu
be added. All menus (and line items) added by a specific
requster are removed by a single
removeMyMenus(...)
call.
The requester need not be the actual object that adds
the menu---there may not be a single one. It is simply
used to identify a group of menu items that will be
removed in bulk. All items that have the same requester
object are removed at once.menuSpecifier
- The menu to create. A simple specifier (with
no colons in it) creates an item on the menu bar itself.
Submenus are specified using the syntax "main:sub"
.
For example,
addMenu( this, "File:New" )
creates a "New" submenu under the "File" menu. If the supermenu
(in this example, "File") doesn't exist, it's created. You can
have more than one colon if you want to go down more than one
level (e.g. "Edit:Text:Size"). Up to six levels below the
menu bar (six colons) are supported.
(If you have more than that, you should seriously
reconsider your menu structure.)
Intermediate menus are
added as necessary.
IllegalArgumentException
- if the menuSpecifier is malformed
(e.g. has spaces in it) or if the specifier identifies
an existing line item (as compared to a menu).public static void addLine(Object requester, String toThisMenu, String name, ActionListener listener)
This method is the preferred way to both create menus and
add line items to existing menus.
See addMenu(...)
for the
rules of menu creation.
By default, the "name" is used for the "label." However,
when there is a name map (see mapNames(java.net.URL)
), then the name
parameter is used for the name, and the associated labels and
shortcuts specified in the map are used.
If there is a map, but the map has no
entry for the item named by the name
parameter,
then the name is used for the label and a warning is logged to the
com.holub.ui stream using the standard java Logging APIs.
requester
- The object that requested that this
line item be added.name
- The (hidden) name text for this item.
When there's no name map,
the same string is used for both the name and the
label (and there is no shortcut), otherwise
the name
argument specifies the
name only, and the associated label
(and shortcut) is taken from the map.
Use the name "-"
to place a separator
into a menu. The listener
argument
is not used in this case, and can be null.
toThisMenu
- The specifier of the menu to which you're adding
the line item.
(See addMenu(...)
for a discussion of specifiers.) The
specified menu is created if it doesn't
already exist.listener
- The ActionListener to notify when the menu
item is selected.addMenu(java.lang.Object, java.lang.String)
,
mapNames(java.net.URL)
public static void removeMyMenus(Object requester)
For the time being, the case of "foreign" items being
placed on a menu created by another requester is not
handled.
Consider a program in which two object both add an item
to the "File" menu. The first object to add an item will
be the official "owner" of the menu, since it created the
menu. When you call removeMyMenus()
for this
first object, you want to remove the line item it added
to the "File" menu, but you don't want to remove the "File"
menu itself because it's not empty. Right now, the only
solution to this problem is for a third requester to create
the menu itself using addMenu(...)
.
public static void setEnable(Object requester, boolean enable)
MenuSite.getMyMenuItem(requester,"parent:spec", "name")
.setEnabled(FALSE);
enable
- true to enable all the requester's menu items.public static JMenuItem getMyMenuItem(Object requester, String menuSpecifier, String name)
JMenuItem
that was created by
addLine(...)
under the covers. Use the returned
reference to do things like disable the line item. Do not
manipulate the menu structure (by adding and removing items),
however.
requester
- the object that inserted the menu or itemmenuSpecifier
- the menuSpecifier passed to the original
addMenu(...)
or
addLine(...)
call.name
- the name passed to
addLine(...)
. null
if you want a menu rather than a line item
within the menu.
JMenu
or
JMenuItem
.
Returns null
if the item
doesn't exist.public static void mapNames(URL table) throws IOException
addLine(...)
and
addMenu(...)
and
in that the specified label
and shortcut are installed automatically for all names specified
in the table.
A map must be specified before the item named in the map
are added to the menu site.
You may call this method multiple times to load multiple maps,
but the "name" component of each entry must be unique across
all maps.
table
- a Properties-style file that maps named
keys to labels, along with an optional
shortcuts. The general form is:
name.1 = label One; C name.2 = label Two; Alt XThe shortcut can be specified in one of two ways. If it's a single character, as in the first example, above, the platform-default modifier is used. For example, in the first example, the shortcut will be a Ctrl-C in Windows, a Command-C on the Mac, etc. Otherwise, the shortcut specifier must take the form described in
KeyStroke.getKeyStroke(String)
.
For example:
F1 control DELETE alt shift X alt shift released X typed aNames like DELETE and F1 are shorthand for VK_DELETE and VK_F1. (The complete set of VK_xxx constants are found in the
KeyEvent
class.) You can use any of
these "virtual" keys simply by removing the VK_.
For reasons that are mysterious to me, F10 is hard mapped to display the main menu (so that you can navigate the menus with the arrow keys). You could probably defeat this behavior with a key binding, but it's easier to just accept it as a fait accompli, and not try to define F10 as a keyboard "shortcut."
The input file is a standard "Properties" file, which is
assumed to be ISO 8859-1 (not Unicode) encoded.
See Properties.load(java.io.InputStream)
for a full
description of the file format.
IOException
- if it can't load the tableKeyEvent
,
Properties
public static void addMapping(String name, String label, String shortcut)
name
- The menu-item name passed to
addMenu(...)
or addLine(...)
.label
- The visible label for that item.shortcut
- The shortcut, if any. Should be an empty string
(""
) if no shortcut is required.
See mapNames(...)
for information on how to
form this string.mapNames(java.net.URL)
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |