Blender V2.61 - r43446
|
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 }