#include "view.h"
#include "view.inl"
#include "cell.inl"
#include "component.inl"
#include "gui.inl"
#include "panel.inl"
#include <draw2d/guictx.h>
#include <geom2d/s2d.h>
#include <geom2d/v2d.h>
#include <core/event.h>
#include <core/keybuf.h>
#include <core/objh.h>
#include <core/strings.h>
#include <sewer/cassert.h>
#include <sewer/ptr.h>
struct _view_t
{
GuiComponent component;
String *subtype;
S2Df size;
Listener *OnDraw;
Listener *OnOverlay;
Listener *OnResize;
Listener *OnEnter;
Listener *OnExit;
Listener *OnMoved;
Listener *OnDown;
Listener *OnUp;
Listener *OnClick;
Listener *OnDrag;
Listener *OnWheel;
Listener *OnKeyDown;
Listener *OnKeyUp;
Listener *OnFocus;
Listener *OnResignFocus;
Listener *OnAcceptFocus;
Listener *OnScroll;
KeyBuf *keybuf;
void *data;
FPtr_destroy func_destroy_data;
FPtr_gctx_call func_empty;
FPtr_gctx_set_uint32 func_uint32;
FPtr_set_image func_image;
};
static void i_OnDraw(View *view, Event *event)
{
cassert_no_null(view);
cassert(event_type(event) == ekGUI_EVENT_DRAW);
listener_pass_event(view->OnDraw, event, view, View);
}
static void i_OnOverlay(View *view, Event *event)
{
cassert_no_null(view);
cassert(event_type(event) == ekGUI_EVENT_OVERLAY);
listener_pass_event(view->OnOverlay, event, view, View);
}
static void i_OnEnter(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
cassert(event_type(event) == ekGUI_EVENT_ENTER);
listener_pass_event(view->OnEnter, event, view, View);
}
static void i_OnExit(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
cassert(event_type(event) == ekGUI_EVENT_EXIT);
listener_pass_event(view->OnExit, event, view, View);
}
static void i_OnMoved(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
cassert(event_type(event) == ekGUI_EVENT_MOVED);
listener_pass_event(view->OnMoved, event, view, View);
}
static void i_OnDown(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
cassert(event_type(event) == ekGUI_EVENT_DOWN);
listener_pass_event(view->OnDown, event, view, View);
}
static void i_OnUp(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
cassert(event_type(event) == ekGUI_EVENT_UP);
listener_pass_event(view->OnUp, event, view, View);
}
static void i_OnClick(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
cassert(event_type(event) == ekGUI_EVENT_CLICK);
listener_pass_event(view->OnClick, event, view, View);
}
static void i_OnDrag(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
cassert(event_type(event) == ekGUI_EVENT_DRAG);
listener_pass_event(view->OnDrag, event, view, View);
}
static void i_OnWheel(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
cassert(event_type(event) == ekGUI_EVENT_WHEEL);
listener_pass_event(view->OnWheel, event, view, View);
}
static void i_OnKeyDown(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
cassert(event_type(event) == ekGUI_EVENT_KEYDOWN);
if (view->keybuf != NULL)
{
const EvKey *p = event_params(event, EvKey);
keybuf_OnDown(view->keybuf, p->key);
}
if (view->OnKeyDown != NULL)
listener_pass_event(view->OnKeyDown, event, view, View);
}
static void i_OnKeyUp(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
cassert(event_type(event) == ekGUI_EVENT_KEYUP);
if (view->keybuf != NULL)
{
const EvKey *p = event_params(event, EvKey);
keybuf_OnUp(view->keybuf, p->key);
}
if (view->OnKeyUp != NULL)
listener_pass_event(view->OnKeyUp, event, view, View);
}
static void i_OnFocus(View *view, Event *event)
{
cassert_no_null(view);
cassert_no_null(event);
if (view->keybuf != NULL)
keybuf_clear(view->keybuf);
listener_pass_event(view->OnFocus, event, view, View);
}
static void i_OnResignFocus(View *view, Event *event)
{
cassert_no_null(view);
listener_pass_event(view->OnResignFocus, event, view, View);
}
static void i_OnAcceptFocus(View *view, Event *event)
{
cassert_no_null(view);
listener_pass_event(view->OnAcceptFocus, event, view, View);
}
static void i_OnScroll(View *view, Event *event)
{
cassert_no_null(view);
listener_pass_event(view->OnScroll, event, view, View);
}
static View *i_create(const uint32_t flags)
{
const GuiCtx *context = guictx_get_current();
void *ositem = context->func_create[ekGUI_TYPE_CUSTOMVIEW](flags);
if (ositem != NULL)
{
View *view = obj_new0(View);
view->size = s2df(128, 128);
view->data = NULL;
view->func_destroy_data = NULL;
_component_init(&view->component, context, PARAM(type, ekGUI_TYPE_CUSTOMVIEW), &ositem);
return view;
}
else
{
return NULL;
}
}
View *view_create(void)
{
return i_create(0);
}
View *view_scroll(void)
{
return i_create(ekVIEW_HSCROLL | ekVIEW_VSCROLL);
}
View *view_custom(const bool_t scroll, const bool_t border)
{
uint32_t flags = 0;
if (scroll == TRUE)
flags |= ekVIEW_HSCROLL | ekVIEW_VSCROLL;
if (border == TRUE)
flags |= ekVIEW_BORDER;
return i_create(flags);
}
View *_view_create(const uint32_t flags)
{
return i_create(flags);
}
void view_data_imp(View *view, void **data, FPtr_destroy func_destroy_data)
{
cassert_no_null(view);
if (view->data != NULL && view->func_destroy_data != NULL)
view->func_destroy_data(&view->data);
view->data = ptr_dget_no_null(data, void);
view->func_destroy_data = func_destroy_data;
}
void *view_get_data_imp(const View *view)
{
cassert_no_null(view);
return view->data;
}
void _view_destroy(View **view)
{
cassert_no_null(view);
cassert_no_null(*view);
if ((*view)->data != NULL && (*view)->func_destroy_data != NULL)
(*view)->func_destroy_data(&(*view)->data);
_component_destroy_imp(&(*view)->component);
str_destopt(&(*view)->subtype);
listener_destroy(&(*view)->OnDraw);
listener_destroy(&(*view)->OnOverlay);
listener_destroy(&(*view)->OnResize);
listener_destroy(&(*view)->OnEnter);
listener_destroy(&(*view)->OnExit);
listener_destroy(&(*view)->OnMoved);
listener_destroy(&(*view)->OnDown);
listener_destroy(&(*view)->OnUp);
listener_destroy(&(*view)->OnClick);
listener_destroy(&(*view)->OnDrag);
listener_destroy(&(*view)->OnWheel);
listener_destroy(&(*view)->OnKeyDown);
listener_destroy(&(*view)->OnKeyUp);
listener_destroy(&(*view)->OnFocus);
listener_destroy(&(*view)->OnResignFocus);
listener_destroy(&(*view)->OnAcceptFocus);
listener_destroy(&(*view)->OnScroll);
_gui_delete_transition(*view, View);
obj_delete(view, View);
}
void view_size(View *view, const S2Df size)
{
cassert_no_null(view);
view->size = size;
}
void view_OnDraw(View *view, Listener *listener)
{
component_update_listener(view, &view->OnDraw, listener, i_OnDraw, view->component.context->func_view_OnDraw, View);
}
void view_OnOverlay(View *view, Listener *listener)
{
component_update_listener(view, &view->OnOverlay, listener, i_OnOverlay, view->component.context->func_view_OnOverlay, View);
}
void view_OnSize(View *view, Listener *listener)
{
cassert_no_null(view);
listener_update(&view->OnResize, listener);
}
void view_OnEnter(View *view, Listener *listener)
{
component_update_listener(view, &view->OnEnter, listener, i_OnEnter, view->component.context->func_view_OnEnter, View);
}
void view_OnExit(View *view, Listener *listener)
{
component_update_listener(view, &view->OnExit, listener, i_OnExit, view->component.context->func_view_OnExit, View);
}
void view_OnMove(View *view, Listener *listener)
{
component_update_listener(view, &view->OnMoved, listener, i_OnMoved, view->component.context->func_view_OnMoved, View);
}
void view_OnDown(View *view, Listener *listener)
{
component_update_listener(view, &view->OnDown, listener, i_OnDown, view->component.context->func_view_OnDown, View);
}
void view_OnUp(View *view, Listener *listener)
{
component_update_listener(view, &view->OnUp, listener, i_OnUp, view->component.context->func_view_OnUp, View);
}
void view_OnClick(View *view, Listener *listener)
{
component_update_listener(view, &view->OnClick, listener, i_OnClick, view->component.context->func_view_OnClick, View);
}
void view_OnDrag(View *view, Listener *listener)
{
component_update_listener(view, &view->OnDrag, listener, i_OnDrag, view->component.context->func_view_OnDrag, View);
}
void view_OnWheel(View *view, Listener *listener)
{
component_update_listener(view, &view->OnWheel, listener, i_OnWheel, view->component.context->func_view_OnWheel, View);
}
void view_OnKeyDown(View *view, Listener *listener)
{
component_update_listener(view, &view->OnKeyDown, listener, i_OnKeyDown, view->component.context->func_view_OnKeyDown, View);
if (view->keybuf != NULL && view->OnKeyDown == NULL)
view->component.context->func_view_OnKeyDown(view->component.ositem, listener(view, i_OnKeyDown, View));
}
void view_OnKeyUp(View *view, Listener *listener)
{
component_update_listener(view, &view->OnKeyUp, listener, i_OnKeyUp, view->component.context->func_view_OnKeyUp, View);
if (view->keybuf != NULL && view->OnKeyUp == NULL)
view->component.context->func_view_OnKeyUp(view->component.ositem, listener(view, i_OnKeyUp, View));
}
void view_OnFocus(View *view, Listener *listener)
{
component_update_listener(view, &view->OnFocus, listener, i_OnFocus, view->component.context->func_view_OnFocus, View);
}
void view_OnResignFocus(View *view, Listener *listener)
{
component_update_listener(view, &view->OnResignFocus, listener, i_OnResignFocus, view->component.context->func_view_OnResignFocus, View);
}
void view_OnAcceptFocus(View *view, Listener *listener)
{
component_update_listener(view, &view->OnAcceptFocus, listener, i_OnAcceptFocus, view->component.context->func_view_OnAcceptFocus, View);
}
void view_OnScroll(View *view, Listener *listener)
{
component_update_listener(view, &view->OnScroll, listener, i_OnScroll, view->component.context->func_view_OnScroll, View);
}
void view_allow_tab(View *view, const bool_t allow)
{
cassert_no_null(view);
cassert_no_null(view->component.context);
view->component.context->func_view_allow_key(view->component.ositem, ekKEY_TAB, (uint32_t)allow);
}
void view_keybuf(View *view, KeyBuf *buffer)
{
cassert_no_null(view);
view->keybuf = buffer;
if (view->keybuf != NULL && view->OnKeyDown == NULL)
view->component.context->func_view_OnKeyDown(view->component.ositem, listener(view, i_OnKeyDown, View));
if (view->keybuf != NULL && view->OnKeyUp == NULL)
view->component.context->func_view_OnKeyUp(view->component.ositem, listener(view, i_OnKeyUp, View));
}
void _view_set_subtype(View *view, const char_t *subtype)
{
cassert_no_null(view);
cassert(view->subtype == NULL);
view->subtype = str_c(subtype);
}
const char_t *_view_subtype(const View *view)
{
cassert_no_null(view);
if (view->subtype != NULL)
return tc(view->subtype);
return "View";
}
void _view_natural(View *view, const uint32_t i, real32_t *dim0, real32_t *dim1)
{
cassert_no_null(view);
cassert_no_null(dim0);
cassert_no_null(dim1);
if (i == 0)
{
*dim0 = view->size.width;
}
else
{
cassert(i == 1);
*dim1 = view->size.height;
}
}
void _view_OnResize(View *view, const S2Df *size)
{
cassert_no_null(view);
cassert_no_null(size);
if (view->OnResize != NULL)
{
EvSize params;
params.width = size->width;
params.height = size->height;
listener_event(view->OnResize, ekGUI_EVENT_RESIZE, view, ¶ms, NULL, View, EvSize, void);
}
view->component.context->func_view_set_need_display(view->component.ositem);
}
Cell *_view_cell(View *view)
{
cassert_no_null(view);
return _component_cell(&view->component);
}
void *_view_get_native_imp(View *view)
{
cassert_no_null(view);
return view->component.ositem;
}
void _view_OnEmpty(View *view, FPtr_gctx_call func_empty)
{
cassert_no_null(view);
view->func_empty = func_empty;
}
void _view_OnUInt32(View *view, FPtr_gctx_set_uint32 func_uint32)
{
cassert_no_null(view);
view->func_uint32 = func_uint32;
}
void _view_OnImage(View *view, FPtr_set_image func_image)
{
cassert_no_null(view);
view->func_image = func_image;
}
void _view_empty(View *view)
{
cassert_no_null(view);
if (view->func_empty != NULL)
view->func_empty(view);
}
void _view_uint32(View *view, const uint32_t value)
{
cassert_no_null(view);
if (view->func_uint32 != NULL)
view->func_uint32(view, value);
}
void _view_image(View *view, const Image *image)
{
cassert_no_null(view);
if (view->func_image != NULL)
view->func_image(view, image);
}
void view_get_size(const View *view, S2Df *size)
{
cassert_no_null(view);
cassert_no_null(size);
view->component.context->func_get_size[ekGUI_TYPE_CUSTOMVIEW](view->component.ositem, &size->width, &size->height);
}
void view_content_size(View *view, const S2Df size, const S2Df line)
{
cassert_no_null(view);
view->component.context->func_view_content_size(view->component.ositem, size.width, size.height, line.width, line.height);
}
void view_scroll_x(View *view, const real32_t pos)
{
cassert_no_null(view);
view->component.context->func_view_scroll(view->component.ositem, pos, -1);
}
void view_scroll_y(View *view, const real32_t pos)
{
cassert_no_null(view);
view->component.context->func_view_scroll(view->component.ositem, -1, pos);
}
void view_scroll_size(const View *view, real32_t *width, real32_t *height)
{
cassert_no_null(view);
view->component.context->func_view_scroller_size(view->component.ositem, width, height);
}
void view_scroll_visible(View *view, const bool_t horizontal, const bool_t vertical)
{
cassert_no_null(view);
view->component.context->func_view_scroller_visible(view->component.ositem, horizontal, vertical);
}
void view_viewport(const View *view, V2Df *pos, S2Df *size)
{
cassert_no_null(view);
if (pos != NULL)
view->component.context->func_view_scroll_get(view->component.ositem, &pos->x, &pos->y);
if (size != NULL)
view->component.context->func_get_size[ekGUI_TYPE_CUSTOMVIEW](view->component.ositem, &size->width, &size->height);
}
void view_point_scale(const View *view, real32_t *scale)
{
cassert_no_null(view);
cassert_no_null(scale);
*scale = view->component.context->func_view_scale_factor(view->component.ositem);
}
void view_update(View *view)
{
cassert_no_null(view);
view->component.context->func_view_set_need_display(view->component.ositem);
}
void *view_native(View *view)
{
cassert_no_null(view);
return view->component.context->func_view_get_native_view(view->component.ositem);
}
void _view_add_transition(View *view, Listener *listener)
{
cassert_no_null(view);
_gui_add_transition(view, listener, View);
}
void _view_delete_transition(View *view)
{
_gui_delete_transition(view, View);
}