Patch by Matt Ebb: upgraded usablitiy of text button.
[blender.git] / source / blender / python / api2_2x / windowTheme.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * This is a new part of Blender.
27  *
28  * Contributor(s): Willian P. Germano
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31 */
32
33 #include "windowTheme.h" /*This must come first*/
34
35 #include "BLI_blenlib.h"
36 #include "MEM_guardedalloc.h"
37 #include "charRGBA.h"
38 #include "gen_utils.h"
39
40 #define EXPP_THEME_VTX_SIZE_MIN 1
41 #define EXPP_THEME_VTX_SIZE_MAX 10
42 #define EXPP_THEME_FDOT_SIZE_MIN 1
43 #define EXPP_THEME_FDOT_SIZE_MAX 10
44 #define EXPP_THEME_DRAWTYPE_MIN 1
45 #define EXPP_THEME_DRAWTYPE_MAX 4
46
47 #define EXPP_THEME_NUMBEROFTHEMES 15
48 static const EXPP_map_pair themes_map[] = {
49         {"ui", -1},
50         {"buts", SPACE_BUTS},
51         {"view3d", SPACE_VIEW3D},
52         {"file", SPACE_FILE},
53         {"ipo", SPACE_IPO},
54         {"info", SPACE_INFO},
55         {"sound", SPACE_SOUND},
56         {"action", SPACE_ACTION},
57         {"nla", SPACE_NLA},
58         {"seq", SPACE_SEQ},
59         {"image", SPACE_IMAGE},
60         {"imasel", SPACE_IMASEL},
61         {"text", SPACE_TEXT},
62         {"oops", SPACE_OOPS},
63         {"time", SPACE_TIME},
64         {NULL, 0}
65 };
66
67 static PyObject *M_Theme_New( PyObject * self, PyObject * args );
68 static PyObject *M_Theme_Get( PyObject * self, PyObject * args );
69
70 static char M_Theme_doc[] = "The Blender Theme module\n\n\
71 This module provides access to UI Theme data in Blender";
72
73 static char M_Theme_New_doc[] = "Theme.New (name = 'New Theme',\
74 theme = <default>):\n\
75         Return a new Theme Data object.\n\
76 (name) - string: the Theme's name, it defaults to 'New Theme';\n\
77 (theme) - bpy Theme: a base Theme to copy all data from, it defaults to the\n\
78 current one.";
79
80 static char M_Theme_Get_doc[] = "Theme.Get (name = None):\n\
81         Return the theme data with the given 'name', None if not found, or\n\
82         Return a list with all Theme Data objects if no argument was given.";
83
84 /*****************************************************************************/
85 /* Python method structure definition for Blender.Theme module:            */
86 /*****************************************************************************/
87 struct PyMethodDef M_Theme_methods[] = {
88         {"New", M_Theme_New, METH_VARARGS, M_Theme_New_doc},
89         {"Get", M_Theme_Get, METH_VARARGS, M_Theme_Get_doc},
90         {NULL, NULL, 0, NULL}
91 };
92
93 static void ThemeSpace_dealloc( BPy_ThemeSpace * self );
94 static int ThemeSpace_compare( BPy_ThemeSpace * a, BPy_ThemeSpace * b );
95 static PyObject *ThemeSpace_repr( BPy_ThemeSpace * self );
96 static PyObject *ThemeSpace_getAttr( BPy_ThemeSpace * self, char *name );
97 static int ThemeSpace_setAttr( BPy_ThemeSpace * self, char *name,
98                                PyObject * val );
99
100 static PyMethodDef BPy_ThemeSpace_methods[] = {
101         {NULL, NULL, 0, NULL}
102 };
103
104 PyTypeObject ThemeSpace_Type = {
105         PyObject_HEAD_INIT( NULL ) 0,   /* ob_size */
106         "Blender Space Theme",  /* tp_name */
107         sizeof( BPy_ThemeSpace ),       /* tp_basicsize */
108         0,                      /* tp_itemsize */
109         /* methods */
110         ( destructor ) ThemeSpace_dealloc,      /* tp_dealloc */
111         0,                      /* tp_print */
112         ( getattrfunc ) ThemeSpace_getAttr,     /* tp_getattr */
113         ( setattrfunc ) ThemeSpace_setAttr,     /* tp_setattr */
114         ( cmpfunc ) ThemeSpace_compare, /* tp_compare */
115         ( reprfunc ) ThemeSpace_repr,   /* tp_repr */
116         0,                      /* tp_as_number */
117         0,                      /* tp_as_sequence */
118         0,                      /* tp_as_mapping */
119         0,                      /* tp_as_hash */
120         0, 0, 0, 0, 0, 0,
121         0,                      /* tp_doc */
122         0, 0, 0, 0, 0, 0,
123         0,                      //BPy_ThemeSpace_methods,            /* tp_methods */
124         0,                      /* tp_members */
125         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
126 };
127
128 static void ThemeSpace_dealloc( BPy_ThemeSpace * self )
129 {
130         PyObject_DEL( self );
131 }
132
133 #define ELSEIF_TSP_RGBA(attr)\
134         else if (!strcmp(name, #attr))\
135                 attrib = charRGBA_New(&tsp->attr[0]);
136
137 /* Example: ELSEIF_TSP_RGBA(back) becomes:
138  * else if (!strcmp(name, "back")
139  *      attrib = charRGBA_New(&tsp->back[0])
140  */
141
142 static PyObject *ThemeSpace_getAttr( BPy_ThemeSpace * self, char *name )
143 {
144         PyObject *attrib = Py_None;
145         ThemeSpace *tsp = self->tsp;
146
147         if( !strcmp( name, "theme" ) )
148                 attrib = PyString_FromString( self->theme->name );
149                 ELSEIF_TSP_RGBA( back )
150                 ELSEIF_TSP_RGBA( text )
151                 ELSEIF_TSP_RGBA( text_hi )
152                 ELSEIF_TSP_RGBA( header )
153                 ELSEIF_TSP_RGBA( panel )
154                 ELSEIF_TSP_RGBA( shade1 )
155                 ELSEIF_TSP_RGBA( shade2 )
156                 ELSEIF_TSP_RGBA( hilite )
157                 ELSEIF_TSP_RGBA( grid )
158                 ELSEIF_TSP_RGBA( wire )
159                 ELSEIF_TSP_RGBA( lamp )
160                 ELSEIF_TSP_RGBA( select )
161                 ELSEIF_TSP_RGBA( active )
162                 ELSEIF_TSP_RGBA( transform )
163                 ELSEIF_TSP_RGBA( vertex )
164                 ELSEIF_TSP_RGBA( vertex_select )
165                 ELSEIF_TSP_RGBA( edge )
166                 ELSEIF_TSP_RGBA( edge_select )
167                 ELSEIF_TSP_RGBA( edge_seam )
168                 ELSEIF_TSP_RGBA( edge_facesel )
169                 ELSEIF_TSP_RGBA( face )
170                 ELSEIF_TSP_RGBA( face_select )
171                 ELSEIF_TSP_RGBA( face_dot )
172                 ELSEIF_TSP_RGBA( normal )
173                 ELSEIF_TSP_RGBA( syntaxl )
174                 ELSEIF_TSP_RGBA( syntaxn )
175                 ELSEIF_TSP_RGBA( syntaxb )
176                 ELSEIF_TSP_RGBA( syntaxv )
177                 ELSEIF_TSP_RGBA( syntaxc )
178                 else if( !strcmp( name, "vertex_size" ) )
179                 attrib = Py_BuildValue( "i", tsp->vertex_size );
180                 else if( !strcmp( name, "facedot_size" ) )
181                 attrib = Py_BuildValue( "i", tsp->facedot_size );
182         else if( !strcmp( name, "__members__" ) )
183                 attrib = Py_BuildValue( "[sssssssssssssssssssssssssssssss]", "theme",
184                                         "back", "text", "text_hi", "header",
185                                         "panel", "shade1", "shade2", "hilite",
186                                         "grid", "wire", "lamp", "select", "active",
187                                         "transform", "vertex", "vertex_select",
188                                         "edge", "edge_select", "edge_seam",
189                                         "edge_facesel", "face", "face_select",
190                                         "face_dot", "normal",
191                                         "syntaxl", "syntaxn", "syntaxb", "syntaxv", "syntaxc",
192                                         "vertex_size", "facedot_size" );
193
194         if( attrib != Py_None )
195                 return attrib;
196
197         return Py_FindMethod( BPy_ThemeSpace_methods, ( PyObject * ) self,
198                               name );
199 }
200
201 static int ThemeSpace_setAttr( BPy_ThemeSpace * self, char *name,
202                                PyObject * value )
203 {
204         PyObject *attrib = NULL;
205         ThemeSpace *tsp = self->tsp;
206         int ret = -1;
207
208         if( !strcmp( name, "back" ) )
209                 attrib = charRGBA_New( &tsp->back[0] );
210                 ELSEIF_TSP_RGBA( text )
211                 ELSEIF_TSP_RGBA( text_hi )
212                 ELSEIF_TSP_RGBA( header )
213                 ELSEIF_TSP_RGBA( panel )
214                 ELSEIF_TSP_RGBA( shade1 )
215                 ELSEIF_TSP_RGBA( shade2 )
216                 ELSEIF_TSP_RGBA( hilite )
217                 ELSEIF_TSP_RGBA( grid )
218                 ELSEIF_TSP_RGBA( wire )
219                 ELSEIF_TSP_RGBA( lamp )
220                 ELSEIF_TSP_RGBA( select )
221                 ELSEIF_TSP_RGBA( active )
222                 ELSEIF_TSP_RGBA( transform )
223                 ELSEIF_TSP_RGBA( vertex )
224                 ELSEIF_TSP_RGBA( vertex_select )
225                 ELSEIF_TSP_RGBA( edge )
226                 ELSEIF_TSP_RGBA( edge_select )
227                 ELSEIF_TSP_RGBA( edge_seam )
228                 ELSEIF_TSP_RGBA( edge_facesel )
229                 ELSEIF_TSP_RGBA( face )
230                 ELSEIF_TSP_RGBA( face_select )
231                 ELSEIF_TSP_RGBA( face_dot )
232                 ELSEIF_TSP_RGBA( normal )
233                 ELSEIF_TSP_RGBA( syntaxl )
234                 ELSEIF_TSP_RGBA( syntaxn )
235                 ELSEIF_TSP_RGBA( syntaxb )
236                 ELSEIF_TSP_RGBA( syntaxv )
237                 ELSEIF_TSP_RGBA( syntaxc )
238                 else if( !strcmp( name, "vertex_size" ) ) {
239                 int val;
240
241                 if( !PyInt_Check( value ) )
242                         return EXPP_ReturnIntError( PyExc_TypeError,
243                                                     "expected integer value" );
244
245                 val = ( int ) PyInt_AsLong( value );
246                 tsp->vertex_size = (char)EXPP_ClampInt( val,
247                                                   EXPP_THEME_VTX_SIZE_MIN,
248                                                   EXPP_THEME_VTX_SIZE_MAX );
249                 ret = 0;
250         }
251         else if( !strcmp( name, "facedot_size" ) ) {
252                 int val;
253
254                 if( !PyInt_Check( value ) )
255                         return EXPP_ReturnIntError( PyExc_TypeError,
256                                                     "expected integer value" );
257
258                 val = ( int ) PyInt_AsLong( value );
259                 tsp->vertex_size = (char)EXPP_ClampInt( val,
260                                                   EXPP_THEME_FDOT_SIZE_MIN,
261                                                   EXPP_THEME_FDOT_SIZE_MAX );
262                 ret = 0;
263         } else
264                 return EXPP_ReturnIntError( PyExc_AttributeError,
265                                             "attribute not found" );
266
267         if( attrib ) {
268                 PyObject *pyret = NULL;
269                 PyObject *valtuple = Py_BuildValue( "(O)", value );
270
271                 if( !valtuple )
272                         return EXPP_ReturnIntError( PyExc_MemoryError,
273                                                     "couldn't create tuple!" );
274
275                 pyret = charRGBA_setCol( ( BPy_charRGBA * ) attrib, valtuple );
276                 Py_DECREF( valtuple );
277
278                 if( pyret == Py_None ) {
279                         Py_DECREF( Py_None );   /* was increfed by charRGBA_setCol */
280                         ret = 0;
281                 }
282
283                 Py_DECREF( attrib );    /* we're done with it */
284         }
285
286         return ret;             /* 0 if all went well */
287 }
288
289 static int ThemeSpace_compare( BPy_ThemeSpace * a, BPy_ThemeSpace * b )
290 {
291         ThemeSpace *pa = a->tsp, *pb = b->tsp;
292         return ( pa == pb ) ? 0 : -1;
293 }
294
295 static PyObject *ThemeSpace_repr( BPy_ThemeSpace * self )
296 {
297         return PyString_FromFormat( "[Space theme from theme \"%s\"]",
298                                     self->theme->name );
299 }
300
301 static void ThemeUI_dealloc( BPy_ThemeUI * self );
302 static int ThemeUI_compare( BPy_ThemeUI * a, BPy_ThemeUI * b );
303 static PyObject *ThemeUI_repr( BPy_ThemeUI * self );
304 static PyObject *ThemeUI_getAttr( BPy_ThemeUI * self, char *name );
305 static int ThemeUI_setAttr( BPy_ThemeUI * self, char *name, PyObject * val );
306
307 static PyMethodDef BPy_ThemeUI_methods[] = {
308         {NULL, NULL, 0, NULL}
309 };
310
311 PyTypeObject ThemeUI_Type = {
312         PyObject_HEAD_INIT( NULL ) 0,   /* ob_size */
313         "Blender UI Theme",     /* tp_name */
314         sizeof( BPy_ThemeUI ),  /* tp_basicsize */
315         0,                      /* tp_itemsize */
316         /* methods */
317         ( destructor ) ThemeUI_dealloc, /* tp_dealloc */
318         0,                      /* tp_print */
319         ( getattrfunc ) ThemeUI_getAttr,        /* tp_getattr */
320         ( setattrfunc ) ThemeUI_setAttr,        /* tp_setattr */
321         ( cmpfunc ) ThemeUI_compare,    /* tp_compare */
322         ( reprfunc ) ThemeUI_repr,      /* tp_repr */
323         0,                      /* tp_as_number */
324         0,                      /* tp_as_sequence */
325         0,                      /* tp_as_mapping */
326         0,                      /* tp_as_hash */
327         0, 0, 0, 0, 0, 0,
328         0,                      /* tp_doc */
329         0, 0, 0, 0, 0, 0,
330         0,                      //BPy_ThemeUI_methods,         /* tp_methods */
331         0,                      /* tp_members */
332         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
333 };
334
335 static void ThemeUI_dealloc( BPy_ThemeUI * self )
336 {
337         PyObject_DEL( self );
338 }
339
340 #define ELSEIF_TUI_RGBA(attr)\
341         else if (!strcmp(name, #attr))\
342                 attrib = charRGBA_New(&tui->attr[0]);
343
344 /* Example: ELSEIF_TUI_RGBA(outline) becomes:
345  * else if (!strcmp(name, "outline")
346  *      attr = charRGBA_New(&tui->outline[0])
347  */
348
349 static PyObject *ThemeUI_getAttr( BPy_ThemeUI * self, char *name )
350 {
351         PyObject *attrib = Py_None;
352         ThemeUI *tui = self->tui;
353
354         if( !strcmp( name, "theme" ) )
355                 attrib = PyString_FromString( self->theme->name );
356         ELSEIF_TUI_RGBA( outline )
357                 ELSEIF_TUI_RGBA( neutral )
358                 ELSEIF_TUI_RGBA( action )
359                 ELSEIF_TUI_RGBA( setting )
360                 ELSEIF_TUI_RGBA( setting1 )
361                 ELSEIF_TUI_RGBA( setting2 )
362                 ELSEIF_TUI_RGBA( num )
363                 ELSEIF_TUI_RGBA( textfield )
364                 ELSEIF_TUI_RGBA( textfield_hi )
365                 ELSEIF_TUI_RGBA( popup )
366                 ELSEIF_TUI_RGBA( text )
367                 ELSEIF_TUI_RGBA( text_hi )
368                 ELSEIF_TUI_RGBA( menu_back )
369                 ELSEIF_TUI_RGBA( menu_item )
370                 ELSEIF_TUI_RGBA( menu_hilite )
371                 ELSEIF_TUI_RGBA( menu_text )
372                 ELSEIF_TUI_RGBA( menu_text_hi )
373                 else if( !strcmp( name, "drawType" ) )
374                 attrib = PyInt_FromLong( ( char ) tui->but_drawtype );
375         else if( !strcmp( name, "__members__" ) )
376                 attrib = Py_BuildValue( "[ssssssssssssssssss]", "theme",
377                                         "outline", "neutral", "action",
378                                         "setting", "setting1", "setting2",
379                                         "num", "textfield", "textfield_hi", "popup", "text",
380                                         "text_hi", "menu_back", "menu_item",
381                                         "menu_hilite", "menu_text",
382                                         "menu_text_hi", "drawType" );
383
384         if( attrib != Py_None )
385                 return attrib;
386
387         return Py_FindMethod( BPy_ThemeUI_methods, ( PyObject * ) self, name );
388 }
389
390 static int ThemeUI_setAttr( BPy_ThemeUI * self, char *name, PyObject * value )
391 {
392         PyObject *attrib = NULL;
393         ThemeUI *tui = self->tui;
394         int ret = -1;
395
396         if( !strcmp( name, "outline" ) )
397                 attrib = charRGBA_New( &tui->outline[0] );
398         ELSEIF_TUI_RGBA( neutral )
399                 ELSEIF_TUI_RGBA( action )
400                 ELSEIF_TUI_RGBA( setting )
401                 ELSEIF_TUI_RGBA( setting1 )
402                 ELSEIF_TUI_RGBA( setting2 )
403                 ELSEIF_TUI_RGBA( num )
404                 ELSEIF_TUI_RGBA( textfield )
405                 ELSEIF_TUI_RGBA( textfield_hi )
406                 ELSEIF_TUI_RGBA( popup )
407                 ELSEIF_TUI_RGBA( text )
408                 ELSEIF_TUI_RGBA( text_hi )
409                 ELSEIF_TUI_RGBA( menu_back )
410                 ELSEIF_TUI_RGBA( menu_item )
411                 ELSEIF_TUI_RGBA( menu_hilite )
412                 ELSEIF_TUI_RGBA( menu_text )
413                 ELSEIF_TUI_RGBA( menu_text_hi )
414                 else if( !strcmp( name, "drawType" ) ) {
415                 int val;
416
417                 if( !PyInt_Check( value ) )
418                         return EXPP_ReturnIntError( PyExc_TypeError,
419                                                     "expected integer value" );
420
421                 val = ( int ) PyInt_AsLong( value );
422                 tui->but_drawtype = (char)EXPP_ClampInt( val,
423                                                    EXPP_THEME_DRAWTYPE_MIN,
424                                                    EXPP_THEME_DRAWTYPE_MAX );
425                 ret = 0;
426         } else
427                 return EXPP_ReturnIntError( PyExc_AttributeError,
428                                             "attribute not found" );
429
430         if( attrib ) {
431                 PyObject *pyret = NULL;
432                 PyObject *valtuple = Py_BuildValue( "(O)", value );
433
434                 if( !valtuple )
435                         return EXPP_ReturnIntError( PyExc_MemoryError,
436                                                     "couldn't create tuple!" );
437
438                 pyret = charRGBA_setCol( ( BPy_charRGBA * ) attrib, valtuple );
439                 Py_DECREF( valtuple );
440
441                 if( pyret == Py_None ) {
442                         Py_DECREF( Py_None );   /* was increfed by charRGBA_setCol */
443                         ret = 0;
444                 }
445
446                 Py_DECREF( attrib );    /* we're done with it */
447         }
448
449         return ret;             /* 0 if all went well */
450 }
451
452
453 static int ThemeUI_compare( BPy_ThemeUI * a, BPy_ThemeUI * b )
454 {
455         ThemeUI *pa = a->tui, *pb = b->tui;
456         return ( pa == pb ) ? 0 : -1;
457 }
458
459 static PyObject *ThemeUI_repr( BPy_ThemeUI * self )
460 {
461         return PyString_FromFormat( "[UI theme from theme \"%s\"]",
462                                     self->theme->name );
463 }
464
465 static void Theme_dealloc( BPy_Theme * self );
466 static int Theme_compare( BPy_Theme * a, BPy_Theme * b );
467 static PyObject *Theme_getAttr( BPy_Theme * self, char *name );
468 static PyObject *Theme_repr( BPy_Theme * self );
469
470 static PyObject *Theme_get( BPy_Theme * self, PyObject * args );
471 static PyObject *Theme_getName( BPy_Theme * self );
472 static PyObject *Theme_setName( BPy_Theme * self, PyObject * args );
473
474 static PyMethodDef BPy_Theme_methods[] = {
475         {"get", ( PyCFunction ) Theme_get, METH_VARARGS,
476          "(param) - Return UI or Space theme object.\n\
477 (param) - the chosen theme object as an int or a string:\n\
478 - () - default: UI;\n\
479 - (i) - int: an entry from the Blender.Window.Types dictionary;\n\
480 - (s) - string: 'UI' or a space name, like 'VIEW3D', etc."},
481         {"getName", ( PyCFunction ) Theme_getName, METH_NOARGS,
482          "() - Return Theme name"},
483         {"setName", ( PyCFunction ) Theme_setName, METH_VARARGS,
484          "(s) - Set Theme name"},
485         {NULL, NULL, 0, NULL}
486 };
487
488 PyTypeObject Theme_Type = {
489         PyObject_HEAD_INIT( NULL ) 
490         0,      /* ob_size */
491         "Blender Theme",        /* tp_name */
492         sizeof( BPy_Theme ),    /* tp_basicsize */
493         0,                      /* tp_itemsize */
494         /* methods */
495         ( destructor ) Theme_dealloc,   /* tp_dealloc */
496         0,                      /* tp_print */
497         ( getattrfunc ) Theme_getAttr,  /* tp_getattr */
498         0,                      //(setattrfunc) Theme_setAttr,        /* tp_setattr */
499         ( cmpfunc ) Theme_compare,      /* tp_compare */
500         ( reprfunc ) Theme_repr,        /* tp_repr */
501         0,                      /* tp_as_number */
502         0,                      /* tp_as_sequence */
503         0,                      /* tp_as_mapping */
504         0,                      /* tp_as_hash */
505         0, 0, 0, 0, 0, 0,
506         0,                      /* tp_doc */
507         0, 0, 0, 0, 0, 0,
508         0,                      /*BPy_Theme_methods,*/ /* tp_methods */
509         0,                      /* tp_members */
510         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
511 };
512
513 static PyObject *M_Theme_New( PyObject * self, PyObject * args )
514 {
515         char *name = "New Theme";
516         BPy_Theme *pytheme = NULL, *base_pytheme = NULL;
517         bTheme *btheme = NULL, *newtheme = NULL;
518
519         if( !PyArg_ParseTuple
520             ( args, "|sO!", &name, &Theme_Type, &base_pytheme ) )
521                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
522                                               "expected nothing or a name and optional theme object as arguments" );
523
524         if( base_pytheme )
525                 btheme = base_pytheme->theme;
526         if( !btheme )
527                 btheme = U.themes.first;
528
529         newtheme = MEM_callocN( sizeof( bTheme ), "theme" );
530
531         if( newtheme )
532                 pytheme = PyObject_New( BPy_Theme, &Theme_Type );
533         if( !pytheme )
534                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
535                                               "couldn't create Theme Data in Blender" );
536
537         memcpy( newtheme, btheme, sizeof( bTheme ) );
538         BLI_addhead( &U.themes, newtheme );
539         BLI_strncpy( newtheme->name, name, 32 );
540
541         pytheme->theme = newtheme;
542
543         return ( PyObject * ) pytheme;
544 }
545
546 static PyObject *M_Theme_Get( PyObject * self, PyObject * args )
547 {
548         char *name = NULL;
549         bTheme *iter;
550         PyObject *ret;
551
552         if( !PyArg_ParseTuple( args, "|s", &name ) )
553                 return EXPP_ReturnPyObjError( PyExc_TypeError,
554                                               "expected string argument (or nothing)" );
555
556         iter = U.themes.first;
557
558         if( name ) {            /* (name) - return requested theme */
559                 BPy_Theme *wanted = NULL;
560
561                 while( iter ) {
562                         if( strcmp( name, iter->name ) == 0 ) {
563                                 wanted = PyObject_New( BPy_Theme,
564                                                        &Theme_Type );
565                                 wanted->theme = iter;
566                                 break;
567                         }
568                         iter = iter->next;
569                 }
570
571                 if( !wanted ) {
572                         char emsg[64];
573                         PyOS_snprintf( emsg, sizeof( emsg ),
574                                        "Theme \"%s\" not found", name );
575                         return EXPP_ReturnPyObjError( PyExc_NameError, emsg );
576                 }
577
578                 ret = ( PyObject * ) wanted;
579         }
580
581         else {                  /* () - return list with all themes */
582                 int index = 0;
583                 PyObject *list = NULL;
584                 BPy_Theme *pytheme = NULL;
585
586                 list = PyList_New( BLI_countlist( &( U.themes ) ) );
587
588                 if( !list )
589                         return EXPP_ReturnPyObjError( PyExc_MemoryError,
590                                                       "couldn't create PyList" );
591
592                 while( iter ) {
593                         pytheme = PyObject_New( BPy_Theme, &Theme_Type );
594                         pytheme->theme = iter;
595
596                         if( !pytheme )
597                                 return EXPP_ReturnPyObjError
598                                         ( PyExc_MemoryError,
599                                           "couldn't create Theme PyObject" );
600
601                         PyList_SET_ITEM( list, index, ( PyObject * ) pytheme );
602
603                         iter = iter->next;
604                         index++;
605                 }
606
607                 ret = list;
608         }
609
610         return ret;
611 }
612
613 static PyObject *Theme_get( BPy_Theme * self, PyObject * args )
614 {
615         bTheme *btheme = self->theme;
616         ThemeUI *tui = NULL;
617         ThemeSpace *tsp = NULL;
618         PyObject *pyob = NULL;
619         BPy_ThemeUI *retUI = NULL;
620         BPy_ThemeSpace *retSpc = NULL;
621         int type;
622
623         if( !PyArg_ParseTuple( args, "|O", &pyob ) )
624                 return EXPP_ReturnPyObjError( PyExc_TypeError,
625                                               "expected string or int argument or nothing" );
626
627         if( !pyob ) {           /* (): return list with all names */
628                 PyObject *ret = PyList_New( EXPP_THEME_NUMBEROFTHEMES );
629
630                 if( !ret )
631                         return EXPP_ReturnPyObjError( PyExc_MemoryError,
632                                                       "couldn't create pylist!" );
633
634                 type = 0;       /* using as a counter only */
635
636                 while( type < EXPP_THEME_NUMBEROFTHEMES ) {
637                         PyList_SET_ITEM( ret, type,
638                                          PyString_FromString( themes_map[type].
639                                                               sval ) );
640                         type++;
641                 }
642
643                 return ret;
644         }
645
646         else if( PyInt_Check( pyob ) )  /* (int) */
647                 type = ( int ) PyInt_AsLong( pyob );
648         else if( PyString_Check( pyob ) ) {     /* (str) */
649                 char *str = PyString_AsString( pyob );
650                 if( !EXPP_map_case_getIntVal( themes_map, str, &type ) )
651                         return EXPP_ReturnPyObjError( PyExc_AttributeError,
652                                                       "unknown string argument" );
653         } else
654                 return EXPP_ReturnPyObjError( PyExc_TypeError,
655                                               "expected string or int argument or nothing" );
656
657         switch ( type ) {
658         case -1:                /* UI */
659                 tui = &btheme->tui;
660                 break;
661         case SPACE_BUTS:
662                 tsp = &btheme->tbuts;
663                 break;
664         case SPACE_VIEW3D:
665                 tsp = &btheme->tv3d;
666                 break;
667         case SPACE_FILE:
668                 tsp = &btheme->tfile;
669                 break;
670         case SPACE_IPO:
671                 tsp = &btheme->tipo;
672                 break;
673         case SPACE_INFO:
674                 tsp = &btheme->tinfo;
675                 break;
676         case SPACE_SOUND:
677                 tsp = &btheme->tsnd;
678                 break;
679         case SPACE_ACTION:
680                 tsp = &btheme->tact;
681                 break;
682         case SPACE_NLA:
683                 tsp = &btheme->tnla;
684                 break;
685         case SPACE_SEQ:
686                 tsp = &btheme->tseq;
687                 break;
688         case SPACE_IMAGE:
689                 tsp = &btheme->tima;
690                 break;
691         case SPACE_IMASEL:
692                 tsp = &btheme->timasel;
693                 break;
694         case SPACE_TEXT:
695                 tsp = &btheme->text;
696                 break;
697         case SPACE_OOPS:
698                 tsp = &btheme->toops;
699                 break;
700         case SPACE_TIME:
701                 tsp = &btheme->ttime;
702                 break;
703         }
704
705         if( tui ) {
706                 retUI = PyObject_New( BPy_ThemeUI, &ThemeUI_Type );
707                 retUI->theme = btheme;
708                 retUI->tui = tui;
709                 return ( PyObject * ) retUI;
710         } else if( tsp ) {
711                 retSpc = PyObject_New( BPy_ThemeSpace, &ThemeSpace_Type );
712                 retSpc->theme = btheme;
713                 retSpc->tsp = tsp;
714                 return ( PyObject * ) retSpc;
715         } else
716                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
717                                               "invalid parameter" );
718 }
719
720 static PyObject *Theme_getName( BPy_Theme * self )
721 {
722         return PyString_FromString( self->theme->name );
723 }
724
725 static PyObject *Theme_setName( BPy_Theme * self, PyObject * args )
726 {
727         char *name = NULL;
728
729         if( !PyArg_ParseTuple( args, "s", &name ) )
730                 return EXPP_ReturnPyObjError( PyExc_TypeError,
731                                               "expected string argument" );
732
733         BLI_strncpy( self->theme->name, name, 32 );
734
735         return EXPP_incr_ret( Py_None );
736 }
737
738 PyObject *Theme_Init( void )
739 {
740         PyObject *submodule;
741
742         Theme_Type.ob_type = &PyType_Type;
743
744         submodule = Py_InitModule3( "Blender.Window.Theme",
745                                     M_Theme_methods, M_Theme_doc );
746
747         return submodule;
748 }
749
750 static void Theme_dealloc( BPy_Theme * self )
751 {
752         PyObject_DEL( self );
753 }
754
755 static PyObject *Theme_getAttr( BPy_Theme * self, char *name )
756 {
757         PyObject *attr = Py_None;
758
759         if( !strcmp( name, "name" ) )
760                 attr = PyString_FromString( self->theme->name );
761         else if( !strcmp( name, "__members__" ) )
762                 attr = Py_BuildValue( "[s]", "name" );
763
764         if( attr != Py_None )
765                 return attr;
766
767         return Py_FindMethod( BPy_Theme_methods, ( PyObject * ) self, name );
768 }
769
770 static int Theme_compare( BPy_Theme * a, BPy_Theme * b )
771 {
772         bTheme *pa = a->theme, *pb = b->theme;
773         return ( pa == pb ) ? 0 : -1;
774 }
775
776 static PyObject *Theme_repr( BPy_Theme * self )
777 {
778         return PyString_FromFormat( "[Theme \"%s\"]", self->theme->name );
779 }