diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-12-16 20:21:55 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-12-16 20:55:45 +0400 |
commit | a621d1e48828d02a5e097dcfc218cc11d149e75f (patch) | |
tree | 3cb9594e0b70fe0ac46d7fc22c05b1ec9b977c72 /source/blender/editors/interface | |
parent | 2231b565f011e984d4ee6eeb33a80567b404e032 (diff) |
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.
Diffstat (limited to 'source/blender/editors/interface')
-rw-r--r-- | source/blender/editors/interface/interface.c | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 19 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 11 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_panel.c | 526 |
4 files changed, 527 insertions, 31 deletions
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 0b86743b622..b57b293e9ef 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1209,7 +1209,7 @@ void uiDrawBlock(const bContext *C, uiBlock *block) if (block->flag & UI_BLOCK_LOOP) ui_draw_menu_back(&style, block, &rect); else if (block->panel) - ui_draw_aligned_panel(&style, block, &rect); + ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar)); /* widgets */ for (but = block->buttons.first; but; but = but->next) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 61761d7db41..f0d064a7a77 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -5272,6 +5272,25 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) uiPupBlock(C, menu_add_shortcut, but); } +/** + * menu to chow when right clicking on the panel header + */ +void ui_panel_menu(bContext *C, ARegion *ar, Panel *pa) +{ + bScreen *sc = CTX_wm_screen(C); + PointerRNA ptr; + uiPopupMenu *pup; + uiLayout *layout; + + RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr); + + pup = uiPupMenuBegin(C, IFACE_("Panel"), ICON_NONE); + layout = uiPupMenuLayout(pup); + if (UI_panel_category_is_visible(ar)) { + uiItemR(layout, &ptr, "use_pin", 0, "Pin" UI_SEP_CHAR_S "Alt+Left Mouse", ICON_NONE); + } + uiPupMenuEnd(C, pup); +} static bool ui_but_menu(bContext *C, uiBut *but) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index cbc1cd2cbbd..13998e03a24 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -124,14 +124,6 @@ enum { #define PNL_GRID (UI_UNIT_Y / 5) /* 4 default */ #define PNL_HEADER (UI_UNIT_Y + 4) /* 24 default */ -/* panel->flag */ -#define PNL_SELECT 1 -#define PNL_CLOSEDX 2 -#define PNL_CLOSEDY 4 -#define PNL_CLOSED 6 -/*#define PNL_TABBED 8*/ /*UNUSED*/ -#define PNL_OVERLAP 16 - /* Button text selection: * extension direction, selextend, inside ui_do_but_TEX */ #define EXTEND_LEFT 1 @@ -505,7 +497,7 @@ struct AutoComplete; /* interface_panel.c */ extern int ui_handler_panel_region(struct bContext *C, const struct wmEvent *event, struct ARegion *ar); -extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, const rcti *rect); +extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, const rcti *rect, const bool show_pin); /* interface_draw.c */ extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select); @@ -531,6 +523,7 @@ extern bool ui_button_is_active(struct ARegion *ar); extern int ui_button_open_menu_direction(uiBut *but); extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, int restore); void ui_button_clipboard_free(void); +void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa); /* interface_widgets.c */ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 9759614dd4c..be6cbaf7b72 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -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 |