Merging r38818 through r39198 from trunk into vgroup_modifiers.
[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
40 #include "BKE_context.h"
41
42
43 #include "RNA_access.h"
44
45 #include "UI_interface.h"
46 #include "UI_resources.h"
47
48
49 /*************************** RNA Utilities ******************************/
50
51 uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, const char *name, int icon, int x1, int y1, int x2, int y2)
52 {
53         uiBut *but=NULL;
54
55         switch(RNA_property_type(prop)) {
56                 case PROP_BOOLEAN:
57                 {
58                         int arraylen= RNA_property_array_length(ptr, prop);
59
60                         if(arraylen && index == -1)
61                                 return NULL;
62                         
63                         if(icon && name && name[0] == '\0')
64                                 but= uiDefIconButR_prop(block, ICONTOG, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
65                         else if(icon)
66                                 but= uiDefIconTextButR_prop(block, ICONTOG, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
67                         else
68                                 but= uiDefButR_prop(block, OPTION, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
69                         break;
70                 }
71                 case PROP_INT:
72                 case PROP_FLOAT:
73                 {
74                         int arraylen= RNA_property_array_length(ptr, prop);
75
76                         if(arraylen && index == -1) {
77                                 if(ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA))
78                                         but= uiDefButR_prop(block, COL, 0, name, x1, y1, x2, y2, ptr, prop, 0, 0, 0, -1, -1, NULL);
79                         }
80                         else if(RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR)
81                                 but= uiDefButR_prop(block, NUMSLI, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
82                         else
83                                 but= uiDefButR_prop(block, NUM, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
84                         break;
85                 }
86                 case PROP_ENUM:
87                         if(icon && name && name[0] == '\0')
88                                 but= uiDefIconButR_prop(block, MENU, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
89                         else if(icon)
90                                 but= uiDefIconTextButR_prop(block, MENU, 0, icon, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
91                         else
92                                 but= uiDefButR_prop(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
93                         break;
94                 case PROP_STRING:
95                         if(icon && name && name[0] == '\0')
96                                 but= uiDefIconButR_prop(block, TEX, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
97                         else if(icon)
98                                 but= uiDefIconTextButR_prop(block, TEX, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
99                         else
100                                 but= uiDefButR_prop(block, TEX, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
101                         break;
102                 case PROP_POINTER: {
103                         PointerRNA pptr;
104
105                         pptr= RNA_property_pointer_get(ptr, prop);
106                         if(!pptr.type)
107                                 pptr.type= RNA_property_pointer_type(ptr, prop);
108                         icon= RNA_struct_ui_icon(pptr.type);
109                         if(icon == ICON_DOT)
110                                 icon= 0;
111
112                         but= uiDefIconTextButR_prop(block, IDPOIN, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
113                         break;
114                 }
115                 case PROP_COLLECTION: {
116                         char text[256];
117                         sprintf(text, "%d items", RNA_property_collection_length(ptr, prop));
118                         but= uiDefBut(block, LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
119                         uiButSetFlag(but, UI_BUT_DISABLED);
120                         break;
121                 }
122                 default:
123                         but= NULL;
124                         break;
125         }
126
127         return but;
128 }
129
130 int uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr, int (*check_prop)(PropertyRNA *), const char label_align)
131 {
132         uiLayout *split, *col;
133         int flag;
134         const char *name;
135         int tot= 0;
136
137         assert(ELEM3(label_align, '\0', 'H', 'V'));
138
139         RNA_STRUCT_BEGIN(ptr, prop) {
140                 flag= RNA_property_flag(prop);
141                 if(flag & PROP_HIDDEN || (check_prop && check_prop(prop)==FALSE))
142                         continue;
143
144                 if(label_align != '\0') {
145                         PropertyType type = RNA_property_type(prop);
146                         int is_boolean = (type == PROP_BOOLEAN && !RNA_property_array_check(ptr, prop));
147
148                         name= RNA_property_ui_name(prop);
149
150                         if(label_align=='V') {
151                                 col= uiLayoutColumn(layout, 1);
152
153                                 if(!is_boolean)
154                                         uiItemL(col, name, ICON_NONE);
155                         }
156                         else if(label_align=='H') {
157                                 split = uiLayoutSplit(layout, 0.5f, 0);
158
159                                 col= uiLayoutColumn(split, 0);
160                                 uiItemL(col, (is_boolean)? "": name, ICON_NONE);
161                                 col= uiLayoutColumn(split, 0);
162                         }
163                         else {
164                                 col= NULL;
165                         }
166
167                         /* may meed to add more cases here.
168                          * don't override enum flag names */
169
170                         /* name is shown above, empty name for button below */
171                         name= (flag & PROP_ENUM_FLAG || is_boolean)? NULL: "";
172                 }
173                 else {
174                         col= layout;
175                         name= NULL; /* no smart label alignment, show default name with button */
176                 }
177
178                 uiItemFullR(col, ptr, prop, -1, 0, 0, name, ICON_NONE);
179                 tot++;
180         }
181         RNA_STRUCT_END;
182
183         return tot;
184 }
185
186 /***************************** ID Utilities *******************************/
187
188 int uiIconFromID(ID *id)
189 {
190         Object *ob;
191         PointerRNA ptr;
192         short idcode;
193
194         if(id==NULL)
195                 return ICON_NONE;
196         
197         idcode= GS(id->name);
198
199         /* exception for objects */
200         if(idcode == ID_OB) {
201                 ob= (Object*)id;
202
203                 if(ob->type == OB_EMPTY)
204                         return ICON_EMPTY_DATA;
205                 else
206                         return uiIconFromID(ob->data);
207         }
208
209         /* otherwise get it through RNA, creating the pointer
210            will set the right type, also with subclassing */
211         RNA_id_pointer_create(id, &ptr);
212
213         return (ptr.type)? RNA_struct_ui_icon(ptr.type) : ICON_NONE;
214 }