UI: Layout Engine
[blender-staging.git] / source / blender / editors / interface / interface_templates.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * Contributor(s): Blender Foundation 2009.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include <stdlib.h>
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_string.h"
30
31 #include "BKE_context.h"
32 #include "BKE_library.h"
33 #include "BKE_utildefines.h"
34
35 #include "ED_screen.h"
36
37 #include "RNA_access.h"
38
39 #include "WM_api.h"
40 #include "WM_types.h"
41
42 #include "UI_interface.h"
43 #include "UI_resources.h"
44
45 static uiBlock *block_free_layout(uiLayout *layout)
46 {
47         uiBlock *block;
48
49         block= uiLayoutBlock(layout);
50         uiBlockSetCurLayout(block, uiLayoutFree(layout, 0));
51
52         return block;
53 }
54
55 void ui_template_fix_linking()
56 {
57 }
58
59 /********************** Header Template *************************/
60
61 void uiTemplateHeader(uiLayout *layout, bContext *C)
62 {
63         uiBlock *block;
64         
65         block= block_free_layout(layout);
66         ED_area_header_standardbuttons(C, block, 0);
67 }
68
69 /******************* Header ID Template ************************/
70
71 typedef struct TemplateHeaderID {
72         PointerRNA ptr;
73         PropertyRNA *prop;
74
75         int flag;
76         short browse;
77
78         char newop[256];
79         char openop[256];
80         char unlinkop[256];
81 } TemplateHeaderID;
82
83 static void template_header_id_cb(bContext *C, void *arg_litem, void *arg_event)
84 {
85         TemplateHeaderID *template= (TemplateHeaderID*)arg_litem;
86         PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
87         ID *idtest, *id= idptr.data;
88         ListBase *lb= wich_libbase(CTX_data_main(C), ID_TXT);
89         int nr, event= GET_INT_FROM_POINTER(arg_event);
90         
91         if(event == UI_ID_BROWSE && template->browse == 32767)
92                 event= UI_ID_ADD_NEW;
93         else if(event == UI_ID_BROWSE && template->browse == 32766)
94                 event= UI_ID_OPEN;
95
96         switch(event) {
97                 case UI_ID_BROWSE: {
98                         if(template->browse== -2) {
99                                 /* XXX implement or find a replacement
100                                  * activate_databrowse((ID *)G.buts->lockpoin, GS(id->name), 0, B_MESHBROWSE, &template->browse, do_global_buttons); */
101                                 return;
102                         }
103                         if(template->browse < 0)
104                                 return;
105
106                         for(idtest=lb->first, nr=1; idtest; idtest=idtest->next, nr++) {
107                                 if(nr==template->browse) {
108                                         if(id == idtest)
109                                                 return;
110
111                                         id= idtest;
112                                         RNA_id_pointer_create(id, &idptr);
113                                         RNA_property_pointer_set(&template->ptr, template->prop, idptr);
114                                         RNA_property_update(C, &template->ptr, template->prop);
115                                         /* XXX */
116
117                                         break;
118                                 }
119                         }
120                         break;
121                 }
122 #if 0
123                 case UI_ID_DELETE:
124                         id= NULL;
125                         break;
126                 case UI_ID_FAKE_USER:
127                         if(id) {
128                                 if(id->flag & LIB_FAKEUSER) id->us++;
129                                 else id->us--;
130                         }
131                         else return;
132                         break;
133 #endif
134                 case UI_ID_PIN:
135                         break;
136                 case UI_ID_ADD_NEW:
137                         WM_operator_name_call(C, template->newop, WM_OP_INVOKE_REGION_WIN, NULL);
138                         break;
139                 case UI_ID_OPEN:
140                         WM_operator_name_call(C, template->openop, WM_OP_INVOKE_REGION_WIN, NULL);
141                         break;
142 #if 0
143                 case UI_ID_ALONE:
144                         if(!id || id->us < 1)
145                                 return;
146                         break;
147                 case UI_ID_LOCAL:
148                         if(!id || id->us < 1)
149                                 return;
150                         break;
151                 case UI_ID_AUTO_NAME:
152                         break;
153 #endif
154         }
155 }
156
157 static void template_header_ID(bContext *C, uiBlock *block, TemplateHeaderID *template)
158 {
159         uiBut *but;
160         TemplateHeaderID *duptemplate;
161         PointerRNA idptr;
162         ListBase *lb;
163         int x= 0, y= 0;
164
165         idptr= RNA_property_pointer_get(&template->ptr, template->prop);
166         lb= wich_libbase(CTX_data_main(C), ID_TXT);
167
168         uiBlockBeginAlign(block);
169         if(template->flag & UI_ID_BROWSE) {
170                 char *extrastr, *str;
171                 
172                 if((template->flag & UI_ID_ADD_NEW) && (template->flag && UI_ID_OPEN))
173                         extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767";
174                 else if(template->flag & UI_ID_ADD_NEW)
175                         extrastr= "ADD NEW %x 32767";
176                 else if(template->flag & UI_ID_OPEN)
177                         extrastr= "OPEN NEW %x 32766";
178                 else
179                         extrastr= NULL;
180
181                 duptemplate= MEM_dupallocN(template);
182                 IDnames_to_pupstring(&str, NULL, extrastr, lb, idptr.data, &duptemplate->browse);
183
184                 but= uiDefButS(block, MENU, 0, str, x, y, UI_UNIT_X, UI_UNIT_Y, &duptemplate->browse, 0, 0, 0, 0, "Browse existing choices, or add new");
185                 uiButSetNFunc(but, template_header_id_cb, duptemplate, SET_INT_IN_POINTER(UI_ID_BROWSE));
186                 x+= UI_UNIT_X;
187         
188                 MEM_freeN(str);
189         }
190
191         /* text button with name */
192         if(idptr.data) {
193                 char name[64];
194
195                 text_idbutton(idptr.data, name);
196                 but= uiDefButR(block, TEX, 0, name, x, y, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
197                 uiButSetNFunc(but, template_header_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
198                 x += UI_UNIT_X*6;
199
200                 /* delete button */
201                 if(template->flag & UI_ID_DELETE) {
202                         but= uiDefIconButO(block, BUT, template->unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, x, y, UI_UNIT_X, UI_UNIT_Y, NULL);
203                         x += UI_UNIT_X;
204                 }
205         }
206         uiBlockEndAlign(block);
207 }
208
209 void uiTemplateHeaderID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop)
210 {
211         TemplateHeaderID *template;
212         uiBlock *block;
213         PropertyRNA *prop;
214
215         if(!ptr->data)
216                 return;
217
218         prop= RNA_struct_find_property(ptr, propname);
219
220         if(!prop) {
221                 printf("uiTemplateHeaderID: property not found: %s\n", propname);
222                 return;
223         }
224
225         template= MEM_callocN(sizeof(TemplateHeaderID), "TemplateHeaderID");
226         template->ptr= *ptr;
227         template->prop= prop;
228         template->flag= UI_ID_BROWSE|UI_ID_RENAME;
229
230         if(newop) {
231                 template->flag |= UI_ID_ADD_NEW;
232                 BLI_strncpy(template->newop, newop, sizeof(template->newop));
233         }
234         if(openop) {
235                 template->flag |= UI_ID_OPEN;
236                 BLI_strncpy(template->openop, openop, sizeof(template->openop));
237         }
238         if(unlinkop) {
239                 template->flag |= UI_ID_DELETE;
240                 BLI_strncpy(template->unlinkop, unlinkop, sizeof(template->unlinkop));
241         }
242
243         block= block_free_layout(layout);
244         template_header_ID(C, block, template);
245
246         MEM_freeN(template);
247 }
248