|
Blender
V2.59
|
00001 /* 00002 * $Id: interface_panel.c 38743 2011-07-26 19:47:56Z campbellbarton $ 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) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * Contributor(s): Blender Foundation, 2003-2009 full recode. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 /* a full doc with API notes can be found in bf-blender/trunk/blender/doc/guides/interface_API.txt */ 00034 00035 #include <math.h> 00036 #include <stdlib.h> 00037 #include <string.h> 00038 #include <ctype.h> 00039 00040 #include "MEM_guardedalloc.h" 00041 00042 #include "PIL_time.h" 00043 00044 #include "BLI_blenlib.h" 00045 #include "BLI_math.h" 00046 #include "BLI_utildefines.h" 00047 00048 #include "DNA_userdef_types.h" 00049 00050 #include "BKE_context.h" 00051 #include "BKE_screen.h" 00052 00053 #include "BIF_gl.h" 00054 #include "BIF_glutil.h" 00055 00056 #include "WM_api.h" 00057 #include "WM_types.h" 00058 00059 #include "ED_screen.h" 00060 00061 #include "UI_interface.h" 00062 00063 #include "interface_intern.h" 00064 00065 /*********************** defines and structs ************************/ 00066 00067 #define ANIMATION_TIME 0.30 00068 #define ANIMATION_INTERVAL 0.02 00069 00070 #define PNL_LAST_ADDED 1 00071 #define PNL_ACTIVE 2 00072 #define PNL_WAS_ACTIVE 4 00073 #define PNL_ANIM_ALIGN 8 00074 #define PNL_NEW_ADDED 16 00075 #define PNL_FIRST 32 00076 00077 typedef enum uiHandlePanelState { 00078 PANEL_STATE_DRAG, 00079 PANEL_STATE_DRAG_SCALE, 00080 PANEL_STATE_WAIT_UNTAB, 00081 PANEL_STATE_ANIMATION, 00082 PANEL_STATE_EXIT 00083 } uiHandlePanelState; 00084 00085 typedef struct uiHandlePanelData { 00086 uiHandlePanelState state; 00087 00088 /* animation */ 00089 wmTimer *animtimer; 00090 double starttime; 00091 00092 /* dragging */ 00093 int startx, starty; 00094 int startofsx, startofsy; 00095 int startsizex, startsizey; 00096 } uiHandlePanelData; 00097 00098 static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state); 00099 00100 /*********************** space specific code ************************/ 00101 /* temporary code to remove all sbuts stuff from panel code */ 00102 00103 static int panel_aligned(ScrArea *sa, ARegion *ar) 00104 { 00105 if(sa->spacetype==SPACE_BUTS && ar->regiontype == RGN_TYPE_WINDOW) { 00106 SpaceButs *sbuts= sa->spacedata.first; 00107 return sbuts->align; 00108 } 00109 else if(sa->spacetype==SPACE_USERPREF && ar->regiontype == RGN_TYPE_WINDOW) 00110 return BUT_VERTICAL; 00111 else if(sa->spacetype==SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) 00112 return BUT_VERTICAL; 00113 else if(sa->spacetype==SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW) 00114 return BUT_VERTICAL; 00115 else if(ELEM3(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS)) 00116 return BUT_VERTICAL; 00117 00118 return 0; 00119 } 00120 00121 static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa) 00122 { 00123 Panel *pa; 00124 int active= 0; 00125 00126 *r_pa= NULL; 00127 00128 if(sa->spacetype==SPACE_BUTS && ar->regiontype == RGN_TYPE_WINDOW) { 00129 SpaceButs *sbuts= sa->spacedata.first; 00130 00131 if(sbuts->align) 00132 if(sbuts->re_align || sbuts->mainbo!=sbuts->mainb) 00133 return 1; 00134 } 00135 else if(ar->regiontype==RGN_TYPE_UI) 00136 return 1; 00137 else if(sa->spacetype==SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW) 00138 return 1; 00139 else if(sa->spacetype==SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) 00140 return 1; 00141 00142 /* in case panel is added or disappears */ 00143 for(pa=ar->panels.first; pa; pa=pa->next) { 00144 if((pa->runtime_flag & PNL_WAS_ACTIVE) && !(pa->runtime_flag & PNL_ACTIVE)) 00145 return 1; 00146 if(!(pa->runtime_flag & PNL_WAS_ACTIVE) && (pa->runtime_flag & PNL_ACTIVE)) 00147 return 1; 00148 if(pa->activedata) 00149 active= 1; 00150 } 00151 00152 /* in case we need to do an animation (size changes) */ 00153 for(pa=ar->panels.first; pa; pa=pa->next) { 00154 if(pa->runtime_flag & PNL_ANIM_ALIGN) { 00155 if(!active) 00156 *r_pa= pa; 00157 return 1; 00158 } 00159 } 00160 00161 return 0; 00162 } 00163 00164 /****************************** panels ******************************/ 00165 00166 static void ui_panel_copy_offset(Panel *pa, Panel *papar) 00167 { 00168 /* with respect to sizes... papar is parent */ 00169 00170 pa->ofsx= papar->ofsx; 00171 pa->ofsy= papar->ofsy + papar->sizey-pa->sizey; 00172 } 00173 00174 Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int *open) 00175 { 00176 uiStyle *style= U.uistyles.first; 00177 Panel *pa, *patab, *palast, *panext; 00178 char *drawname= pt->label; 00179 char *idname= pt->idname; 00180 char *tabname= pt->idname; 00181 char *hookname= NULL; 00182 int newpanel; 00183 int align= panel_aligned(sa, ar); 00184 00185 /* check if Panel exists, then use that one */ 00186 for(pa=ar->panels.first; pa; pa=pa->next) 00187 if(strncmp(pa->panelname, idname, UI_MAX_NAME_STR)==0) 00188 if(strncmp(pa->tabname, tabname, UI_MAX_NAME_STR)==0) 00189 break; 00190 00191 newpanel= (pa == NULL); 00192 00193 if(!newpanel) { 00194 pa->type= pt; 00195 } 00196 else { 00197 /* new panel */ 00198 pa= MEM_callocN(sizeof(Panel), "new panel"); 00199 pa->type= pt; 00200 BLI_strncpy(pa->panelname, idname, UI_MAX_NAME_STR); 00201 BLI_strncpy(pa->tabname, tabname, UI_MAX_NAME_STR); 00202 00203 if(pt->flag & PNL_DEFAULT_CLOSED) { 00204 if(align == BUT_VERTICAL) 00205 pa->flag |= PNL_CLOSEDY; 00206 else 00207 pa->flag |= PNL_CLOSEDX; 00208 } 00209 00210 pa->ofsx= 0; 00211 pa->ofsy= style->panelouter; 00212 pa->sizex= 0; 00213 pa->sizey= 0; 00214 pa->runtime_flag |= PNL_NEW_ADDED; 00215 00216 BLI_addtail(&ar->panels, pa); 00217 00218 /* make new Panel tabbed? */ 00219 if(hookname) { 00220 for(patab= ar->panels.first; patab; patab= patab->next) { 00221 if((patab->runtime_flag & PNL_ACTIVE) && patab->paneltab==NULL) { 00222 if(strncmp(hookname, patab->panelname, UI_MAX_NAME_STR)==0) { 00223 if(strncmp(tabname, patab->tabname, UI_MAX_NAME_STR)==0) { 00224 pa->paneltab= patab; 00225 ui_panel_copy_offset(pa, patab); 00226 break; 00227 } 00228 } 00229 } 00230 } 00231 } 00232 } 00233 00234 BLI_strncpy(pa->drawname, drawname, UI_MAX_NAME_STR); 00235 00236 /* if a new panel is added, we insert it right after the panel 00237 * that was last added. this way new panels are inserted in the 00238 * right place between versions */ 00239 for(palast=ar->panels.first; palast; palast=palast->next) 00240 if(palast->runtime_flag & PNL_LAST_ADDED) 00241 break; 00242 00243 if(newpanel) { 00244 pa->sortorder= (palast)? palast->sortorder+1: 0; 00245 00246 for(panext=ar->panels.first; panext; panext=panext->next) 00247 if(panext != pa && panext->sortorder >= pa->sortorder) 00248 panext->sortorder++; 00249 } 00250 00251 if(palast) 00252 palast->runtime_flag &= ~PNL_LAST_ADDED; 00253 00254 /* assign to block */ 00255 block->panel= pa; 00256 pa->runtime_flag |= PNL_ACTIVE|PNL_LAST_ADDED; 00257 00258 *open= 0; 00259 00260 if(pa->paneltab) return pa; 00261 if(pa->flag & PNL_CLOSED) return pa; 00262 00263 *open= 1; 00264 00265 return pa; 00266 } 00267 00268 void uiEndPanel(uiBlock *block, int width, int height) 00269 { 00270 Panel *pa= block->panel; 00271 00272 if(pa->runtime_flag & PNL_NEW_ADDED) { 00273 pa->runtime_flag &= ~PNL_NEW_ADDED; 00274 pa->sizex= width; 00275 pa->sizey= height; 00276 } 00277 else { 00278 /* check if we need to do an animation */ 00279 if(!ELEM(width, 0, pa->sizex) || !ELEM(height, 0, pa->sizey)) { 00280 pa->runtime_flag |= PNL_ANIM_ALIGN; 00281 if(height != 0) 00282 pa->ofsy += pa->sizey-height; 00283 } 00284 00285 /* update width/height if non-zero */ 00286 if(width != 0) 00287 pa->sizex= width; 00288 if(height != 0) 00289 pa->sizey= height; 00290 } 00291 } 00292 00293 static void ui_offset_panel_block(uiBlock *block) 00294 { 00295 uiStyle *style= U.uistyles.first; 00296 uiBut *but; 00297 int ofsy; 00298 00299 /* compute bounds and offset */ 00300 ui_bounds_block(block); 00301 00302 ofsy= block->panel->sizey - style->panelspace; 00303 00304 for(but= block->buttons.first; but; but=but->next) { 00305 but->y1 += ofsy; 00306 but->y2 += ofsy; 00307 } 00308 00309 block->maxx= block->panel->sizex; 00310 block->maxy= block->panel->sizey; 00311 block->minx= block->miny= 0.0; 00312 } 00313 00314 /**************************** drawing *******************************/ 00315 00316 /* extern used by previewrender */ 00317 #if 0 /*UNUSED 2.5*/ 00318 static void uiPanelPush(uiBlock *block) 00319 { 00320 glPushMatrix(); 00321 00322 if(block->panel) 00323 glTranslatef((float)block->panel->ofsx, (float)block->panel->ofsy, 0.0); 00324 } 00325 00326 static void uiPanelPop(uiBlock *UNUSED(block)) 00327 { 00328 glPopMatrix(); 00329 } 00330 #endif 00331 00332 /* triangle 'icon' for panel header */ 00333 /* NOTE - this seems to be only used for hiding nodes now */ 00334 void UI_DrawTriIcon(float x, float y, char dir) 00335 { 00336 if(dir=='h') { 00337 ui_draw_anti_tria( x-3, y-5, x-3, y+5, x+7,y ); 00338 } 00339 else if(dir=='t') { 00340 ui_draw_anti_tria( x-5, y-7, x+5, y-7, x, y+3); 00341 } 00342 else { /* 'v' = vertical, down */ 00343 ui_draw_anti_tria( x-5, y+3, x+5, y+3, x, y-7); 00344 } 00345 } 00346 00347 /* triangle 'icon' inside rect */ 00348 static void ui_draw_tria_rect(rctf *rect, char dir) 00349 { 00350 if(dir=='h') { 00351 float half= 0.5f*(rect->ymax - rect->ymin); 00352 ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin+half); 00353 } 00354 else { 00355 float half= 0.5f*(rect->xmax - rect->xmin); 00356 ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin+half, rect->ymin); 00357 } 00358 } 00359 00360 static void ui_draw_anti_x(float x1, float y1, float x2, float y2) 00361 { 00362 00363 /* set antialias line */ 00364 glEnable(GL_LINE_SMOOTH); 00365 glEnable(GL_BLEND); 00366 00367 glLineWidth(2.0); 00368 00369 fdrawline(x1, y1, x2, y2); 00370 fdrawline(x1, y2, x2, y1); 00371 00372 glLineWidth(1.0); 00373 00374 glDisable(GL_LINE_SMOOTH); 00375 glDisable(GL_BLEND); 00376 00377 } 00378 00379 /* x 'icon' for panel header */ 00380 static void ui_draw_x_icon(float x, float y) 00381 { 00382 00383 ui_draw_anti_x(x, y, x+9.375f, y+9.375f); 00384 00385 } 00386 00387 #define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */ 00388 00389 static void ui_draw_panel_scalewidget(rcti *rect) 00390 { 00391 float xmin, xmax, dx; 00392 float ymin, ymax, dy; 00393 00394 xmin= rect->xmax-PNL_HEADER+2; 00395 xmax= rect->xmax-3; 00396 ymin= rect->ymin+3; 00397 ymax= rect->ymin+PNL_HEADER-2; 00398 00399 dx= 0.5f*(xmax-xmin); 00400 dy= 0.5f*(ymax-ymin); 00401 00402 glEnable(GL_BLEND); 00403 glColor4ub(255, 255, 255, 50); 00404 fdrawline(xmin, ymin, xmax, ymax); 00405 fdrawline(xmin+dx, ymin, xmax, ymax-dy); 00406 00407 glColor4ub(0, 0, 0, 50); 00408 fdrawline(xmin, ymin+1, xmax, ymax+1); 00409 fdrawline(xmin+dx, ymin+1, xmax, ymax-dy+1); 00410 glDisable(GL_BLEND); 00411 } 00412 00413 static void ui_draw_panel_dragwidget(rctf *rect) 00414 { 00415 float xmin, xmax, dx; 00416 float ymin, ymax, dy; 00417 00418 xmin= rect->xmin; 00419 xmax= rect->xmax; 00420 ymin= rect->ymin; 00421 ymax= rect->ymax; 00422 00423 dx= 0.333f*(xmax-xmin); 00424 dy= 0.333f*(ymax-ymin); 00425 00426 glEnable(GL_BLEND); 00427 glColor4ub(255, 255, 255, 50); 00428 fdrawline(xmin, ymax, xmax, ymin); 00429 fdrawline(xmin+dx, ymax, xmax, ymin+dy); 00430 fdrawline(xmin+2*dx, ymax, xmax, ymin+2*dy); 00431 00432 glColor4ub(0, 0, 0, 50); 00433 fdrawline(xmin, ymax+1, xmax, ymin+1); 00434 fdrawline(xmin+dx, ymax+1, xmax, ymin+dy+1); 00435 fdrawline(xmin+2*dx, ymax+1, xmax, ymin+2*dy+1); 00436 glDisable(GL_BLEND); 00437 } 00438 00439 00440 static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, rcti *rect, char dir) 00441 { 00442 Panel *panel= block->panel; 00443 rcti hrect; 00444 int pnl_icons; 00445 char *activename= panel->drawname[0]?panel->drawname:panel->panelname; 00446 00447 /* + 0.001f to avoid flirting with float inaccuracy */ 00448 if(panel->control & UI_PNL_CLOSE) pnl_icons=(panel->labelofs+2*PNL_ICON+5)/block->aspect + 0.001f; 00449 else pnl_icons= (panel->labelofs+PNL_ICON+5)/block->aspect + 0.001f; 00450 00451 /* active tab */ 00452 /* draw text label */ 00453 UI_ThemeColor(TH_TITLE); 00454 00455 hrect= *rect; 00456 if(dir == 'h') { 00457 hrect.xmin= rect->xmin+pnl_icons; 00458 uiStyleFontDraw(&style->paneltitle, &hrect, activename); 00459 } 00460 else { 00461 /* ignore 'pnl_icons', otherwise the text gets offset horizontally 00462 * + 0.001f to avoid flirting with float inaccuracy 00463 */ 00464 hrect.xmin= rect->xmin + (PNL_ICON+5)/block->aspect + 0.001f; 00465 uiStyleFontDrawRotated(&style->paneltitle, &hrect, activename); 00466 } 00467 } 00468 00469 static void rectf_scale(rctf *rect, float scale) 00470 { 00471 float centx= 0.5f*(rect->xmin+rect->xmax); 00472 float centy= 0.5f*(rect->ymin+rect->ymax); 00473 float sizex= 0.5f*scale*(rect->xmax - rect->xmin); 00474 float sizey= 0.5f*scale*(rect->ymax - rect->ymin); 00475 00476 rect->xmin= centx - sizex; 00477 rect->xmax= centx + sizex; 00478 rect->ymin= centy - sizey; 00479 rect->ymax= centy + sizey; 00480 } 00481 00482 /* panel integrated in buttonswindow, tool/property lists etc */ 00483 void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect) 00484 { 00485 Panel *panel= block->panel; 00486 rcti headrect; 00487 rctf itemrect; 00488 int ofsx; 00489 00490 if(panel->paneltab) return; 00491 if(panel->type && (panel->type->flag & PNL_NO_HEADER)) return; 00492 00493 /* calculate header rect */ 00494 /* + 0.001f to prevent flicker due to float inaccuracy */ 00495 headrect= *rect; 00496 headrect.ymin= headrect.ymax; 00497 headrect.ymax= headrect.ymin + floor(PNL_HEADER/block->aspect + 0.001f); 00498 00499 if(!(panel->runtime_flag & PNL_FIRST)) { 00500 float minx= rect->xmin+5.0f/block->aspect; 00501 float maxx= rect->xmax-5.0f/block->aspect; 00502 float y= headrect.ymax; 00503 00504 glEnable(GL_BLEND); 00505 glColor4f(0.0f, 0.0f, 0.0f, 0.5f); 00506 fdrawline(minx, y+1, maxx, y+1); 00507 glColor4f(1.0f, 1.0f, 1.0f, 0.25f); 00508 fdrawline(minx, y, maxx, y); 00509 glDisable(GL_BLEND); 00510 } 00511 00512 /* horizontal title */ 00513 if(!(panel->flag & PNL_CLOSEDX)) { 00514 ui_draw_aligned_panel_header(style, block, &headrect, 'h'); 00515 00516 /* itemrect smaller */ 00517 itemrect.xmax= headrect.xmax - 5.0f/block->aspect; 00518 itemrect.xmin= itemrect.xmax - (headrect.ymax-headrect.ymin); 00519 itemrect.ymin= headrect.ymin; 00520 itemrect.ymax= headrect.ymax; 00521 rectf_scale(&itemrect, 0.8f); 00522 ui_draw_panel_dragwidget(&itemrect); 00523 } 00524 00525 /* if the panel is minimized vertically: 00526 * (------) 00527 */ 00528 if(panel->flag & PNL_CLOSEDY) { 00529 00530 } 00531 else if(panel->flag & PNL_CLOSEDX) { 00532 /* draw vertical title */ 00533 ui_draw_aligned_panel_header(style, block, &headrect, 'v'); 00534 } 00535 /* an open panel */ 00536 else { 00537 00538 /* in some occasions, draw a border */ 00539 if(panel->flag & PNL_SELECT) { 00540 if(panel->control & UI_PNL_SOLID) uiSetRoundBox(15); 00541 else uiSetRoundBox(3); 00542 00543 UI_ThemeColorShade(TH_BACK, -120); 00544 uiRoundRect(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax+1, 8); 00545 } 00546 00547 if(panel->control & UI_PNL_SCALE) 00548 ui_draw_panel_scalewidget(rect); 00549 } 00550 00551 /* draw optional close icon */ 00552 00553 ofsx= 6; 00554 if(panel->control & UI_PNL_CLOSE) { 00555 00556 UI_ThemeColor(TH_TEXT); 00557 ui_draw_x_icon(rect->xmin+2+ofsx, rect->ymax+2); 00558 ofsx= 22; 00559 } 00560 00561 /* draw collapse icon */ 00562 UI_ThemeColor(TH_TEXT); 00563 00564 /* itemrect smaller */ 00565 itemrect.xmin= headrect.xmin + 5.0f/block->aspect; 00566 itemrect.xmax= itemrect.xmin + (headrect.ymax-headrect.ymin); 00567 itemrect.ymin= headrect.ymin; 00568 itemrect.ymax= headrect.ymax; 00569 00570 rectf_scale(&itemrect, 0.5f); 00571 00572 if(panel->flag & PNL_CLOSEDY) 00573 ui_draw_tria_rect(&itemrect, 'h'); 00574 else if(panel->flag & PNL_CLOSEDX) 00575 ui_draw_tria_rect(&itemrect, 'h'); 00576 else 00577 ui_draw_tria_rect(&itemrect, 'v'); 00578 00579 (void)ofsx; 00580 } 00581 00582 /************************** panel alignment *************************/ 00583 00584 static int get_panel_header(Panel *pa) 00585 { 00586 if(pa->type && (pa->type->flag & PNL_NO_HEADER)) 00587 return 0; 00588 00589 return PNL_HEADER; 00590 } 00591 00592 static int get_panel_size_y(uiStyle *style, Panel *pa) 00593 { 00594 if(pa->type && (pa->type->flag & PNL_NO_HEADER)) 00595 return pa->sizey; 00596 00597 return PNL_HEADER + pa->sizey + style->panelouter; 00598 } 00599 00600 /* this function is needed because uiBlock and Panel itself dont 00601 change sizey or location when closed */ 00602 static int get_panel_real_ofsy(Panel *pa) 00603 { 00604 if(pa->flag & PNL_CLOSEDY) return pa->ofsy+pa->sizey; 00605 else if(pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDY)) return pa->ofsy+pa->sizey; 00606 else if(pa->paneltab) return pa->paneltab->ofsy; 00607 else return pa->ofsy; 00608 } 00609 00610 static int get_panel_real_ofsx(Panel *pa) 00611 { 00612 if(pa->flag & PNL_CLOSEDX) return pa->ofsx+get_panel_header(pa); 00613 else if(pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDX)) return pa->ofsx+get_panel_header(pa); 00614 else return pa->ofsx+pa->sizex; 00615 } 00616 00617 typedef struct PanelSort { 00618 Panel *pa, *orig; 00619 } PanelSort; 00620 00621 /* note about sorting; 00622 the sortorder has a lower value for new panels being added. 00623 however, that only works to insert a single panel, when more new panels get 00624 added the coordinates of existing panels and the previously stored to-be-insterted 00625 panels do not match for sorting */ 00626 00627 static int find_leftmost_panel(const void *a1, const void *a2) 00628 { 00629 const PanelSort *ps1=a1, *ps2=a2; 00630 00631 if(ps1->pa->ofsx > ps2->pa->ofsx) return 1; 00632 else if(ps1->pa->ofsx < ps2->pa->ofsx) return -1; 00633 else if(ps1->pa->sortorder > ps2->pa->sortorder) return 1; 00634 else if(ps1->pa->sortorder < ps2->pa->sortorder) return -1; 00635 00636 return 0; 00637 } 00638 00639 00640 static int find_highest_panel(const void *a1, const void *a2) 00641 { 00642 const PanelSort *ps1=a1, *ps2=a2; 00643 00644 /* stick uppermost header-less panels to the top of the region - 00645 * prevent them from being sorted */ 00646 if (ps1->pa->sortorder < ps2->pa->sortorder && ps1->pa->type->flag & PNL_NO_HEADER) return -1; 00647 00648 if(ps1->pa->ofsy+ps1->pa->sizey < ps2->pa->ofsy+ps2->pa->sizey) return 1; 00649 else if(ps1->pa->ofsy+ps1->pa->sizey > ps2->pa->ofsy+ps2->pa->sizey) return -1; 00650 else if(ps1->pa->sortorder > ps2->pa->sortorder) return 1; 00651 else if(ps1->pa->sortorder < ps2->pa->sortorder) return -1; 00652 00653 return 0; 00654 } 00655 00656 static int compare_panel(const void *a1, const void *a2) 00657 { 00658 const PanelSort *ps1=a1, *ps2=a2; 00659 00660 if(ps1->pa->sortorder > ps2->pa->sortorder) return 1; 00661 else if(ps1->pa->sortorder < ps2->pa->sortorder) return -1; 00662 00663 return 0; 00664 } 00665 00666 /* this doesnt draw */ 00667 /* returns 1 when it did something */ 00668 static int uiAlignPanelStep(ScrArea *sa, ARegion *ar, float fac, int drag) 00669 { 00670 uiStyle *style= U.uistyles.first; 00671 Panel *pa; 00672 PanelSort *ps, *panelsort, *psnext; 00673 int a, tot=0, done; 00674 int align= panel_aligned(sa, ar); 00675 00676 /* count active, not tabbed panels */ 00677 for(pa= ar->panels.first; pa; pa= pa->next) 00678 if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==NULL) 00679 tot++; 00680 00681 if(tot==0) return 0; 00682 00683 /* extra; change close direction? */ 00684 for(pa= ar->panels.first; pa; pa= pa->next) { 00685 if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==NULL) { 00686 if((pa->flag & PNL_CLOSEDX) && (align==BUT_VERTICAL)) 00687 pa->flag ^= PNL_CLOSED; 00688 else if((pa->flag & PNL_CLOSEDY) && (align==BUT_HORIZONTAL)) 00689 pa->flag ^= PNL_CLOSED; 00690 } 00691 } 00692 00693 /* sort panels */ 00694 panelsort= MEM_callocN(tot*sizeof(PanelSort), "panelsort"); 00695 00696 ps= panelsort; 00697 for(pa= ar->panels.first; pa; pa= pa->next) { 00698 if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==NULL) { 00699 ps->pa= MEM_dupallocN(pa); 00700 ps->orig= pa; 00701 ps++; 00702 } 00703 } 00704 00705 if(drag) { 00706 /* while we are dragging, we sort on location and update sortorder */ 00707 if(align==BUT_VERTICAL) 00708 qsort(panelsort, tot, sizeof(PanelSort), find_highest_panel); 00709 else 00710 qsort(panelsort, tot, sizeof(PanelSort), find_leftmost_panel); 00711 00712 for(ps=panelsort, a=0; a<tot; a++, ps++) 00713 ps->orig->sortorder= a; 00714 } 00715 else 00716 /* otherwise use sortorder */ 00717 qsort(panelsort, tot, sizeof(PanelSort), compare_panel); 00718 00719 /* no smart other default start loc! this keeps switching f5/f6/etc compatible */ 00720 ps= panelsort; 00721 ps->pa->ofsx= 0; 00722 ps->pa->ofsy= -get_panel_size_y(style, ps->pa); 00723 00724 for(a=0; a<tot-1; a++, ps++) { 00725 psnext= ps+1; 00726 00727 if(align==BUT_VERTICAL) { 00728 psnext->pa->ofsx= ps->pa->ofsx; 00729 psnext->pa->ofsy= get_panel_real_ofsy(ps->pa) - get_panel_size_y(style, psnext->pa); 00730 } 00731 else { 00732 psnext->pa->ofsx= get_panel_real_ofsx(ps->pa); 00733 psnext->pa->ofsy= ps->pa->ofsy + get_panel_size_y(style, ps->pa) - get_panel_size_y(style, psnext->pa); 00734 } 00735 } 00736 00737 /* we interpolate */ 00738 done= 0; 00739 ps= panelsort; 00740 for(a=0; a<tot; a++, ps++) { 00741 if((ps->pa->flag & PNL_SELECT)==0) { 00742 if((ps->orig->ofsx != ps->pa->ofsx) || (ps->orig->ofsy != ps->pa->ofsy)) { 00743 ps->orig->ofsx= floorf(0.5f + fac*(float)ps->pa->ofsx + (1.0f-fac)*(float)ps->orig->ofsx); 00744 ps->orig->ofsy= floorf(0.5f + fac*(float)ps->pa->ofsy + (1.0f-fac)*(float)ps->orig->ofsy); 00745 done= 1; 00746 } 00747 } 00748 } 00749 00750 /* copy locations to tabs */ 00751 for(pa= ar->panels.first; pa; pa= pa->next) 00752 if(pa->paneltab && (pa->runtime_flag & PNL_ACTIVE)) 00753 ui_panel_copy_offset(pa, pa->paneltab); 00754 00755 /* free panelsort array */ 00756 for(ps= panelsort, a=0; a<tot; a++, ps++) 00757 MEM_freeN(ps->pa); 00758 MEM_freeN(panelsort); 00759 00760 return done; 00761 } 00762 00763 00764 static void ui_do_animate(const bContext *C, Panel *panel) 00765 { 00766 uiHandlePanelData *data= panel->activedata; 00767 ScrArea *sa= CTX_wm_area(C); 00768 ARegion *ar= CTX_wm_region(C); 00769 float fac; 00770 00771 fac= (PIL_check_seconds_timer()-data->starttime)/ANIMATION_TIME; 00772 fac= sqrt(fac); 00773 fac= MIN2(fac, 1.0f); 00774 00775 /* for max 1 second, interpolate positions */ 00776 if(uiAlignPanelStep(sa, ar, fac, 0)) 00777 ED_region_tag_redraw(ar); 00778 else 00779 fac= 1.0f; 00780 00781 if(fac >= 1.0f) { 00782 panel_activate_state(C, panel, PANEL_STATE_EXIT); 00783 return; 00784 } 00785 } 00786 00787 void uiBeginPanels(const bContext *UNUSED(C), ARegion *ar) 00788 { 00789 Panel *pa; 00790 00791 /* set all panels as inactive, so that at the end we know 00792 * which ones were used */ 00793 for(pa=ar->panels.first; pa; pa=pa->next) { 00794 if(pa->runtime_flag & PNL_ACTIVE) 00795 pa->runtime_flag= PNL_WAS_ACTIVE; 00796 else 00797 pa->runtime_flag= 0; 00798 } 00799 } 00800 00801 /* only draws blocks with panels */ 00802 void uiEndPanels(const bContext *C, ARegion *ar) 00803 { 00804 ScrArea *sa= CTX_wm_area(C); 00805 uiBlock *block; 00806 Panel *panot, *panew, *patest, *pa, *firstpa; 00807 00808 /* offset contents */ 00809 for(block= ar->uiblocks.first; block; block= block->next) 00810 if(block->active && block->panel) 00811 ui_offset_panel_block(block); 00812 00813 /* consistency; are panels not made, whilst they have tabs */ 00814 for(panot= ar->panels.first; panot; panot= panot->next) { 00815 if((panot->runtime_flag & PNL_ACTIVE)==0) { // not made 00816 00817 for(panew= ar->panels.first; panew; panew= panew->next) { 00818 if((panew->runtime_flag & PNL_ACTIVE)) { 00819 if(panew->paneltab==panot) { // panew is tab in notmade pa 00820 break; 00821 } 00822 } 00823 } 00824 /* now panew can become the new parent, check all other tabs */ 00825 if(panew) { 00826 for(patest= ar->panels.first; patest; patest= patest->next) { 00827 if(patest->paneltab == panot) { 00828 patest->paneltab= panew; 00829 } 00830 } 00831 panot->paneltab= panew; 00832 panew->paneltab= NULL; 00833 ED_region_tag_redraw(ar); // the buttons panew were not made 00834 } 00835 } 00836 } 00837 00838 /* re-align, possibly with animation */ 00839 if(panels_re_align(sa, ar, &pa)) { 00840 if(pa) 00841 panel_activate_state(C, pa, PANEL_STATE_ANIMATION); 00842 else 00843 uiAlignPanelStep(sa, ar, 1.0, 0); 00844 } 00845 00846 /* tag first panel */ 00847 firstpa= NULL; 00848 for(block= ar->uiblocks.first; block; block=block->next) 00849 if(block->active && block->panel) 00850 if(!firstpa || block->panel->sortorder < firstpa->sortorder) 00851 firstpa= block->panel; 00852 00853 if(firstpa) 00854 firstpa->runtime_flag |= PNL_FIRST; 00855 00856 UI_ThemeClearColor(TH_BACK); 00857 00858 /* draw panels, selected on top */ 00859 for(block= ar->uiblocks.first; block; block=block->next) { 00860 if(block->active && block->panel && !(block->panel->flag & PNL_SELECT)) { 00861 uiDrawBlock(C, block); 00862 } 00863 } 00864 00865 for(block= ar->uiblocks.first; block; block=block->next) { 00866 if(block->active && block->panel && (block->panel->flag & PNL_SELECT)) { 00867 uiDrawBlock(C, block); 00868 } 00869 } 00870 } 00871 00872 /* ------------ panel merging ---------------- */ 00873 00874 static void check_panel_overlap(ARegion *ar, Panel *panel) 00875 { 00876 Panel *pa; 00877 00878 /* also called with panel==NULL for clear */ 00879 00880 for(pa=ar->panels.first; pa; pa=pa->next) { 00881 pa->flag &= ~PNL_OVERLAP; 00882 if(panel && (pa != panel)) { 00883 if(pa->paneltab==NULL && (pa->runtime_flag & PNL_ACTIVE)) { 00884 float safex= 0.2, safey= 0.2; 00885 00886 if(pa->flag & PNL_CLOSEDX) safex= 0.05; 00887 else if(pa->flag & PNL_CLOSEDY) safey= 0.05; 00888 else if(panel->flag & PNL_CLOSEDX) safex= 0.05; 00889 else if(panel->flag & PNL_CLOSEDY) safey= 0.05; 00890 00891 if(pa->ofsx > panel->ofsx- safex*panel->sizex) 00892 if(pa->ofsx+pa->sizex < panel->ofsx+ (1.0f+safex)*panel->sizex) 00893 if(pa->ofsy > panel->ofsy- safey*panel->sizey) 00894 if(pa->ofsy+pa->sizey < panel->ofsy+ (1.0f+safey)*panel->sizey) 00895 pa->flag |= PNL_OVERLAP; 00896 } 00897 } 00898 } 00899 } 00900 00901 /************************ panel dragging ****************************/ 00902 00903 static void ui_do_drag(const bContext *C, wmEvent *event, Panel *panel) 00904 { 00905 uiHandlePanelData *data= panel->activedata; 00906 ScrArea *sa= CTX_wm_area(C); 00907 ARegion *ar= CTX_wm_region(C); 00908 short align= panel_aligned(sa, ar), dx=0, dy=0; 00909 00910 /* first clip for window, no dragging outside */ 00911 if(!BLI_in_rcti(&ar->winrct, event->x, event->y)) 00912 return; 00913 00914 dx= (event->x-data->startx) & ~(PNL_GRID-1); 00915 dy= (event->y-data->starty) & ~(PNL_GRID-1); 00916 00917 dx *= (float)(ar->v2d.cur.xmax - ar->v2d.cur.xmin)/(float)(ar->winrct.xmax - ar->winrct.xmin); 00918 dy *= (float)(ar->v2d.cur.ymax - ar->v2d.cur.ymin)/(float)(ar->winrct.ymax - ar->winrct.ymin); 00919 00920 if(data->state == PANEL_STATE_DRAG_SCALE) { 00921 panel->sizex = MAX2(data->startsizex+dx, UI_PANEL_MINX); 00922 00923 if(data->startsizey-dy < UI_PANEL_MINY) 00924 dy= -UI_PANEL_MINY+data->startsizey; 00925 00926 panel->sizey= data->startsizey-dy; 00927 panel->ofsy= data->startofsy+dy; 00928 } 00929 else { 00930 /* reset the panel snapping, to allow dragging away from snapped edges */ 00931 panel->snap = PNL_SNAP_NONE; 00932 00933 panel->ofsx = data->startofsx+dx; 00934 panel->ofsy = data->startofsy+dy; 00935 check_panel_overlap(ar, panel); 00936 00937 if(align) uiAlignPanelStep(sa, ar, 0.2, 1); 00938 } 00939 00940 ED_region_tag_redraw(ar); 00941 } 00942 00943 /******************* region level panel interaction *****************/ 00944 00945 00946 /* this function is supposed to call general window drawing too */ 00947 /* also it supposes a block has panel, and isnt a menu */ 00948 static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, int my, int event) 00949 { 00950 ScrArea *sa= CTX_wm_area(C); 00951 ARegion *ar= CTX_wm_region(C); 00952 Panel *pa; 00953 int align= panel_aligned(sa, ar), button= 0; 00954 00955 /* mouse coordinates in panel space! */ 00956 00957 /* XXX weak code, currently it assumes layout style for location of widgets */ 00958 00959 /* check open/collapsed button */ 00960 if(event==RETKEY) 00961 button= 1; 00962 else if(event==AKEY) 00963 button= 1; 00964 else if(block->panel->flag & PNL_CLOSEDX) { 00965 if(my >= block->maxy) button= 1; 00966 } 00967 else if(block->panel->control & UI_PNL_CLOSE) { 00968 /* whole of header can be used to collapse panel (except top-right corner) */ 00969 if(mx <= block->maxx-8-PNL_ICON) button= 2; 00970 //else if(mx <= block->minx+10+2*PNL_ICON+2) button= 1; 00971 } 00972 else if(mx <= block->maxx-PNL_ICON-12) { 00973 button= 1; 00974 } 00975 00976 if(button) { 00977 if(button==2) { // close 00978 ED_region_tag_redraw(ar); 00979 } 00980 else { // collapse 00981 if(block->panel->flag & PNL_CLOSED) { 00982 block->panel->flag &= ~PNL_CLOSED; 00983 /* snap back up so full panel aligns with screen edge */ 00984 if (block->panel->snap & PNL_SNAP_BOTTOM) 00985 block->panel->ofsy= 0; 00986 } 00987 else if(align==BUT_HORIZONTAL) { 00988 block->panel->flag |= PNL_CLOSEDX; 00989 } 00990 else { 00991 /* snap down to bottom screen edge*/ 00992 block->panel->flag |= PNL_CLOSEDY; 00993 if (block->panel->snap & PNL_SNAP_BOTTOM) 00994 block->panel->ofsy= -block->panel->sizey; 00995 } 00996 00997 for(pa= ar->panels.first; pa; pa= pa->next) { 00998 if(pa->paneltab==block->panel) { 00999 if(block->panel->flag & PNL_CLOSED) pa->flag |= PNL_CLOSED; 01000 else pa->flag &= ~PNL_CLOSED; 01001 } 01002 } 01003 } 01004 01005 if(align) 01006 panel_activate_state(C, block->panel, PANEL_STATE_ANIMATION); 01007 else 01008 ED_region_tag_redraw(ar); 01009 } 01010 else if(mx <= (block->maxx-PNL_ICON-12)+PNL_ICON+2) { 01011 panel_activate_state(C, block->panel, PANEL_STATE_DRAG); 01012 } 01013 } 01014 01015 /* XXX should become modal keymap */ 01016 /* AKey is opening/closing panels, independent of button state now */ 01017 01018 int ui_handler_panel_region(bContext *C, wmEvent *event) 01019 { 01020 ARegion *ar= CTX_wm_region(C); 01021 uiBlock *block; 01022 Panel *pa; 01023 int retval, mx, my, inside_header= 0, inside_scale= 0, inside; 01024 01025 retval= WM_UI_HANDLER_CONTINUE; 01026 for(block=ar->uiblocks.last; block; block=block->prev) { 01027 mx= event->x; 01028 my= event->y; 01029 ui_window_to_block(ar, block, &mx, &my); 01030 01031 /* check if inside boundbox */ 01032 inside= 0; 01033 pa= block->panel; 01034 01035 if(!pa || pa->paneltab!=NULL) 01036 continue; 01037 if(pa->type && pa->type->flag & PNL_NO_HEADER) // XXX - accessed freed panels when scripts reload, need to fix. 01038 continue; 01039 01040 if(block->minx <= mx && block->maxx >= mx) 01041 if(block->miny <= my && block->maxy+PNL_HEADER >= my) 01042 inside= 1; 01043 01044 if(inside && event->val==KM_PRESS) { 01045 if(event->type == AKEY && !ELEM4(1, event->ctrl, event->oskey, event->shift, event->alt)) { 01046 01047 if(pa->flag & PNL_CLOSEDY) { 01048 if((block->maxy <= my) && (block->maxy+PNL_HEADER >= my)) 01049 ui_handle_panel_header(C, block, mx, my, event->type); 01050 } 01051 else 01052 ui_handle_panel_header(C, block, mx, my, event->type); 01053 01054 continue; 01055 } 01056 } 01057 01058 /* on active button, do not handle panels */ 01059 if(ui_button_is_active(ar)) 01060 continue; 01061 01062 if(inside) { 01063 /* clicked at panel header? */ 01064 if(pa->flag & PNL_CLOSEDX) { 01065 if(block->minx <= mx && block->minx+PNL_HEADER >= mx) 01066 inside_header= 1; 01067 } 01068 else if((block->maxy <= my) && (block->maxy+PNL_HEADER >= my)) { 01069 inside_header= 1; 01070 } 01071 else if(pa->control & UI_PNL_SCALE) { 01072 if(block->maxx-PNL_HEADER <= mx) 01073 if(block->miny+PNL_HEADER >= my) 01074 inside_scale= 1; 01075 } 01076 01077 if(event->val==KM_PRESS) { 01078 /* open close on header */ 01079 if(ELEM(event->type, RETKEY, PADENTER)) { 01080 if(inside_header) { 01081 ui_handle_panel_header(C, block, mx, my, RETKEY); 01082 break; 01083 } 01084 } 01085 else if(event->type == LEFTMOUSE) { 01086 if(inside_header) { 01087 ui_handle_panel_header(C, block, mx, my, 0); 01088 break; 01089 } 01090 else if(inside_scale && !(pa->flag & PNL_CLOSED)) { 01091 panel_activate_state(C, pa, PANEL_STATE_DRAG_SCALE); 01092 break; 01093 } 01094 } 01095 else if(event->type == ESCKEY) { 01096 /*XXX 2.50 if(block->handler) { 01097 rem_blockhandler(sa, block->handler); 01098 ED_region_tag_redraw(ar); 01099 retval= WM_UI_HANDLER_BREAK; 01100 }*/ 01101 } 01102 else if(event->type==PADPLUSKEY || event->type==PADMINUS) { 01103 #if 0 // XXX make float panel exception? 01104 int zoom=0; 01105 01106 /* if panel is closed, only zoom if mouse is over the header */ 01107 if (pa->flag & (PNL_CLOSEDX|PNL_CLOSEDY)) { 01108 if (inside_header) 01109 zoom=1; 01110 } 01111 else 01112 zoom=1; 01113 01114 if(zoom) { 01115 ScrArea *sa= CTX_wm_area(C); 01116 SpaceLink *sl= sa->spacedata.first; 01117 01118 if(sa->spacetype!=SPACE_BUTS) { 01119 if(!(pa->control & UI_PNL_SCALE)) { 01120 if(event->type==PADPLUSKEY) sl->blockscale+= 0.1; 01121 else sl->blockscale-= 0.1; 01122 CLAMP(sl->blockscale, 0.6, 1.0); 01123 01124 ED_region_tag_redraw(ar); 01125 retval= WM_UI_HANDLER_BREAK; 01126 } 01127 } 01128 } 01129 #endif 01130 } 01131 } 01132 } 01133 } 01134 01135 return retval; 01136 } 01137 01138 /**************** window level modal panel interaction **************/ 01139 01140 /* note, this is modal handler and should not swallow events for animation */ 01141 static int ui_handler_panel(bContext *C, wmEvent *event, void *userdata) 01142 { 01143 Panel *panel= userdata; 01144 uiHandlePanelData *data= panel->activedata; 01145 01146 /* verify if we can stop */ 01147 if(event->type == LEFTMOUSE && event->val!=KM_PRESS) { 01148 ScrArea *sa= CTX_wm_area(C); 01149 ARegion *ar= CTX_wm_region(C); 01150 int align= panel_aligned(sa, ar); 01151 01152 if(align) 01153 panel_activate_state(C, panel, PANEL_STATE_ANIMATION); 01154 else 01155 panel_activate_state(C, panel, PANEL_STATE_EXIT); 01156 } 01157 else if(event->type == MOUSEMOVE) { 01158 if(data->state == PANEL_STATE_DRAG) 01159 ui_do_drag(C, event, panel); 01160 } 01161 else if(event->type == TIMER && event->customdata == data->animtimer) { 01162 if(data->state == PANEL_STATE_ANIMATION) 01163 ui_do_animate(C, panel); 01164 else if(data->state == PANEL_STATE_DRAG) 01165 ui_do_drag(C, event, panel); 01166 } 01167 01168 data= panel->activedata; 01169 01170 if(data && data->state == PANEL_STATE_ANIMATION) 01171 return WM_UI_HANDLER_CONTINUE; 01172 else 01173 return WM_UI_HANDLER_BREAK; 01174 } 01175 01176 static void ui_handler_remove_panel(bContext *C, void *userdata) 01177 { 01178 Panel *pa= userdata; 01179 01180 panel_activate_state(C, pa, PANEL_STATE_EXIT); 01181 } 01182 01183 static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state) 01184 { 01185 uiHandlePanelData *data= pa->activedata; 01186 wmWindow *win= CTX_wm_window(C); 01187 ARegion *ar= CTX_wm_region(C); 01188 01189 if(data && data->state == state) 01190 return; 01191 01192 if(state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) { 01193 if(data && data->state != PANEL_STATE_ANIMATION) { 01194 /* XXX: 01195 * - the panel tabbing function call below (test_add_new_tabs()) has been commented out 01196 * "It is too easy to do by accident when reordering panels, is very hard to control and use, and has no real benefit." - BillRey 01197 * Aligorith, 2009Sep 01198 */ 01199 //test_add_new_tabs(ar); // also copies locations of tabs in dragged panel 01200 check_panel_overlap(ar, NULL); // clears 01201 } 01202 01203 pa->flag &= ~PNL_SELECT; 01204 } 01205 else 01206 pa->flag |= PNL_SELECT; 01207 01208 if(data && data->animtimer) { 01209 WM_event_remove_timer(CTX_wm_manager(C), win, data->animtimer); 01210 data->animtimer= NULL; 01211 } 01212 01213 if(state == PANEL_STATE_EXIT) { 01214 MEM_freeN(data); 01215 pa->activedata= NULL; 01216 01217 WM_event_remove_ui_handler(&win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, 0); 01218 } 01219 else { 01220 if(!data) { 01221 data= MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData"); 01222 pa->activedata= data; 01223 01224 WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa); 01225 } 01226 01227 if(ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG)) 01228 data->animtimer= WM_event_add_timer(CTX_wm_manager(C), win, TIMER, ANIMATION_INTERVAL); 01229 01230 data->state= state; 01231 data->startx= win->eventstate->x; 01232 data->starty= win->eventstate->y; 01233 data->startofsx= pa->ofsx; 01234 data->startofsy= pa->ofsy; 01235 data->startsizex= pa->sizex; 01236 data->startsizey= pa->sizey; 01237 data->starttime= PIL_check_seconds_timer(); 01238 } 01239 01240 ED_region_tag_redraw(ar); 01241 01242 /* XXX exception handling, 3d window preview panel */ 01243 /* if(block->drawextra==BIF_view3d_previewdraw) 01244 BIF_view3d_previewrender_clear(curarea);*/ 01245 01246 /* XXX exception handling, 3d window preview panel */ 01247 /* if(block->drawextra==BIF_view3d_previewdraw) 01248 BIF_view3d_previewrender_signal(curarea, PR_DISPRECT); 01249 else if(strcmp(block->name, "image_panel_preview")==0) 01250 image_preview_event(2); */ 01251 } 01252