UI: Tabs categories for panels (D75)
- works by defining panel categories, currently restricted to the toolbar. - no panels define bl_categories yet, so no user visible changes since tabs only show when there are multiple. - panel pinning is available in rmb menu or alt+lmb.
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_color_blend.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLF_translation.h"
|
||||
@@ -53,12 +54,15 @@
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
#include "BLF_api.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_interface_icons.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "interface_intern.h"
|
||||
@@ -75,6 +79,9 @@
|
||||
#define PNL_NEW_ADDED 16
|
||||
#define PNL_FIRST 32
|
||||
|
||||
/* only show pin header button for pinned panels */
|
||||
#define USE_PIN_HIDDEN
|
||||
|
||||
typedef enum uiHandlePanelState {
|
||||
PANEL_STATE_DRAG,
|
||||
PANEL_STATE_DRAG_SCALE,
|
||||
@@ -188,23 +195,36 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar)
|
||||
pa->ofsy = papar->ofsy + papar->sizey - pa->sizey;
|
||||
}
|
||||
|
||||
Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int *open)
|
||||
Panel *uiPanelFindByType(ARegion *ar, PanelType *pt)
|
||||
{
|
||||
Panel *pa, *patab, *palast, *panext;
|
||||
Panel *pa;
|
||||
|
||||
const char *idname = pt->idname;
|
||||
const char *tabname = pt->idname;
|
||||
|
||||
for (pa = ar->panels.first; pa; pa = pa->next) {
|
||||
if (STREQLEN(pa->panelname, idname, UI_MAX_NAME_STR)) {
|
||||
if (STREQLEN(pa->tabname, tabname, UI_MAX_NAME_STR)) {
|
||||
return pa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \note \a pa should be return value from #uiPanelFindByType and can be NULL.
|
||||
*/
|
||||
Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, Panel *pa, bool *r_open)
|
||||
{
|
||||
Panel *patab, *palast, *panext;
|
||||
const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
|
||||
char *idname = pt->idname;
|
||||
char *tabname = pt->idname;
|
||||
char *hookname = NULL;
|
||||
int newpanel;
|
||||
const bool newpanel = (pa == NULL);
|
||||
int align = panel_aligned(sa, ar);
|
||||
|
||||
/* check if Panel exists, then use that one */
|
||||
for (pa = ar->panels.first; pa; pa = pa->next)
|
||||
if (strncmp(pa->panelname, idname, UI_MAX_NAME_STR) == 0)
|
||||
if (strncmp(pa->tabname, tabname, UI_MAX_NAME_STR) == 0)
|
||||
break;
|
||||
|
||||
newpanel = (pa == NULL);
|
||||
|
||||
if (!newpanel) {
|
||||
pa->type = pt;
|
||||
@@ -279,12 +299,12 @@ Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int
|
||||
block->panel = pa;
|
||||
pa->runtime_flag |= PNL_ACTIVE | PNL_LAST_ADDED;
|
||||
|
||||
*open = 0;
|
||||
*r_open = false;
|
||||
|
||||
if (pa->paneltab) return pa;
|
||||
if (pa->flag & PNL_CLOSED) return pa;
|
||||
|
||||
*open = 1;
|
||||
*r_open = true;
|
||||
|
||||
return pa;
|
||||
}
|
||||
@@ -497,7 +517,7 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r
|
||||
}
|
||||
|
||||
/* panel integrated in buttonswindow, tool/property lists etc */
|
||||
void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect)
|
||||
void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, const bool show_pin)
|
||||
{
|
||||
Panel *panel = block->panel;
|
||||
rcti headrect;
|
||||
@@ -542,6 +562,21 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect)
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
/* draw optional pin icon */
|
||||
|
||||
#ifdef USE_PIN_HIDDEN
|
||||
if (show_pin && (block->panel->flag & PNL_PIN))
|
||||
#else
|
||||
if (show_pin)
|
||||
#endif
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
UI_icon_draw_aspect(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect), headrect.ymin + (5.0f / block->aspect),
|
||||
(panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
|
||||
block->aspect / U.pixelsize, 1.0f);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
/* horizontal title */
|
||||
if (!(panel->flag & PNL_CLOSEDX)) {
|
||||
ui_draw_aligned_panel_header(style, block, &headrect, 'h');
|
||||
@@ -710,6 +745,7 @@ static int uiAlignPanelStep(ScrArea *sa, ARegion *ar, float fac, int drag)
|
||||
PanelSort *ps, *panelsort, *psnext;
|
||||
int a, tot = 0, done;
|
||||
int align = panel_aligned(sa, ar);
|
||||
bool has_category_tabs = UI_panel_category_is_visible(ar);
|
||||
|
||||
/* count active, not tabbed panels */
|
||||
for (pa = ar->panels.first; pa; pa = pa->next)
|
||||
@@ -759,6 +795,12 @@ static int uiAlignPanelStep(ScrArea *sa, ARegion *ar, float fac, int drag)
|
||||
ps->pa->ofsx = 0;
|
||||
ps->pa->ofsy = -get_panel_size_y(ps->pa);
|
||||
|
||||
if (has_category_tabs) {
|
||||
if (align == BUT_VERTICAL) {
|
||||
ps->pa->ofsx += UI_PANEL_CATEGORY_MARGIN_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
for (a = 0; a < tot - 1; a++, ps++) {
|
||||
psnext = ps + 1;
|
||||
|
||||
@@ -1047,13 +1089,32 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
|
||||
|
||||
/* this function is supposed to call general window drawing too */
|
||||
/* also it supposes a block has panel, and isn't a menu */
|
||||
static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, int my, int event, int ctrl)
|
||||
static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, int my, int event, short ctrl, short alt)
|
||||
{
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
Panel *pa;
|
||||
#ifdef USE_PIN_HIDDEN
|
||||
const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->flag & PNL_PIN);
|
||||
#else
|
||||
const bool show_pin = UI_panel_category_is_visible(ar);
|
||||
#endif
|
||||
|
||||
int align = panel_aligned(sa, ar), button = 0;
|
||||
|
||||
rctf rect_drag, rect_pin;
|
||||
float rect_leftmost;
|
||||
|
||||
|
||||
/* drag and pin rect's */
|
||||
rect_drag = block->rect;
|
||||
rect_drag.xmin = block->rect.xmax - (PNL_ICON * 1.5f);
|
||||
rect_pin = rect_drag;
|
||||
if (show_pin) {
|
||||
BLI_rctf_translate(&rect_pin, -PNL_ICON, 0.0f);
|
||||
}
|
||||
rect_leftmost = rect_pin.xmin;
|
||||
|
||||
/* mouse coordinates in panel space! */
|
||||
|
||||
/* XXX weak code, currently it assumes layout style for location of widgets */
|
||||
@@ -1063,6 +1124,10 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
|
||||
button = 1;
|
||||
else if (event == AKEY)
|
||||
button = 1;
|
||||
else if (ELEM3(event, 0, RETKEY, LEFTMOUSE) && alt) {
|
||||
block->panel->flag ^= PNL_PIN;
|
||||
button = 2;
|
||||
}
|
||||
else if (block->panel->flag & PNL_CLOSEDX) {
|
||||
if (my >= block->rect.ymax) button = 1;
|
||||
}
|
||||
@@ -1071,7 +1136,7 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
|
||||
if (mx <= block->rect.xmax - 8 - PNL_ICON) button = 2;
|
||||
//else if (mx <= block->rect.xmin + 10 + 2 * PNL_ICON + 2) button = 1;
|
||||
}
|
||||
else if (mx <= block->rect.xmax - PNL_ICON - 12) {
|
||||
else if (mx < rect_leftmost) {
|
||||
button = 1;
|
||||
}
|
||||
|
||||
@@ -1112,9 +1177,402 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
|
||||
else
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
else if (mx <= (block->rect.xmax - PNL_ICON - 12) + PNL_ICON + 2) {
|
||||
else if (BLI_rctf_isect_x(&rect_drag, mx)) {
|
||||
panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
|
||||
}
|
||||
else if (show_pin && BLI_rctf_isect_x(&rect_pin, mx)) {
|
||||
block->panel->flag ^= PNL_PIN;
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
}
|
||||
|
||||
bool UI_panel_category_is_visible(ARegion *ar)
|
||||
{
|
||||
/* more then one */
|
||||
return ar->panels_category.first && ar->panels_category.first != ar->panels_category.last;
|
||||
}
|
||||
|
||||
PanelCategoryDyn *UI_panel_category_find(ARegion *ar, const char *idname)
|
||||
{
|
||||
return BLI_findstring(&ar->panels_category, idname, offsetof(PanelCategoryDyn, idname));
|
||||
}
|
||||
|
||||
PanelCategoryStack *UI_panel_category_active_find(ARegion *ar, const char *idname)
|
||||
{
|
||||
return BLI_findstring(&ar->panels_category_active, idname, offsetof(PanelCategoryStack, idname));
|
||||
}
|
||||
|
||||
const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback)
|
||||
{
|
||||
PanelCategoryStack *pc_act;
|
||||
|
||||
for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
|
||||
if (UI_panel_category_find(ar, pc_act->idname)) {
|
||||
return pc_act->idname;
|
||||
}
|
||||
}
|
||||
|
||||
if (set_fallback) {
|
||||
PanelCategoryDyn *pc_dyn = ar->panels_category.first;
|
||||
if (pc_dyn) {
|
||||
UI_panel_category_active_set(ar, pc_dyn->idname);
|
||||
return pc_dyn->idname;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void UI_panel_category_active_set(ARegion *ar, const char *idname)
|
||||
{
|
||||
ListBase *lb = &ar->panels_category_active;
|
||||
PanelCategoryStack *pc_act = UI_panel_category_active_find(ar, idname);
|
||||
|
||||
if (pc_act) {
|
||||
BLI_remlink(lb, pc_act);
|
||||
}
|
||||
else {
|
||||
pc_act = MEM_callocN(sizeof(PanelCategoryStack), __func__);
|
||||
BLI_strncpy(pc_act->idname, idname, sizeof(pc_act->idname));
|
||||
}
|
||||
|
||||
BLI_addhead(lb, pc_act);
|
||||
|
||||
|
||||
/* validate all active panels, we could do this on load,
|
||||
* they are harmless - but we should remove somewhere.
|
||||
* (addons could define own and gather cruft over time) */
|
||||
{
|
||||
PanelCategoryStack *pc_act_next;
|
||||
/* intentionally skip first */
|
||||
pc_act_next = pc_act->next;
|
||||
while ((pc_act = pc_act_next)) {
|
||||
pc_act_next = pc_act->next;
|
||||
if (!BLI_findstring(&ar->type->paneltypes, pc_act->idname, offsetof(PanelType, category))) {
|
||||
BLI_remlink(lb, pc_act);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *ar, const int x, const int y)
|
||||
{
|
||||
PanelCategoryDyn *ptd;
|
||||
|
||||
for (ptd = ar->panels_category.first; ptd; ptd = ptd->next) {
|
||||
if (BLI_rcti_isect_pt(&ptd->rect, x, y)) {
|
||||
return ptd;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PanelCategoryDyn *UI_panel_category_find_mouse_over(ARegion *ar, const wmEvent *event)
|
||||
{
|
||||
return UI_panel_category_find_mouse_over_ex(ar, event->mval[0], event->mval[1]);
|
||||
}
|
||||
|
||||
|
||||
void UI_panel_category_add(ARegion *ar, const char *name)
|
||||
{
|
||||
PanelCategoryDyn *pc_dyn = MEM_callocN(sizeof(*pc_dyn), __func__);
|
||||
BLI_addtail(&ar->panels_category, pc_dyn);
|
||||
|
||||
BLI_strncpy(pc_dyn->idname, name, sizeof(pc_dyn->idname));
|
||||
|
||||
/* 'pc_dyn->rect' must be set on draw */
|
||||
}
|
||||
|
||||
void UI_panel_category_clear_all(ARegion *ar)
|
||||
{
|
||||
BLI_freelistN(&ar->panels_category);
|
||||
}
|
||||
|
||||
/* based on uiDrawBox, check on making a version which allows us to skip some sides */
|
||||
static void ui_panel_category_draw_tab(int mode, float minx, float miny, float maxx, float maxy, float rad,
|
||||
int roundboxtype,
|
||||
const bool use_highlight, const bool use_shadow,
|
||||
const unsigned char highlight_fade[3])
|
||||
{
|
||||
float vec[4][2] = {
|
||||
{0.195, 0.02},
|
||||
{0.55, 0.169},
|
||||
{0.831, 0.45},
|
||||
{0.98, 0.805}};
|
||||
int a;
|
||||
|
||||
/* mult */
|
||||
for (a = 0; a < 4; a++) {
|
||||
mul_v2_fl(vec[a], rad);
|
||||
}
|
||||
|
||||
(void)use_shadow;
|
||||
(void)use_highlight;
|
||||
|
||||
glBegin(mode);
|
||||
|
||||
/* start with corner right-top */
|
||||
if (use_highlight) {
|
||||
if (roundboxtype & UI_CNR_TOP_RIGHT) {
|
||||
glVertex2f(maxx, maxy - rad);
|
||||
for (a = 0; a < 4; a++) {
|
||||
glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
|
||||
}
|
||||
glVertex2f(maxx - rad, maxy);
|
||||
}
|
||||
else {
|
||||
glVertex2f(maxx, maxy);
|
||||
}
|
||||
|
||||
/* corner left-top */
|
||||
if (roundboxtype & UI_CNR_TOP_LEFT) {
|
||||
glVertex2f(minx + rad, maxy);
|
||||
for (a = 0; a < 4; a++) {
|
||||
glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
|
||||
}
|
||||
glVertex2f(minx, maxy - rad);
|
||||
}
|
||||
else {
|
||||
glVertex2f(minx, maxy);
|
||||
}
|
||||
}
|
||||
|
||||
if (use_highlight && !use_shadow) {
|
||||
if (highlight_fade) {
|
||||
glColor3ubv(highlight_fade);
|
||||
}
|
||||
glVertex2f(minx, miny + rad);
|
||||
glEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
/* corner left-bottom */
|
||||
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
|
||||
glVertex2f(minx, miny + rad);
|
||||
for (a = 0; a < 4; a++) {
|
||||
glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
|
||||
}
|
||||
glVertex2f(minx + rad, miny);
|
||||
}
|
||||
else {
|
||||
glVertex2f(minx, miny);
|
||||
}
|
||||
|
||||
/* corner right-bottom */
|
||||
|
||||
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
|
||||
glVertex2f(maxx - rad, miny);
|
||||
for (a = 0; a < 4; a++) {
|
||||
glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
|
||||
}
|
||||
glVertex2f(maxx, miny + rad);
|
||||
}
|
||||
else {
|
||||
glVertex2f(maxx, miny);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw vertical tabs on the left side of the region,
|
||||
* one tab per category.
|
||||
*/
|
||||
void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
|
||||
{
|
||||
/* no tab outlines for */
|
||||
#define USE_FLAT_INACTIVE
|
||||
View2D *v2d = &ar->v2d;
|
||||
uiStyle *style = UI_GetStyle();
|
||||
const int fontid = style->widget.uifont_id;
|
||||
|
||||
PanelCategoryDyn *pc_dyn;
|
||||
const float zoom = 1.0f / ((uiBlock *)ar->uiblocks.first)->aspect;
|
||||
const int px = max_ii(1.0, (int)U.pixelsize + 0.5f);
|
||||
const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH * zoom;
|
||||
const float dpi_fac = UI_DPI_FAC;
|
||||
const int tab_v_pad_text = ((px * 3) * dpi_fac) * zoom; /* pading of tabs around text */
|
||||
const int tab_v_pad = (2 + (2 * px * dpi_fac)) * zoom; /* padding between tabs */
|
||||
const float tab_curve_radius = (px * 2) * dpi_fac;
|
||||
const int roundboxtype = UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
|
||||
bool do_scaletabs = false;
|
||||
#ifdef USE_FLAT_INACTIVE
|
||||
bool is_active_prev = false;
|
||||
#endif
|
||||
float scaletabs = 1.0f;
|
||||
/* same for all tabs */
|
||||
const int rct_xmin = v2d->mask.xmin + (3 * px);
|
||||
const int rct_xmax = v2d->mask.xmin + category_tabs_width;
|
||||
const int text_v_ofs = (rct_xmax - rct_xmin) * 0.3f;
|
||||
|
||||
int y_ofs = tab_v_pad;
|
||||
|
||||
/* Primary theme colors */
|
||||
unsigned char theme_col_back[4];
|
||||
unsigned char theme_col_text[4];
|
||||
unsigned char theme_col_text_hi[4];
|
||||
|
||||
/* Secondary theme colors */
|
||||
unsigned char theme_col_tab_bg[4];
|
||||
unsigned char theme_col_tab_inactive[4];
|
||||
unsigned char theme_col_tab_outline[4];
|
||||
unsigned char theme_col_tab_divider[4]; /* line that divides tabs from the main area */
|
||||
unsigned char theme_col_tab_highlight[4];
|
||||
unsigned char theme_col_tab_highlight_inactive[4];
|
||||
|
||||
|
||||
UI_GetThemeColor4ubv(TH_BACK, theme_col_back);
|
||||
UI_GetThemeColor4ubv(TH_TEXT, theme_col_text);
|
||||
UI_GetThemeColor4ubv(TH_TEXT_HI, theme_col_text_hi);
|
||||
|
||||
|
||||
blend_color_interpolate_byte(theme_col_tab_bg, theme_col_back, theme_col_text, 0.12f);
|
||||
blend_color_interpolate_byte(theme_col_tab_inactive, theme_col_back, theme_col_text, 0.1f);
|
||||
blend_color_interpolate_byte(theme_col_tab_outline, theme_col_back, theme_col_text, 0.3f);
|
||||
blend_color_interpolate_byte(theme_col_tab_divider, theme_col_back, theme_col_text, 0.3f);
|
||||
|
||||
blend_color_interpolate_byte(theme_col_tab_highlight, theme_col_back, theme_col_text_hi, 0.2f);
|
||||
blend_color_interpolate_byte(theme_col_tab_highlight_inactive, theme_col_tab_inactive, theme_col_text_hi, 0.12f);
|
||||
|
||||
|
||||
BLF_enable(fontid, BLF_ROTATION);
|
||||
BLF_rotation(fontid, M_PI / 2);
|
||||
//uiStyleFontSet(&style->widget);
|
||||
BLF_size(fontid, (style->widget.points * U.pixelsize) * zoom, U.dpi);
|
||||
|
||||
BLI_assert(UI_panel_category_is_visible(ar));
|
||||
|
||||
|
||||
/* calculate tab rect's and check if we need to scale down */
|
||||
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
|
||||
rcti *rct = &pc_dyn->rect;
|
||||
const char *category_id = pc_dyn->idname;
|
||||
const char *category_id_draw = IFACE_(category_id);
|
||||
const int category_width = BLF_width(fontid, category_id_draw, BLF_DRAW_STR_DUMMY_MAX);
|
||||
|
||||
rct->xmin = rct_xmin;
|
||||
rct->xmax = rct_xmax;
|
||||
|
||||
rct->ymin = v2d->mask.ymax - (y_ofs + category_width + (tab_v_pad_text * 2));
|
||||
rct->ymax = v2d->mask.ymax - (y_ofs);
|
||||
|
||||
y_ofs += category_width + tab_v_pad + (tab_v_pad_text * 2);
|
||||
}
|
||||
|
||||
if (y_ofs > BLI_rcti_size_y(&v2d->mask)) {
|
||||
scaletabs = (float)BLI_rcti_size_y(&v2d->mask) / (float)y_ofs;
|
||||
|
||||
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
|
||||
rcti *rct = &pc_dyn->rect;
|
||||
rct->ymin = ((rct->ymin - v2d->mask.ymax) * scaletabs) + v2d->mask.ymax;
|
||||
rct->ymax = ((rct->ymax - v2d->mask.ymax) * scaletabs) + v2d->mask.ymax;
|
||||
}
|
||||
|
||||
do_scaletabs = true;
|
||||
}
|
||||
|
||||
|
||||
/* begin drawing */
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
/* draw the background */
|
||||
glColor3ubv(theme_col_tab_bg);
|
||||
glRecti(v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
|
||||
|
||||
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
|
||||
const rcti *rct = &pc_dyn->rect;
|
||||
const char *category_id = pc_dyn->idname;
|
||||
const char *category_id_draw = IFACE_(category_id);
|
||||
int category_width = BLI_rcti_size_y(rct) - (tab_v_pad_text * 2);
|
||||
size_t category_draw_len = BLF_DRAW_STR_DUMMY_MAX;
|
||||
// int category_width = BLF_width(fontid, category_id_draw, BLF_DRAW_STR_DUMMY_MAX);
|
||||
|
||||
const bool is_active = STREQ(category_id, category_id_active);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
#ifdef USE_FLAT_INACTIVE
|
||||
if (is_active)
|
||||
#endif
|
||||
{
|
||||
glColor3ubv(is_active ? theme_col_back : theme_col_tab_inactive);
|
||||
ui_panel_category_draw_tab(GL_POLYGON, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
|
||||
tab_curve_radius - px, roundboxtype, true, true, NULL);
|
||||
|
||||
/* tab outline */
|
||||
glColor3ubv(theme_col_tab_outline);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px,
|
||||
tab_curve_radius, roundboxtype, true, true, NULL);
|
||||
/* tab highlight (3d look) */
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glColor3ubv(is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive);
|
||||
ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
|
||||
tab_curve_radius, roundboxtype, true, false,
|
||||
is_active ? theme_col_back : theme_col_tab_inactive);
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
||||
/* tab blackline */
|
||||
if (!is_active) {
|
||||
glColor3ubv(theme_col_tab_divider);
|
||||
glRecti(v2d->mask.xmin + category_tabs_width - px,
|
||||
rct->ymin - tab_v_pad,
|
||||
v2d->mask.xmin + category_tabs_width,
|
||||
rct->ymax + tab_v_pad);
|
||||
}
|
||||
|
||||
if (do_scaletabs) {
|
||||
category_draw_len = BLF_width_to_strlen(fontid, category_id_draw, category_draw_len,
|
||||
category_width, NULL);
|
||||
}
|
||||
|
||||
BLF_position(fontid, rct->xmax - text_v_ofs, rct->ymin + tab_v_pad_text, 0.0f);
|
||||
|
||||
glColor3ubv(theme_col_text);
|
||||
BLF_draw(fontid, category_id_draw, category_draw_len);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
/* tab blackline remaining (last tab) */
|
||||
if (pc_dyn->prev == NULL) {
|
||||
glColor3ubv(theme_col_tab_divider);
|
||||
glRecti(v2d->mask.xmin + category_tabs_width - px,
|
||||
rct->ymax + px,
|
||||
v2d->mask.xmin + category_tabs_width,
|
||||
v2d->mask.ymax);
|
||||
}
|
||||
if (pc_dyn->next == NULL) {
|
||||
glColor3ubv(theme_col_tab_divider);
|
||||
glRecti(v2d->mask.xmin + category_tabs_width - px,
|
||||
0,
|
||||
v2d->mask.xmin + category_tabs_width,
|
||||
rct->ymin);
|
||||
}
|
||||
|
||||
#ifdef USE_FLAT_INACTIVE
|
||||
/* draw line between inactive tabs */
|
||||
if (is_active == false && is_active_prev == false && pc_dyn->prev) {
|
||||
glColor3ubv(theme_col_tab_divider);
|
||||
glRecti(v2d->mask.xmin + (category_tabs_width / 5),
|
||||
rct->ymax + px,
|
||||
(v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5),
|
||||
rct->ymax + (px * 3));
|
||||
}
|
||||
|
||||
is_active_prev = is_active;
|
||||
#endif
|
||||
}
|
||||
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
|
||||
BLF_disable(fontid, BLF_ROTATION);
|
||||
|
||||
#undef USE_FLAT_INACTIVE
|
||||
}
|
||||
|
||||
/* XXX should become modal keymap */
|
||||
@@ -1125,8 +1583,27 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
|
||||
uiBlock *block;
|
||||
Panel *pa;
|
||||
int retval, mx, my;
|
||||
bool has_category_tabs = UI_panel_category_is_visible(ar);
|
||||
|
||||
retval = WM_UI_HANDLER_CONTINUE;
|
||||
|
||||
if (has_category_tabs) {
|
||||
if (event->val == KM_PRESS) {
|
||||
if (event->type == LEFTMOUSE) {
|
||||
PanelCategoryDyn *pc_dyn = UI_panel_category_find_mouse_over(ar, event);
|
||||
if (pc_dyn) {
|
||||
UI_panel_category_active_set(ar, pc_dyn->idname);
|
||||
ED_region_tag_redraw(ar);
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == WM_UI_HANDLER_BREAK) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
for (block = ar->uiblocks.last; block; block = block->prev) {
|
||||
bool inside = false, inside_header = false, inside_scale = false;
|
||||
|
||||
@@ -1171,10 +1648,10 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
|
||||
|
||||
if (pa->flag & PNL_CLOSEDY) {
|
||||
if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my))
|
||||
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl);
|
||||
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->alt);
|
||||
}
|
||||
else
|
||||
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl);
|
||||
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->alt);
|
||||
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
continue;
|
||||
@@ -1192,7 +1669,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
|
||||
/* open close on header */
|
||||
if (ELEM(event->type, RETKEY, PADENTER)) {
|
||||
if (inside_header) {
|
||||
ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl);
|
||||
ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->alt);
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
break;
|
||||
}
|
||||
@@ -1202,7 +1679,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
|
||||
if (inside_header) {
|
||||
ui_handle_panel_header(C, block, mx, my, 0, event->ctrl);
|
||||
ui_handle_panel_header(C, block, mx, my, 0, event->ctrl, event->alt);
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
break;
|
||||
}
|
||||
@@ -1213,6 +1690,13 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
|
||||
}
|
||||
|
||||
}
|
||||
else if (event->type == RIGHTMOUSE) {
|
||||
if (inside_header) {
|
||||
ui_panel_menu(C, ar, block->panel);
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (event->type == ESCKEY) {
|
||||
/*XXX 2.50*/
|
||||
#if 0
|
||||
|
||||
Reference in New Issue
Block a user