/* $Id: xmMenu.c,v 1.1 1992/11/07 07:59:13 mjl Exp $
 * $Log: xmMenu.c,v $
 * Revision 1.1  1992/11/07  07:59:13  mjl
 * Files for the Plplot Motif device driver.  The menus are still just barely
 * sketched out, and this doesn't currently offer any additional functionality
 * over the Xlib driver (but soon, soon..).
 *
*/

/*	xmMenu.c

	Menu support routines for PLPLOT OSF/Motif driver.
*/

#include "xm.h"
#include "xmMenu.h"

int    currentView;     /*  This holds the current state of the View menu. */

int    currentOption;   /*  This holds the current option (from the second
			    group of toggles in the Options menu).  */

Widget opt1Toggle, opt2Toggle, opt3Toggle;  /* These are the radio buttons 
					       from the Options menu. */

/*----------------------------------------------------------------------*\
* MenuCB()
*
* Callback routine used for processing menu commands.
\*----------------------------------------------------------------------*/

void MenuCB (
     Widget	w,		/*  widget id		*/
     XtPointer	client_data,	/*  data from application   */
     XtPointer	call_data	/*  data from widget class  */
)
{
  Widget         button;

  int      i;

  /* Some menu commands may not return immediately, so update 
     the display to prevent the application from looking dead. */
  XmUpdateDisplay(topLevel);

  switch ((int)client_data)
    {
    case MENU_File_Open:
      printf("File: Open!\n");
      break;
    case MENU_File_New:
      printf("File: New!\n");
      break;
    case MENU_File_Print:
      printf("File: Print!\n");
      break;
    case MENU_File_Save:
      printf("File: Save!\n");
      break;
    case MENU_File_SaveAs:
      printf("File: Save As!\n");
      break;
    case MENU_File_Exit:
      XtManageChild (exitDialog);
      break;
	    
    case MENU_Edit_Undo:
      printf("Edit: Undo!\n");
      break;
    case MENU_Edit_Cut:
      printf("Edit: Cut!\n");
      break;
    case MENU_Edit_Copy:
      printf("Edit: Copy!\n");
      break;
    case MENU_Edit_Paste:
      printf("Edit: Paste!\n");
      break;
    case MENU_Edit_Clear:
      printf("Edit: Clear!\n");
      break;
    case MENU_Edit_Delete:
      printf("Edit: Delete!\n");
      break;

    case MENU_View_AsOne:
    case MENU_View_AsTwo:
    case MENU_View_AsThree:
      /* This MenuCB() routine is called twice each time a choice is
	 made from the View menu: First for the toggle being unset, then
	 for the toggle being set.  Therefore, a response is needed only
	 if the toggle is set and it isn't already the current view.  */

      if (XmToggleButtonGadgetGetState(w) && (int)client_data != currentView)
	{
	  switch ((int)client_data)
	    {
	    case MENU_View_AsOne:
	      printf("View: As One!\n");
	      break;
	    case MENU_View_AsTwo:
	      printf("View: As Two!\n");
	      break;
	    case MENU_View_AsThree:
	      printf("View: As Three!\n");
	      break;
	    }
	  currentView = (int)client_data;
	}
      break;

    case MENU_Options_OptA:
    case MENU_Options_OptB:
    case MENU_Options_OptC:
      printf("Options: Option ");
      switch ((int)client_data)
	{
	case MENU_Options_OptA:
	  printf("A");
	  break;
	case MENU_Options_OptB:
	  printf("B");
	  break;
	case MENU_Options_OptC:
	  printf("C");
	  break;
	}
      if (XmToggleButtonGadgetGetState(w))
	printf(" on");
      else
	printf(" off");
      printf("!\n");
      break;

    case MENU_Options_Opt1:
    case MENU_Options_Opt2:
    case MENU_Options_Opt3:
      /* Enforce radio behavior by clearing all three toggles,
	 then setting the toggle just chosen (w). */
      XmToggleButtonGadgetSetState (opt1Toggle, False, False);
      XmToggleButtonGadgetSetState (opt2Toggle, False, False);
      XmToggleButtonGadgetSetState (opt3Toggle, False, False);
      XmToggleButtonGadgetSetState (w,          True,  False);

      /* Behavior for the current choice goes here.  If the option
	 was already selected, nothing happens. */

      if (currentOption != (int)client_data)
	{
	  currentOption = (int)client_data;

	  switch (currentOption)
	    {
	    case MENU_Options_Opt1:
	      printf("Options: Switched to Option 1!\n");
	      break;
	    case MENU_Options_Opt2:
	      printf("Options: Switched to Option 2!\n");
	      break;
	    case MENU_Options_Opt3:
	      printf("Options: Switched to Option 3!\n");
	      break;
	    }
	}
      break;
      
    case MENU_Help_OnItem:
      printf("Help: On Item!\n");
      break;
    case MENU_Help_OnApplication:
      printf("Help: On Application!\n");
      break;
    case MENU_Help_OnHelp:
      printf("Help: On Help!\n");
      break;
    case MENU_Help_Index:
      printf("Help: Index!\n");
      break;
    case MENU_Help_Tutorial:
      printf("Help: Tutorial!\n");
      break;
    case MENU_Help_OnVersion:
      printf("Help: On Version!\n");
      break;
      
    default:
      /* A client_data was received for which 
	 there is no case setup to handle */
      printf ("Unknown client_data in MenuCB(): %d\n",client_data);
      break;
    }
  
}

/*----------------------------------------------------------------------*\
* 
* CreateMenuBar()  -- a convenience function for creating
*                     the application's menu bar.
* 
* CreateMenuButton() -- a convenience function for adding
*                       individual buttons to panes within
*                       the menu bar.
* 
* AddSeparator() -- a convenience function for adding 
*                   separators to panes within the menu bar.
* 
\*----------------------------------------------------------------------*/

Widget CreateMenuBar (Widget parent)
{
  Widget  menuBar;
  Widget  cascade;
  Widget  pulldownPane;
  Widget  button;

  XmString  label;

  /* Create menu bar. */
  ac = 0;
  menuBar = XmCreateMenuBar (parent, "menuBar", al, ac);

  /************************************************************
                            F i l e
 ************************************************************/

  ac = 0;
  pulldownPane = XmCreatePulldownMenu (menuBar, "pulldownPane", al, ac);

  /*** New ... ***/ CreateMenuButton (pulldownPane, NULL, MENU_File_New,
				      "New ...", 'N', PushButton,
				      NULL, NULL);

  /*** Open ... ***/ CreateMenuButton (pulldownPane, NULL, MENU_File_Open,
				       "Open ...", 'O', PushButton,
				       NULL, NULL);

  /* ----------------- */  AddSeparator(pulldownPane);

  /*** Save ***/ CreateMenuButton (pulldownPane, NULL, MENU_File_Save,
				   "Save", 'S', PushButton,
				   NULL, NULL);

  /*** Save As ... ***/ CreateMenuButton (pulldownPane, NULL, MENU_File_SaveAs,
					  "Save As ...", 'A', PushButton,
					  NULL, NULL);

  /* ----------------- */  AddSeparator(pulldownPane);

  /*** Print ... ***/ CreateMenuButton (pulldownPane, NULL, MENU_File_Print,
					"Print ...", 'P', PushButton,
					NULL, NULL);

  /* ----------------- */  AddSeparator(pulldownPane);

  /*** Exit ***/ CreateMenuButton (pulldownPane, NULL, MENU_File_Exit,
				   "Exit", 'E', PushButton,
				   "Meta<Key>F4:","Meta+F4");

  /*** File cascade button ****/
  label = XmStringCreateSimple ("File");
  ac = 0;
  XtSetArg (al[ac], XmNsubMenuId, pulldownPane);  ac++;
  XtSetArg (al[ac], XmNlabelString, label);  ac++;
  XtSetArg (al[ac], XmNmnemonic, 'F'); ac++;
  cascade= XmCreateCascadeButtonGadget (menuBar, NULL, al, ac);
  XtManageChild (cascade);
  XmStringFree(label);  

  /************************************************************
	                    E d i t
 ************************************************************/

  ac = 0;
  pulldownPane = XmCreatePulldownMenu (menuBar, "pulldownPane", al, ac);

  /*** Undo ***/ CreateMenuButton (pulldownPane, NULL, MENU_Edit_Undo,
				   "Undo", 'U', PushButton,
				   "Meta<Key>BackSpace:","Alt+Backspace");

  /* ----------------- */  AddSeparator(pulldownPane);

  /*** Cut ***/ CreateMenuButton (pulldownPane, NULL, MENU_Edit_Cut,
				  "Cut", 't', PushButton,
				  "Shift<Key>DeleteChar:", "Shift+Del");

  /*** Copy ***/ CreateMenuButton (pulldownPane, NULL, MENU_Edit_Copy,
				   "Copy", 'C', PushButton,
				   "Ctrl<Key>InsertChar:", "Ctrl+Ins");

  /*** Paste ***/ CreateMenuButton (pulldownPane, NULL, MENU_Edit_Paste,
				    "Paste", 'P', PushButton,
				    "Shift<Key>InsertChar:", "Shift+Ins");

  /* ----------------- */  AddSeparator(pulldownPane);

  /*** Clear ***/ CreateMenuButton (pulldownPane, NULL, MENU_Edit_Clear,
				    "Clear", 'e', PushButton,
				    NULL, NULL);

  /*** Delete ***/ CreateMenuButton (pulldownPane, NULL, MENU_Edit_Delete,
				     "Delete", 'D', PushButton,
				     NULL, NULL);

  /*** Edit cascade button ****/
  label = XmStringCreateSimple ("Edit");
  ac = 0;
  XtSetArg (al[ac], XmNsubMenuId, pulldownPane);  ac++;
  XtSetArg (al[ac], XmNlabelString, label);  ac++;
  XtSetArg (al[ac], XmNmnemonic, 'E'); ac++;
  cascade = XmCreateCascadeButtonGadget (menuBar, NULL, al, ac);
  XtManageChild (cascade);
  XmStringFree(label);

  /************************************************************
           	              V i e w
 ************************************************************/

  /* This menu pane demonstrates how setting the XmNradioBehavior resources
     enables the menu pane (a row column manager) to enforce a one-of-many
     selection among its toggle button children.  

     This technique has a side effect worth noting: The MenuCB() routine
     is called twice each time the user chooses a toggle button from the
     menu pane.	 The first call occurs when the row column manager unsets
     the current selection.  The second call occurs when the row column
     manager sets the new selection.  Refer to the MenuCB() routine to
     see how behavior for the View menu is handled.	 */

  ac = 0;
  XtSetArg (al[ac], XmNradioBehavior, True);  ac++;
  pulldownPane = XmCreatePulldownMenu (menuBar, "pulldownPane", al, ac);

  /*** As One ***/ CreateMenuButton (pulldownPane, NULL, MENU_View_AsOne,
				     "As One", 'O', RadioButtonOn,
				     NULL, NULL); 
  currentView = MENU_View_AsOne;

  /*** As Two ***/ CreateMenuButton (pulldownPane, NULL, MENU_View_AsTwo,
				     "As Two", 'w', RadioButton,
				     NULL, NULL);

  /*** As Three ***/ CreateMenuButton (pulldownPane, NULL, MENU_View_AsThree,
				       "As Three", 'h', RadioButton,
				       NULL, NULL);

  /*** View cascade button ****/
  label = XmStringCreateSimple ("View");
  ac = 0;
  XtSetArg (al[ac], XmNsubMenuId, pulldownPane);  ac++;
  XtSetArg (al[ac], XmNlabelString, label); ac++;
  XtSetArg (al[ac], XmNmnemonic, 'V'); ac++;
  cascade = XmCreateCascadeButtonGadget (menuBar, NULL, al, ac);
  XtManageChild (cascade);
  XmStringFree(label);

  /************************************************************
         	          O p t i o n s
 ************************************************************/

  /* This menu pane contains two groups of toggle buttons: One group of
     check boxes, and one group of radio buttons.  Since the pane (row
     column manager) has no way of distinguishing separate groups, radio
     behavior cannot be enforced using the same technique used in the View
     menu.  

     In this case, the radio behavior for the second group of toggle
     buttons is implemented within the MenuCB() routine.  The widget IDs
     for the three radio buttons are saved in variables (eg. opt1Toggle)
     for access within MenuCB(). */

  ac = 0;
  pulldownPane = XmCreatePulldownMenu (menuBar, "pulldownPane", al, ac);


  /*** Option A ***/ CreateMenuButton (pulldownPane, NULL, MENU_Options_OptA,
				       "Option A", 'A', CheckBoxOn,
				       NULL, NULL);

  /*** Option B ***/ CreateMenuButton (pulldownPane, NULL, MENU_Options_OptB,
				       "Option B", 'B', CheckBox,
				       NULL, NULL);

  /*** Option C ***/ CreateMenuButton (pulldownPane, NULL, MENU_Options_OptC,
				       "Option C", 'C', CheckBox,
				       NULL, NULL);

  /* ----------------- */  AddSeparator(pulldownPane);
  
                     opt1Toggle = 
  /*** Option 1 ***/ CreateMenuButton (pulldownPane, NULL, MENU_Options_Opt1,
				       "Option 1", '1', RadioButtonOn,
				       NULL, NULL);
  currentOption = MENU_Options_Opt1;

                     opt2Toggle = 
  /*** Option 2 ***/ CreateMenuButton (pulldownPane, NULL, MENU_Options_Opt2,
				       "Option 2", '2', RadioButton,
				       NULL, NULL);

                     opt3Toggle = 
  /*** Option 3 ***/ CreateMenuButton (pulldownPane, NULL, MENU_Options_Opt3,
				       "Option 3", '3', RadioButton,
				       NULL, NULL);


  /*** Options cascade button ****/
  label = XmStringCreateSimple ("Options");
  ac = 0;
  XtSetArg (al[ac], XmNsubMenuId, pulldownPane);  ac++;
  XtSetArg (al[ac], XmNlabelString, label); ac++;
  XtSetArg (al[ac], XmNmnemonic, 'O'); ac++;
  cascade = XmCreateCascadeButtonGadget (menuBar, NULL, al, ac);
  XtManageChild (cascade);
  XmStringFree(label);


  /************************************************************
	                   H e l p     
 ************************************************************/

  ac = 0;
  pulldownPane = XmCreatePulldownMenu (menuBar, "pulldownPane", al, ac);

  /*** On Item ... ***/ CreateMenuButton (pulldownPane, NULL, MENU_Help_OnItem,
					  "On Item ...", 'I', PushButton,
					  NULL, NULL);

  /*** On Application ... ***/ CreateMenuButton (pulldownPane, NULL,
						 MENU_Help_OnApplication,
						 "On Application ...", 'A',
						 PushButton, "<Key>F1", "F1");

  /*** On Help ... ***/ CreateMenuButton (pulldownPane, NULL, MENU_Help_OnHelp,
					  "On Help ...", 'H', PushButton,
					  NULL, NULL);

  /* ----------------- */  AddSeparator(pulldownPane);

  /*** Index ... ***/ CreateMenuButton (pulldownPane, NULL, 
					MENU_Help_Index,
					"Index ...", 'x', PushButton,
					NULL, NULL);

  /*** Tutorial ... ***/ CreateMenuButton (pulldownPane, NULL, 
					   MENU_Help_Tutorial,
					   "Tutorial ...", 'T', PushButton,
					   NULL, NULL);

  /* ----------------- */  AddSeparator(pulldownPane);

  /*** On Version ... ***/ CreateMenuButton (pulldownPane, NULL, 
					     MENU_Help_OnVersion, 
					     "On Version ...", 'V', PushButton,
					     NULL, NULL);

  /*** Help cascade button ****/
  label = XmStringCreateSimple ("Help");
  ac = 0;
  XtSetArg (al[ac], XmNsubMenuId, pulldownPane);  ac++;
  XtSetArg (al[ac], XmNlabelString, label);  ac++;
  XtSetArg (al[ac], XmNmnemonic, 'H'); ac++;
  cascade = XmCreateCascadeButtonGadget (menuBar, NULL, al, ac);
  XtManageChild (cascade);
  XmStringFree(label);

  /*** Make Help button right-justified in menu bar ***/
  ac = 0;
  XtSetArg (al[ac], XmNmenuHelpWidget, cascade); ac++;
  XtSetValues(menuBar, al, ac);
  
  return(menuBar);

} /* End of the CreateMenuBar() function. */



/******************************************************************************
              C r e a t e   M e n u   B u t t o n   U t i l i t y
******************************************************************************/

Widget CreateMenuButton(
     Widget  parent,
     char    *name,
     int     buttonID,                    /* Values defined in Menu.h */
     char    *buttonLabelStr,
     char    buttonMnemonic,
     int     buttonType,                  /* Values defined in Menu.h */
     char    *buttonAccelerator,
     char    *buttonAcceleratorTextStr
)
{
  Widget    button;
  XmString  buttonLabel;
  XmString  buttonAcceleratorText;

  if (strlen(buttonLabelStr) > 0)
    buttonLabel = XmStringCreateSimple (buttonLabelStr);
  else
    buttonLabel = NULL;

  if (strlen(buttonAcceleratorTextStr) > 0)
    buttonAcceleratorText = XmStringCreateSimple (buttonAcceleratorTextStr);
  else
    buttonAcceleratorText = NULL;

  ac = 0;
  XtSetArg (al[ac], XmNlabelString, buttonLabel); ac++;
  XtSetArg (al[ac], XmNmnemonic, buttonMnemonic); ac++;
  XtSetArg (al[ac], XmNaccelerator, buttonAccelerator); ac++;
  XtSetArg (al[ac], XmNacceleratorText, buttonAcceleratorText); ac++;

  if (buttonType == CascadeButton)
    {
      button = XmCreateCascadeButtonGadget (parent, NULL, al, ac);
    }
  else if (buttonType == CheckBox    || buttonType == CheckBoxOn ||
	   buttonType == RadioButton || buttonType == RadioButtonOn)
    {
      /* Radio buttons should have one-of-many (diamond shaped) indicator. */
      if (buttonType == RadioButton || buttonType == RadioButtonOn)
	{
	  XtSetArg (al[ac], XmNindicatorType, XmONE_OF_MANY); ac++;
	}

      /* If the toggle button is "on," set the "set" resource. */
      if (buttonType == CheckBoxOn || buttonType == RadioButtonOn)
	{
	  XtSetArg (al[ac], XmNset, True); ac++;
	}

      button = XmCreateToggleButtonGadget (parent, NULL, al, ac);
      XtAddCallback(button, XmNvalueChangedCallback, MenuCB,
		    (XtPointer)buttonID);
    }
  else /* Create a push button by default. */
    {
      button = XmCreatePushButtonGadget (parent, NULL, al, ac);
      XtAddCallback(button, XmNactivateCallback, MenuCB,
		    (XtPointer)buttonID);
    }
  XtManageChild (button);

  XmStringFree(buttonLabel);
  XmStringFree(buttonAcceleratorText);

  return (button);

}



/******************************************************************************
                   A d d   S e p a r a t o r   U t i l i t y
******************************************************************************/

static AddSeparator(Widget parent)
{
  Widget separator;
  Arg    al[10];
  int    ac;
  
  ac = 0;
  separator = XmCreateSeparatorGadget (parent, NULL, al, ac);
  XtManageChild (separator);
}

/****************************************************************** 
   C r e a t e   W i n d o w   M a n a g e r   P r o t o c o l s
 ****************************************************************** 
   This function establishes a protocol callback that detects 
   the window manager's Close command. 
 ******************************************************************/

void CreateWindowManagerProtocols(Widget shell)
{
  Atom  XaWmDeleteWindow;

  XaWmDeleteWindow=XInternAtom(XtDisplay(topLevel),"WM_DELETE_WINDOW", False);
  XmAddWMProtocolCallback (shell, XaWmDeleteWindow, MenuCB,
			   (caddr_t)MENU_File_Exit);
}


/****************************************************************** 
  C r e a t e   S e s s i o n   M a n a g e r   P r o t o c o l s
 ****************************************************************** 
   This function establishes a protocol callback to detect a "save 
   yourself" message from an ICCCM-compliant session manager.
 ******************************************************************/

void CreateSessionManagerProtocols(Widget shell)
{
  Atom  XaWmSaveYourself;

  XaWmSaveYourself=XInternAtom(XtDisplay(shell),"WM_SAVE_YOURSELF", False);
  XmAddWMProtocolCallback (shell, XaWmSaveYourself, SaveSessionCB, NULL);
}


/*****************************************************************
              S a v e   S e s s i o n   C a l l b a c k
 *****************************************************************
   This callback function is executed whenever this application 
   receives a "save yourself" message from an ICCCM-compliant
   session manager.
 *****************************************************************/

void SaveSessionCB(Widget w, XtPointer client_data, XtPointer call_data)
{

   printf("This is when the application should save\n");
   printf("its current state in a session file!\n");

   /* Ideally, a session file should save enough application-specific
      information to restart the application and return it to the
      current state, as though the user was never interrupted.  */

   /* This routine should also update the top-level window's 
      WM_COMMAND property.  This signals the session manager
      that the application is done saving itself.  (Refer to the 
      man page for XSetCommand().)  */

   /* For more information about session management, refer to the 
      "Inter-Client Conventions Manual" (ICCCM) and to the "HP VUE 
      Programmer's Guide."  */

}

