/*
 * pin_menu.c -
 *	Demonstrate how to generate your own pinup menu.
 *	Use of MENU_GEN_PIN_WINDOW is for static menus only.
 *	This demo uses menus whose items may change, so we
 *	need to reflect those changes in our own command frame.
 */
#include <xview/xview.h>
#include <xview/canvas.h>
#include <xview/panel.h>

Frame	frame;

/*
 * main -
 *	Create a frame, canvas and menu.
 *	A canvas receives input in its canvas_paint_window().
 *	Specify creation of an Open Look Menu and transformation of
 *	the menu to a pinned command window.
 *	Each menu item specifies an action proc to be called when the
 *	item is chosen, regardless of whether or not menu is pinned.
 */
main(argc,argv)
int	argc;
char	*argv[];
{
    Canvas	canvas;
    Menu	menu;
    int		my_notify_proc();
    void	my_event_proc(), my_menu_done();
    extern void	exit();

    xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);

    frame = (Frame)xv_create(NULL, FRAME,
	FRAME_LABEL,	argv[0],
	NULL);
    canvas = (Canvas)xv_create(frame, CANVAS,
	XV_WIDTH,	300,
	XV_HEIGHT,	200,
	NULL);
    menu = (Menu)xv_create(NULL, MENU,
	MENU_GEN_PIN_WINDOW,	frame, "Junk",
	MENU_DONE_PROC,		my_menu_done,
	/*
	MENU_STRINGS,		"Yes", "No", "Maybe", NULL,
	MENU_NOTIFY_PROC,	my_notify_proc,
	*/
	MENU_ITEM, MENU_STRING,	"No", MENU_NOTIFY_PROC, my_notify_proc, NULL,
	MENU_ITEM, MENU_STRING,	"Yes", MENU_NOTIFY_PROC, my_notify_proc, NULL,
	MENU_ITEM, MENU_STRING,	"Maybe", MENU_NOTIFY_PROC, my_notify_proc, NULL,
	MENU_ITEM,
	    MENU_STRING,	"Save",
	    MENU_NOTIFY_PROC,	my_notify_proc,
	    MENU_PULLRIGHT,
		xv_create(canvas, MENU,
		    MENU_ITEM,
			MENU_STRING,		"Update Changes",
			MENU_NOTIFY_PROC,	my_notify_proc,
			NULL,
		    NULL),
	    NULL,
	MENU_ITEM,
	    MENU_STRING,	"Quit",
	    MENU_NOTIFY_PROC,	exit,
	    NULL,
	NULL);

    xv_set(canvas_paint_window(canvas),
	WIN_CONSUME_EVENTS,	WIN_MOUSE_BUTTONS, NULL,
	WIN_EVENT_PROC,		my_event_proc,
	/* associate the menu to the canvas win so we can retreive it easily */
	WIN_CLIENT_DATA,	menu,
	NULL);

    window_fit(frame);
    window_main_loop(frame);
}

/*
 * my_menu_done - menu has been popped-down.  Make sure the command frame panel
 * matches the menu.
 */
void
my_menu_done(menu, result)
Menu menu;
Xv_opaque result;
{
    int default_item, i;
    Frame pin_frame;
    Panel panel;
    Panel_item pi;

    printf("result = %x\n", result);
    if (!(pin_frame = (Frame)xv_get(menu, MENU_PIN_WINDOW))) {
	puts("menu has no pin frame");
	return;
    }
    panel = (Panel)xv_get(pin_frame, FRAME_CMD_PANEL);
    /* get the ordinal number of the default menu item */
    default_item = (int)xv_get(menu, MENU_DEFAULT);

    /* search for the <default>-th item in the panel and... */
    pi = (Panel_item)xv_get(panel, PANEL_FIRST_ITEM);
    for (i = 1 /*menu items offset at 1*/; i < default_item && pi; i++)
	pi = (Panel_item)xv_get(pi, PANEL_NEXT_ITEM);

    /* set that panel item to be the default item */
    xv_set(panel, PANEL_DEFAULT_ITEM, pi, NULL);
}

/*
 * my_notify_proc - Display menu selection in frame header.
 */
/*ARGSUSED*/
int
my_notify_proc(menu, menu_item)
Menu menu;
Menu_item menu_item;
{
    xv_set(frame,
	FRAME_LABEL,	xv_get(menu_item, MENU_STRING),
	NULL);
    return (XV_OK);
}

/*
 * my_event_proc - Call menu_show() to display menu on right mouse button push.
 */
void
my_event_proc(window, event)
Xv_Window window;
Event *event;
{
    if (event_action(event) == ACTION_MENU && event_is_down(event)) {
	Menu menu = (Menu)xv_get(window, WIN_CLIENT_DATA);
	if (!xv_get(menu, MENU_PIN_WINDOW))
	    create_pin_win(menu);
	menu_show(menu, window, event, NULL);
    }
}

#define MENU_KEY	100
#define MENU_ITEM_KEY	101
#define ACTION_KEY	102

#define nullstr "(null)"

create_pin_win(menu)
Menu menu;
{
    int i;
    void pin_btn_notify();
    Frame cmd_frame = (Frame)xv_create(frame, FRAME_CMD, XV_SHOW, FALSE, NULL);
    Panel panel = (Panel)xv_get(cmd_frame, FRAME_CMD_PANEL);
    Menu_item mi;
    char *ms;

    xv_set(panel, PANEL_LAYOUT, PANEL_VERTICAL, 0);
    printf("frame = %x, panel = %x\n", cmd_frame, panel);
    for (i = (int)xv_get(menu, MENU_NITEMS); i > 0; i--) {
	mi = (Menu_item)xv_get(menu, MENU_NTH_ITEM, i);
        if ((ms = (char *)xv_get(mi, MENU_STRING)) == 0)
            ms = nullstr;
        printf("adding panel item: %s\n", ms );
	xv_create(panel, PANEL_BUTTON,
	    /* PANEL_MENU_ITEM,		TRUE, */
	    PANEL_LABEL_STRING,		xv_get(mi, MENU_STRING),
	    PANEL_NOTIFY_PROC,		pin_btn_notify,
	    XV_KEY_DATA, MENU_KEY,	menu,
	    XV_KEY_DATA, MENU_ITEM_KEY,	mi,
	    XV_KEY_DATA, ACTION_KEY,	xv_get(mi, MENU_NOTIFY_PROC),
	    NULL);
    }
    window_fit(panel);
    window_fit(cmd_frame);
    xv_set(menu, MENU_PIN_WINDOW, cmd_frame, NULL);
}

/*ARGSUSED*/
void
pin_btn_notify(item, event)
Panel_item item;
Event *event;
{
    Menu	menu = (Menu)xv_get(item, XV_KEY_DATA, MENU_KEY);
    Menu_item	mi = (Menu)xv_get(item, XV_KEY_DATA, MENU_ITEM_KEY);
    void	(*action)() = (void (*)())xv_get(item, XV_KEY_DATA, ACTION_KEY);

    (*action)(menu, mi);
}
