| @@ -20,7 +20,7 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | THE SOFTWARE. | ||||
| */ | |||||
| */ | |||||
| #ifndef _OUI_H_ | #ifndef _OUI_H_ | ||||
| #define _OUI_H_ | #define _OUI_H_ | ||||
| @@ -63,10 +63,10 @@ void app_main(...) { | |||||
| // update button state | // update button state | ||||
| for (int i = 0; i < 3; ++i) | for (int i = 0; i < 3; ++i) | ||||
| uiSetButton(i, app_get_button_state(i)); | uiSetButton(i, app_get_button_state(i)); | ||||
| // begin new UI declarations | // begin new UI declarations | ||||
| uiClear(); | uiClear(); | ||||
| // - UI setup code goes here - | // - UI setup code goes here - | ||||
| app_setup_ui(); | app_setup_ui(); | ||||
| @@ -75,7 +75,7 @@ void app_main(...) { | |||||
| // draw UI | // draw UI | ||||
| app_draw_ui(render_context,0,0,0); | app_draw_ui(render_context,0,0,0); | ||||
| // update states and fire handlers | // update states and fire handlers | ||||
| uiProcess(); | uiProcess(); | ||||
| } | } | ||||
| @@ -93,32 +93,32 @@ typedef struct CheckBoxData { | |||||
| // called when the item is clicked (see checkbox()) | // called when the item is clicked (see checkbox()) | ||||
| void app_checkbox_handler(int item, UIevent event) { | void app_checkbox_handler(int item, UIevent event) { | ||||
| // retrieve custom data (see checkbox()) | // retrieve custom data (see checkbox()) | ||||
| const CheckBoxData *data = (const CheckBoxData *)uiGetData(item); | const CheckBoxData *data = (const CheckBoxData *)uiGetData(item); | ||||
| // toggle value | // toggle value | ||||
| *data->checked = !(*data->checked); | |||||
| *data->checked = !(*data->checked); | |||||
| } | } | ||||
| // creates a checkbox control for a pointer to a boolean and attaches it to | // creates a checkbox control for a pointer to a boolean and attaches it to | ||||
| // a parent item. | // a parent item. | ||||
| int checkbox(int parent, UIhandle handle, const char *label, bool *checked) { | int checkbox(int parent, UIhandle handle, const char *label, bool *checked) { | ||||
| // create new ui item | // create new ui item | ||||
| int item = uiItem(); | int item = uiItem(); | ||||
| // set persistent handle for item that is used | // set persistent handle for item that is used | ||||
| // to track activity over time | // to track activity over time | ||||
| uiSetHandle(item, handle); | uiSetHandle(item, handle); | ||||
| // set size of wiget; horizontal size is dynamic, vertical is fixed | // set size of wiget; horizontal size is dynamic, vertical is fixed | ||||
| uiSetSize(item, 0, APP_WIDGET_HEIGHT); | uiSetSize(item, 0, APP_WIDGET_HEIGHT); | ||||
| // attach checkbox handler, set to fire as soon as the left button is | // attach checkbox handler, set to fire as soon as the left button is | ||||
| // pressed; UI_BUTTON0_HOT_UP is also a popular alternative. | // pressed; UI_BUTTON0_HOT_UP is also a popular alternative. | ||||
| uiSetHandler(item, app_checkbox_handler, UI_BUTTON0_DOWN); | uiSetHandler(item, app_checkbox_handler, UI_BUTTON0_DOWN); | ||||
| // store some custom data with the checkbox that we use for rendering | // store some custom data with the checkbox that we use for rendering | ||||
| // and value changes. | // and value changes. | ||||
| CheckBoxData *data = (CheckBoxData *)uiAllocData(item, sizeof(CheckBoxData)); | CheckBoxData *data = (CheckBoxData *)uiAllocData(item, sizeof(CheckBoxData)); | ||||
| @@ -127,10 +127,10 @@ int checkbox(int parent, UIhandle handle, const char *label, bool *checked) { | |||||
| data->type = APP_WIDGET_CHECKBOX; | data->type = APP_WIDGET_CHECKBOX; | ||||
| data->label = label; | data->label = label; | ||||
| data->checked = checked; | data->checked = checked; | ||||
| // append to parent | // append to parent | ||||
| uiAppend(parent, item); | uiAppend(parent, item); | ||||
| return item; | return item; | ||||
| } | } | ||||
| @@ -140,13 +140,13 @@ void app_draw_ui(AppRenderContext *ctx, int item, int x, int y) { | |||||
| // retrieve custom data and cast it to an int; we assume the first member | // retrieve custom data and cast it to an int; we assume the first member | ||||
| // of every widget data item to be an "int type" field. | // of every widget data item to be an "int type" field. | ||||
| const int *type = (const int *)uiGetData(item); | const int *type = (const int *)uiGetData(item); | ||||
| // get the widgets relative rectangle and offset by the parents | // get the widgets relative rectangle and offset by the parents | ||||
| // absolute position. | // absolute position. | ||||
| UIrect rect = uiGetRect(item); | UIrect rect = uiGetRect(item); | ||||
| rect.x += x; | rect.x += x; | ||||
| rect.y += y; | rect.y += y; | ||||
| // if a type is set, this is a specialized widget | // if a type is set, this is a specialized widget | ||||
| if (type) { | if (type) { | ||||
| switch(*type) { | switch(*type) { | ||||
| @@ -160,20 +160,20 @@ void app_draw_ui(AppRenderContext *ctx, int item, int x, int y) { | |||||
| case APP_WIDGET_CHECKBOX: { | case APP_WIDGET_CHECKBOX: { | ||||
| // cast to the full data type | // cast to the full data type | ||||
| const CheckBoxData *data = (CheckBoxData*)type; | const CheckBoxData *data = (CheckBoxData*)type; | ||||
| // get the widgets current state | // get the widgets current state | ||||
| int state = uiGetState(item); | int state = uiGetState(item); | ||||
| // if the value is set, the state is always active | // if the value is set, the state is always active | ||||
| if (*data->checked) | if (*data->checked) | ||||
| state = UI_ACTIVE; | state = UI_ACTIVE; | ||||
| // draw the checkbox | // draw the checkbox | ||||
| app_draw_checkbox(ctx, rect, state, data->label); | app_draw_checkbox(ctx, rect, state, data->label); | ||||
| } break; | } break; | ||||
| } | } | ||||
| } | } | ||||
| // iterate through all children and draw | // iterate through all children and draw | ||||
| int kid = uiFirstChild(item); | int kid = uiFirstChild(item); | ||||
| while (kid >= 0) { | while (kid >= 0) { | ||||
| @@ -184,7 +184,7 @@ void app_draw_ui(AppRenderContext *ctx, int item, int x, int y) { | |||||
| See example.cpp in the repository for a full usage example. | See example.cpp in the repository for a full usage example. | ||||
| */ | |||||
| */ | |||||
| // you can override this from the outside to pick | // you can override this from the outside to pick | ||||
| // the export level you need | // the export level you need | ||||
| @@ -195,19 +195,19 @@ See example.cpp in the repository for a full usage example. | |||||
| // limits | // limits | ||||
| enum { | enum { | ||||
| // maximum number of items that may be added (must be power of 2) | |||||
| UI_MAX_ITEMS = 4096, | |||||
| // maximum size in bytes reserved for storage of application dependent data | |||||
| // as passed to uiAllocData(). | |||||
| UI_MAX_BUFFERSIZE = 1048576, | |||||
| // maximum size in bytes of a single data buffer passed to uiAllocData(). | |||||
| UI_MAX_DATASIZE = 4096, | |||||
| // maximum depth of nested containers | |||||
| UI_MAX_DEPTH = 64, | |||||
| // maximum number of buffered input events | |||||
| UI_MAX_INPUT_EVENTS = 64, | |||||
| // consecutive click threshold in ms | |||||
| UI_CLICK_THRESHOLD = 250, | |||||
| // maximum number of items that may be added (must be power of 2) | |||||
| UI_MAX_ITEMS = 4096, | |||||
| // maximum size in bytes reserved for storage of application dependent data | |||||
| // as passed to uiAllocData(). | |||||
| UI_MAX_BUFFERSIZE = 1048576, | |||||
| // maximum size in bytes of a single data buffer passed to uiAllocData(). | |||||
| UI_MAX_DATASIZE = 4096, | |||||
| // maximum depth of nested containers | |||||
| UI_MAX_DEPTH = 64, | |||||
| // maximum number of buffered input events | |||||
| UI_MAX_INPUT_EVENTS = 64, | |||||
| // consecutive click threshold in ms | |||||
| UI_CLICK_THRESHOLD = 250, | |||||
| }; | }; | ||||
| typedef unsigned int UIuint; | typedef unsigned int UIuint; | ||||
| @@ -604,48 +604,48 @@ OUI_EXPORT short uiGetMarginDown(int item); | |||||
| #include <assert.h> | #include <assert.h> | ||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||
| #pragma warning (disable: 4996) // Switch off security warnings | |||||
| #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings | |||||
| #ifdef __cplusplus | |||||
| #define UI_INLINE inline | |||||
| #else | |||||
| #define UI_INLINE | |||||
| #endif | |||||
| #pragma warning (disable: 4996) // Switch off security warnings | |||||
| #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings | |||||
| #ifdef __cplusplus | |||||
| #define UI_INLINE inline | |||||
| #else | #else | ||||
| #define UI_INLINE inline | |||||
| #define UI_INLINE | |||||
| #endif | |||||
| #else | |||||
| #define UI_INLINE inline | |||||
| #endif | #endif | ||||
| #define UI_MAX_KIND 16 | #define UI_MAX_KIND 16 | ||||
| #define UI_ANY_BUTTON0_INPUT (UI_BUTTON0_DOWN \ | #define UI_ANY_BUTTON0_INPUT (UI_BUTTON0_DOWN \ | ||||
| |UI_BUTTON0_UP \ | |||||
| |UI_BUTTON0_HOT_UP \ | |||||
| |UI_BUTTON0_CAPTURE) | |||||
| |UI_BUTTON0_UP \ | |||||
| |UI_BUTTON0_HOT_UP \ | |||||
| |UI_BUTTON0_CAPTURE) | |||||
| #define UI_ANY_BUTTON2_INPUT (UI_BUTTON2_DOWN) | #define UI_ANY_BUTTON2_INPUT (UI_BUTTON2_DOWN) | ||||
| #define UI_ANY_MOUSE_INPUT (UI_ANY_BUTTON0_INPUT \ | #define UI_ANY_MOUSE_INPUT (UI_ANY_BUTTON0_INPUT \ | ||||
| |UI_ANY_BUTTON2_INPUT) | |||||
| |UI_ANY_BUTTON2_INPUT) | |||||
| #define UI_ANY_KEY_INPUT (UI_KEY_DOWN \ | #define UI_ANY_KEY_INPUT (UI_KEY_DOWN \ | ||||
| |UI_KEY_UP \ | |||||
| |UI_CHAR) | |||||
| |UI_KEY_UP \ | |||||
| |UI_CHAR) | |||||
| #define UI_ANY_INPUT (UI_ANY_MOUSE_INPUT \ | #define UI_ANY_INPUT (UI_ANY_MOUSE_INPUT \ | ||||
| |UI_ANY_KEY_INPUT) | |||||
| |UI_ANY_KEY_INPUT) | |||||
| // extra item flags | // extra item flags | ||||
| enum { | enum { | ||||
| // bit 0-8 | |||||
| // bit 0-8 | |||||
| UI_ITEM_LAYOUT_MASK = 0x0001FF, | UI_ITEM_LAYOUT_MASK = 0x0001FF, | ||||
| // bit 9-18 | // bit 9-18 | ||||
| UI_ITEM_EVENT_MASK = 0x07FE00, | UI_ITEM_EVENT_MASK = 0x07FE00, | ||||
| // item is frozen (bit 19) | // item is frozen (bit 19) | ||||
| UI_ITEM_FROZEN = 0x080000, | |||||
| // item handle is pointer to data (bit 20) | |||||
| UI_ITEM_DATA = 0x100000, | |||||
| // item has been inserted | |||||
| UI_ITEM_INSERTED = 0x200000, | |||||
| UI_ITEM_FROZEN = 0x080000, | |||||
| // item handle is pointer to data (bit 20) | |||||
| UI_ITEM_DATA = 0x100000, | |||||
| // item has been inserted | |||||
| UI_ITEM_INSERTED = 0x200000, | |||||
| }; | }; | ||||
| typedef struct UIitem { | typedef struct UIitem { | ||||
| @@ -659,7 +659,7 @@ typedef struct UIitem { | |||||
| int firstkid; | int firstkid; | ||||
| // index of next sibling with same parent | // index of next sibling with same parent | ||||
| int nextitem; | int nextitem; | ||||
| // margin offsets, interpretation depends on flags | // margin offsets, interpretation depends on flags | ||||
| // after layouting, the first two components are absolute coordinates | // after layouting, the first two components are absolute coordinates | ||||
| short margins[4]; | short margins[4]; | ||||
| @@ -691,7 +691,7 @@ struct UIcontext { | |||||
| unsigned long long buttons; | unsigned long long buttons; | ||||
| // button state in the previous frame | // button state in the previous frame | ||||
| unsigned long long last_buttons; | unsigned long long last_buttons; | ||||
| // where the cursor was at the beginning of the active state | // where the cursor was at the beginning of the active state | ||||
| UIvec2 start_cursor; | UIvec2 start_cursor; | ||||
| // where the cursor was last frame | // where the cursor was last frame | ||||
| @@ -700,7 +700,7 @@ struct UIcontext { | |||||
| UIvec2 cursor; | UIvec2 cursor; | ||||
| // accumulated scroll wheel offsets | // accumulated scroll wheel offsets | ||||
| UIvec2 scroll; | UIvec2 scroll; | ||||
| int active_item; | int active_item; | ||||
| int focus_item; | int focus_item; | ||||
| int last_hot_item; | int last_hot_item; | ||||
| @@ -714,11 +714,11 @@ struct UIcontext { | |||||
| int last_timestamp; | int last_timestamp; | ||||
| int last_click_timestamp; | int last_click_timestamp; | ||||
| int clicks; | int clicks; | ||||
| int count; | int count; | ||||
| int datasize; | int datasize; | ||||
| int eventcount; | int eventcount; | ||||
| UIitem items[UI_MAX_ITEMS]; | UIitem items[UI_MAX_ITEMS]; | ||||
| unsigned char data[UI_MAX_BUFFERSIZE]; | unsigned char data[UI_MAX_BUFFERSIZE]; | ||||
| UIinputEvent events[UI_MAX_INPUT_EVENTS]; | UIinputEvent events[UI_MAX_INPUT_EVENTS]; | ||||
| @@ -760,8 +760,8 @@ void uiSetButton(int button, int enabled) { | |||||
| unsigned long long mask = 1ull<<button; | unsigned long long mask = 1ull<<button; | ||||
| // set new bit | // set new bit | ||||
| ui_context->buttons = (enabled)? | ui_context->buttons = (enabled)? | ||||
| (ui_context->buttons | mask): | |||||
| (ui_context->buttons & ~mask); | |||||
| (ui_context->buttons | mask): | |||||
| (ui_context->buttons & ~mask); | |||||
| } | } | ||||
| static void uiAddInputEvent(UIinputEvent event) { | static void uiAddInputEvent(UIinputEvent event) { | ||||
| @@ -839,8 +839,8 @@ UIvec2 uiGetCursorStart() { | |||||
| UIvec2 uiGetCursorDelta() { | UIvec2 uiGetCursorDelta() { | ||||
| assert(ui_context); | assert(ui_context); | ||||
| UIvec2 result = {{{ | UIvec2 result = {{{ | ||||
| ui_context->cursor.x - ui_context->last_cursor.x, | |||||
| ui_context->cursor.y - ui_context->last_cursor.y | |||||
| ui_context->cursor.x - ui_context->last_cursor.x, | |||||
| ui_context->cursor.y - ui_context->last_cursor.y | |||||
| }}}; | }}}; | ||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -848,8 +848,8 @@ UIvec2 uiGetCursorDelta() { | |||||
| UIvec2 uiGetCursorStartDelta() { | UIvec2 uiGetCursorStartDelta() { | ||||
| assert(ui_context); | assert(ui_context); | ||||
| UIvec2 result = {{{ | UIvec2 result = {{{ | ||||
| ui_context->cursor.x - ui_context->start_cursor.x, | |||||
| ui_context->cursor.y - ui_context->start_cursor.y | |||||
| ui_context->cursor.x - ui_context->start_cursor.x, | |||||
| ui_context->cursor.y - ui_context->start_cursor.y | |||||
| }}}; | }}}; | ||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -887,14 +887,14 @@ void uiFocus(int item) { | |||||
| static void uiValidateStateItems() { | static void uiValidateStateItems() { | ||||
| assert(ui_context); | assert(ui_context); | ||||
| if (ui_context->last_hot_item >= ui_context->count) | |||||
| ui_context->last_hot_item = -1; | |||||
| if (ui_context->active_item >= ui_context->count) | |||||
| ui_context->active_item = -1; | |||||
| if (ui_context->focus_item >= ui_context->count) | |||||
| ui_context->focus_item = -1; | |||||
| if (ui_context->last_click_item >= ui_context->count) | |||||
| ui_context->last_click_item = -1; | |||||
| if (ui_context->last_hot_item >= ui_context->count) | |||||
| ui_context->last_hot_item = -1; | |||||
| if (ui_context->active_item >= ui_context->count) | |||||
| ui_context->active_item = -1; | |||||
| if (ui_context->focus_item >= ui_context->count) | |||||
| ui_context->focus_item = -1; | |||||
| if (ui_context->last_click_item >= ui_context->count) | |||||
| ui_context->last_click_item = -1; | |||||
| } | } | ||||
| int uiGetFocusedItem() { | int uiGetFocusedItem() { | ||||
| @@ -911,10 +911,10 @@ void uiClear() { | |||||
| void uiClearState() { | void uiClearState() { | ||||
| assert(ui_context); | assert(ui_context); | ||||
| ui_context->last_hot_item = -1; | |||||
| ui_context->active_item = -1; | |||||
| ui_context->focus_item = -1; | |||||
| ui_context->last_click_item = -1; | |||||
| ui_context->last_hot_item = -1; | |||||
| ui_context->active_item = -1; | |||||
| ui_context->focus_item = -1; | |||||
| ui_context->last_click_item = -1; | |||||
| } | } | ||||
| int uiItem() { | int uiItem() { | ||||
| @@ -931,25 +931,25 @@ int uiItem() { | |||||
| void uiNotifyItem(int item, UIevent event) { | void uiNotifyItem(int item, UIevent event) { | ||||
| assert(ui_context); | assert(ui_context); | ||||
| if (!ui_context->handler) | if (!ui_context->handler) | ||||
| return; | |||||
| return; | |||||
| assert((event & UI_ITEM_EVENT_MASK) == event); | assert((event & UI_ITEM_EVENT_MASK) == event); | ||||
| ui_context->event_item = item; | ui_context->event_item = item; | ||||
| UIitem *pitem = uiItemPtr(item); | |||||
| if (pitem->flags & event) { | |||||
| ui_context->handler(item, event); | |||||
| } | |||||
| UIitem *pitem = uiItemPtr(item); | |||||
| if (pitem->flags & event) { | |||||
| ui_context->handler(item, event); | |||||
| } | |||||
| } | } | ||||
| UI_INLINE int uiLastChild(int item) { | UI_INLINE int uiLastChild(int item) { | ||||
| item = uiFirstChild(item); | |||||
| if (item < 0) | |||||
| return -1; | |||||
| while (true) { | |||||
| int nextitem = uiNextSibling(item); | |||||
| if (nextitem < 0) | |||||
| return item; | |||||
| item = nextitem; | |||||
| } | |||||
| item = uiFirstChild(item); | |||||
| if (item < 0) | |||||
| return -1; | |||||
| while (true) { | |||||
| int nextitem = uiNextSibling(item); | |||||
| if (nextitem < 0) | |||||
| return item; | |||||
| item = nextitem; | |||||
| } | |||||
| } | } | ||||
| int uiInsert(int item, int sibling) { | int uiInsert(int item, int sibling) { | ||||
| @@ -972,7 +972,7 @@ int uiAppend(int item, int child) { | |||||
| pparent->firstkid = child; | pparent->firstkid = child; | ||||
| pchild->flags |= UI_ITEM_INSERTED; | pchild->flags |= UI_ITEM_INSERTED; | ||||
| } else { | } else { | ||||
| uiInsert(uiLastChild(item), child); | |||||
| uiInsert(uiLastChild(item), child); | |||||
| } | } | ||||
| return child; | return child; | ||||
| } | } | ||||
| @@ -980,9 +980,9 @@ int uiAppend(int item, int child) { | |||||
| void uiSetFrozen(int item, int enable) { | void uiSetFrozen(int item, int enable) { | ||||
| UIitem *pitem = uiItemPtr(item); | UIitem *pitem = uiItemPtr(item); | ||||
| if (enable) | if (enable) | ||||
| pitem->flags |= UI_ITEM_FROZEN; | |||||
| pitem->flags |= UI_ITEM_FROZEN; | |||||
| else | else | ||||
| pitem->flags &= ~UI_ITEM_FROZEN; | |||||
| pitem->flags &= ~UI_ITEM_FROZEN; | |||||
| } | } | ||||
| void uiSetSize(int item, int w, int h) { | void uiSetSize(int item, int w, int h) { | ||||
| @@ -1031,34 +1031,34 @@ short uiGetMarginDown(int item) { | |||||
| // compute bounding box of all items super-imposed | // compute bounding box of all items super-imposed | ||||
| UI_INLINE void uiComputeImposedSizeDim(UIitem *pitem, int dim) { | UI_INLINE void uiComputeImposedSizeDim(UIitem *pitem, int dim) { | ||||
| int wdim = dim+2; | int wdim = dim+2; | ||||
| if (pitem->size[dim]) | |||||
| return; | |||||
| // largest size is required size | |||||
| short need_size = 0; | |||||
| int kid = pitem->firstkid; | |||||
| while (kid >= 0) { | |||||
| UIitem *pkid = uiItemPtr(kid); | |||||
| // width = start margin + calculated width + end margin | |||||
| int kidsize = pkid->margins[dim] + pkid->size[dim] + pkid->margins[wdim]; | |||||
| need_size = ui_max(need_size, kidsize); | |||||
| kid = uiNextSibling(kid); | |||||
| } | |||||
| pitem->size[dim] = need_size; | |||||
| if (pitem->size[dim]) | |||||
| return; | |||||
| // largest size is required size | |||||
| short need_size = 0; | |||||
| int kid = pitem->firstkid; | |||||
| while (kid >= 0) { | |||||
| UIitem *pkid = uiItemPtr(kid); | |||||
| // width = start margin + calculated width + end margin | |||||
| int kidsize = pkid->margins[dim] + pkid->size[dim] + pkid->margins[wdim]; | |||||
| need_size = ui_max(need_size, kidsize); | |||||
| kid = uiNextSibling(kid); | |||||
| } | |||||
| pitem->size[dim] = need_size; | |||||
| } | } | ||||
| // compute bounding box of all items stacked | // compute bounding box of all items stacked | ||||
| UI_INLINE void uiComputeStackedSizeDim(UIitem *pitem, int dim) { | UI_INLINE void uiComputeStackedSizeDim(UIitem *pitem, int dim) { | ||||
| int wdim = dim+2; | int wdim = dim+2; | ||||
| if (pitem->size[dim]) | |||||
| return; | |||||
| short need_size = 0; | |||||
| int kid = pitem->firstkid; | |||||
| while (kid >= 0) { | |||||
| UIitem *pkid = uiItemPtr(kid); | |||||
| // width += start margin + calculated width + end margin | |||||
| need_size += pkid->margins[dim] + pkid->size[dim] + pkid->margins[wdim]; | |||||
| kid = uiNextSibling(kid); | |||||
| } | |||||
| if (pitem->size[dim]) | |||||
| return; | |||||
| short need_size = 0; | |||||
| int kid = pitem->firstkid; | |||||
| while (kid >= 0) { | |||||
| UIitem *pkid = uiItemPtr(kid); | |||||
| // width += start margin + calculated width + end margin | |||||
| need_size += pkid->margins[dim] + pkid->size[dim] + pkid->margins[wdim]; | |||||
| kid = uiNextSibling(kid); | |||||
| } | |||||
| pitem->size[dim] = need_size; | pitem->size[dim] = need_size; | ||||
| } | } | ||||
| @@ -1071,16 +1071,16 @@ static void uiComputeBestSize(int item, int dim) { | |||||
| uiComputeBestSize(kid, dim); | uiComputeBestSize(kid, dim); | ||||
| kid = uiNextSibling(kid); | kid = uiNextSibling(kid); | ||||
| } | } | ||||
| if(pitem->flags & UI_FLEX) { | if(pitem->flags & UI_FLEX) { | ||||
| // flex model | |||||
| if ((pitem->flags & 1) == (unsigned int)dim) // direction | |||||
| uiComputeStackedSizeDim(pitem, dim); | |||||
| else | |||||
| uiComputeImposedSizeDim(pitem, dim); | |||||
| // flex model | |||||
| if ((pitem->flags & 1) == (unsigned int)dim) // direction | |||||
| uiComputeStackedSizeDim(pitem, dim); | |||||
| else | |||||
| uiComputeImposedSizeDim(pitem, dim); | |||||
| } else { | } else { | ||||
| // layout model | |||||
| uiComputeImposedSizeDim(pitem, dim); | |||||
| // layout model | |||||
| uiComputeImposedSizeDim(pitem, dim); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1091,63 +1091,63 @@ UI_INLINE void uiLayoutStackedItemDim(UIitem *pitem, int dim) { | |||||
| short space = pitem->size[dim]; | short space = pitem->size[dim]; | ||||
| short used = 0; | short used = 0; | ||||
| int count = 0; | |||||
| // first pass: count items that need to be expanded, | |||||
| // and the space that is used | |||||
| int kid = pitem->firstkid; | |||||
| while (kid >= 0) { | |||||
| UIitem *pkid = uiItemPtr(kid); | |||||
| int flags = (pkid->flags & UI_ITEM_LAYOUT_MASK) >> dim; | |||||
| if ((flags & UI_HFILL) == UI_HFILL) { // grow | |||||
| count++; | |||||
| used += pkid->margins[dim] + pkid->margins[wdim]; | |||||
| } else { | |||||
| used += pkid->margins[dim] + pkid->size[dim] + pkid->margins[wdim]; | |||||
| } | |||||
| kid = uiNextSibling(kid); | |||||
| } | |||||
| int count = 0; | |||||
| // first pass: count items that need to be expanded, | |||||
| // and the space that is used | |||||
| int kid = pitem->firstkid; | |||||
| while (kid >= 0) { | |||||
| UIitem *pkid = uiItemPtr(kid); | |||||
| int flags = (pkid->flags & UI_ITEM_LAYOUT_MASK) >> dim; | |||||
| if ((flags & UI_HFILL) == UI_HFILL) { // grow | |||||
| count++; | |||||
| used += pkid->margins[dim] + pkid->margins[wdim]; | |||||
| } else { | |||||
| used += pkid->margins[dim] + pkid->size[dim] + pkid->margins[wdim]; | |||||
| } | |||||
| kid = uiNextSibling(kid); | |||||
| } | |||||
| int extra_space = ui_max(space - used,0); | int extra_space = ui_max(space - used,0); | ||||
| if (extra_space && count) { | if (extra_space && count) { | ||||
| // distribute width among items | |||||
| float width = (float)extra_space / (float)count; | |||||
| float x = (float)pitem->margins[dim]; | |||||
| float x1; | |||||
| // second pass: distribute and rescale | |||||
| kid = pitem->firstkid; | |||||
| while (kid >= 0) { | |||||
| short ix0,ix1; | |||||
| UIitem *pkid = uiItemPtr(kid); | |||||
| int flags = (pkid->flags & UI_ITEM_LAYOUT_MASK) >> dim; | |||||
| x += (float)pkid->margins[dim]; | |||||
| if ((flags & UI_HFILL) == UI_HFILL) { // grow | |||||
| x1 = x+width; | |||||
| } else { | |||||
| x1 = x+(float)pkid->size[dim]; | |||||
| } | |||||
| ix0 = (short)x; | |||||
| ix1 = (short)x1; | |||||
| pkid->margins[dim] = ix0; | |||||
| pkid->size[dim] = ix1-ix0; | |||||
| x = x1 + (float)pkid->margins[wdim]; | |||||
| kid = uiNextSibling(kid); | |||||
| } | |||||
| // distribute width among items | |||||
| float width = (float)extra_space / (float)count; | |||||
| float x = (float)pitem->margins[dim]; | |||||
| float x1; | |||||
| // second pass: distribute and rescale | |||||
| kid = pitem->firstkid; | |||||
| while (kid >= 0) { | |||||
| short ix0,ix1; | |||||
| UIitem *pkid = uiItemPtr(kid); | |||||
| int flags = (pkid->flags & UI_ITEM_LAYOUT_MASK) >> dim; | |||||
| x += (float)pkid->margins[dim]; | |||||
| if ((flags & UI_HFILL) == UI_HFILL) { // grow | |||||
| x1 = x+width; | |||||
| } else { | |||||
| x1 = x+(float)pkid->size[dim]; | |||||
| } | |||||
| ix0 = (short)x; | |||||
| ix1 = (short)x1; | |||||
| pkid->margins[dim] = ix0; | |||||
| pkid->size[dim] = ix1-ix0; | |||||
| x = x1 + (float)pkid->margins[wdim]; | |||||
| kid = uiNextSibling(kid); | |||||
| } | |||||
| } else { | } else { | ||||
| // single pass: just distribute | |||||
| short x = pitem->margins[dim]; | |||||
| int kid = pitem->firstkid; | |||||
| while (kid >= 0) { | |||||
| UIitem *pkid = uiItemPtr(kid); | |||||
| x += pkid->margins[dim]; | |||||
| pkid->margins[dim] = x; | |||||
| x += pkid->size[dim] + pkid->margins[wdim]; | |||||
| kid = uiNextSibling(kid); | |||||
| } | |||||
| // single pass: just distribute | |||||
| short x = pitem->margins[dim]; | |||||
| int kid = pitem->firstkid; | |||||
| while (kid >= 0) { | |||||
| UIitem *pkid = uiItemPtr(kid); | |||||
| x += pkid->margins[dim]; | |||||
| pkid->margins[dim] = x; | |||||
| x += pkid->size[dim] + pkid->margins[wdim]; | |||||
| kid = uiNextSibling(kid); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1173,7 +1173,7 @@ UI_INLINE void uiLayoutImposedItemDim(UIitem *pitem, int dim) { | |||||
| pkid->margins[dim] = space-pkid->size[dim]-pkid->margins[wdim]; | pkid->margins[dim] = space-pkid->size[dim]-pkid->margins[wdim]; | ||||
| } break; | } break; | ||||
| case UI_HFILL: { | case UI_HFILL: { | ||||
| pkid->size[dim] = ui_max(0,space-pkid->margins[dim]-pkid->margins[wdim]); | |||||
| pkid->size[dim] = ui_max(0,space-pkid->margins[dim]-pkid->margins[wdim]); | |||||
| } break; | } break; | ||||
| } | } | ||||
| pkid->margins[dim] += offset; | pkid->margins[dim] += offset; | ||||
| @@ -1184,18 +1184,18 @@ UI_INLINE void uiLayoutImposedItemDim(UIitem *pitem, int dim) { | |||||
| static void uiLayoutItem(int item, int dim) { | static void uiLayoutItem(int item, int dim) { | ||||
| UIitem *pitem = uiItemPtr(item); | UIitem *pitem = uiItemPtr(item); | ||||
| if(pitem->flags & UI_FLEX) { | if(pitem->flags & UI_FLEX) { | ||||
| // flex model | |||||
| if ((pitem->flags & 1) == (unsigned int)dim) // direction | |||||
| uiLayoutStackedItemDim(pitem, dim); | |||||
| else | |||||
| uiLayoutImposedItemDim(pitem, dim); | |||||
| // flex model | |||||
| if ((pitem->flags & 1) == (unsigned int)dim) // direction | |||||
| uiLayoutStackedItemDim(pitem, dim); | |||||
| else | |||||
| uiLayoutImposedItemDim(pitem, dim); | |||||
| } else { | } else { | ||||
| // layout model | |||||
| uiLayoutImposedItemDim(pitem, dim); | |||||
| // layout model | |||||
| uiLayoutImposedItemDim(pitem, dim); | |||||
| } | } | ||||
| int kid = uiFirstChild(item); | int kid = uiFirstChild(item); | ||||
| while (kid >= 0) { | while (kid >= 0) { | ||||
| uiLayoutItem(kid, dim); | uiLayoutItem(kid, dim); | ||||
| @@ -1204,11 +1204,11 @@ static void uiLayoutItem(int item, int dim) { | |||||
| } | } | ||||
| UIrect uiGetRect(int item) { | UIrect uiGetRect(int item) { | ||||
| UIitem *pitem = uiItemPtr(item); | |||||
| UIrect rc = {{{ | |||||
| pitem->margins[0], pitem->margins[1], | |||||
| pitem->size[0], pitem->size[1] | |||||
| }}}; | |||||
| UIitem *pitem = uiItemPtr(item); | |||||
| UIrect rc = {{{ | |||||
| pitem->margins[0], pitem->margins[1], | |||||
| pitem->size[0], pitem->size[1] | |||||
| }}}; | |||||
| return rc; | return rc; | ||||
| } | } | ||||
| @@ -1242,12 +1242,12 @@ void *uiGetHandle(int item) { | |||||
| } | } | ||||
| void uiSetHandler(UIhandler handler) { | void uiSetHandler(UIhandler handler) { | ||||
| assert(ui_context); | |||||
| ui_context->handler = handler; | |||||
| assert(ui_context); | |||||
| ui_context->handler = handler; | |||||
| } | } | ||||
| UIhandler uiGetHandler() { | UIhandler uiGetHandler() { | ||||
| assert(ui_context); | |||||
| assert(ui_context); | |||||
| return ui_context->handler; | return ui_context->handler; | ||||
| } | } | ||||
| @@ -1266,9 +1266,9 @@ int uiContains(int item, int x, int y) { | |||||
| x -= rect.x; | x -= rect.x; | ||||
| y -= rect.y; | y -= rect.y; | ||||
| if ((x>=0) | if ((x>=0) | ||||
| && (y>=0) | |||||
| && (x<rect.w) | |||||
| && (y<rect.h)) return 1; | |||||
| && (y>=0) | |||||
| && (x<rect.w) | |||||
| && (y<rect.h)) return 1; | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -1276,17 +1276,17 @@ int uiFindItemForEvent(int item, UIevent event, int x, int y) { | |||||
| UIitem *pitem = uiItemPtr(item); | UIitem *pitem = uiItemPtr(item); | ||||
| if (pitem->flags & UI_ITEM_FROZEN) return -1; | if (pitem->flags & UI_ITEM_FROZEN) return -1; | ||||
| if (uiContains(item, x, y)) { | if (uiContains(item, x, y)) { | ||||
| int best_hit = -1; | |||||
| int best_hit = -1; | |||||
| int kid = uiFirstChild(item); | int kid = uiFirstChild(item); | ||||
| while (kid >= 0) { | while (kid >= 0) { | ||||
| int hit = uiFindItemForEvent(kid, event, x, y); | int hit = uiFindItemForEvent(kid, event, x, y); | ||||
| if (hit >= 0) { | if (hit >= 0) { | ||||
| best_hit = hit; | |||||
| best_hit = hit; | |||||
| } | } | ||||
| kid = uiNextSibling(kid); | kid = uiNextSibling(kid); | ||||
| } | } | ||||
| if (best_hit >= 0) { | if (best_hit >= 0) { | ||||
| return best_hit; | |||||
| return best_hit; | |||||
| } | } | ||||
| // click-through if the item has no handler for this event | // click-through if the item has no handler for this event | ||||
| if (pitem->flags & event) { | if (pitem->flags & event) { | ||||
| @@ -1317,12 +1317,12 @@ void uiUpdateHotItem() { | |||||
| assert(ui_context); | assert(ui_context); | ||||
| if (!ui_context->count) return; | if (!ui_context->count) return; | ||||
| ui_context->hot_item = uiFindItemForEvent(0, | ui_context->hot_item = uiFindItemForEvent(0, | ||||
| (UIevent)UI_ANY_MOUSE_INPUT, | |||||
| ui_context->cursor.x, ui_context->cursor.y); | |||||
| (UIevent)UI_ANY_MOUSE_INPUT, | |||||
| ui_context->cursor.x, ui_context->cursor.y); | |||||
| } | } | ||||
| int uiGetClicks() { | int uiGetClicks() { | ||||
| return ui_context->clicks; | |||||
| return ui_context->clicks; | |||||
| } | } | ||||
| void uiProcess(int timestamp) { | void uiProcess(int timestamp) { | ||||
| @@ -1331,7 +1331,7 @@ void uiProcess(int timestamp) { | |||||
| uiClearInputEvents(); | uiClearInputEvents(); | ||||
| return; | return; | ||||
| } | } | ||||
| int hot_item = ui_context->last_hot_item; | int hot_item = ui_context->last_hot_item; | ||||
| int active_item = ui_context->active_item; | int active_item = ui_context->active_item; | ||||
| int focus_item = ui_context->focus_item; | int focus_item = ui_context->focus_item; | ||||
| @@ -1342,17 +1342,17 @@ void uiProcess(int timestamp) { | |||||
| ui_context->active_key = ui_context->events[i].key; | ui_context->active_key = ui_context->events[i].key; | ||||
| ui_context->active_modifier = ui_context->events[i].mod; | ui_context->active_modifier = ui_context->events[i].mod; | ||||
| uiNotifyItem(focus_item, | uiNotifyItem(focus_item, | ||||
| ui_context->events[i].event); | |||||
| ui_context->events[i].event); | |||||
| } | } | ||||
| } else { | } else { | ||||
| ui_context->focus_item = -1; | ui_context->focus_item = -1; | ||||
| } | } | ||||
| if (ui_context->scroll.x || ui_context->scroll.y) { | if (ui_context->scroll.x || ui_context->scroll.y) { | ||||
| int scroll_item = uiFindItemForEvent(0, UI_SCROLL, | |||||
| ui_context->cursor.x, ui_context->cursor.y); | |||||
| if (scroll_item >= 0) { | |||||
| int scroll_item = uiFindItemForEvent(0, UI_SCROLL, | |||||
| ui_context->cursor.x, ui_context->cursor.y); | |||||
| if (scroll_item >= 0) { | |||||
| uiNotifyItem(scroll_item, UI_SCROLL); | uiNotifyItem(scroll_item, UI_SCROLL); | ||||
| } | |||||
| } | |||||
| } | } | ||||
| uiClearInputEvents(); | uiClearInputEvents(); | ||||
| @@ -1366,19 +1366,19 @@ void uiProcess(int timestamp) { | |||||
| if (uiGetButton(0)) { | if (uiGetButton(0)) { | ||||
| hot_item = -1; | hot_item = -1; | ||||
| active_item = hot; | active_item = hot; | ||||
| if (active_item != focus_item) { | if (active_item != focus_item) { | ||||
| focus_item = -1; | focus_item = -1; | ||||
| ui_context->focus_item = -1; | ui_context->focus_item = -1; | ||||
| } | } | ||||
| if (active_item >= 0) { | if (active_item >= 0) { | ||||
| if ( | |||||
| ((timestamp - ui_context->last_click_timestamp) > UI_CLICK_THRESHOLD) | |||||
| || (ui_context->last_click_item != active_item)) { | |||||
| ui_context->clicks = 0; | |||||
| } | |||||
| ui_context->clicks++; | |||||
| if ( | |||||
| ((timestamp - ui_context->last_click_timestamp) > UI_CLICK_THRESHOLD) | |||||
| || (ui_context->last_click_item != active_item)) { | |||||
| ui_context->clicks = 0; | |||||
| } | |||||
| ui_context->clicks++; | |||||
| ui_context->last_click_timestamp = timestamp; | ui_context->last_click_timestamp = timestamp; | ||||
| ui_context->last_click_item = active_item; | ui_context->last_click_item = active_item; | ||||
| @@ -1387,11 +1387,11 @@ void uiProcess(int timestamp) { | |||||
| ui_context->state = UI_STATE_CAPTURE; | ui_context->state = UI_STATE_CAPTURE; | ||||
| } else if (uiGetButton(2) && !uiGetLastButton(2)) { | } else if (uiGetButton(2) && !uiGetLastButton(2)) { | ||||
| hot_item = -1; | hot_item = -1; | ||||
| hot = uiFindItemForEvent(0, UI_BUTTON2_DOWN, | |||||
| ui_context->cursor.x, ui_context->cursor.y); | |||||
| if (hot >= 0) { | |||||
| uiNotifyItem(hot, UI_BUTTON2_DOWN); | |||||
| } | |||||
| hot = uiFindItemForEvent(0, UI_BUTTON2_DOWN, | |||||
| ui_context->cursor.x, ui_context->cursor.y); | |||||
| if (hot >= 0) { | |||||
| uiNotifyItem(hot, UI_BUTTON2_DOWN); | |||||
| } | |||||
| } else { | } else { | ||||
| hot_item = hot; | hot_item = hot; | ||||
| } | } | ||||
| @@ -1417,7 +1417,7 @@ void uiProcess(int timestamp) { | |||||
| } | } | ||||
| } break; | } break; | ||||
| } | } | ||||
| ui_context->last_cursor = ui_context->cursor; | ui_context->last_cursor = ui_context->cursor; | ||||
| ui_context->last_hot_item = hot_item; | ui_context->last_hot_item = hot_item; | ||||
| ui_context->active_item = active_item; | ui_context->active_item = active_item; | ||||
| @@ -1450,7 +1450,7 @@ UIitemState uiGetState(int item) { | |||||
| if (uiIsActive(item)) { | if (uiIsActive(item)) { | ||||
| if (pitem->flags & (UI_BUTTON0_CAPTURE|UI_BUTTON0_UP)) return UI_ACTIVE; | if (pitem->flags & (UI_BUTTON0_CAPTURE|UI_BUTTON0_UP)) return UI_ACTIVE; | ||||
| if ((pitem->flags & UI_BUTTON0_HOT_UP) | if ((pitem->flags & UI_BUTTON0_HOT_UP) | ||||
| && uiIsHot(item)) return UI_ACTIVE; | |||||
| && uiIsHot(item)) return UI_ACTIVE; | |||||
| return UI_COLD; | return UI_COLD; | ||||
| } else if (uiIsHot(item)) { | } else if (uiIsHot(item)) { | ||||
| return UI_HOT; | return UI_HOT; | ||||