2.5: ID datablock button back, previously known as std_libbuttons. The
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #include <math.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "MEM_guardedalloc.h"
31
32 #include "DNA_listBase.h"
33 #include "DNA_material_types.h"
34 #include "DNA_screen_types.h"
35 #include "DNA_windowmanager_types.h"
36
37 #include "BKE_context.h"
38 #include "BKE_idprop.h"
39 #include "BKE_library.h"
40 #include "BKE_main.h"
41 #include "BKE_utildefines.h"
42
43 #include "RNA_access.h"
44
45 #include "UI_interface.h"
46 #include "UI_resources.h"
47
48 #include "ED_util.h"
49
50 #include "WM_api.h"
51 #include "WM_types.h"
52
53 #define DEF_BUT_WIDTH           150
54 #define DEF_ICON_BUT_WIDTH      20
55 #define DEF_BUT_HEIGHT          20
56
57 /*************************** RNA Utilities ******************************/
58
59 int UI_GetIconRNA(PointerRNA *ptr)
60 {
61         StructRNA *rnatype= ptr->type;
62
63         if(rnatype == &RNA_Scene)
64                 return ICON_SCENE_DEHLT;
65         else if(rnatype == &RNA_World)
66                 return ICON_WORLD;
67         else if(rnatype == &RNA_Object)
68                 return ICON_OBJECT;
69         else if(rnatype == &RNA_Mesh)
70                 return ICON_MESH;
71         else if(rnatype == &RNA_MeshVertex)
72                 return ICON_VERTEXSEL;
73         else if(rnatype == &RNA_MeshEdge)
74                 return ICON_EDGESEL;
75         else if(rnatype == &RNA_MeshFace)
76                 return ICON_FACESEL;
77         else if(rnatype == &RNA_MeshTextureFace)
78                 return ICON_FACESEL_HLT;
79         else if(rnatype == &RNA_VertexGroup)
80                 return ICON_VGROUP;
81         else if(rnatype == &RNA_VertexGroupElement)
82                 return ICON_VGROUP;
83         else if(rnatype == &RNA_Curve)
84                 return ICON_CURVE;
85         else if(rnatype == &RNA_MetaBall)
86                 return ICON_MBALL;
87         else if(rnatype == &RNA_MetaElement)
88                 return ICON_OUTLINER_DATA_META;
89         else if(rnatype == &RNA_Lattice)
90                 return ICON_LATTICE;
91         else if(rnatype == &RNA_Armature)
92                 return ICON_ARMATURE;
93         else if(rnatype == &RNA_Bone)
94                 return ICON_BONE_DEHLT;
95         else if(rnatype == &RNA_Camera)
96                 return ICON_CAMERA;
97         else if(rnatype == &RNA_LocalLamp)
98                 return ICON_LAMP;
99         else if(rnatype == &RNA_AreaLamp)
100                 return ICON_LAMP;
101         else if(rnatype == &RNA_SpotLamp)
102                 return ICON_LAMP;
103         else if(rnatype == &RNA_SunLamp)
104                 return ICON_LAMP;
105         else if(rnatype == &RNA_HemiLamp)
106                 return ICON_LAMP;
107         else if(rnatype == &RNA_Lamp)
108                 return ICON_LAMP;
109         else if(rnatype == &RNA_Group)
110                 return ICON_GROUP;
111         else if(rnatype == &RNA_ParticleSystem)
112                 return ICON_PARTICLES;
113         else if(rnatype == &RNA_ParticleSettings)
114                 return ICON_PARTICLES;
115         else if(rnatype == &RNA_Material)
116                 return ICON_MATERIAL;
117         else if(rnatype == &RNA_Texture)
118                 return ICON_TEXTURE;
119         else if(rnatype == &RNA_TextureSlot)
120                 return ICON_TEXTURE;
121         else if(rnatype == &RNA_WorldTextureSlot)
122                 return ICON_TEXTURE;
123         else if(rnatype == &RNA_MaterialTextureSlot)
124                 return ICON_TEXTURE;
125         else if(rnatype == &RNA_Image)
126                 return ICON_TEXTURE;
127         else if(rnatype == &RNA_Screen)
128                 return ICON_SPLITSCREEN;
129         else if(rnatype == &RNA_NodeTree)
130                 return ICON_NODE;
131         else if(rnatype == &RNA_Text)
132                 return ICON_TEXT;
133         else if(rnatype == &RNA_Sound)
134                 return ICON_SOUND;
135         else if(rnatype == &RNA_Brush)
136                 return ICON_TPAINT_HLT;
137         else if(rnatype == &RNA_Library)
138                 return ICON_LIBRARY_DEHLT;
139         else if(rnatype == &RNA_Action)
140                 return ICON_ACTION;
141         else if(rnatype == &RNA_FCurve)
142                 return ICON_IPO_DEHLT;
143         //else if(rnatype == &RNA_Ipo)
144         //      return ICON_IPO_DEHLT;
145         else if(rnatype == &RNA_Key)
146                 return ICON_SHAPEKEY;
147         else if(rnatype == &RNA_Main)
148                 return ICON_BLENDER;
149         else if(rnatype == &RNA_Struct)
150                 return ICON_RNA;
151         else if(rnatype == &RNA_Property)
152                 return ICON_RNA;
153         else if(rnatype == &RNA_BooleanProperty)
154                 return ICON_RNA;
155         else if(rnatype == &RNA_IntProperty)
156                 return ICON_RNA;
157         else if(rnatype == &RNA_FloatProperty)
158                 return ICON_RNA;
159         else if(rnatype == &RNA_StringProperty)
160                 return ICON_RNA;
161         else if(rnatype == &RNA_EnumProperty)
162                 return ICON_RNA;
163         else if(rnatype == &RNA_EnumPropertyItem)
164                 return ICON_RNA;
165         else if(rnatype == &RNA_PointerProperty)
166                 return ICON_RNA;
167         else if(rnatype == &RNA_CollectionProperty)
168                 return ICON_RNA;
169         else if(rnatype == &RNA_GameObjectSettings)
170                 return ICON_GAME;
171         else if(rnatype == &RNA_ScriptLink)
172                 return ICON_PYTHON;
173         
174         /* modifiers */
175         else if(rnatype == &RNA_SubsurfModifier)
176                 return ICON_MOD_SUBSURF;
177         else if(rnatype == &RNA_ArmatureModifier)
178                 return ICON_ARMATURE;
179         else if(rnatype == &RNA_LatticeModifier)
180                 return ICON_LATTICE;
181         else if(rnatype == &RNA_CurveModifier)
182                 return ICON_CURVE;
183         else if(rnatype == &RNA_BuildModifier)
184                 return ICON_MOD_BUILD;
185         else if(rnatype == &RNA_MirrorModifier)
186                 return ICON_MOD_MIRROR;
187         else if(rnatype == &RNA_DecimateModifier)
188                 return ICON_MOD_DECIM;
189         else if(rnatype == &RNA_WaveModifier)
190                 return ICON_MOD_WAVE;
191         else if(rnatype == &RNA_HookModifier)
192                 return ICON_HOOK;
193         else if(rnatype == &RNA_SoftbodyModifier)
194                 return ICON_MOD_SOFT;
195         else if(rnatype == &RNA_BooleanModifier)
196                 return ICON_MOD_BOOLEAN;
197         else if(rnatype == &RNA_ParticleInstanceModifier)
198                 return ICON_MOD_PARTICLEINSTANCE;
199         else if(rnatype == &RNA_ParticleSystemModifier)
200                 return ICON_MOD_PARTICLES;
201         else if(rnatype == &RNA_EdgeSplitModifier)
202                 return ICON_MOD_EDGESPLIT;
203         else if(rnatype == &RNA_ArrayModifier)
204                 return ICON_MOD_ARRAY;
205         else if(rnatype == &RNA_UVProjectModifier)
206                 return ICON_MOD_UVPROJECT;
207         else if(rnatype == &RNA_DisplaceModifier)
208                 return ICON_MOD_DISPLACE;
209         else
210                 return ICON_DOT;
211 }
212
213 uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, char *name, int x1, int y1, int x2, int y2)
214 {
215         uiBut *but=NULL;
216         const char *propname= RNA_property_identifier(ptr, prop);
217         int arraylen= RNA_property_array_length(ptr, prop);
218
219         switch(RNA_property_type(ptr, prop)) {
220                 case PROP_BOOLEAN: {
221                         int value, length;
222
223                         if(arraylen && index == -1)
224                                 return NULL;
225
226                         length= RNA_property_array_length(ptr, prop);
227
228                         if(length)
229                                 value= RNA_property_boolean_get_index(ptr, prop, index);
230                         else
231                                 value= RNA_property_boolean_get(ptr, prop);
232
233                         if(name && strcmp(name, "") == 0)
234                                 name= (value)? "Enabled": "Disabled";
235
236                         but= uiDefButR(block, TOG, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
237                         break;
238                 }
239                 case PROP_INT:
240                 case PROP_FLOAT:
241                         if(arraylen && index == -1) {
242                                 if(RNA_property_subtype(ptr, prop) == PROP_COLOR)
243                                         but= uiDefButR(block, COL, 0, name, x1, y1, x2, y2, ptr, propname, 0, 0, 0, -1, -1, NULL);
244                         }
245                         else
246                                 but= uiDefButR(block, NUM, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
247                         break;
248                 case PROP_ENUM:
249                         but= uiDefButR(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
250                         break;
251                 case PROP_STRING:
252                         but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
253                         break;
254                 case PROP_POINTER: {
255                         PointerRNA pptr;
256                         PropertyRNA *nameprop;
257                         char *text, *descr, textbuf[256];
258                         int icon;
259
260                         pptr= RNA_property_pointer_get(ptr, prop);
261
262                         if(!pptr.data)
263                                 return NULL;
264
265                         icon= UI_GetIconRNA(&pptr);
266                         nameprop= RNA_struct_name_property(&pptr);
267
268                         if(nameprop) {
269                                 text= RNA_property_string_get_alloc(&pptr, nameprop, textbuf, sizeof(textbuf));
270                                 descr= (char*)RNA_property_ui_description(&pptr, prop);
271                                 but= uiDefIconTextBut(block, LABEL, 0, icon, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, descr);
272                                 if(text != textbuf)
273                                         MEM_freeN(text);
274                         }
275                         else {
276                                 text= (char*)RNA_struct_ui_name(&pptr);
277                                 descr= (char*)RNA_property_ui_description(&pptr, prop);
278                                 but= uiDefIconTextBut(block, LABEL, 0, icon, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, descr);
279                         }
280                         break;
281                 }
282                 case PROP_COLLECTION: {
283                         char text[256];
284                         sprintf(text, "%d items", RNA_property_collection_length(ptr, prop));
285                         but= uiDefBut(block, LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
286                         uiButSetFlag(but, UI_BUT_DISABLED);
287                         break;
288                 }
289                 default:
290                         but= NULL;
291                         break;
292         }
293
294         return but;
295 }
296
297 int uiDefAutoButsRNA(uiBlock *block, PointerRNA *ptr)
298 {
299         CollectionPropertyIterator iter;
300         PropertyRNA *iterprop, *prop;
301         PropertySubType subtype;
302         char *name, namebuf[128];
303         int a, length, x= 0, y= 0;
304
305         x= 0;
306         y= 0;
307
308         /* create buttons */
309         uiSetCurFont(block, UI_HELVB);
310         uiDefBut(block, LABEL, 0, (char*)RNA_struct_ui_name(ptr), x, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1, NULL, 0, 0, 0, 0, "");
311         y -= DEF_BUT_HEIGHT;
312         uiSetCurFont(block, UI_HELV);
313
314         iterprop= RNA_struct_iterator_property(ptr);
315         RNA_property_collection_begin(ptr, iterprop, &iter);
316
317         for(; iter.valid; RNA_property_collection_next(&iter)) {
318                 prop= iter.ptr.data;
319
320                 if(strcmp(RNA_property_identifier(ptr, prop), "rna_type") == 0)
321                         continue;
322
323                 if((length= RNA_property_array_length(ptr, prop))) {
324                         name= (char*)RNA_property_ui_name(ptr, prop);
325                         uiDefBut(block, LABEL, 0, name, x, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1, NULL, 0, 0, 0, 0, "");
326                 }
327                 else
328                         length= 1;
329
330                 subtype= RNA_property_subtype(ptr, prop);
331
332                 name= (char*)RNA_property_ui_name(ptr, prop);
333                 uiDefBut(block, LABEL, 0, name, x, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1, NULL, 0, 0, 0, 0, "");
334
335                 uiBlockBeginAlign(block);
336
337                 if(length <= 16 && subtype == PROP_MATRIX) {
338                         /* matrix layout */
339                         int size, row, col, butwidth;
340
341                         size= ceil(sqrt(length));
342                         butwidth= DEF_BUT_WIDTH*2/size;
343                         y -= DEF_BUT_HEIGHT;
344
345                         for(a=0; a<length; a++) {
346                                 col= a%size;
347                                 row= a/size;
348
349                                 uiDefAutoButR(block, ptr, prop, a, "", x+butwidth*col, y-row*DEF_BUT_HEIGHT, butwidth, DEF_BUT_HEIGHT-1);
350                         }
351
352                         y -= DEF_BUT_HEIGHT*(length/size);
353                 }
354                 else if(length <= 4 && ELEM3(subtype, PROP_ROTATION, PROP_VECTOR, PROP_COLOR)) {
355                         static char *vectoritem[4]= {"X:", "Y:", "Z:", "W:"};
356                         static char *quatitem[4]= {"W:", "X:", "Y:", "Z:"};
357                         static char *coloritem[4]= {"R:", "G:", "B:", "A:"};
358                         int butwidth;
359
360                         butwidth= DEF_BUT_WIDTH*2/length;
361                         y -= DEF_BUT_HEIGHT;
362
363                         for(a=0; a<length; a++) {
364                                 if(length == 4 && subtype == PROP_ROTATION)
365                                         name= quatitem[a];
366                                 else if(subtype == PROP_VECTOR || subtype == PROP_ROTATION)
367                                         name= vectoritem[a];
368                                 else
369                                         name= coloritem[a];
370
371                                 uiDefAutoButR(block, ptr, prop, a, name, x+butwidth*a, y, butwidth, DEF_BUT_HEIGHT-1);
372                         }
373                         y -= DEF_BUT_HEIGHT;
374                 }
375                 else {
376                         if(RNA_property_array_length(ptr, prop)) {
377                                 sprintf(namebuf, "%d:", a+1);
378                                 name= namebuf;
379                         }
380                         else
381                                 name= "";
382
383                         uiDefAutoButR(block, ptr, prop, a, name, x+DEF_BUT_WIDTH, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1);
384                         y -= DEF_BUT_HEIGHT;
385                 }
386
387                 uiBlockEndAlign(block);
388         }
389
390         RNA_property_collection_end(&iter);
391
392         return -y;
393 }
394
395 /***************************** ID Utilities *******************************/
396
397 typedef struct uiIDPoinParams {
398         uiIDPoinFunc func;
399         ID **id_p;
400         short id_code;
401         short browsenr;
402 } uiIDPoinParams;
403
404 static void idpoin_cb(bContext *C, void *arg_params, void *arg_event)
405 {
406         Main *bmain;
407         ListBase *lb;
408         uiIDPoinParams *params= (uiIDPoinParams*)arg_params;
409         uiIDPoinFunc func= params->func;
410         ID **id_p= params->id_p;
411         ID *id= *id_p, *idtest;
412         int nr, event= GET_INT_FROM_POINTER(arg_event);
413
414         bmain= CTX_data_main(C);
415         lb= wich_libbase(bmain, params->id_code);
416
417         switch(event) {
418                 case UI_ID_RENAME:
419                         if(id) test_idbutton(id->name+2);
420                         else return;
421                         break;
422                 case UI_ID_BROWSE: {
423                         if(id==0) id= lb->first;
424                         if(id==0) return;
425
426                         if(params->browsenr== -2) {
427                                 /* XXX implement or find a replacement
428                                  * activate_databrowse((ID *)G.buts->lockpoin, GS(id->name), 0, B_MESHBROWSE, &params->browsenr, do_global_buttons); */
429                                 return;
430                         }
431                         if(params->browsenr < 0)
432                                 return;
433
434                         for(idtest=lb->first, nr=1; idtest; idtest=idtest->next, nr++) {
435                                 if(nr==params->browsenr) {
436                                         if(id == idtest)
437                                                 return;
438
439                                         *id_p= idtest;
440                                         break;
441                                 }
442                         }
443                         break;
444                 }
445                 case UI_ID_DELETE:
446                         *id_p= NULL;
447                         break;
448                 case UI_ID_FAKE_USER:
449                         if(id) {
450                                 if(id->flag & LIB_FAKEUSER) id->us++;
451                                 else id->us--;
452                         }
453                         else return;
454                         break;
455                 case UI_ID_PIN:
456                         break;
457                 case UI_ID_ADD_NEW:
458                         break;
459                 case UI_ID_OPEN:
460                         break;
461                 case UI_ID_ALONE:
462                         if(!id || id->us < 1)
463                                 return;
464                         break;
465                 case UI_ID_LOCAL:
466                         if(!id || id->us < 1)
467                                 return;
468                         break;
469                 case UI_ID_AUTO_NAME:
470                         break;
471         }
472
473         if(func)
474                 func(C, *id_p, event);
475 }
476
477 int uiDefIDPoinButs(uiBlock *block, Main *bmain, ID *parid, ID **id_p, int id_code, short *pin_p, int x, int y, uiIDPoinFunc func, int events)
478 {
479         ListBase *lb;
480         uiBut *but;
481         ID *id= *id_p;
482         uiIDPoinParams *params, *dup_params;
483         char *str=NULL, str1[10];
484         int len, oldcol, add_addbutton=0;
485
486         /* setup struct that we will pass on with the buttons */
487         params= MEM_callocN(sizeof(uiIDPoinParams), "uiIDPoinParams");
488         params->id_p= id_p;
489         params->id_code= id_code;
490         params->func= func;
491
492         lb= wich_libbase(bmain, id_code);
493
494         /* create buttons */
495         uiBlockBeginAlign(block);
496         oldcol= uiBlockGetCol(block);
497
498         if(id && id->us>1)
499                 uiBlockSetCol(block, TH_BUT_SETTING1);
500
501         if((events & UI_ID_PIN) && *pin_p)
502                 uiBlockSetCol(block, TH_BUT_SETTING2);
503
504         /* pin button */
505         if(id && (events & UI_ID_PIN)) {
506                 but= uiDefIconButS(block, ICONTOG, (events & UI_ID_PIN), 0 /* XXX ICON_PIN_DEHLT */, x, y ,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, pin_p, 0, 0, 0, 0, "Keeps this view displaying the current data regardless of what object is selected");
507                 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_PIN));
508                 x+= DEF_ICON_BUT_WIDTH;
509         }
510
511         /* browse menu */
512         if(events & UI_ID_BROWSE) {
513                 char *extrastr= NULL;
514                 
515                 if(ELEM4(id_code, ID_MA, ID_TE, ID_BR, ID_PA))
516                         add_addbutton= 1;
517                 
518                 if(ELEM8(id_code, ID_SCE, ID_SCR, ID_MA, ID_TE, ID_WO, ID_IP, ID_AC, ID_BR) || id_code == ID_PA)
519                         extrastr= "ADD NEW %x 32767";
520                 else if(id_code==ID_TXT)
521                         extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767";
522                 else if(id_code==ID_SO)
523                         extrastr= "OPEN NEW %x 32766";
524
525                 /* XXX should be moved out of this function
526                 uiBlockSetButLock(block, G.scene->id.lib!=0, "Can't edit external libdata");
527                 if( id_code==ID_SCE || id_code==ID_SCR ) uiBlockClearButLock(block); */
528                 
529                 /* XXX should be moved out of this function
530                 if(curarea->spacetype==SPACE_BUTS)
531                         uiBlockSetButLock(block, id_code!=ID_SCR && G.obedit!=0 && G.buts->mainb==CONTEXT_EDITING, "Cannot perform in EditMode"); */
532                 
533                 if(parid)
534                         uiBlockSetButLock(block, parid->lib!=0, "Can't edit external libdata");
535
536                 if(lb) {
537                         if(id_code!=ID_IM || (events & UI_ID_BROWSE_RENDER))
538                                 IDnames_to_pupstring(&str, NULL, extrastr, lb, id, &params->browsenr);
539                         else
540                                 IMAnames_to_pupstring(&str, NULL, extrastr, lb, id, &params->browsenr);
541                 }
542
543                 dup_params= MEM_dupallocN(params);
544                 but= uiDefButS(block, MENU, 0, str, x, y, DEF_ICON_BUT_WIDTH, DEF_BUT_HEIGHT, &dup_params->browsenr, 0, 0, 0, 0, "Browse existing choices, or add new");
545                 uiButSetNFunc(but, idpoin_cb, dup_params, SET_INT_IN_POINTER(UI_ID_BROWSE));
546                 x+= DEF_ICON_BUT_WIDTH;
547                 
548                 uiBlockClearButLock(block);
549         
550                 MEM_freeN(str);
551         }
552
553         uiBlockSetCol(block, oldcol);
554
555         /* text button with name */
556         if(id) {
557                 /* name */
558                 if(id->us > 1)
559                         uiBlockSetCol(block, TH_BUT_SETTING1);
560
561                 /* pinned data? */
562                 if((events & UI_ID_PIN) && *pin_p)
563                         uiBlockSetCol(block, TH_BUT_SETTING2);
564
565                 /* redalert overrides pin color */
566                 if(id->us<=0)
567                         uiBlockSetCol(block, TH_REDALERT);
568
569                 uiBlockSetButLock(block, id->lib!=0, "Can't edit external libdata");
570                 
571                 /* name button */
572                 if(GS(id->name)==ID_SCE)
573                         strcpy(str1, "SCE:");
574                 else if(GS(id->name)==ID_SCE)
575                         strcpy(str1, "SCR:");
576                 else if(GS(id->name)==ID_MA && ((Material*)id)->use_nodes)
577                         strcpy(str1, "NT:");
578                 else {
579                         str1[0]= id->name[0];
580                         str1[1]= id->name[1];
581                         str1[2]= ':';
582                         str1[3]= 0;
583                 }
584                 
585                 if(GS(id->name)==ID_IP) len= 110;
586                 else if((y) && (GS(id->name)==ID_AC)) len= 100; // comes from button panel (poselib)
587                 else if(y) len= 140;    // comes from button panel
588                 else len= 120;
589                 
590                 but= uiDefBut(block, TEX, 0, str1,x, y, (short)len, DEF_BUT_HEIGHT, id->name+2, 0.0, 21.0, 0, 0, "Displays current Datablock name. Click to change.");
591                 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_RENAME));
592
593                 x+= len;
594
595                 uiBlockClearButLock(block);
596                 
597                 /* lib make local button */
598                 if(id->lib) {
599                         if(id->flag & LIB_INDIRECT) uiDefIconBut(block, BUT, 0, 0 /* XXX ICON_DATALIB */,x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Indirect Library Datablock. Cannot change.");
600                         else {
601                                 but= uiDefIconBut(block, BUT, 0, 0 /* XXX ICON_PARLIB */, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, 
602                                                           (events & UI_ID_LOCAL)? "Direct linked Library Datablock. Click to make local.": "Direct linked Library Datablock, cannot make local.");
603                                 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ALONE));
604                         }
605                         
606                         x+= DEF_ICON_BUT_WIDTH;
607                 }
608                 
609                 /* number of users / make local button */
610                 if((events & UI_ID_ALONE) && id->us>1) {
611                         int butwidth;
612
613                         uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't make pinned data single-user");
614                         
615                         sprintf(str1, "%d", id->us);
616                         butwidth= (id->us<10)? DEF_ICON_BUT_WIDTH: DEF_ICON_BUT_WIDTH+10;
617
618                         but= uiDefBut(block, BUT, 0, str1, x, y, butwidth, DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
619                         uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ALONE));
620                         x+= butwidth;
621                         
622                         uiBlockClearButLock(block);
623                 }
624                 
625                 /* delete button */
626                 if(events & UI_ID_DELETE) {
627                         uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't unlink pinned data");
628                         if(parid && parid->lib);
629                         else {
630                                 but= uiDefIconBut(block, BUT, 0, ICON_X, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Deletes link to this Datablock");
631                                 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_DELETE));
632                                 x+= DEF_ICON_BUT_WIDTH;
633                         }
634                         
635                         uiBlockClearButLock(block);
636                 }
637
638                 /* auto name button */
639                 if(events & UI_ID_AUTO_NAME) {
640                         if(parid && parid->lib);
641                         else {
642                                 but= uiDefIconBut(block, BUT, 0, ICON_AUTO,x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Generates an automatic name");
643                                 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_AUTO_NAME));
644                                 x+= DEF_ICON_BUT_WIDTH;
645                         }
646                 }
647
648                 /* fake user button */
649                 if(events & UI_ID_FAKE_USER) {
650                         but= uiDefButBitS(block, TOG, LIB_FAKEUSER, 0, "F", x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, &id->flag, 0, 0, 0, 0, "Saves this datablock even if it has no users");
651                         uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_FAKE_USER));
652                         x+= DEF_ICON_BUT_WIDTH;
653                 }
654         }
655         /* add new button */
656         else if(add_addbutton) {
657                 uiBlockSetCol(block, oldcol);
658                 if(parid) uiBlockSetButLock(block, parid->lib!=0, "Can't edit external libdata");
659                 dup_params= MEM_dupallocN(params);
660                 but= uiDefButS(block, TOG, 0, "Add New", x, y, 110, DEF_BUT_HEIGHT, &dup_params->browsenr, params->browsenr, 32767.0, 0, 0, "Add new data block");
661                 uiButSetNFunc(but, idpoin_cb, dup_params, SET_INT_IN_POINTER(UI_ID_ADD_NEW));
662                 x+= 110;
663         }
664         
665         uiBlockSetCol(block, oldcol);
666         uiBlockEndAlign(block);
667
668         MEM_freeN(params);
669
670         return x;
671 }
672