Blender V2.61 - r43446

area.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2008 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * 
00022  * Contributor(s): Blender Foundation
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 #include <string.h>
00033 #include <stdio.h>
00034 
00035 #include "MEM_guardedalloc.h"
00036 
00037 #include "DNA_userdef_types.h"
00038 
00039 #include "BLI_blenlib.h"
00040 #include "BLI_math.h"
00041 #include "BLI_rand.h"
00042 #include "BLI_utildefines.h"
00043 
00044 #include "BLF_translation.h"
00045 
00046 #include "BKE_context.h"
00047 #include "BKE_global.h"
00048 #include "BKE_screen.h"
00049 
00050 #include "WM_api.h"
00051 #include "WM_types.h"
00052 #include "wm_subwindow.h"
00053 
00054 #include "ED_screen.h"
00055 #include "ED_screen_types.h"
00056 #include "ED_space_api.h"
00057 #include "ED_types.h"
00058 #include "ED_fileselect.h" 
00059 
00060 #include "BIF_gl.h"
00061 #include "BIF_glutil.h"
00062 #include "BLF_api.h"
00063 
00064 #include "UI_interface.h"
00065 #include "UI_resources.h"
00066 #include "UI_view2d.h"
00067 
00068 #include "screen_intern.h"
00069 
00070 /* general area and region code */
00071 
00072 static void region_draw_emboss(ARegion *ar, rcti *scirct)
00073 {
00074     rcti rect;
00075     
00076     /* translate scissor rect to region space */
00077     rect.xmin= scirct->xmin - ar->winrct.xmin;
00078     rect.ymin= scirct->ymin - ar->winrct.ymin;
00079     rect.xmax= scirct->xmax - ar->winrct.xmin;
00080     rect.ymax= scirct->ymax - ar->winrct.ymin;
00081     
00082     /* set transp line */
00083     glEnable( GL_BLEND );
00084     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00085     
00086     /* right  */
00087     glColor4ub(0,0,0, 30);
00088     sdrawline(rect.xmax, rect.ymin, rect.xmax, rect.ymax);
00089     
00090     /* bottom  */
00091     glColor4ub(0,0,0, 30);
00092     sdrawline(rect.xmin, rect.ymin, rect.xmax, rect.ymin);
00093     
00094     /* top  */
00095     glColor4ub(255,255,255, 30);
00096     sdrawline(rect.xmin, rect.ymax, rect.xmax, rect.ymax);
00097 
00098     /* left  */
00099     glColor4ub(255,255,255, 30);
00100     sdrawline(rect.xmin, rect.ymin, rect.xmin, rect.ymax);
00101     
00102     glDisable( GL_BLEND );
00103 }
00104 
00105 void ED_region_pixelspace(ARegion *ar)
00106 {
00107     int width= ar->winrct.xmax-ar->winrct.xmin+1;
00108     int height= ar->winrct.ymax-ar->winrct.ymin+1;
00109     
00110     wmOrtho2(-0.375f, (float)width-0.375f, -0.375f, (float)height-0.375f);
00111     glLoadIdentity();
00112 }
00113 
00114 /* only exported for WM */
00115 void ED_region_do_listen(ARegion *ar, wmNotifier *note)
00116 {
00117     /* generic notes first */
00118     switch(note->category) {
00119         case NC_WM:
00120             if(note->data==ND_FILEREAD)
00121                 ED_region_tag_redraw(ar);
00122             break;
00123         case NC_WINDOW:
00124             ED_region_tag_redraw(ar);
00125             break;
00126     }
00127 
00128     if(ar->type && ar->type->listener)
00129         ar->type->listener(ar, note);
00130 }
00131 
00132 /* only exported for WM */
00133 void ED_area_do_listen(ScrArea *sa, wmNotifier *note)
00134 {
00135     /* no generic notes? */
00136     if(sa->type && sa->type->listener) {
00137         sa->type->listener(sa, note);
00138     }
00139 }
00140 
00141 /* only exported for WM */
00142 void ED_area_do_refresh(bContext *C, ScrArea *sa)
00143 {
00144     /* no generic notes? */
00145     if(sa->type && sa->type->refresh) {
00146         sa->type->refresh(C, sa);
00147     }
00148     sa->do_refresh= 0;
00149 }
00150 
00151 /* based on screen region draw tags, set draw tags in azones, and future region tabs etc */
00152 /* only exported for WM */
00153 void ED_area_overdraw_flush(ScrArea *sa, ARegion *ar)
00154 {
00155     AZone *az;
00156     
00157     for(az= sa->actionzones.first; az; az= az->next) {
00158         int xs, ys;
00159         
00160         xs= (az->x1+az->x2)/2;
00161         ys= (az->y1+az->y2)/2;
00162 
00163         /* test if inside */
00164         if(BLI_in_rcti(&ar->winrct, xs, ys)) {
00165             az->do_draw= 1;
00166         }
00167     }
00168 }
00169 
00170 static void area_draw_azone(short x1, short y1, short x2, short y2)
00171 {
00172     int dx = x2 - x1;
00173     int dy = y2 - y1;
00174 
00175     dx= copysign(ceil(0.3f*fabs(dx)), dx);
00176     dy= copysign(ceil(0.3f*fabs(dy)), dy);
00177 
00178     glEnable(GL_BLEND);
00179     glEnable(GL_LINE_SMOOTH);
00180     
00181     glColor4ub(255, 255, 255, 180);
00182     fdrawline(x1, y2, x2, y1);
00183     glColor4ub(255, 255, 255, 130);
00184     fdrawline(x1, y2-dy, x2-dx, y1);
00185     glColor4ub(255, 255, 255, 80);
00186     fdrawline(x1, y2-2*dy, x2-2*dx, y1);
00187     
00188     glColor4ub(0, 0, 0, 210);
00189     fdrawline(x1, y2+1, x2+1, y1);
00190     glColor4ub(0, 0, 0, 180);
00191     fdrawline(x1, y2-dy+1, x2-dx+1, y1);
00192     glColor4ub(0, 0, 0, 150);
00193     fdrawline(x1, y2-2*dy+1, x2-2*dx+1, y1);
00194 
00195     glDisable(GL_LINE_SMOOTH);
00196     glDisable(GL_BLEND);
00197 }
00198 
00199 static void region_draw_azone_icon(AZone *az)
00200 {
00201     GLUquadricObj *qobj = NULL; 
00202     short midx = az->x1 + (az->x2 - az->x1)/2;
00203     short midy = az->y1 + (az->y2 - az->y1)/2;
00204         
00205     qobj = gluNewQuadric();
00206     
00207     glPushMatrix();     
00208     glTranslatef(midx, midy, 0.); 
00209     
00210     /* outlined circle */
00211     glEnable(GL_LINE_SMOOTH);
00212 
00213     glColor4f(1.f, 1.f, 1.f, 0.8f);
00214 
00215     gluQuadricDrawStyle(qobj, GLU_FILL); 
00216     gluDisk( qobj, 0.0,  4.25f, 16, 1); 
00217 
00218     glColor4f(0.2f, 0.2f, 0.2f, 0.9f);
00219     
00220     gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
00221     gluDisk( qobj, 0.0,  4.25f, 16, 1); 
00222     
00223     glDisable(GL_LINE_SMOOTH);
00224     
00225     glPopMatrix();
00226     gluDeleteQuadric(qobj);
00227     
00228     /* + */
00229     sdrawline(midx, midy-2, midx, midy+3);
00230     sdrawline(midx-2, midy, midx+3, midy);
00231 }
00232 
00233 static void draw_azone_plus(float x1, float y1, float x2, float y2)
00234 {
00235     float width = 2.0f;
00236     float pad = 4.0f;
00237     
00238     glRectf((x1 + x2 - width)*0.5f, y1 + pad, (x1 + x2 + width)*0.5f, y2 - pad);
00239     glRectf(x1 + pad, (y1 + y2 - width)*0.5f, (x1 + x2 - width)*0.5f, (y1 + y2 + width)*0.5f);
00240     glRectf((x1 + x2 + width)*0.5f, (y1 + y2 - width)*0.5f, x2 - pad, (y1 + y2 + width)*0.5f);
00241 }
00242 
00243 static void region_draw_azone_tab_plus(AZone *az)
00244 {
00245     extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */
00246     
00247     glEnable(GL_BLEND);
00248     
00249     /* add code to draw region hidden as 'too small' */
00250     switch(az->edge) {
00251         case AE_TOP_TO_BOTTOMRIGHT:
00252             uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
00253             break;
00254         case AE_BOTTOM_TO_TOPLEFT:
00255             uiSetRoundBox(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
00256             break;
00257         case AE_LEFT_TO_TOPRIGHT:
00258             uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
00259             break;
00260         case AE_RIGHT_TO_TOPLEFT:
00261             uiSetRoundBox(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
00262             break;
00263     }
00264 
00265     glColor4f(0.05f, 0.05f, 0.05f, 0.4f);
00266     uiRoundBox((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
00267 
00268     glEnable(GL_BLEND);
00269 
00270     glColor4f(0.8f, 0.8f, 0.8f, 0.4f);
00271     draw_azone_plus((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2);
00272 
00273     glDisable(GL_BLEND);
00274 }
00275 
00276 static void region_draw_azone_tab(AZone *az)
00277 {
00278     float col[3];
00279     
00280     glEnable(GL_BLEND);
00281     UI_GetThemeColor3fv(TH_HEADER, col);
00282     glColor4f(col[0], col[1], col[2], 0.5f);
00283     
00284     /* add code to draw region hidden as 'too small' */
00285     switch(az->edge) {
00286         case AE_TOP_TO_BOTTOMRIGHT:
00287             uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_RB_ALPHA);
00288             
00289             uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
00290             glColor4ub(0, 0, 0, 255);
00291             uiRoundRect((float)az->x1, 0.3f+(float)az->y1, (float)az->x2, 0.3f+(float)az->y2, 4.0f);
00292             break;
00293         case AE_BOTTOM_TO_TOPLEFT:
00294             uiSetRoundBox(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA);
00295             
00296             uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
00297             glColor4ub(0, 0, 0, 255);
00298             uiRoundRect((float)az->x1, 0.3f+(float)az->y1, (float)az->x2, 0.3f+(float)az->y2, 4.0f);
00299             break;
00300         case AE_LEFT_TO_TOPRIGHT:
00301             uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA);
00302             
00303             uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
00304             glColor4ub(0, 0, 0, 255);
00305             uiRoundRect((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
00306             break;
00307         case AE_RIGHT_TO_TOPLEFT:
00308             uiSetRoundBox(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_RB_ALPHA);
00309             
00310             uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
00311             glColor4ub(0, 0, 0, 255);
00312             uiRoundRect((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
00313             break;
00314     }
00315     
00316     glDisable(GL_BLEND);
00317 }
00318 
00319 static void region_draw_azone_tria(AZone *az)
00320 {
00321     extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */
00322     
00323     glEnable(GL_BLEND);
00324     //UI_GetThemeColor3fv(TH_HEADER, col);
00325     glColor4f(0.0f, 0.0f, 0.0f, 0.35f);
00326     
00327     /* add code to draw region hidden as 'too small' */
00328     switch(az->edge) {
00329         case AE_TOP_TO_BOTTOMRIGHT:
00330             ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y1, (float)(az->x1+az->x2)/2, (float)az->y2);
00331             break;
00332             
00333         case AE_BOTTOM_TO_TOPLEFT:
00334             ui_draw_anti_tria((float)az->x1, (float)az->y2, (float)az->x2, (float)az->y2, (float)(az->x1+az->x2)/2, (float)az->y1);
00335             break;
00336 
00337         case AE_LEFT_TO_TOPRIGHT:
00338             ui_draw_anti_tria((float)az->x2, (float)az->y1, (float)az->x2, (float)az->y2, (float)az->x1, (float)(az->y1+az->y2)/2);
00339             break;
00340             
00341         case AE_RIGHT_TO_TOPLEFT:
00342             ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x1, (float)az->y2, (float)az->x2, (float)(az->y1+az->y2)/2);
00343             break;
00344             
00345     }
00346     
00347     glDisable(GL_BLEND);
00348 }
00349 
00350 /* only exported for WM */
00351 void ED_area_overdraw(bContext *C)
00352 {
00353     wmWindow *win= CTX_wm_window(C);
00354     bScreen *screen= CTX_wm_screen(C);
00355     ScrArea *sa;
00356     
00357     /* Draw AZones, in screenspace */
00358     wmSubWindowSet(win, screen->mainwin);
00359 
00360     glEnable( GL_BLEND );
00361     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00362     
00363     for(sa= screen->areabase.first; sa; sa= sa->next) {
00364         AZone *az;
00365         for(az= sa->actionzones.first; az; az= az->next) {
00366             if(az->do_draw) {
00367                 if(az->type==AZONE_AREA) {
00368                     area_draw_azone(az->x1, az->y1, az->x2, az->y2);
00369                 } else if(az->type==AZONE_REGION) {
00370                     
00371                     if(az->ar) {
00372                         /* only display tab or icons when the region is hidden */
00373                         if (az->ar->flag & (RGN_FLAG_HIDDEN|RGN_FLAG_TOO_SMALL)) {
00374                             if(G.rt==3)
00375                                 region_draw_azone_icon(az);
00376                             else if(G.rt==2)
00377                                 region_draw_azone_tria(az);
00378                             else if(G.rt==1)
00379                                 region_draw_azone_tab(az);
00380                             else
00381                                 region_draw_azone_tab_plus(az);
00382                         }
00383                     }
00384                 }
00385                 
00386                 az->do_draw= 0;
00387             }
00388         }
00389     }   
00390     glDisable( GL_BLEND );
00391     
00392 }
00393 
00394 /* get scissor rect, checking overlapping regions */
00395 void region_scissor_winrct(ARegion *ar, rcti *winrct)
00396 {
00397     *winrct= ar->winrct;
00398     
00399     if(ELEM(ar->alignment, RGN_OVERLAP_LEFT, RGN_OVERLAP_RIGHT))
00400         return;
00401 
00402     while(ar->prev) {
00403         ar= ar->prev;
00404         
00405         if(BLI_isect_rcti(winrct, &ar->winrct, NULL)) {
00406             if(ar->flag & RGN_FLAG_HIDDEN);
00407             else if(ar->alignment & RGN_SPLIT_PREV);
00408             else if(ar->alignment==RGN_OVERLAP_LEFT) {
00409                 winrct->xmin= ar->winrct.xmax + 1;
00410             }
00411             else if(ar->alignment==RGN_OVERLAP_RIGHT) {
00412                 winrct->xmax= ar->winrct.xmin - 1;
00413             }
00414             else break;
00415         }
00416     }
00417 }
00418 
00419 /* only exported for WM */
00420 /* makes region ready for drawing, sets pixelspace */
00421 void ED_region_set(const bContext *C, ARegion *ar)
00422 {
00423     wmWindow *win= CTX_wm_window(C);
00424     ScrArea *sa= CTX_wm_area(C);
00425     rcti winrct;
00426     
00427     /* checks other overlapping regions */
00428     region_scissor_winrct(ar, &winrct);
00429     
00430     ar->drawrct= winrct;
00431     
00432     /* note; this sets state, so we can use wmOrtho and friends */
00433     wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
00434     
00435     UI_SetTheme(sa?sa->spacetype:0, ar->type?ar->type->regionid:0);
00436     
00437     ED_region_pixelspace(ar);
00438 }
00439 
00440 
00441 /* only exported for WM */
00442 void ED_region_do_draw(bContext *C, ARegion *ar)
00443 {
00444     wmWindow *win= CTX_wm_window(C);
00445     ScrArea *sa= CTX_wm_area(C);
00446     ARegionType *at= ar->type;
00447     rcti winrct;
00448     
00449     /* see BKE_spacedata_draw_locks() */
00450     if(at->do_lock)
00451         return;
00452     
00453     /* checks other overlapping regions */
00454     region_scissor_winrct(ar, &winrct);
00455     
00456     /* if no partial draw rect set, full rect */
00457     if(ar->drawrct.xmin == ar->drawrct.xmax)
00458         ar->drawrct= winrct;
00459     else {
00460         /* extra clip for safety */
00461         ar->drawrct.xmin= MAX2(winrct.xmin, ar->drawrct.xmin);
00462         ar->drawrct.ymin= MAX2(winrct.ymin, ar->drawrct.ymin);
00463         ar->drawrct.xmax= MIN2(winrct.xmax, ar->drawrct.xmax);
00464         ar->drawrct.ymax= MIN2(winrct.ymax, ar->drawrct.ymax);
00465     }
00466     
00467     /* note; this sets state, so we can use wmOrtho and friends */
00468     wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
00469 
00470     ar->do_draw= 0;
00471     memset(&ar->drawrct, 0, sizeof(ar->drawrct));
00472     
00473     UI_SetTheme(sa?sa->spacetype:0, ar->type?ar->type->regionid:0);
00474     
00475     /* optional header info instead? */
00476     if(ar->headerstr) {
00477         UI_ThemeClearColor(TH_HEADER);
00478         glClear(GL_COLOR_BUFFER_BIT);
00479         
00480         UI_ThemeColor(TH_TEXT);
00481         BLF_draw_default(20, 8, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
00482     }
00483     else if(at->draw) {
00484         at->draw(C, ar);
00485     }
00486 
00487     /* XXX test: add convention to end regions always in pixel space, for drawing of borders/gestures etc */
00488     ED_region_pixelspace(ar);
00489 
00490     ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_PIXEL);
00491     
00492     uiFreeInactiveBlocks(C, &ar->uiblocks);
00493 
00494     if(sa)
00495         region_draw_emboss(ar, &winrct);
00496 }
00497 
00498 /* **********************************
00499    maybe silly, but let's try for now
00500    to keep these tags protected
00501    ********************************** */
00502 
00503 void ED_region_tag_redraw(ARegion *ar)
00504 {
00505     if(ar) {
00506         /* zero region means full region redraw */
00507         ar->do_draw= RGN_DRAW;
00508         memset(&ar->drawrct, 0, sizeof(ar->drawrct));
00509     }
00510 }
00511 
00512 void ED_region_tag_redraw_overlay(ARegion *ar)
00513 {
00514     if(ar)
00515         ar->do_draw_overlay= RGN_DRAW;
00516 }
00517 
00518 void ED_region_tag_redraw_partial(ARegion *ar, rcti *rct)
00519 {
00520     if(ar) {
00521         if(!ar->do_draw) {
00522             /* no redraw set yet, set partial region */
00523             ar->do_draw= RGN_DRAW_PARTIAL;
00524             ar->drawrct= *rct;
00525         }
00526         else if(ar->drawrct.xmin != ar->drawrct.xmax) {
00527             /* partial redraw already set, expand region */
00528             ar->drawrct.xmin= MIN2(ar->drawrct.xmin, rct->xmin);
00529             ar->drawrct.ymin= MIN2(ar->drawrct.ymin, rct->ymin);
00530             ar->drawrct.xmax= MAX2(ar->drawrct.xmax, rct->xmax);
00531             ar->drawrct.ymax= MAX2(ar->drawrct.ymax, rct->ymax);
00532         }
00533     }
00534 }
00535 
00536 void ED_area_tag_redraw(ScrArea *sa)
00537 {
00538     ARegion *ar;
00539     
00540     if(sa)
00541         for(ar= sa->regionbase.first; ar; ar= ar->next)
00542             ED_region_tag_redraw(ar);
00543 }
00544 
00545 void ED_area_tag_redraw_regiontype(ScrArea *sa, int regiontype)
00546 {
00547     ARegion *ar;
00548     
00549     if(sa) {
00550         for(ar= sa->regionbase.first; ar; ar= ar->next) {
00551             if(ar->regiontype == regiontype) {
00552                 ED_region_tag_redraw(ar);
00553             }
00554         }
00555     }
00556 }
00557 
00558 void ED_area_tag_refresh(ScrArea *sa)
00559 {
00560     if(sa)
00561         sa->do_refresh= 1;
00562 }
00563 
00564 /* *************************************************************** */
00565 
00566 /* use NULL to disable it */
00567 void ED_area_headerprint(ScrArea *sa, const char *str)
00568 {
00569     ARegion *ar;
00570 
00571     /* happens when running transform operators in backround mode */
00572     if(sa == NULL)
00573         return;
00574 
00575     for(ar= sa->regionbase.first; ar; ar= ar->next) {
00576         if(ar->regiontype==RGN_TYPE_HEADER) {
00577             if(str) {
00578                 if(ar->headerstr==NULL)
00579                     ar->headerstr= MEM_mallocN(256, "headerprint");
00580                 BLI_strncpy(ar->headerstr, str, 256);
00581             }
00582             else if(ar->headerstr) {
00583                 MEM_freeN(ar->headerstr);
00584                 ar->headerstr= NULL;
00585             }
00586             ED_region_tag_redraw(ar);
00587         }
00588     }
00589 }
00590 
00591 /* ************************************************************ */
00592 
00593 
00594 static void area_azone_initialize(ScrArea *sa) 
00595 {
00596     AZone *az;
00597     
00598     /* reinitalize entirely, regions add azones too */
00599     BLI_freelistN(&sa->actionzones);
00600     
00601     /* set area action zones */
00602     az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
00603     BLI_addtail(&(sa->actionzones), az);
00604     az->type= AZONE_AREA;
00605     az->x1= sa->totrct.xmin - 1;
00606     az->y1= sa->totrct.ymin - 1;
00607     az->x2= sa->totrct.xmin + (AZONESPOT-1);
00608     az->y2= sa->totrct.ymin + (AZONESPOT-1);
00609     BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2);
00610     
00611     az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
00612     BLI_addtail(&(sa->actionzones), az);
00613     az->type= AZONE_AREA;
00614     az->x1= sa->totrct.xmax + 1;
00615     az->y1= sa->totrct.ymax + 1;
00616     az->x2= sa->totrct.xmax - (AZONESPOT-1);
00617     az->y2= sa->totrct.ymax - (AZONESPOT-1);
00618     BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2);
00619 }
00620 
00621 #define AZONEPAD_EDGE   4
00622 #define AZONEPAD_ICON   9
00623 static void region_azone_edge(AZone *az, ARegion *ar)
00624 {
00625     switch(az->edge) {
00626         case AE_TOP_TO_BOTTOMRIGHT:
00627             az->x1= ar->winrct.xmin;
00628             az->y1= ar->winrct.ymax - AZONEPAD_EDGE;
00629             az->x2= ar->winrct.xmax;
00630             az->y2= ar->winrct.ymax;
00631             break;
00632         case AE_BOTTOM_TO_TOPLEFT:
00633             az->x1= ar->winrct.xmin;
00634             az->y1= ar->winrct.ymin + AZONEPAD_EDGE;
00635             az->x2= ar->winrct.xmax;
00636             az->y2= ar->winrct.ymin;
00637             break;
00638         case AE_LEFT_TO_TOPRIGHT:
00639             az->x1= ar->winrct.xmin;
00640             az->y1= ar->winrct.ymin;
00641             az->x2= ar->winrct.xmin + AZONEPAD_EDGE;
00642             az->y2= ar->winrct.ymax;
00643             break;
00644         case AE_RIGHT_TO_TOPLEFT:
00645             az->x1= ar->winrct.xmax;
00646             az->y1= ar->winrct.ymin;
00647             az->x2= ar->winrct.xmax - AZONEPAD_EDGE;
00648             az->y2= ar->winrct.ymax;
00649             break;
00650     }
00651 
00652     BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2);
00653 }
00654 
00655 static void region_azone_icon(ScrArea *sa, AZone *az, ARegion *ar)
00656 {
00657     AZone *azt;
00658     int tot=0;
00659     
00660     /* count how many actionzones with along same edge are available.
00661        This allows for adding more action zones in the future without
00662        having to worry about correct offset */
00663     for(azt= sa->actionzones.first; azt; azt= azt->next) {
00664         if(azt->edge == az->edge) tot++;
00665     }
00666     
00667     switch(az->edge) {
00668         case AE_TOP_TO_BOTTOMRIGHT:
00669             az->x1= ar->winrct.xmax - tot*2*AZONEPAD_ICON;
00670             az->y1= ar->winrct.ymax + AZONEPAD_ICON;
00671             az->x2= ar->winrct.xmax - tot*AZONEPAD_ICON;
00672             az->y2= ar->winrct.ymax + 2*AZONEPAD_ICON;
00673             break;
00674         case AE_BOTTOM_TO_TOPLEFT:
00675             az->x1= ar->winrct.xmin + AZONEPAD_ICON;
00676             az->y1= ar->winrct.ymin - 2*AZONEPAD_ICON;
00677             az->x2= ar->winrct.xmin + 2*AZONEPAD_ICON;
00678             az->y2= ar->winrct.ymin - AZONEPAD_ICON;
00679             break;
00680         case AE_LEFT_TO_TOPRIGHT:
00681             az->x1= ar->winrct.xmin - 2*AZONEPAD_ICON;
00682             az->y1= ar->winrct.ymax - tot*2*AZONEPAD_ICON;
00683             az->x2= ar->winrct.xmin - AZONEPAD_ICON;
00684             az->y2= ar->winrct.ymax - tot*AZONEPAD_ICON;
00685             break;
00686         case AE_RIGHT_TO_TOPLEFT:
00687             az->x1= ar->winrct.xmax + AZONEPAD_ICON;
00688             az->y1= ar->winrct.ymax - tot*2*AZONEPAD_ICON;
00689             az->x2= ar->winrct.xmax + 2*AZONEPAD_ICON;
00690             az->y2= ar->winrct.ymax - tot*AZONEPAD_ICON;
00691             break;
00692     }
00693 
00694     BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2);
00695     
00696     /* if more azones on 1 spot, set offset */
00697     for(azt= sa->actionzones.first; azt; azt= azt->next) {
00698         if(az!=azt) {
00699             if( ABS(az->x1-azt->x1) < 2 && ABS(az->y1-azt->y1) < 2) {
00700                 if(az->edge==AE_TOP_TO_BOTTOMRIGHT || az->edge==AE_BOTTOM_TO_TOPLEFT) {
00701                     az->x1+= AZONESPOT;
00702                     az->x2+= AZONESPOT;
00703                 }
00704                 else{
00705                     az->y1-= AZONESPOT;
00706                     az->y2-= AZONESPOT;
00707                 }
00708                 BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2);
00709             }
00710         }
00711     }
00712 }
00713 
00714 #define AZONEPAD_TAB_PLUSW  14
00715 #define AZONEPAD_TAB_PLUSH  14
00716 
00717 /* region already made zero sized, in shape of edge */
00718 static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
00719 {
00720     AZone *azt;
00721     int tot= 0, add;
00722     
00723     for(azt= sa->actionzones.first; azt; azt= azt->next) {
00724         if(azt->edge == az->edge) tot++;
00725     }
00726     
00727     switch(az->edge) {
00728         case AE_TOP_TO_BOTTOMRIGHT:
00729             if(ar->winrct.ymax == sa->totrct.ymin) add= 1; else add= 0;
00730             az->x1= ar->winrct.xmax - 2.5*AZONEPAD_TAB_PLUSW;
00731             az->y1= ar->winrct.ymax - add;
00732             az->x2= ar->winrct.xmax - 1.5*AZONEPAD_TAB_PLUSW;
00733             az->y2= ar->winrct.ymax - add + AZONEPAD_TAB_PLUSH;
00734             break;
00735         case AE_BOTTOM_TO_TOPLEFT:
00736             az->x1= ar->winrct.xmax - 2.5*AZONEPAD_TAB_PLUSW;
00737             az->y1= ar->winrct.ymin - AZONEPAD_TAB_PLUSH;
00738             az->x2= ar->winrct.xmax - 1.5*AZONEPAD_TAB_PLUSW;
00739             az->y2= ar->winrct.ymin;
00740             break;
00741         case AE_LEFT_TO_TOPRIGHT:
00742             az->x1= ar->winrct.xmin - AZONEPAD_TAB_PLUSH;
00743             az->y1= ar->winrct.ymax - 2.5*AZONEPAD_TAB_PLUSW;
00744             az->x2= ar->winrct.xmin;
00745             az->y2= ar->winrct.ymax - 1.5*AZONEPAD_TAB_PLUSW;
00746             break;
00747         case AE_RIGHT_TO_TOPLEFT:
00748             az->x1= ar->winrct.xmax - 1;
00749             az->y1= ar->winrct.ymax - 2.5*AZONEPAD_TAB_PLUSW;
00750             az->x2= ar->winrct.xmax - 1 + AZONEPAD_TAB_PLUSH;
00751             az->y2= ar->winrct.ymax - 1.5*AZONEPAD_TAB_PLUSW;
00752             break;
00753     }
00754     /* rect needed for mouse pointer test */
00755     BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2);
00756 }   
00757 
00758 
00759 #define AZONEPAD_TABW   18
00760 #define AZONEPAD_TABH   7
00761 
00762 /* region already made zero sized, in shape of edge */
00763 static void region_azone_tab(ScrArea *sa, AZone *az, ARegion *ar)
00764 {
00765     AZone *azt;
00766     int tot= 0, add;
00767     
00768     for(azt= sa->actionzones.first; azt; azt= azt->next) {
00769         if(azt->edge == az->edge) tot++;
00770     }
00771     
00772     switch(az->edge) {
00773         case AE_TOP_TO_BOTTOMRIGHT:
00774             if(ar->winrct.ymax == sa->totrct.ymin) add= 1; else add= 0;
00775             az->x1= ar->winrct.xmax - 2*AZONEPAD_TABW;
00776             az->y1= ar->winrct.ymax - add;
00777             az->x2= ar->winrct.xmax - AZONEPAD_TABW;
00778             az->y2= ar->winrct.ymax - add + AZONEPAD_TABH;
00779             break;
00780         case AE_BOTTOM_TO_TOPLEFT:
00781             az->x1= ar->winrct.xmin + AZONEPAD_TABW;
00782             az->y1= ar->winrct.ymin - AZONEPAD_TABH;
00783             az->x2= ar->winrct.xmin + 2*AZONEPAD_TABW;
00784             az->y2= ar->winrct.ymin;
00785             break;
00786         case AE_LEFT_TO_TOPRIGHT:
00787             az->x1= ar->winrct.xmin + 1 - AZONEPAD_TABH;
00788             az->y1= ar->winrct.ymax - 2*AZONEPAD_TABW;
00789             az->x2= ar->winrct.xmin + 1;
00790             az->y2= ar->winrct.ymax - AZONEPAD_TABW;
00791             break;
00792         case AE_RIGHT_TO_TOPLEFT:
00793             az->x1= ar->winrct.xmax - 1;
00794             az->y1= ar->winrct.ymax - 2*AZONEPAD_TABW;
00795             az->x2= ar->winrct.xmax - 1 + AZONEPAD_TABH;
00796             az->y2= ar->winrct.ymax - AZONEPAD_TABW;
00797             break;
00798     }
00799     /* rect needed for mouse pointer test */
00800     BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2);
00801 }   
00802 
00803 #define AZONEPAD_TRIAW  16
00804 #define AZONEPAD_TRIAH  9
00805 
00806 
00807 /* region already made zero sized, in shape of edge */
00808 static void region_azone_tria(ScrArea *sa, AZone *az, ARegion *ar)
00809 {
00810     AZone *azt;
00811     int tot= 0, add;
00812     
00813     for(azt= sa->actionzones.first; azt; azt= azt->next) {
00814         if(azt->edge == az->edge) tot++;
00815     }
00816     
00817     switch(az->edge) {
00818         case AE_TOP_TO_BOTTOMRIGHT:
00819             if(ar->winrct.ymax == sa->totrct.ymin) add= 1; else add= 0;
00820             az->x1= ar->winrct.xmax - 2*AZONEPAD_TRIAW;
00821             az->y1= ar->winrct.ymax - add;
00822             az->x2= ar->winrct.xmax - AZONEPAD_TRIAW;
00823             az->y2= ar->winrct.ymax - add + AZONEPAD_TRIAH;
00824             break;
00825             case AE_BOTTOM_TO_TOPLEFT:
00826             az->x1= ar->winrct.xmin + AZONEPAD_TRIAW;
00827             az->y1= ar->winrct.ymin - AZONEPAD_TRIAH;
00828             az->x2= ar->winrct.xmin + 2*AZONEPAD_TRIAW;
00829             az->y2= ar->winrct.ymin;
00830             break;
00831             case AE_LEFT_TO_TOPRIGHT:
00832             az->x1= ar->winrct.xmin + 1 - AZONEPAD_TRIAH;
00833             az->y1= ar->winrct.ymax - 2*AZONEPAD_TRIAW;
00834             az->x2= ar->winrct.xmin + 1;
00835             az->y2= ar->winrct.ymax - AZONEPAD_TRIAW;
00836             break;
00837             case AE_RIGHT_TO_TOPLEFT:
00838             az->x1= ar->winrct.xmax - 1;
00839             az->y1= ar->winrct.ymax - 2*AZONEPAD_TRIAW;
00840             az->x2= ar->winrct.xmax - 1 + AZONEPAD_TRIAH;
00841             az->y2= ar->winrct.ymax - AZONEPAD_TRIAW;
00842             break;
00843     }
00844     /* rect needed for mouse pointer test */
00845     BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2);
00846 }   
00847 
00848 
00849 static void region_azone_initialize(ScrArea *sa, ARegion *ar, AZEdge edge) 
00850 {
00851     AZone *az;
00852     
00853     az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
00854     BLI_addtail(&(sa->actionzones), az);
00855     az->type= AZONE_REGION;
00856     az->ar= ar;
00857     az->edge= edge;
00858     
00859     if (ar->flag & (RGN_FLAG_HIDDEN|RGN_FLAG_TOO_SMALL)) {
00860         if(G.rt==3)
00861             region_azone_icon(sa, az, ar);
00862         else if(G.rt==2)
00863             region_azone_tria(sa, az, ar);
00864         else if(G.rt==1)
00865             region_azone_tab(sa, az, ar);
00866         else
00867             region_azone_tab_plus(sa, az, ar);
00868     } else {
00869         region_azone_edge(az, ar);
00870     }
00871     
00872 }
00873 
00874 
00875 /* *************************************************************** */
00876 
00877 static void region_azone_add(ScrArea *sa, ARegion *ar, int alignment)
00878 {
00879      /* edge code (t b l r) is along which area edge azone will be drawn */
00880     
00881     if(alignment==RGN_ALIGN_TOP)
00882         region_azone_initialize(sa, ar, AE_BOTTOM_TO_TOPLEFT);
00883     else if(alignment==RGN_ALIGN_BOTTOM)
00884         region_azone_initialize(sa, ar, AE_TOP_TO_BOTTOMRIGHT);
00885     else if(ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT))
00886         region_azone_initialize(sa, ar, AE_LEFT_TO_TOPRIGHT);
00887     else if(ELEM(alignment, RGN_ALIGN_LEFT, RGN_OVERLAP_LEFT))
00888         region_azone_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT);
00889 }
00890 
00891 /* dir is direction to check, not the splitting edge direction! */
00892 static int rct_fits(rcti *rect, char dir, int size)
00893 {
00894     if(dir=='h') {
00895         return rect->xmax-rect->xmin - size;
00896     }
00897     else { // 'v'
00898         return rect->ymax-rect->ymin - size;
00899     }
00900 }
00901 
00902 static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int quad)
00903 {
00904     rcti *remainder_prev= remainder;
00905     int prefsizex, prefsizey;
00906     int alignment;
00907     
00908     if(ar==NULL)
00909         return;
00910     
00911     /* no returns in function, winrct gets set in the end again */
00912     BLI_init_rcti(&ar->winrct, 0, 0, 0, 0);
00913     
00914     /* for test; allow split of previously defined region */
00915     if(ar->alignment & RGN_SPLIT_PREV)
00916         if(ar->prev)
00917             remainder= &ar->prev->winrct;
00918     
00919     alignment = ar->alignment & ~RGN_SPLIT_PREV;
00920     
00921     /* clear state flags first */
00922     ar->flag &= ~RGN_FLAG_TOO_SMALL;
00923     /* user errors */
00924     if(ar->next==NULL && alignment!=RGN_ALIGN_QSPLIT)
00925         alignment= RGN_ALIGN_NONE;
00926     
00927     /* prefsize, for header we stick to exception */
00928     prefsizex= ar->sizex?ar->sizex:ar->type->prefsizex;
00929     if(ar->regiontype==RGN_TYPE_HEADER)
00930         prefsizey= ar->type->prefsizey;
00931     else if(ar->regiontype==RGN_TYPE_UI && sa->spacetype == SPACE_FILE) {
00932         prefsizey= UI_UNIT_Y * 2 + (UI_UNIT_Y/2);
00933     }
00934     else
00935         prefsizey= ar->sizey?ar->sizey:ar->type->prefsizey;
00936     
00937     /* hidden is user flag */
00938     if(ar->flag & RGN_FLAG_HIDDEN);
00939     /* XXX floating area region, not handled yet here */
00940     else if(alignment == RGN_ALIGN_FLOAT);
00941     /* remainder is too small for any usage */
00942     else if( rct_fits(remainder, 'v', 1)<0 || rct_fits(remainder, 'h', 1) < 0 ) {
00943         ar->flag |= RGN_FLAG_TOO_SMALL;
00944     }
00945     else if(alignment==RGN_ALIGN_NONE) {
00946         /* typically last region */
00947         ar->winrct= *remainder;
00948         BLI_init_rcti(remainder, 0, 0, 0, 0);
00949     }
00950     else if(alignment==RGN_ALIGN_TOP || alignment==RGN_ALIGN_BOTTOM) {
00951         
00952         if( rct_fits(remainder, 'v', prefsizey) < 0 ) {
00953             ar->flag |= RGN_FLAG_TOO_SMALL;
00954         }
00955         else {
00956             int fac= rct_fits(remainder, 'v', prefsizey);
00957 
00958             if(fac < 0 )
00959                 prefsizey += fac;
00960             
00961             ar->winrct= *remainder;
00962             
00963             if(alignment==RGN_ALIGN_TOP) {
00964                 ar->winrct.ymin= ar->winrct.ymax - prefsizey + 1;
00965                 remainder->ymax= ar->winrct.ymin - 1;
00966             }
00967             else {
00968                 ar->winrct.ymax= ar->winrct.ymin + prefsizey - 1;
00969                 remainder->ymin= ar->winrct.ymax + 1;
00970             }
00971         }
00972     }
00973     else if( ELEM4(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT, RGN_OVERLAP_LEFT, RGN_OVERLAP_RIGHT)) {
00974         
00975         if( rct_fits(remainder, 'h', prefsizex) < 0 ) {
00976             ar->flag |= RGN_FLAG_TOO_SMALL;
00977         }
00978         else {
00979             int fac= rct_fits(remainder, 'h', prefsizex);
00980             
00981             if(fac < 0 )
00982                 prefsizex += fac;
00983             
00984             ar->winrct= *remainder;
00985             
00986             if(ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT)) {
00987                 ar->winrct.xmin= ar->winrct.xmax - prefsizex + 1;
00988                 if(alignment==RGN_ALIGN_RIGHT)
00989                     remainder->xmax= ar->winrct.xmin - 1;
00990             }
00991             else {
00992                 ar->winrct.xmax= ar->winrct.xmin + prefsizex - 1;
00993                 if(alignment==RGN_ALIGN_LEFT)
00994                     remainder->xmin= ar->winrct.xmax + 1;
00995             }
00996         }
00997     }
00998     else if(alignment==RGN_ALIGN_VSPLIT || alignment==RGN_ALIGN_HSPLIT) {
00999         /* percentage subdiv*/
01000         ar->winrct= *remainder;
01001         
01002         if(alignment==RGN_ALIGN_HSPLIT) {
01003             if( rct_fits(remainder, 'h', prefsizex) > 4) {
01004                 ar->winrct.xmax= (remainder->xmin+remainder->xmax)/2;
01005                 remainder->xmin= ar->winrct.xmax+1;
01006             }
01007             else {
01008                 BLI_init_rcti(remainder, 0, 0, 0, 0);
01009             }
01010         }
01011         else {
01012             if( rct_fits(remainder, 'v', prefsizey) > 4) {
01013                 ar->winrct.ymax= (remainder->ymin+remainder->ymax)/2;
01014                 remainder->ymin= ar->winrct.ymax+1;
01015             }
01016             else {
01017                 BLI_init_rcti(remainder, 0, 0, 0, 0);
01018             }
01019         }
01020     }
01021     else if(alignment==RGN_ALIGN_QSPLIT) {
01022         ar->winrct= *remainder;
01023         
01024         /* test if there's still 4 regions left */
01025         if(quad==0) {
01026             ARegion *artest= ar->next;
01027             int count= 1;
01028             
01029             while(artest) {
01030                 artest->alignment= RGN_ALIGN_QSPLIT;
01031                 artest= artest->next;
01032                 count++;
01033             }
01034             
01035             if(count!=4) {
01036                 /* let's stop adding regions */
01037                 BLI_init_rcti(remainder, 0, 0, 0, 0);
01038                 if (G.f & G_DEBUG)
01039                     printf("region quadsplit failed\n");
01040             }
01041             else quad= 1;
01042         }
01043         if(quad) {
01044             if(quad==1) { /* left bottom */
01045                 ar->winrct.xmax = (remainder->xmin + remainder->xmax)/2;
01046                 ar->winrct.ymax = (remainder->ymin + remainder->ymax)/2;
01047             }
01048             else if(quad==2) { /* left top */
01049                 ar->winrct.xmax = (remainder->xmin + remainder->xmax)/2;
01050                 ar->winrct.ymin = 1 + (remainder->ymin + remainder->ymax)/2;
01051             }
01052             else if(quad==3) { /* right bottom */
01053                 ar->winrct.xmin = 1 + (remainder->xmin + remainder->xmax)/2;
01054                 ar->winrct.ymax = (remainder->ymin + remainder->ymax)/2;
01055             }
01056             else {  /* right top */
01057                 ar->winrct.xmin = 1 + (remainder->xmin + remainder->xmax)/2;
01058                 ar->winrct.ymin = 1 + (remainder->ymin + remainder->ymax)/2;
01059                 BLI_init_rcti(remainder, 0, 0, 0, 0);
01060             }
01061 
01062             quad++;
01063         }
01064     }
01065     
01066     /* for speedup */
01067     ar->winx= ar->winrct.xmax - ar->winrct.xmin + 1;
01068     ar->winy= ar->winrct.ymax - ar->winrct.ymin + 1;
01069     
01070     /* set winrect for azones */
01071     if(ar->flag & (RGN_FLAG_HIDDEN|RGN_FLAG_TOO_SMALL)) {
01072         ar->winrct= *remainder;
01073         
01074         if(alignment==RGN_ALIGN_TOP)
01075             ar->winrct.ymin= ar->winrct.ymax;
01076         else if(alignment==RGN_ALIGN_BOTTOM)
01077             ar->winrct.ymax= ar->winrct.ymin;
01078         else if(ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT))
01079             ar->winrct.xmin= ar->winrct.xmax;
01080         else if(ELEM(alignment, RGN_ALIGN_LEFT, RGN_OVERLAP_LEFT))
01081             ar->winrct.xmax= ar->winrct.xmin;
01082         else /* prevent winrct to be valid */
01083             ar->winrct.xmax= ar->winrct.xmin;
01084     }
01085 
01086     /* restore prev-split exception */
01087     if(ar->alignment & RGN_SPLIT_PREV) {
01088         if(ar->prev) {
01089             remainder= remainder_prev;
01090             ar->prev->winx= ar->prev->winrct.xmax - ar->prev->winrct.xmin + 1;
01091             ar->prev->winy= ar->prev->winrct.ymax - ar->prev->winrct.ymin + 1;
01092         }
01093     }
01094     
01095     /* in end, add azones, where appropriate */
01096     if(ar->regiontype == RGN_TYPE_HEADER && ar->winy + 6 > sa->winy) {
01097         /* The logic for this is: when the header takes up the full area,
01098          * disallow hiding it to view the main window.
01099          *
01100          * Without this, you can drag down the file selectors header and hide it
01101          * by accident very easily (highly annoying!), the value 6 is arbitrary
01102          * but accounts for small common rounding problems when scaling the UI,
01103          * must be minimum '4' */
01104     }
01105     else {
01106         region_azone_add(sa, ar, alignment);
01107     }
01108 
01109     region_rect_recursive(sa, ar->next, remainder, quad);
01110 }
01111 
01112 static void area_calc_totrct(ScrArea *sa, int sizex, int sizey)
01113 {
01114     short rt= 0; // CLAMPIS(G.rt, 0, 16);
01115 
01116     if(sa->v1->vec.x>0) sa->totrct.xmin= sa->v1->vec.x+1+rt;
01117     else sa->totrct.xmin= sa->v1->vec.x;
01118     if(sa->v4->vec.x<sizex-1) sa->totrct.xmax= sa->v4->vec.x-1-rt;
01119     else sa->totrct.xmax= sa->v4->vec.x;
01120     
01121     if(sa->v1->vec.y>0) sa->totrct.ymin= sa->v1->vec.y+1+rt;
01122     else sa->totrct.ymin= sa->v1->vec.y;
01123     if(sa->v2->vec.y<sizey-1) sa->totrct.ymax= sa->v2->vec.y-1-rt;
01124     else sa->totrct.ymax= sa->v2->vec.y;
01125     
01126     /* for speedup */
01127     sa->winx= sa->totrct.xmax-sa->totrct.xmin+1;
01128     sa->winy= sa->totrct.ymax-sa->totrct.ymin+1;
01129 }
01130 
01131 
01132 /* used for area initialize below */
01133 static void region_subwindow(wmWindow *win, ARegion *ar)
01134 {
01135     if(ar->flag & (RGN_FLAG_HIDDEN|RGN_FLAG_TOO_SMALL)) {
01136         if(ar->swinid)
01137             wm_subwindow_close(win, ar->swinid);
01138         ar->swinid= 0;
01139     }
01140     else if(ar->swinid==0)
01141         ar->swinid= wm_subwindow_open(win, &ar->winrct);
01142     else 
01143         wm_subwindow_position(win, ar->swinid, &ar->winrct);
01144 }
01145 
01146 static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *handlers, int flag)
01147 {
01148     /* note, add-handler checks if it already exists */
01149     
01150     // XXX it would be good to have boundbox checks for some of these...
01151     if(flag & ED_KEYMAP_UI) {
01152         /* user interface widgets */
01153         UI_add_region_handlers(handlers);
01154     }
01155     if(flag & ED_KEYMAP_VIEW2D) {
01156         /* 2d-viewport handling+manipulation */
01157         wmKeyMap *keymap= WM_keymap_find(wm->defaultconf, "View2D", 0, 0);
01158         WM_event_add_keymap_handler(handlers, keymap);
01159     }
01160     if(flag & ED_KEYMAP_MARKERS) {
01161         /* time-markers */
01162         wmKeyMap *keymap= WM_keymap_find(wm->defaultconf, "Markers", 0, 0);
01163         
01164         /* time space only has this keymap, the others get a boundbox restricted map */
01165         if(sa->spacetype!=SPACE_TIME) {
01166             ARegion *ar;
01167             static rcti rect= {0, 10000, 0, 30};    /* same local check for all areas */
01168             ar= BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
01169             if(ar) {
01170                 WM_event_add_keymap_handler_bb(handlers, keymap, &rect, &ar->winrct);
01171             }
01172         }
01173         else
01174             WM_event_add_keymap_handler(handlers, keymap);
01175     }
01176     if(flag & ED_KEYMAP_ANIMATION) {
01177         /* frame changing and timeline operators (for time spaces) */
01178         wmKeyMap *keymap= WM_keymap_find(wm->defaultconf, "Animation", 0, 0);
01179         WM_event_add_keymap_handler(handlers, keymap);
01180     }
01181     if(flag & ED_KEYMAP_FRAMES) {
01182         /* frame changing/jumping (for all spaces) */
01183         wmKeyMap *keymap= WM_keymap_find(wm->defaultconf, "Frames", 0, 0);
01184         WM_event_add_keymap_handler(handlers, keymap);
01185     }
01186     if(flag & ED_KEYMAP_GPENCIL) {
01187         /* grease pencil */
01188         wmKeyMap *keymap= WM_keymap_find(wm->defaultconf, "Grease Pencil", 0, 0);
01189         WM_event_add_keymap_handler(handlers, keymap);
01190     }
01191     if(flag & ED_KEYMAP_HEADER) {
01192         /* standard keymap for headers regions */
01193         wmKeyMap *keymap= WM_keymap_find(wm->defaultconf, "Header", 0, 0);
01194         WM_event_add_keymap_handler(handlers, keymap);
01195     }
01196 }
01197 
01198 
01199 /* called in screen_refresh, or screens_init, also area size changes */
01200 void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
01201 {
01202     ARegion *ar;
01203     rcti rect;
01204     
01205     /* set typedefinitions */
01206     sa->type= BKE_spacetype_from_id(sa->spacetype);
01207     
01208     if(sa->type==NULL) {
01209         sa->butspacetype= sa->spacetype= SPACE_VIEW3D;
01210         sa->type= BKE_spacetype_from_id(sa->spacetype);
01211     }
01212     
01213     for(ar= sa->regionbase.first; ar; ar= ar->next)
01214         ar->type= BKE_regiontype_from_id(sa->type, ar->regiontype);
01215     
01216     /* area sizes */
01217     area_calc_totrct(sa, win->sizex, win->sizey);
01218     
01219     /* clear all azones, add the area triange widgets */
01220     area_azone_initialize(sa);
01221 
01222     /* region rect sizes */
01223     rect= sa->totrct;
01224     region_rect_recursive(sa, sa->regionbase.first, &rect, 0);
01225     
01226     /* default area handlers */
01227     ed_default_handlers(wm, sa, &sa->handlers, sa->type->keymapflag);
01228     /* checks spacedata, adds own handlers */
01229     if(sa->type->init)
01230         sa->type->init(wm, sa);
01231     
01232     /* region windows, default and own handlers */
01233     for(ar= sa->regionbase.first; ar; ar= ar->next) {
01234         region_subwindow(win, ar);
01235         
01236         if(ar->swinid) {
01237             /* default region handlers */
01238             ed_default_handlers(wm, sa, &ar->handlers, ar->type->keymapflag);
01239             /* own handlers */
01240             if(ar->type->init)
01241                 ar->type->init(wm, ar);
01242         }
01243         else {
01244             /* prevent uiblocks to run */
01245             uiFreeBlocks(NULL, &ar->uiblocks);  
01246         }
01247         
01248         /* rechecks 2d matrix for header on dpi changing, do not do for other regions, it resets view && blocks view2d operator polls (ton) */
01249         if(ar->regiontype==RGN_TYPE_HEADER)
01250             ar->v2d.flag &= ~V2D_IS_INITIALISED;
01251     }
01252 }
01253 
01254 /* externally called for floating regions like menus */
01255 void ED_region_init(bContext *C, ARegion *ar)
01256 {
01257 //  ARegionType *at= ar->type;
01258     
01259     /* refresh can be called before window opened */
01260     region_subwindow(CTX_wm_window(C), ar);
01261     
01262     ar->winx= ar->winrct.xmax - ar->winrct.xmin + 1;
01263     ar->winy= ar->winrct.ymax - ar->winrct.ymin + 1;
01264     
01265     /* UI convention */
01266     wmOrtho2(-0.01f, ar->winx-0.01f, -0.01f, ar->winy-0.01f);
01267     glLoadIdentity();
01268 }
01269 
01270 void ED_region_toggle_hidden(bContext *C, ARegion *ar)
01271 {
01272     ScrArea *sa= CTX_wm_area(C);
01273 
01274     ar->flag ^= RGN_FLAG_HIDDEN;
01275 
01276     if(ar->flag & RGN_FLAG_HIDDEN)
01277         WM_event_remove_handlers(C, &ar->handlers);
01278 
01279     ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
01280     ED_area_tag_redraw(sa);
01281 }
01282 
01283 /* sa2 to sa1, we swap spaces for fullscreen to keep all allocated data */
01284 /* area vertices were set */
01285 void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space)
01286 {
01287     SpaceType *st;
01288     ARegion *ar;
01289     int spacetype= sa1->spacetype;
01290     
01291     sa1->headertype= sa2->headertype;
01292     sa1->spacetype= sa2->spacetype;
01293     sa1->butspacetype= sa2->butspacetype;
01294     
01295     if(swap_space == 1) {
01296         SWAP(ListBase, sa1->spacedata, sa2->spacedata);
01297         /* exception: ensure preview is reset */
01298 //      if(sa1->spacetype==SPACE_VIEW3D)
01299 // XXX          BIF_view3d_previewrender_free(sa1->spacedata.first);
01300     }
01301     else if (swap_space == 2) {
01302         BKE_spacedata_copylist(&sa1->spacedata, &sa2->spacedata);
01303     }
01304     else {
01305         BKE_spacedata_freelist(&sa1->spacedata);
01306         BKE_spacedata_copylist(&sa1->spacedata, &sa2->spacedata);
01307     }
01308     
01309     /* Note; SPACE_EMPTY is possible on new screens */
01310     
01311     /* regions */
01312     if(swap_space == 1) {
01313         SWAP(ListBase, sa1->regionbase, sa2->regionbase);
01314     }
01315     else {
01316         if(swap_space<2) {
01317             st= BKE_spacetype_from_id(spacetype);
01318             for(ar= sa1->regionbase.first; ar; ar= ar->next)
01319                 BKE_area_region_free(st, ar);
01320             BLI_freelistN(&sa1->regionbase);
01321         }
01322         
01323         st= BKE_spacetype_from_id(sa2->spacetype);
01324         for(ar= sa2->regionbase.first; ar; ar= ar->next) {
01325             ARegion *newar= BKE_area_region_copy(st, ar);
01326             BLI_addtail(&sa1->regionbase, newar);
01327         }
01328     }
01329 }
01330 
01331 /* *********** Space switching code *********** */
01332 
01333 void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
01334 {
01335     ScrArea *tmp= MEM_callocN(sizeof(ScrArea), "addscrarea");
01336 
01337     ED_area_exit(C, sa1);
01338     ED_area_exit(C, sa2);
01339 
01340     area_copy_data(tmp, sa1, 2);
01341     area_copy_data(sa1, sa2, 0);
01342     area_copy_data(sa2, tmp, 0);
01343     ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa1);
01344     ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa2);
01345 
01346     BKE_screen_area_free(tmp);
01347     MEM_freeN(tmp);
01348 
01349     /* tell WM to refresh, cursor types etc */
01350     WM_event_add_mousemove(C);
01351     
01352     ED_area_tag_redraw(sa1);
01353     ED_area_tag_refresh(sa1);
01354     ED_area_tag_redraw(sa2);
01355     ED_area_tag_refresh(sa2);
01356 }
01357 
01358 void ED_area_newspace(bContext *C, ScrArea *sa, int type)
01359 {
01360     if(sa->spacetype != type) {
01361         SpaceType *st;
01362         SpaceLink *slold;
01363         SpaceLink *sl;
01364 
01365         ED_area_exit(C, sa);
01366 
01367         st= BKE_spacetype_from_id(type);
01368         slold= sa->spacedata.first;
01369 
01370         sa->spacetype= type;
01371         sa->butspacetype= type;
01372         sa->type= st;
01373         
01374         /* check previously stored space */
01375         for (sl= sa->spacedata.first; sl; sl= sl->next)
01376             if(sl->spacetype==type)
01377                 break;
01378         
01379         /* old spacedata... happened during work on 2.50, remove */
01380         if(sl && sl->regionbase.first==NULL) {
01381             st->free(sl);
01382             BLI_freelinkN(&sa->spacedata, sl);
01383             if(slold == sl) {
01384                 slold= NULL;
01385             }
01386             sl= NULL;
01387         }
01388         
01389         if (sl) {
01390             
01391             /* swap regions */
01392             slold->regionbase= sa->regionbase;
01393             sa->regionbase= sl->regionbase;
01394             sl->regionbase.first= sl->regionbase.last= NULL;
01395             
01396             /* put in front of list */
01397             BLI_remlink(&sa->spacedata, sl);
01398             BLI_addhead(&sa->spacedata, sl);
01399         } 
01400         else {
01401             /* new space */
01402             if(st) {
01403                 sl= st->new(C);
01404                 BLI_addhead(&sa->spacedata, sl);
01405                 
01406                 /* swap regions */
01407                 if(slold)
01408                     slold->regionbase= sa->regionbase;
01409                 sa->regionbase= sl->regionbase;
01410                 sl->regionbase.first= sl->regionbase.last= NULL;
01411             }
01412         }
01413         
01414         ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
01415         
01416         /* tell WM to refresh, cursor types etc */
01417         WM_event_add_mousemove(C);
01418                 
01419         /*send space change notifier*/
01420         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_CHANGED, sa);
01421         
01422         ED_area_tag_refresh(sa);
01423     }
01424     
01425     /* also redraw when re-used */
01426     ED_area_tag_redraw(sa);
01427 }
01428 
01429 void ED_area_prevspace(bContext *C, ScrArea *sa)
01430 {
01431     SpaceLink *sl = (sa) ? sa->spacedata.first : CTX_wm_space_data(C);
01432 
01433     if(sl->next) {
01434         /* workaround for case of double prevspace, render window
01435            with a file browser on top of it */
01436         if(sl->next->spacetype == SPACE_FILE && sl->next->next)
01437             ED_area_newspace(C, sa, sl->next->next->spacetype);
01438         else
01439             ED_area_newspace(C, sa, sl->next->spacetype);
01440     }
01441     else {
01442         ED_area_newspace(C, sa, SPACE_INFO);
01443     }
01444     ED_area_tag_redraw(sa);
01445 
01446     /*send space change notifier*/
01447     WM_event_add_notifier(C, NC_SPACE|ND_SPACE_CHANGED, sa);
01448 }
01449 
01450 static const char *editortype_pup(void)
01451 {
01452     const char *types= N_(
01453            "Editor type:%t"
01454            "|3D View %x1"
01455 
01456            "|%l"
01457            
01458            "|Timeline %x15"
01459            "|Graph Editor %x2"
01460            "|DopeSheet %x12"
01461            "|NLA Editor %x13"
01462            
01463            "|%l"
01464            
01465            "|UV/Image Editor %x6"
01466            
01467            "|Video Sequence Editor %x8"
01468            "|Movie Clip Editor %x20"
01469            "|Text Editor %x9" 
01470            "|Node Editor %x16"
01471            "|Logic Editor %x17"
01472            
01473            "|%l"
01474            
01475            "|Properties %x4"
01476            "|Outliner %x3"
01477            "|User Preferences %x19"
01478            "|Info%x7"
01479 
01480            "|%l"
01481 
01482            "|File Browser %x5"
01483            
01484            "|%l"
01485            
01486            "|Python Console %x18"
01487            );
01488 
01489     return IFACE_(types);
01490 }
01491 
01492 static void spacefunc(struct bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
01493 {
01494     ED_area_newspace(C, CTX_wm_area(C), CTX_wm_area(C)->butspacetype);
01495     ED_area_tag_redraw(CTX_wm_area(C));
01496 
01497     /*send space change notifier*/
01498     WM_event_add_notifier(C, NC_SPACE|ND_SPACE_CHANGED, CTX_wm_area(C));
01499 }
01500 
01501 /* returns offset for next button in header */
01502 int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
01503 {
01504     ScrArea *sa= CTX_wm_area(C);
01505     uiBut *but;
01506     int xco= 8;
01507     
01508     but= uiDefIconTextButC(block, ICONTEXTROW, 0, ICON_VIEW3D, 
01509                            editortype_pup(), xco, yco, UI_UNIT_X+10, UI_UNIT_Y, 
01510                            &(sa->butspacetype), 1.0, SPACEICONMAX, 0, 0, 
01511                            TIP_("Displays current editor type. Click for menu of available types"));
01512     uiButSetFunc(but, spacefunc, NULL, NULL);
01513     uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
01514     
01515     return xco + UI_UNIT_X + 14;
01516 }
01517 
01518 int ED_area_header_standardbuttons(const bContext *C, uiBlock *block, int yco)
01519 {
01520     ScrArea *sa= CTX_wm_area(C);
01521     int xco= 8;
01522     uiBut *but;
01523     
01524     if (!sa->full)
01525         xco= ED_area_header_switchbutton(C, block, yco);
01526 
01527     uiBlockSetEmboss(block, UI_EMBOSSN);
01528 
01529     if (sa->flag & HEADER_NO_PULLDOWN) {
01530         but= uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0,
01531                          ICON_DISCLOSURE_TRI_RIGHT,
01532                          xco,yco,UI_UNIT_X,UI_UNIT_Y-2,
01533                          &(sa->flag), 0, 0, 0, 0, 
01534                          "Show pulldown menus");
01535     }
01536     else {
01537         but= uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0,
01538                          ICON_DISCLOSURE_TRI_DOWN,
01539                          xco,yco,UI_UNIT_X,UI_UNIT_Y-2,
01540                          &(sa->flag), 0, 0, 0, 0, 
01541                          "Hide pulldown menus");
01542     }
01543 
01544     uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
01545 
01546     uiBlockSetEmboss(block, UI_EMBOSS);
01547     
01548     return xco + UI_UNIT_X;
01549 }
01550 
01551 /************************ standard UI regions ************************/
01552 
01553 void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *context, int contextnr)
01554 {
01555     ScrArea *sa= CTX_wm_area(C);
01556     uiStyle *style= UI_GetStyle();
01557     uiBlock *block;
01558     PanelType *pt;
01559     Panel *panel;
01560     View2D *v2d= &ar->v2d;
01561     View2DScrollers *scrollers;
01562     int x, y, xco, yco, w, em, triangle, open, newcontext= 0;
01563 
01564     if(contextnr >= 0)
01565         newcontext= UI_view2d_tab_set(v2d, contextnr);
01566 
01567     if(vertical) {
01568         w= v2d->cur.xmax - v2d->cur.xmin;
01569         em= (ar->type->prefsizex)? UI_UNIT_Y/2: UI_UNIT_Y;
01570     }
01571     else {
01572         w= UI_PANEL_WIDTH;
01573         em= (ar->type->prefsizex)? UI_UNIT_Y/2: UI_UNIT_Y;
01574     }
01575 
01576     /* create panels */
01577     uiBeginPanels(C, ar);
01578 
01579     /* set view2d view matrix for scrolling (without scrollers) */
01580     UI_view2d_view_ortho(v2d);
01581 
01582     for(pt= ar->type->paneltypes.first; pt; pt= pt->next) {
01583         /* verify context */
01584         if(context)
01585             if(pt->context[0] && strcmp(context, pt->context) != 0)
01586                 continue;
01587 
01588         /* draw panel */
01589         if(pt->draw && (!pt->poll || pt->poll(C, pt))) {
01590             block= uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
01591             panel= uiBeginPanel(sa, ar, block, pt, &open);
01592 
01593             /* bad fixed values */
01594             triangle= (int)(UI_UNIT_Y * 1.1f);
01595 
01596             if(pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
01597                 /* for enabled buttons */
01598                 panel->layout= uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
01599                     triangle, UI_UNIT_Y+style->panelspace+2, UI_UNIT_Y, 1, style);
01600 
01601                 pt->draw_header(C, panel);
01602 
01603                 uiBlockLayoutResolve(block, &xco, &yco);
01604                 panel->labelofs= xco - triangle;
01605                 panel->layout= NULL;
01606             }
01607             else {
01608                 panel->labelofs= 0;
01609             }
01610 
01611             if(open) {
01612                 short panelContext;
01613                 
01614                 /* panel context can either be toolbar region or normal panels region */
01615                 if (ar->regiontype == RGN_TYPE_TOOLS)
01616                     panelContext= UI_LAYOUT_TOOLBAR;
01617                 else
01618                     panelContext= UI_LAYOUT_PANEL;
01619                 
01620                 panel->layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
01621                     style->panelspace, 0, w-2*style->panelspace, em, style);
01622 
01623                 pt->draw(C, panel);
01624 
01625                 uiBlockLayoutResolve(block, &xco, &yco);
01626                 panel->layout= NULL;
01627 
01628                 yco -= 2*style->panelspace;
01629                 uiEndPanel(block, w, -yco);
01630             }
01631             else {
01632                 yco= 0;
01633                 uiEndPanel(block, w, 0);
01634             }
01635 
01636             uiEndBlock(C, block);
01637         }
01638     }
01639 
01640     /* align panels and return size */
01641     uiEndPanels(C, ar, &x, &y);
01642 
01643     /* clear */
01644     UI_ThemeClearColor((ar->type->regionid == RGN_TYPE_PREVIEW)?TH_PREVIEW_BACK:TH_BACK);
01645     glClear(GL_COLOR_BUFFER_BIT);
01646     
01647     /* before setting the view */
01648     if(vertical) {
01649         /* only allow scrolling in vertical direction */
01650         v2d->keepofs |= V2D_LOCKOFS_X|V2D_KEEPOFS_Y;
01651         v2d->keepofs &= ~(V2D_LOCKOFS_Y|V2D_KEEPOFS_X);
01652         v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
01653         v2d->scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
01654         
01655         // don't jump back when panels close or hide
01656         if(!newcontext)
01657             y= MAX2(-y, -v2d->cur.ymin);
01658         else
01659             y= -y;
01660     }
01661     else {
01662         /* for now, allow scrolling in both directions (since layouts are optimised for vertical,
01663          * they often don't fit in horizontal layout)
01664          */
01665         v2d->keepofs &= ~(V2D_LOCKOFS_X|V2D_LOCKOFS_Y|V2D_KEEPOFS_X|V2D_KEEPOFS_Y);
01666         //v2d->keepofs |= V2D_LOCKOFS_Y|V2D_KEEPOFS_X;
01667         //v2d->keepofs &= ~(V2D_LOCKOFS_X|V2D_KEEPOFS_Y);
01668         v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
01669         v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_HIDE;
01670         
01671         // don't jump back when panels close or hide
01672         if(!newcontext)
01673             x= MAX2(x, v2d->cur.xmax);
01674         y= -y;
01675     }
01676 
01677     // +V2D_SCROLL_HEIGHT is workaround to set the actual height
01678     UI_view2d_totRect_set(v2d, x+V2D_SCROLL_WIDTH, y+V2D_SCROLL_HEIGHT);
01679 
01680     /* set the view */
01681     UI_view2d_view_ortho(v2d);
01682 
01683     /* draw panels */
01684     uiDrawPanels(C, ar);
01685 
01686     /* restore view matrix */
01687     UI_view2d_view_restore(C);
01688     
01689     /* scrollers */
01690     scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
01691     UI_view2d_scrollers_draw(C, v2d, scrollers);
01692     UI_view2d_scrollers_free(scrollers);
01693 }
01694 
01695 void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
01696 {
01697     wmKeyMap *keymap;
01698     
01699     // XXX quick hacks for files saved with 2.5 already (i.e. the builtin defaults file)
01700         // scrollbars for button regions
01701     ar->v2d.scroll |= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM); 
01702     ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
01703     ar->v2d.scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
01704     ar->v2d.keepzoom |= V2D_KEEPZOOM;
01705 
01706         // correctly initialised User-Prefs?
01707     if(!(ar->v2d.align & V2D_ALIGN_NO_POS_Y))
01708         ar->v2d.flag &= ~V2D_IS_INITIALISED;
01709     
01710     UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
01711 
01712     keymap= WM_keymap_find(wm->defaultconf, "View2D Buttons List", 0, 0);
01713     WM_event_add_keymap_handler(&ar->handlers, keymap);
01714 }
01715 
01716 void ED_region_header(const bContext *C, ARegion *ar)
01717 {
01718     uiStyle *style= UI_GetStyle();
01719     uiBlock *block;
01720     uiLayout *layout;
01721     HeaderType *ht;
01722     Header header = {NULL};
01723     int maxco, xco, yco;
01724     int headery= ED_area_headersize();
01725 
01726     /* clear */ 
01727     UI_ThemeClearColor((ED_screen_area_active(C))?TH_HEADER:TH_HEADERDESEL);
01728     glClear(GL_COLOR_BUFFER_BIT);
01729     
01730     /* set view2d view matrix for scrolling (without scrollers) */
01731     UI_view2d_view_ortho(&ar->v2d);
01732 
01733     xco= maxco= 8;
01734     yco= headery-4;
01735 
01736     /* draw all headers types */
01737     for(ht= ar->type->headertypes.first; ht; ht= ht->next) {
01738         block= uiBeginBlock(C, ar, ht->idname, UI_EMBOSS);
01739         layout= uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, UI_UNIT_Y, 1, style);
01740 
01741         if(ht->draw) {
01742             header.type= ht;
01743             header.layout= layout;
01744             ht->draw(C, &header);
01745             
01746             /* for view2d */
01747             xco= uiLayoutGetWidth(layout);
01748             if(xco > maxco)
01749                 maxco= xco;
01750         }
01751 
01752         uiBlockLayoutResolve(block, &xco, &yco);
01753         
01754         /* for view2d */
01755         if(xco > maxco)
01756             maxco= xco;
01757         
01758         uiEndBlock(C, block);
01759         uiDrawBlock(C, block);
01760     }
01761 
01762     /* always as last  */
01763     UI_view2d_totRect_set(&ar->v2d, maxco+UI_UNIT_X+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
01764 
01765     /* restore view matrix? */
01766     UI_view2d_view_restore(C);
01767 }
01768 
01769 void ED_region_header_init(ARegion *ar)
01770 {
01771     UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
01772 }
01773 
01774 /* UI_UNIT_Y is defined as U variable now, depending dpi */
01775 int ED_area_headersize(void)
01776 {
01777     return UI_UNIT_Y+6;
01778 }
01779 
01780 void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha)
01781 {
01782     const int header_height = 18;
01783     uiStyle *style= UI_GetStyle();
01784     int fontid= style->widget.uifont_id;
01785     rcti rect;
01786 
01787     BLF_size(fontid, 11.0f, 72);
01788 
01789     /* background box */
01790     rect= ar->winrct;
01791     rect.xmin= 0;
01792     rect.ymin= ar->winrct.ymax - ar->winrct.ymin - header_height;
01793 
01794     if(block) {
01795         rect.xmax= ar->winrct.xmax - ar->winrct.xmin;
01796     }
01797     else {
01798         rect.xmax= rect.xmin + BLF_width(fontid, text) + 24;
01799     }
01800 
01801     rect.ymax= ar->winrct.ymax - ar->winrct.ymin;
01802 
01803     glEnable(GL_BLEND);
01804     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
01805     glColor4f(0.0f, 0.0f, 0.0f, alpha);
01806     glRecti(rect.xmin, rect.ymin, rect.xmax+1, rect.ymax+1);
01807     glDisable(GL_BLEND);
01808 
01809     /* text */
01810     UI_ThemeColor(TH_TEXT_HI);
01811     BLF_position(fontid, 12, rect.ymin + 5, 0.0f);
01812     BLF_draw(fontid, text, BLF_DRAW_STR_DUMMY_MAX);
01813 }