UI List: ctrl click on names in list can be used for renaming.
authorBastien Montagne <montagne29@wanadoo.fr>
Sat, 23 Nov 2013 17:43:23 +0000 (18:43 +0100)
committerBastien Montagne <montagne29@wanadoo.fr>
Sat, 23 Nov 2013 17:43:23 +0000 (18:43 +0100)
Summary:
More information here:
http://lists.blender.org/pipermail/bf-committers/2013-November/042113.html

Reviewers: brecht

Reviewed By: brecht

CC: mont29
Differential Revision: http://developer.blender.org/D8

release/scripts/startup/bl_ui/properties_data_mesh.py
source/blender/editors/include/UI_interface.h
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_intern.h
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/interface_widgets.c
source/blender/makesrna/intern/rna_ui_api.c
source/blenderplayer/bad_level_call_stubs/stubs.c

index f59d479c50919ca54b753790e3ead97232d46b35..0ec22323092d4f4b31487548772a7cfbcd5ab063 100644 (file)
@@ -64,7 +64,7 @@ class MESH_UL_vgroups(UIList):
         # assert(isinstance(item, bpy.types.VertexGroup)
         vgroup = item
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
-            layout.label(text=vgroup.name, translate=False, icon_value=icon)
+            layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
             icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
             layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
         elif self.layout_type in {'GRID'}:
index 0c37d35a93b41ff1e3cc7f29d0bb87243cbf1686..0786f2667355a4ef322a26390635cfd891c3bd5b 100644 (file)
@@ -432,7 +432,6 @@ void    uiButSetDragValue(uiBut *but);
 void    uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale);
 
 int     UI_but_active_drop_name(struct bContext *C);
-struct uiBut  *ui_but_find_mouse_over(struct ARegion *ar, int x, int y);
 
 void    uiButSetFlag(uiBut *but, int flag);
 void    uiButClearFlag(uiBut *but, int flag);
index db53809c7c4585e0dc39501d7a6517400b2e4f5a..c871fdcf7465846f7a68f8447480d7df3672e838 100644 (file)
@@ -235,8 +235,10 @@ typedef struct uiAfterFunc {
 
 
 
+static bool ui_is_but_interactive(uiBut *but, const bool ctrl);
 static bool ui_but_contains_pt(uiBut *but, int mx, int my);
 static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y);
+static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event, int x, int y);
 static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
 static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userdata);
 static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type);
@@ -728,7 +730,9 @@ static bool ui_drag_toggle_set_xy_xy(bContext *C, ARegion *ar, const bool is_set
                ui_window_to_block_fl(ar, block, &xy_b_block[0], &xy_b_block[1]);
 
                for (but = block->buttons.first; but; but = but->next) {
-                       if (ui_is_but_interactive(but)) {
+                       /* Note: ctrl is always true here because (at least for now) we always want to consider text control
+                        *       in this case, even when not embossed. */
+                       if (ui_is_but_interactive(but, true)) {
                                if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) {
 
                                        /* execute the button */
@@ -754,7 +758,7 @@ static bool ui_drag_toggle_set_xy_xy(bContext *C, ARegion *ar, const bool is_set
        return change;
 }
 
-static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const int xy_input[2])
+static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const wmEvent *event)
 {
        ARegion *ar = CTX_wm_region(C);
        bool do_draw = false;
@@ -768,7 +772,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const
         */
        if (drag_info->is_init == false) {
                /* first store the buttons original coords */
-               uiBut *but = ui_but_find_mouse_over(ar, xy_input[0], xy_input[1]);
+               uiBut *but = ui_but_find_mouse_over(ar, event, 0, 0);
 
                if (but) {
                        if (but->flag & UI_BUT_DRAG_LOCK) {
@@ -796,8 +800,8 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const
        /* done with axis locking */
 
 
-       xy[0] = (drag_info->xy_lock[0] == false) ? xy_input[0] : drag_info->xy_last[0];
-       xy[1] = (drag_info->xy_lock[1] == false) ? xy_input[1] : drag_info->xy_last[1];
+       xy[0] = (drag_info->xy_lock[0] == false) ? event->x : drag_info->xy_last[0];
+       xy[1] = (drag_info->xy_lock[1] == false) ? event->y : drag_info->xy_last[1];
 
 
        /* touch all buttons between last mouse coord and this one */
@@ -831,7 +835,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
                }
                case MOUSEMOVE:
                {
-                       ui_drag_toggle_set(C, drag_info, &event->x);
+                       ui_drag_toggle_set(C, drag_info, event);
                        break;
                }
        }
@@ -839,7 +843,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
        if (done) {
                wmWindow *win = CTX_wm_window(C);
                ARegion *ar = CTX_wm_region(C);
-               uiBut *but = ui_but_find_mouse_over(ar, drag_info->xy_init[0], drag_info->xy_init[1]);
+               uiBut *but = ui_but_find_mouse_over(ar, NULL, drag_info->xy_init[0], drag_info->xy_init[1]);
 
                if (but) {
                        ui_apply_undo(but);
@@ -5883,8 +5887,9 @@ static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
 
 /**
  * Can we mouse over the button or is it hidden/disabled/layout.
+ * Note: ctrl is kind of a hack currently, so that non-embossed TEX button behaves as a label when ctrl is not pressed.
  */
-bool ui_is_but_interactive(uiBut *but)
+static bool ui_is_but_interactive(uiBut *but, const bool ctrl)
 {
        /* note, LABEL is included for highlights, this allows drags */
        if ((but->type == LABEL) && but->dragpoin == NULL)
@@ -5895,6 +5900,8 @@ bool ui_is_but_interactive(uiBut *but)
                return false;
        if (but->flag & UI_SCROLLED)
                return false;
+       if ((but->type == TEX) && (but->dt & UI_EMBOSSN) && !ctrl)
+               return false;
 
        return true;
 }
@@ -5906,11 +5913,19 @@ bool ui_is_but_search_unlink_visible(uiBut *but)
                (but->drawstr[0] != '\0'));
 }
 
-uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
+/* x and y are only used in case event is NULL... */
+static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event, int x, int y)
 {
        uiBlock *block;
        uiBut *but, *butover = NULL;
        int mx, my;
+       bool ctrl = true;
+
+       if (event) {
+               x = event->x;
+               y = event->y;
+               ctrl = event->ctrl;
+       }
 
 //     if (!win->active)
 //             return NULL;
@@ -5923,7 +5938,7 @@ uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
                ui_window_to_block(ar, block, &mx, &my);
 
                for (but = block->buttons.first; but; but = but->next) {
-                       if (ui_is_but_interactive(but)) {
+                       if (ui_is_but_interactive(but, ctrl)) {
                                if (ui_but_contains_pt(but, mx, my)) {
                                        butover = but;
                                }
@@ -6493,7 +6508,7 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
        uiBut *but;
 
        if (event->type == MOUSEMOVE) {
-               but = ui_but_find_mouse_over(ar, event->x, event->y);
+               but = ui_but_find_mouse_over(ar, event, 0, 0);
                if (but) {
                        button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
                }
@@ -6585,7 +6600,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
                                        data->cancel = TRUE;
                                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                                }
-                               else if (ui_but_find_mouse_over(ar, event->x, event->y) != but) {
+                               else if (ui_but_find_mouse_over(ar, event, 0, 0) != but) {
                                        data->cancel = TRUE;
                                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                                }
@@ -6697,7 +6712,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
                                        }
                                }
 
-                               bt = ui_but_find_mouse_over(ar, event->x, event->y);
+                               bt = ui_but_find_mouse_over(ar, event, 0, 0);
                                
                                if (bt && bt->active != data) {
                                        if (but->type != COLOR) {  /* exception */
@@ -6737,7 +6752,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
                         * it stays active while the mouse is over it.
                         * This avoids adding mousemoves, see: [#33466] */
                        if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT)) {
-                               if (ui_but_find_mouse_over(ar, event->x, event->y) == but) {
+                               if (ui_but_find_mouse_over(ar, event, 0, 0) == but) {
                                        button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
                                }
                        }
@@ -6778,7 +6793,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
                        break;
                }
        }
-       if (dragbut && dragbut == ui_but_find_mouse_over(ar, event->x, event->y)) {
+       if (dragbut && dragbut == ui_but_find_mouse_over(ar, event, 0, 0)) {
                is_over_dragbut = true;
        }
 
index 30d8535e4710dfbf5e754fc6a0d787c462f10394..9287385a329af9934f15c1cc88a0f39b08ef3c3a 100644 (file)
@@ -54,6 +54,9 @@ struct ImBuf;
 
 /* ****************** general defines ************** */
 
+#define RNA_NO_INDEX    -1
+#define RNA_ENUM_VALUE  -2
+
 /* visual types for drawing */
 /* for time being separated from functional types */
 typedef enum {
@@ -403,7 +406,6 @@ extern bool ui_is_but_bool(uiBut *but);
 extern bool ui_is_but_unit(uiBut *but);
 extern bool ui_is_but_rna_valid(uiBut *but);
 extern bool ui_is_but_utf8(uiBut *but);
-extern bool ui_is_but_interactive(uiBut *but);
 extern bool ui_is_but_search_unlink_visible(uiBut *but);
 
 extern int  ui_is_but_push_ex(uiBut *but, double *value);
index b85c30b8710ad3059f7fb7076bb6745790445880..346a54cf4eb248fbacfbc1af8f7ca2f23f23d5f2 100644 (file)
 
 /************************ Structs and Defines *************************/
 
-#define RNA_NO_INDEX    -1
-#define RNA_ENUM_VALUE  -2
-
-
 // #define USE_OP_RESET_BUT  // we may want to make this optional, disable for now.
 
 #define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement)                 \
@@ -632,13 +628,11 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
 
        if (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
                uiBlockSetCurLayout(block, uiLayoutRow(sub, TRUE));
-               uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w - UI_UNIT_X, h);
+               but = uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w - UI_UNIT_X, h);
 
                /* BUTTONS_OT_file_browse calls uiFileBrowseContextProperty */
-               but = uiDefIconButO(block, BUT, subtype == PROP_DIRPATH ?
-                                   "BUTTONS_OT_directory_browse" :
-                                   "BUTTONS_OT_file_browse",
-                                   WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL);
+               uiDefIconButO(block, BUT, subtype == PROP_DIRPATH ? "BUTTONS_OT_directory_browse" : "BUTTONS_OT_file_browse",
+                             WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL);
        }
        else if (flag & UI_ITEM_R_EVENT) {
                uiDefButR_prop(block, KEYEVT, 0, name, x, y, w, h, ptr, prop, index, 0, 0, -1, -1, NULL);
@@ -1142,7 +1136,7 @@ static void ui_item_rna_size(uiLayout *layout, const char *name, int icon, Point
 void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int flag, const char *name, int icon)
 {
        uiBlock *block = layout->root->block;
-       uiBut *but;
+       uiBut *but = NULL;
        PropertyType type;
        char namestr[UI_MAX_NAME_STR];
        int len, is_array, w, h, slider, toggle, expand, icon_only, no_bg;
@@ -1231,7 +1225,12 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
                if (layout->redalert)
                        uiButSetFlag(but, UI_BUT_REDALERT);
        }
-       
+
+       /* Mark non-embossed textfields inside a listbox. */
+       if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == TEX) && (but->dt & UI_EMBOSSN)) {
+               uiButSetFlag(but, UI_BUT_LIST_ITEM);
+       }
+
        if (no_bg)
                uiBlockSetEmboss(block, UI_EMBOSS);
 }
@@ -2452,8 +2451,9 @@ uiLayout *uiLayoutBox(uiLayout *layout)
        return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
 }
 
-/* Check all buttons defined in this layout, and set labels as active/selected.
- * Needed to handle correctly text colors of list items. */
+/* Check all buttons defined in this layout, and set any button flagged as UI_BUT_LIST_ITEM as active/selected.
+ * Needed to handle correctly text colors of active (selected) list item.
+ */
 void ui_layout_list_set_labels_active(uiLayout *layout)
 {
        uiButtonItem *bitem;
index 1d1b7dbb835a31ad6a359401566883ed672a2616..8926a16481d35202654329ec69932b2397168e90 100644 (file)
@@ -2475,11 +2475,7 @@ static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UN
                                      struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
                                      int UNUSED(index), int UNUSED(flt_flag))
 {
-       char *namebuf;
-       const char *name;
-
-       namebuf = RNA_struct_name_get_alloc(itemptr, NULL, 0, NULL);
-       name = (namebuf) ? namebuf : "";
+       PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type);
 
        /* Simplest one! */
        switch (ui_list->layout_type) {
@@ -2489,14 +2485,14 @@ static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UN
                case UILST_LAYOUT_DEFAULT:
                case UILST_LAYOUT_COMPACT:
                default:
-                       uiItemL(layout, name, icon);
+                       if (nameprop) {
+                               uiItemFullR(layout, itemptr, nameprop, RNA_NO_INDEX, 0, UI_ITEM_R_NO_BG, "", icon);
+                       }
+                       else {
+                               uiItemL(layout, "", icon);
+                       }
                        break;
        }
-
-       /* free name */
-       if (namebuf) {
-               MEM_freeN(namebuf);
-       }
 }
 
 static void uilist_draw_filter_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout)
@@ -2713,8 +2709,8 @@ static void prepare_list(uiList *ui_list, int len, int activei, int rows, int ma
 }
 
 void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id,
-                    PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
-                    const char *active_propname, int rows, int maxrows, int layout_type, int columns)
+                    PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname,
+                    int rows, int maxrows, int layout_type, int columns)
 {
        uiListType *ui_list_type;
        uiList *ui_list = NULL;
@@ -2950,7 +2946,6 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
                                        draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname,
                                                  org_i, flt_flag);
 
-
                                        /* If we are "drawing" active item, set all labels as active. */
                                        if (i == activei) {
                                                ui_layout_list_set_labels_active(sub);
index 3058888c012ba62a49bcd7aa2378b66c03c69224..c85ecd1b5a1c9a33c931b25dcde9da0415c76c5b 100644 (file)
@@ -1656,8 +1656,14 @@ static void widget_state(uiWidgetType *wt, int state)
 {
        uiWidgetStateColors *wcol_state = wt->wcol_state;
 
+       if ((state & UI_BUT_LIST_ITEM) && !(state & UI_TEXTINPUT)) {
+               /* Override default widget's colors. */
+               bTheme *btheme = UI_GetTheme();
+               wt->wcol_theme = &btheme->tui.wcol_list_item;
+       }
+
        wt->wcol = *(wt->wcol_theme);
-       
+
        if (state & UI_SELECT) {
                copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
 
index d79a40aa6152e20c3449b6e2b5902d36bc5e0f3a..dcf51cdceafc64ac868882bf778b09e1a4829e08 100644 (file)
@@ -97,7 +97,7 @@ static const char *rna_translate_ui_text(const char *text, const char *text_ctxt
 
 static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, const char *text_ctxt,
                         int translate, int icon, int expand, int slider, int toggle, int icon_only, int event,
-                        int full_event, int emboss, int index)
+                        int full_event, int emboss, int index, int icon_value)
 {
        PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
        int flag = 0;
@@ -107,6 +107,10 @@ static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname,
                return;
        }
 
+       if (icon_value && !icon) {
+               icon = icon_value;
+       }
+
        /* Get translated name (label). */
        name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
 
@@ -511,6 +515,10 @@ void RNA_api_ui_layout(StructRNA *srna)
        RNA_def_int(func, "index", -1, -2, INT_MAX, "",
                    "The index of this button, when set a single member of an array can be accessed, "
                    "when set to -1 all array members are used", -2, INT_MAX); /* RNA_NO_INDEX == -1 */
+       parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_ui_text(parm, "Icon Value",
+                                "Override automatic icon of the item "
+                                "(use it e.g. with custom material icons returned by icon()...)");
 
        func = RNA_def_function(srna, "props_enum", "uiItemsEnumR");
        api_ui_item_rna_common(func);
index f61b54ac3607466d78941d0bb3dd8203f6778716..d79da3f3d6f5a6c6e65be75368b3d30023150f66 100644 (file)
@@ -468,8 +468,8 @@ void uiTemplateColorRamp(struct uiLayout *layout, struct ColorBand *coba, int ex
 void uiTemplateLayers(struct uiLayout *layout, struct PointerRNA *ptr, char *propname) {STUB_ASSERT(0);}
 void uiTemplateImageLayers(struct uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser) {STUB_ASSERT(0);}
 void uiTemplateList(struct uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id,
-                    PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
-                    const char *active_propname, int rows, int maxrows, int layout_type, int columns) {STUB_ASSERT(0);}
+                    PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname,
+                    int rows, int maxrows, int layout_type, int columns) {STUB_ASSERT(0);}
 void uiTemplateRunningJobs(struct uiLayout *layout, struct bContext *C) {STUB_ASSERT(0);}
 void uiTemplateOperatorSearch(struct uiLayout *layout) {STUB_ASSERT(0);}
 void uiTemplateHeader3D(struct uiLayout *layout, struct bContext *C) {STUB_ASSERT(0);}