Add tabs as standard button types

NOTE: This is really a backend-only implementation, nothing is changed in the UI

Adds a tab button-type and the basic drawing and handling code for it.
More work needs to be done on it, but idea is to get in ready for usage in the
topbar.

Differential Revision: https://developer.blender.org/D1371
This commit is contained in:
Julian Eisel 2017-03-17 17:08:20 +01:00
parent a96008f3aa
commit 2977a8cd21
9 changed files with 194 additions and 6 deletions

View File

@ -256,6 +256,7 @@ typedef enum {
UI_BTYPE_CHECKBOX = (13 << 9), /* similar to toggle, display a 'tick' */
UI_BTYPE_CHECKBOX_N = (14 << 9),
UI_BTYPE_COLOR = (15 << 9),
UI_BTYPE_TAB = (16 << 9),
UI_BTYPE_SCROLL = (18 << 9),
UI_BTYPE_BLOCK = (19 << 9),
UI_BTYPE_LABEL = (20 << 9),

View File

@ -1463,6 +1463,7 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
break;
case UI_BTYPE_ROW:
case UI_BTYPE_LISTROW:
case UI_BTYPE_TAB:
UI_GET_BUT_VALUE_INIT(but, *value);
/* support for rna enum buts */
if (but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) {

View File

@ -110,9 +110,9 @@ enum {
bool ui_but_can_align(const uiBut *but)
{
return (
!ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE) &&
(BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f));
const bool btype_can_align = !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N,
UI_BTYPE_TAB, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE);
return (btype_can_align && (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f));
}
/**

View File

@ -464,6 +464,93 @@ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const flo
/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */
void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3])
{
VertexFormat *format = immVertexFormat();
unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
unsigned int col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
/* add a 1px offset, looks nicer */
const int minx = rect->xmin + U.pixelsize, maxx = rect->xmax - U.pixelsize;
const int miny = rect->ymin + U.pixelsize, maxy = rect->ymax - U.pixelsize;
int a;
float vec[4][2] = {
{0.195, 0.02},
{0.55, 0.169},
{0.831, 0.45},
{0.98, 0.805},
};
/* mult */
for (a = 0; a < 4; a++) {
mul_v2_fl(vec[a], rad);
}
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
immBeginAtMost(PRIM_LINE_STRIP, 25);
immAttrib3ubv(col, highlight);
/* start with corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
immVertex2f(pos, minx, maxy - rad);
for (a = 0; a < 4; a++) {
immVertex2f(pos, minx + vec[a][1], maxy - rad + vec[a][0]);
}
immVertex2f(pos, minx + rad, maxy);
}
else {
immVertex2f(pos, minx, maxy);
}
/* corner right-top */
if (roundboxtype & UI_CNR_TOP_RIGHT) {
immVertex2f(pos, maxx - rad, maxy);
for (a = 0; a < 4; a++) {
immVertex2f(pos, maxx - rad + vec[a][0], maxy - vec[a][1]);
}
immVertex2f(pos, maxx, maxy - rad);
}
else {
immVertex2f(pos, maxx, maxy);
}
immAttrib3ubv(col, highlight_fade);
/* corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
immVertex2f(pos, maxx, miny + rad);
for (a = 0; a < 4; a++) {
immVertex2f(pos, maxx - vec[a][1], miny + rad - vec[a][0]);
}
immVertex2f(pos, maxx - rad, miny);
}
else {
immVertex2f(pos, maxx, miny);
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
immVertex2f(pos, minx + rad, miny);
for (a = 0; a < 4; a++) {
immVertex2f(pos, minx + rad - vec[a][0], miny + vec[a][1]);
}
immVertex2f(pos, minx, miny + rad);
}
else {
immVertex2f(pos, minx, miny);
}
immAttrib3ubv(col, highlight);
/* back to corner left-top */
immVertex2f(pos, minx, roundboxtype & UI_CNR_TOP_LEFT ? maxy - rad : maxy);
immEnd();
immUnbindProgram();
}
void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
{
#ifdef WITH_HEADLESS

View File

@ -2094,6 +2094,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
break;
case UI_BTYPE_ROW:
case UI_BTYPE_LISTROW:
case UI_BTYPE_TAB:
ui_apply_but_ROW(C, block, but, data);
break;
case UI_BTYPE_SCROLL:
@ -3835,6 +3836,18 @@ static int ui_do_but_KEYEVT(
return WM_UI_HANDLER_CONTINUE;
}
static int ui_do_but_TAB(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_CONTINUE;
}
}
return WM_UI_HANDLER_CONTINUE;
}
static bool ui_but_is_mouse_over_icon_extra(const ARegion *region, uiBut *but, const int mouse_xy[2])
{
int x = mouse_xy[0], y = mouse_xy[1];
@ -7078,6 +7091,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_HOTKEY_EVENT:
retval = ui_do_but_HOTKEYEVT(C, but, data, event);
break;
case UI_BTYPE_TAB:
retval = ui_do_but_TAB(C, but, data, event);
break;
case UI_BTYPE_BUT_TOGGLE:
case UI_BTYPE_TOGGLE:
case UI_BTYPE_ICON_TOGGLE:

View File

@ -72,6 +72,7 @@ typedef enum {
UI_WTYPE_NUMBER,
UI_WTYPE_SLIDER,
UI_WTYPE_EXEC,
UI_WTYPE_TAB,
UI_WTYPE_TOOLTIP,
/* strings */
@ -639,6 +640,8 @@ extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, floa
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha);
void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3]);
void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);

View File

@ -1671,6 +1671,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
widget_draw_text(fstyle, wcol, but, rect);
ui_but_text_password_hide(password_str, but, true);
/* if a widget uses font shadow it has to be deactivated now */
BLF_disable(fstyle->uifont_id, BLF_SHADOW);
}
#undef UI_TEXT_CLIP_MARGIN
@ -1929,6 +1932,19 @@ static struct uiWidgetColors wcol_list_item = {
0, 0
};
struct uiWidgetColors wcol_tab = {
{255, 255, 255, 255},
{83, 83, 83, 255},
{114, 114, 114, 255},
{90, 90, 90, 255},
{0, 0, 0, 255},
{0, 0, 0, 255},
0,
0, 0
};
/* free wcol struct to play with */
static struct uiWidgetColors wcol_tmp = {
{0, 0, 0, 255},
@ -1951,6 +1967,7 @@ void ui_widget_color_init(ThemeUI *tui)
tui->wcol_tool = wcol_tool;
tui->wcol_text = wcol_text;
tui->wcol_radio = wcol_radio;
tui->wcol_tab = wcol_tab;
tui->wcol_option = wcol_option;
tui->wcol_toggle = wcol_toggle;
tui->wcol_num = wcol_num;
@ -3464,6 +3481,44 @@ static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
widgetbase_draw(&wtb, wcol);
}
static void widget_tab(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
const uiStyle *style = UI_style_get();
const float rad = 0.15f * U.widget_unit;
const int fontid = style->widget.uifont_id;
const bool is_active = (but->flag & UI_SELECT);
uiWidgetBase wtb;
unsigned char theme_col_tab_highlight[3];
/* create outline highlight colors */
if (is_active) {
interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner_sel,
(unsigned char *)wcol->outline, 0.2f);
}
else {
interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner,
(unsigned char *)wcol->outline, 0.12f);
}
widget_init(&wtb);
/* half rounded */
round_box_edges(&wtb, roundboxalign, rect, rad);
/* draw inner */
wtb.draw_outline = 0;
widgetbase_draw(&wtb, wcol);
/* draw outline (3d look) */
ui_draw_but_TAB_outline(rect, rad, theme_col_tab_highlight, (unsigned char *)wcol->inner);
/* text shadow */
BLF_enable(fontid, BLF_SHADOW);
BLF_shadow(fontid, 3, (const float[4]){1.0f, 1.0f, 1.0f, 0.25f});
BLF_shadow_offset(fontid, 0, -1);
}
static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
{
uiWidgetBase wtb;
@ -3551,6 +3606,11 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.draw = widget_roundbut;
break;
case UI_WTYPE_TAB:
wt.custom = widget_tab;
wt.wcol_theme = &btheme->tui.wcol_tab;
break;
case UI_WTYPE_TOOLTIP:
wt.wcol_theme = &btheme->tui.wcol_tooltip;
wt.draw = widget_menu_back;
@ -3805,7 +3865,11 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
if (but->block->flag & UI_BLOCK_LOOP)
wt->wcol_theme = &btheme->tui.wcol_menu_back;
break;
case UI_BTYPE_TAB:
wt = widget_type(UI_WTYPE_TAB);
break;
case UI_BTYPE_BUT_TOGGLE:
case UI_BTYPE_TOGGLE:
case UI_BTYPE_TOGGLE_N:

View File

@ -2871,7 +2871,23 @@ void init_userdef_do_versions(void)
* (keep this block even if it becomes empty).
*/
{
/* interface_widgets.c */
struct uiWidgetColors wcol_tab = {
{255, 255, 255, 255},
{83, 83, 83, 255},
{114, 114, 114, 255},
{90, 90, 90, 255},
{0, 0, 0, 255},
{0, 0, 0, 255},
0,
0, 0
};
for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
btheme->tui.wcol_tab = wcol_tab;
}
}
if (U.pixelsize == 0.0f)

View File

@ -161,7 +161,7 @@ typedef struct ThemeUI {
/* Interface Elements (buttons, menus, icons) */
uiWidgetColors wcol_regular, wcol_tool, wcol_text;
uiWidgetColors wcol_radio, wcol_option, wcol_toggle;
uiWidgetColors wcol_num, wcol_numslider;
uiWidgetColors wcol_num, wcol_numslider, wcol_tab;
uiWidgetColors wcol_menu, wcol_pulldown, wcol_menu_back, wcol_menu_item, wcol_tooltip;
uiWidgetColors wcol_box, wcol_scroll, wcol_progress, wcol_list_item, wcol_pie_menu;