#include "menuitem.h"
#include "menuitem.inl"
#include "menu.inl"
#include "gui.inl"
#include <draw2d/guictx.h>
#include <draw2d/image.h>
#include <core/event.h>
#include <core/objh.h>
#include <core/strings.h>
#include <sewer/cassert.h>
#include <sewer/ptr.h>
struct _menu_item_t
{
Object object;
GuiCtx *context;
bool_t separator;
bool_t visible;
bool_t enabled;
gui_state_t state;
uint16_t index;
ResId textid;
String *text;
Image *image;
void *ositem;
Menu *submenu;
Listener *OnClick;
};
static MenuItem *i_create(const GuiCtx *context, const bool_t separator, void **ositem)
{
MenuItem *item = obj_new0(MenuItem);
item->context = guictx_retain(context);
item->separator = separator;
item->visible = TRUE;
item->enabled = TRUE;
item->state = ekGUI_OFF;
item->index = UINT16_MAX;
item->text = str_c("");
item->ositem = ptr_dget_no_null(ositem, void);
return item;
}
void _menuitem_destroy(MenuItem **item)
{
cassert_no_null(item);
cassert_no_null(*item);
cassert((*item)->index == UINT16_MAX);
cassert_no_null((*item)->context);
cassert_no_nullf((*item)->context->func_menuitem_destroy);
cassert((*item)->OnClick == NULL);
if ((*item)->submenu != NULL)
{
void *ositem = NULL;
cassert_no_nullf((*item)->context->func_detach_menu_from_menu_item);
_menu_unset_parent((*item)->submenu);
ositem = _menu_ositem((*item)->submenu);
(*item)->context->func_detach_menu_from_menu_item((*item)->ositem, ositem);
_menu_destroy(&(*item)->submenu);
}
(*item)->context->func_menuitem_destroy(&(*item)->ositem);
str_destopt(&(*item)->text);
ptr_destopt(image_destroy, &(*item)->image, Image);
guictx_release(&(*item)->context);
obj_delete(item, MenuItem);
}
static void i_OnMenuItemClick(MenuItem *item, Event *e)
{
cassert_no_null(item);
cassert(item->separator == FALSE);
cassert(event_sender_imp(e, NULL) == item->ositem);
if (item->OnClick != NULL)
{
EvMenu *p = event_params(e, EvMenu);
cassert(p->index == UINT32_MAX);
cassert(p->text == NULL);
p->index = item->index;
p->text = tc(item->text);
listener_pass_event(item->OnClick, e, item, MenuItem);
}
}
MenuItem *menuitem_create(void)
{
const GuiCtx *context = guictx_get_current();
void *ositem = NULL;
MenuItem *item = NULL;
cassert_no_null(context);
cassert_no_nullf(context->func_menuitem_create);
cassert_no_nullf(context->func_menuitem_OnClick);
ositem = context->func_menuitem_create((enum_t)ekMENU_ITEM);
item = i_create(context, FALSE, &ositem);
context->func_menuitem_OnClick(item->ositem, obj_listener(item, i_OnMenuItemClick, MenuItem));
return item;
}
MenuItem *menuitem_separator(void)
{
const GuiCtx *context = guictx_get_current();
void *ositem = NULL;
cassert_no_null(context);
cassert_no_nullf(context->func_menuitem_create);
ositem = context->func_menuitem_create((enum_t)ekMENU_SEPARATOR);
return i_create(context, TRUE, &ositem);
}
void menuitem_OnClick(MenuItem *item, Listener *listener)
{
cassert_no_null(item);
listener_update(&item->OnClick, listener);
}
void menuitem_enabled(MenuItem *item, const bool_t enabled)
{
cassert_no_null(item);
cassert_no_null(item->context);
cassert_no_nullf(item->context->func_menuitem_set_enabled);
item->enabled = enabled;
item->context->func_menuitem_set_enabled(item->ositem, enabled);
}
void menuitem_visible(MenuItem *item, const bool_t visible)
{
cassert_no_null(item);
cassert_no_null(item->context);
cassert_no_nullf(item->context->func_menuitem_set_visible);
item->visible = visible;
item->context->func_menuitem_set_visible(item->ositem, visible);
}
void menuitem_state(MenuItem *item, const gui_state_t state)
{
cassert_no_null(item);
cassert(item->separator == FALSE);
cassert_no_null(item->context);
cassert_no_nullf(item->context->func_menuitem_set_state);
item->state = state;
item->context->func_menuitem_set_state(item->ositem, (enum_t)state);
}
static void i_update_text(MenuItem *item, const char_t *text, ResId *resid)
{
const char_t *ltext = NULL;
cassert_no_null(item);
cassert(item->separator == FALSE);
cassert_no_null(item->context);
cassert_no_nullf(item->context->func_menuitem_set_text);
ltext = _gui_respack_text(text, resid);
item->context->func_menuitem_set_text(item->ositem, ltext);
str_upd(&item->text, ltext);
}
void menuitem_text(MenuItem *item, const char_t *text)
{
cassert_no_null(item);
i_update_text(item, text, &item->textid);
}
void menuitem_image(MenuItem *item, const Image *image)
{
const Image *limage = _gui_respack_image((ResId)image, NULL);
cassert_no_null(item);
cassert_no_null(item->context);
cassert_no_nullf(item->context->func_menuitem_set_image);
ptr_destopt(image_destroy, &item->image, Image);
item->image = ptr_copyopt(image_copy, limage, Image);
item->context->func_menuitem_set_image(item->ositem, limage);
}
void menuitem_key(MenuItem *item, const vkey_t key, const uint32_t modifiers)
{
cassert_no_null(item);
cassert(item->separator == FALSE);
cassert_no_null(item->context);
cassert_no_nullf(item->context->func_menuitem_set_key_equivalent);
item->context->func_menuitem_set_key_equivalent(item->ositem, key, modifiers);
}
void menuitem_submenu(MenuItem *item, Menu **submenu)
{
void *ositem = NULL;
cassert_no_null(item);
cassert(item->separator == FALSE);
cassert(item->submenu == NULL);
cassert_no_null(submenu);
cassert_no_null(item->context);
cassert_no_nullf(item->context->func_attach_menu_to_menu_item);
_menu_set_parent(*submenu);
ositem = _menu_ositem(*submenu);
item->context->func_attach_menu_to_menu_item(item->ositem, ositem);
item->submenu = *submenu;
*submenu = NULL;
}
const char_t *menuitem_get_text(const MenuItem *item)
{
cassert_no_null(item);
return tc(item->text);
}
const Image *menuitem_get_image(const MenuItem *item)
{
cassert_no_null(item);
return item->image;
}
bool_t menuitem_get_separator(const MenuItem *item)
{
cassert_no_null(item);
return item->separator;
}
bool_t menuitem_get_enabled(const MenuItem *item)
{
cassert_no_null(item);
return item->enabled;
}
bool_t menuitem_get_visible(const MenuItem *item)
{
cassert_no_null(item);
return item->visible;
}
gui_state_t menuitem_get_state(const MenuItem *item)
{
cassert_no_null(item);
return item->state;
}
Menu *menuitem_get_submenu(const MenuItem *item)
{
cassert_no_null(item);
return item->submenu;
}
void *_menuitem_get_renderable(const MenuItem *item)
{
cassert_no_null(item);
return item->ositem;
}
void _menuitem_set_parent(MenuItem *item, const uint32_t index)
{
cassert_no_null(item);
cassert(item->index == UINT16_MAX);
item->index = (uint16_t)index;
}
void _menuitem_unset_parent(MenuItem *item)
{
cassert_no_null(item);
cassert(item->index != UINT16_MAX);
listener_destroy(&item->OnClick);
item->index = UINT16_MAX;
}
void _menuitem_locale(MenuItem *item)
{
if (item->textid != NULL)
i_update_text(item, item->textid, NULL);
if (item->submenu != NULL)
_menu_locale(item->submenu);
}