7da12277372edc811f606b22e3b9b03aa085c2f1
[blender.git] / source / blender / editors / interface / interface_utils.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  * 
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/interface/interface_utils.c
27  *  \ingroup edinterface
28  */
29
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <assert.h>
35
36 #include "DNA_object_types.h"
37
38 #include "BLI_utildefines.h"
39 #include "BLI_string.h"
40
41 #include "BLF_translation.h"
42
43 #include "BKE_context.h"
44
45
46 #include "RNA_access.h"
47
48 #include "UI_interface.h"
49 #include "UI_resources.h"
50
51
52 /*************************** RNA Utilities ******************************/
53
54 uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, const char *name, int icon, int x1, int y1, int x2, int y2)
55 {
56         uiBut *but = NULL;
57
58         switch (RNA_property_type(prop)) {
59                 case PROP_BOOLEAN:
60                 {
61                         int arraylen = RNA_property_array_length(ptr, prop);
62
63                         if (arraylen && index == -1)
64                                 return NULL;
65                         
66                         if (icon && name && name[0] == '\0')
67                                 but = uiDefIconButR_prop(block, ICONTOG, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
68                         else if (icon)
69                                 but = uiDefIconTextButR_prop(block, ICONTOG, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
70                         else
71                                 but = uiDefButR_prop(block, OPTION, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
72                         break;
73                 }
74                 case PROP_INT:
75                 case PROP_FLOAT:
76                 {
77                         int arraylen = RNA_property_array_length(ptr, prop);
78
79                         if (arraylen && index == -1) {
80                                 if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA))
81                                         but = uiDefButR_prop(block, COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, -1, -1, NULL);
82                         }
83                         else if (RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR)
84                                 but = uiDefButR_prop(block, NUMSLI, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
85                         else
86                                 but = uiDefButR_prop(block, NUM, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
87                         break;
88                 }
89                 case PROP_ENUM:
90                         if (icon && name && name[0] == '\0')
91                                 but = uiDefIconButR_prop(block, MENU, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
92                         else if (icon)
93                                 but = uiDefIconTextButR_prop(block, MENU, 0, icon, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
94                         else
95                                 but = uiDefButR_prop(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
96                         break;
97                 case PROP_STRING:
98                         if (icon && name && name[0] == '\0')
99                                 but = uiDefIconButR_prop(block, TEX, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
100                         else if (icon)
101                                 but = uiDefIconTextButR_prop(block, TEX, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
102                         else
103                                 but = uiDefButR_prop(block, TEX, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
104                         break;
105                 case PROP_POINTER:
106                 {
107                         PointerRNA pptr;
108
109                         pptr = RNA_property_pointer_get(ptr, prop);
110                         if (!pptr.type)
111                                 pptr.type = RNA_property_pointer_type(ptr, prop);
112                         icon = RNA_struct_ui_icon(pptr.type);
113                         if (icon == ICON_DOT)
114                                 icon = 0;
115
116                         but = uiDefIconTextButR_prop(block, SEARCH_MENU, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
117                         break;
118                 }
119                 case PROP_COLLECTION:
120                 {
121                         char text[256];
122                         BLI_snprintf(text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop));
123                         but = uiDefBut(block, LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
124                         uiButSetFlag(but, UI_BUT_DISABLED);
125                         break;
126                 }
127                 default:
128                         but = NULL;
129                         break;
130         }
131
132         return but;
133 }
134
135 /**
136  * \a check_prop callback filters functions to avoid drawing certain properties,
137  * in cases where PROP_HIDDEN flag can't be used for a property.
138  */
139 int uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr,
140                      bool (*check_prop)(PointerRNA *, PropertyRNA *),
141                      const char label_align)
142 {
143         uiLayout *split, *col;
144         int flag;
145         const char *name;
146         int tot = 0;
147
148         assert(ELEM3(label_align, '\0', 'H', 'V'));
149
150         RNA_STRUCT_BEGIN (ptr, prop)
151         {
152                 flag = RNA_property_flag(prop);
153                 if (flag & PROP_HIDDEN || (check_prop && check_prop(ptr, prop) == FALSE))
154                         continue;
155
156                 if (label_align != '\0') {
157                         PropertyType type = RNA_property_type(prop);
158                         int is_boolean = (type == PROP_BOOLEAN && !RNA_property_array_check(prop));
159
160                         name = RNA_property_ui_name(prop);
161
162                         if (label_align == 'V') {
163                                 col = uiLayoutColumn(layout, TRUE);
164
165                                 if (!is_boolean)
166                                         uiItemL(col, name, ICON_NONE);
167                         }
168                         else if (label_align == 'H') {
169                                 split = uiLayoutSplit(layout, 0.5f, FALSE);
170
171                                 col = uiLayoutColumn(split, FALSE);
172                                 uiItemL(col, (is_boolean) ? "" : name, ICON_NONE);
173                                 col = uiLayoutColumn(split, FALSE);
174                         }
175                         else {
176                                 col = NULL;
177                         }
178
179                         /* may meed to add more cases here.
180                          * don't override enum flag names */
181
182                         /* name is shown above, empty name for button below */
183                         name = (flag & PROP_ENUM_FLAG || is_boolean) ? NULL : "";
184                 }
185                 else {
186                         col = layout;
187                         name = NULL; /* no smart label alignment, show default name with button */
188                 }
189
190                 uiItemFullR(col, ptr, prop, -1, 0, 0, name, ICON_NONE);
191                 tot++;
192         }
193         RNA_STRUCT_END;
194
195         return tot;
196 }
197
198 /***************************** ID Utilities *******************************/
199
200 int uiIconFromID(ID *id)
201 {
202         Object *ob;
203         PointerRNA ptr;
204         short idcode;
205
206         if (id == NULL)
207                 return ICON_NONE;
208         
209         idcode = GS(id->name);
210
211         /* exception for objects */
212         if (idcode == ID_OB) {
213                 ob = (Object *)id;
214
215                 if (ob->type == OB_EMPTY)
216                         return ICON_EMPTY_DATA;
217                 else
218                         return uiIconFromID(ob->data);
219         }
220
221         /* otherwise get it through RNA, creating the pointer
222          * will set the right type, also with subclassing */
223         RNA_id_pointer_create(id, &ptr);
224
225         return (ptr.type) ? RNA_struct_ui_icon(ptr.type) : ICON_NONE;
226 }