svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r22701:22704
[blender.git] / source / blender / editors / screen / area.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30 #include <stdio.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_screen_types.h"
35 #include "DNA_userdef_types.h"
36
37 #include "BLI_blenlib.h"
38 #include "BLI_arithb.h"
39 #include "BLI_rand.h"
40
41 #include "BKE_context.h"
42 #include "BKE_global.h"
43 #include "BKE_screen.h"
44 #include "BKE_utildefines.h"
45
46 #include "WM_api.h"
47 #include "WM_types.h"
48 #include "wm_subwindow.h"
49
50 #include "ED_screen.h"
51 #include "ED_screen_types.h"
52 #include "ED_types.h"
53
54 #include "BIF_gl.h"
55 #include "BIF_glutil.h"
56 #include "BLF_api.h"
57
58 #include "UI_interface.h"
59 #include "UI_resources.h"
60 #include "UI_view2d.h"
61
62 #ifndef DISABLE_PYTHON
63 #include "BPY_extern.h"
64 #endif
65
66 #include "screen_intern.h"
67
68 /* general area and region code */
69
70 static void region_draw_emboss(ARegion *ar, rcti *scirct)
71 {
72         rcti rect;
73         
74         /* translate scissor rect to region space */
75         rect.xmin= scirct->xmin - ar->winrct.xmin;
76         rect.ymin= scirct->ymin - ar->winrct.ymin;
77         rect.xmax= scirct->xmax - ar->winrct.xmin;
78         rect.ymax= scirct->ymax - ar->winrct.ymin;
79         
80         /* set transp line */
81         glEnable( GL_BLEND );
82         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
83         
84         /* right  */
85         glColor4ub(0,0,0, 50);
86         sdrawline(rect.xmax, rect.ymin, rect.xmax, rect.ymax);
87         
88         /* bottom  */
89         glColor4ub(0,0,0, 80);
90         sdrawline(rect.xmin, rect.ymin, rect.xmax, rect.ymin);
91         
92         /* top  */
93         glColor4ub(255,255,255, 60);
94         sdrawline(rect.xmin, rect.ymax, rect.xmax, rect.ymax);
95
96         /* left  */
97         glColor4ub(255,255,255, 50);
98         sdrawline(rect.xmin, rect.ymin, rect.xmin, rect.ymax);
99         
100         glDisable( GL_BLEND );
101 }
102
103 void ED_region_pixelspace(ARegion *ar)
104 {
105         int width= ar->winrct.xmax-ar->winrct.xmin+1;
106         int height= ar->winrct.ymax-ar->winrct.ymin+1;
107         
108         wmOrtho2(-0.375, (float)width-0.375, -0.375, (float)height-0.375);
109         wmLoadIdentity();
110 }
111
112 /* only exported for WM */
113 void ED_region_do_listen(ARegion *ar, wmNotifier *note)
114 {
115         /* generic notes first */
116         switch(note->category) {
117                 case NC_WM:
118                         if(note->data==ND_FILEREAD)
119                                 ED_region_tag_redraw(ar);
120                         break;
121                 case NC_WINDOW:
122                         ED_region_tag_redraw(ar);
123                         break;
124                 case NC_SCREEN:
125                         if(note->action==NA_EDITED)
126                                 ED_region_tag_redraw(ar);
127                         /* pass on */
128                 default:
129                         if(ar->type && ar->type->listener)
130                                 ar->type->listener(ar, note);
131         }
132 }
133
134 /* only exported for WM */
135 void ED_area_do_listen(ScrArea *sa, wmNotifier *note)
136 {
137         /* no generic notes? */
138         if(sa->type && sa->type->listener) {
139                 sa->type->listener(sa, note);
140         }
141 }
142
143 /* only exported for WM */
144 void ED_area_do_refresh(bContext *C, ScrArea *sa)
145 {
146         /* no generic notes? */
147         if(sa->type && sa->type->refresh) {
148                 sa->type->refresh(C, sa);
149         }
150         sa->do_refresh= 0;
151 }
152
153 /* based on screen region draw tags, set draw tags in azones, and future region tabs etc */
154 /* only exported for WM */
155 void ED_area_overdraw_flush(bContext *C, ScrArea *sa, ARegion *ar)
156 {
157         AZone *az;
158         
159         for(az= sa->actionzones.first; az; az= az->next) {
160                 int xs, ys;
161                 
162                 if(az->type==AZONE_AREA) {
163                         xs= (az->x1+az->x2)/2;
164                         ys= (az->y1+az->y2)/2;
165                 }
166                 else {
167                         xs= az->x3;
168                         ys= az->y3;
169                 }
170
171                 /* test if inside */
172                 if(BLI_in_rcti(&ar->winrct, xs, ys)) {
173                         az->do_draw= 1;
174                 }
175         }
176 }
177
178 static void area_draw_azone(short x1, short y1, short x2, short y2)
179 {
180         float xmin = x1;
181         float xmax = x2-2;
182         float ymin = y1-1;
183         float ymax = y2-3;
184         
185         float dx= 0.3f*(xmax-xmin);
186         float dy= 0.3f*(ymax-ymin);
187         
188         glColor4ub(255, 255, 255, 80);
189         fdrawline(xmin, ymax, xmax, ymin);
190         fdrawline(xmin, ymax-dy, xmax-dx, ymin);
191         fdrawline(xmin, ymax-2*dy, xmax-2*dx, ymin);
192         
193         glColor4ub(0, 0, 0, 150);
194         fdrawline(xmin, ymax+1, xmax+1, ymin);
195         fdrawline(xmin, ymax-dy+1, xmax-dx+1, ymin);
196         fdrawline(xmin, ymax-2*dy+1, xmax-2*dx+1, ymin);
197 }
198
199 static void region_draw_azone(ScrArea *sa, AZone *az)
200 {
201         if(az->ar==NULL) return;
202         
203         UI_SetTheme(sa->spacetype, az->ar->type->regionid);
204         
205         UI_ThemeColor(TH_BACK);
206         glBegin(GL_TRIANGLES);
207         glVertex2s(az->x1, az->y1);
208         glVertex2s(az->x2, az->y2);
209         glVertex2s(az->x3, az->y3);
210         glEnd();
211         
212         UI_ThemeColorShade(TH_BACK, 50);
213         sdrawline(az->x1, az->y1, az->x3, az->y3);
214         
215         UI_ThemeColorShade(TH_BACK, -50);
216         sdrawline(az->x2, az->y2, az->x3, az->y3);
217
218 }
219
220
221 /* only exported for WM */
222 void ED_area_overdraw(bContext *C)
223 {
224         wmWindow *win= CTX_wm_window(C);
225         bScreen *screen= CTX_wm_screen(C);
226         ScrArea *sa;
227         
228         /* Draw AZones, in screenspace */
229         wmSubWindowSet(win, screen->mainwin);
230
231         glEnable( GL_BLEND );
232         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
233         
234         for(sa= screen->areabase.first; sa; sa= sa->next) {
235                 AZone *az;
236                 for(az= sa->actionzones.first; az; az= az->next) {
237                         if(az->do_draw) {
238                                 if(az->type==AZONE_AREA)
239                                         area_draw_azone(az->x1, az->y1, az->x2, az->y2);
240                                 else if(az->type==AZONE_REGION)
241                                         region_draw_azone(sa, az);
242                                 
243                                 az->do_draw= 0;
244                         }
245                 }
246         }       
247         glDisable( GL_BLEND );
248         
249 }
250
251 /* get scissor rect, checking overlapping regions */
252 void region_scissor_winrct(ARegion *ar, rcti *winrct)
253 {
254         *winrct= ar->winrct;
255         
256         if(ELEM(ar->alignment, RGN_OVERLAP_LEFT, RGN_OVERLAP_RIGHT))
257                 return;
258
259         while(ar->prev) {
260                 ar= ar->prev;
261                 
262                 if(BLI_isect_rcti(winrct, &ar->winrct, NULL)) {
263                         if(ar->flag & RGN_FLAG_HIDDEN);
264                         else if(ar->alignment & RGN_SPLIT_PREV);
265                         else if(ar->alignment==RGN_OVERLAP_LEFT) {
266                                 winrct->xmin= ar->winrct.xmax + 1;
267                         }
268                         else if(ar->alignment==RGN_OVERLAP_RIGHT) {
269                                 winrct->xmax= ar->winrct.xmin - 1;
270                         }
271                         else break;
272                 }
273         }
274 }
275
276 /* only exported for WM */
277 /* makes region ready for drawing, sets pixelspace */
278 void ED_region_set(const bContext *C, ARegion *ar)
279 {
280         wmWindow *win= CTX_wm_window(C);
281         ScrArea *sa= CTX_wm_area(C);
282         rcti winrct;
283         
284         /* checks other overlapping regions */
285         region_scissor_winrct(ar, &winrct);
286         
287         ar->drawrct= winrct;
288         
289         /* note; this sets state, so we can use wmOrtho and friends */
290         wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
291         
292         UI_SetTheme(sa?sa->spacetype:0, ar->type?ar->type->regionid:0);
293         
294         ED_region_pixelspace(ar);
295 }
296
297
298 /* only exported for WM */
299 void ED_region_do_draw(bContext *C, ARegion *ar)
300 {
301         wmWindow *win= CTX_wm_window(C);
302         ScrArea *sa= CTX_wm_area(C);
303         ARegionType *at= ar->type;
304         rcti winrct;
305         
306         /* checks other overlapping regions */
307         region_scissor_winrct(ar, &winrct);
308         
309         /* if no partial draw rect set, full rect */
310         if(ar->drawrct.xmin == ar->drawrct.xmax)
311                 ar->drawrct= winrct;
312         else {
313                 /* extra clip for safety */
314                 ar->drawrct.xmin= MAX2(winrct.xmin, ar->drawrct.xmin);
315                 ar->drawrct.ymin= MAX2(winrct.ymin, ar->drawrct.ymin);
316                 ar->drawrct.xmax= MIN2(winrct.xmax, ar->drawrct.xmax);
317                 ar->drawrct.ymax= MIN2(winrct.ymax, ar->drawrct.ymax);
318         }
319         
320         /* note; this sets state, so we can use wmOrtho and friends */
321         wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
322         
323         UI_SetTheme(sa?sa->spacetype:0, ar->type?ar->type->regionid:0);
324         
325         /* optional header info instead? */
326         if(ar->headerstr) {
327                 float col[3];
328                 UI_GetThemeColor3fv(TH_HEADER, col);
329                 glClearColor(col[0], col[1], col[2], 0.0);
330                 glClear(GL_COLOR_BUFFER_BIT);
331                 
332                 UI_ThemeColor(TH_TEXT);
333                 BLF_draw_default(20, 8, 0.0f, ar->headerstr);
334         }
335         else if(at->draw) {
336                 at->draw(C, ar);
337         }
338         
339         uiFreeInactiveBlocks(C, &ar->uiblocks);
340         
341         if(sa)
342                 region_draw_emboss(ar, &winrct);
343         
344         /* XXX test: add convention to end regions always in pixel space, for drawing of borders/gestures etc */
345         ED_region_pixelspace(ar);
346         
347         ar->do_draw= 0;
348         memset(&ar->drawrct, 0, sizeof(ar->drawrct));
349 }
350
351 /* **********************************
352    maybe silly, but let's try for now
353    to keep these tags protected
354    ********************************** */
355
356 void ED_region_tag_redraw(ARegion *ar)
357 {
358         if(ar) {
359                 /* zero region means full region redraw */
360                 ar->do_draw= 1;
361                 memset(&ar->drawrct, 0, sizeof(ar->drawrct));
362         }
363 }
364
365 void ED_region_tag_redraw_partial(ARegion *ar, rcti *rct)
366 {
367         if(ar) {
368                 if(!ar->do_draw) {
369                         /* no redraw set yet, set partial region */
370                         ar->do_draw= 1;
371                         ar->drawrct= *rct;
372                 }
373                 else if(ar->drawrct.xmin != ar->drawrct.xmax) {
374                         /* partial redraw already set, expand region */
375                         ar->drawrct.xmin= MIN2(ar->drawrct.xmin, rct->xmin);
376                         ar->drawrct.ymin= MIN2(ar->drawrct.ymin, rct->ymin);
377                         ar->drawrct.xmax= MAX2(ar->drawrct.xmax, rct->xmax);
378                         ar->drawrct.ymax= MAX2(ar->drawrct.ymax, rct->ymax);
379                 }
380         }
381 }
382
383 void ED_area_tag_redraw(ScrArea *sa)
384 {
385         ARegion *ar;
386         
387         if(sa)
388                 for(ar= sa->regionbase.first; ar; ar= ar->next)
389                         ED_region_tag_redraw(ar);
390 }
391
392 void ED_area_tag_refresh(ScrArea *sa)
393 {
394         if(sa)
395                 sa->do_refresh= 1;
396 }
397
398 /* *************************************************************** */
399
400 /* use NULL to disable it */
401 void ED_area_headerprint(ScrArea *sa, const char *str)
402 {
403         ARegion *ar;
404         
405         for(ar= sa->regionbase.first; ar; ar= ar->next) {
406                 if(ar->regiontype==RGN_TYPE_HEADER) {
407                         if(str) {
408                                 if(ar->headerstr==NULL)
409                                         ar->headerstr= MEM_mallocN(256, "headerprint");
410                                 BLI_strncpy(ar->headerstr, str, 256);
411                         }
412                         else if(ar->headerstr) {
413                                 MEM_freeN(ar->headerstr);
414                                 ar->headerstr= NULL;
415                         }
416                         ED_region_tag_redraw(ar);
417                 }
418         }
419 }
420
421 /* ************************************************************ */
422
423
424 #define AZONESPOT               12
425 static void area_azone_initialize(ScrArea *sa) 
426 {
427         AZone *az;
428         
429         /* reinitalize entirely, regions add azones too */
430         BLI_freelistN(&sa->actionzones);
431         
432         /* set area action zones */
433         az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
434         BLI_addtail(&(sa->actionzones), az);
435         az->type= AZONE_AREA;
436         az->x1= sa->totrct.xmin;
437         az->y1= sa->totrct.ymin;
438         az->x2= sa->totrct.xmin + AZONESPOT-1;
439         az->y2= sa->totrct.ymin + AZONESPOT-1;
440         BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2);
441         
442         az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
443         BLI_addtail(&(sa->actionzones), az);
444         az->type= AZONE_AREA;
445         az->x1= sa->totrct.xmax+1;
446         az->y1= sa->totrct.ymax+1;
447         az->x2= sa->totrct.xmax-AZONESPOT+1;
448         az->y2= sa->totrct.ymax-AZONESPOT+1;
449         BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2);
450 }
451
452 static void region_azone_initialize(ScrArea *sa, ARegion *ar, char edge) 
453 {
454         AZone *az, *azt;
455         
456         az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
457         BLI_addtail(&(sa->actionzones), az);
458         az->type= AZONE_REGION;
459         az->ar= ar;
460         az->edge= edge;
461         
462         if(edge=='t') {
463                 az->x1= ar->winrct.xmin+AZONESPOT;
464                 az->y1= ar->winrct.ymax;
465                 az->x2= ar->winrct.xmin+2*AZONESPOT;
466                 az->y2= ar->winrct.ymax;
467                 az->x3= (az->x1+az->x2)/2;
468                 az->y3= az->y2+AZONESPOT/2;
469                 BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y3);
470         }
471         else if(edge=='b') {
472                 az->x1= ar->winrct.xmin+AZONESPOT;
473                 az->y1= ar->winrct.ymin;
474                 az->x2= ar->winrct.xmin+2*AZONESPOT;
475                 az->y2= ar->winrct.ymin;
476                 az->x3= (az->x1+az->x2)/2;
477                 az->y3= az->y2-AZONESPOT/2;
478                 BLI_init_rcti(&az->rect, az->x1, az->x2, az->y3, az->y1);
479         }
480         else if(edge=='l') {
481                 az->x1= ar->winrct.xmin;
482                 az->y1= ar->winrct.ymax-AZONESPOT;
483                 az->x2= ar->winrct.xmin;
484                 az->y2= ar->winrct.ymax-2*AZONESPOT;
485                 az->x3= az->x2-AZONESPOT/2;
486                 az->y3= (az->y1+az->y2)/2;
487                 BLI_init_rcti(&az->rect, az->x3, az->x1, az->y1, az->y2);
488         }
489         else { // if(edge=='r') {
490                 az->x1= ar->winrct.xmax;
491                 az->y1= ar->winrct.ymax-AZONESPOT;
492                 az->x2= ar->winrct.xmax;
493                 az->y2= ar->winrct.ymax-2*AZONESPOT;
494                 az->x3= az->x2+AZONESPOT/2;
495                 az->y3= (az->y1+az->y2)/2;
496                 BLI_init_rcti(&az->rect, az->x1, az->x3, az->y1, az->y2);
497         }
498         
499         /* if more azones on 1 spot, set offset */
500         for(azt= sa->actionzones.first; azt; azt= azt->next) {
501                 if(az!=azt) {
502                         if( ABS(az->x1-azt->x1) < 2 && ABS(az->y1-azt->y1) < 2) {
503                                 if(edge=='t' || edge=='b') {
504                                         az->x1+= AZONESPOT;
505                                         az->x2+= AZONESPOT;
506                                         az->x3+= AZONESPOT;
507                                         BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y3);
508                                 }
509                                 else {
510                                         az->y1-= AZONESPOT;
511                                         az->y2-= AZONESPOT;
512                                         az->y3-= AZONESPOT;
513                                         BLI_init_rcti(&az->rect, az->x1, az->x3, az->y1, az->y2);
514                                 }
515                         }
516                 }
517         }
518         
519 }
520
521
522 /* *************************************************************** */
523
524 static void region_azone_add(ScrArea *sa, ARegion *ar, int alignment)
525 {
526          /* edge code (t b l r) is where azone will be drawn */
527         
528         if(alignment==RGN_ALIGN_TOP)
529                 region_azone_initialize(sa, ar, 'b');
530         else if(alignment==RGN_ALIGN_BOTTOM)
531                 region_azone_initialize(sa, ar, 't');
532         else if(ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT))
533                 region_azone_initialize(sa, ar, 'l');
534         else if(ELEM(alignment, RGN_ALIGN_LEFT, RGN_OVERLAP_LEFT))
535                 region_azone_initialize(sa, ar, 'r');
536                                                                 
537 }
538
539 /* dir is direction to check, not the splitting edge direction! */
540 static int rct_fits(rcti *rect, char dir, int size)
541 {
542         if(dir=='h') {
543                 return rect->xmax-rect->xmin - size;
544         }
545         else { // 'v'
546                 return rect->ymax-rect->ymin - size;
547         }
548 }
549
550 static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int quad)
551 {
552         rcti *remainder_prev= remainder;
553         int prefsizex, prefsizey;
554         int alignment;
555         
556         if(ar==NULL)
557                 return;
558         
559         /* no returns in function, winrct gets set in the end again */
560         BLI_init_rcti(&ar->winrct, 0, 0, 0, 0);
561         
562         /* for test; allow split of previously defined region */
563         if(ar->alignment & RGN_SPLIT_PREV)
564                 if(ar->prev)
565                         remainder= &ar->prev->winrct;
566         
567         alignment = ar->alignment & ~RGN_SPLIT_PREV;
568         
569         /* clear state flags first */
570         ar->flag &= ~RGN_FLAG_TOO_SMALL;
571         /* user errors */
572         if(ar->next==NULL && alignment!=RGN_ALIGN_QSPLIT)
573                 alignment= RGN_ALIGN_NONE;
574         
575         prefsizex= ar->type->minsizex;
576         prefsizey= ar->type->minsizey;
577         
578         /* hidden is user flag */
579         if(ar->flag & RGN_FLAG_HIDDEN);
580         /* XXX floating area region, not handled yet here */
581         else if(alignment == RGN_ALIGN_FLOAT);
582         /* remainder is too small for any usage */
583         else if( rct_fits(remainder, 'v', 1)<0 || rct_fits(remainder, 'h', 1) < 0 ) {
584                 ar->flag |= RGN_FLAG_TOO_SMALL;
585         }
586         else if(alignment==RGN_ALIGN_NONE) {
587                 /* typically last region */
588                 ar->winrct= *remainder;
589                 BLI_init_rcti(remainder, 0, 0, 0, 0);
590         }
591         else if(alignment==RGN_ALIGN_TOP || alignment==RGN_ALIGN_BOTTOM) {
592                 
593                 if( rct_fits(remainder, 'v', prefsizey) < 0 ) {
594                         ar->flag |= RGN_FLAG_TOO_SMALL;
595                 }
596                 else {
597                         int fac= rct_fits(remainder, 'v', prefsizey);
598
599                         if(fac < 0 )
600                                 prefsizey += fac;
601                         
602                         ar->winrct= *remainder;
603                         
604                         if(alignment==RGN_ALIGN_TOP) {
605                                 ar->winrct.ymin= ar->winrct.ymax - prefsizey + 1;
606                                 remainder->ymax= ar->winrct.ymin - 1;
607                         }
608                         else {
609                                 ar->winrct.ymax= ar->winrct.ymin + prefsizey - 1;
610                                 remainder->ymin= ar->winrct.ymax + 1;
611                         }
612                 }
613         }
614         else if( ELEM4(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT, RGN_OVERLAP_LEFT, RGN_OVERLAP_RIGHT)) {
615                 
616                 if( rct_fits(remainder, 'h', prefsizex) < 0 ) {
617                         ar->flag |= RGN_FLAG_TOO_SMALL;
618                 }
619                 else {
620                         int fac= rct_fits(remainder, 'h', prefsizex);
621                         
622                         if(fac < 0 )
623                                 prefsizex += fac;
624                         
625                         ar->winrct= *remainder;
626                         
627                         if(ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT)) {
628                                 ar->winrct.xmin= ar->winrct.xmax - prefsizex + 1;
629                                 if(alignment==RGN_ALIGN_RIGHT)
630                                         remainder->xmax= ar->winrct.xmin - 1;
631                         }
632                         else {
633                                 ar->winrct.xmax= ar->winrct.xmin + prefsizex - 1;
634                                 if(alignment==RGN_ALIGN_LEFT)
635                                         remainder->xmin= ar->winrct.xmax + 1;
636                         }
637                 }
638         }
639         else if(alignment==RGN_ALIGN_VSPLIT || alignment==RGN_ALIGN_HSPLIT) {
640                 /* percentage subdiv*/
641                 ar->winrct= *remainder;
642                 
643                 if(alignment==RGN_ALIGN_HSPLIT) {
644                         if( rct_fits(remainder, 'h', prefsizex) > 4) {
645                                 ar->winrct.xmax= (remainder->xmin+remainder->xmax)/2;
646                                 remainder->xmin= ar->winrct.xmax+1;
647                         }
648                         else {
649                                 BLI_init_rcti(remainder, 0, 0, 0, 0);
650                         }
651                 }
652                 else {
653                         if( rct_fits(remainder, 'v', prefsizey) > 4) {
654                                 ar->winrct.ymax= (remainder->ymin+remainder->ymax)/2;
655                                 remainder->ymin= ar->winrct.ymax+1;
656                         }
657                         else {
658                                 BLI_init_rcti(remainder, 0, 0, 0, 0);
659                         }
660                 }
661         }
662         else if(alignment==RGN_ALIGN_QSPLIT) {
663                 ar->winrct= *remainder;
664                 
665                 /* test if there's still 4 regions left */
666                 if(quad==0) {
667                         ARegion *artest= ar->next;
668                         int count= 1;
669                         
670                         while(artest) {
671                                 artest->alignment= RGN_ALIGN_QSPLIT;
672                                 artest= artest->next;
673                                 count++;
674                         }
675                         
676                         if(count!=4) {
677                                 /* let's stop adding regions */
678                                 BLI_init_rcti(remainder, 0, 0, 0, 0);
679                                 printf("region quadsplit failed\n");
680                         }
681                         else quad= 1;
682                 }
683                 if(quad) {
684                         if(quad==1) { /* left bottom */
685                                 ar->winrct.xmax = (remainder->xmin + remainder->xmax)/2;
686                                 ar->winrct.ymax = (remainder->ymin + remainder->ymax)/2;
687                         }
688                         else if(quad==2) { /* left top */
689                                 ar->winrct.xmax = (remainder->xmin + remainder->xmax)/2;
690                                 ar->winrct.ymin = 1 + (remainder->ymin + remainder->ymax)/2;
691                         }
692                         else if(quad==3) { /* right bottom */
693                                 ar->winrct.xmin = 1 + (remainder->xmin + remainder->xmax)/2;
694                                 ar->winrct.ymax = (remainder->ymin + remainder->ymax)/2;
695                         }
696                         else {  /* right top */
697                                 ar->winrct.xmin = 1 + (remainder->xmin + remainder->xmax)/2;
698                                 ar->winrct.ymin = 1 + (remainder->ymin + remainder->ymax)/2;
699                                 BLI_init_rcti(remainder, 0, 0, 0, 0);
700                         }
701
702                         quad++;
703                 }
704         }
705         
706         /* for speedup */
707         ar->winx= ar->winrct.xmax - ar->winrct.xmin + 1;
708         ar->winy= ar->winrct.ymax - ar->winrct.ymin + 1;
709         
710         /* restore test exception */
711         if(ar->alignment & RGN_SPLIT_PREV) {
712                 if(ar->prev) {
713                         remainder= remainder_prev;
714                         ar->prev->winx= ar->prev->winrct.xmax - ar->prev->winrct.xmin + 1;
715                         ar->prev->winy= ar->prev->winrct.ymax - ar->prev->winrct.ymin + 1;
716                 }
717         }
718
719         /* set winrect for azones */
720         if(ar->flag & (RGN_FLAG_HIDDEN|RGN_FLAG_TOO_SMALL)) {
721                 ar->winrct= *remainder;
722                 
723                 if(alignment==RGN_ALIGN_TOP)
724                         ar->winrct.ymin= ar->winrct.ymax;
725                 else if(alignment==RGN_ALIGN_BOTTOM)
726                         ar->winrct.ymax= ar->winrct.ymin;
727                 else if(ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT))
728                         ar->winrct.xmin= ar->winrct.xmax;
729                 else if(ELEM(alignment, RGN_ALIGN_LEFT, RGN_OVERLAP_LEFT))
730                         ar->winrct.xmax= ar->winrct.xmin;
731                 else /* prevent winrct to be valid */
732                         ar->winrct.xmax= ar->winrct.xmin;
733         }
734         /* in end, add azones, where appropriate */
735         region_azone_add(sa, ar, alignment);
736
737
738         region_rect_recursive(sa, ar->next, remainder, quad);
739 }
740
741 static void area_calc_totrct(ScrArea *sa, int sizex, int sizey)
742 {
743         short rt= CLAMPIS(G.rt, 0, 16);
744
745         if(sa->v1->vec.x>0) sa->totrct.xmin= sa->v1->vec.x+1+rt;
746         else sa->totrct.xmin= sa->v1->vec.x;
747         if(sa->v4->vec.x<sizex-1) sa->totrct.xmax= sa->v4->vec.x-1-rt;
748         else sa->totrct.xmax= sa->v4->vec.x;
749         
750         if(sa->v1->vec.y>0) sa->totrct.ymin= sa->v1->vec.y+1+rt;
751         else sa->totrct.ymin= sa->v1->vec.y;
752         if(sa->v2->vec.y<sizey-1) sa->totrct.ymax= sa->v2->vec.y-1-rt;
753         else sa->totrct.ymax= sa->v2->vec.y;
754         
755         /* for speedup */
756         sa->winx= sa->totrct.xmax-sa->totrct.xmin+1;
757         sa->winy= sa->totrct.ymax-sa->totrct.ymin+1;
758 }
759
760
761 /* used for area initialize below */
762 static void region_subwindow(wmWindowManager *wm, wmWindow *win, ARegion *ar)
763 {
764         if(ar->flag & (RGN_FLAG_HIDDEN|RGN_FLAG_TOO_SMALL)) {
765                 if(ar->swinid)
766                         wm_subwindow_close(win, ar->swinid);
767                 ar->swinid= 0;
768         }
769         else if(ar->swinid==0)
770                 ar->swinid= wm_subwindow_open(win, &ar->winrct);
771         else 
772                 wm_subwindow_position(win, ar->swinid, &ar->winrct);
773 }
774
775 static void ed_default_handlers(wmWindowManager *wm, ListBase *handlers, int flag)
776 {
777         /* note, add-handler checks if it already exists */
778         
779         // XXX it would be good to have boundbox checks for some of these...
780         if(flag & ED_KEYMAP_UI) {
781                 UI_add_region_handlers(handlers);
782         }
783         if(flag & ED_KEYMAP_VIEW2D) {
784                 ListBase *keymap= WM_keymap_listbase(wm, "View2D", 0, 0);
785                 WM_event_add_keymap_handler(handlers, keymap);
786         }
787         if(flag & ED_KEYMAP_MARKERS) {
788                 ListBase *keymap= WM_keymap_listbase(wm, "Markers", 0, 0);
789                 WM_event_add_keymap_handler(handlers, keymap);
790                 // XXX need boundbox check urgently!!!
791         }
792         if(flag & ED_KEYMAP_ANIMATION) {
793                 ListBase *keymap= WM_keymap_listbase(wm, "Animation", 0, 0);
794                 WM_event_add_keymap_handler(handlers, keymap);
795         }
796         if(flag & ED_KEYMAP_FRAMES) {
797                 ListBase *keymap= WM_keymap_listbase(wm, "Frames", 0, 0);
798                 WM_event_add_keymap_handler(handlers, keymap);
799         }
800 }
801
802
803 /* called in screen_refresh, or screens_init, also area size changes */
804 void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
805 {
806         ARegion *ar;
807         rcti rect;
808         
809         /* set typedefinitions */
810         sa->type= BKE_spacetype_from_id(sa->spacetype);
811         
812         if(sa->type==NULL) {
813                 sa->butspacetype= sa->spacetype= SPACE_VIEW3D;
814                 sa->type= BKE_spacetype_from_id(sa->spacetype);
815         }
816         
817         for(ar= sa->regionbase.first; ar; ar= ar->next)
818                 ar->type= BKE_regiontype_from_id(sa->type, ar->regiontype);
819         
820         /* area sizes */
821         area_calc_totrct(sa, win->sizex, win->sizey);
822         
823         /* clear all azones, add the area triange widgets */
824         area_azone_initialize(sa);
825
826         /* region rect sizes */
827         rect= sa->totrct;
828         region_rect_recursive(sa, sa->regionbase.first, &rect, 0);
829         
830         /* default area handlers */
831         ed_default_handlers(wm, &sa->handlers, sa->type->keymapflag);
832         /* checks spacedata, adds own handlers */
833         if(sa->type->init)
834                 sa->type->init(wm, sa);
835         
836         /* region windows, default and own handlers */
837         for(ar= sa->regionbase.first; ar; ar= ar->next) {
838                 region_subwindow(wm, win, ar);
839                 
840                 if(ar->swinid) {
841                         /* default region handlers */
842                         ed_default_handlers(wm, &ar->handlers, ar->type->keymapflag);
843
844                         if(ar->type->init)
845                                 ar->type->init(wm, ar);
846                 }
847                 else {
848                         /* prevent uiblocks to run */
849                         uiFreeBlocks(NULL, &ar->uiblocks);      
850                 }
851                 
852         }
853 }
854
855 /* externally called for floating regions like menus */
856 void ED_region_init(bContext *C, ARegion *ar)
857 {
858 //      ARegionType *at= ar->type;
859         
860         /* refresh can be called before window opened */
861         region_subwindow(CTX_wm_manager(C), CTX_wm_window(C), ar);
862         
863         ar->winx= ar->winrct.xmax - ar->winrct.xmin + 1;
864         ar->winy= ar->winrct.ymax - ar->winrct.ymin + 1;
865         
866         /* UI convention */
867         wmLoadIdentity();
868         wmOrtho2(-0.01f, ar->winx-0.01f, -0.01f, ar->winy-0.01f);
869         
870 }
871
872
873 /* sa2 to sa1, we swap spaces for fullscreen to keep all allocated data */
874 /* area vertices were set */
875 void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space)
876 {
877         SpaceType *st;
878         ARegion *ar;
879         
880         sa1->headertype= sa2->headertype;
881         sa1->spacetype= sa2->spacetype;
882         sa1->butspacetype= sa2->butspacetype;
883         
884         if(swap_space == 1) {
885                 SWAP(ListBase, sa1->spacedata, sa2->spacedata);
886                 /* exception: ensure preview is reset */
887 //              if(sa1->spacetype==SPACE_VIEW3D)
888 // XXX                  BIF_view3d_previewrender_free(sa1->spacedata.first);
889         }
890         else if (swap_space == 2) {
891                 BKE_spacedata_copylist(&sa1->spacedata, &sa2->spacedata);
892         }
893         else {
894                 BKE_spacedata_freelist(&sa1->spacedata);
895                 BKE_spacedata_copylist(&sa1->spacedata, &sa2->spacedata);
896         }
897         
898         /* Note; SPACE_EMPTY is possible on new screens */
899         
900         /* regions */
901         if(swap_space<2) {
902                 st= BKE_spacetype_from_id(sa1->spacetype);
903                 for(ar= sa1->regionbase.first; ar; ar= ar->next)
904                         BKE_area_region_free(st, ar);
905                 BLI_freelistN(&sa1->regionbase);
906         }
907         
908         st= BKE_spacetype_from_id(sa2->spacetype);
909         for(ar= sa2->regionbase.first; ar; ar= ar->next) {
910                 ARegion *newar= BKE_area_region_copy(st, ar);
911                 BLI_addtail(&sa1->regionbase, newar);
912         }
913 }
914
915 /* *********** Space switching code *********** */
916
917 void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
918 {
919         ScrArea *tmp= MEM_callocN(sizeof(ScrArea), "addscrarea");
920
921         ED_area_exit(C, sa1);
922         ED_area_exit(C, sa2);
923
924         tmp->spacetype= sa1->spacetype;
925         tmp->butspacetype= sa1->butspacetype;
926         BKE_spacedata_copyfirst(&tmp->spacedata, &sa1->spacedata);
927
928         area_copy_data(tmp, sa1, 2);
929         area_copy_data(sa1, sa2, 0);
930         area_copy_data(sa2, tmp, 0);
931         ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa1);
932         ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa2);
933
934         BKE_screen_area_free(tmp);
935         MEM_freeN(tmp);
936
937         /* tell WM to refresh, cursor types etc */
938         WM_event_add_mousemove(C);
939         
940         ED_area_tag_redraw(sa1);
941         ED_area_tag_refresh(sa1);
942         ED_area_tag_redraw(sa2);
943         ED_area_tag_refresh(sa2);
944 }
945
946 void ED_area_newspace(bContext *C, ScrArea *sa, int type)
947 {
948         if(sa->spacetype != type) {
949                 SpaceType *st;
950                 SpaceLink *slold;
951                 SpaceLink *sl;
952
953                 ED_area_exit(C, sa);
954
955                 st= BKE_spacetype_from_id(type);
956                 slold= sa->spacedata.first;
957
958                 sa->spacetype= type;
959                 sa->butspacetype= type;
960                 sa->type= st;
961                 
962                 /* check previously stored space */
963                 for (sl= sa->spacedata.first; sl; sl= sl->next)
964                         if(sl->spacetype==type)
965                                 break;
966                 
967                 /* old spacedata... happened during work on 2.50, remove */
968                 if(sl && sl->regionbase.first==NULL) {
969                         st->free(sl);
970                         BLI_freelinkN(&sa->spacedata, sl);
971                         sl= NULL;
972                 }
973                 
974                 if (sl) {
975                         
976                         /* swap regions */
977                         slold->regionbase= sa->regionbase;
978                         sa->regionbase= sl->regionbase;
979                         sl->regionbase.first= sl->regionbase.last= NULL;
980                         
981                         /* put in front of list */
982                         BLI_remlink(&sa->spacedata, sl);
983                         BLI_addhead(&sa->spacedata, sl);
984                 } 
985                 else {
986                         /* new space */
987                         if(st) {
988                                 sl= st->new(C);
989                                 BLI_addhead(&sa->spacedata, sl);
990                                 
991                                 /* swap regions */
992                                 if(slold)
993                                         slold->regionbase= sa->regionbase;
994                                 sa->regionbase= sl->regionbase;
995                                 sl->regionbase.first= sl->regionbase.last= NULL;
996                         }
997                 }
998                 
999                 ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
1000                 
1001                 /* tell WM to refresh, cursor types etc */
1002                 WM_event_add_mousemove(C);
1003                 
1004                 ED_area_tag_redraw(sa);
1005                 ED_area_tag_refresh(sa);
1006         }
1007 }
1008
1009 void ED_area_prevspace(bContext *C)
1010 {
1011         SpaceLink *sl= CTX_wm_space_data(C);
1012         ScrArea *sa= CTX_wm_area(C);
1013
1014         /* cleanup */
1015 #if 0 // XXX needs to be space type specific
1016         if(sfile->spacetype==SPACE_FILE) {
1017                 if(sfile->pupmenu) {
1018                         MEM_freeN(sfile->pupmenu);
1019                         sfile->pupmenu= NULL;
1020                 }
1021         }
1022 #endif
1023
1024         if(sl->next) {
1025
1026 #if 0 // XXX check whether this is still needed
1027                 if (sfile->spacetype == SPACE_SCRIPT) {
1028                         SpaceScript *sc = (SpaceScript *)sfile;
1029                         if (sc->script) sc->script->flags &=~SCRIPT_FILESEL;
1030                 }
1031 #endif
1032
1033                 ED_area_newspace(C, sa, sl->next->spacetype);
1034         }
1035         else {
1036                 ED_area_newspace(C, sa, SPACE_INFO);
1037         }
1038         ED_area_tag_redraw(sa);
1039 }
1040
1041 static char *windowtype_pup(void)
1042 {
1043         return(
1044                    "Window type:%t"
1045                    "|3D View %x1"
1046
1047                    "|%l"
1048                    
1049                    "|Timeline %x15"
1050                    "|Graph Editor %x2"
1051                    "|DopeSheet %x12"
1052                    "|NLA Editor %x13"
1053                    
1054                    "|%l"
1055                    
1056                    "|UV/Image Editor %x6"
1057                    
1058                    "|Video Sequence Editor %x8"
1059                    "|Text Editor %x9" 
1060                    "|Node Editor %x16"
1061                    "|Logic Editor %x17"
1062                    
1063                    "|%l"
1064                    
1065                    "|Properties %x4"
1066                    "|Outliner %x3"
1067                    "|User Preferences %x19"
1068                    "|Info%x7"
1069                                    
1070                    "|%l"
1071                    
1072                    "|File Browser %x5"
1073                    
1074                    "|%l"
1075                    
1076                    "|Console %x18"
1077                    );
1078 }
1079
1080 static void spacefunc(struct bContext *C, void *arg1, void *arg2)
1081 {
1082         ED_area_newspace(C, CTX_wm_area(C), CTX_wm_area(C)->butspacetype);
1083         ED_area_tag_redraw(CTX_wm_area(C));
1084 }
1085
1086 /* returns offset for next button in header */
1087 int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
1088 {
1089         ScrArea *sa= CTX_wm_area(C);
1090         uiBut *but;
1091         int xco= 8;
1092         
1093         but= uiDefIconTextButC(block, ICONTEXTROW, 0, ICON_VIEW3D, 
1094                                                    windowtype_pup(), xco, yco, XIC+10, YIC, 
1095                                                    &(sa->butspacetype), 1.0, SPACEICONMAX, 0, 0, 
1096                                                    "Displays Current Window Type. "
1097                                                    "Click for menu of available types.");
1098         uiButSetFunc(but, spacefunc, NULL, NULL);
1099         
1100         return xco + XIC + 14;
1101 }
1102
1103 int ED_area_header_standardbuttons(const bContext *C, uiBlock *block, int yco)
1104 {
1105         ScrArea *sa= CTX_wm_area(C);
1106         int xco= 8;
1107         
1108         xco= ED_area_header_switchbutton(C, block, yco);
1109
1110         uiBlockSetEmboss(block, UI_EMBOSSN);
1111
1112         if (sa->flag & HEADER_NO_PULLDOWN) {
1113                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0, 
1114                                                  ICON_DISCLOSURE_TRI_RIGHT,
1115                                                  xco,yco,XIC,YIC-2,
1116                                                  &(sa->flag), 0, 0, 0, 0, 
1117                                                  "Show pulldown menus");
1118         }
1119         else {
1120                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0, 
1121                                                  ICON_DISCLOSURE_TRI_DOWN,
1122                                                  xco,yco,XIC,YIC-2,
1123                                                  &(sa->flag), 0, 0, 0, 0, 
1124                                                  "Hide pulldown menus");
1125         }
1126
1127         uiBlockSetEmboss(block, UI_EMBOSS);
1128         
1129         return xco + XIC;
1130 }
1131
1132 /************************ standard UI regions ************************/
1133
1134 void ED_region_panels(const bContext *C, ARegion *ar, int vertical, char *context, int contextnr)
1135 {
1136         ScrArea *sa= CTX_wm_area(C);
1137         uiStyle *style= U.uistyles.first;
1138         uiBlock *block;
1139         PanelType *pt;
1140         Panel *panel;
1141         View2D *v2d= &ar->v2d;
1142         View2DScrollers *scrollers;
1143         float col[3];
1144         int xco, yco, x, y, miny=0, w, em, header, triangle, open, newcontext= 0;
1145
1146         if(contextnr >= 0)
1147                 newcontext= UI_view2d_tab_set(v2d, contextnr);
1148
1149         if(vertical) {
1150                 w= v2d->cur.xmax - v2d->cur.xmin;
1151                 em= (ar->type->minsizex)? 10: 20;
1152         }
1153         else {
1154                 w= UI_PANEL_WIDTH;
1155                 em= (ar->type->minsizex)? 10: 20;
1156         }
1157
1158         x= 0;
1159         y= -style->panelouter;
1160
1161         /* create panels */
1162         uiBeginPanels(C, ar);
1163
1164         /* set view2d view matrix for scrolling (without scrollers) */
1165         UI_view2d_view_ortho(C, v2d);
1166
1167         for(pt= ar->type->paneltypes.first; pt; pt= pt->next) {
1168                 /* verify context */
1169                 if(context)
1170                         if(pt->context[0] && strcmp(context, pt->context) != 0)
1171                                 continue;
1172
1173                 /* draw panel */
1174                 if(pt->draw && (!pt->poll || pt->poll(C, pt))) {
1175                         block= uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
1176                         panel= uiBeginPanel(sa, ar, block, pt, &open);
1177
1178                         /* bad fixed values */
1179                         header= (pt->flag & PNL_NO_HEADER)? 0: 20;
1180                         triangle= 22;
1181
1182                         if(vertical)
1183                                 y -= header;
1184
1185                         if(pt->draw_header && header && (open || vertical)) {
1186                                 /* for enabled buttons */
1187                                 panel->layout= uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
1188                                         triangle, header+style->panelspace, header, 1, style);
1189
1190                                 pt->draw_header(C, panel);
1191
1192                                 uiBlockLayoutResolve(C, block, &xco, &yco);
1193                                 panel->labelofs= xco - triangle;
1194                                 panel->layout= NULL;
1195                         }
1196
1197                         if(open) {
1198                                 panel->layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
1199                                         style->panelspace, 0, w-2*style->panelspace, em, style);
1200
1201                                 pt->draw(C, panel);
1202
1203                                 uiBlockLayoutResolve(C, block, &xco, &yco);
1204                                 panel->layout= NULL;
1205
1206                                 yco -= 2*style->panelspace;
1207                                 uiEndPanel(block, w, -yco);
1208                         }
1209                         else {
1210                                 yco= 0;
1211                                 uiEndPanel(block, w, 0);
1212                         }
1213
1214                         uiEndBlock(C, block);
1215
1216                         if(vertical) {
1217                                 if(pt->flag & PNL_NO_HEADER)
1218                                         y += yco;
1219                                 else
1220                                         y += yco-style->panelouter;
1221                         }
1222                         else {
1223                                 x += w;
1224                                 miny= MIN2(y, yco-style->panelouter-header);
1225                         }
1226                 }
1227         }
1228
1229         if(vertical)
1230                 x += w;
1231         else
1232                 y= miny;
1233         
1234         /* in case there are no panels */
1235         if(x == 0 || y == 0) {
1236                 x= UI_PANEL_WIDTH;
1237                 y= UI_PANEL_WIDTH;
1238         }
1239
1240         /* clear */
1241         UI_GetThemeColor3fv(TH_BACK, col);
1242         glClearColor(col[0], col[1], col[2], 0.0);
1243         glClear(GL_COLOR_BUFFER_BIT);
1244
1245         /* before setting the view */
1246         if(vertical) {
1247                 v2d->keepofs |= V2D_LOCKOFS_X|V2D_KEEPOFS_Y;
1248                 v2d->keepofs &= ~(V2D_LOCKOFS_Y|V2D_KEEPOFS_X);
1249                 
1250                 // don't jump back when panels close or hide
1251                 if(!newcontext)
1252                         y= MAX2(-y, -v2d->cur.ymin);
1253                 else
1254                         y= -y;
1255         }
1256         else {
1257                 v2d->keepofs |= V2D_LOCKOFS_Y|V2D_KEEPOFS_X;
1258                 v2d->keepofs &= ~(V2D_LOCKOFS_X|V2D_KEEPOFS_Y);
1259                 
1260                 // don't jump back when panels close or hide
1261                 if(!newcontext)
1262                         x= MAX2(x, v2d->cur.xmax);
1263                 y= -y;
1264         }
1265
1266         // +V2D_SCROLL_HEIGHT is workaround to set the actual height
1267         UI_view2d_totRect_set(v2d, x+V2D_SCROLL_WIDTH, y+V2D_SCROLL_HEIGHT);
1268
1269         /* set the view */
1270         UI_view2d_view_ortho(C, v2d);
1271
1272         /* this does the actual drawing! */
1273         uiEndPanels(C, ar);
1274         
1275         /* restore view matrix */
1276         UI_view2d_view_restore(C);
1277         
1278         /* scrollers */
1279         scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
1280         UI_view2d_scrollers_draw(C, v2d, scrollers);
1281         UI_view2d_scrollers_free(scrollers);
1282 }
1283
1284 void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
1285 {
1286         ListBase *keymap;
1287         
1288         // XXX quick hacks for files saved with 2.5 already (i.e. the builtin defaults file)
1289                 // scrollbars for button regions
1290         ar->v2d.scroll |= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM); 
1291         ar->v2d.keepzoom |= V2D_KEEPZOOM;
1292
1293                 // correctly initialised User-Prefs?
1294         if(!(ar->v2d.align & V2D_ALIGN_NO_POS_Y))
1295                 ar->v2d.flag &= ~V2D_IS_INITIALISED;
1296         
1297         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
1298
1299         keymap= WM_keymap_listbase(wm, "View2D Buttons List", 0, 0);
1300         WM_event_add_keymap_handler(&ar->handlers, keymap);
1301 }
1302
1303 void ED_region_header(const bContext *C, ARegion *ar)
1304 {
1305         uiStyle *style= U.uistyles.first;
1306         uiBlock *block;
1307         uiLayout *layout;
1308         HeaderType *ht;
1309         Header header = {0};
1310         float col[3];
1311         int maxco, xco, yco;
1312
1313         /* clear */
1314         if(ED_screen_area_active(C))
1315                 UI_GetThemeColor3fv(TH_HEADER, col);
1316         else
1317                 UI_GetThemeColor3fv(TH_HEADERDESEL, col);
1318         
1319         glClearColor(col[0], col[1], col[2], 0.0);
1320         glClear(GL_COLOR_BUFFER_BIT);
1321         
1322         /* set view2d view matrix for scrolling (without scrollers) */
1323         UI_view2d_view_ortho(C, &ar->v2d);
1324
1325         xco= maxco= 8;
1326         yco= HEADERY-3;
1327
1328         /* draw all headers types */
1329         for(ht= ar->type->headertypes.first; ht; ht= ht->next) {
1330                 block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
1331                 layout= uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, HEADERY-6, 1, style);
1332
1333                 if(ht->draw) {
1334                         header.type= ht;
1335                         header.layout= layout;
1336                         ht->draw(C, &header);
1337                         
1338                         /* for view2d */
1339                         xco= uiLayoutGetWidth(layout);
1340                         if(xco > maxco)
1341                                 maxco= xco;
1342                 }
1343
1344                 uiBlockLayoutResolve(C, block, &xco, &yco);
1345                 
1346                 /* for view2d */
1347                 if(xco > maxco)
1348                         maxco= xco;
1349                 
1350                 uiEndBlock(C, block);
1351                 uiDrawBlock(C, block);
1352         }
1353
1354         /* always as last  */
1355         UI_view2d_totRect_set(&ar->v2d, maxco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
1356
1357         /* restore view matrix? */
1358         UI_view2d_view_restore(C);
1359 }
1360
1361 void ED_region_header_init(ARegion *ar)
1362 {
1363         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
1364 }
1365