UI List: ctrl click on names in list can be used for renaming.
[blender-staging.git] / source / blender / editors / interface / interface_layout.c
index 7c32f354c0a32d3c012adc21778a37304f82d1c3..346a54cf4eb248fbacfbc1af8f7ca2f23f23d5f2 100644 (file)
@@ -54,6 +54,8 @@
 
 #include "UI_interface.h"
 
+#include "ED_armature.h"
+
 
 #include "WM_api.h"
 #include "WM_types.h"
 
 /************************ 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)                 \
@@ -355,7 +353,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
        PropertyType type;
        PropertySubType subtype;
        uiLayout *sub;
-       int a, b;
+       unsigned int a, b;
 
        /* retrieve type and subtype */
        type = RNA_property_type(prop);
@@ -373,8 +371,9 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
                /* special check for layer layout */
                int butw, buth, unit;
                int cols = (len >= 20) ? 2 : 1;
-               int colbuts = len / (2 * cols);
-               int layer_used = 0;
+               const unsigned int colbuts = len / (2 * cols);
+               unsigned int layer_used = 0;
+               unsigned int layer_active = 0;
 
                uiBlockSetCurLayout(block, uiLayoutAbsolute(layout, FALSE));
 
@@ -384,27 +383,59 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
 
                if (ptr->type == &RNA_Armature) {
                        bArmature *arm = (bArmature *)ptr->data;
+                       
                        layer_used = arm->layer_used;
+                       
+                       if (arm->edbo) {
+                               if (arm->act_edbone) {
+                                       layer_active |= arm->act_edbone->layer;
+                               }
+                       }
+                       else {
+                               if (arm->act_bone) {
+                                       layer_active |= arm->act_bone->layer;
+                               }
+                       }
                }
 
                for (b = 0; b < cols; b++) {
                        uiBlockBeginAlign(block);
 
                        for (a = 0; a < colbuts; a++) {
-                               if (layer_used & (1 << (a + b * colbuts))) icon = ICON_LAYER_USED;
-                               else icon = ICON_BLANK1;
+                               int layer_num  = a + b * colbuts;
+                               int layer_flag = 1 << layer_num;
+                               
+                               if (layer_used & layer_flag) {
+                                       if (layer_active & layer_flag)
+                                               icon = ICON_LAYER_ACTIVE;
+                                       else
+                                               icon = ICON_LAYER_USED;
+                               }
+                               else {
+                                       icon = ICON_BLANK1;
+                               }
 
-                               but = uiDefAutoButR(block, ptr, prop, a + b * colbuts, "", icon, x + butw * a, y + buth, butw, buth);
+                               but = uiDefAutoButR(block, ptr, prop, layer_num, "", icon, x + butw * a, y + buth, butw, buth);
                                if (subtype == PROP_LAYER_MEMBER)
-                                       uiButSetFunc(but, ui_layer_but_cb, but, SET_INT_IN_POINTER(a + b * colbuts));
+                                       uiButSetFunc(but, ui_layer_but_cb, but, SET_INT_IN_POINTER(layer_num));
                        }
                        for (a = 0; a < colbuts; a++) {
-                               if (layer_used & (1 << (a + len / 2 + b * colbuts))) icon = ICON_LAYER_USED;
-                               else icon = ICON_BLANK1;
+                               int layer_num  = a + len / 2 + b * colbuts;
+                               int layer_flag = 1 << layer_num;
+                               
+                               if (layer_used & layer_flag) {
+                                       if (layer_active & layer_flag)
+                                               icon = ICON_LAYER_ACTIVE;
+                                       else
+                                               icon = ICON_LAYER_USED;
+                               }
+                               else {
+                                       icon = ICON_BLANK1;
+                               }
 
-                               but = uiDefAutoButR(block, ptr, prop, a + len / 2 + b * colbuts, "", icon, x + butw * a, y, butw, buth);
+                               but = uiDefAutoButR(block, ptr, prop, layer_num, "", icon, x + butw * a, y, butw, buth);
                                if (subtype == PROP_LAYER_MEMBER)
-                                       uiButSetFunc(but, ui_layer_but_cb, but, SET_INT_IN_POINTER(a + len / 2 + b * colbuts));
+                                       uiButSetFunc(but, ui_layer_but_cb, but, SET_INT_IN_POINTER(layer_num));
                        }
                        uiBlockEndAlign(block);
 
@@ -471,6 +502,8 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
                                        but->type = NUMSLI;
                                if (toggle && but->type == OPTION)
                                        but->type = TOG;
+                               if ((a == 0) && (subtype == PROP_AXISANGLE))
+                                       uiButSetUnitType(but, PROP_UNIT_ROTATION);
                        }
 
                        if (boolarr) {
@@ -503,6 +536,14 @@ static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2)
 static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop,
                                 const char *uiname, int h, int icon_only)
 {
+       /* XXX The way this function currently handles uiname parameter is insane and inconsistent with general UI API:
+        *     * uiname is the *enum property* label.
+        *     * when it is NULL or empty, we do not draw *enum items* labels, this doubles the icon_only parameter.
+        *     * we *never* draw (i.e. really use) the enum label uiname, it is just used as a mere flag!
+        *     Unfortunately, fixing this implies an API "soft break", so better to defer it for later... :/
+        *     --mont29
+        */
+
        uiBut *but;
        EnumPropertyItem *item, *item_array;
        const char *name;
@@ -539,7 +580,7 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt
                }
 
                if (ui_layout_local_dir(layout) != UI_LAYOUT_HORIZONTAL)
-                       but->flag |= UI_TEXT_LEFT;
+                       but->drawflag |= UI_BUT_TEXT_LEFT;
        }
        uiBlockSetCurLayout(block, layout);
 
@@ -568,7 +609,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
        PropertySubType subtype;
        int labelw;
 
-       sub = uiLayoutRow(layout, FALSE);
+       sub = uiLayoutRow(layout, layout->align);
        uiBlockSetCurLayout(block, sub);
 
        if (name[0]) {
@@ -587,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);
@@ -721,7 +760,7 @@ PointerRNA uiItemFullO_ptr(uiLayout *layout, wmOperatorType *ot, const char *nam
 
        /* text alignment for toolbar buttons */
        if ((layout->root->type == UI_LAYOUT_TOOLBAR) && !icon)
-               but->flag |= UI_TEXT_LEFT;
+               but->drawflag |= UI_BUT_TEXT_LEFT;
 
        if (flag & UI_ITEM_R_NO_BG)
                uiBlockSetEmboss(block, UI_EMBOSS);
@@ -871,7 +910,7 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
 
                                        uiItemL(column, item->name, ICON_NONE);
                                        but = block->buttons.last;
-                                       but->flag = UI_TEXT_LEFT;
+                                       but->drawflag = UI_BUT_TEXT_LEFT;
                                        ui_but_tip_from_enum_item(but, item);
                                }
                                else {  /* XXX bug here, colums draw bottom item badly */
@@ -1097,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;
@@ -1186,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);
 }
@@ -1295,7 +1339,7 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname
 
                                        uiItemL(column, item[i].name, ICON_NONE);
                                        bt = block->buttons.last;
-                                       bt->flag = UI_TEXT_LEFT;
+                                       bt->drawflag = UI_BUT_TEXT_LEFT;
 
                                        ui_but_tip_from_enum_item(bt, &item[i]);
                                }
@@ -1445,7 +1489,7 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
                but->hardmax = MAX2(but->hardmax, 256.0f);
                but->rnasearchpoin = *searchptr;
                but->rnasearchprop = searchprop;
-               but->flag |= UI_ICON_LEFT | UI_TEXT_LEFT;
+               but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
 
                if (RNA_property_type(prop) == PROP_ENUM) {
                        /* XXX, this will have a menu string,
@@ -1465,6 +1509,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
        uiBlock *block;
        StructRNA *icontype;
        int w, h;
+       char namestr[UI_MAX_NAME_STR];
        
        /* validate arguments */
        prop = RNA_struct_find_property(ptr, propname);
@@ -1507,6 +1552,8 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
        if (!name)
                name = RNA_property_ui_name(prop);
 
+       name = ui_item_name_add_colon(name, namestr);
+
        /* create button */
        block = uiLayoutGetBlock(layout);
 
@@ -1585,7 +1632,7 @@ static void ui_item_menu(uiLayout *layout, const char *name, int icon, uiMenuCre
            (force_menu && layout->root->type != UI_LAYOUT_MENU))  /* We never want a dropdown in menu! */
        {
                but->type = MENU;
-               but->flag |= UI_TEXT_LEFT;
+               but->drawflag |= UI_BUT_TEXT_LEFT;
        }
 }
 
@@ -1632,15 +1679,20 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
                but = uiDefIconBut(block, LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
        else
                but = uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-       
+
        /* to compensate for string size padding in ui_text_icon_width,
         * make text aligned right if the layout is aligned right.
         */
        if (uiLayoutGetAlignment(layout) == UI_LAYOUT_ALIGN_RIGHT) {
-               but->flag &= ~UI_TEXT_LEFT;     /* default, needs to be unset */
-               but->flag |= UI_TEXT_RIGHT;
+               but->drawflag &= ~UI_BUT_TEXT_LEFT;     /* default, needs to be unset */
+               but->drawflag |= UI_BUT_TEXT_RIGHT;
        }
-       
+
+       /* Mark as a label inside a listbox. */
+       if (block->flag & UI_BLOCK_LIST_ITEM) {
+               but->flag |= UI_BUT_LIST_ITEM;
+       }
+
        return but;
 }
 
@@ -2399,6 +2451,22 @@ uiLayout *uiLayoutBox(uiLayout *layout)
        return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
 }
 
+/* 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;
+       for (bitem = layout->items.first; bitem; bitem = bitem->item.next) {
+               if (bitem->item.type != ITEM_BUTTON) {
+                       ui_layout_list_set_labels_active((uiLayout *)(&bitem->item));
+               }
+               else if (bitem->but->flag & UI_BUT_LIST_ITEM) {
+                       uiButSetFlag(bitem->but, UI_SELECT);
+               }
+       }
+}
+
 uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr,
                           PropertyRNA *actprop)
 {
@@ -2412,6 +2480,20 @@ uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, Pr
        but->rnapoin = *actptr;
        but->rnaprop = actprop;
 
+       /* Resizing data. */
+       /* Note: we can't use usual "num button" value handling, as it only tries rnapoin when it is non-NULL... :/
+        *       So just setting but->poin, not but->pointype.
+        */
+       but->poin = (void *)&ui_list->list_grip;
+       but->hardmin = but->softmin = 0.0f;
+       but->hardmax = but->softmax = 1000.0f; /* Should be more than enough! */
+       but->a1 = 0.0f;
+
+       /* only for the undo string */
+       if (but->flag & UI_BUT_UNDO) {
+               but->tip = RNA_property_description(actprop);
+       }
+
        return (uiLayout *)box;
 }
 
@@ -2656,8 +2738,9 @@ static void ui_item_align(uiLayout *litem, short nr)
                        BLI_remlink(&litem->root->block->buttons, box->roundbox);
                        BLI_addhead(&litem->root->block->buttons, box->roundbox);
                }
-               else
+               else if (((uiLayout *)item)->align) {
                        ui_item_align((uiLayout *)item, nr);
+               }
        }
 }
 
@@ -2886,7 +2969,7 @@ static void ui_intro_button(DynStr *ds, uiButtonItem *bitem)
        BLI_dynstr_appendf(ds, "'tip':'''%s''', ", but->tip ? but->tip : "");  /* not exactly needed, rna has this */
 
        if (but->optype) {
-               char *opstr = WM_operator_pystring(but->block->evil_C, but->optype, but->opptr, 0);
+               char *opstr = WM_operator_pystring_ex(but->block->evil_C, NULL, false, but->optype, but->opptr);
                BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr ? opstr : "");
                MEM_freeN(opstr);
        }
@@ -3054,17 +3137,24 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,
 
        /* set various special settings for buttons */
        {
+               uiBlock *block = uiLayoutGetBlock(layout);
+               const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0;
                uiBut *but;
+
                
-               for (but = uiLayoutGetBlock(layout)->buttons.first; but; but = but->next) {
+               for (but = block->buttons.first; but; but = but->next) {
                        /* no undo for buttons for operator redo panels */
                        uiButClearFlag(but, UI_BUT_UNDO);
                        
+                       /* only for popups, see [#36109] */
+
                        /* if button is operator's default property, and a text-field, enable focus for it
                         *      - this is used for allowing operators with popups to rename stuff with fewer clicks
                         */
-                       if ((but->rnaprop == op->type->prop) && (but->type == TEX)) {
-                               uiButSetFocusOnEnter(CTX_wm_window(C), but);
+                       if (is_popup) {
+                               if ((but->rnaprop == op->type->prop) && (but->type == TEX)) {
+                                       uiButSetFocusOnEnter(CTX_wm_window(C), but);
+                               }
                        }
                }
        }