#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "menu.h"
#include "button.h"
#include "toolkit.h"
#include "stock.h"
#include "container.h"
#include "../common/context.h"
#include "../ui/window.h"
UcxList *menus;
UcxList *current;
void ui_menu(
char *label) {
ucx_list_free(current);
UiMenu *menu = malloc(
sizeof(UiMenu));
menu->item.add_to = (ui_menu_add_f)add_menu_widget;
menu->label = label;
menu->items =
NULL;
menu->parent =
NULL;
current = ucx_list_prepend(
NULL, menu);
menus = ucx_list_append(menus, menu);
}
void ui_submenu(
char *label) {
UiMenu *menu = malloc(
sizeof(UiMenu));
menu->item.add_to = (ui_menu_add_f)add_menu_widget;
menu->label = label;
menu->items =
NULL;
menu->parent =
NULL;
UiMenu *cm = current->data;
cm->items = ucx_list_append(cm->items, menu);
current = ucx_list_prepend(current, menu);
}
void ui_submenu_end() {
if(ucx_list_size(current) <
2) {
return;
}
current = ucx_list_remove(current, current);
}
void ui_menuitem(
char *label, ui_callback f,
void *userdata) {
ui_menuitem_gr(label, f, userdata, -
1);
}
void ui_menuitem_st(
char *stockid, ui_callback f,
void *userdata) {
ui_menuitem_stgr(stockid, f, userdata, -
1);
}
void ui_menuitem_gr(
char *label, ui_callback f,
void *userdata, ...) {
if(!current) {
return;
}
UiMenuItem *item = malloc(
sizeof(UiMenuItem));
item->item.add_to = (ui_menu_add_f)add_menuitem_widget;
item->label = label;
item->userdata = userdata;
item->callback = f;
item->groups =
NULL;
va_list ap;
va_start(ap, userdata);
int group;
while((group = va_arg(ap,
int)) != -
1) {
item->groups = ucx_list_append(item->groups, (
void*)(
intptr_t)group);
}
va_end(ap);
UiMenu *cm = current->data;
cm->items = ucx_list_append(cm->items, item);
}
void ui_menuitem_stgr(
char *stockid, ui_callback f,
void *userdata, ...) {
if(!current) {
return;
}
UiStMenuItem *item = malloc(
sizeof(UiStMenuItem));
item->item.add_to = (ui_menu_add_f)add_menuitem_st_widget;
item->stockid = stockid;
item->userdata = userdata;
item->callback = f;
item->groups =
NULL;
va_list ap;
va_start(ap, userdata);
int group;
while((group = va_arg(ap,
int)) != -
1) {
item->groups = ucx_list_append(item->groups, (
void*)(
intptr_t)group);
}
va_end(ap);
UiMenu *cm = current->data;
cm->items = ucx_list_append(cm->items, item);
}
void ui_menuseparator() {
if(!current) {
return;
}
UiMenuItemI *item = malloc(
sizeof(UiMenuItemI));
item->add_to = (ui_menu_add_f)add_menuseparator_widget;
UiMenu *cm = current->data;
cm->items = ucx_list_append(cm->items, item);
}
void ui_checkitem(
char *label, ui_callback f,
void *userdata) {
if(!current) {
return;
}
UiCheckItem *item = malloc(
sizeof(UiCheckItem));
item->item.add_to = (ui_menu_add_f)add_checkitem_widget;
item->label = label;
item->callback = f;
item->userdata = userdata;
UiMenu *cm = current->data;
cm->items = ucx_list_append(cm->items, item);
}
void ui_checkitem_nv(
char *label,
char *vname) {
if(!current) {
return;
}
UiCheckItemNV *item = malloc(
sizeof(UiCheckItemNV));
item->item.add_to = (ui_menu_add_f)add_checkitemnv_widget;
item->varname = vname;
item->label = label;
UiMenu *cm = current->data;
cm->items = ucx_list_append(cm->items, item);
}
void ui_menuitem_list(UiList *items, ui_callback f,
void *userdata) {
if(!current) {
return;
}
UiMenuItemList *item = malloc(
sizeof(UiMenuItemList));
item->item.add_to = (ui_menu_add_f)add_menuitem_list_widget;
item->callback = f;
item->userdata = userdata;
item->list = items;
UiMenu *cm = current->data;
cm->items = ucx_list_append(cm->items, item);
}
void ui_create_menubar(UiObject *obj) {
if(!menus) {
return;
}
Widget menubar = XmCreateMenuBar(obj->widget,
"main_list",
NULL,
0);
XtManageChild(menubar);
UcxList *ls = menus;
int menu_index =
0;
while(ls) {
UiMenu *menu = ls->data;
menu_index += menu->item.add_to(menubar, menu_index, &menu->item, obj);
ls = ls->next;
}
}
int add_menu_widget(Widget parent,
int i, UiMenuItemI *item, UiObject *obj) {
UiMenu *menu = (UiMenu*)item;
Widget menuItem = XtVaCreateManagedWidget(
menu->label,
xmCascadeButtonWidgetClass,
parent,
NULL);
Widget m = XmVaCreateSimplePulldownMenu(parent, menu->label, i,
NULL,
NULL);
UcxList *ls = menu->items;
int menu_index =
0;
while(ls) {
UiMenuItemI *mi = ls->data;
menu_index += mi->add_to(m, menu_index, mi, obj);
ls = ls->next;
}
return 1;
}
int add_menuitem_widget(
Widget parent,
int i,
UiMenuItemI *item,
UiObject *obj)
{
UiMenuItem *mi = (UiMenuItem*)item;
Arg args[
1];
XmString label = XmStringCreateLocalized(mi->label);
XtSetArg(args[
0], XmNlabelString, label);
Widget mitem = XtCreateManagedWidget(
"menubutton",
xmPushButtonWidgetClass,
parent,
args,
1);
XmStringFree(label);
if(mi->callback !=
NULL) {
UiEventData *event = ucx_mempool_malloc(
obj->ctx->mempool,
sizeof(UiEventData));
event->obj = obj;
event->userdata = mi->userdata;
event->callback = mi->callback;
event->value =
0;
XtAddCallback(
mitem,
XmNactivateCallback,
(XtCallbackProc)ui_push_button_callback,
event);
}
if(mi->groups) {
uic_add_group_widget(obj->ctx, mitem, (ui_enablefunc)XtSetSensitive, mi->groups);
}
return 1;
}
int add_menuitem_st_widget(Widget parent,
int i, UiMenuItemI *item, UiObject *obj) {
UiStMenuItem *mi = (UiStMenuItem*)item;
UiStockItem *si = ui_get_stock_item(mi->stockid);
if(!si) {
fprintf(stderr,
"UI Error: unknown stock id: %s\n", mi->stockid);
return 0;
}
int n =
0;
Arg args[
4];
XmString label = XmStringCreateLocalized(si->label);
XmString at =
NULL;
XtSetArg(args[n], XmNlabelString, label);
n++;
if(si->accelerator) {
XtSetArg(args[n], XmNaccelerator, si->accelerator);
n++;
}
if(si->accelerator_label) {
at = XmStringCreateLocalized(si->accelerator_label);
XtSetArg(args[n], XmNacceleratorText, at);
n++;
}
Widget mitem = XtCreateManagedWidget(
"menubutton",
xmPushButtonWidgetClass,
parent,
args,
n);
XmStringFree(label);
if(at) {
XmStringFree(at);
}
if(mi->callback !=
NULL) {
UiEventData *event = ucx_mempool_malloc(
obj->ctx->mempool,
sizeof(UiEventData));
event->obj = obj;
event->userdata = mi->userdata;
event->callback = mi->callback;
event->value =
0;
XtAddCallback(
mitem,
XmNactivateCallback,
(XtCallbackProc)ui_push_button_callback,
event);
}
if(mi->groups) {
uic_add_group_widget(obj->ctx, mitem, (ui_enablefunc)XtSetSensitive, mi->groups);
}
return 1;
}
int add_menuseparator_widget(
Widget parent,
int i,
UiMenuItemI *item,
UiObject *obj)
{
Widget s = XmCreateSeparatorGadget (parent,
"menu_separator",
NULL,
0);
XtManageChild(s);
return 1;
}
int add_checkitem_widget(
Widget parent,
int i,
UiMenuItemI *item,
UiObject *obj)
{
UiCheckItem *ci = (UiCheckItem*)item;
Arg args[
3];
XmString label = XmStringCreateLocalized(ci->label);
XtSetArg(args[
0], XmNlabelString, label);
XtSetArg(args[
1], XmNvisibleWhenOff,
1);
Widget checkbox = XtCreateManagedWidget(
"menutogglebutton",
xmToggleButtonWidgetClass,
parent,
args,
2);
XmStringFree(label);
if(ci->callback) {
UiEventData *event = ucx_mempool_malloc(
obj->ctx->mempool,
sizeof(UiEventData));
event->obj = obj;
event->userdata = ci->userdata;
event->callback = ci->callback;
XtAddCallback(
checkbox,
XmNvalueChangedCallback,
(XtCallbackProc)ui_toggle_button_callback,
event);
}
return 1;
}
int add_checkitemnv_widget(
Widget parent,
int i,
UiMenuItemI *item,
UiObject *obj)
{
UiCheckItemNV *ci = (UiCheckItemNV*)item;
Arg args[
3];
XmString label = XmStringCreateLocalized(ci->label);
XtSetArg(args[
0], XmNlabelString, label);
XtSetArg(args[
1], XmNvisibleWhenOff,
1);
Widget checkbox = XtCreateManagedWidget(
"menutogglebutton",
xmToggleButtonWidgetClass,
parent,
args,
2);
XmStringFree(label);
UiVar *var = uic_create_var(obj->ctx, ci->varname,
UI_VAR_INTEGER);
if(var) {
UiInteger *value = var->value;
value->obj = checkbox;
value->get = ui_toggle_button_get;
value->set = ui_toggle_button_set;
value =
0;
}
else {
}
return 1;
}
int add_menuitem_list_widget(
Widget parent,
int i,
UiMenuItemI *item,
UiObject *obj)
{
UiMenuItemList *il = (UiMenuItemList*)item;
UcxMempool *mp = obj->ctx->mempool;
UiActiveMenuItemList *ls = ucx_mempool_malloc(
mp,
sizeof(UiActiveMenuItemList));
ls->object = obj;
ls->menu = parent;
ls->index = i;
ls->oldcount =
0;
ls->list = il->list;
ls->callback = il->callback;
ls->userdata = il->userdata;
ls->list->observers = ui_add_observer(
ls->list->observers,
(ui_callback)ui_update_menuitem_list,
ls);
ui_update_menuitem_list(
NULL, ls);
return 0;
}
void ui_update_menuitem_list(UiEvent *event, UiActiveMenuItemList *list) {
Arg args[
4];
if(list->oldcount >
0) {
Widget *children;
int nc;
XtVaGetValues(
list->menu,
XmNchildren,
&children,
XmNnumChildren,
&nc,
NULL);
for(
int i=
0;i<list->oldcount;i++) {
XtDestroyWidget(children[list->index + i]);
}
}
char *str = ui_list_first(list->list);
if(str) {
XtSetArg(args[
0], XmNpositionIndex, list->index);
Widget s = XmCreateSeparatorGadget (list->menu,
"menu_separator", args,
1);
XtManageChild(s);
}
int i =
1;
while(str) {
XmString label = XmStringCreateLocalized(str);
XtSetArg(args[
0], XmNlabelString, label);
XtSetArg(args[
1], XmNpositionIndex, list->index + i);
Widget mitem = XtCreateManagedWidget(
"menubutton",
xmPushButtonWidgetClass,
list->menu,
args,
2);
XmStringFree(label);
if(list->callback) {
UiEventData *event = malloc(
sizeof(UiEventData));
event->obj = list->object;
event->userdata = list->userdata;
event->callback = list->callback;
event->value = i -
1;
XtAddCallback(
mitem,
XmNactivateCallback,
(XtCallbackProc)ui_push_button_callback,
event);
}
str = ui_list_next(list->list);
i++;
}
list->oldcount = i;
}
void ui_menu_event_wrapper(Widget widget, XtPointer udata, XtPointer cdata) {
UiEventData *event = udata;
UiEvent e;
e.obj = event->obj;
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.intval =
0;
event->callback(&e, event->userdata);
}
static void ui_popup_handler(Widget widget, XtPointer data, XEvent *event, Boolean *c) {
Widget menu = data;
XmMenuPosition(menu, (XButtonPressedEvent *)event);
XtManageChild(menu);
*c =
FALSE;
}
UIMENU ui_contextmenu(UiObject *obj) {
UiContainer *ct = uic_get_current_container(obj);
if(ct->current) {
return ui_contextmenu_w(obj, ct->current);
}
else {
return NULL;
}
}
UIMENU ui_contextmenu_w(UiObject *obj,
UIWIDGET widget) {
UiContainer *ct = uic_get_current_container(obj);
Widget menu = XmCreatePopupMenu(widget,
"popup_menu",
NULL,
0);
ct->menu = menu;
XtAddEventHandler(widget, ButtonPressMask,
FALSE, ui_popup_handler, menu);
return menu;
}
void ui_contextmenu_popup(
UIMENU menu) {
}
void ui_widget_menuitem(UiObject *obj,
char *label, ui_callback f,
void *userdata) {
ui_widget_menuitem_gr(obj, label, f, userdata, -
1);
}
void ui_widget_menuitem_gr(UiObject *obj,
char *label, ui_callback f,
void *userdata, ...) {
UiContainer *ct = uic_get_current_container(obj);
if(!ct->menu) {
return;
}
UcxList *groups =
NULL;
va_list ap;
va_start(ap, userdata);
int group;
while((group = va_arg(ap,
int)) != -
1) {
ucx_list_append(groups, (
void*)(
intptr_t)group);
}
va_end(ap);
Arg args[
4];
XmString labelstr = XmStringCreateLocalized(label);
XtSetArg(args[
0], XmNlabelString, labelstr);
Widget item = XmCreatePushButton(ct->menu,
"menu_button", args,
1);
XtManageChild(item);
XmStringFree(labelstr);
}
void ui_widget_menuitem_st(UiObject *obj,
char *stockid, ui_callback f,
void *userdata) {
ui_widget_menuitem_stgr(obj, stockid, f, userdata, -
1);
}
void ui_widget_menuitem_stgr(UiObject *obj,
char *stockid, ui_callback f,
void *userdata, ...) {
UiContainer *ct = uic_get_current_container(obj);
if(!ct->menu) {
return;
}
UcxList *groups =
NULL;
va_list ap;
va_start(ap, userdata);
int group;
while((group = va_arg(ap,
int)) != -
1) {
ucx_list_append(groups, (
void*)(
intptr_t)group);
}
va_end(ap);
UiStockItem *stockItem = ui_get_stock_item(stockid);
Arg args[
4];
XmString labelstr = XmStringCreateLocalized(stockItem->label);
XtSetArg(args[
0], XmNlabelString, labelstr);
Widget item = XmCreatePushButton(ct->menu,
"menu_button", args,
1);
XtManageChild(item);
XmStringFree(labelstr);
}