|
Article
|
Difficulty
Rating
|
1
|
Doing
Menus in
MetaCard
|
|
Menus
are really very simple
to do in MetaCard.
However, they often
prove to be one of the
more difficult concepts
to get to grips with if
you are just starting
out. The important thing
to understand is that
menus in MetaCard are
really just buttons with
a few fancy properties
set. This even applies
to the MacOS version of
MetaCard - editing the
menu bar is just a case
of moving around buttons
on the stack to which
the menus are
"attached". Even if you
are an old hand with
menus, you'll want to
check out our scrolling
menus stack, which is
available for download
(see the bottom of this
document).
MetaCard
supports two different
methods of doing menus.
The first method is
known as a button
contents menu. Use it to
construct simple menus
which use only the
normal set of options -
radio buttons, check
boxes, dividers and
enabled or disabled
items and hierarchical
(or pull right) menus.
The second, the menu
panel, is used for doing
more complex menus that
support any kind of
scripting or control.
Use these to make pop up
palettes, menus with
graphics, images, icons,
or any other complex
type of menu.
Button Contents
Menus
We'll
start off by looking at
button contents menus.
Button contents menus
are buttons, with their
text property set to
contain a list of items
to pop up. Use the
properties palette to
create a button, then
set its style to
pulldown. Then, put the
name of each menu item
on a separate line in
the menu contents field.
Try out that button:
clicking on it will
cause the menu to open.
If you want to
dynamically alter the
contents of the menu
before display, use a
mouseDown handler in the
button to set the
text
property of the button
to whatever you want.
Use this technique to
add, delete, check,
uncheck, enable or
disable
items.
|
To
make an
item...
|
Do
the
following...
|
a
dividing line
|
use
"-" as the name of the
item.
|
disabled
|
place
a "(" at the start of
the item
name.
|
a
hilited
checkbox
|
place
a "!c" at the start of
the item
name.
|
an
unhilited
checkbox
|
use
"!n" at the start of the
item name.
|
a
hilited radio
button
|
place
a "!r" at the start of
the item
name.
|
an
unhilited radio
button
|
place
a "!u" at the start of
the item
name.
|
Example:
Item
1
(Item 2
-
!cFourth item
Fifth item
-
Seventh Item
Eight item
(!rItem nine
|
![](/web/20030803132646im_/http://www.xworlds.com/images/metaclass/menus.gif)
Button contents menus
on Windows and the
MacOS.
|
MetaCard
can use HyperCard
compatible syntax for
menu operations. Here's
a sample script to
disable an item (in this
case, item
5):
|
on mouseDown disable menuItem 5 of me end mouseDown
And a few more
HyperCard compatible
examples:
disable menu "Style"
enable menuItem 3 of menu "Style"
hilite menuItem 1 of menu "Font"
MetaCard's
native way of handling
menus is actually a
little harder to use.
The following script
does the same as the
first example above,
disabling menu item
5:
|
on mouseDown
get the text of me
if char 1 of line 5 of it is not "(" then put "(" before line 5 of it
set the text of me to it
end mouseDown
You
may need to use this
method to control some
MetaCard specific
features, such as
placing checkboxes
before menu
items.
When
an item gets chosen, it
sends a "menuPick"
message to the button.
The menuPick message is
sent with the name of
the item chosen. Here is
an example
script:
|
on menuPick pWhichItemPicked switch pWhichItemPicked case "Item 1" --do something to handle the first item picked break case "Second item" --do something to handle the second item getting picked break ... etc... end switch end menuPick
Tip:
If
you prefer to work with
item numbers instead of
names, use the
menuHistory property. It
contains the number of
the item last chosen,
instead of the name. Use
a switch
statement:
switch the menuHistory of me
|
Button
contents menus can also
be used to do option
style menus, and
comboBox style menus.
Use an option menu to
create a list of items.
Use a comboBox to create
a scrolling list of
items where the user has
the option to type the
name of the item in
instead of choose it
from a list. Use the
menuLines
property to set how many
lines in a comboBox are
visible at one time.
Note that disabling
items, checkboxes,
dividers, etc. are not
supported in this type
of menu.
|
![](/web/20030803132646im_/http://www.xworlds.com/images/metaclass/comboboxes.gif)
ComboBoxes on Windows
and the MacOS. The
menuLines
has been set to 5.
When
an item is chosen, the
label
property of the button
is automatically set to
the name of the item
chosen. In option menus,
when you re-open the
menu, it will be
positioned with the item
most recently chosen
over the mouse. You can
get and set this using
the
menuHistory
property of the
button.
|
![](/web/20030803132646im_/http://www.xworlds.com/images/metaclass/optionmenus.gif)
Option menus on
Windows and the
MacOS.
The
final type of button
contents menu is the
tabbed button. This type
of menu can be used to
display a tabbed
interface, often used
for doing program
Preferences screens. The
tab items are set as
contents in the normal
way. Like option menus
and comboBoxes, using
dividers, disabling
items and other such
features are not
supported.
|
|
When
a tab is chosen, a
menuPick message is sent
to the button. In this
case it is sent with two
parameters, the name of
the tab chosen, and the
name of the tab
previously chosen. The
most common use for this
is to hide and show a
group of
controls.
If
you want to set which
tab is currently active,
you can set the
menuHistory property of
the button to the number
of the tab,
e.g.:
set the menuHistory of btn "tabbed
example" to 2
Note
that setting the
menuHistory causes a
menuPick message to be
sent to the button, just
as if one of the tabs
had been pressed with
the mouse.
|
Menu panel
menus
Menu
Panels are very
different from button
contents menus. They are
actual MetaCard stacks,
as opposed to a property
attached to a single
button. This means you
can open them in
multiple places
throughout an
application without
having to duplicate
anything. It also means
that you have to draw
out the panel yourself,
and you can place any
standard MetaCard
control in it if you
wish.
To
create a menu panel, it
is simplest to clone the
existing menu panel
structure found in
MetaCard.
Type:
clone stack "MC SelectedObject Menu"
to
create an editable copy
of the MetaCard object
selection menu. You'll
find that all the
buttons in the stack
have mouseUp scripts,
instead of menuPick
handlers. You can use
mouseUp messages
attached to each button
in the menu, or use a
single menuPick handler
like in button contents.
In addition, normal
messages are sent to
controls in a panel
stack. This means you
can use the messages
mouseEnter, mouseLeave,
etc. to provide
additional functionality
if you wish.
To
display a menu panel,
create a button on the
stack you want to
display it. Set the
style to either pulldown
or popup, and then set
the menuName property to
the name of the stack
you've created. You can
do all of these
operations using the
button properties
palette. For example,
you could create a
button to pop up the
MetaCard object
selection menu in
anywhere - simply create
a new button, set the
style to pulldown and
the menuName to "MC
SelectedObject
Menu".
If
you need to display a
panel by script, rather
than attached to a
button, you can open the
menu stack using a
command in a mouseDown
handler. For
example:
popup "myStackMenu"
will
open the stack
"myStackMenu" as a popup
menu under the position
of the
cursor.
|
Tip:If
you only want your panel
to open on a button when
a particular mouse
button is used, set the
menuMouseButton
property. For example,
select a pulldown panel
button and
type:
set the menuMouseButton of the selobj to 3
The
button will now only
display the menu if you
use the third mouse
button. Note that the
third mouse button is
actually the second
mouse button on Windows
systems, and the
mouse-Control key
combination on the
Mac.
|
Sub-menus (or "pull
right"
menus)
If
you want to create menus
inside menus, you can
use either contents
menus with tabs
inserted, or create the
first menu as a menu
panel. Note that
sub-menus inside button
contents menus are only
supported in 2.2.1B1 or
above, previous versions
require you to use panel
menus.
For
button contents menus,
place tabs before the
menu items that you want
to be displayed in a
sub-menu. The number of
tabs can be used to
indicate the number of
levels deep an item
is.
For
panel menus, the item
where you want the
second menu to be
displayed should have
its style set to
cascade. You can either
set the button contents
of that button to form a
button-contents
sub-menu, or set the
menuName property to
display a panel inside
the panel. The sub-menu
will be displayed
automatically when the
mouse moves over the
item. Note that you
can't use the cascade
style menu in a normal
stack - you must use it
inside a menu
panel.
Menu
Bars
A
menu bar is made from a
group of buttons. To
create a menu bar,
create buttons
corresponding to each
menu and, using the
Button Properties
dialogue, set the style
of the buttons to
pulldown menu. If you're
using Windows, set the
text and font to the
Windows standard (MS
Sans Serif). If you're
using the MacOS, you
don't need to set the
font - the system font
will be used when
MetaCard places your
buttons into the MacOS
standard menu bar at the
top of the
screen.
Set
the menu contents of
each button to the menu
items you require.
Arrange the buttons as a
menu bar and group them.
Name the group. To
display a menu bar as
the system menu bar on
MacOS, use the Stack
Properties dialog in the
Edit menu to set the
menubar
property of the stack to
the name of the group.
Whenever the stack is
active that group will
be used for the system
menu bar.
|
IMPORTANT:
On MacOS when you set
the
menubar
property of a stack to a
group which exists in
the same stack, the
whole stack is scrolled
so that the menu bar
group and everything
above it disappears from
the window. The height
of the stack is actually
decreased by the height
of the menu bar group
and everything above it.
This is a useful time
saver for cross-platform
projects because the
same menu bar appears
inside the window in
Windows and UNIX, and on
the system menubar in
MacOS. However, if you
want the group to remain
in the stack window
where it is editable on
MacOS systems, set the
editMenus
property of the stack to
true.
|
A
good example of an
existing menu bar you
can take apart and
examine is the MetaCard
standard menu bar. The
entire MetaCard
interface is written in
MetaCard. The menus you
see while using MetaCard
are a MetaCard group.
The menubar of stack
"Home" is set to the
group "MetaCard Menu
Bar". If you want to see
this group type the
following into the
Message Box:
toplevel "MetaCard Menu Bar"-- stack name happens to be group name
Select
the group named
"MetaCard Menu Bar"
inside this stack. These
are the actual menus
MetaCard displays in its
editor. Be cautious as
editing this group will
alter the MetaCard
interface.
Menu
bars on MacOS
systems
The
menu bar includes the
MacOS standard Help menu
with the Apple default
items (usually Show
Balloons, About Balloon
Help). The righter-most
menu button in the
menubar group always
operates as the Help
menu (and is named Help,
regardless of what you
call it). The last item
in the menu contents of
the righter-most button
is used as the About...
menu item in the Apple
menu. To capture a user
selection of that item,
place a
menuPick
message handler in the
group containing the
menu bar.
If
you want to update the
contents of the menu bar
before displaying the
menus, place a mouseDown
message in the group
containing the menus.
Note that the mouseDown
message is only sent to
the group, not the
individual menus. This
is a limitation of the
MacOS. Another
limitation for the 2.2
release of MetaCard is
that you can't use menu
panels in the Mac menu
bar. All Mac menu bar
menus must be standard
button contents menus
(cascade and option
styles are not supported
either). If you want to
do sub-menus, these must
be done using the
sub-menu button contents
properties in the
2.2.1B1 release or
above.
If
any of the subStacks in
your project don't have
a menu bar, but you want
one to be displayed set
the
defaultMenuBar
global property to the
one you want displayed.
That menu bar will then
be displayed for stacks
without a menu
bar.
|
Important
Note:
Make
sure that the buttons in
any menu bar you create
don't overlap. If they
do, it may cause strange
behavior - including
multiple panels being
displayed at once. If
you're having problems
with a menu bar, check
to see that the buttons
aren't
overlapping.
|
Scrolling
Menus
One
limitation of MetaCard
is that you can't do
scrolling menus, except
as the comboBox type.
There are plans to add
scrolling menu support
to the MetaCard engine.
In the mean time, Cross
Worlds has produced a
free utility for
creating menu panel
menus, which includes
full support for
scrolling. Fully
compatible with MetaCard
on any platform, you can
use it to create menus
with greater ease than
producing even button
contents menus. The
panels created can
easily also be edited
easily by script on the
fly - just like button
contents menus. This
stack comes complete
with support for doing
cascade (sub-menu) style
menus inside the
scrolling menu, with
support for scrolling
sub-menus inside
sub-menus. (Of course,
actually doing this in
your program would make
it just about impossible
to navigate :-) Download
it here
as a
Stuffit
archive, or
here
as a
zip
archive.
|
|