This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/editors/screen/area.c

1892 lines
50 KiB
C
Raw Normal View History

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
2010-02-12 13:34:04 +00:00
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
*
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
2011-02-27 20:29:51 +00:00
/** \file blender/editors/screen/area.c
* \ingroup edscr
*/
#include <string.h>
#include <stdio.h>
#include "MEM_guardedalloc.h"
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
#include "DNA_userdef_types.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
#include "BLF_translation.h"
2011-06-15 08:28:56 +00:00
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_screen.h"
#include "WM_api.h"
#include "WM_types.h"
#include "wm_subwindow.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "ED_space_api.h"
#include "ED_types.h"
#include "ED_fileselect.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BLF_api.h"
#include "UI_interface.h"
Port of part of the Interface code to 2.50. This is based on the current trunk version, so these files should not need merges. There's two things (clipboard and intptr_t) that are missing in 2.50 and commented out with XXX 2.48, these can be enabled again once trunk is merged into this branch. Further this is not all interface code, there are many parts commented out: * interface.c: nearly all button types, missing: links, chartab, keyevent. * interface_draw.c: almost all code, with some small exceptions. * interface_ops.c: this replaces ui_do_but and uiDoBlocks with two operators, making it non-blocking. * interface_regions: this is a part of interface.c, split off, contains code to create regions for tooltips, menus, pupmenu (that one is crashing currently), color chooser, basically regions with buttons which is fairly independent of core interface code. * interface_panel.c and interface_icons.c: not ported over, so no panels and icons yet. Panels should probably become (free floating) regions? * text.c: (formerly language.c) for drawing text and translation. this works but is using bad globals still and could be cleaned up. Header Files: * ED_datafiles.h now has declarations for datatoc_ files, so those extern declarations can be #included instead of repeated. * The user interface code is in UI_interface.h and other UI_* files. Core: * The API for creating blocks, buttons, etc is nearly the same still. Blocks are now created per region instead of per area. * The code was made non-blocking, which means that any changes and redraws should be possible while editing a button. That means though that we need some sort of persistence even though the blender model is to recreate buttons for each redraw. So when a new block is created, some matching happens to find out which buttons correspond to buttons in the previously created block, and for activated buttons some data is then copied over to the new button. * Added UI_init/UI_init_userdef/UI_exit functions that should initialize code in this module, instead of multiple function calls in the windowmanager. * Removed most static/globals from interface.c. * Removed UIafterfunc_ I don't think it's needed anymore, and not sure how it would integrate here? * Currently only full window redraws are used, this should become per region and maybe per button later. Operators: * Events are currently handled through two operators: button activate and menu handle. Operators may not be the best way to implement this, since there are currently some issues with events being missed, but they can become a special handler type instead, this should not be a big change. * The button activate operator runs as long as a button is active, and will handle all interaction with that button until the button is not activated anymore. This means clicking, text editing, number dragging, opening menu blocks, etc. * Since this operator has to be non-blocking, the ui_do_but code needed to made non-blocking. That means variables that were previously on the stack, now need to be stored away in a struct such that they can be accessed again when the operator receives more events. * Additionally the place in the ui_do_but code indicated the state, now that needs to be set explicit in order to handle the right events in the right state. So an activated button can be in one of these states: init, highlight, wait_flash, wait_release, wait_key_event, num_editing, text_editing, text_selecting, block_open, exit. * For each button type an ui_apply_but_* function has also been separated out from ui_do_but. This makes it possible to continuously apply the button as text is being typed for example, and there is an option in the code to enable this. Since the code non-blocking and can deal with the button being deleted even, it should be safe to do this. * When editing text, dragging numbers, etc, the actual data (but->poin) is not being edited, since that would mean data is being edited without correct updates happening, while some other part of blender may be accessing that data in the meantime. So data values, strings, vectors are written to a temporary location and only flush in the apply function. Regions: * Menus, color chooser, tooltips etc all create screen level regions. Such menu blocks give a handle to the button that creates it, which will contain the results of the menu block once a MESSAGE event is received from that menu block. * For this type of menu block the coordinates used to be in window space. They are still created that way and ui_positionblock still works with window coordinates, but after that the block and buttons are brought back to region coordinates since these are now contained in a region. * The flush/overdraw frontbuffer drawing code was removed, the windowmanager should have enough information with these screen level regions to have full control over what gets drawn when and to then do correct compositing. Testing: * The header in the time space currently has some buttons to test the UI code.
2008-11-11 18:31:32 +00:00
#include "UI_resources.h"
#include "UI_view2d.h"
Port of part of the Interface code to 2.50. This is based on the current trunk version, so these files should not need merges. There's two things (clipboard and intptr_t) that are missing in 2.50 and commented out with XXX 2.48, these can be enabled again once trunk is merged into this branch. Further this is not all interface code, there are many parts commented out: * interface.c: nearly all button types, missing: links, chartab, keyevent. * interface_draw.c: almost all code, with some small exceptions. * interface_ops.c: this replaces ui_do_but and uiDoBlocks with two operators, making it non-blocking. * interface_regions: this is a part of interface.c, split off, contains code to create regions for tooltips, menus, pupmenu (that one is crashing currently), color chooser, basically regions with buttons which is fairly independent of core interface code. * interface_panel.c and interface_icons.c: not ported over, so no panels and icons yet. Panels should probably become (free floating) regions? * text.c: (formerly language.c) for drawing text and translation. this works but is using bad globals still and could be cleaned up. Header Files: * ED_datafiles.h now has declarations for datatoc_ files, so those extern declarations can be #included instead of repeated. * The user interface code is in UI_interface.h and other UI_* files. Core: * The API for creating blocks, buttons, etc is nearly the same still. Blocks are now created per region instead of per area. * The code was made non-blocking, which means that any changes and redraws should be possible while editing a button. That means though that we need some sort of persistence even though the blender model is to recreate buttons for each redraw. So when a new block is created, some matching happens to find out which buttons correspond to buttons in the previously created block, and for activated buttons some data is then copied over to the new button. * Added UI_init/UI_init_userdef/UI_exit functions that should initialize code in this module, instead of multiple function calls in the windowmanager. * Removed most static/globals from interface.c. * Removed UIafterfunc_ I don't think it's needed anymore, and not sure how it would integrate here? * Currently only full window redraws are used, this should become per region and maybe per button later. Operators: * Events are currently handled through two operators: button activate and menu handle. Operators may not be the best way to implement this, since there are currently some issues with events being missed, but they can become a special handler type instead, this should not be a big change. * The button activate operator runs as long as a button is active, and will handle all interaction with that button until the button is not activated anymore. This means clicking, text editing, number dragging, opening menu blocks, etc. * Since this operator has to be non-blocking, the ui_do_but code needed to made non-blocking. That means variables that were previously on the stack, now need to be stored away in a struct such that they can be accessed again when the operator receives more events. * Additionally the place in the ui_do_but code indicated the state, now that needs to be set explicit in order to handle the right events in the right state. So an activated button can be in one of these states: init, highlight, wait_flash, wait_release, wait_key_event, num_editing, text_editing, text_selecting, block_open, exit. * For each button type an ui_apply_but_* function has also been separated out from ui_do_but. This makes it possible to continuously apply the button as text is being typed for example, and there is an option in the code to enable this. Since the code non-blocking and can deal with the button being deleted even, it should be safe to do this. * When editing text, dragging numbers, etc, the actual data (but->poin) is not being edited, since that would mean data is being edited without correct updates happening, while some other part of blender may be accessing that data in the meantime. So data values, strings, vectors are written to a temporary location and only flush in the apply function. Regions: * Menus, color chooser, tooltips etc all create screen level regions. Such menu blocks give a handle to the button that creates it, which will contain the results of the menu block once a MESSAGE event is received from that menu block. * For this type of menu block the coordinates used to be in window space. They are still created that way and ui_positionblock still works with window coordinates, but after that the block and buttons are brought back to region coordinates since these are now contained in a region. * The flush/overdraw frontbuffer drawing code was removed, the windowmanager should have enough information with these screen level regions to have full control over what gets drawn when and to then do correct compositing. Testing: * The header in the time space currently has some buttons to test the UI code.
2008-11-11 18:31:32 +00:00
#include "screen_intern.h"
/* general area and region code */
2009-04-27 13:44:11 +00:00
static void region_draw_emboss(ARegion *ar, rcti *scirct)
{
2009-04-27 13:44:11 +00:00
rcti rect;
2009-04-27 13:44:11 +00:00
/* translate scissor rect to region space */
rect.xmin = scirct->xmin - ar->winrct.xmin;
rect.ymin = scirct->ymin - ar->winrct.ymin;
rect.xmax = scirct->xmax - ar->winrct.xmin;
rect.ymax = scirct->ymax - ar->winrct.ymin;
/* set transp line */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* right */
2012-04-29 15:47:02 +00:00
glColor4ub(0, 0, 0, 30);
2009-04-27 13:44:11 +00:00
sdrawline(rect.xmax, rect.ymin, rect.xmax, rect.ymax);
/* bottom */
2012-04-29 15:47:02 +00:00
glColor4ub(0, 0, 0, 30);
2009-04-27 13:44:11 +00:00
sdrawline(rect.xmin, rect.ymin, rect.xmax, rect.ymin);
/* top */
2012-04-29 15:47:02 +00:00
glColor4ub(255, 255, 255, 30);
2009-04-27 13:44:11 +00:00
sdrawline(rect.xmin, rect.ymax, rect.xmax, rect.ymax);
/* left */
2012-04-29 15:47:02 +00:00
glColor4ub(255, 255, 255, 30);
2009-04-27 13:44:11 +00:00
sdrawline(rect.xmin, rect.ymin, rect.xmin, rect.ymax);
glDisable(GL_BLEND);
}
void ED_region_pixelspace(ARegion *ar)
{
int width = BLI_rcti_size_x(&ar->winrct) + 1;
int height = BLI_rcti_size_y(&ar->winrct) + 1;
wmOrtho2(-GLA_PIXEL_OFS, (float)width - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, (float)height - GLA_PIXEL_OFS);
glLoadIdentity();
}
/* only exported for WM */
void ED_region_do_listen(ARegion *ar, wmNotifier *note)
{
/* generic notes first */
switch (note->category) {
case NC_WM:
2012-05-08 15:43:59 +00:00
if (note->data == ND_FILEREAD)
ED_region_tag_redraw(ar);
break;
case NC_WINDOW:
ED_region_tag_redraw(ar);
break;
}
if (ar->type && ar->type->listener)
ar->type->listener(ar, note);
}
/* only exported for WM */
void ED_area_do_listen(ScrArea *sa, wmNotifier *note)
{
/* no generic notes? */
if (sa->type && sa->type->listener) {
sa->type->listener(sa, note);
}
}
/* only exported for WM */
void ED_area_do_refresh(bContext *C, ScrArea *sa)
{
/* no generic notes? */
if (sa->type && sa->type->refresh) {
sa->type->refresh(C, sa);
}
sa->do_refresh = FALSE;
}
/* based on screen region draw tags, set draw tags in azones, and future region tabs etc */
/* only exported for WM */
void ED_area_overdraw_flush(ScrArea *sa, ARegion *ar)
{
AZone *az;
2012-05-08 15:43:59 +00:00
for (az = sa->actionzones.first; az; az = az->next) {
int xs, ys;
2012-05-08 15:43:59 +00:00
xs = (az->x1 + az->x2) / 2;
ys = (az->y1 + az->y2) / 2;
/* test if inside */
if (BLI_rcti_isect_pt(&ar->winrct, xs, ys)) {
az->do_draw = TRUE;
}
}
}
/**
* \brief Corner widgets use for dragging and splitting the view.
*/
static void area_draw_azone(short x1, short y1, short x2, short y2)
{
int dx = x2 - x1;
int dy = y2 - y1;
dx = copysign(ceilf(0.3f * fabsf(dx)), dx);
dy = copysign(ceilf(0.3f * fabsf(dy)), dy);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glColor4ub(255, 255, 255, 180);
fdrawline(x1, y2, x2, y1);
glColor4ub(255, 255, 255, 130);
2012-05-08 15:43:59 +00:00
fdrawline(x1, y2 - dy, x2 - dx, y1);
glColor4ub(255, 255, 255, 80);
2012-05-08 15:43:59 +00:00
fdrawline(x1, y2 - 2 * dy, x2 - 2 * dx, y1);
glColor4ub(0, 0, 0, 210);
2012-05-08 15:43:59 +00:00
fdrawline(x1, y2 + 1, x2 + 1, y1);
glColor4ub(0, 0, 0, 180);
2012-05-08 15:43:59 +00:00
fdrawline(x1, y2 - dy + 1, x2 - dx + 1, y1);
glColor4ub(0, 0, 0, 150);
2012-05-08 15:43:59 +00:00
fdrawline(x1, y2 - 2 * dy + 1, x2 - 2 * dx + 1, y1);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
static void region_draw_azone_icon(AZone *az)
{
2009-10-12 11:41:20 +00:00
GLUquadricObj *qobj = NULL;
2012-05-08 15:43:59 +00:00
short midx = az->x1 + (az->x2 - az->x1) / 2;
short midy = az->y1 + (az->y2 - az->y1) / 2;
2009-10-12 11:41:20 +00:00
qobj = gluNewQuadric();
glPushMatrix();
glTranslatef(midx, midy, 0.0);
/* outlined circle */
glEnable(GL_LINE_SMOOTH);
glColor4f(1.f, 1.f, 1.f, 0.8f);
gluQuadricDrawStyle(qobj, GLU_FILL);
gluDisk(qobj, 0.0, 4.25f, 16, 1);
glColor4f(0.2f, 0.2f, 0.2f, 0.9f);
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
gluDisk(qobj, 0.0, 4.25f, 16, 1);
glDisable(GL_LINE_SMOOTH);
glPopMatrix();
gluDeleteQuadric(qobj);
/* + */
2012-05-08 15:43:59 +00:00
sdrawline(midx, midy - 2, midx, midy + 3);
sdrawline(midx - 2, midy, midx + 3, midy);
}
static void draw_azone_plus(float x1, float y1, float x2, float y2)
{
float width = 2.0f;
float pad = 4.0f;
2012-05-08 15:43:59 +00:00
glRectf((x1 + x2 - width) * 0.5f, y1 + pad, (x1 + x2 + width) * 0.5f, y2 - pad);
glRectf(x1 + pad, (y1 + y2 - width) * 0.5f, (x1 + x2 - width) * 0.5f, (y1 + y2 + width) * 0.5f);
glRectf((x1 + x2 + width) * 0.5f, (y1 + y2 - width) * 0.5f, x2 - pad, (y1 + y2 + width) * 0.5f);
}
static void region_draw_azone_tab_plus(AZone *az)
{
extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */
glEnable(GL_BLEND);
/* add code to draw region hidden as 'too small' */
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
break;
case AE_BOTTOM_TO_TOPLEFT:
uiSetRoundBox(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
break;
case AE_LEFT_TO_TOPRIGHT:
uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
break;
case AE_RIGHT_TO_TOPLEFT:
uiSetRoundBox(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
break;
}
glColor4f(0.05f, 0.05f, 0.05f, 0.4f);
uiRoundBox((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
glEnable(GL_BLEND);
glColor4f(0.8f, 0.8f, 0.8f, 0.4f);
draw_azone_plus((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2);
glDisable(GL_BLEND);
}
static void region_draw_azone_tab(AZone *az)
{
float col[3];
glEnable(GL_BLEND);
UI_GetThemeColor3fv(TH_HEADER, col);
glColor4f(col[0], col[1], col[2], 0.5f);
/* add code to draw region hidden as 'too small' */
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_RB_ALPHA);
uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
glColor4ub(0, 0, 0, 255);
2012-05-08 15:43:59 +00:00
uiRoundRect((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f);
break;
case AE_BOTTOM_TO_TOPLEFT:
uiSetRoundBox(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA);
uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
glColor4ub(0, 0, 0, 255);
2012-05-08 15:43:59 +00:00
uiRoundRect((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f);
break;
case AE_LEFT_TO_TOPRIGHT:
uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA);
uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
glColor4ub(0, 0, 0, 255);
uiRoundRect((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
break;
case AE_RIGHT_TO_TOPLEFT:
uiSetRoundBox(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_RB_ALPHA);
uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
glColor4ub(0, 0, 0, 255);
uiRoundRect((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
break;
}
glDisable(GL_BLEND);
}
static void region_draw_azone_tria(AZone *az)
{
extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */
glEnable(GL_BLEND);
//UI_GetThemeColor3fv(TH_HEADER, col);
glColor4f(0.0f, 0.0f, 0.0f, 0.35f);
/* add code to draw region hidden as 'too small' */
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
2012-05-08 15:43:59 +00:00
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);
break;
case AE_BOTTOM_TO_TOPLEFT:
2012-05-08 15:43:59 +00:00
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);
break;
case AE_LEFT_TO_TOPRIGHT:
2012-05-08 15:43:59 +00:00
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);
break;
case AE_RIGHT_TO_TOPLEFT:
2012-05-08 15:43:59 +00:00
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);
break;
}
glDisable(GL_BLEND);
}
/* only exported for WM */
void ED_area_overdraw(bContext *C)
{
2012-05-08 15:43:59 +00:00
wmWindow *win = CTX_wm_window(C);
bScreen *screen = CTX_wm_screen(C);
ScrArea *sa;
/* Draw AZones, in screenspace */
wmSubWindowSet(win, screen->mainwin);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2012-05-08 15:43:59 +00:00
for (sa = screen->areabase.first; sa; sa = sa->next) {
AZone *az;
2012-05-08 15:43:59 +00:00
for (az = sa->actionzones.first; az; az = az->next) {
if (az->do_draw) {
2012-05-08 15:43:59 +00:00
if (az->type == AZONE_AREA) {
area_draw_azone(az->x1, az->y1, az->x2, az->y2);
}
2012-05-08 15:43:59 +00:00
else if (az->type == AZONE_REGION) {
if (az->ar) {
/* only display tab or icons when the region is hidden */
2012-05-08 15:43:59 +00:00
if (az->ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
if (G.debug_value == 3)
region_draw_azone_icon(az);
else if (G.debug_value == 2)
region_draw_azone_tria(az);
else if (G.debug_value == 1)
region_draw_azone_tab(az);
else
region_draw_azone_tab_plus(az);
}
}
}
az->do_draw = FALSE;
}
}
}
glDisable(GL_BLEND);
}
2009-04-27 13:44:11 +00:00
/* get scissor rect, checking overlapping regions */
void region_scissor_winrct(ARegion *ar, rcti *winrct)
2009-04-27 13:44:11 +00:00
{
2012-05-08 15:43:59 +00:00
*winrct = ar->winrct;
2009-04-27 13:44:11 +00:00
if (ELEM(ar->alignment, RGN_OVERLAP_LEFT, RGN_OVERLAP_RIGHT))
2009-04-27 13:44:11 +00:00
return;
while (ar->prev) {
2012-05-08 15:43:59 +00:00
ar = ar->prev;
2009-04-27 13:44:11 +00:00
if (BLI_rcti_isect(winrct, &ar->winrct, NULL)) {
2012-10-07 09:48:59 +00:00
if (ar->flag & RGN_FLAG_HIDDEN) {
/* pass */
}
else if (ar->alignment & RGN_SPLIT_PREV) {
/* pass */
}
2012-05-08 15:43:59 +00:00
else if (ar->alignment == RGN_OVERLAP_LEFT) {
winrct->xmin = ar->winrct.xmax + 1;
}
2012-05-08 15:43:59 +00:00
else if (ar->alignment == RGN_OVERLAP_RIGHT) {
winrct->xmax = ar->winrct.xmin - 1;
}
else break;
2009-04-27 13:44:11 +00:00
}
}
}
/* only exported for WM */
/* makes region ready for drawing, sets pixelspace */
void ED_region_set(const bContext *C, ARegion *ar)
{
2012-05-08 15:43:59 +00:00
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
rcti winrct;
/* checks other overlapping regions */
region_scissor_winrct(ar, &winrct);
2012-05-08 15:43:59 +00:00
ar->drawrct = winrct;
/* note; this sets state, so we can use wmOrtho and friends */
wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
2012-05-08 15:43:59 +00:00
UI_SetTheme(sa ? sa->spacetype : 0, ar->type ? ar->type->regionid : 0);
ED_region_pixelspace(ar);
}
/* only exported for WM */
void ED_region_do_draw(bContext *C, ARegion *ar)
{
2012-05-08 15:43:59 +00:00
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
ARegionType *at = ar->type;
2009-04-27 13:44:11 +00:00
rcti winrct;
/* see BKE_spacedata_draw_locks() */
if (at->do_lock)
return;
2009-04-27 13:44:11 +00:00
/* checks other overlapping regions */
region_scissor_winrct(ar, &winrct);
2.5: WM Compositing * Triple Buffer is now more complete: - Proper handling of window resize, duplicate, etc. - It now uses 3x3 textures (or less) if the power of two sizes do not match well. That still has a worst case wast of 23.4%, but better than 300%. - It can also use the ARB/NV/EXT_texture_rectangle extension now, which may be supported on hardware that does not support ARB_texture_non_power_of_two. - Gesture, menu and brushe redraws now require no redraws at all from the area regions. So even on a high poly scene just moving the paint cursor or opening a menu should be fast. * Testing can be done by setting the "Window Draw Method" in the User Preferences in the outliner. "Overlap" is still default, since "Triple Buffer" has not been tested on computers other than mine, would like to avoid crashing Blender on startup in case there is a common bug, but it's ready for testing now. - For reference "Full" draws the full window each time. - "Triple Buffer" should work for both swap copy and swap exchange systems, the latter still need the -E command line option for "Overlap". - Resizing and going fullscreen still gives flicker here but no more than "Full" drawing. * Partial Redraw was added. ED_region_tag_redraw_partial takes a rect in window coordinates to define a subarea of the region. On region draw it will then set glScissor to a smaller area, and ar->drawrct will always be set to either the partial or full window rect. The latter can then be used for clipping in the 3D view or clipping interface drawing. Neither is implemented yet.
2009-01-23 03:52:52 +00:00
/* if no partial draw rect set, full rect */
if (ar->drawrct.xmin == ar->drawrct.xmax)
2012-05-08 15:43:59 +00:00
ar->drawrct = winrct;
2009-04-27 13:44:11 +00:00
else {
/* extra clip for safety */
ar->drawrct.xmin = MAX2(winrct.xmin, ar->drawrct.xmin);
ar->drawrct.ymin = MAX2(winrct.ymin, ar->drawrct.ymin);
ar->drawrct.xmax = MIN2(winrct.xmax, ar->drawrct.xmax);
ar->drawrct.ymax = MIN2(winrct.ymax, ar->drawrct.ymax);
2009-04-27 13:44:11 +00:00
}
/* note; this sets state, so we can use wmOrtho and friends */
2.5: WM Compositing * Triple Buffer is now more complete: - Proper handling of window resize, duplicate, etc. - It now uses 3x3 textures (or less) if the power of two sizes do not match well. That still has a worst case wast of 23.4%, but better than 300%. - It can also use the ARB/NV/EXT_texture_rectangle extension now, which may be supported on hardware that does not support ARB_texture_non_power_of_two. - Gesture, menu and brushe redraws now require no redraws at all from the area regions. So even on a high poly scene just moving the paint cursor or opening a menu should be fast. * Testing can be done by setting the "Window Draw Method" in the User Preferences in the outliner. "Overlap" is still default, since "Triple Buffer" has not been tested on computers other than mine, would like to avoid crashing Blender on startup in case there is a common bug, but it's ready for testing now. - For reference "Full" draws the full window each time. - "Triple Buffer" should work for both swap copy and swap exchange systems, the latter still need the -E command line option for "Overlap". - Resizing and going fullscreen still gives flicker here but no more than "Full" drawing. * Partial Redraw was added. ED_region_tag_redraw_partial takes a rect in window coordinates to define a subarea of the region. On region draw it will then set glScissor to a smaller area, and ar->drawrct will always be set to either the partial or full window rect. The latter can then be used for clipping in the 3D view or clipping interface drawing. Neither is implemented yet.
2009-01-23 03:52:52 +00:00
wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
2012-05-08 15:43:59 +00:00
UI_SetTheme(sa ? sa->spacetype : 0, ar->type ? ar->type->regionid : 0);
2009-04-27 13:44:11 +00:00
/* optional header info instead? */
if (ar->headerstr) {
UI_ThemeClearColor(TH_HEADER);
glClear(GL_COLOR_BUFFER_BIT);
2009-04-27 13:44:11 +00:00
UI_ThemeColor(TH_TEXT);
BLF_draw_default(20, 8, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
}
else if (at->draw) {
at->draw(C, ar);
}
/* XXX test: add convention to end regions always in pixel space, for drawing of borders/gestures etc */
ED_region_pixelspace(ar);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_PIXEL);
ar->do_draw = FALSE;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
uiFreeInactiveBlocks(C, &ar->uiblocks);
if (sa)
2009-04-27 13:44:11 +00:00
region_draw_emboss(ar, &winrct);
}
/* **********************************
* maybe silly, but let's try for now
* to keep these tags protected
* ********************************** */
void ED_region_tag_redraw(ARegion *ar)
{
if (ar) {
2.5: WM Compositing * Triple Buffer is now more complete: - Proper handling of window resize, duplicate, etc. - It now uses 3x3 textures (or less) if the power of two sizes do not match well. That still has a worst case wast of 23.4%, but better than 300%. - It can also use the ARB/NV/EXT_texture_rectangle extension now, which may be supported on hardware that does not support ARB_texture_non_power_of_two. - Gesture, menu and brushe redraws now require no redraws at all from the area regions. So even on a high poly scene just moving the paint cursor or opening a menu should be fast. * Testing can be done by setting the "Window Draw Method" in the User Preferences in the outliner. "Overlap" is still default, since "Triple Buffer" has not been tested on computers other than mine, would like to avoid crashing Blender on startup in case there is a common bug, but it's ready for testing now. - For reference "Full" draws the full window each time. - "Triple Buffer" should work for both swap copy and swap exchange systems, the latter still need the -E command line option for "Overlap". - Resizing and going fullscreen still gives flicker here but no more than "Full" drawing. * Partial Redraw was added. ED_region_tag_redraw_partial takes a rect in window coordinates to define a subarea of the region. On region draw it will then set glScissor to a smaller area, and ar->drawrct will always be set to either the partial or full window rect. The latter can then be used for clipping in the 3D view or clipping interface drawing. Neither is implemented yet.
2009-01-23 03:52:52 +00:00
/* zero region means full region redraw */
2012-05-08 15:43:59 +00:00
ar->do_draw = RGN_DRAW;
2.5: WM Compositing * Triple Buffer is now more complete: - Proper handling of window resize, duplicate, etc. - It now uses 3x3 textures (or less) if the power of two sizes do not match well. That still has a worst case wast of 23.4%, but better than 300%. - It can also use the ARB/NV/EXT_texture_rectangle extension now, which may be supported on hardware that does not support ARB_texture_non_power_of_two. - Gesture, menu and brushe redraws now require no redraws at all from the area regions. So even on a high poly scene just moving the paint cursor or opening a menu should be fast. * Testing can be done by setting the "Window Draw Method" in the User Preferences in the outliner. "Overlap" is still default, since "Triple Buffer" has not been tested on computers other than mine, would like to avoid crashing Blender on startup in case there is a common bug, but it's ready for testing now. - For reference "Full" draws the full window each time. - "Triple Buffer" should work for both swap copy and swap exchange systems, the latter still need the -E command line option for "Overlap". - Resizing and going fullscreen still gives flicker here but no more than "Full" drawing. * Partial Redraw was added. ED_region_tag_redraw_partial takes a rect in window coordinates to define a subarea of the region. On region draw it will then set glScissor to a smaller area, and ar->drawrct will always be set to either the partial or full window rect. The latter can then be used for clipping in the 3D view or clipping interface drawing. Neither is implemented yet.
2009-01-23 03:52:52 +00:00
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
}
}
void ED_region_tag_redraw_overlay(ARegion *ar)
{
if (ar)
2012-05-08 15:43:59 +00:00
ar->do_draw_overlay = RGN_DRAW;
}
2.5: WM Compositing * Triple Buffer is now more complete: - Proper handling of window resize, duplicate, etc. - It now uses 3x3 textures (or less) if the power of two sizes do not match well. That still has a worst case wast of 23.4%, but better than 300%. - It can also use the ARB/NV/EXT_texture_rectangle extension now, which may be supported on hardware that does not support ARB_texture_non_power_of_two. - Gesture, menu and brushe redraws now require no redraws at all from the area regions. So even on a high poly scene just moving the paint cursor or opening a menu should be fast. * Testing can be done by setting the "Window Draw Method" in the User Preferences in the outliner. "Overlap" is still default, since "Triple Buffer" has not been tested on computers other than mine, would like to avoid crashing Blender on startup in case there is a common bug, but it's ready for testing now. - For reference "Full" draws the full window each time. - "Triple Buffer" should work for both swap copy and swap exchange systems, the latter still need the -E command line option for "Overlap". - Resizing and going fullscreen still gives flicker here but no more than "Full" drawing. * Partial Redraw was added. ED_region_tag_redraw_partial takes a rect in window coordinates to define a subarea of the region. On region draw it will then set glScissor to a smaller area, and ar->drawrct will always be set to either the partial or full window rect. The latter can then be used for clipping in the 3D view or clipping interface drawing. Neither is implemented yet.
2009-01-23 03:52:52 +00:00
void ED_region_tag_redraw_partial(ARegion *ar, rcti *rct)
{
if (ar) {
if (!ar->do_draw) {
2.5: WM Compositing * Triple Buffer is now more complete: - Proper handling of window resize, duplicate, etc. - It now uses 3x3 textures (or less) if the power of two sizes do not match well. That still has a worst case wast of 23.4%, but better than 300%. - It can also use the ARB/NV/EXT_texture_rectangle extension now, which may be supported on hardware that does not support ARB_texture_non_power_of_two. - Gesture, menu and brushe redraws now require no redraws at all from the area regions. So even on a high poly scene just moving the paint cursor or opening a menu should be fast. * Testing can be done by setting the "Window Draw Method" in the User Preferences in the outliner. "Overlap" is still default, since "Triple Buffer" has not been tested on computers other than mine, would like to avoid crashing Blender on startup in case there is a common bug, but it's ready for testing now. - For reference "Full" draws the full window each time. - "Triple Buffer" should work for both swap copy and swap exchange systems, the latter still need the -E command line option for "Overlap". - Resizing and going fullscreen still gives flicker here but no more than "Full" drawing. * Partial Redraw was added. ED_region_tag_redraw_partial takes a rect in window coordinates to define a subarea of the region. On region draw it will then set glScissor to a smaller area, and ar->drawrct will always be set to either the partial or full window rect. The latter can then be used for clipping in the 3D view or clipping interface drawing. Neither is implemented yet.
2009-01-23 03:52:52 +00:00
/* no redraw set yet, set partial region */
2012-05-08 15:43:59 +00:00
ar->do_draw = RGN_DRAW_PARTIAL;
ar->drawrct = *rct;
2.5: WM Compositing * Triple Buffer is now more complete: - Proper handling of window resize, duplicate, etc. - It now uses 3x3 textures (or less) if the power of two sizes do not match well. That still has a worst case wast of 23.4%, but better than 300%. - It can also use the ARB/NV/EXT_texture_rectangle extension now, which may be supported on hardware that does not support ARB_texture_non_power_of_two. - Gesture, menu and brushe redraws now require no redraws at all from the area regions. So even on a high poly scene just moving the paint cursor or opening a menu should be fast. * Testing can be done by setting the "Window Draw Method" in the User Preferences in the outliner. "Overlap" is still default, since "Triple Buffer" has not been tested on computers other than mine, would like to avoid crashing Blender on startup in case there is a common bug, but it's ready for testing now. - For reference "Full" draws the full window each time. - "Triple Buffer" should work for both swap copy and swap exchange systems, the latter still need the -E command line option for "Overlap". - Resizing and going fullscreen still gives flicker here but no more than "Full" drawing. * Partial Redraw was added. ED_region_tag_redraw_partial takes a rect in window coordinates to define a subarea of the region. On region draw it will then set glScissor to a smaller area, and ar->drawrct will always be set to either the partial or full window rect. The latter can then be used for clipping in the 3D view or clipping interface drawing. Neither is implemented yet.
2009-01-23 03:52:52 +00:00
}
else if (ar->drawrct.xmin != ar->drawrct.xmax) {
2.5: WM Compositing * Triple Buffer is now more complete: - Proper handling of window resize, duplicate, etc. - It now uses 3x3 textures (or less) if the power of two sizes do not match well. That still has a worst case wast of 23.4%, but better than 300%. - It can also use the ARB/NV/EXT_texture_rectangle extension now, which may be supported on hardware that does not support ARB_texture_non_power_of_two. - Gesture, menu and brushe redraws now require no redraws at all from the area regions. So even on a high poly scene just moving the paint cursor or opening a menu should be fast. * Testing can be done by setting the "Window Draw Method" in the User Preferences in the outliner. "Overlap" is still default, since "Triple Buffer" has not been tested on computers other than mine, would like to avoid crashing Blender on startup in case there is a common bug, but it's ready for testing now. - For reference "Full" draws the full window each time. - "Triple Buffer" should work for both swap copy and swap exchange systems, the latter still need the -E command line option for "Overlap". - Resizing and going fullscreen still gives flicker here but no more than "Full" drawing. * Partial Redraw was added. ED_region_tag_redraw_partial takes a rect in window coordinates to define a subarea of the region. On region draw it will then set glScissor to a smaller area, and ar->drawrct will always be set to either the partial or full window rect. The latter can then be used for clipping in the 3D view or clipping interface drawing. Neither is implemented yet.
2009-01-23 03:52:52 +00:00
/* partial redraw already set, expand region */
ar->drawrct.xmin = MIN2(ar->drawrct.xmin, rct->xmin);
ar->drawrct.ymin = MIN2(ar->drawrct.ymin, rct->ymin);
ar->drawrct.xmax = MAX2(ar->drawrct.xmax, rct->xmax);
ar->drawrct.ymax = MAX2(ar->drawrct.ymax, rct->ymax);
2.5: WM Compositing * Triple Buffer is now more complete: - Proper handling of window resize, duplicate, etc. - It now uses 3x3 textures (or less) if the power of two sizes do not match well. That still has a worst case wast of 23.4%, but better than 300%. - It can also use the ARB/NV/EXT_texture_rectangle extension now, which may be supported on hardware that does not support ARB_texture_non_power_of_two. - Gesture, menu and brushe redraws now require no redraws at all from the area regions. So even on a high poly scene just moving the paint cursor or opening a menu should be fast. * Testing can be done by setting the "Window Draw Method" in the User Preferences in the outliner. "Overlap" is still default, since "Triple Buffer" has not been tested on computers other than mine, would like to avoid crashing Blender on startup in case there is a common bug, but it's ready for testing now. - For reference "Full" draws the full window each time. - "Triple Buffer" should work for both swap copy and swap exchange systems, the latter still need the -E command line option for "Overlap". - Resizing and going fullscreen still gives flicker here but no more than "Full" drawing. * Partial Redraw was added. ED_region_tag_redraw_partial takes a rect in window coordinates to define a subarea of the region. On region draw it will then set glScissor to a smaller area, and ar->drawrct will always be set to either the partial or full window rect. The latter can then be used for clipping in the 3D view or clipping interface drawing. Neither is implemented yet.
2009-01-23 03:52:52 +00:00
}
}
}
void ED_area_tag_redraw(ScrArea *sa)
{
ARegion *ar;
if (sa)
2012-05-08 15:43:59 +00:00
for (ar = sa->regionbase.first; ar; ar = ar->next)
2.5: WM Compositing * Triple Buffer is now more complete: - Proper handling of window resize, duplicate, etc. - It now uses 3x3 textures (or less) if the power of two sizes do not match well. That still has a worst case wast of 23.4%, but better than 300%. - It can also use the ARB/NV/EXT_texture_rectangle extension now, which may be supported on hardware that does not support ARB_texture_non_power_of_two. - Gesture, menu and brushe redraws now require no redraws at all from the area regions. So even on a high poly scene just moving the paint cursor or opening a menu should be fast. * Testing can be done by setting the "Window Draw Method" in the User Preferences in the outliner. "Overlap" is still default, since "Triple Buffer" has not been tested on computers other than mine, would like to avoid crashing Blender on startup in case there is a common bug, but it's ready for testing now. - For reference "Full" draws the full window each time. - "Triple Buffer" should work for both swap copy and swap exchange systems, the latter still need the -E command line option for "Overlap". - Resizing and going fullscreen still gives flicker here but no more than "Full" drawing. * Partial Redraw was added. ED_region_tag_redraw_partial takes a rect in window coordinates to define a subarea of the region. On region draw it will then set glScissor to a smaller area, and ar->drawrct will always be set to either the partial or full window rect. The latter can then be used for clipping in the 3D view or clipping interface drawing. Neither is implemented yet.
2009-01-23 03:52:52 +00:00
ED_region_tag_redraw(ar);
}
void ED_area_tag_redraw_regiontype(ScrArea *sa, int regiontype)
{
ARegion *ar;
if (sa) {
2012-05-08 15:43:59 +00:00
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == regiontype) {
ED_region_tag_redraw(ar);
}
}
}
}
void ED_area_tag_refresh(ScrArea *sa)
{
if (sa)
sa->do_refresh = TRUE;
}
/* *************************************************************** */
/* use NULL to disable it */
void ED_area_headerprint(ScrArea *sa, const char *str)
{
ARegion *ar;
/* happens when running transform operators in backround mode */
if (sa == NULL)
return;
2012-05-08 15:43:59 +00:00
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == RGN_TYPE_HEADER) {
if (str) {
2012-05-08 15:43:59 +00:00
if (ar->headerstr == NULL)
ar->headerstr = MEM_mallocN(256, "headerprint");
BLI_strncpy(ar->headerstr, str, 256);
}
else if (ar->headerstr) {
MEM_freeN(ar->headerstr);
2012-05-08 15:43:59 +00:00
ar->headerstr = NULL;
}
ED_region_tag_redraw(ar);
}
}
}
/* ************************************************************ */
static void area_azone_initialize(bScreen *screen, ScrArea *sa)
{
AZone *az;
/* reinitalize entirely, regions add azones too */
BLI_freelistN(&sa->actionzones);
if (screen->full != SCREENNORMAL) {
return;
}
/* set area action zones */
2012-05-08 15:43:59 +00:00
az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
BLI_addtail(&(sa->actionzones), az);
2012-05-08 15:43:59 +00:00
az->type = AZONE_AREA;
az->x1 = sa->totrct.xmin - 1;
az->y1 = sa->totrct.ymin - 1;
az->x2 = sa->totrct.xmin + (AZONESPOT - 1);
az->y2 = sa->totrct.ymin + (AZONESPOT - 1);
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
2012-05-08 15:43:59 +00:00
az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
BLI_addtail(&(sa->actionzones), az);
2012-05-08 15:43:59 +00:00
az->type = AZONE_AREA;
az->x1 = sa->totrct.xmax + 1;
az->y1 = sa->totrct.ymax + 1;
az->x2 = sa->totrct.xmax - (AZONESPOT - 1);
az->y2 = sa->totrct.ymax - (AZONESPOT - 1);
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
2012-05-08 15:43:59 +00:00
#define AZONEPAD_EDGE 4
#define AZONEPAD_ICON 9
static void region_azone_edge(AZone *az, ARegion *ar)
{
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmin;
az->y1 = ar->winrct.ymax - AZONEPAD_EDGE;
az->x2 = ar->winrct.xmax;
az->y2 = ar->winrct.ymax;
break;
case AE_BOTTOM_TO_TOPLEFT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmin;
az->y1 = ar->winrct.ymin + AZONEPAD_EDGE;
az->x2 = ar->winrct.xmax;
az->y2 = ar->winrct.ymin;
break;
case AE_LEFT_TO_TOPRIGHT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmin;
az->y1 = ar->winrct.ymin;
az->x2 = ar->winrct.xmin + AZONEPAD_EDGE;
az->y2 = ar->winrct.ymax;
break;
case AE_RIGHT_TO_TOPLEFT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmax;
az->y1 = ar->winrct.ymin;
az->x2 = ar->winrct.xmax - AZONEPAD_EDGE;
az->y2 = ar->winrct.ymax;
break;
}
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
static void region_azone_icon(ScrArea *sa, AZone *az, ARegion *ar)
{
AZone *azt;
2012-05-08 15:43:59 +00:00
int tot = 0;
/* count how many actionzones with along same edge are available.
* This allows for adding more action zones in the future without
* having to worry about correct offset */
2012-05-08 15:43:59 +00:00
for (azt = sa->actionzones.first; azt; azt = azt->next) {
if (azt->edge == az->edge) tot++;
}
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmax - tot * 2 * AZONEPAD_ICON;
az->y1 = ar->winrct.ymax + AZONEPAD_ICON;
az->x2 = ar->winrct.xmax - tot * AZONEPAD_ICON;
az->y2 = ar->winrct.ymax + 2 * AZONEPAD_ICON;
break;
case AE_BOTTOM_TO_TOPLEFT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmin + AZONEPAD_ICON;
az->y1 = ar->winrct.ymin - 2 * AZONEPAD_ICON;
az->x2 = ar->winrct.xmin + 2 * AZONEPAD_ICON;
az->y2 = ar->winrct.ymin - AZONEPAD_ICON;
break;
case AE_LEFT_TO_TOPRIGHT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmin - 2 * AZONEPAD_ICON;
az->y1 = ar->winrct.ymax - tot * 2 * AZONEPAD_ICON;
az->x2 = ar->winrct.xmin - AZONEPAD_ICON;
az->y2 = ar->winrct.ymax - tot * AZONEPAD_ICON;
break;
case AE_RIGHT_TO_TOPLEFT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmax + AZONEPAD_ICON;
az->y1 = ar->winrct.ymax - tot * 2 * AZONEPAD_ICON;
az->x2 = ar->winrct.xmax + 2 * AZONEPAD_ICON;
az->y2 = ar->winrct.ymax - tot * AZONEPAD_ICON;
break;
}
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
/* if more azones on 1 spot, set offset */
2012-05-08 15:43:59 +00:00
for (azt = sa->actionzones.first; azt; azt = azt->next) {
if (az != azt) {
if (ABS(az->x1 - azt->x1) < 2 && ABS(az->y1 - azt->y1) < 2) {
if (az->edge == AE_TOP_TO_BOTTOMRIGHT || az->edge == AE_BOTTOM_TO_TOPLEFT) {
az->x1 += AZONESPOT;
az->x2 += AZONESPOT;
}
else {
2012-05-08 15:43:59 +00:00
az->y1 -= AZONESPOT;
az->y2 -= AZONESPOT;
}
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
}
}
}
2012-05-08 15:43:59 +00:00
#define AZONEPAD_TAB_PLUSW 14
#define AZONEPAD_TAB_PLUSH 14
/* region already made zero sized, in shape of edge */
static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
{
AZone *azt;
2012-05-08 15:43:59 +00:00
int tot = 0, add;
2012-05-08 15:43:59 +00:00
for (azt = sa->actionzones.first; azt; azt = azt->next) {
if (azt->edge == az->edge) tot++;
}
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
2012-05-08 15:43:59 +00:00
if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0;
az->x1 = ar->winrct.xmax - 2.5 * AZONEPAD_TAB_PLUSW;
az->y1 = ar->winrct.ymax - add;
az->x2 = ar->winrct.xmax - 1.5 * AZONEPAD_TAB_PLUSW;
az->y2 = ar->winrct.ymax - add + AZONEPAD_TAB_PLUSH;
break;
case AE_BOTTOM_TO_TOPLEFT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmax - 2.5 * AZONEPAD_TAB_PLUSW;
az->y1 = ar->winrct.ymin - AZONEPAD_TAB_PLUSH;
az->x2 = ar->winrct.xmax - 1.5 * AZONEPAD_TAB_PLUSW;
az->y2 = ar->winrct.ymin;
break;
case AE_LEFT_TO_TOPRIGHT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmin - AZONEPAD_TAB_PLUSH;
az->y1 = ar->winrct.ymax - 2.5 * AZONEPAD_TAB_PLUSW;
az->x2 = ar->winrct.xmin;
az->y2 = ar->winrct.ymax - 1.5 * AZONEPAD_TAB_PLUSW;
break;
case AE_RIGHT_TO_TOPLEFT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmax - 1;
az->y1 = ar->winrct.ymax - 2.5 * AZONEPAD_TAB_PLUSW;
az->x2 = ar->winrct.xmax - 1 + AZONEPAD_TAB_PLUSH;
az->y2 = ar->winrct.ymax - 1.5 * AZONEPAD_TAB_PLUSW;
break;
}
/* rect needed for mouse pointer test */
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
2012-05-08 15:43:59 +00:00
#define AZONEPAD_TABW 18
#define AZONEPAD_TABH 7
/* region already made zero sized, in shape of edge */
static void region_azone_tab(ScrArea *sa, AZone *az, ARegion *ar)
{
AZone *azt;
2012-05-08 15:43:59 +00:00
int tot = 0, add;
2012-05-08 15:43:59 +00:00
for (azt = sa->actionzones.first; azt; azt = azt->next) {
if (azt->edge == az->edge) tot++;
}
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
2012-05-08 15:43:59 +00:00
if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0;
az->x1 = ar->winrct.xmax - 2 * AZONEPAD_TABW;
az->y1 = ar->winrct.ymax - add;
az->x2 = ar->winrct.xmax - AZONEPAD_TABW;
az->y2 = ar->winrct.ymax - add + AZONEPAD_TABH;
break;
case AE_BOTTOM_TO_TOPLEFT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmin + AZONEPAD_TABW;
az->y1 = ar->winrct.ymin - AZONEPAD_TABH;
az->x2 = ar->winrct.xmin + 2 * AZONEPAD_TABW;
az->y2 = ar->winrct.ymin;
break;
case AE_LEFT_TO_TOPRIGHT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmin + 1 - AZONEPAD_TABH;
az->y1 = ar->winrct.ymax - 2 * AZONEPAD_TABW;
az->x2 = ar->winrct.xmin + 1;
az->y2 = ar->winrct.ymax - AZONEPAD_TABW;
break;
case AE_RIGHT_TO_TOPLEFT:
2012-05-08 15:43:59 +00:00
az->x1 = ar->winrct.xmax - 1;
az->y1 = ar->winrct.ymax - 2 * AZONEPAD_TABW;
az->x2 = ar->winrct.xmax - 1 + AZONEPAD_TABH;
az->y2 = ar->winrct.ymax - AZONEPAD_TABW;
break;
}
/* rect needed for mouse pointer test */
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
2012-05-08 15:43:59 +00:00
#define AZONEPAD_TRIAW 16
#define AZONEPAD_TRIAH 9
/* region already made zero sized, in shape of edge */
static void region_azone_tria(ScrArea *sa, AZone *az, ARegion *ar)
{
AZone *azt;
2012-05-08 15:43:59 +00:00
int tot = 0, add;
2012-05-08 15:43:59 +00:00
for (azt = sa->actionzones.first; azt; azt = azt->next) {
if (azt->edge == az->edge) tot++;
}
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
2012-05-08 15:43:59 +00:00
if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0;
az->x1 = ar->winrct.xmax - 2 * AZONEPAD_TRIAW;
az->y1 = ar->winrct.ymax - add;
az->x2 = ar->winrct.xmax - AZONEPAD_TRIAW;
az->y2 = ar->winrct.ymax - add + AZONEPAD_TRIAH;
break;
2012-05-08 15:43:59 +00:00
case AE_BOTTOM_TO_TOPLEFT:
az->x1 = ar->winrct.xmin + AZONEPAD_TRIAW;
az->y1 = ar->winrct.ymin - AZONEPAD_TRIAH;
az->x2 = ar->winrct.xmin + 2 * AZONEPAD_TRIAW;
az->y2 = ar->winrct.ymin;
break;
2012-05-08 15:43:59 +00:00
case AE_LEFT_TO_TOPRIGHT:
az->x1 = ar->winrct.xmin + 1 - AZONEPAD_TRIAH;
az->y1 = ar->winrct.ymax - 2 * AZONEPAD_TRIAW;
az->x2 = ar->winrct.xmin + 1;
az->y2 = ar->winrct.ymax - AZONEPAD_TRIAW;
break;
2012-05-08 15:43:59 +00:00
case AE_RIGHT_TO_TOPLEFT:
az->x1 = ar->winrct.xmax - 1;
az->y1 = ar->winrct.ymax - 2 * AZONEPAD_TRIAW;
az->x2 = ar->winrct.xmax - 1 + AZONEPAD_TRIAH;
az->y2 = ar->winrct.ymax - AZONEPAD_TRIAW;
break;
}
/* rect needed for mouse pointer test */
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
static void region_azone_initialize(ScrArea *sa, ARegion *ar, AZEdge edge)
{
AZone *az;
2012-05-08 15:43:59 +00:00
az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
BLI_addtail(&(sa->actionzones), az);
2012-05-08 15:43:59 +00:00
az->type = AZONE_REGION;
az->ar = ar;
az->edge = edge;
2012-05-08 15:43:59 +00:00
if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
if (G.debug_value == 3)
region_azone_icon(sa, az, ar);
else if (G.debug_value == 2)
region_azone_tria(sa, az, ar);
else if (G.debug_value == 1)
region_azone_tab(sa, az, ar);
else
region_azone_tab_plus(sa, az, ar);
}
else {
region_azone_edge(az, ar);
}
}
/* *************************************************************** */
static void region_azone_add(ScrArea *sa, ARegion *ar, int alignment)
{
2012-05-08 15:43:59 +00:00
/* edge code (t b l r) is along which area edge azone will be drawn */
2012-05-08 15:43:59 +00:00
if (alignment == RGN_ALIGN_TOP)
region_azone_initialize(sa, ar, AE_BOTTOM_TO_TOPLEFT);
2012-05-08 15:43:59 +00:00
else if (alignment == RGN_ALIGN_BOTTOM)
region_azone_initialize(sa, ar, AE_TOP_TO_BOTTOMRIGHT);
else if (ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT))
region_azone_initialize(sa, ar, AE_LEFT_TO_TOPRIGHT);
else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_OVERLAP_LEFT))
region_azone_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT);
}
/* dir is direction to check, not the splitting edge direction! */
static int rct_fits(rcti *rect, char dir, int size)
{
2012-05-08 15:43:59 +00:00
if (dir == 'h') {
return BLI_rcti_size_x(rect) - size;
}
2012-08-20 23:06:17 +00:00
else { /* 'v' */
return BLI_rcti_size_y(rect) - size;
}
}
static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int quad)
{
2012-05-08 15:43:59 +00:00
rcti *remainder_prev = remainder;
int prefsizex, prefsizey;
int alignment;
2012-05-08 15:43:59 +00:00
if (ar == NULL)
return;
/* no returns in function, winrct gets set in the end again */
BLI_rcti_init(&ar->winrct, 0, 0, 0, 0);
/* for test; allow split of previously defined region */
if (ar->alignment & RGN_SPLIT_PREV)
if (ar->prev)
2012-05-08 15:43:59 +00:00
remainder = &ar->prev->winrct;
alignment = ar->alignment & ~RGN_SPLIT_PREV;
/* clear state flags first */
ar->flag &= ~RGN_FLAG_TOO_SMALL;
/* user errors */
2012-05-08 15:43:59 +00:00
if (ar->next == NULL && alignment != RGN_ALIGN_QSPLIT)
alignment = RGN_ALIGN_NONE;
/* prefsize, for header we stick to exception */
2012-05-08 15:43:59 +00:00
prefsizex = ar->sizex ? ar->sizex : ar->type->prefsizex;
2012-10-07 09:48:59 +00:00
if (ar->regiontype == RGN_TYPE_HEADER) {
2012-05-08 15:43:59 +00:00
prefsizey = ar->type->prefsizey;
2012-10-07 09:48:59 +00:00
}
2012-05-08 15:43:59 +00:00
else if (ar->regiontype == RGN_TYPE_UI && sa->spacetype == SPACE_FILE) {
prefsizey = UI_UNIT_Y * 2 + (UI_UNIT_Y / 2);
}
2012-10-07 09:48:59 +00:00
else {
2012-05-08 15:43:59 +00:00
prefsizey = ar->sizey ? ar->sizey : ar->type->prefsizey;
2012-10-07 09:48:59 +00:00
}
if (ar->flag & RGN_FLAG_HIDDEN) {
/* hidden is user flag */
}
else if (alignment == RGN_ALIGN_FLOAT) {
/* XXX floating area region, not handled yet here */
}
2012-05-08 15:43:59 +00:00
else if (rct_fits(remainder, 'v', 1) < 0 || rct_fits(remainder, 'h', 1) < 0) {
2012-10-07 09:48:59 +00:00
/* remainder is too small for any usage */
ar->flag |= RGN_FLAG_TOO_SMALL;
}
2012-05-08 15:43:59 +00:00
else if (alignment == RGN_ALIGN_NONE) {
/* typically last region */
2012-05-08 15:43:59 +00:00
ar->winrct = *remainder;
BLI_rcti_init(remainder, 0, 0, 0, 0);
}
2012-05-08 15:43:59 +00:00
else if (alignment == RGN_ALIGN_TOP || alignment == RGN_ALIGN_BOTTOM) {
2012-05-08 15:43:59 +00:00
if (rct_fits(remainder, 'v', prefsizey) < 0) {
ar->flag |= RGN_FLAG_TOO_SMALL;
}
else {
2012-05-08 15:43:59 +00:00
int fac = rct_fits(remainder, 'v', prefsizey);
Various changes made in the process of working on the UI code: * Added functions to generate Timer events. There was some unfinished code to create one timer per window, this replaces that with a way to let operators or other handlers add/remove their own timers as needed. This is currently delivered as an event with the timer handle, perhaps this should be a notifier instead? Also includes some fixes in ghost for timer events that were not delivered in time, due to passing negative timeout. * Added a Message event, which is a generic event that can be added by any operator. This is used in the UI code to communicate the results of opened blocks. Again, this may be better as a notifier. * These two events should not be blocked as they are intended for a specific operator or handler, so there were exceptions added for this, which is one of the reasons they might work better as notifiers, but currently these things can't listen to notifier yet. * Added an option to events to indicate if the customdata should be freed or not. * Added a free() callback for area regions, and added a free function for area regions in blenkernel since it was already there for screens and areas. * Added ED_screen/area/region_exit functions to clean up things like operators and handlers when they are closed. * Added screen level regions, these will draw over areas boundaries, with the last created region on top. These are useful for tooltips, menus, etc, and are not saved to file. It's using the same ARegion struct as areas to avoid code duplication, but perhaps that should be renamed then. Note that redraws currently go correct, because only full window redraws are used, for partial redraws without any frontbuffer drawing, the window manager needs to get support for compositing subwindows. * Minor changes in the subwindow code to retrieve the matrix, and moved setlinestyle to glutil.c. * Reversed argument order in WM_event_add/remove_keymap_handler to be consistent with modal_handler. * Operators can now block events but not necessarily cancel/finish. * Modal operators are now stored in a list in the window/area/region they were created in. This means for example that when a transform operator is invoked from a region but registers a handler at the window level (since mouse motion across areas should work), it will still get removed when the region is closed while the operator is running.
2008-11-11 15:18:21 +00:00
2012-05-08 15:43:59 +00:00
if (fac < 0)
prefsizey += fac;
2012-05-08 15:43:59 +00:00
ar->winrct = *remainder;
2012-05-08 15:43:59 +00:00
if (alignment == RGN_ALIGN_TOP) {
ar->winrct.ymin = ar->winrct.ymax - prefsizey + 1;
remainder->ymax = ar->winrct.ymin - 1;
}
else {
ar->winrct.ymax = ar->winrct.ymin + prefsizey - 1;
remainder->ymin = ar->winrct.ymax + 1;
}
}
}
2012-05-08 15:43:59 +00:00
else if (ELEM4(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT, RGN_OVERLAP_LEFT, RGN_OVERLAP_RIGHT)) {
2012-05-08 15:43:59 +00:00
if (rct_fits(remainder, 'h', prefsizex) < 0) {
ar->flag |= RGN_FLAG_TOO_SMALL;
}
else {
2012-05-08 15:43:59 +00:00
int fac = rct_fits(remainder, 'h', prefsizex);
2012-05-08 15:43:59 +00:00
if (fac < 0)
prefsizex += fac;
2012-05-08 15:43:59 +00:00
ar->winrct = *remainder;
if (ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT)) {
ar->winrct.xmin = ar->winrct.xmax - prefsizex + 1;
2012-05-08 15:43:59 +00:00
if (alignment == RGN_ALIGN_RIGHT)
remainder->xmax = ar->winrct.xmin - 1;
}
else {
ar->winrct.xmax = ar->winrct.xmin + prefsizex - 1;
2012-05-08 15:43:59 +00:00
if (alignment == RGN_ALIGN_LEFT)
remainder->xmin = ar->winrct.xmax + 1;
}
}
}
2012-05-08 15:43:59 +00:00
else if (alignment == RGN_ALIGN_VSPLIT || alignment == RGN_ALIGN_HSPLIT) {
/* percentage subdiv*/
2012-05-08 15:43:59 +00:00
ar->winrct = *remainder;
2012-05-08 15:43:59 +00:00
if (alignment == RGN_ALIGN_HSPLIT) {
if (rct_fits(remainder, 'h', prefsizex) > 4) {
ar->winrct.xmax = BLI_rcti_cent_x(remainder);
2012-05-08 15:43:59 +00:00
remainder->xmin = ar->winrct.xmax + 1;
}
else {
BLI_rcti_init(remainder, 0, 0, 0, 0);
}
}
else {
2012-05-08 15:43:59 +00:00
if (rct_fits(remainder, 'v', prefsizey) > 4) {
ar->winrct.ymax = BLI_rcti_cent_y(remainder);
2012-05-08 15:43:59 +00:00
remainder->ymin = ar->winrct.ymax + 1;
}
else {
BLI_rcti_init(remainder, 0, 0, 0, 0);
}
}
}
2012-05-08 15:43:59 +00:00
else if (alignment == RGN_ALIGN_QSPLIT) {
ar->winrct = *remainder;
/* test if there's still 4 regions left */
2012-05-08 15:43:59 +00:00
if (quad == 0) {
ARegion *artest = ar->next;
int count = 1;
while (artest) {
2012-05-08 15:43:59 +00:00
artest->alignment = RGN_ALIGN_QSPLIT;
artest = artest->next;
count++;
}
2012-05-08 15:43:59 +00:00
if (count != 4) {
/* let's stop adding regions */
BLI_rcti_init(remainder, 0, 0, 0, 0);
if (G.debug & G_DEBUG)
printf("region quadsplit failed\n");
}
2012-05-08 15:43:59 +00:00
else quad = 1;
}
if (quad) {
2012-05-08 15:43:59 +00:00
if (quad == 1) { /* left bottom */
ar->winrct.xmax = BLI_rcti_cent_x(remainder);
ar->winrct.ymax = BLI_rcti_cent_y(remainder);
}
2012-05-08 15:43:59 +00:00
else if (quad == 2) { /* left top */
ar->winrct.xmax = BLI_rcti_cent_x(remainder);
ar->winrct.ymin = BLI_rcti_cent_y(remainder) + 1;
}
2012-05-08 15:43:59 +00:00
else if (quad == 3) { /* right bottom */
ar->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
ar->winrct.ymax = BLI_rcti_cent_y(remainder);
}
2012-05-08 15:43:59 +00:00
else { /* right top */
ar->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
ar->winrct.ymin = BLI_rcti_cent_y(remainder) + 1;
BLI_rcti_init(remainder, 0, 0, 0, 0);
}
quad++;
}
}
/* for speedup */
ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
/* set winrect for azones */
2012-05-08 15:43:59 +00:00
if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
ar->winrct = *remainder;
2012-05-08 15:43:59 +00:00
if (alignment == RGN_ALIGN_TOP)
ar->winrct.ymin = ar->winrct.ymax;
2012-05-08 15:43:59 +00:00
else if (alignment == RGN_ALIGN_BOTTOM)
ar->winrct.ymax = ar->winrct.ymin;
else if (ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT))
ar->winrct.xmin = ar->winrct.xmax;
else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_OVERLAP_LEFT))
ar->winrct.xmax = ar->winrct.xmin;
else /* prevent winrct to be valid */
ar->winrct.xmax = ar->winrct.xmin;
}
/* restore prev-split exception */
if (ar->alignment & RGN_SPLIT_PREV) {
if (ar->prev) {
2012-05-08 15:43:59 +00:00
remainder = remainder_prev;
ar->prev->winx = BLI_rcti_size_x(&ar->prev->winrct) + 1;
ar->prev->winy = BLI_rcti_size_y(&ar->prev->winrct) + 1;
}
}
/* in end, add azones, where appropriate */
if (ar->regiontype == RGN_TYPE_HEADER && ar->winy + 6 > sa->winy) {
/* The logic for this is: when the header takes up the full area,
* disallow hiding it to view the main window.
*
* Without this, you can drag down the file selectors header and hide it
* by accident very easily (highly annoying!), the value 6 is arbitrary
* but accounts for small common rounding problems when scaling the UI,
* must be minimum '4' */
}
else {
region_azone_add(sa, ar, alignment);
}
region_rect_recursive(sa, ar->next, remainder, quad);
}
static void area_calc_totrct(ScrArea *sa, int sizex, int sizey)
{
short rt = 0; // CLAMPIS(G.debug_value, 0, 16);
2012-05-08 15:43:59 +00:00
if (sa->v1->vec.x > 0) sa->totrct.xmin = sa->v1->vec.x + 1 + rt;
else sa->totrct.xmin = sa->v1->vec.x;
2012-05-08 15:43:59 +00:00
if (sa->v4->vec.x < sizex - 1) sa->totrct.xmax = sa->v4->vec.x - 1 - rt;
else sa->totrct.xmax = sa->v4->vec.x;
2012-05-08 15:43:59 +00:00
if (sa->v1->vec.y > 0) sa->totrct.ymin = sa->v1->vec.y + 1 + rt;
else sa->totrct.ymin = sa->v1->vec.y;
2012-05-08 15:43:59 +00:00
if (sa->v2->vec.y < sizey - 1) sa->totrct.ymax = sa->v2->vec.y - 1 - rt;
else sa->totrct.ymax = sa->v2->vec.y;
/* for speedup */
sa->winx = BLI_rcti_size_x(&sa->totrct) + 1;
sa->winy = BLI_rcti_size_y(&sa->totrct) + 1;
}
/* used for area initialize below */
static void region_subwindow(wmWindow *win, ARegion *ar)
Various changes made in the process of working on the UI code: * Added functions to generate Timer events. There was some unfinished code to create one timer per window, this replaces that with a way to let operators or other handlers add/remove their own timers as needed. This is currently delivered as an event with the timer handle, perhaps this should be a notifier instead? Also includes some fixes in ghost for timer events that were not delivered in time, due to passing negative timeout. * Added a Message event, which is a generic event that can be added by any operator. This is used in the UI code to communicate the results of opened blocks. Again, this may be better as a notifier. * These two events should not be blocked as they are intended for a specific operator or handler, so there were exceptions added for this, which is one of the reasons they might work better as notifiers, but currently these things can't listen to notifier yet. * Added an option to events to indicate if the customdata should be freed or not. * Added a free() callback for area regions, and added a free function for area regions in blenkernel since it was already there for screens and areas. * Added ED_screen/area/region_exit functions to clean up things like operators and handlers when they are closed. * Added screen level regions, these will draw over areas boundaries, with the last created region on top. These are useful for tooltips, menus, etc, and are not saved to file. It's using the same ARegion struct as areas to avoid code duplication, but perhaps that should be renamed then. Note that redraws currently go correct, because only full window redraws are used, for partial redraws without any frontbuffer drawing, the window manager needs to get support for compositing subwindows. * Minor changes in the subwindow code to retrieve the matrix, and moved setlinestyle to glutil.c. * Reversed argument order in WM_event_add/remove_keymap_handler to be consistent with modal_handler. * Operators can now block events but not necessarily cancel/finish. * Modal operators are now stored in a list in the window/area/region they were created in. This means for example that when a transform operator is invoked from a region but registers a handler at the window level (since mouse motion across areas should work), it will still get removed when the region is closed while the operator is running.
2008-11-11 15:18:21 +00:00
{
2012-05-08 15:43:59 +00:00
if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
if (ar->swinid)
Various changes made in the process of working on the UI code: * Added functions to generate Timer events. There was some unfinished code to create one timer per window, this replaces that with a way to let operators or other handlers add/remove their own timers as needed. This is currently delivered as an event with the timer handle, perhaps this should be a notifier instead? Also includes some fixes in ghost for timer events that were not delivered in time, due to passing negative timeout. * Added a Message event, which is a generic event that can be added by any operator. This is used in the UI code to communicate the results of opened blocks. Again, this may be better as a notifier. * These two events should not be blocked as they are intended for a specific operator or handler, so there were exceptions added for this, which is one of the reasons they might work better as notifiers, but currently these things can't listen to notifier yet. * Added an option to events to indicate if the customdata should be freed or not. * Added a free() callback for area regions, and added a free function for area regions in blenkernel since it was already there for screens and areas. * Added ED_screen/area/region_exit functions to clean up things like operators and handlers when they are closed. * Added screen level regions, these will draw over areas boundaries, with the last created region on top. These are useful for tooltips, menus, etc, and are not saved to file. It's using the same ARegion struct as areas to avoid code duplication, but perhaps that should be renamed then. Note that redraws currently go correct, because only full window redraws are used, for partial redraws without any frontbuffer drawing, the window manager needs to get support for compositing subwindows. * Minor changes in the subwindow code to retrieve the matrix, and moved setlinestyle to glutil.c. * Reversed argument order in WM_event_add/remove_keymap_handler to be consistent with modal_handler. * Operators can now block events but not necessarily cancel/finish. * Modal operators are now stored in a list in the window/area/region they were created in. This means for example that when a transform operator is invoked from a region but registers a handler at the window level (since mouse motion across areas should work), it will still get removed when the region is closed while the operator is running.
2008-11-11 15:18:21 +00:00
wm_subwindow_close(win, ar->swinid);
2012-05-08 15:43:59 +00:00
ar->swinid = 0;
Various changes made in the process of working on the UI code: * Added functions to generate Timer events. There was some unfinished code to create one timer per window, this replaces that with a way to let operators or other handlers add/remove their own timers as needed. This is currently delivered as an event with the timer handle, perhaps this should be a notifier instead? Also includes some fixes in ghost for timer events that were not delivered in time, due to passing negative timeout. * Added a Message event, which is a generic event that can be added by any operator. This is used in the UI code to communicate the results of opened blocks. Again, this may be better as a notifier. * These two events should not be blocked as they are intended for a specific operator or handler, so there were exceptions added for this, which is one of the reasons they might work better as notifiers, but currently these things can't listen to notifier yet. * Added an option to events to indicate if the customdata should be freed or not. * Added a free() callback for area regions, and added a free function for area regions in blenkernel since it was already there for screens and areas. * Added ED_screen/area/region_exit functions to clean up things like operators and handlers when they are closed. * Added screen level regions, these will draw over areas boundaries, with the last created region on top. These are useful for tooltips, menus, etc, and are not saved to file. It's using the same ARegion struct as areas to avoid code duplication, but perhaps that should be renamed then. Note that redraws currently go correct, because only full window redraws are used, for partial redraws without any frontbuffer drawing, the window manager needs to get support for compositing subwindows. * Minor changes in the subwindow code to retrieve the matrix, and moved setlinestyle to glutil.c. * Reversed argument order in WM_event_add/remove_keymap_handler to be consistent with modal_handler. * Operators can now block events but not necessarily cancel/finish. * Modal operators are now stored in a list in the window/area/region they were created in. This means for example that when a transform operator is invoked from a region but registers a handler at the window level (since mouse motion across areas should work), it will still get removed when the region is closed while the operator is running.
2008-11-11 15:18:21 +00:00
}
2012-05-08 15:43:59 +00:00
else if (ar->swinid == 0)
ar->swinid = wm_subwindow_open(win, &ar->winrct);
Various changes made in the process of working on the UI code: * Added functions to generate Timer events. There was some unfinished code to create one timer per window, this replaces that with a way to let operators or other handlers add/remove their own timers as needed. This is currently delivered as an event with the timer handle, perhaps this should be a notifier instead? Also includes some fixes in ghost for timer events that were not delivered in time, due to passing negative timeout. * Added a Message event, which is a generic event that can be added by any operator. This is used in the UI code to communicate the results of opened blocks. Again, this may be better as a notifier. * These two events should not be blocked as they are intended for a specific operator or handler, so there were exceptions added for this, which is one of the reasons they might work better as notifiers, but currently these things can't listen to notifier yet. * Added an option to events to indicate if the customdata should be freed or not. * Added a free() callback for area regions, and added a free function for area regions in blenkernel since it was already there for screens and areas. * Added ED_screen/area/region_exit functions to clean up things like operators and handlers when they are closed. * Added screen level regions, these will draw over areas boundaries, with the last created region on top. These are useful for tooltips, menus, etc, and are not saved to file. It's using the same ARegion struct as areas to avoid code duplication, but perhaps that should be renamed then. Note that redraws currently go correct, because only full window redraws are used, for partial redraws without any frontbuffer drawing, the window manager needs to get support for compositing subwindows. * Minor changes in the subwindow code to retrieve the matrix, and moved setlinestyle to glutil.c. * Reversed argument order in WM_event_add/remove_keymap_handler to be consistent with modal_handler. * Operators can now block events but not necessarily cancel/finish. * Modal operators are now stored in a list in the window/area/region they were created in. This means for example that when a transform operator is invoked from a region but registers a handler at the window level (since mouse motion across areas should work), it will still get removed when the region is closed while the operator is running.
2008-11-11 15:18:21 +00:00
else
wm_subwindow_position(win, ar->swinid, &ar->winrct);
}
static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *handlers, int flag)
{
/* note, add-handler checks if it already exists */
2012-07-07 22:51:57 +00:00
/* XXX it would be good to have boundbox checks for some of these... */
if (flag & ED_KEYMAP_UI) {
/* user interface widgets */
UI_add_region_handlers(handlers);
}
if (flag & ED_KEYMAP_VIEW2D) {
/* 2d-viewport handling+manipulation */
wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "View2D", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_MARKERS) {
/* time-markers */
wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Markers", 0, 0);
/* time space only has this keymap, the others get a boundbox restricted map */
2012-05-08 15:43:59 +00:00
if (sa->spacetype != SPACE_TIME) {
ARegion *ar;
2012-05-08 15:43:59 +00:00
static rcti rect = {0, 10000, 0, 30}; /* same local check for all areas */
ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
if (ar) {
WM_event_add_keymap_handler_bb(handlers, keymap, &rect, &ar->winrct);
}
}
else
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_ANIMATION) {
/* frame changing and timeline operators (for time spaces) */
wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Animation", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_FRAMES) {
/* frame changing/jumping (for all spaces) */
wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Frames", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_GPENCIL) {
/* grease pencil */
wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Grease Pencil", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_HEADER) {
/* standard keymap for headers regions */
wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Header", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
}
/* called in screen_refresh, or screens_init, also area size changes */
void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
{
ARegion *ar;
rcti rect;
/* set typedefinitions */
2012-05-08 15:43:59 +00:00
sa->type = BKE_spacetype_from_id(sa->spacetype);
2012-05-08 15:43:59 +00:00
if (sa->type == NULL) {
sa->butspacetype = sa->spacetype = SPACE_VIEW3D;
sa->type = BKE_spacetype_from_id(sa->spacetype);
}
2012-05-08 15:43:59 +00:00
for (ar = sa->regionbase.first; ar; ar = ar->next)
ar->type = BKE_regiontype_from_id(sa->type, ar->regiontype);
/* area sizes */
area_calc_totrct(sa, win->sizex, win->sizey);
/* clear all azones, add the area triange widgets */
area_azone_initialize(win->screen, sa);
/* region rect sizes */
2012-05-08 15:43:59 +00:00
rect = sa->totrct;
region_rect_recursive(sa, sa->regionbase.first, &rect, 0);
/* default area handlers */
ed_default_handlers(wm, sa, &sa->handlers, sa->type->keymapflag);
/* checks spacedata, adds own handlers */
if (sa->type->init)
sa->type->init(wm, sa);
/* region windows, default and own handlers */
2012-05-08 15:43:59 +00:00
for (ar = sa->regionbase.first; ar; ar = ar->next) {
region_subwindow(win, ar);
if (ar->swinid) {
/* default region handlers */
ed_default_handlers(wm, sa, &ar->handlers, ar->type->keymapflag);
/* own handlers */
if (ar->type->init)
ar->type->init(wm, ar);
}
else {
/* prevent uiblocks to run */
uiFreeBlocks(NULL, &ar->uiblocks);
}
/* rechecks 2d matrix for header on dpi changing, do not do for other regions, it resets view && blocks view2d operator polls (ton) */
2012-05-08 15:43:59 +00:00
if (ar->regiontype == RGN_TYPE_HEADER)
ar->v2d.flag &= ~V2D_IS_INITIALISED;
}
}
/* externally called for floating regions like menus */
void ED_region_init(bContext *C, ARegion *ar)
{
// ARegionType *at= ar->type;
/* refresh can be called before window opened */
region_subwindow(CTX_wm_window(C), ar);
ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
/* UI convention */
2012-05-08 15:43:59 +00:00
wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f);
glLoadIdentity();
}
void ED_region_toggle_hidden(bContext *C, ARegion *ar)
{
2012-05-08 15:43:59 +00:00
ScrArea *sa = CTX_wm_area(C);
ar->flag ^= RGN_FLAG_HIDDEN;
if (ar->flag & RGN_FLAG_HIDDEN)
WM_event_remove_handlers(C, &ar->handlers);
ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
ED_area_tag_redraw(sa);
}
/* sa2 to sa1, we swap spaces for fullscreen to keep all allocated data */
/* area vertices were set */
void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space)
{
SpaceType *st;
ARegion *ar;
2012-05-08 15:43:59 +00:00
int spacetype = sa1->spacetype;
2012-05-08 15:43:59 +00:00
sa1->headertype = sa2->headertype;
sa1->spacetype = sa2->spacetype;
sa1->butspacetype = sa2->butspacetype;
if (swap_space == 1) {
SWAP(ListBase, sa1->spacedata, sa2->spacedata);
/* exception: ensure preview is reset */
2012-08-04 12:30:16 +00:00
// if (sa1->spacetype == SPACE_VIEW3D)
// XXX BIF_view3d_previewrender_free(sa1->spacedata.first);
}
else if (swap_space == 2) {
BKE_spacedata_copylist(&sa1->spacedata, &sa2->spacedata);
}
else {
BKE_spacedata_freelist(&sa1->spacedata);
BKE_spacedata_copylist(&sa1->spacedata, &sa2->spacedata);
}
/* Note; SPACE_EMPTY is possible on new screens */
/* regions */
if (swap_space == 1) {
SWAP(ListBase, sa1->regionbase, sa2->regionbase);
}
else {
2012-05-08 15:43:59 +00:00
if (swap_space < 2) {
st = BKE_spacetype_from_id(spacetype);
for (ar = sa1->regionbase.first; ar; ar = ar->next)
BKE_area_region_free(st, ar);
BLI_freelistN(&sa1->regionbase);
}
2012-05-08 15:43:59 +00:00
st = BKE_spacetype_from_id(sa2->spacetype);
for (ar = sa2->regionbase.first; ar; ar = ar->next) {
ARegion *newar = BKE_area_region_copy(st, ar);
BLI_addtail(&sa1->regionbase, newar);
}
Various changes made in the process of working on the UI code: * Added functions to generate Timer events. There was some unfinished code to create one timer per window, this replaces that with a way to let operators or other handlers add/remove their own timers as needed. This is currently delivered as an event with the timer handle, perhaps this should be a notifier instead? Also includes some fixes in ghost for timer events that were not delivered in time, due to passing negative timeout. * Added a Message event, which is a generic event that can be added by any operator. This is used in the UI code to communicate the results of opened blocks. Again, this may be better as a notifier. * These two events should not be blocked as they are intended for a specific operator or handler, so there were exceptions added for this, which is one of the reasons they might work better as notifiers, but currently these things can't listen to notifier yet. * Added an option to events to indicate if the customdata should be freed or not. * Added a free() callback for area regions, and added a free function for area regions in blenkernel since it was already there for screens and areas. * Added ED_screen/area/region_exit functions to clean up things like operators and handlers when they are closed. * Added screen level regions, these will draw over areas boundaries, with the last created region on top. These are useful for tooltips, menus, etc, and are not saved to file. It's using the same ARegion struct as areas to avoid code duplication, but perhaps that should be renamed then. Note that redraws currently go correct, because only full window redraws are used, for partial redraws without any frontbuffer drawing, the window manager needs to get support for compositing subwindows. * Minor changes in the subwindow code to retrieve the matrix, and moved setlinestyle to glutil.c. * Reversed argument order in WM_event_add/remove_keymap_handler to be consistent with modal_handler. * Operators can now block events but not necessarily cancel/finish. * Modal operators are now stored in a list in the window/area/region they were created in. This means for example that when a transform operator is invoked from a region but registers a handler at the window level (since mouse motion across areas should work), it will still get removed when the region is closed while the operator is running.
2008-11-11 15:18:21 +00:00
}
}
/* *********** Space switching code *********** */
void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
{
2012-05-08 15:43:59 +00:00
ScrArea *tmp = MEM_callocN(sizeof(ScrArea), "addscrarea");
ED_area_exit(C, sa1);
ED_area_exit(C, sa2);
area_copy_data(tmp, sa1, 2);
area_copy_data(sa1, sa2, 0);
area_copy_data(sa2, tmp, 0);
ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa1);
ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa2);
BKE_screen_area_free(tmp);
MEM_freeN(tmp);
/* tell WM to refresh, cursor types etc */
WM_event_add_mousemove(C);
ED_area_tag_redraw(sa1);
ED_area_tag_refresh(sa1);
ED_area_tag_redraw(sa2);
ED_area_tag_refresh(sa2);
}
void ED_area_newspace(bContext *C, ScrArea *sa, int type)
{
if (sa->spacetype != type) {
SpaceType *st;
SpaceLink *slold;
SpaceLink *sl;
ED_area_exit(C, sa);
2012-05-08 15:43:59 +00:00
st = BKE_spacetype_from_id(type);
slold = sa->spacedata.first;
2012-05-08 15:43:59 +00:00
sa->spacetype = type;
sa->butspacetype = type;
sa->type = st;
/* check previously stored space */
2012-05-08 15:43:59 +00:00
for (sl = sa->spacedata.first; sl; sl = sl->next)
if (sl->spacetype == type)
break;
/* old spacedata... happened during work on 2.50, remove */
2012-05-08 15:43:59 +00:00
if (sl && sl->regionbase.first == NULL) {
st->free(sl);
BLI_freelinkN(&sa->spacedata, sl);
if (slold == sl) {
2012-05-08 15:43:59 +00:00
slold = NULL;
}
2012-05-08 15:43:59 +00:00
sl = NULL;
}
if (sl) {
/* swap regions */
2012-05-08 15:43:59 +00:00
slold->regionbase = sa->regionbase;
sa->regionbase = sl->regionbase;
sl->regionbase.first = sl->regionbase.last = NULL;
/* put in front of list */
BLI_remlink(&sa->spacedata, sl);
BLI_addhead(&sa->spacedata, sl);
}
else {
/* new space */
if (st) {
2012-05-08 15:43:59 +00:00
sl = st->new(C);
BLI_addhead(&sa->spacedata, sl);
/* swap regions */
if (slold)
2012-05-08 15:43:59 +00:00
slold->regionbase = sa->regionbase;
sa->regionbase = sl->regionbase;
sl->regionbase.first = sl->regionbase.last = NULL;
}
}
ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
/* tell WM to refresh, cursor types etc */
WM_event_add_mousemove(C);
/* send space change notifier */
2012-05-08 15:43:59 +00:00
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, sa);
ED_area_tag_refresh(sa);
}
/* also redraw when re-used */
ED_area_tag_redraw(sa);
}
void ED_area_prevspace(bContext *C, ScrArea *sa)
{
SpaceLink *sl = (sa) ? sa->spacedata.first : CTX_wm_space_data(C);
if (sl->next) {
/* workaround for case of double prevspace, render window
* with a file browser on top of it */
if (sl->next->spacetype == SPACE_FILE && sl->next->next)
ED_area_newspace(C, sa, sl->next->next->spacetype);
else
ED_area_newspace(C, sa, sl->next->spacetype);
}
else {
ED_area_newspace(C, sa, SPACE_INFO);
}
ED_area_tag_redraw(sa);
/* send space change notifier */
2012-05-08 15:43:59 +00:00
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, sa);
}
static const char *editortype_pup(void)
{
2012-05-08 15:43:59 +00:00
const char *types = N_(
"Editor type: %t"
2012-05-08 15:43:59 +00:00
"|3D View %x1"
2012-05-08 15:43:59 +00:00
"|%l"
2012-05-08 15:43:59 +00:00
"|Timeline %x15"
"|Graph Editor %x2"
"|DopeSheet %x12"
"|NLA Editor %x13"
2012-05-08 15:43:59 +00:00
"|%l"
2012-05-08 15:43:59 +00:00
"|UV/Image Editor %x6"
2012-05-08 15:43:59 +00:00
"|Video Sequence Editor %x8"
"|Movie Clip Editor %x20"
"|Text Editor %x9"
"|Node Editor %x16"
"|Logic Editor %x17"
2012-05-08 15:43:59 +00:00
"|%l"
2012-05-08 15:43:59 +00:00
"|Properties %x4"
"|Outliner %x3"
"|User Preferences %x19"
"|Info %x7"
2011-09-25 12:31:21 +00:00
2012-05-08 15:43:59 +00:00
"|%l"
2011-09-25 12:31:21 +00:00
2012-05-08 15:43:59 +00:00
"|File Browser %x5"
2012-05-08 15:43:59 +00:00
"|%l"
2012-05-08 15:43:59 +00:00
"|Python Console %x18"
);
return IFACE_(types);
}
static void spacefunc(struct bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
{
ED_area_newspace(C, CTX_wm_area(C), CTX_wm_area(C)->butspacetype);
ED_area_tag_redraw(CTX_wm_area(C));
/* send space change notifier */
2012-05-08 15:43:59 +00:00
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, CTX_wm_area(C));
}
/* returns offset for next button in header */
int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
{
2012-05-08 15:43:59 +00:00
ScrArea *sa = CTX_wm_area(C);
uiBut *but;
2012-05-08 15:43:59 +00:00
int xco = 8;
but = uiDefIconTextButC(block, ICONTEXTROW, 0, ICON_VIEW3D,
2012-05-08 15:43:59 +00:00
editortype_pup(), xco, yco, UI_UNIT_X + 10, UI_UNIT_Y,
&(sa->butspacetype), 1.0, SPACEICONMAX, 0, 0,
TIP_("Display current editor type (click for menu of available types)"));
uiButSetFunc(but, spacefunc, NULL, NULL);
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
return xco + UI_UNIT_X + 14;
}
int ED_area_header_standardbuttons(const bContext *C, uiBlock *block, int yco)
{
2012-05-08 15:43:59 +00:00
ScrArea *sa = CTX_wm_area(C);
int xco = 8;
uiBut *but;
if (!sa->full)
2012-05-08 15:43:59 +00:00
xco = ED_area_header_switchbutton(C, block, yco);
uiBlockSetEmboss(block, UI_EMBOSSN);
if (sa->flag & HEADER_NO_PULLDOWN) {
but = uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0,
2012-04-29 15:47:02 +00:00
ICON_DISCLOSURE_TRI_RIGHT,
xco, yco, UI_UNIT_X, UI_UNIT_Y - 2,
&(sa->flag), 0, 0, 0, 0,
"Show pulldown menus");
}
else {
but = uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0,
2012-04-29 15:47:02 +00:00
ICON_DISCLOSURE_TRI_DOWN,
xco, yco, UI_UNIT_X, UI_UNIT_Y - 2,
&(sa->flag), 0, 0, 0, 0,
"Hide pulldown menus");
}
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
uiBlockSetEmboss(block, UI_EMBOSS);
return xco + UI_UNIT_X;
}
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
/************************ standard UI regions ************************/
void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *context, int contextnr)
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
{
2012-05-08 15:43:59 +00:00
ScrArea *sa = CTX_wm_area(C);
uiStyle *style = UI_GetStyle();
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
uiBlock *block;
PanelType *pt;
Panel *panel;
2012-05-08 15:43:59 +00:00
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
2012-05-08 15:43:59 +00:00
int x, y, xco, yco, w, em, triangle, open, newcontext = 0;
if (contextnr >= 0)
2012-05-08 15:43:59 +00:00
newcontext = UI_view2d_tab_set(v2d, contextnr);
if (vertical) {
w = BLI_rctf_size_x(&v2d->cur);
2012-05-08 15:43:59 +00:00
em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
}
else {
2012-05-08 15:43:59 +00:00
w = UI_PANEL_WIDTH;
em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
}
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
/* create panels */
uiBeginPanels(C, ar);
/* set view2d view matrix for scrolling (without scrollers) */
UI_view2d_view_ortho(v2d);
2012-05-08 15:43:59 +00:00
for (pt = ar->type->paneltypes.first; pt; pt = pt->next) {
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
/* verify context */
if (context)
if (pt->context[0] && strcmp(context, pt->context) != 0)
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
continue;
/* draw panel */
if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
2012-05-08 15:43:59 +00:00
block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
panel = uiBeginPanel(sa, ar, block, pt, &open);
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
/* bad fixed values */
2012-05-08 15:43:59 +00:00
triangle = (int)(UI_UNIT_Y * 1.1f);
if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
/* for enabled buttons */
2012-05-08 15:43:59 +00:00
panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
triangle, UI_UNIT_Y + style->panelspace + 2, UI_UNIT_Y, 1, style);
pt->draw_header(C, panel);
uiBlockLayoutResolve(block, &xco, &yco);
2012-05-08 15:43:59 +00:00
panel->labelofs = xco - triangle;
panel->layout = NULL;
}
else {
2012-05-08 15:43:59 +00:00
panel->labelofs = 0;
}
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
if (open) {
short panelContext;
/* panel context can either be toolbar region or normal panels region */
if (ar->regiontype == RGN_TYPE_TOOLS)
2012-05-08 15:43:59 +00:00
panelContext = UI_LAYOUT_TOOLBAR;
else
2012-05-08 15:43:59 +00:00
panelContext = UI_LAYOUT_PANEL;
2012-05-08 15:43:59 +00:00
panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
style->panelspace, 0, w - 2 * style->panelspace, em, style);
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
pt->draw(C, panel);
uiBlockLayoutResolve(block, &xco, &yco);
2012-05-08 15:43:59 +00:00
panel->layout = NULL;
2012-05-08 15:43:59 +00:00
yco -= 2 * style->panelspace;
uiEndPanel(block, w, -yco);
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
}
else {
2012-05-08 15:43:59 +00:00
yco = 0;
uiEndPanel(block, w, 0);
}
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
uiEndBlock(C, block);
}
}
/* align panels and return size */
uiEndPanels(C, ar, &x, &y);
/* clear */
2012-05-08 15:43:59 +00:00
UI_ThemeClearColor((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
glClear(GL_COLOR_BUFFER_BIT);
/* before setting the view */
if (vertical) {
/* only allow scrolling in vertical direction */
2012-05-08 15:43:59 +00:00
v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y;
v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
v2d->scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
2012-07-07 22:51:57 +00:00
/* don't jump back when panels close or hide */
if (!newcontext)
2012-05-08 15:43:59 +00:00
y = MAX2(-y, -v2d->cur.ymin);
else
2012-05-08 15:43:59 +00:00
y = -y;
}
else {
/* for now, allow scrolling in both directions (since layouts are optimized for vertical,
* they often don't fit in horizontal layout)
*/
2012-05-08 15:43:59 +00:00
v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
//v2d->keepofs |= V2D_LOCKOFS_Y|V2D_KEEPOFS_X;
//v2d->keepofs &= ~(V2D_LOCKOFS_X|V2D_KEEPOFS_Y);
v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_HIDE;
2012-07-07 22:51:57 +00:00
/* don't jump back when panels close or hide */
if (!newcontext)
2012-05-08 15:43:59 +00:00
x = MAX2(x, v2d->cur.xmax);
y = -y;
}
2012-07-07 22:51:57 +00:00
/* +V2D_SCROLL_HEIGHT is workaround to set the actual height */
2012-05-08 15:43:59 +00:00
UI_view2d_totRect_set(v2d, x + V2D_SCROLL_WIDTH, y + V2D_SCROLL_HEIGHT);
/* set the view */
UI_view2d_view_ortho(v2d);
/* draw panels */
uiDrawPanels(C, ar);
/* restore view matrix */
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
UI_view2d_view_restore(C);
/* scrollers */
2012-05-08 15:43:59 +00:00
scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
}
void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
2012-07-07 22:51:57 +00:00
/* XXX quick hacks for files saved with 2.5 already (i.e. the builtin defaults file)
* scrollbars for button regions */
2012-05-08 15:43:59 +00:00
ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
ar->v2d.scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
ar->v2d.keepzoom |= V2D_KEEPZOOM;
2012-07-07 22:51:57 +00:00
/* correctly initialized User-Prefs? */
if (!(ar->v2d.align & V2D_ALIGN_NO_POS_Y))
ar->v2d.flag &= ~V2D_IS_INITIALISED;
2012-07-07 22:51:57 +00:00
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
keymap = WM_keymap_find(wm->defaultconf, "View2D Buttons List", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
void ED_region_header(const bContext *C, ARegion *ar)
{
2012-05-08 15:43:59 +00:00
uiStyle *style = UI_GetStyle();
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
uiBlock *block;
uiLayout *layout;
HeaderType *ht;
Header header = {NULL};
int maxco, xco, yco;
2012-05-08 15:43:59 +00:00
int headery = ED_area_headersize();
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
/* clear */
2012-05-08 15:43:59 +00:00
UI_ThemeClearColor((ED_screen_area_active(C)) ? TH_HEADER : TH_HEADERDESEL);
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
glClear(GL_COLOR_BUFFER_BIT);
/* set view2d view matrix for scrolling (without scrollers) */
UI_view2d_view_ortho(&ar->v2d);
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
2012-05-08 15:43:59 +00:00
xco = maxco = 8;
yco = headery - 4;
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
/* draw all headers types */
2012-05-08 15:43:59 +00:00
for (ht = ar->type->headertypes.first; ht; ht = ht->next) {
block = uiBeginBlock(C, ar, ht->idname, UI_EMBOSS);
layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, UI_UNIT_Y, 1, style);
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
if (ht->draw) {
2012-05-08 15:43:59 +00:00
header.type = ht;
header.layout = layout;
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
ht->draw(C, &header);
/* for view2d */
2012-05-08 15:43:59 +00:00
xco = uiLayoutGetWidth(layout);
if (xco > maxco)
2012-05-08 15:43:59 +00:00
maxco = xco;
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
}
uiBlockLayoutResolve(block, &xco, &yco);
/* for view2d */
if (xco > maxco)
2012-05-08 15:43:59 +00:00
maxco = xco;
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
uiEndBlock(C, block);
uiDrawBlock(C, block);
}
/* always as last */
UI_view2d_totRect_set(&ar->v2d, maxco + UI_UNIT_X + 80, BLI_rctf_size_y(&ar->v2d.tot));
UI: Layout Engine * Buttons are now created first, and after that the layout is computed. This means the layout engine now works at button level, and makes it easier to write templates. Otherwise you had to store all info and create the buttons later. * Added interface_templates.c as a separate file to put templates in. These can contain regular buttons, and can be put in a Free layout, which means you can specify manual coordinates, but still get nested correct inside other layouts. * API was changed to allow better nesting. Previously items were added in the last added layout specifier, i.e. one level up in the layout hierarchy. This doesn't work well in always, so now when creating things like rows or columns it always returns a layout which you have to add the items in. All py scripts were updated to follow this. * Computing the layout now goes in two passes, first estimating the required width/height of all nested layouts, and then in the second pass using the results of that to decide on the actual locations. * Enum and array buttons now follow the direction of the layout, i.e. they are vertical or horizontal depending if they are in a column or row. * Color properties now get a color picker, and only get the additional RGB sliders with Expand=True. * File/directory string properties now get a button next to them for opening the file browse, though this is not implemented yet. * Layout items can now be aligned, set align=True when creating a column, row, etc. * Buttons now get a minimum width of one icon (avoids squashing icon buttons). * Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00
/* restore view matrix? */
UI_view2d_view_restore(C);
}
void ED_region_header_init(ARegion *ar)
{
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
}
/* UI_UNIT_Y is defined as U variable now, depending dpi */
int ED_area_headersize(void)
{
2012-05-08 15:43:59 +00:00
return UI_UNIT_Y + 6;
}
void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha)
{
const int header_height = 18;
2012-05-08 15:43:59 +00:00
uiStyle *style = UI_GetStyle();
int fontid = style->widget.uifont_id;
rcti rect;
BLF_size(fontid, 11.0f, 72);
/* background box */
2012-05-08 15:43:59 +00:00
rect = ar->winrct;
rect.xmin = 0;
rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height;
if (block) {
rect.xmax = BLI_rcti_size_x(&ar->winrct);
}
else {
rect.xmax = rect.xmin + BLF_width(fontid, text) + 24;
}
rect.ymax = BLI_rcti_size_y(&ar->winrct);
glEnable(GL_BLEND);
2012-04-29 15:47:02 +00:00
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.0f, 0.0f, 0.0f, alpha);
2012-05-08 15:43:59 +00:00
glRecti(rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1);
glDisable(GL_BLEND);
/* text */
UI_ThemeColor(TH_TEXT_HI);
BLF_position(fontid, 12, rect.ymin + 5, 0.0f);
BLF_draw(fontid, text, BLF_DRAW_STR_DUMMY_MAX);
}
void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
{
float gridsize, gridstep = 1.0f / 32.0f;
float fac, blendfac;
int x1, y1, x2, y2;
2012-04-29 15:47:02 +00:00
/* the image is located inside (0, 0), (1, 1) as set by view2d */
UI_ThemeColorShade(TH_BACK, 20);
UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x1, &y1);
UI_view2d_to_region_no_clip(&ar->v2d, 1.0f, 1.0f, &x2, &y2);
glRectf(x1, y1, x2, y2);
/* gridsize adapted to zoom level */
gridsize = 0.5f * (zoomx + zoomy);
if (gridsize <= 0.0f)
return;
if (gridsize < 1.0f) {
while (gridsize < 1.0f) {
gridsize *= 4.0f;
gridstep *= 4.0f;
}
}
else {
while (gridsize >= 4.0f) {
gridsize /= 4.0f;
gridstep /= 4.0f;
}
}
/* the fine resolution level */
blendfac = 0.25f * gridsize - floorf(0.25f * gridsize);
CLAMP(blendfac, 0.0f, 1.0f);
UI_ThemeColorShade(TH_BACK, (int)(20.0f * (1.0f - blendfac)));
fac = 0.0f;
glBegin(GL_LINES);
while (fac < 1.0f) {
glVertex2f(x1, y1 * (1.0f - fac) + y2 * fac);
glVertex2f(x2, y1 * (1.0f - fac) + y2 * fac);
glVertex2f(x1 * (1.0f - fac) + x2 * fac, y1);
glVertex2f(x1 * (1.0f - fac) + x2 * fac, y2);
fac += gridstep;
}
/* the large resolution level */
UI_ThemeColor(TH_BACK);
fac = 0.0f;
while (fac < 1.0f) {
glVertex2f(x1, y1 * (1.0f - fac) + y2 * fac);
glVertex2f(x2, y1 * (1.0f - fac) + y2 * fac);
glVertex2f(x1 * (1.0f - fac) + x2 * fac, y1);
glVertex2f(x1 * (1.0f - fac) + x2 * fac, y2);
fac += 4.0f * gridstep;
}
glEnd();
}