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