Replaced old fly mode for a fly mode that works in all 3 view types - ortho, perspect...
[blender-staging.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( bone_solid )
174                 ELSEIF_TSP_RGBA( bone_pose )
175                 ELSEIF_TSP_RGBA( strip )
176                 ELSEIF_TSP_RGBA( strip_select )
177                 ELSEIF_TSP_RGBA( syntaxl )
178                 ELSEIF_TSP_RGBA( syntaxn )
179                 ELSEIF_TSP_RGBA( syntaxb )
180                 ELSEIF_TSP_RGBA( syntaxv )
181                 ELSEIF_TSP_RGBA( syntaxc )
182                 else if( !strcmp( name, "vertex_size" ) )
183                 attrib = Py_BuildValue( "i", tsp->vertex_size );
184                 else if( !strcmp( name, "facedot_size" ) )
185                 attrib = Py_BuildValue( "i", tsp->facedot_size );
186         else if( !strcmp( name, "__members__" ) )
187                 attrib = Py_BuildValue("[sssssssssssssssssssssssssssssssssss]", "theme",
188                                         "back", "text", "text_hi", "header",
189                                         "panel", "shade1", "shade2", "hilite",
190                                         "grid", "wire", "lamp", "select", "active",
191                                         "transform", "vertex", "vertex_select",
192                                         "edge", "edge_select", "edge_seam",
193                                         "edge_facesel", "face", "face_select",
194                                         "face_dot", "normal", "bone_solid", "bone_pose",
195                                         "strip", "strip_select",
196                                         "syntaxl", "syntaxn", "syntaxb", "syntaxv", "syntaxc",
197                                         "vertex_size", "facedot_size" );
198
199         if( attrib != Py_None )
200                 return attrib;
201
202         return Py_FindMethod( BPy_ThemeSpace_methods, ( PyObject * ) self,
203                               name );
204 }
205
206 static int ThemeSpace_setAttr( BPy_ThemeSpace * self, char *name,
207                                PyObject * value )
208 {
209         PyObject *attrib = NULL;
210         ThemeSpace *tsp = self->tsp;
211         int ret = -1;
212
213         if( !strcmp( name, "back" ) )
214                 attrib = charRGBA_New( &tsp->back[0] );
215                 ELSEIF_TSP_RGBA( text )
216                 ELSEIF_TSP_RGBA( text_hi )
217                 ELSEIF_TSP_RGBA( header )
218                 ELSEIF_TSP_RGBA( panel )
219                 ELSEIF_TSP_RGBA( shade1 )
220                 ELSEIF_TSP_RGBA( shade2 )
221                 ELSEIF_TSP_RGBA( hilite )
222                 ELSEIF_TSP_RGBA( grid )
223                 ELSEIF_TSP_RGBA( wire )
224                 ELSEIF_TSP_RGBA( lamp )
225                 ELSEIF_TSP_RGBA( select )
226                 ELSEIF_TSP_RGBA( active )
227                 ELSEIF_TSP_RGBA( transform )
228                 ELSEIF_TSP_RGBA( vertex )
229                 ELSEIF_TSP_RGBA( vertex_select )
230                 ELSEIF_TSP_RGBA( edge )
231                 ELSEIF_TSP_RGBA( edge_select )
232                 ELSEIF_TSP_RGBA( edge_seam )
233                 ELSEIF_TSP_RGBA( edge_facesel )
234                 ELSEIF_TSP_RGBA( face )
235                 ELSEIF_TSP_RGBA( face_select )
236                 ELSEIF_TSP_RGBA( face_dot )
237                 ELSEIF_TSP_RGBA( normal )
238                 ELSEIF_TSP_RGBA( bone_solid )
239                 ELSEIF_TSP_RGBA( bone_pose )
240                 ELSEIF_TSP_RGBA( strip )
241                 ELSEIF_TSP_RGBA( strip_select )
242                 ELSEIF_TSP_RGBA( syntaxl )
243                 ELSEIF_TSP_RGBA( syntaxn )
244                 ELSEIF_TSP_RGBA( syntaxb )
245                 ELSEIF_TSP_RGBA( syntaxv )
246                 ELSEIF_TSP_RGBA( syntaxc )
247                 else if( !strcmp( name, "vertex_size" ) ) {
248                 int val;
249
250                 if( !PyInt_Check( value ) )
251                         return EXPP_ReturnIntError( PyExc_TypeError,
252                                                     "expected integer value" );
253
254                 val = ( int ) PyInt_AsLong( value );
255                 tsp->vertex_size = (char)EXPP_ClampInt( val,
256                                                   EXPP_THEME_VTX_SIZE_MIN,
257                                                   EXPP_THEME_VTX_SIZE_MAX );
258                 ret = 0;
259         }
260         else if( !strcmp( name, "facedot_size" ) ) {
261                 int val;
262
263                 if( !PyInt_Check( value ) )
264                         return EXPP_ReturnIntError( PyExc_TypeError,
265                                                     "expected integer value" );
266
267                 val = ( int ) PyInt_AsLong( value );
268                 tsp->vertex_size = (char)EXPP_ClampInt( val,
269                                                   EXPP_THEME_FDOT_SIZE_MIN,
270                                                   EXPP_THEME_FDOT_SIZE_MAX );
271                 ret = 0;
272         } else
273                 return EXPP_ReturnIntError( PyExc_AttributeError,
274                                             "attribute not found" );
275
276         if( attrib ) {
277                 PyObject *pyret = NULL;
278                 PyObject *valtuple = Py_BuildValue( "(O)", value );
279
280                 if( !valtuple )
281                         return EXPP_ReturnIntError( PyExc_MemoryError,
282                                                     "couldn't create tuple!" );
283
284                 pyret = charRGBA_setCol( ( BPy_charRGBA * ) attrib, valtuple );
285                 Py_DECREF( valtuple );
286
287                 if( pyret == Py_None ) {
288                         Py_DECREF( Py_None );   /* was increfed by charRGBA_setCol */
289                         ret = 0;
290                 }
291
292                 Py_DECREF( attrib );    /* we're done with it */
293         }
294
295         return ret;             /* 0 if all went well */
296 }
297
298 static int ThemeSpace_compare( BPy_ThemeSpace * a, BPy_ThemeSpace * b )
299 {
300         ThemeSpace *pa = a->tsp, *pb = b->tsp;
301         return ( pa == pb ) ? 0 : -1;
302 }
303
304 static PyObject *ThemeSpace_repr( BPy_ThemeSpace * self )
305 {
306         return PyString_FromFormat( "[Space theme from theme \"%s\"]",
307                                     self->theme->name );
308 }
309
310 static void ThemeUI_dealloc( BPy_ThemeUI * self );
311 static int ThemeUI_compare( BPy_ThemeUI * a, BPy_ThemeUI * b );
312 static PyObject *ThemeUI_repr( BPy_ThemeUI * self );
313 static PyObject *ThemeUI_getAttr( BPy_ThemeUI * self, char *name );
314 static int ThemeUI_setAttr( BPy_ThemeUI * self, char *name, PyObject * val );
315
316 static PyMethodDef BPy_ThemeUI_methods[] = {
317         {NULL, NULL, 0, NULL}
318 };
319
320 PyTypeObject ThemeUI_Type = {
321         PyObject_HEAD_INIT( NULL ) 0,   /* ob_size */
322         "Blender UI Theme",     /* tp_name */
323         sizeof( BPy_ThemeUI ),  /* tp_basicsize */
324         0,                      /* tp_itemsize */
325         /* methods */
326         ( destructor ) ThemeUI_dealloc, /* tp_dealloc */
327         0,                      /* tp_print */
328         ( getattrfunc ) ThemeUI_getAttr,        /* tp_getattr */
329         ( setattrfunc ) ThemeUI_setAttr,        /* tp_setattr */
330         ( cmpfunc ) ThemeUI_compare,    /* tp_compare */
331         ( reprfunc ) ThemeUI_repr,      /* tp_repr */
332         0,                      /* tp_as_number */
333         0,                      /* tp_as_sequence */
334         0,                      /* tp_as_mapping */
335         0,                      /* tp_as_hash */
336         0, 0, 0, 0, 0, 0,
337         0,                      /* tp_doc */
338         0, 0, 0, 0, 0, 0,
339         0,                      //BPy_ThemeUI_methods,         /* tp_methods */
340         0,                      /* tp_members */
341         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
342 };
343
344 static void ThemeUI_dealloc( BPy_ThemeUI * self )
345 {
346         PyObject_DEL( self );
347 }
348
349 #define ELSEIF_TUI_RGBA(attr)\
350         else if (!strcmp(name, #attr))\
351                 attrib = charRGBA_New(&tui->attr[0]);
352
353 /* Example: ELSEIF_TUI_RGBA(outline) becomes:
354  * else if (!strcmp(name, "outline")
355  *      attr = charRGBA_New(&tui->outline[0])
356  */
357
358 static PyObject *ThemeUI_getAttr( BPy_ThemeUI * self, char *name )
359 {
360         PyObject *attrib = Py_None;
361         ThemeUI *tui = self->tui;
362
363         if( !strcmp( name, "theme" ) )
364                 attrib = PyString_FromString( self->theme->name );
365         ELSEIF_TUI_RGBA( outline )
366                 ELSEIF_TUI_RGBA( neutral )
367                 ELSEIF_TUI_RGBA( action )
368                 ELSEIF_TUI_RGBA( setting )
369                 ELSEIF_TUI_RGBA( setting1 )
370                 ELSEIF_TUI_RGBA( setting2 )
371                 ELSEIF_TUI_RGBA( num )
372                 ELSEIF_TUI_RGBA( textfield )
373                 ELSEIF_TUI_RGBA( textfield_hi )
374                 ELSEIF_TUI_RGBA( popup )
375                 ELSEIF_TUI_RGBA( text )
376                 ELSEIF_TUI_RGBA( text_hi )
377                 ELSEIF_TUI_RGBA( menu_back )
378                 ELSEIF_TUI_RGBA( menu_item )
379                 ELSEIF_TUI_RGBA( menu_hilite )
380                 ELSEIF_TUI_RGBA( menu_text )
381                 ELSEIF_TUI_RGBA( menu_text_hi )
382                 else if( !strcmp( name, "drawType" ) )
383                 attrib = PyInt_FromLong( ( char ) tui->but_drawtype );
384         else if( !strcmp( name, "__members__" ) )
385                 attrib = Py_BuildValue( "[ssssssssssssssssss]", "theme",
386                                         "outline", "neutral", "action",
387                                         "setting", "setting1", "setting2",
388                                         "num", "textfield", "textfield_hi", "popup", "text",
389                                         "text_hi", "menu_back", "menu_item",
390                                         "menu_hilite", "menu_text",
391                                         "menu_text_hi", "drawType" );
392
393         if( attrib != Py_None )
394                 return attrib;
395
396         return Py_FindMethod( BPy_ThemeUI_methods, ( PyObject * ) self, name );
397 }
398
399 static int ThemeUI_setAttr( BPy_ThemeUI * self, char *name, PyObject * value )
400 {
401         PyObject *attrib = NULL;
402         ThemeUI *tui = self->tui;
403         int ret = -1;
404
405         if( !strcmp( name, "outline" ) )
406                 attrib = charRGBA_New( &tui->outline[0] );
407         ELSEIF_TUI_RGBA( neutral )
408                 ELSEIF_TUI_RGBA( action )
409                 ELSEIF_TUI_RGBA( setting )
410                 ELSEIF_TUI_RGBA( setting1 )
411                 ELSEIF_TUI_RGBA( setting2 )
412                 ELSEIF_TUI_RGBA( num )
413                 ELSEIF_TUI_RGBA( textfield )
414                 ELSEIF_TUI_RGBA( textfield_hi )
415                 ELSEIF_TUI_RGBA( popup )
416                 ELSEIF_TUI_RGBA( text )
417                 ELSEIF_TUI_RGBA( text_hi )
418                 ELSEIF_TUI_RGBA( menu_back )
419                 ELSEIF_TUI_RGBA( menu_item )
420                 ELSEIF_TUI_RGBA( menu_hilite )
421                 ELSEIF_TUI_RGBA( menu_text )
422                 ELSEIF_TUI_RGBA( menu_text_hi )
423                 else if( !strcmp( name, "drawType" ) ) {
424                 int val;
425
426                 if( !PyInt_Check( value ) )
427                         return EXPP_ReturnIntError( PyExc_TypeError,
428                                                     "expected integer value" );
429
430                 val = ( int ) PyInt_AsLong( value );
431                 tui->but_drawtype = (char)EXPP_ClampInt( val,
432                                                    EXPP_THEME_DRAWTYPE_MIN,
433                                                    EXPP_THEME_DRAWTYPE_MAX );
434                 ret = 0;
435         } else
436                 return EXPP_ReturnIntError( PyExc_AttributeError,
437                                             "attribute not found" );
438
439         if( attrib ) {
440                 PyObject *pyret = NULL;
441                 PyObject *valtuple = Py_BuildValue( "(O)", value );
442
443                 if( !valtuple )
444                         return EXPP_ReturnIntError( PyExc_MemoryError,
445                                                     "couldn't create tuple!" );
446
447                 pyret = charRGBA_setCol( ( BPy_charRGBA * ) attrib, valtuple );
448                 Py_DECREF( valtuple );
449
450                 if( pyret == Py_None ) {
451                         Py_DECREF( Py_None );   /* was increfed by charRGBA_setCol */
452                         ret = 0;
453                 }
454
455                 Py_DECREF( attrib );    /* we're done with it */
456         }
457
458         return ret;             /* 0 if all went well */
459 }
460
461
462 static int ThemeUI_compare( BPy_ThemeUI * a, BPy_ThemeUI * b )
463 {
464         ThemeUI *pa = a->tui, *pb = b->tui;
465         return ( pa == pb ) ? 0 : -1;
466 }
467
468 static PyObject *ThemeUI_repr( BPy_ThemeUI * self )
469 {
470         return PyString_FromFormat( "[UI theme from theme \"%s\"]",
471                                     self->theme->name );
472 }
473
474 static void Theme_dealloc( BPy_Theme * self );
475 static int Theme_compare( BPy_Theme * a, BPy_Theme * b );
476 static PyObject *Theme_getAttr( BPy_Theme * self, char *name );
477 static PyObject *Theme_repr( BPy_Theme * self );
478
479 static PyObject *Theme_get( BPy_Theme * self, PyObject * args );
480 static PyObject *Theme_getName( BPy_Theme * self );
481 static PyObject *Theme_setName( BPy_Theme * self, PyObject * args );
482
483 static PyMethodDef BPy_Theme_methods[] = {
484         {"get", ( PyCFunction ) Theme_get, METH_VARARGS,
485          "(param) - Return UI or Space theme object.\n\
486 (param) - the chosen theme object as an int or a string:\n\
487 - () - default: UI;\n\
488 - (i) - int: an entry from the Blender.Window.Types dictionary;\n\
489 - (s) - string: 'UI' or a space name, like 'VIEW3D', etc."},
490         {"getName", ( PyCFunction ) Theme_getName, METH_NOARGS,
491          "() - Return Theme name"},
492         {"setName", ( PyCFunction ) Theme_setName, METH_VARARGS,
493          "(s) - Set Theme name"},
494         {NULL, NULL, 0, NULL}
495 };
496
497 PyTypeObject Theme_Type = {
498         PyObject_HEAD_INIT( NULL ) 
499         0,      /* ob_size */
500         "Blender Theme",        /* tp_name */
501         sizeof( BPy_Theme ),    /* tp_basicsize */
502         0,                      /* tp_itemsize */
503         /* methods */
504         ( destructor ) Theme_dealloc,   /* tp_dealloc */
505         0,                      /* tp_print */
506         ( getattrfunc ) Theme_getAttr,  /* tp_getattr */
507         0,                      //(setattrfunc) Theme_setAttr,        /* tp_setattr */
508         ( cmpfunc ) Theme_compare,      /* tp_compare */
509         ( reprfunc ) Theme_repr,        /* tp_repr */
510         0,                      /* tp_as_number */
511         0,                      /* tp_as_sequence */
512         0,                      /* tp_as_mapping */
513         0,                      /* tp_as_hash */
514         0, 0, 0, 0, 0, 0,
515         0,                      /* tp_doc */
516         0, 0, 0, 0, 0, 0,
517         0,                      /*BPy_Theme_methods,*/ /* tp_methods */
518         0,                      /* tp_members */
519         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
520 };
521
522 static PyObject *M_Theme_New( PyObject * self, PyObject * args )
523 {
524         char *name = "New Theme";
525         BPy_Theme *pytheme = NULL, *base_pytheme = NULL;
526         bTheme *btheme = NULL, *newtheme = NULL;
527
528         if( !PyArg_ParseTuple
529             ( args, "|sO!", &name, &Theme_Type, &base_pytheme ) )
530                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
531                                               "expected nothing or a name and optional theme object as arguments" );
532
533         if( base_pytheme )
534                 btheme = base_pytheme->theme;
535         if( !btheme )
536                 btheme = U.themes.first;
537
538         newtheme = MEM_callocN( sizeof( bTheme ), "theme" );
539
540         if( newtheme )
541                 pytheme = PyObject_New( BPy_Theme, &Theme_Type );
542         if( !pytheme )
543                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
544                                               "couldn't create Theme Data in Blender" );
545
546         memcpy( newtheme, btheme, sizeof( bTheme ) );
547         BLI_addhead( &U.themes, newtheme );
548         BLI_strncpy( newtheme->name, name, 32 );
549
550         pytheme->theme = newtheme;
551
552         return ( PyObject * ) pytheme;
553 }
554
555 static PyObject *M_Theme_Get( PyObject * self, PyObject * args )
556 {
557         char *name = NULL;
558         bTheme *iter;
559         PyObject *ret;
560
561         if( !PyArg_ParseTuple( args, "|s", &name ) )
562                 return EXPP_ReturnPyObjError( PyExc_TypeError,
563                                               "expected string argument (or nothing)" );
564
565         iter = U.themes.first;
566
567         if( name ) {            /* (name) - return requested theme */
568                 BPy_Theme *wanted = NULL;
569
570                 while( iter ) {
571                         if( strcmp( name, iter->name ) == 0 ) {
572                                 wanted = PyObject_New( BPy_Theme,
573                                                        &Theme_Type );
574                                 wanted->theme = iter;
575                                 break;
576                         }
577                         iter = iter->next;
578                 }
579
580                 if( !wanted ) {
581                         char emsg[64];
582                         PyOS_snprintf( emsg, sizeof( emsg ),
583                                        "Theme \"%s\" not found", name );
584                         return EXPP_ReturnPyObjError( PyExc_NameError, emsg );
585                 }
586
587                 ret = ( PyObject * ) wanted;
588         }
589
590         else {                  /* () - return list with all themes */
591                 int index = 0;
592                 PyObject *list = NULL;
593                 BPy_Theme *pytheme = NULL;
594
595                 list = PyList_New( BLI_countlist( &( U.themes ) ) );
596
597                 if( !list )
598                         return EXPP_ReturnPyObjError( PyExc_MemoryError,
599                                                       "couldn't create PyList" );
600
601                 while( iter ) {
602                         pytheme = PyObject_New( BPy_Theme, &Theme_Type );
603                         pytheme->theme = iter;
604
605                         if( !pytheme )
606                                 return EXPP_ReturnPyObjError
607                                         ( PyExc_MemoryError,
608                                           "couldn't create Theme PyObject" );
609
610                         PyList_SET_ITEM( list, index, ( PyObject * ) pytheme );
611
612                         iter = iter->next;
613                         index++;
614                 }
615
616                 ret = list;
617         }
618
619         return ret;
620 }
621
622 static PyObject *Theme_get( BPy_Theme * self, PyObject * args )
623 {
624         bTheme *btheme = self->theme;
625         ThemeUI *tui = NULL;
626         ThemeSpace *tsp = NULL;
627         PyObject *pyob = NULL;
628         BPy_ThemeUI *retUI = NULL;
629         BPy_ThemeSpace *retSpc = NULL;
630         int type;
631
632         if( !PyArg_ParseTuple( args, "|O", &pyob ) )
633                 return EXPP_ReturnPyObjError( PyExc_TypeError,
634                                               "expected string or int argument or nothing" );
635
636         if( !pyob ) {           /* (): return list with all names */
637                 PyObject *ret = PyList_New( EXPP_THEME_NUMBEROFTHEMES );
638
639                 if( !ret )
640                         return EXPP_ReturnPyObjError( PyExc_MemoryError,
641                                                       "couldn't create pylist!" );
642
643                 type = 0;       /* using as a counter only */
644
645                 while( type < EXPP_THEME_NUMBEROFTHEMES ) {
646                         PyList_SET_ITEM( ret, type,
647                                          PyString_FromString( themes_map[type].
648                                                               sval ) );
649                         type++;
650                 }
651
652                 return ret;
653         }
654
655         else if( PyInt_Check( pyob ) )  /* (int) */
656                 type = ( int ) PyInt_AsLong( pyob );
657         else if( PyString_Check( pyob ) ) {     /* (str) */
658                 char *str = PyString_AsString( pyob );
659                 if( !EXPP_map_case_getIntVal( themes_map, str, &type ) )
660                         return EXPP_ReturnPyObjError( PyExc_AttributeError,
661                                                       "unknown string argument" );
662         } else
663                 return EXPP_ReturnPyObjError( PyExc_TypeError,
664                                               "expected string or int argument or nothing" );
665
666         switch ( type ) {
667         case -1:                /* UI */
668                 tui = &btheme->tui;
669                 break;
670         case SPACE_BUTS:
671                 tsp = &btheme->tbuts;
672                 break;
673         case SPACE_VIEW3D:
674                 tsp = &btheme->tv3d;
675                 break;
676         case SPACE_FILE:
677                 tsp = &btheme->tfile;
678                 break;
679         case SPACE_IPO:
680                 tsp = &btheme->tipo;
681                 break;
682         case SPACE_INFO:
683                 tsp = &btheme->tinfo;
684                 break;
685         case SPACE_SOUND:
686                 tsp = &btheme->tsnd;
687                 break;
688         case SPACE_ACTION:
689                 tsp = &btheme->tact;
690                 break;
691         case SPACE_NLA:
692                 tsp = &btheme->tnla;
693                 break;
694         case SPACE_SEQ:
695                 tsp = &btheme->tseq;
696                 break;
697         case SPACE_IMAGE:
698                 tsp = &btheme->tima;
699                 break;
700         case SPACE_IMASEL:
701                 tsp = &btheme->timasel;
702                 break;
703         case SPACE_TEXT:
704                 tsp = &btheme->text;
705                 break;
706         case SPACE_OOPS:
707                 tsp = &btheme->toops;
708                 break;
709         case SPACE_TIME:
710                 tsp = &btheme->ttime;
711                 break;
712         }
713
714         if( tui ) {
715                 retUI = PyObject_New( BPy_ThemeUI, &ThemeUI_Type );
716                 retUI->theme = btheme;
717                 retUI->tui = tui;
718                 return ( PyObject * ) retUI;
719         } else if( tsp ) {
720                 retSpc = PyObject_New( BPy_ThemeSpace, &ThemeSpace_Type );
721                 retSpc->theme = btheme;
722                 retSpc->tsp = tsp;
723                 return ( PyObject * ) retSpc;
724         } else
725                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
726                                               "invalid parameter" );
727 }
728
729 static PyObject *Theme_getName( BPy_Theme * self )
730 {
731         return PyString_FromString( self->theme->name );
732 }
733
734 static PyObject *Theme_setName( BPy_Theme * self, PyObject * args )
735 {
736         char *name = NULL;
737
738         if( !PyArg_ParseTuple( args, "s", &name ) )
739                 return EXPP_ReturnPyObjError( PyExc_TypeError,
740                                               "expected string argument" );
741
742         BLI_strncpy( self->theme->name, name, 32 );
743
744         return EXPP_incr_ret( Py_None );
745 }
746
747 PyObject *Theme_Init( void )
748 {
749         PyObject *submodule;
750
751         Theme_Type.ob_type = &PyType_Type;
752
753         submodule = Py_InitModule3( "Blender.Window.Theme",
754                                     M_Theme_methods, M_Theme_doc );
755
756         return submodule;
757 }
758
759 static void Theme_dealloc( BPy_Theme * self )
760 {
761         PyObject_DEL( self );
762 }
763
764 static PyObject *Theme_getAttr( BPy_Theme * self, char *name )
765 {
766         PyObject *attr = Py_None;
767
768         if( !strcmp( name, "name" ) )
769                 attr = PyString_FromString( self->theme->name );
770         else if( !strcmp( name, "__members__" ) )
771                 attr = Py_BuildValue( "[s]", "name" );
772
773         if( attr != Py_None )
774                 return attr;
775
776         return Py_FindMethod( BPy_Theme_methods, ( PyObject * ) self, name );
777 }
778
779 static int Theme_compare( BPy_Theme * a, BPy_Theme * b )
780 {
781         bTheme *pa = a->theme, *pb = b->theme;
782         return ( pa == pb ) ? 0 : -1;
783 }
784
785 static PyObject *Theme_repr( BPy_Theme * self )
786 {
787         return PyString_FromFormat( "[Theme \"%s\"]", self->theme->name );
788 }