[Bf-blender-cvs] [6640bcca742] master: UI: support drawing booleans with icons as check-boxes

Campbell Barton noreply at git.blender.org
Tue May 21 07:21:16 CEST 2019


Commit: 6640bcca742210fa3dc9c8a0675ebf71a9e9e7f6
Author: Campbell Barton
Date:   Tue May 21 14:39:09 2019 +1000
Branches: master
https://developer.blender.org/rB6640bcca742210fa3dc9c8a0675ebf71a9e9e7f6

UI: support drawing booleans with icons as check-boxes

Previously, if a boolean happened to use an icon there was no way
to make it display as a check-box from Python scripts.

The previous logic meant we ended up having to edit the RNA.
Since booleans with icons don't work well with the split-property layout
(now used for most of the interface).
Icons were being removed from RNA then added back using awkward Python
ternary expressions in the interface scripts.

The toggle argument now has an unset state (-1).

- toggle=True: no checkbox (emboss).
- toggle=False: always use a checkbox (no icon).
- toggle=(unset/-1): depends on the icon status, default as before.

Since toggle=False was default, this isn't used in existing UI logic.

===================================================================

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_layout.c
M	source/blender/makesrna/intern/rna_ui_api.c

===================================================================

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 5912a3a59e4..5efe5a7e07c 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1714,15 +1714,28 @@ enum {
   UI_ITEM_O_RETURN_PROPS = 1 << 0,
   UI_ITEM_R_EXPAND = 1 << 1,
   UI_ITEM_R_SLIDER = 1 << 2,
+  /**
+   * Use for booleans, causes the button to draw with an outline (emboss),
+   * instead of text with a checkbox.
+   * This is implied when toggle buttons have an icon
+   * unless #UI_ITEM_R_ICON_NEVER flag is set.
+   */
   UI_ITEM_R_TOGGLE = 1 << 3,
-  UI_ITEM_R_ICON_ONLY = 1 << 4,
-  UI_ITEM_R_EVENT = 1 << 5,
-  UI_ITEM_R_FULL_EVENT = 1 << 6,
-  UI_ITEM_R_NO_BG = 1 << 7,
-  UI_ITEM_R_IMMEDIATE = 1 << 8,
-  UI_ITEM_O_DEPRESS = 1 << 9,
-  UI_ITEM_R_COMPACT = 1 << 10,
-  UI_ITEM_R_CHECKBOX_INVERT = 1 << 11,
+  /**
+   * Don't attempt to use an icon when the icon is set to #ICON_NONE.
+   *
+   * Use for boolean's, causes the buttons to always show as a checkbox
+   * even when there is an icon (which would normally show the button as a toggle).
+   */
+  UI_ITEM_R_ICON_NEVER = 1 << 4,
+  UI_ITEM_R_ICON_ONLY = 1 << 5,
+  UI_ITEM_R_EVENT = 1 << 6,
+  UI_ITEM_R_FULL_EVENT = 1 << 7,
+  UI_ITEM_R_NO_BG = 1 << 8,
+  UI_ITEM_R_IMMEDIATE = 1 << 9,
+  UI_ITEM_O_DEPRESS = 1 << 10,
+  UI_ITEM_R_COMPACT = 1 << 11,
+  UI_ITEM_R_CHECKBOX_INVERT = 1 << 12,
 };
 
 #define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X)
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 8ff270bb622..931a4faa1c0 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -3738,6 +3738,16 @@ void ui_def_but_icon(uiBut *but, const int icon, const int flag)
   }
 }
 
+/**
+ * Avoid using this where possible since it's better not to ask for an icon in the first place.
+ */
+void ui_def_but_icon_clear(uiBut *but)
+{
+  but->icon = ICON_NONE;
+  but->flag &= ~UI_HAS_ICON;
+  but->drawflag &= ~UI_BUT_ICON_LEFT;
+}
+
 static void ui_def_but_rna__disable(uiBut *but, const char *info)
 {
   but->flag |= UI_BUT_DISABLED;
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 33288df15ba..8a2b28ee2d4 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -500,6 +500,7 @@ extern int ui_but_string_get_max_length(uiBut *but);
 extern uiBut *ui_but_drag_multi_edit_get(uiBut *but);
 
 void ui_def_but_icon(uiBut *but, const int icon, const int flag);
+void ui_def_but_icon_clear(uiBut *but);
 extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but);
 
 extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 9632bcd35e4..a3906879fd7 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -484,7 +484,7 @@ static void ui_item_array(uiLayout *layout,
                           int UNUSED(h),
                           bool expand,
                           bool slider,
-                          bool toggle,
+                          int toggle,
                           bool icon_only,
                           bool compact,
                           bool show_text)
@@ -691,7 +691,7 @@ static void ui_item_array(uiLayout *layout,
         if (slider && but->type == UI_BTYPE_NUM) {
           but->type = UI_BTYPE_NUM_SLIDER;
         }
-        if (toggle && but->type == UI_BTYPE_CHECKBOX) {
+        if ((toggle == 1) && but->type == UI_BTYPE_CHECKBOX) {
           but->type = UI_BTYPE_TOGGLE;
         }
         if ((a == 0) && (subtype == PROP_AXISANGLE)) {
@@ -1889,6 +1889,10 @@ void uiItemFullR(uiLayout *layout,
 
   const bool icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0;
 
+  /* Boolean with -1 to signify that the value depends on the presence of an icon. */
+  const int toggle = ((flag & UI_ITEM_R_TOGGLE) ? 1 : ((flag & UI_ITEM_R_ICON_NEVER) ? 0 : -1));
+  const bool no_icon = (toggle == 0);
+
   /* set name and icon */
   if (!name) {
     if (!icon_only) {
@@ -1903,10 +1907,6 @@ void uiItemFullR(uiLayout *layout,
     flag &= ~UI_ITEM_R_CHECKBOX_INVERT;
   }
 
-  if (icon == ICON_NONE) {
-    icon = RNA_property_ui_icon(prop);
-  }
-
   if (flag & UI_ITEM_R_ICON_ONLY) {
     /* pass */
   }
@@ -1931,51 +1931,60 @@ void uiItemFullR(uiLayout *layout,
     }
   }
 
-#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION
-  if (use_prop_sep) {
-    if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
-      use_prop_sep_split_label = false;
+  if (no_icon == false) {
+    if (icon == ICON_NONE) {
+      icon = RNA_property_ui_icon(prop);
     }
-  }
-#endif
 
-  /* menus and pie-menus don't show checkbox without this */
-  if ((layout->root->type == UI_LAYOUT_MENU) ||
-      /* use checkboxes only as a fallback in pie-menu's, when no icon is defined */
-      ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) {
-    int prop_flag = RNA_property_flag(prop);
-    if (type == PROP_BOOLEAN && ((is_array == false) || (index != RNA_NO_INDEX))) {
-      if (prop_flag & PROP_ICONS_CONSECUTIVE) {
-        icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
-      }
-      else if (is_array) {
-        icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT :
-                                                                    ICON_CHECKBOX_DEHLT;
+    /* Menus and pie-menus don't show checkbox without this. */
+    if ((layout->root->type == UI_LAYOUT_MENU) ||
+        /* Use checkboxes only as a fallback in pie-menu's, when no icon is defined. */
+        ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) {
+      int prop_flag = RNA_property_flag(prop);
+      if (type == PROP_BOOLEAN) {
+        if ((is_array == false) || (index != RNA_NO_INDEX)) {
+          if (prop_flag & PROP_ICONS_CONSECUTIVE) {
+            icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
+          }
+          else if (is_array) {
+            icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT :
+                                                                        ICON_CHECKBOX_DEHLT;
+          }
+          else {
+            icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+          }
+        }
       }
-      else {
-        icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+      else if (type == PROP_ENUM) {
+        if (index == RNA_ENUM_VALUE) {
+          int enum_value = RNA_property_enum_get(ptr, prop);
+          if (prop_flag & PROP_ICONS_CONSECUTIVE) {
+            icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
+          }
+          else if (prop_flag & PROP_ENUM_FLAG) {
+            icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+          }
+          else {
+            icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+          }
+        }
       }
     }
-    else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
-      int enum_value = RNA_property_enum_get(ptr, prop);
-      if (prop_flag & PROP_ICONS_CONSECUTIVE) {
-        icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
-      }
-      else if (prop_flag & PROP_ENUM_FLAG) {
-        icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
-      }
-      else {
-        icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
-      }
+  }
+
+#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION
+  if (use_prop_sep) {
+    if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
+      use_prop_sep_split_label = false;
     }
   }
+#endif
 
   if ((type == PROP_ENUM) && (RNA_property_flag(prop) & PROP_ENUM_FLAG)) {
     flag |= UI_ITEM_R_EXPAND;
   }
 
   const bool slider = (flag & UI_ITEM_R_SLIDER) != 0;
-  const bool toggle = (flag & UI_ITEM_R_TOGGLE) != 0;
   const bool expand = (flag & UI_ITEM_R_EXPAND) != 0;
   const bool no_bg = (flag & UI_ITEM_R_NO_BG) != 0;
   const bool compact = (flag & UI_ITEM_R_COMPACT) != 0;
@@ -2164,7 +2173,7 @@ void uiItemFullR(uiLayout *layout,
       }
     }
 
-    if (toggle && but->type == UI_BTYPE_CHECKBOX) {
+    if ((toggle == 1) && but->type == UI_BTYPE_CHECKBOX) {
       but->type = UI_BTYPE_TOGGLE;
     }
 
@@ -2183,6 +2192,18 @@ void uiItemFullR(uiLayout *layout,
     }
   }
 
+  /* The resulting button may have the icon set since boolean button drawing
+   * is being 'helpful' and adding an icon for us.
+   * In this case we want the ability not to have an icon.
+   *
+   * We could pass an argument not to set the icon to begin with however this is the one case
+   * the functionality is needed.  */
+  if (but && no_icon) {
+    if ((icon == ICON_NONE) && (but->icon != ICON_NONE)) {
+      ui_def_but_icon_clear(but);
+    }
+  }
+
   /* Mark non-embossed textfields inside a listbox. */
   if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) &&
       (but->dt & UI_EMBOSS_NONE)) {
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 5a001f05b53..d50f97e88ca 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -95,7 +95,7 @@ static void rna_uiItemR(uiLayout *layout,
                         int icon,
                         bool expand,
                         bool slider,
-                        bool toggle,
+                        int toggle,
                         bool icon_only,
                         bool event,
                         bool full_event,
@@ -121,7 +121,12 @@ static void rna_uiItemR(uiLayout *layout,
 
   flag |= (slider) ? UI_ITEM_R_SLIDER : 0;
   flag |= (expand) ? UI_ITEM_R_EXPAND : 0;
-  flag |= (toggle) ? UI_ITEM_R_TOGGLE : 0;
+  if (toggle == 1) {
+    flag |= 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list