[comp.sys.mac.hypercard] Radio buttons

tgl@zog.cs.cmu.edu (Tom Lane) (11/20/88)

There's been some discussion recently about how to deal with radio buttons
with per-card state; i.e., you have the same group of radio buttons on
every card of a background, but the currently selected button differs from
card to card.

In article <185@s1.sys.uea.ac.uk>, jrwg@s1.sys.uea.ac.uk (John Glauert CMP)
writes:
> I am no expert Hypertext programmer so this may be naive, but the
> scripts below do provide radio button groups: I use a hidden field to
> hold the state of the group given by the id of the selected button;
> blank implies no selection. Since button state is global, you need to
> adjust it to the right value when the card is opened.
> 
> Now the problem: I want to print this stack, but my radio buttons are
> not displayed properly because (it seems) opencard is not sent to
> cards before they are printed (hence I get the current button state
> everywhere).  What can I do?
> 
> [Scripts deleted, but basically he has N background buttons of radio
>  style, and a single hidden background field.  In each card, the field
>  holds the ID of the button to highlight, or "" if none are highlighted.
>  An openCard handler is needed to adjust the highlighting of the buttons
>  when moving to a new card.]

I had the same problem in a slightly different context: a mailing list stack
in which I wanted to include a membership status for each card.  Since there
were only a few valid status codes (full member, assoc. member, etc) I wanted
to use radio buttons rather than type directly into the status field.  I
originally tried a solution like John's, but also found that Print Stack
(and "show all cards") didn't show the correct button state on each card.
(Also, moving to a new card was painfully slow, since half-a-dozen button
highlight changes were needed.)

I eventually hit upon a neat solution that solves these problems, at the
cost of slowing up creation of new cards a trifle.  Here are the components
of my solution:

  1. N background buttons of radio style.  These all invoke a common handler
     which is in the background script.  *None of these buttons ever get
     highlighted*.

  2. A hidden background field which contains the current status for each
     card, or initially nothing (no button selected yet).  I put "the
     short name" of the selected button into the field, so that the field
     can be printed in Print Report and it'll produce a meaningful value;
     but you could also use the button ID like John did.

  3. On each card, a *card* button of radio style.  This button is
     highlighted, and the idea is to move it so that it overlays the proper
     background button for the card's status value.  Then the background
     button appears to be highlighted.  In the initial state, the card
     button can be hidden so that none of the radio buttons appear
     highlighted.

The beauty of this solution is that HyperCard shows a card's state
correctly without any need for an openCard handler; hence there is
no problem with Print Stack (etc.) and no speed penalty when moving
to another card.  The cost is that you have to create the card button
at newCard time; on a Mac Plus, this adds a second or two to the time
needed to make a new card.

Here are the handlers needed; both go into the background script:

on newCard
  set lockScreen to true  -- so user doesn't see new button appear/disappear
  doMenu "New Button"	-- create the card button; it will be card button 1
  choose browse tool	-- undo "New Button"'s selection of button tool
  set the visible of card button 1 to false   -- until we need it visible
  set the showName of card button 1 to false  -- set the properties we want
  set the style of card button 1 to radioButton
  set the hilite of card button 1 to true     -- will be hilited when visible
  set the name of card button 1 to "radio1"
  set lockScreen to false
  tabKey		-- this is explained later
end newCard

-- note: the background radio buttons all have showName true, and their
-- names remain visible even when the card button overlays them.

on radioGroup1		-- common handler for all bkgnd buttons in radio group
  set the rect of card button "radio1" to the rect of the target
  -- now card button exactly overlays target bkgnd button
  set the visible of card button "radio1" to true  -- in case it wasn't
  put the short name of the target into field "Status"
  -- the status field is only needed for Print Report, or if other handlers
  -- need to know what the radio-group status is...
end radioGroup1

Each background radio button's script is

on mouseUp
  radioGroup1
end mouseUp

Note that clicking on an already-highlighted radio button does nothing,
because the click is sent to the *card* button, which has an empty script.
This is OK for the normal semantics of radio buttons.  If you wanted
something to happen, you could set the card button's script to do it.

This method can easily be extended to handle several independent groups of
radio buttons; you will need one card button for each group.  Also, you can
easily arrange for a default button to be selected when a new card is
created, if you want things to work that way.

In my application, when you make a new card you almost always want to
start typing into its first field; hence the "tabKey" message in the
newCard handler.  Although it takes a couple of seconds for the cursor
to appear (because "New Button" is so slow), you can start typing right
away; the keystrokes won't be lost.  Hence the delay to create the button
is not a serious problem.  (It's still annoying, though; I wish Apple
would do something about it.  Why should it take longer to make a button
than a card?)

Another approach would be to create the card button when first clicking
on one of the radio buttons; this would speed up card creation but slow
down first response to a radio button.  That didn't seem like a win in
my case, but it might be in your application.

One caveat: get the background button positions right before you start
using the stack.  If you adjust their positions later, you have to
go thru the stack and update all the card button positions, or things
look very peculiar...

-- 
				tom lane
Internet: tgl@zog.cs.cmu.edu
UUCP: <your favorite internet/arpanet gateway>!zog.cs.cmu.edu!tgl
BITNET: tgl%zog.cs.cmu.edu@cmuccvma
--