Blame src-nuklear/nuklear_property.c

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