diff --git a/oui.h b/oui.h index 9cddd1e..6b7ad50 100644 --- a/oui.h +++ b/oui.h @@ -398,6 +398,16 @@ typedef enum UIevent { UI_CHAR = 0x40000, } UIevent; +enum { + // these bits, starting at bit 24, can be safely assigned by the + // application, e.g. as item types, other event types, drop targets, etc. + // they can be set and queried using uiSetFlags() and uiGetFlags() + UI_USERMASK = 0xff000000, + + // a special mask passed to uiFindItem() + UI_ANY = 0xffffffff, +}; + // handler callback; event is one of UI_EVENT_* typedef void (*UIhandler)(int item, UIevent event); @@ -564,6 +574,9 @@ OUI_EXPORT void uiSetHandler(UIhandler handler); // handler should be called. OUI_EXPORT void uiSetEvents(int item, int flags); +// flags is a user-defined set of flags defined by UI_USERMASK. +OUI_EXPORT void uiSetFlags(int item, unsigned int flags); + // assign an item to a container. // an item ID of 0 refers to the root item. // the function returns the child item ID @@ -630,10 +643,22 @@ OUI_EXPORT int uiGetHotItem(); // return the item that is currently focused or -1 for none OUI_EXPORT int uiGetFocusedItem(); +// returns the topmost item containing absolute location (x,y), starting with +// item as parent, using a set of flags and masks as filter: +// if both flags and mask are UI_ANY, the first topmost item is returned. +// if mask is UI_ANY, the first topmost item matching *any* of flags is returned. +// otherwise the first item matching (item.flags & flags) == mask is returned. +// you may combine box, layout, event and user flags. +OUI_EXPORT int uiFindItem(int item, int x, int y, + unsigned int flags, unsigned int mask); + // return the handler callback as passed to uiSetHandler() OUI_EXPORT UIhandler uiGetHandler(); // return the event flags for an item as passed to uiSetEvents() OUI_EXPORT int uiGetEvents(int item); +// return the user-defined flags for an item as passed to uiSetFlags() +OUI_EXPORT unsigned int uiGetFlags(int item); + // when handling a KEY_DOWN/KEY_UP event: the key that triggered this event OUI_EXPORT unsigned int uiGetKey(); // when handling a KEY_DOWN/KEY_UP event: the key that triggered this event @@ -725,7 +750,7 @@ enum { UI_ITEM_FROZEN = 0x080000, // item handle is pointer to data (bit 20) UI_ITEM_DATA = 0x100000, - // item has been inserted + // item has been inserted (bit 21) UI_ITEM_INSERTED = 0x200000, }; @@ -1498,6 +1523,16 @@ int uiGetEvents(int item) { return uiItemPtr(item)->flags & UI_ITEM_EVENT_MASK; } +void uiSetFlags(int item, unsigned int flags) { + UIitem *pitem = uiItemPtr(item); + pitem->flags &= ~UI_USERMASK; + pitem->flags |= flags & UI_USERMASK; +} + +unsigned int uiGetFlags(int item) { + return uiItemPtr(item)->flags & UI_USERMASK; +} + int uiContains(int item, int x, int y) { UIrect rect = uiGetRect(item); x -= rect.x; @@ -1509,14 +1544,14 @@ int uiContains(int item, int x, int y) { return 0; } -int uiFindItemForEvent(int item, UIevent event, int x, int y) { +int uiFindItem(int item, int x, int y, unsigned int flags, unsigned int mask) { UIitem *pitem = uiItemPtr(item); if (pitem->flags & UI_ITEM_FROZEN) return -1; if (uiContains(item, x, y)) { int best_hit = -1; int kid = uiFirstChild(item); while (kid >= 0) { - int hit = uiFindItemForEvent(kid, event, x, y); + int hit = uiFindItem(kid, x, y, flags, mask); if (hit >= 0) { best_hit = hit; } @@ -1525,8 +1560,9 @@ int uiFindItemForEvent(int item, UIevent event, int x, int y) { if (best_hit >= 0) { return best_hit; } - // click-through if the item has no handler for this event - if (pitem->flags & event) { + if (((mask == UI_ANY) && ((flags == UI_ANY) + || (pitem->flags & flags))) + || ((pitem->flags & flags) == mask)) { return item; } } @@ -1536,9 +1572,9 @@ int uiFindItemForEvent(int item, UIevent event, int x, int y) { void uiUpdateHotItem() { assert(ui_context); if (!ui_context->count) return; - ui_context->hot_item = uiFindItemForEvent(0, - (UIevent)UI_ANY_MOUSE_INPUT, - ui_context->cursor.x, ui_context->cursor.y); + ui_context->hot_item = uiFindItem(0, + ui_context->cursor.x, ui_context->cursor.y, + UI_ANY_MOUSE_INPUT, UI_ANY); } int uiGetClicks() { @@ -1568,8 +1604,9 @@ void uiProcess(int timestamp) { ui_context->focus_item = -1; } if (ui_context->scroll.x || ui_context->scroll.y) { - int scroll_item = uiFindItemForEvent(0, UI_SCROLL, - ui_context->cursor.x, ui_context->cursor.y); + int scroll_item = uiFindItem(0, + ui_context->cursor.x, ui_context->cursor.y, + UI_SCROLL, UI_ANY); if (scroll_item >= 0) { uiNotifyItem(scroll_item, UI_SCROLL); } @@ -1607,8 +1644,8 @@ void uiProcess(int timestamp) { ui_context->state = UI_STATE_CAPTURE; } else if (uiGetButton(2) && !uiGetLastButton(2)) { hot_item = -1; - hot = uiFindItemForEvent(0, UI_BUTTON2_DOWN, - ui_context->cursor.x, ui_context->cursor.y); + hot = uiFindItem(0, ui_context->cursor.x, ui_context->cursor.y, + UI_BUTTON2_DOWN, UI_ANY); if (hot >= 0) { uiNotifyItem(hot, UI_BUTTON2_DOWN); }