UI: File/Asset Browser: Improve positioning of labels and icons
While working on #136907, I noticed issues with how we position and size elements in the File/Asset Browser: - A padding meant for outside the list "tiles" was applied inside, resulting in unnecessary/unintended extra space between previews and their label, and too small vertical paddings between tiles (see screenshots in PR). - The height of text was measured based on the font size (not the actual line height) and scaled up by some arbitrary amount. Made it hard to draw multi-line text well, as done in #136907. - Icons in list views were not centered vertically. - The vertical list offset the entire list by the padding meant for tiles. Not quite sure if intentional, I think it looks better with it. But code was confusing since suddenly this extra tile padding was thrown in. Should be a separate padding. All these changes are a bit intertwined, so submitting them together. Basically this makes paddings be applied more consistently and fixes related issues, so the code makes much more sense. Pull Request: https://projects.blender.org/blender/blender/pulls/137675
This commit is contained in:
committed by
Julian Eisel
parent
826abf2ddc
commit
529ab6555c
@@ -62,7 +62,13 @@ struct FileLayout {
|
||||
int attribute_column_header_h;
|
||||
int prv_w;
|
||||
int prv_h;
|
||||
/** Extra padding to add above any files. Used for horizontal and column list views. */
|
||||
int list_padding_top;
|
||||
/** Width to draw the file's "tile" (matches the highlight background) with. `tile_border_x` will
|
||||
* be added before and after it as padding around the tile. */
|
||||
int tile_w;
|
||||
/** Height to draw the file's "tile" (matches the highlight background) with. `tile_border_y`
|
||||
* will be added above and below it as padding around the tile. */
|
||||
int tile_h;
|
||||
int tile_border_x;
|
||||
int tile_border_y;
|
||||
|
||||
@@ -421,23 +421,13 @@ static uiBut *file_add_icon_but(const SpaceFile *sfile,
|
||||
uiBut *but;
|
||||
|
||||
const int x = tile_draw_rect->xmin + padx;
|
||||
const int y = tile_draw_rect->ymax - sfile->layout->tile_border_y -
|
||||
round_fl_to_int((sfile->layout->tile_h + height) / 2.0f);
|
||||
const int y = tile_draw_rect->ymin +
|
||||
round_fl_to_int((BLI_rcti_size_y(tile_draw_rect) - height) / 2.0f);
|
||||
|
||||
if (icon < BIFICONID_LAST_STATIC) {
|
||||
/* Small built-in icon. Draw centered in given width. */
|
||||
but = uiDefIconBut(block,
|
||||
UI_BTYPE_LABEL,
|
||||
0,
|
||||
icon,
|
||||
x,
|
||||
y + 1,
|
||||
width,
|
||||
height,
|
||||
nullptr,
|
||||
0.0f,
|
||||
0.0f,
|
||||
std::nullopt);
|
||||
but = uiDefIconBut(
|
||||
block, UI_BTYPE_LABEL, 0, icon, x, y, width, height, nullptr, 0.0f, 0.0f, std::nullopt);
|
||||
/* Center the icon. */
|
||||
UI_but_drawflag_disable(but, UI_BUT_ICON_LEFT);
|
||||
}
|
||||
@@ -963,7 +953,7 @@ static void draw_background(FileLayout *layout, View2D *v2d)
|
||||
|
||||
/* alternating flat shade background */
|
||||
for (i = 2; (i <= layout->rows + 1); i += 2) {
|
||||
sy = int(v2d->cur.ymax) - layout->offset_top - i * item_height - layout->tile_border_y;
|
||||
sy = int(v2d->cur.ymax) - layout->offset_top - i * item_height - layout->list_padding_top;
|
||||
|
||||
/* Offset pattern slightly to add scroll effect. */
|
||||
sy += round_fl_to_int(item_height * (v2d->tot.ymax - v2d->cur.ymax) / item_height);
|
||||
@@ -1189,7 +1179,7 @@ static void draw_details_columns(const FileSelectParams *params,
|
||||
|
||||
if (str) {
|
||||
file_draw_string(sx + ATTRIBUTE_COLUMN_PADDING,
|
||||
tile_draw_rect->ymax - layout->tile_border_y,
|
||||
tile_draw_rect->ymax,
|
||||
IFACE_(str),
|
||||
column->width - 2 * ATTRIBUTE_COLUMN_PADDING,
|
||||
layout->tile_h,
|
||||
@@ -1212,7 +1202,32 @@ static rcti tile_draw_rect_get(const View2D *v2d, const FileLayout *layout, cons
|
||||
rect.xmin = tile_pos_x;
|
||||
rect.xmax = rect.xmin + layout->tile_w;
|
||||
rect.ymax = tile_pos_y;
|
||||
rect.ymin = rect.ymax - layout->tile_h - layout->tile_border_y;
|
||||
rect.ymin = rect.ymax - layout->tile_h;
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the boundaries to display the name label in (this isn't the rectangle of the text itself).
|
||||
*/
|
||||
static rcti text_draw_rect_get(const View2D *v2d,
|
||||
const eFileDisplayType display_type,
|
||||
const FileLayout *layout,
|
||||
const int file_idx,
|
||||
const int icon_ofs_x)
|
||||
{
|
||||
rcti tile_rect = tile_draw_rect_get(v2d, layout, file_idx);
|
||||
|
||||
rcti rect = tile_rect;
|
||||
if (display_type == FILE_IMGDISPLAY) {
|
||||
rect.ymin += round_fl_to_int(layout->prv_border_y * 0.5f);
|
||||
rect.ymax = rect.ymin + layout->textheight;
|
||||
}
|
||||
else {
|
||||
rect.xmin += icon_ofs_x + 1;
|
||||
rect.xmax = tile_rect.xmin + round_fl_to_int(layout->attribute_columns[COLUMN_NAME].width) -
|
||||
layout->tile_border_x;
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
@@ -1231,7 +1246,6 @@ void file_draw_list(const bContext *C, ARegion *region)
|
||||
int numfiles;
|
||||
int numfiles_layout;
|
||||
int offset;
|
||||
int column_width, textheight;
|
||||
int i;
|
||||
eFontStyle_Align align;
|
||||
bool do_drag;
|
||||
@@ -1262,11 +1276,6 @@ void file_draw_list(const bContext *C, ARegion *region)
|
||||
|
||||
filelist_file_cache_slidingwindow_set(files, numfiles_layout);
|
||||
|
||||
column_width = (FILE_IMGDISPLAY == params->display) ?
|
||||
layout->tile_w :
|
||||
round_fl_to_int(layout->attribute_columns[COLUMN_NAME].width);
|
||||
textheight = int(layout->textheight * 3.0 / 2.0 + 0.5);
|
||||
|
||||
align = (FILE_IMGDISPLAY == params->display) ? UI_STYLE_TEXT_CENTER : UI_STYLE_TEXT_LEFT;
|
||||
|
||||
if (numfiles > 0) {
|
||||
@@ -1323,10 +1332,7 @@ void file_draw_list(const bContext *C, ARegion *region)
|
||||
0;
|
||||
BLI_assert(i == 0 || !FILENAME_IS_CURRPAR(file->relpath));
|
||||
|
||||
rcti tile_bg_rect = tile_draw_rect;
|
||||
/* One pixel downwards, places it more in the center. */
|
||||
BLI_rcti_translate(&tile_bg_rect, 0, -U.pixelsize);
|
||||
draw_tile_background(&tile_bg_rect, colorid, shade);
|
||||
draw_tile_background(&tile_draw_rect, colorid, shade);
|
||||
}
|
||||
}
|
||||
UI_draw_roundbox_corner_set(UI_CNR_NONE);
|
||||
@@ -1383,15 +1389,18 @@ void file_draw_list(const bContext *C, ARegion *region)
|
||||
if (do_drag) {
|
||||
const uiStyle *style = UI_style_get();
|
||||
const int str_width = UI_fontstyle_string_width(&style->widget, file->name);
|
||||
const int drag_width = std::min(str_width + icon_ofs,
|
||||
int(column_width - ATTRIBUTE_COLUMN_PADDING));
|
||||
const int drag_width = std::min(
|
||||
str_width + icon_ofs,
|
||||
int(layout->attribute_columns[COLUMN_NAME].width - ATTRIBUTE_COLUMN_PADDING));
|
||||
if (drag_width > 0) {
|
||||
/* Uses full row height (tile height plus 2 * tile border padding) so there's no space
|
||||
* between rows. */
|
||||
uiBut *drag_but = uiDefBut(block,
|
||||
UI_BTYPE_LABEL,
|
||||
0,
|
||||
"",
|
||||
tile_draw_rect.xmin,
|
||||
tile_draw_rect.ymin - 1,
|
||||
tile_draw_rect.ymin - layout->tile_border_y,
|
||||
drag_width,
|
||||
layout->tile_h + layout->tile_border_y * 2,
|
||||
nullptr,
|
||||
@@ -1425,26 +1434,30 @@ void file_draw_list(const bContext *C, ARegion *region)
|
||||
(filelist_loading || icon >= BIFICONID_LAST_STATIC))
|
||||
{
|
||||
const BIFIconID type_icon = filelist_geticon_file_type(files, i, true);
|
||||
file_add_overlay_icon_but(
|
||||
block, tile_draw_rect.xmin + padx - 2, tile_draw_rect.ymin - 1, type_icon);
|
||||
file_add_overlay_icon_but(block,
|
||||
tile_draw_rect.xmin + padx - 2,
|
||||
tile_draw_rect.ymin - 2 * UI_SCALE_FAC,
|
||||
type_icon);
|
||||
}
|
||||
}
|
||||
|
||||
if (file_selflag & FILE_SEL_EDITING) {
|
||||
const short width = (params->display == FILE_IMGDISPLAY) ?
|
||||
column_width :
|
||||
layout->attribute_columns[COLUMN_NAME].width -
|
||||
ATTRIBUTE_COLUMN_PADDING;
|
||||
const rcti text_rect = text_draw_rect_get(
|
||||
v2d, eFileDisplayType(params->display), layout, i, icon_ofs);
|
||||
|
||||
if (file_selflag & FILE_SEL_EDITING) {
|
||||
const int but_height =
|
||||
(params->display == FILE_IMGDISPLAY) ?
|
||||
layout->textheight * 1.4f :
|
||||
/* Just a little smaller than the tile height, clamped to #UI_UNIT_Y as maximum. */
|
||||
std::min(short(BLI_rcti_size_y(&text_rect) - 1.0f * UI_SCALE_FAC), UI_UNIT_Y);
|
||||
uiBut *but = uiDefBut(block,
|
||||
UI_BTYPE_TEXT,
|
||||
1,
|
||||
"",
|
||||
tile_draw_rect.xmin + icon_ofs,
|
||||
tile_draw_rect.ymin + layout->tile_border_y +
|
||||
((layout->tile_h - textheight) / 2.0f) - 0.15f * UI_UNIT_X,
|
||||
width - icon_ofs,
|
||||
textheight,
|
||||
text_rect.xmin,
|
||||
text_rect.ymin,
|
||||
BLI_rcti_size_x(&text_rect),
|
||||
but_height,
|
||||
params->renamefile,
|
||||
1.0f,
|
||||
float(sizeof(params->renamefile)),
|
||||
@@ -1471,17 +1484,13 @@ void file_draw_list(const bContext *C, ARegion *region)
|
||||
|
||||
/* file_selflag might have been modified by branch above. */
|
||||
if ((file_selflag & FILE_SEL_EDITING) == 0) {
|
||||
const int txpos = (params->display == FILE_IMGDISPLAY) ? tile_draw_rect.xmin :
|
||||
tile_draw_rect.xmin + 1 + icon_ofs;
|
||||
const int typos = (params->display == FILE_IMGDISPLAY) ?
|
||||
tile_draw_rect.ymin + layout->tile_border_y + layout->textheight :
|
||||
tile_draw_rect.ymax - layout->tile_border_y;
|
||||
const int twidth = (params->display == FILE_IMGDISPLAY) ?
|
||||
column_width :
|
||||
column_width - 1 - icon_ofs - padx - layout->tile_border_x;
|
||||
const int theight = (params->display == FILE_IMGDISPLAY) ? textheight : layout->tile_h;
|
||||
|
||||
file_draw_string(txpos, typos, file->name, float(twidth), theight, align, text_col);
|
||||
file_draw_string(text_rect.xmin,
|
||||
text_rect.ymax,
|
||||
file->name,
|
||||
BLI_rcti_size_x(&text_rect),
|
||||
BLI_rcti_size_y(&text_rect),
|
||||
align,
|
||||
text_col);
|
||||
}
|
||||
|
||||
if (params->display != FILE_IMGDISPLAY) {
|
||||
|
||||
@@ -762,7 +762,8 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *region)
|
||||
}
|
||||
|
||||
const int y_item = layout->tile_h + (2 * layout->tile_border_y);
|
||||
const int y_view = int(BLI_rctf_size_y(®ion->v2d.cur)) - layout->offset_top;
|
||||
const int y_view = int(BLI_rctf_size_y(®ion->v2d.cur)) - layout->offset_top -
|
||||
layout->list_padding_top;
|
||||
const int y_over = y_item - (y_view % y_item);
|
||||
numfiles = int(float(y_view + y_over) / float(y_item));
|
||||
return numfiles * layout->flow_columns;
|
||||
@@ -784,9 +785,11 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r
|
||||
}
|
||||
|
||||
colmin = (rect->xmin) / (layout->tile_w + 2 * layout->tile_border_x);
|
||||
rowmin = (rect->ymin - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
|
||||
rowmin = (rect->ymin - layout->offset_top - layout->list_padding_top) /
|
||||
(layout->tile_h + 2 * layout->tile_border_y);
|
||||
colmax = (rect->xmax) / (layout->tile_w + 2 * layout->tile_border_x);
|
||||
rowmax = (rect->ymax - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
|
||||
rowmax = (rect->ymax - layout->offset_top - layout->list_padding_top) /
|
||||
(layout->tile_h + 2 * layout->tile_border_y);
|
||||
|
||||
if (is_inside(colmin, rowmin, layout->flow_columns, layout->rows) ||
|
||||
is_inside(colmax, rowmax, layout->flow_columns, layout->rows))
|
||||
@@ -833,7 +836,8 @@ int ED_fileselect_layout_offset(FileLayout *layout, int x, int y)
|
||||
}
|
||||
|
||||
offsetx = (x) / (layout->tile_w + 2 * layout->tile_border_x);
|
||||
offsety = (y - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
|
||||
offsety = (y - layout->offset_top - layout->list_padding_top) /
|
||||
(layout->tile_h + 2 * layout->tile_border_y);
|
||||
|
||||
if (offsetx > layout->flow_columns - 1) {
|
||||
return -1;
|
||||
@@ -879,13 +883,13 @@ void ED_fileselect_layout_tilepos(const FileLayout *layout, int tile, int *x, in
|
||||
if (layout->flag == FILE_LAYOUT_HOR) {
|
||||
*x = layout->tile_border_x +
|
||||
(tile / layout->rows) * (layout->tile_w + 2 * layout->tile_border_x);
|
||||
*y = layout->offset_top + layout->tile_border_y +
|
||||
*y = layout->offset_top + layout->list_padding_top + layout->tile_border_y +
|
||||
(tile % layout->rows) * (layout->tile_h + 2 * layout->tile_border_y);
|
||||
}
|
||||
else {
|
||||
*x = layout->tile_border_x +
|
||||
((tile) % layout->flow_columns) * (layout->tile_w + 2 * layout->tile_border_x);
|
||||
*y = layout->offset_top + layout->tile_border_y +
|
||||
*y = layout->offset_top + layout->list_padding_top + layout->tile_border_y +
|
||||
((tile) / layout->flow_columns) * (layout->tile_h + 2 * layout->tile_border_y);
|
||||
}
|
||||
}
|
||||
@@ -967,18 +971,8 @@ float file_string_width(const char *str)
|
||||
|
||||
float file_font_pointsize()
|
||||
{
|
||||
#if 0
|
||||
float s;
|
||||
char tmp[2] = "X";
|
||||
const uiStyle *style = UI_style_get();
|
||||
UI_fontstyle_set(&style->widget);
|
||||
s = BLF_height(style->widget.uifont_id, tmp);
|
||||
return style->widget.points;
|
||||
#else
|
||||
const uiStyle *style = UI_style_get();
|
||||
UI_fontstyle_set(&style->widget);
|
||||
return style->widget.points * UI_SCALE_FAC;
|
||||
#endif
|
||||
return UI_fontstyle_height_max(&style->widget);
|
||||
}
|
||||
|
||||
static void file_attribute_columns_widths(const FileSelectParams *params, FileLayout *layout)
|
||||
@@ -1047,7 +1041,6 @@ void ED_fileselect_init_layout(SpaceFile *sfile, ARegion *region)
|
||||
FileLayout *layout = nullptr;
|
||||
View2D *v2d = ®ion->v2d;
|
||||
int numfiles;
|
||||
int textheight;
|
||||
|
||||
if (sfile->layout == nullptr) {
|
||||
sfile->layout = static_cast<FileLayout *>(MEM_callocN(sizeof(FileLayout), "file_layout"));
|
||||
@@ -1058,7 +1051,7 @@ void ED_fileselect_init_layout(SpaceFile *sfile, ARegion *region)
|
||||
}
|
||||
|
||||
numfiles = filelist_files_ensure(sfile->files);
|
||||
textheight = int(file_font_pointsize());
|
||||
const int textheight = int(file_font_pointsize());
|
||||
layout = sfile->layout;
|
||||
layout->textheight = textheight;
|
||||
|
||||
@@ -1070,6 +1063,7 @@ void ED_fileselect_init_layout(SpaceFile *sfile, ARegion *region)
|
||||
layout->prv_h = (float(params->thumbnail_size) / 20.0f) * UI_UNIT_Y;
|
||||
layout->tile_border_x = pad_fac * UI_UNIT_X;
|
||||
layout->tile_border_y = pad_fac * UI_UNIT_X;
|
||||
layout->list_padding_top = 0;
|
||||
layout->prv_border_x = pad_fac * UI_UNIT_X;
|
||||
layout->prv_border_y = pad_fac * UI_UNIT_Y;
|
||||
layout->tile_w = layout->prv_w + 2 * layout->prv_border_x;
|
||||
@@ -1095,14 +1089,16 @@ void ED_fileselect_init_layout(SpaceFile *sfile, ARegion *region)
|
||||
layout->prv_w = ICON_DEFAULT_WIDTH_SCALE;
|
||||
layout->prv_h = ICON_DEFAULT_HEIGHT_SCALE;
|
||||
layout->tile_border_x = 0.4f * UI_UNIT_X;
|
||||
layout->tile_border_y = 0.1f * UI_UNIT_Y;
|
||||
layout->tile_h = textheight * 3 / 2;
|
||||
layout->tile_border_y = 0.05f * UI_UNIT_Y;
|
||||
layout->list_padding_top = 2 * layout->tile_border_y;
|
||||
layout->tile_h = round_fl_to_int(textheight * 1.4f);
|
||||
layout->width = int(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
|
||||
layout->tile_w = layout->width;
|
||||
layout->flow_columns = 1;
|
||||
layout->attribute_column_header_h = layout->tile_h * 1.2f + 2 * layout->tile_border_y;
|
||||
layout->offset_top = layout->attribute_column_header_h;
|
||||
rowcount = int(BLI_rctf_size_y(&v2d->cur) - layout->offset_top - 2 * layout->tile_border_y) /
|
||||
rowcount = int(BLI_rctf_size_y(&v2d->cur) - layout->offset_top -
|
||||
2 * layout->list_padding_top) /
|
||||
(layout->tile_h + 2 * layout->tile_border_y);
|
||||
file_attribute_columns_init(params, layout);
|
||||
|
||||
@@ -1111,15 +1107,16 @@ void ED_fileselect_init_layout(SpaceFile *sfile, ARegion *region)
|
||||
/* layout->rows can be zero if a very small area is changed to a File Browser. #124168. */
|
||||
|
||||
layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) +
|
||||
layout->tile_border_y * 2 + layout->offset_top;
|
||||
layout->list_padding_top * 2 + layout->offset_top;
|
||||
layout->flag = FILE_LAYOUT_VER;
|
||||
}
|
||||
else if (params->display == FILE_HORIZONTALDISPLAY) {
|
||||
layout->prv_w = params->list_thumbnail_size * UI_SCALE_FAC;
|
||||
layout->prv_h = params->list_thumbnail_size * UI_SCALE_FAC;
|
||||
layout->tile_border_x = 0.4f * UI_UNIT_X;
|
||||
layout->tile_border_y = 0.1f * UI_UNIT_Y;
|
||||
layout->tile_h = std::max(textheight * 3 / 2, layout->prv_h);
|
||||
layout->tile_border_y = 0.05f * UI_UNIT_Y;
|
||||
layout->list_padding_top = 2 * layout->tile_border_y;
|
||||
layout->tile_h = std::max(round_fl_to_int(textheight * 1.4f), layout->prv_h);
|
||||
layout->attribute_column_header_h = 0;
|
||||
layout->offset_top = layout->attribute_column_header_h;
|
||||
layout->height = int(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y);
|
||||
|
||||
Reference in New Issue
Block a user