Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/interface/interface_handlers.c')
-rw-r--r--source/blender/editors/interface/interface_handlers.c876
1 files changed, 528 insertions, 348 deletions
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index fe5a5031725..6c961179c6f 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -119,6 +119,7 @@ static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to);
static void ui_but_link_add(bContext *C, uiBut *from, uiBut *to);
static int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *data, const wmEvent *event);
static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b);
+static void ui_textedit_string_set(uiBut *but, struct uiHandleButtonData *data, const char *str);
#ifdef USE_KEYNAV_LIMIT
static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event);
@@ -138,6 +139,8 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve
#define MENU_TOWARDS_MARGIN 20 /* margin in pixels */
#define MENU_TOWARDS_WIGGLE_ROOM 64 /* tolerance in pixels */
+/* drag-lock distance threshold in pixels */
+#define BUTTON_DRAGLOCK_THRESH 3
typedef enum uiButtonActivateType {
BUTTON_ACTIVATE_OVER,
@@ -280,7 +283,9 @@ typedef struct uiHandleButtonData {
wmTimer *flashtimer;
/* edited value */
- char *str, *origstr;
+ /* use 'ui_textedit_string_set' to assign new strings */
+ char *str;
+ char *origstr;
double value, origvalue, startvalue;
float vec[3], origvec[3];
#if 0 /* UNUSED */
@@ -291,14 +296,25 @@ typedef struct uiHandleButtonData {
/* tooltip */
ARegion *tooltip;
wmTimer *tooltiptimer;
+ unsigned int tooltip_force : 1;
/* auto open */
bool used_mouse;
wmTimer *autoopentimer;
/* text selection/editing */
- int maxlen, selextend;
+ /* size of 'str' (including terminator) */
+ int maxlen;
+ /* Button text selection:
+ * extension direction, selextend, inside ui_do_but_TEX */
+ enum {
+ EXTEND_NONE = 0,
+ EXTEND_LEFT = 1,
+ EXTEND_RIGHT = 2,
+ } selextend;
float selstartx;
+ /* allow to realloc str/editstr and use 'maxlen' to track alloc size (maxlen + 1) */
+ bool is_str_dynamic;
/* number editing / dragging */
/* coords are Window/uiBlock relative (depends on the button) */
@@ -381,7 +397,6 @@ static bool ui_but_is_interactive(const uiBut *but, const bool labeledit);
static bool ui_but_contains_pt(uiBut *but, float mx, float my);
static bool ui_but_contains_point_px(ARegion *ar, uiBut *but, int x, int y);
static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit);
-static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event);
static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type);
static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
static void button_activate_exit(
@@ -529,6 +544,30 @@ static bool ui_but_is_cursor_warp(uiBut *but)
return false;
}
+/**
+ * Ignore mouse movements within some horizontal pixel threshold before starting to drag
+ */
+static bool ui_but_dragedit_update_mval(uiHandleButtonData *data, int mx)
+{
+ if (mx == data->draglastx)
+ return false;
+
+ if (data->draglock) {
+ if (ABS(mx - data->dragstartx) <= BUTTON_DRAGLOCK_THRESH) {
+ return false;
+ }
+#ifdef USE_DRAG_MULTINUM
+ if (ELEM(data->multi_data.init, BUTTON_MULTI_INIT_UNSET, BUTTON_MULTI_INIT_SETUP)) {
+ return false;
+ }
+#endif
+ data->draglock = false;
+ data->dragstartx = mx; /* ignore mouse movement within drag-lock */
+ }
+
+ return true;
+}
+
static float ui_mouse_scale_warp_factor(const bool shift)
{
return shift ? 0.05f : 1.0f;
@@ -721,7 +760,7 @@ static void ui_apply_but_funcs_after(bContext *C)
if (after.opptr) {
/* free in advance to avoid leak on exit */
- opptr = *after.opptr,
+ opptr = *after.opptr;
MEM_freeN(after.opptr);
}
@@ -783,7 +822,7 @@ static void ui_apply_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data
if (but->type == UI_BTYPE_MENU)
ui_but_value_set(but, data->value);
- ui_but_update(but);
+ ui_but_update_edited(but);
ui_apply_but_func(C, but);
data->retval = but->retval;
data->applied = true;
@@ -803,7 +842,9 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
else lvalue = UI_BITBUT_SET(lvalue, but->bitnr);
ui_but_value_set(but, (double)lvalue);
- if (but->type == UI_BTYPE_ICON_TOGGLE || but->type == UI_BTYPE_ICON_TOGGLE_N) ui_but_update(but);
+ if (but->type == UI_BTYPE_ICON_TOGGLE || but->type == UI_BTYPE_ICON_TOGGLE_N) {
+ ui_but_update_edited(but);
+ }
}
else {
@@ -812,7 +853,9 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
if (ELEM(but->type, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_CHECKBOX_N)) push = !push;
ui_but_value_set(but, (double)push);
- if (but->type == UI_BTYPE_ICON_TOGGLE || but->type == UI_BTYPE_ICON_TOGGLE_N) ui_but_update(but);
+ if (but->type == UI_BTYPE_ICON_TOGGLE || but->type == UI_BTYPE_ICON_TOGGLE_N) {
+ ui_but_update_edited(but);
+ }
}
ui_apply_but_func(C, but);
@@ -830,9 +873,11 @@ static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
ui_apply_but_func(C, but);
/* states of other row buttons */
- for (bt = block->buttons.first; bt; bt = bt->next)
- if (bt != but && bt->poin == but->poin && ELEM(bt->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW))
- ui_but_update(bt);
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (bt != but && bt->poin == but->poin && ELEM(bt->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) {
+ ui_but_update_edited(bt);
+ }
+ }
data->retval = but->retval;
data->applied = true;
@@ -844,7 +889,7 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
return;
ui_but_string_set(C, but, data->str);
- ui_but_update(but);
+ ui_but_update_edited(but);
/* give butfunc a copy of the original text too.
* feature used for bone renaming, channels, etc.
@@ -875,10 +920,11 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
return;
}
}
- else
+ else {
ui_but_value_set(but, data->value);
+ }
- ui_but_update(but);
+ ui_but_update_edited(but);
ui_apply_but_func(C, but);
data->retval = but->retval;
@@ -888,7 +934,7 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
static void ui_apply_but_VEC(bContext *C, uiBut *but, uiHandleButtonData *data)
{
ui_but_v3_set(but, data->vec);
- ui_but_update(but);
+ ui_but_update_edited(but);
ui_apply_but_func(C, but);
data->retval = but->retval;
@@ -1199,7 +1245,7 @@ static bool ui_drag_toggle_set_xy_xy(
if (is_set_but != is_set) {
UI_but_execute(C, but);
if (do_check) {
- ui_but_update(but);
+ ui_but_update_edited(but);
}
changed = true;
}
@@ -2130,7 +2176,8 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
ID *id = (ID *)wmd->poin;
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- BLI_strncpy(data->str, id->name + 2, data->maxlen);
+
+ ui_textedit_string_set(but, data, id->name + 2);
if (ELEM(but->type, UI_BTYPE_SEARCH_MENU)) {
but->changed = true;
@@ -2146,12 +2193,39 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
/* ******************* copy and paste ******************** */
+static void ui_but_copy_data_path(uiBut *but, const bool full_path)
+{
+ char *id_path;
+
+ if (but->rnapoin.id.data == NULL) {
+ return;
+ }
+
+ if (full_path) {
+ if (but->rnaprop) {
+ id_path = RNA_path_full_property_py_ex(&but->rnapoin, but->rnaprop, but->rnaindex, true);
+ }
+ else {
+ id_path = RNA_path_full_struct_py(&but->rnapoin);
+ }
+ }
+ else {
+ id_path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
+ }
+
+ if (id_path) {
+ WM_clipboard_text_set(id_path, false);
+ MEM_freeN(id_path);
+ }
+}
+
/* c = copy, v = paste */
static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, char mode)
{
int buf_paste_len = 0;
const char *buf_paste = "";
bool buf_paste_alloc = false;
+ bool show_report = false; /* use to display errors parsing paste input */
if (mode == 'v' && but->lock == true) {
return;
@@ -2186,9 +2260,9 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
else if (mode == 'c') {
/* Get many decimal places, then strip trailing zeros.
- * note: too high values start to give strange results (6 or so is ok) */
+ * note: too high values start to give strange results */
char buf_copy[UI_MAX_DRAW_STR];
- ui_but_string_get_ex(but, buf_copy, sizeof(buf_copy), 6);
+ ui_but_string_get_ex(but, buf_copy, sizeof(buf_copy), UI_PRECISION_FLOAT_MAX);
BLI_str_rstrip_float_zero(buf_copy, '\0');
WM_clipboard_text_set(buf_copy, 0);
@@ -2202,6 +2276,10 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
ui_but_string_set(C, but, buf_paste);
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
+ else {
+ /* evaluating will report errors */
+ show_report = true;
+ }
}
}
@@ -2228,6 +2306,10 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
ui_but_v3_set(but, xyz);
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
+ else {
+ WM_report(RPT_ERROR, "Paste expected 3 numbers, formatted: '[n, n, n]'");
+ show_report = true;
+ }
}
}
@@ -2269,6 +2351,10 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
+ else {
+ WM_report(RPT_ERROR, "Paste expected 4 numbers, formatted: '[n, n, n, n]'");
+ show_report = true;
+ }
}
}
@@ -2288,10 +2374,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
else {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- if (ui_but_is_utf8(but))
- BLI_strncpy_utf8(active_data->str, buf_paste, active_data->maxlen);
- else
- BLI_strncpy(active_data->str, buf_paste, active_data->maxlen);
+ ui_textedit_string_set(but, active_data, buf_paste);
if (but->type == UI_BTYPE_SEARCH_MENU) {
/* else uiSearchboxData.active member is not updated [#26856] */
@@ -2366,6 +2449,10 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
if (buf_paste_alloc) {
MEM_freeN((void *)buf_paste);
}
+
+ if (show_report) {
+ WM_report_banner_show();
+ }
}
/**
@@ -2442,6 +2529,31 @@ void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR], uiBut *bu
/* ************* in-button text selection/editing ************* */
+static void ui_textedit_string_ensure_max_length(uiBut *but, uiHandleButtonData *data, int maxlen)
+{
+ BLI_assert(data->is_str_dynamic);
+ BLI_assert(data->str == but->editstr);
+
+ if (maxlen > data->maxlen) {
+ data->str = but->editstr = MEM_reallocN(data->str, sizeof(char) * maxlen);
+ data->maxlen = maxlen;
+ }
+}
+
+static void ui_textedit_string_set(uiBut *but, uiHandleButtonData *data, const char *str)
+{
+ if (data->is_str_dynamic) {
+ ui_textedit_string_ensure_max_length(but, data, strlen(str) + 1);
+ }
+
+ if (ui_but_is_utf8(but)) {
+ BLI_strncpy_utf8(data->str, str, data->maxlen);
+ }
+ else {
+ BLI_strncpy(data->str, str, data->maxlen);
+ }
+}
+
static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
{
@@ -2471,7 +2583,9 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
float startx = but->rect.xmin;
float starty_dummy = 0.0f;
- char *origstr, password_str[UI_MAX_PASSWORD_STR];
+ char password_str[UI_MAX_PASSWORD_STR];
+ /* treat 'str_last' as null terminator for str, no need to modify in-place */
+ const char *str = but->editstr, *str_last;
ui_block_to_window_fl(data->region, but->block, &startx, &starty_dummy);
@@ -2484,10 +2598,6 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
ui_but_text_password_hide(password_str, but, false);
- origstr = MEM_mallocN(sizeof(char) * data->maxlen, "ui_textedit origstr");
-
- BLI_strncpy(origstr, but->editstr, data->maxlen);
-
if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
if (but->flag & UI_HAS_ICON) {
startx += UI_DPI_ICON_SIZE / aspect;
@@ -2500,12 +2610,12 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
if (x < startx) {
int i = but->ofs;
- origstr[but->ofs] = '\0';
+ str_last = &str[but->ofs];
while (i > 0) {
- if (BLI_str_cursor_step_prev_utf8(origstr, but->ofs, &i)) {
+ if (BLI_str_cursor_step_prev_utf8(str, but->ofs, &i)) {
/* 0.25 == scale factor for less sensitivity */
- if (BLF_width(fstyle->uifont_id, origstr + i, BLF_DRAW_STR_DUMMY_MAX) > (startx - x) * 0.25f) {
+ if (BLF_width(fstyle->uifont_id, str + i, (str_last - str) - i) > (startx - x) * 0.25f) {
break;
}
}
@@ -2524,10 +2634,12 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
float cdist, cdist_prev = 0.0f;
short pos_prev;
- but->pos = pos_prev = strlen(origstr) - but->ofs;
+ str_last = &str[strlen(str)];
+
+ but->pos = pos_prev = ((str_last - str) - but->ofs);
while (true) {
- cdist = startx + BLF_width(fstyle->uifont_id, origstr + but->ofs, BLF_DRAW_STR_DUMMY_MAX);
+ cdist = startx + BLF_width(fstyle->uifont_id, str + but->ofs, (str_last - str) - but->ofs);
/* check if position is found */
if (cdist < x) {
@@ -2543,9 +2655,9 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
pos_i = but->pos;
if (but->pos <= 0) break;
- if (BLI_str_cursor_step_prev_utf8(origstr, but->ofs, &pos_i)) {
+ if (BLI_str_cursor_step_prev_utf8(str, but->ofs, &pos_i)) {
but->pos = pos_i;
- origstr[but->pos + but->ofs] = 0;
+ str_last = &str[but->pos + but->ofs];
}
else {
break; /* unlikely but possible */
@@ -2560,8 +2672,6 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
ui_but_text_password_hide(password_str, but, true);
- MEM_freeN(origstr);
-
fstyle->points = fstyle_points_prev;
}
@@ -2579,22 +2689,25 @@ static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data,
}
/**
- * This is used for both utf8 and ascii, its meant to be used for single keys,
- * notice the buffer is either copied or not, so its not suitable for pasting in
- * - campbell */
-static bool ui_textedit_type_buf(
+ * This is used for both utf8 and ascii
+ *
+ * For unicode buttons, \a buf is treated as unicode.
+ */
+static bool ui_textedit_insert_buf(
uiBut *but, uiHandleButtonData *data,
- const char *utf8_buf, int utf8_buf_len)
+ const char *buf, int buf_len)
{
- char *str;
- int len;
+ int len = strlen(data->str);
+ int len_new = len - (but->selend - but->selsta) + 1;
bool changed = false;
- str = data->str;
- len = strlen(str);
+ if (data->is_str_dynamic) {
+ ui_textedit_string_ensure_max_length(but, data, len_new + buf_len);
+ }
- if (len - (but->selend - but->selsta) + 1 <= data->maxlen) {
- int step = utf8_buf_len;
+ if (len_new <= data->maxlen) {
+ char *str = data->str;
+ size_t step = buf_len;
/* type over the current selection */
if ((but->selend - but->selsta) > 0) {
@@ -2602,9 +2715,19 @@ static bool ui_textedit_type_buf(
len = strlen(str);
}
- if (len + step < data->maxlen) {
+ if ((len + step >= data->maxlen) && (data->maxlen - (len + 1) > 0)) {
+ if (ui_but_is_utf8(but)) {
+ /* shorten 'step' to a utf8 algined size that fits */
+ BLI_strnlen_utf8_ex(buf, data->maxlen - (len + 1), &step);
+ }
+ else {
+ step = data->maxlen - (len + 1);
+ }
+ }
+
+ if (step && (len + step < data->maxlen)) {
memmove(&str[but->pos + step], &str[but->pos], (len + 1) - but->pos);
- memcpy(&str[but->pos], utf8_buf, step * sizeof(char));
+ memcpy(&str[but->pos], buf, step * sizeof(char));
but->pos += step;
changed = true;
}
@@ -2613,7 +2736,7 @@ static bool ui_textedit_type_buf(
return changed;
}
-static bool ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char ascii)
+static bool ui_textedit_insert_ascii(uiBut *but, uiHandleButtonData *data, char ascii)
{
char buf[2] = {ascii, '\0'};
@@ -2625,7 +2748,7 @@ static bool ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char as
}
/* in some cases we want to allow invalid utf8 chars */
- return ui_textedit_type_buf(but, data, buf, 1);
+ return ui_textedit_insert_buf(but, data, buf, 1);
}
static void ui_textedit_move(
@@ -2652,7 +2775,7 @@ static void ui_textedit_move(
but->pos = but->selend = but->selsta;
}
}
- data->selextend = 0;
+ data->selextend = EXTEND_NONE;
}
else {
int pos_i = but->pos;
@@ -2663,7 +2786,7 @@ static void ui_textedit_move(
/* existing selection */
if (has_sel) {
- if (data->selextend == 0) {
+ if (data->selextend == EXTEND_NONE) {
data->selextend = EXTEND_RIGHT;
}
@@ -2779,48 +2902,24 @@ enum {
static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const int mode)
{
- char *str, *pbuf;
- int x;
+ char *pbuf;
bool changed = false;
- int str_len, buf_len;
-
- str = data->str;
- str_len = strlen(str);
+ int buf_len;
/* paste */
if (mode == UI_TEXTEDIT_PASTE) {
- /* TODO, ensure UTF8 ui_but_is_utf8() - campbell */
/* extract the first line from the clipboard */
pbuf = WM_clipboard_text_get_firstline(false, &buf_len);
if (pbuf) {
- char buf[UI_MAX_DRAW_STR] = {0};
- unsigned int y;
-
- buf_len = BLI_strncpy_rlen(buf, pbuf, sizeof(buf));
-
- /* paste over the current selection */
- if ((but->selend - but->selsta) > 0) {
- ui_textedit_delete_selection(but, data);
- str_len = strlen(str);
- }
-
- for (y = 0; y < buf_len; y++) {
- /* add contents of buffer */
- if (str_len + 1 < data->maxlen) {
- for (x = data->maxlen; x > but->pos; x--)
- str[x] = str[x - 1];
- str[but->pos] = buf[y];
- but->pos++;
- str_len++;
- str[str_len] = '\0';
- }
+ if (ui_but_is_utf8(but)) {
+ buf_len -= BLI_utf8_invalid_strip(pbuf, buf_len);
}
+ ui_textedit_insert_buf(but, data, pbuf, buf_len);
+
changed = true;
- }
- if (pbuf) {
MEM_freeN(pbuf);
}
}
@@ -2830,7 +2929,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in
int sellen = but->selend - but->selsta;
char *buf = MEM_mallocN(sizeof(char) * (sellen + 1), "ui_textedit_copypaste");
- BLI_strncpy(buf, str + but->selsta, sellen + 1);
+ BLI_strncpy(buf, data->str + but->selsta, sellen + 1);
WM_clipboard_text_set(buf, 0);
MEM_freeN(buf);
@@ -2934,14 +3033,21 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
/* retrieve string */
data->maxlen = ui_but_string_get_max_length(but);
- data->str = MEM_callocN(sizeof(char) * data->maxlen + 1, "textedit str");
- ui_but_string_get(but, data->str, data->maxlen);
+ if (data->maxlen != 0) {
+ data->str = MEM_callocN(sizeof(char) * data->maxlen, "textedit str");
+ ui_but_string_get(but, data->str, data->maxlen);
+ }
+ else {
+ data->is_str_dynamic = true;
+ data->str = ui_but_string_get_dynamic(but, &data->maxlen);
+ }
if (ui_but_is_float(but) && !ui_but_is_unit(but)) {
BLI_str_rstrip_float_zero(data->str, '\0');
}
if (is_num_but) {
+ BLI_assert(data->is_str_dynamic == false);
ui_but_convert_to_unit_alt_name(but, data->str, data->maxlen);
}
@@ -2949,7 +3055,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
len = strlen(data->str);
data->origstr = BLI_strdupn(data->str, len);
- data->selextend = 0;
+ data->selextend = EXTEND_NONE;
data->selstartx = 0.0f;
/* set cursor pos to the end of the text */
@@ -2960,7 +3066,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
/* optional searchbox */
if (but->type == UI_BTYPE_SEARCH_MENU) {
- data->searchbox = ui_searchbox_create(C, data->region, but);
+ data->searchbox = but->search_create_func(C, data->region, but);
ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */
}
@@ -3323,10 +3429,10 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
}
// strcpy(utf8_buf, "12345");
- changed = ui_textedit_type_buf(but, data, event->utf8_buf, utf8_buf_len);
+ changed = ui_textedit_insert_buf(but, data, event->utf8_buf, utf8_buf_len);
}
else {
- changed = ui_textedit_type_ascii(but, data, ascii);
+ changed = ui_textedit_insert_ascii(but, data, ascii);
}
retval = WM_UI_HANDLER_BREAK;
@@ -3346,7 +3452,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
ui_textedit_delete_selection(but, data);
}
if (event->type == WM_IME_COMPOSITE_EVENT && ime_data->result_len) {
- ui_textedit_type_buf(
+ ui_textedit_insert_buf(
but, data,
ime_data->str_result,
ime_data->result_len);
@@ -3363,7 +3469,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
ui_apply_but(C, block, but, data, true);
}
else {
- ui_but_update(but);
+ ui_but_update_edited(but);
}
but->changed = true;
@@ -3936,8 +4042,12 @@ static float ui_numedit_apply_snapf(
/* snapping by 10's for float buttons is quite annoying (location, scale...),
* but allow for rotations */
if (softrange >= 21.0f) {
+ UnitSettings *unit = but->block->unit;
int unit_type = UI_but_unit_type_get(but);
- if (!ELEM(unit_type, PROP_UNIT_ROTATION)) {
+ if ((unit_type == PROP_UNIT_ROTATION) && (unit->system_rotation != USER_UNIT_ROT_RADIANS)) {
+ /* pass (degrees)*/
+ }
+ else {
softrange = 20.0f;
}
}
@@ -3993,23 +4103,10 @@ static bool ui_numedit_but_NUM(
int lvalue, temp;
bool changed = false;
const bool is_float = ui_but_is_float(but);
-
- if (mx == data->draglastx)
- return changed;
-
- /* drag-lock - prevent unwanted scroll adjustments */
- /* change value (now 3) to adjust threshold in pixels */
- if (data->draglock) {
- if (abs(mx - data->dragstartx) <= 3)
- return changed;
-#ifdef USE_DRAG_MULTINUM
- if (ELEM(data->multi_data.init, BUTTON_MULTI_INIT_UNSET, BUTTON_MULTI_INIT_SETUP)) {
- return changed;
- }
-#endif
- data->draglock = false;
- data->dragstartx = mx; /* ignore mouse movement within drag-lock */
+ /* prevent unwanted drag adjustments */
+ if (ui_but_dragedit_update_mval(data, mx) == false) {
+ return changed;
}
softmin = but->softmin;
@@ -4074,9 +4171,23 @@ static bool ui_numedit_but_NUM(
data->draglastx = mx;
}
else {
+ float non_linear_range_limit;
+ float non_linear_pixel_map;
+ float non_linear_scale;
+
/* Use a non-linear mapping of the mouse drag especially for large floats (normal behavior) */
deler = 500;
- if (!is_float) {
+ if (is_float) {
+ /* not needed for smaller float buttons */
+ non_linear_range_limit = 11.0f;
+ non_linear_pixel_map = 500.0f;
+ }
+ else {
+ /* only scale large int buttons */
+ non_linear_range_limit = 129.0f;
+ /* larger for ints, we dont need to fine tune them */
+ non_linear_pixel_map = 250.0f;
+
/* prevent large ranges from getting too out of control */
if (softrange > 600) deler = powf(softrange, 0.75f);
else if (softrange < 25) deler = 50.0;
@@ -4084,18 +4195,19 @@ static bool ui_numedit_but_NUM(
}
deler /= fac;
- if ((is_float == true) && (softrange > 11)) {
- /* non linear change in mouse input- good for high precicsion */
- data->dragf += (((float)(mx - data->draglastx)) / deler) * ((float)abs(mx - data->dragstartx) / 500.0f);
- }
- else if ((is_float == false) && (softrange > 129)) { /* only scale large int buttons */
- /* non linear change in mouse input- good for high precicsionm ints need less fine tuning */
- data->dragf += (((float)(mx - data->draglastx)) / deler) * ((float)abs(mx - data->dragstartx) / 250.0f);
+ if (softrange > non_linear_range_limit) {
+ non_linear_scale = (float)abs(mx - data->dragstartx) / non_linear_pixel_map;
}
else {
- /*no scaling */
- data->dragf += ((float)(mx - data->draglastx)) / deler;
+ non_linear_scale = 1.0f;
}
+
+ if (is_float == false) {
+ /* at minimum, moving cursor 2 pixels should change an int button. */
+ CLAMP_MIN(non_linear_scale, 0.5f * U.pixelsize);
+ }
+
+ data->dragf += (((float)(mx - data->draglastx)) / deler) * non_linear_scale;
CLAMP(data->dragf, 0.0f, 1.0f);
data->draglastx = mx;
@@ -4332,6 +4444,13 @@ static bool ui_numedit_but_SLI(
/* note, 'offs' is really from the widget drawing rounded corners see 'widget_numslider' */
float offs;
+ /* prevent unwanted drag adjustments */
+ if ((but->type != UI_BTYPE_SCROLL) &&
+ (ui_but_dragedit_update_mval(data, mx) == false))
+ {
+ return changed;
+ }
+
softmin = but->softmin;
softmax = but->softmax;
softrange = softmax - softmin;
@@ -4511,6 +4630,10 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
}
}
else {
+#ifdef USE_CONT_MOUSE_CORRECT
+ /* reset! */
+ copy_v2_fl(data->ungrab_mval, FLT_MAX);
+#endif
click = 1;
}
}
@@ -6317,10 +6440,10 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
uiLayout *layout;
uiStyle *style = UI_style_get_dpi();
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
- int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
- kmi = WM_keymap_item_find_id(km, kmi_id);
-
+ kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km);
+ BLI_assert(kmi != NULL);
+
RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
@@ -6414,7 +6537,6 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiBut *but = (uiBut *)arg1;
- UI_but_tooltip_timer_remove(C, but);
UI_popup_block_invoke(C, menu_change_shortcut, but);
}
@@ -6424,9 +6546,10 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
wmKeyMap *km;
wmKeyMapItem *kmi;
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
- int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
-
- kmi = WM_keymap_item_find_id(km, kmi_id);
+
+ kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km);
+ BLI_assert(kmi != NULL);
+
WM_keymap_remove_item(km, kmi);
but_shortcut_name_func(C, but, 0);
@@ -6435,7 +6558,6 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiBut *but = (uiBut *)arg1;
- UI_but_tooltip_timer_remove(C, but);
UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but);
}
@@ -6484,8 +6606,6 @@ static bool ui_but_menu(bContext *C, uiBut *but)
return false;
}
- UI_but_tooltip_timer_remove(C, but);
-
/* highly unlikely getting the label ever fails */
UI_but_string_info_get(C, but, &label, NULL);
@@ -6517,7 +6637,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
/* replace/delete keyfraemes */
if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframes"),
- ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1);
+ ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1);
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Single Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframes"),
@@ -6527,7 +6647,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframe"),
- ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1);
+ ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1);
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1);
}
@@ -6543,26 +6663,26 @@ static bool ui_but_menu(bContext *C, uiBut *but)
else if (is_anim) {
if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"),
- ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1);
+ ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1);
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"),
- ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1);
+ ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1);
}
}
if ((but->flag & UI_BUT_ANIMATED) && (but->rnapoin.type != &RNA_NlaStrip)) {
if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
- ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 1);
+ ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1);
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"),
ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0);
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
- ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 1);
+ ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1);
}
}
@@ -6572,13 +6692,13 @@ static bool ui_but_menu(bContext *C, uiBut *but)
if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"),
- ICON_NONE, "ANIM_OT_driver_button_remove", "all", 1);
+ ICON_X, "ANIM_OT_driver_button_remove", "all", 1);
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"),
ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0);
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"),
- ICON_NONE, "ANIM_OT_driver_button_remove", "all", 1);
+ ICON_X, "ANIM_OT_driver_button_remove", "all", 1);
}
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"),
@@ -6595,14 +6715,14 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemS(layout);
if (is_array_component) {
- uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Drivers"),
- ICON_NONE, "ANIM_OT_driver_button_add", "all", 1);
- uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single Driver"),
- ICON_NONE, "ANIM_OT_driver_button_add", "all", 0);
+ uiItemMenuEnumO(layout, C, "ANIM_OT_driver_button_add", "mapping_type",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Drivers"),
+ ICON_DRIVER);
}
else {
- uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
- ICON_NONE, "ANIM_OT_driver_button_add", "all", 1);
+ uiItemMenuEnumO(layout, C, "ANIM_OT_driver_button_add", "mapping_type",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
+ ICON_DRIVER);
}
if (ANIM_driver_can_paste()) {
@@ -6618,7 +6738,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"),
- ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 1);
+ ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1);
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single to Keying Set"),
ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 0);
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
@@ -6626,7 +6746,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Keying Set"),
- ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 1);
+ ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1);
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
ICON_NONE, "ANIM_OT_keyingset_button_remove");
}
@@ -6641,23 +6761,32 @@ static bool ui_but_menu(bContext *C, uiBut *but)
if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"),
- ICON_NONE, "UI_OT_reset_default_button", "all", 1);
+ ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1);
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"),
ICON_NONE, "UI_OT_reset_default_button", "all", 0);
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"),
- ICON_NONE, "UI_OT_reset_default_button", "all", 1);
+ ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1);
}
if (is_editable /*&& is_idprop*/ && is_set) {
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"),
ICON_NONE, "UI_OT_unset_property_button");
}
+ if (is_array_component) {
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy All To Selected"),
+ ICON_NONE, "UI_OT_copy_to_selected_button", "all", true);
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Single To Selected"),
+ ICON_NONE, "UI_OT_copy_to_selected_button", "all", false);
+ }
+ else {
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy To Selected"),
+ ICON_NONE, "UI_OT_copy_to_selected_button", "all", true);
+ }
+
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"),
ICON_NONE, "UI_OT_copy_data_path_button");
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy To Selected"),
- ICON_NONE, "UI_OT_copy_to_selected_button");
uiItemS(layout);
}
@@ -6669,29 +6798,39 @@ static bool ui_but_menu(bContext *C, uiBut *but)
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
int w = uiLayoutGetWidth(layout);
wmKeyMap *km;
- wmKeyMapItem *kmi = NULL;
- int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
-
- if (kmi_id)
- kmi = WM_keymap_item_find_id(km, kmi_id);
-
- /* keyboard shortcuts */
- if ((kmi) && ISKEYBOARD(kmi->type)) {
+ /* We want to know if this op has a shortcut, be it hotkey or not. */
+ wmKeyMapItem *kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, false, &km);
+
+ /* We do have a shortcut, but only keyboard ones are editbale that way... */
+ if (kmi) {
+ if (ISKEYBOARD(kmi->type)) {
+#if 0 /* would rather use a block but, but gets weirdly positioned... */
+ uiDefBlockBut(block, menu_change_shortcut, but, "Change Shortcut",
+ 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, "");
+#endif
- /* would rather use a block but, but gets weirdly positioned... */
- //uiDefBlockBut(block, menu_change_shortcut, but, "Change Shortcut", 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, "");
-
- but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but2, popup_change_shortcut_func, but, NULL);
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_HAND,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"),
+ 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ UI_but_func_set(but2, popup_change_shortcut_func, but, NULL);
- but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but2, remove_shortcut_func, but, NULL);
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_NONE,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
+ 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ UI_but_func_set(but2, remove_shortcut_func, but, NULL);
+ }
+ else {
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_HAND, IFACE_("Non-Keyboard Shortcut"),
+ 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0,
+ TIP_("Only keyboard shortcuts can be edited that way, "
+ "please use User Preferences otherwise"));
+ UI_but_flag_enable(but2, UI_BUT_DISABLED);
+ }
}
/* only show 'add' if there's a suitable key map for it to go in */
else if (WM_keymap_guess_opname(C, but->optype->idname)) {
- but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"),
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_HAND,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
UI_but_func_set(but2, popup_add_shortcut_func, but, NULL);
}
@@ -6714,7 +6853,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
if (UI_but_online_manual_id(but, buf, sizeof(buf))) {
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
- ICON_NONE, "WM_OT_doc_view_manual_ui_context");
+ ICON_URL, "WM_OT_doc_view_manual_ui_context");
WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
RNA_string_set(&ptr_props, "doc_id", buf);
@@ -6732,6 +6871,11 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
}
+ if (but->optype) {
+ uiItemO(layout, NULL,
+ ICON_NONE, "UI_OT_copy_python_command_button");
+ }
+
/* perhaps we should move this into (G.debug & G_DEBUG) - campbell */
if (ui_block_is_menu(but->block) == false) {
uiItemFullO(layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0);
@@ -6768,6 +6912,12 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
}
+ /* special case, copy-data-path */
+ if ((event->type == CKEY) && event->shift) {
+ ui_but_copy_data_path(but, event->alt != 0);
+ return WM_UI_HANDLER_BREAK;
+ }
+
ui_but_copy_paste(C, but, data, (event->type == CKEY) ? 'c' : 'v');
return WM_UI_HANDLER_BREAK;
}
@@ -6832,12 +6982,12 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle drivers */
else if ((event->type == DKEY) &&
- !IS_EVENT_MOD(event, shift, ctrl, oskey) &&
+ !IS_EVENT_MOD(event, shift, oskey) &&
(event->val == KM_PRESS))
{
if (event->alt)
ui_but_anim_remove_driver(C);
- else
+ else if (event->ctrl)
ui_but_anim_add_driver(C);
ED_region_tag_redraw(data->region);
@@ -6875,7 +7025,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
/* this should become disabled button .. */
if (but->lock == true) {
if (but->lockstr) {
- WM_report(C, RPT_INFO, but->lockstr);
+ WM_report(RPT_INFO, but->lockstr);
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
@@ -7360,7 +7510,7 @@ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, c
return butover;
}
-static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event)
+uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event)
{
return ui_but_find_mouse_over_ex(ar, event->x, event->y, event->ctrl != 0);
}
@@ -7408,6 +7558,20 @@ static bool button_modal_state(uiHandleButtonState state)
BUTTON_STATE_MENU_OPEN);
}
+/**
+ * Recreate tooltip (use to update dynamic tips)
+ */
+void UI_but_tooltip_refresh(bContext *C, uiBut *but)
+{
+ uiHandleButtonData *data;
+
+ data = but->active;
+ if (data && data->tooltip) {
+ ui_tooltip_free(C, data->tooltip);
+ data->tooltip = ui_tooltip_create(C, data->region, but);
+ }
+}
+
/* removes tooltip timer from active but (meaning tooltip is disabled until it's reenabled again) */
void UI_but_tooltip_timer_remove(bContext *C, uiBut *but)
{
@@ -7444,7 +7608,7 @@ static void button_tooltip_timer_reset(bContext *C, uiBut *but)
data->tooltiptimer = NULL;
}
- if ((U.flag & USER_TOOLTIPS) || (but->flag & UI_BUT_TIP_FORCE)) {
+ if ((U.flag & USER_TOOLTIPS) || (data->tooltip_force)) {
if (!but->block->tooltipdisabled) {
if (!wm->drags.first) {
data->tooltiptimer = WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY);
@@ -7513,8 +7677,14 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
else if (data->state == BUTTON_STATE_NUM_EDITING) {
ui_numedit_end(but, data);
- if (but->flag & UI_BUT_DRIVEN)
- WM_report(C, RPT_INFO, "Can't edit driven number value, see graph editor for the driver setup.");
+ if (but->flag & UI_BUT_DRIVEN) {
+ /* Only warn when editing stepping/dragging the value.
+ * No warnings should show for editing driver expressions though!
+ */
+ if (state != BUTTON_STATE_TEXT_EDITING) {
+ WM_report(RPT_INFO, "Can't edit driven number value, see graph editor for the driver setup.");
+ }
+ }
if (ui_but_is_cursor_warp(but)) {
@@ -7604,7 +7774,9 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
/* XXX curve is temp */
}
else {
- data->interactive = true;
+ if ((but->flag & UI_BUT_UPDATE_DELAY) == 0) {
+ data->interactive = true;
+ }
}
data->state = BUTTON_STATE_INIT;
@@ -7964,14 +8136,12 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
if (event->type == MOUSEMOVE) {
but = ui_but_find_mouse_over(ar, event);
if (but) {
- if (event->alt) {
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+
+ if (event->alt && but->active) {
/* display tooltips if holding alt on mouseover when tooltips are off in prefs */
- but->flag |= UI_BUT_TIP_FORCE;
+ but->active->tooltip_force = true;
}
- else {
- but->flag &= ~UI_BUT_TIP_FORCE;
- }
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
}
}
else if (event->type == EVT_BUT_OPEN) {
@@ -8145,7 +8315,6 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
case MOUSEMOVE:
if (ELEM(but->type, UI_BTYPE_LINK, UI_BTYPE_INLINK)) {
- ARegion *ar = data->region;
but->flag |= UI_SELECT;
ui_do_button(C, block, but, event);
ED_region_tag_redraw(ar);
@@ -9318,6 +9487,9 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
is_click_style = (block->pie_data.flags & UI_PIE_CLICK_STYLE);
+ /* if there's an active modal button, don't check events or outside, except for search menu */
+ but = ui_but_find_active_in_region(ar);
+
if (menu->scrolltimer == NULL) {
menu->scrolltimer =
WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, PIE_MENU_INTERVAL);
@@ -9333,210 +9505,214 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
dist = ui_block_calc_pie_segment(block, event_xy);
- if (event->type == TIMER) {
- if (event->customdata == menu->scrolltimer) {
- /* deactivate initial direction after a while */
- if (duration > 0.01 * U.pie_initial_timeout) {
- block->pie_data.flags &= ~UI_PIE_INITIAL_DIRECTION;
- }
+ if (but && button_modal_state(but->active->state)) {
+ retval = ui_handle_menu_button(C, event, menu);
+ }
+ else {
+ if (event->type == TIMER) {
+ if (event->customdata == menu->scrolltimer) {
+ /* deactivate initial direction after a while */
+ if (duration > 0.01 * U.pie_initial_timeout) {
+ block->pie_data.flags &= ~UI_PIE_INITIAL_DIRECTION;
+ }
- /* handle animation */
- if (!(block->pie_data.flags & UI_PIE_ANIMATION_FINISHED)) {
- uiBut *but;
- double final_time = 0.01 * U.pie_animation_timeout;
- float fac = duration / final_time;
- float pie_radius = U.pie_menu_radius * UI_DPI_FAC;
+ /* handle animation */
+ if (!(block->pie_data.flags & UI_PIE_ANIMATION_FINISHED)) {
+ double final_time = 0.01 * U.pie_animation_timeout;
+ float fac = duration / final_time;
+ float pie_radius = U.pie_menu_radius * UI_DPI_FAC;
- if (fac > 1.0f) {
- fac = 1.0f;
- block->pie_data.flags |= UI_PIE_ANIMATION_FINISHED;
- }
+ if (fac > 1.0f) {
+ fac = 1.0f;
+ block->pie_data.flags |= UI_PIE_ANIMATION_FINISHED;
+ }
- for (but = block->buttons.first; but; but = but->next) {
- if (but->pie_dir != UI_RADIAL_NONE) {
- float vec[2];
- float center[2];
-
- ui_but_pie_dir(but->pie_dir, vec);
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->pie_dir != UI_RADIAL_NONE) {
+ float vec[2];
+ float center[2];
- center[0] = (vec[0] > 0.01f) ? 0.5f : ((vec[0] < -0.01f) ? -0.5f : 0.0f);
- center[1] = (vec[1] > 0.99f) ? 0.5f : ((vec[1] < -0.99f) ? -0.5f : 0.0f);
+ ui_but_pie_dir(but->pie_dir, vec);
- center[0] *= BLI_rctf_size_x(&but->rect);
- center[1] *= BLI_rctf_size_y(&but->rect);
-
- mul_v2_fl(vec, pie_radius);
- add_v2_v2(vec, center);
- mul_v2_fl(vec, fac);
- add_v2_v2(vec, block->pie_data.pie_center_spawned);
-
- BLI_rctf_recenter(&but->rect, vec[0], vec[1]);
+ center[0] = (vec[0] > 0.01f) ? 0.5f : ((vec[0] < -0.01f) ? -0.5f : 0.0f);
+ center[1] = (vec[1] > 0.99f) ? 0.5f : ((vec[1] < -0.99f) ? -0.5f : 0.0f);
+
+ center[0] *= BLI_rctf_size_x(&but->rect);
+ center[1] *= BLI_rctf_size_y(&but->rect);
+
+ mul_v2_fl(vec, pie_radius);
+ add_v2_v2(vec, center);
+ mul_v2_fl(vec, fac);
+ add_v2_v2(vec, block->pie_data.pie_center_spawned);
+
+ BLI_rctf_recenter(&but->rect, vec[0], vec[1]);
+ }
}
- }
- block->pie_data.alphafac = fac;
+ block->pie_data.alphafac = fac;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
+ }
}
- }
- /* check pie velociy here if gesture has ended */
- if (block->pie_data.flags & UI_PIE_GESTURE_END_WAIT) {
- float len_sq = 10;
+ /* check pie velociy here if gesture has ended */
+ if (block->pie_data.flags & UI_PIE_GESTURE_END_WAIT) {
+ float len_sq = 10;
- /* use a time threshold to ensure we leave time to the mouse to move */
- if (duration - block->pie_data.duration_gesture > 0.02) {
- len_sq = len_squared_v2v2(event_xy, block->pie_data.last_pos);
- copy_v2_v2(block->pie_data.last_pos, event_xy);
- block->pie_data.duration_gesture = duration;
- }
+ /* use a time threshold to ensure we leave time to the mouse to move */
+ if (duration - block->pie_data.duration_gesture > 0.02) {
+ len_sq = len_squared_v2v2(event_xy, block->pie_data.last_pos);
+ copy_v2_v2(block->pie_data.last_pos, event_xy);
+ block->pie_data.duration_gesture = duration;
+ }
- if (len_sq < 1.0f) {
- uiBut *but = ui_but_find_active_in_region(menu->region);
+ if (len_sq < 1.0f) {
+ but = ui_but_find_active_in_region(menu->region);
- if (but) {
- return ui_but_pie_menu_apply(C, menu, but, true);
+ if (but) {
+ return ui_but_pie_menu_apply(C, menu, but, true);
+ }
}
}
}
- }
- if (event->type == block->pie_data.event && !is_click_style) {
- if (event->val != KM_RELEASE) {
- ui_handle_menu_button(C, event, menu);
+ if (event->type == block->pie_data.event && !is_click_style) {
+ if (event->val != KM_RELEASE) {
+ ui_handle_menu_button(C, event, menu);
- if (len_squared_v2v2(event_xy, block->pie_data.pie_center_init) > PIE_CLICK_THRESHOLD_SQ) {
- block->pie_data.flags |= UI_PIE_DRAG_STYLE;
- }
- /* why redraw here? It's simple, we are getting many double click events here.
- * Those operate like mouse move events almost */
- ED_region_tag_redraw(ar);
- }
- else {
- /* distance from initial point */
- if (!(block->pie_data.flags & UI_PIE_DRAG_STYLE)) {
- block->pie_data.flags |= UI_PIE_CLICK_STYLE;
+ if (len_squared_v2v2(event_xy, block->pie_data.pie_center_init) > PIE_CLICK_THRESHOLD_SQ) {
+ block->pie_data.flags |= UI_PIE_DRAG_STYLE;
+ }
+ /* why redraw here? It's simple, we are getting many double click events here.
+ * Those operate like mouse move events almost */
+ ED_region_tag_redraw(ar);
}
else {
- uiBut *but = ui_but_find_active_in_region(menu->region);
-
- if (but && (U.pie_menu_confirm > 0) &&
- (dist >= U.pie_menu_threshold + U.pie_menu_confirm))
- {
- if (but)
- return ui_but_pie_menu_apply(C, menu, but, true);
+ /* distance from initial point */
+ if (!(block->pie_data.flags & UI_PIE_DRAG_STYLE)) {
+ block->pie_data.flags |= UI_PIE_CLICK_STYLE;
}
+ else {
+ but = ui_but_find_active_in_region(menu->region);
- retval = ui_but_pie_menu_apply(C, menu, but, true);
+ if (but && (U.pie_menu_confirm > 0) &&
+ (dist >= U.pie_menu_threshold + U.pie_menu_confirm))
+ {
+ if (but)
+ return ui_but_pie_menu_apply(C, menu, but, true);
+ }
+
+ retval = ui_but_pie_menu_apply(C, menu, but, true);
+ }
}
}
- }
- else {
- /* direction from numpad */
- RadialDirection num_dir = UI_RADIAL_NONE;
+ else {
+ /* direction from numpad */
+ RadialDirection num_dir = UI_RADIAL_NONE;
- switch (event->type) {
- case MOUSEMOVE:
- if (!is_click_style) {
- float len_sq = len_squared_v2v2(event_xy, block->pie_data.pie_center_init);
+ switch (event->type) {
+ case MOUSEMOVE:
+ if (!is_click_style) {
+ float len_sq = len_squared_v2v2(event_xy, block->pie_data.pie_center_init);
- /* here we use the initial position explicitly */
- if (len_sq > PIE_CLICK_THRESHOLD_SQ) {
- block->pie_data.flags |= UI_PIE_DRAG_STYLE;
- }
+ /* here we use the initial position explicitly */
+ if (len_sq > PIE_CLICK_THRESHOLD_SQ) {
+ block->pie_data.flags |= UI_PIE_DRAG_STYLE;
+ }
- /* here instead, we use the offset location to account for the initial direction timeout */
- if ((U.pie_menu_confirm > 0) &&
- (dist >= U.pie_menu_threshold + U.pie_menu_confirm))
- {
- block->pie_data.flags |= UI_PIE_GESTURE_END_WAIT;
- copy_v2_v2(block->pie_data.last_pos, event_xy);
- block->pie_data.duration_gesture = duration;
+ /* here instead, we use the offset location to account for the initial direction timeout */
+ if ((U.pie_menu_confirm > 0) &&
+ (dist >= U.pie_menu_threshold + U.pie_menu_confirm))
+ {
+ block->pie_data.flags |= UI_PIE_GESTURE_END_WAIT;
+ copy_v2_v2(block->pie_data.last_pos, event_xy);
+ block->pie_data.duration_gesture = duration;
+ }
}
- }
- ui_handle_menu_button(C, event, menu);
-
- /* mouse move should always refresh the area for pie menus */
- ED_region_tag_redraw(ar);
- break;
+ ui_handle_menu_button(C, event, menu);
- case LEFTMOUSE:
- if (is_click_style) {
- if (block->pie_data.flags & UI_PIE_INVALID_DIR) {
- menu->menuretval = UI_RETURN_CANCEL;
- }
- else {
- retval = ui_handle_menu_button(C, event, menu);
+ /* mouse move should always refresh the area for pie menus */
+ ED_region_tag_redraw(ar);
+ break;
+
+ case LEFTMOUSE:
+ if (is_click_style) {
+ if (block->pie_data.flags & UI_PIE_INVALID_DIR) {
+ menu->menuretval = UI_RETURN_CANCEL;
+ }
+ else {
+ retval = ui_handle_menu_button(C, event, menu);
+ }
}
- }
- break;
+ break;
- case ESCKEY:
- case RIGHTMOUSE:
- menu->menuretval = UI_RETURN_CANCEL;
- break;
+ case ESCKEY:
+ case RIGHTMOUSE:
+ menu->menuretval = UI_RETURN_CANCEL;
+ break;
- case AKEY:
- case BKEY:
- case CKEY:
- case DKEY:
- case EKEY:
- case FKEY:
- case GKEY:
- case HKEY:
- case IKEY:
- case JKEY:
- case KKEY:
- case LKEY:
- case MKEY:
- case NKEY:
- case OKEY:
- case PKEY:
- case QKEY:
- case RKEY:
- case SKEY:
- case TKEY:
- case UKEY:
- case VKEY:
- case WKEY:
- case XKEY:
- case YKEY:
- case ZKEY:
- {
- if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
- !IS_EVENT_MOD(event, shift, ctrl, oskey))
+ case AKEY:
+ case BKEY:
+ case CKEY:
+ case DKEY:
+ case EKEY:
+ case FKEY:
+ case GKEY:
+ case HKEY:
+ case IKEY:
+ case JKEY:
+ case KKEY:
+ case LKEY:
+ case MKEY:
+ case NKEY:
+ case OKEY:
+ case PKEY:
+ case QKEY:
+ case RKEY:
+ case SKEY:
+ case TKEY:
+ case UKEY:
+ case VKEY:
+ case WKEY:
+ case XKEY:
+ case YKEY:
+ case ZKEY:
{
- for (but = block->buttons.first; but; but = but->next) {
- if (but->menu_key == event->type) {
- ui_but_pie_button_activate(C, but, menu);
+ if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
+ !IS_EVENT_MOD(event, shift, ctrl, oskey))
+ {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->menu_key == event->type) {
+ ui_but_pie_button_activate(C, but, menu);
+ }
}
}
+ break;
}
- break;
- }
#define CASE_NUM_TO_DIR(n, d) \
case (ZEROKEY + n): case (PAD0 + n): \
{ if (num_dir == UI_RADIAL_NONE) num_dir = d; } (void)0
- CASE_NUM_TO_DIR(1, UI_RADIAL_SW);
- CASE_NUM_TO_DIR(2, UI_RADIAL_S);
- CASE_NUM_TO_DIR(3, UI_RADIAL_SE);
- CASE_NUM_TO_DIR(4, UI_RADIAL_W);
- CASE_NUM_TO_DIR(6, UI_RADIAL_E);
- CASE_NUM_TO_DIR(7, UI_RADIAL_NW);
- CASE_NUM_TO_DIR(8, UI_RADIAL_N);
- CASE_NUM_TO_DIR(9, UI_RADIAL_NE);
- {
- but = ui_block_pie_dir_activate(block, event, num_dir);
- retval = ui_but_pie_button_activate(C, but, menu);
- break;
- }
+ CASE_NUM_TO_DIR(1, UI_RADIAL_SW);
+ CASE_NUM_TO_DIR(2, UI_RADIAL_S);
+ CASE_NUM_TO_DIR(3, UI_RADIAL_SE);
+ CASE_NUM_TO_DIR(4, UI_RADIAL_W);
+ CASE_NUM_TO_DIR(6, UI_RADIAL_E);
+ CASE_NUM_TO_DIR(7, UI_RADIAL_NW);
+ CASE_NUM_TO_DIR(8, UI_RADIAL_N);
+ CASE_NUM_TO_DIR(9, UI_RADIAL_NE);
+ {
+ but = ui_block_pie_dir_activate(block, event, num_dir);
+ retval = ui_but_pie_button_activate(C, but, menu);
+ break;
+ }
#undef CASE_NUM_TO_DIR
- default:
- retval = ui_handle_menu_button(C, event, menu);
- break;
+ default:
+ retval = ui_handle_menu_button(C, event, menu);
+ break;
+ }
}
}
@@ -9783,10 +9959,14 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata)
menu_region = CTX_wm_menu(C);
CTX_wm_menu_set(C, menu->region);
- if (event->type == EVT_DROP) {
- /* if we're handling drop event we'll want it to be handled by popup callee as well,
- * so it'll be possible to perform such operations as opening .blend files by dropping
- * them into blender even if there's opened popup like splash screen (sergey)
+ if (event->type == EVT_DROP || event->val == KM_DBL_CLICK) {
+ /* EVT_DROP:
+ * If we're handling drop event we'll want it to be handled by popup callee as well,
+ * so it'll be possible to perform such operations as opening .blend files by dropping
+ * them into blender, even if there's opened popup like splash screen (sergey).
+ * KM_DBL_CLICK:
+ * Continue in case of double click so wm_handlers_do calls handler again with KM_PRESS
+ * event. This is needed to ensure correct button handling for fast clicking (T47532).
*/
retval = WM_UI_HANDLER_CONTINUE;