| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- #include "nuklear.h"
- #include "nuklear_internal.h"
- /* ===============================================================
- *
- * PROPERTY
- *
- * ===============================================================*/
- NK_LIB void
- nk_drag_behavior(nk_flags *state, const struct nk_input *in,
- struct nk_rect drag, struct nk_property_variant *variant,
- float inc_per_pixel)
- {
- int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
- int left_mouse_click_in_cursor = in &&
- nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true);
- nk_widget_state_reset(state);
- if (nk_input_is_mouse_hovering_rect(in, drag))
- *state = NK_WIDGET_STATE_HOVERED;
- if (left_mouse_down && left_mouse_click_in_cursor) {
- float delta, pixels;
- pixels = in->mouse.delta.x;
- delta = pixels * inc_per_pixel;
- switch (variant->kind) {
- default: break;
- case NK_PROPERTY_INT:
- variant->value.i = variant->value.i + (int)delta;
- variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
- break;
- case NK_PROPERTY_FLOAT:
- variant->value.f = variant->value.f + (float)delta;
- variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
- break;
- case NK_PROPERTY_DOUBLE:
- variant->value.d = variant->value.d + (double)delta;
- variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
- break;
- }
- *state = NK_WIDGET_STATE_ACTIVE;
- }
- if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
- *state |= NK_WIDGET_STATE_ENTERED;
- else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
- *state |= NK_WIDGET_STATE_LEFT;
- }
- NK_LIB void
- nk_property_behavior(nk_flags *ws, const struct nk_input *in,
- struct nk_rect property, struct nk_rect label, struct nk_rect edit,
- struct nk_rect empty, int *state, struct nk_property_variant *variant,
- float inc_per_pixel)
- {
- nk_widget_state_reset(ws);
- if (in && *state == NK_PROPERTY_DEFAULT) {
- if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
- *state = NK_PROPERTY_EDIT;
- else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true))
- *state = NK_PROPERTY_DRAG;
- else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true))
- *state = NK_PROPERTY_DRAG;
- }
- if (*state == NK_PROPERTY_DRAG) {
- nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
- if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
- }
- }
- NK_LIB void
- nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
- const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
- const char *name, int len, const struct nk_user_font *font)
- {
- struct nk_text text;
- const struct nk_style_item *background;
- /* select correct background and text color */
- if (state & NK_WIDGET_STATE_ACTIVED) {
- background = &style->active;
- text.text = style->label_active;
- } else if (state & NK_WIDGET_STATE_HOVER) {
- background = &style->hover;
- text.text = style->label_hover;
- } else {
- background = &style->normal;
- text.text = style->label_normal;
- }
- text.text = nk_rgb_factor(text.text, style->color_factor);
- /* draw background */
- switch(background->type) {
- case NK_STYLE_ITEM_IMAGE:
- text.background = nk_rgba(0, 0, 0, 0);
- nk_draw_image(out, *bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
- break;
- case NK_STYLE_ITEM_NINE_SLICE:
- text.background = nk_rgba(0, 0, 0, 0);
- nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor));
- break;
- case NK_STYLE_ITEM_COLOR:
- text.background = background->data.color;
- nk_fill_rect(out, *bounds, style->rounding, nk_rgb_factor(background->data.color, style->color_factor));
- nk_stroke_rect(out, *bounds, style->rounding, style->border, nk_rgb_factor(style->border_color, style->color_factor));
- break;
- }
- /* draw label */
- text.padding = nk_vec2(0,0);
- if (name && name[0] != '#') {
- nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
- }
- }
- NK_LIB void
- nk_do_property(nk_flags *ws,
- struct nk_command_buffer *out, struct nk_rect property,
- const char *name, struct nk_property_variant *variant,
- float inc_per_pixel, char *buffer, int *len,
- int *state, int *cursor, int *select_begin, int *select_end,
- const struct nk_style_property *style,
- enum nk_property_filter filter, struct nk_input *in,
- const struct nk_user_font *font, struct nk_text_edit *text_edit,
- enum nk_button_behavior behavior)
- {
- const nk_plugin_filter filters[] = {
- nk_filter_decimal,
- nk_filter_float
- };
- nk_bool active, old;
- int num_len = 0, name_len = 0;
- char string[NK_MAX_NUMBER_BUFFER];
- float size;
- char *dst = 0;
- int *length;
- struct nk_rect left;
- struct nk_rect right;
- struct nk_rect label;
- struct nk_rect edit;
- struct nk_rect empty;
- /* left decrement button */
- left.h = font->height/2;
- left.w = left.h;
- left.x = property.x + style->border + style->padding.x;
- left.y = property.y + style->border + property.h/2.0f - left.h/2;
- /* text label */
- if (name && name[0] != '#') {
- name_len = nk_strlen(name);
- }
- size = font->width(font->userdata, font->height, name, name_len);
- label.x = left.x + left.w + style->padding.x;
- label.w = (float)size + 2 * style->padding.x;
- label.y = property.y + style->border + style->padding.y;
- label.h = property.h - (2 * style->border + 2 * style->padding.y);
- /* right increment button */
- right.y = left.y;
- right.w = left.w;
- right.h = left.h;
- right.x = property.x + property.w - (right.w + style->padding.x);
- /* edit */
- if (*state == NK_PROPERTY_EDIT) {
- size = font->width(font->userdata, font->height, buffer, *len);
- size += style->edit.cursor_size;
- length = len;
- dst = buffer;
- } else {
- switch (variant->kind) {
- default: break;
- case NK_PROPERTY_INT:
- nk_itoa(string, variant->value.i);
- num_len = nk_strlen(string);
- break;
- case NK_PROPERTY_FLOAT:
- NK_DTOA(string, (double)variant->value.f);
- num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
- break;
- case NK_PROPERTY_DOUBLE:
- NK_DTOA(string, variant->value.d);
- num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
- break;
- }
- size = font->width(font->userdata, font->height, string, num_len);
- dst = string;
- length = &num_len;
- }
- edit.w = (float)size + 2 * style->padding.x;
- edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
- edit.x = right.x - (edit.w + style->padding.x);
- edit.y = property.y + style->border;
- edit.h = property.h - (2 * style->border);
- /* empty left space activator */
- empty.w = edit.x - (label.x + label.w);
- empty.x = label.x + label.w;
- empty.y = property.y;
- empty.h = property.h;
- /* update property */
- old = (*state == NK_PROPERTY_EDIT);
- nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
- /* draw property */
- if (style->draw_begin) style->draw_begin(out, style->userdata);
- nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
- if (style->draw_end) style->draw_end(out, style->userdata);
- /* execute right button */
- if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
- switch (variant->kind) {
- default: break;
- case NK_PROPERTY_INT:
- variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
- case NK_PROPERTY_FLOAT:
- variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
- case NK_PROPERTY_DOUBLE:
- variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
- }
- }
- /* execute left button */
- if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
- switch (variant->kind) {
- default: break;
- case NK_PROPERTY_INT:
- variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
- case NK_PROPERTY_FLOAT:
- variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
- case NK_PROPERTY_DOUBLE:
- variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
- }
- }
- if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
- /* property has been activated so setup buffer */
- NK_MEMCPY(buffer, dst, (nk_size)*length);
- *cursor = nk_utf_len(buffer, *length);
- *len = *length;
- length = len;
- dst = buffer;
- active = 0;
- } else active = (*state == NK_PROPERTY_EDIT);
- /* execute and run text edit field */
- nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
- text_edit->active = (unsigned char)active;
- text_edit->string.len = *length;
- text_edit->cursor = NK_CLAMP(0, *cursor, *length);
- text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
- text_edit->select_end = NK_CLAMP(0,*select_end, *length);
- text_edit->string.buffer.allocated = (nk_size)*length;
- text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER;
- text_edit->string.buffer.memory.ptr = dst;
- text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
- text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
- nk_do_edit(ws, out, edit, (int)NK_EDIT_FIELD|(int)NK_EDIT_AUTO_SELECT,
- filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
- *length = text_edit->string.len;
- *cursor = text_edit->cursor;
- *select_begin = text_edit->select_start;
- *select_end = text_edit->select_end;
- if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
- text_edit->active = nk_false;
- if (active && !text_edit->active) {
- /* property is now not active so convert edit text to value*/
- *state = NK_PROPERTY_DEFAULT;
- buffer[*len] = '\0';
- switch (variant->kind) {
- default: break;
- case NK_PROPERTY_INT:
- variant->value.i = nk_strtoi(buffer, 0);
- variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
- break;
- case NK_PROPERTY_FLOAT:
- nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
- variant->value.f = nk_strtof(buffer, 0);
- variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
- break;
- case NK_PROPERTY_DOUBLE:
- nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
- variant->value.d = nk_strtod(buffer, 0);
- variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
- break;
- }
- }
- }
- NK_LIB struct nk_property_variant
- nk_property_variant_int(int value, int min_value, int max_value, int step)
- {
- struct nk_property_variant result;
- result.kind = NK_PROPERTY_INT;
- result.value.i = value;
- result.min_value.i = min_value;
- result.max_value.i = max_value;
- result.step.i = step;
- return result;
- }
- NK_LIB struct nk_property_variant
- nk_property_variant_float(float value, float min_value, float max_value, float step)
- {
- struct nk_property_variant result;
- result.kind = NK_PROPERTY_FLOAT;
- result.value.f = value;
- result.min_value.f = min_value;
- result.max_value.f = max_value;
- result.step.f = step;
- return result;
- }
- NK_LIB struct nk_property_variant
- nk_property_variant_double(double value, double min_value, double max_value,
- double step)
- {
- struct nk_property_variant result;
- result.kind = NK_PROPERTY_DOUBLE;
- result.value.d = value;
- result.min_value.d = min_value;
- result.max_value.d = max_value;
- result.step.d = step;
- return result;
- }
- NK_LIB void
- nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
- float inc_per_pixel, const enum nk_property_filter filter)
- {
- struct nk_window *win;
- struct nk_panel *layout;
- struct nk_input *in;
- const struct nk_style *style;
- struct nk_rect bounds;
- enum nk_widget_layout_states s;
- int *state = 0;
- nk_hash hash = 0;
- char *buffer = 0;
- int *len = 0;
- int *cursor = 0;
- int *select_begin = 0;
- int *select_end = 0;
- int old_state;
- char dummy_buffer[NK_MAX_NUMBER_BUFFER];
- int dummy_state = NK_PROPERTY_DEFAULT;
- int dummy_length = 0;
- int dummy_cursor = 0;
- int dummy_select_begin = 0;
- int dummy_select_end = 0;
- NK_ASSERT(ctx);
- NK_ASSERT(ctx->current);
- NK_ASSERT(ctx->current->layout);
- if (!ctx || !ctx->current || !ctx->current->layout)
- return;
- win = ctx->current;
- layout = win->layout;
- style = &ctx->style;
- s = nk_widget(&bounds, ctx);
- if (!s) return;
- /* calculate hash from name */
- if (name[0] == '#') {
- hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
- name++; /* special number hash */
- } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
- /* check if property is currently hot item */
- if (win->property.active && hash == win->property.name) {
- buffer = win->property.buffer;
- len = &win->property.length;
- cursor = &win->property.cursor;
- state = &win->property.state;
- select_begin = &win->property.select_start;
- select_end = &win->property.select_end;
- } else {
- buffer = dummy_buffer;
- len = &dummy_length;
- cursor = &dummy_cursor;
- state = &dummy_state;
- select_begin = &dummy_select_begin;
- select_end = &dummy_select_end;
- }
- /* execute property widget */
- old_state = *state;
- ctx->text_edit.clip = ctx->clip;
- in = ((s == NK_WIDGET_ROM && !win->property.active) ||
- layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_DISABLED) ? 0 : &ctx->input;
- nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
- variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
- select_end, &style->property, filter, in, style->font, &ctx->text_edit,
- ctx->button_behavior);
- if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
- /* current property is now hot */
- win->property.active = 1;
- NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
- win->property.length = *len;
- win->property.cursor = *cursor;
- win->property.state = *state;
- win->property.name = hash;
- win->property.select_start = *select_begin;
- win->property.select_end = *select_end;
- if (*state == NK_PROPERTY_DRAG) {
- ctx->input.mouse.grab = nk_true;
- ctx->input.mouse.grabbed = nk_true;
- }
- }
- /* check if previously active property is now inactive */
- if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
- if (old_state == NK_PROPERTY_DRAG) {
- ctx->input.mouse.grab = nk_false;
- ctx->input.mouse.grabbed = nk_false;
- ctx->input.mouse.ungrab = nk_true;
- }
- win->property.select_start = 0;
- win->property.select_end = 0;
- win->property.active = 0;
- }
- }
- NK_API void
- nk_property_int(struct nk_context *ctx, const char *name,
- int min, int *val, int max, int step, float inc_per_pixel)
- {
- struct nk_property_variant variant;
- NK_ASSERT(ctx);
- NK_ASSERT(name);
- NK_ASSERT(val);
- if (!ctx || !ctx->current || !name || !val) return;
- variant = nk_property_variant_int(*val, min, max, step);
- nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
- *val = variant.value.i;
- }
- NK_API void
- nk_property_float(struct nk_context *ctx, const char *name,
- float min, float *val, float max, float step, float inc_per_pixel)
- {
- struct nk_property_variant variant;
- NK_ASSERT(ctx);
- NK_ASSERT(name);
- NK_ASSERT(val);
- if (!ctx || !ctx->current || !name || !val) return;
- variant = nk_property_variant_float(*val, min, max, step);
- nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
- *val = variant.value.f;
- }
- NK_API void
- nk_property_double(struct nk_context *ctx, const char *name,
- double min, double *val, double max, double step, float inc_per_pixel)
- {
- struct nk_property_variant variant;
- NK_ASSERT(ctx);
- NK_ASSERT(name);
- NK_ASSERT(val);
- if (!ctx || !ctx->current || !name || !val) return;
- variant = nk_property_variant_double(*val, min, max, step);
- nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
- *val = variant.value.d;
- }
- NK_API int
- nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
- int max, int step, float inc_per_pixel)
- {
- struct nk_property_variant variant;
- NK_ASSERT(ctx);
- NK_ASSERT(name);
- if (!ctx || !ctx->current || !name) return val;
- variant = nk_property_variant_int(val, min, max, step);
- nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
- val = variant.value.i;
- return val;
- }
- NK_API float
- nk_propertyf(struct nk_context *ctx, const char *name, float min,
- float val, float max, float step, float inc_per_pixel)
- {
- struct nk_property_variant variant;
- NK_ASSERT(ctx);
- NK_ASSERT(name);
- if (!ctx || !ctx->current || !name) return val;
- variant = nk_property_variant_float(val, min, max, step);
- nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
- val = variant.value.f;
- return val;
- }
- NK_API double
- nk_propertyd(struct nk_context *ctx, const char *name, double min,
- double val, double max, double step, float inc_per_pixel)
- {
- struct nk_property_variant variant;
- NK_ASSERT(ctx);
- NK_ASSERT(name);
- if (!ctx || !ctx->current || !name) return val;
- variant = nk_property_variant_double(val, min, max, step);
- nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
- val = variant.value.d;
- return val;
- }
|