1  Introduction

Toggling Menu Items

Richard Bunter Okay, you've just read Mike Hedblom's article on  menus
and you're excited.  Look at all that stuff you can do.  Your  dBASE
programs will look much more finished now.  But, there's just  one
thing.  It's such a little thing too. 


2  Article

Wouldn't it be nice if you could toggle something on or off just by 
selecting it on a popup menu?  Okay, so that's easy.  But what about 
having the menu reflect the current status of that item?  For
example,  the menu item would read "Turn the clock ON" if it's off. 
After it's  been selected, it would read "Turn the clock OFF."  That
is, the menu  item should tell you what action selecting it would
accomplish. Pretty  snazzy, huh?  If we want to do this, we need to
delve into a few menu  basics.

Menu Basics

In order to create a popup menu, you have to define the menu name, 
define each menu bar prompt, define what happens when the menu is 
selected and activate the menu--in that order.  All of that is  easy
enough, but there's one kicker: the menu prompts cannot change  once
the menu is activated.  So, in order to change the prompt, you  have
to deactivate the menu, redefine the prompt, and then activate  the
menu again.  Also, realize that you can define the prompt with  a
variable.

With those two thoughts in mind, take a look at the sample
application  following this article.  The flow of the program goes
like this:

Initialize the variables

We store nulls to what will become the menu prompts because we need 
those variables to be there, but we don't need to put anything
particular  into them since we're going to change them anyway.

Define the menu and its prompts

We use our variables when defining the menu prompts.  Define those 
items that don't need to change in the normal way.

Control loop

Within a DO WHILE loop, we'll assign values to those items we want 
reflected on the menu.  Then we'll redefine the menu prompts using 
the variables.  Next we activate the menu.

ACTIVATE and DEACTIVATE are like DO WHILE and ENDDO.  That is, they 
go together.  When the DEACTIVATE command is invoked, the program 
goes to the line immediately following the appropriate ACTIVATE
command.  This  means that we can't deactivate the menu until we know
what was selected  and take some appropriate action.  In the sample
application, choosing  a menu item will cause the program to branch to
a procedure called  Pop1.  Here we assign the value of the choice to a
variable, then  deactivate the menu preparatory to redefining and
activating it again.

Back in the main routine we now evaluate the choice and take
appropriate  action.

About NGAM

NGAM, our sample application, has three changeable choices on the 
menu.  Each of these has something unique to demonstrate:  changeable 
menu messages, constant messages, and using SET() when assigning
values.  Also,  the structure of the program can be different in that
we could take  action (DO CASE) in the Pop1 procedure instead of the
main program.  It  should also be apparent that you can change the
status of the logical  system variables using this technique.  For
example,

bar1_prompt = "Turn word wrap " + IIF(_wrap,"OFF","ON ")

and

_wrap = IIF(_wrap,.F.,.T.)

can be used to toggle the _wrap variable.

Because we are turning the menus off, redefining them and turning 
them on, this is not going to be real fast.  But it does work rather 
nicely and adds a nice touch to the programs that can use this
technique.





3  Sample Program: NGAM.PRG

NGAM.PRG
* Nuclear Generator Activation Menu
CLEAR ALL
CLEAR
SET TALK OFF

bar = 0
STORE .F. TO t1,t2
STORE "" TO bar1_prompt,bar1_msg,bar2_prompt,bar3_prompt

DEFINE POPUP Test FROM 1,13
DEFINE BAR 1 OF Test PROMPT bar1_prompt MESSAGE bar1_msg
DEFINE BAR 2 OF Test PROMPT bar2_prompt 
DEFINE BAR 3 OF Test PROMPT bar3_prompt
DEFINE BAR 4 OF Test PROMPT REPL(CHR(196),27) SKIP
DEFINE BAR 5 OF Test PROMPT "Quit" ;
  MESSAGE "Blow this taco stand"
ON SELECTION POPUP Test DO Pop1

DO WHILE .T.
   bar1_prompt = "Turn Nuclear Generator " + IIF(t1,"OFF","ON ")
   bar1_msg = "The Generator is currently " + IIF(t1,"ON","OFF")
   bar2_prompt = IIF(t2,"EN","DIS") + "ABLE Auto Destruct "
   bar3_prompt = "Turn the clock " + IIF(SET("CLOCK")="ON","OFF","ON
")
   DEFI BAR 1 OF Test PROMPT bar1_prompt MESSAGE bar1_msg
   DEFI BAR 2 OF Test PROMPT bar2_prompt ;
     MESSAGE "Change the Auto Destruct status"
   DEFI BAR 3 OF Test PROMPT bar3_prompt ; 
     MESSAGE "Turn the clock on or off"
   
   ACTIVATE POPUP Test
   IF bar = 5 .OR. LASTKEY() = 27
      EXIT
   ENDIF
   DO CASE
      CASE bar = 1
         t1 = IIF(t1,.F.,.T.)      
      CASE bar = 2
         t2 = IIF(t2,.F.,.T.)
      CASE bar = 3
         IF SET("CLOCK") = "ON"
            SET CLOCK OFF
         ELSE
            SET CLOCK ON
         ENDIF      
   ENDCASE   
ENDDO
RETURN
* EOP: NGAM

PROCEDURE Pop1
   *--- Get choices from Test POPUP menu -----------------------------
   bar = BAR()
   DEACTIVATE POPUP
RETURN
* EOP: Pop1
                                                        