Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <eiseljulian@gmail.com>2019-09-03 16:43:38 +0300
committerJulian Eisel <eiseljulian@gmail.com>2019-09-03 17:10:40 +0300
commitee8f69c96cba62b083fb089432cddd0bce5d08e1 (patch)
tree3be49501a9174fcf6d271ac2a3938a6304abddfb /source/blender/editors/space_file/file_draw.c
parent545f565426562604eeaa84c6f098a4dda829ba0a (diff)
UI: File Browser Design Overhaul
This is a general redesign of the File Browser GUI and interaction methods. For screenshots, check patch D5601. Main changes in short: * File Browser as floating window * New layout of regions * Popovers for view and filter options * Vertical list view with interactive column header * New and updated icons * Keymap consistency fixes * Many tweaks and fixes to the drawing of views ---- General: * The file browser now opens as temporary floating window. It closes on Esc. The header is hidden then. * When the file browser is opened as regular editor, the header remains visible. * All file browser regions are now defined in Python (the button layout). * Adjusted related operator UI names. Keymap: Keymap is now consistent with other list-based views in Blender, such as the Outliner. * Left click to select, double-click to open * Right-click context menus * Shift-click to fill selection * Ctrl-click to extend selection Operator options: These previously overlapped with the source list, which caused numerous issues with resizing and presenting many settings in a small panel area. It was also generally inconsistent with Blender. * Moved to new sidebar, which can easily be shown or hidden using a prominent Options toggle. * IO operators have new layouts to match this new sidebar, using sub-panels. This will have to be committed separately (Add-on repository). * If operators want to show the options by default, they have the option to do so (see `WM_FILESEL_SHOW_PROPS`, `hide_props_region`), otherwise they are hidden by default. General Layout: The layout has been changed to be simpler, more standard, and fits better in with Blender 2.8. * More conventional layout (file path at top, file name at the bottom, execute/cancel buttons in bottom right). * Use of popovers to group controls, and allow for more descriptive naming. * Search box is always live now, just like Outliner. Views: * Date Modified column combines both date and time, also uses user friendly strings for recent dates (i.e. "Yesterday", "Today"). * Details columns (file size, modification date/time) are now toggleable for all display types, they are not hardcoded per display type. * File sizes now show as B, KB, MB, ... rather than B, KiB, MiB, … They are now also calculated using base 10 of course. * Option to sort in inverse order. Vertical List View: * This view now used a much simpler single vertical list with columns for information. * Users can click on the headers of these columns to order by that category, and click again to reverse the ordering. Icons: * Updated icons by Jendrzych, with better centering. * Files and folders have new icons in Icon view. * Both files and folders have reworked superimposed icons that show users the file/folder type. * 3D file documents correctly use the 3d file icon, which was unused previously. * Workspaces now show their icon on Link/Append - also when listed in the Outliner. Minor Python-API breakage: * `bpy.types.FileSelectParams.display_type`: `LIST_SHORT` and `LIST_LONG` are replaced by `LIST_VERTICAL` and `LIST_HORIZONTAL`. Removes the feature where directories would automatically be created if they are entered into the file path text button, but don't exist. We were not sure if users use it enough to keep it. We can definitely bring it back. ---- //Combined effort by @billreynish, @harley, @jendrzych, my university colleague Brian Meisenheimer and myself.// Differential Revision: https://developer.blender.org/D5601 Reviewers: Brecht, Bastien
Diffstat (limited to 'source/blender/editors/space_file/file_draw.c')
-rw-r--r--source/blender/editors/space_file/file_draw.c637
1 files changed, 285 insertions, 352 deletions
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 3a6d59c1dbf..0083fc244d8 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include "BLI_blenlib.h"
+#include "BLI_fileops_types.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -77,234 +78,6 @@ static char *file_draw_tooltip_func(bContext *UNUSED(C), void *argN, const char
return BLI_strdup(dyn_tooltip);
}
-/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d.
- * The controls are laid out as follows:
- *
- * -------------------------------------------
- * | Directory input | execute |
- * -------------------------------------------
- * | Filename input | + | - | cancel |
- * -------------------------------------------
- *
- * The input widgets will stretch to fill any excess space.
- * When there isn't enough space for all controls to be shown, they are
- * hidden in this order: x/-, execute/cancel, input widgets.
- */
-void file_draw_buttons(const bContext *C, ARegion *ar)
-{
- /* Button layout. */
- const int max_x = ar->winx - 10;
- const int line1_y = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
- const int line2_y = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
- const int input_minw = 20;
- const int btn_h = UI_UNIT_Y;
- const int btn_fn_w = UI_UNIT_X;
- const int btn_minw = 80;
- const int btn_margin = 20;
- const int separator = 4;
-
- /* Additional locals. */
- char uiblockstr[32];
- int loadbutton;
- int fnumbuttons;
- int min_x = 10;
- int chan_offs = 0;
- int available_w = max_x - min_x;
- int line1_w = available_w;
- int line2_w = available_w;
-
- uiBut *but;
- uiBlock *block;
- SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
- ARegion *artmp;
- const bool is_browse_only = (sfile->op == NULL);
-
- /* Initialize UI block. */
- BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
- block = UI_block_begin(C, ar, uiblockstr, UI_EMBOSS);
-
- /* exception to make space for collapsed region icon */
- for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) {
- if (artmp->regiontype == RGN_TYPE_TOOLS && artmp->flag & RGN_FLAG_HIDDEN) {
- chan_offs = 16;
- min_x += chan_offs;
- available_w -= chan_offs;
- }
- }
-
- /* Is there enough space for the execute / cancel buttons? */
-
- if (is_browse_only) {
- loadbutton = 0;
- }
- else {
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin;
- CLAMP_MIN(loadbutton, btn_minw);
- if (available_w <= loadbutton + separator + input_minw) {
- loadbutton = 0;
- }
- }
-
- if (loadbutton) {
- line1_w -= (loadbutton + separator);
- line2_w = line1_w;
- }
-
- /* Is there enough space for file number increment/decrement buttons? */
- fnumbuttons = 2 * btn_fn_w;
- if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) {
- fnumbuttons = 0;
- }
- else {
- line2_w -= (fnumbuttons + separator);
- }
-
- /* Text input fields for directory and file. */
- if (available_w > 0) {
- const struct FileDirEntry *file = sfile->files ?
- filelist_file(sfile->files, params->active_file) :
- NULL;
- int overwrite_alert = file_draw_check_exists(sfile);
- const bool is_active_dir = file && (file->typeflag & FILE_TYPE_FOLDER);
-
- /* callbacks for operator check functions */
- UI_block_func_set(block, file_draw_check_cb, NULL, NULL);
-
- but = uiDefBut(block,
- UI_BTYPE_TEXT,
- -1,
- "",
- min_x,
- line1_y,
- line1_w - chan_offs,
- btn_h,
- params->dir,
- 0.0,
- (float)FILE_MAX,
- 0,
- 0,
- TIP_("File path"));
- UI_but_func_complete_set(but, autocomplete_directory, NULL);
- UI_but_flag_enable(but, UI_BUT_NO_UTF8);
- UI_but_flag_disable(but, UI_BUT_UNDO);
- UI_but_funcN_set(but, file_directory_enter_handle, NULL, but);
-
- /* TODO, directory editing is non-functional while a library is loaded
- * until this is properly supported just disable it. */
- if (sfile->files && filelist_lib(sfile->files)) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
-
- if ((params->flag & FILE_DIRSEL_ONLY) == 0) {
- but = uiDefBut(
- block,
- UI_BTYPE_TEXT,
- -1,
- "",
- min_x,
- line2_y,
- line2_w - chan_offs,
- btn_h,
- is_active_dir ? (char *)"" : params->file,
- 0.0,
- (float)FILE_MAXFILE,
- 0,
- 0,
- TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name")));
- UI_but_func_complete_set(but, autocomplete_file, NULL);
- UI_but_flag_enable(but, UI_BUT_NO_UTF8);
- UI_but_flag_disable(but, UI_BUT_UNDO);
- /* silly workaround calling NFunc to ensure this does not get called
- * immediate ui_apply_but_func but only after button deactivates */
- UI_but_funcN_set(but, file_filename_enter_handle, NULL, but);
-
- /* check if this overrides a file and if the operator option is used */
- if (overwrite_alert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
- }
-
- /* clear func */
- UI_block_func_set(block, NULL, NULL, NULL);
- }
-
- /* Filename number increment / decrement buttons. */
- if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) {
- UI_block_align_begin(block);
- but = uiDefIconButO(block,
- UI_BTYPE_BUT,
- "FILE_OT_filenum",
- 0,
- ICON_REMOVE,
- min_x + line2_w + separator - chan_offs,
- line2_y,
- btn_fn_w,
- btn_h,
- TIP_("Decrement the filename number"));
- RNA_int_set(UI_but_operator_ptr_get(but), "increment", -1);
-
- but = uiDefIconButO(block,
- UI_BTYPE_BUT,
- "FILE_OT_filenum",
- 0,
- ICON_ADD,
- min_x + line2_w + separator + btn_fn_w - chan_offs,
- line2_y,
- btn_fn_w,
- btn_h,
- TIP_("Increment the filename number"));
- RNA_int_set(UI_but_operator_ptr_get(but), "increment", 1);
- UI_block_align_end(block);
- }
-
- /* Execute / cancel buttons. */
- if (loadbutton) {
- const struct FileDirEntry *file = sfile->files ?
- filelist_file(sfile->files, params->active_file) :
- NULL;
- char const *str_exec;
-
- if (file && FILENAME_IS_PARENT(file->relpath)) {
- str_exec = IFACE_("Parent Directory");
- }
- else if (file && file->typeflag & FILE_TYPE_DIR) {
- str_exec = IFACE_("Open Directory");
- }
- else {
- str_exec = params->title; /* params->title is already translated! */
- }
-
- but = uiDefButO(block,
- UI_BTYPE_BUT,
- "FILE_OT_execute",
- WM_OP_EXEC_REGION_WIN,
- str_exec,
- max_x - loadbutton,
- line1_y,
- loadbutton,
- btn_h,
- "");
- /* Just a display hint. */
- UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
-
- uiDefButO(block,
- UI_BTYPE_BUT,
- "FILE_OT_cancel",
- WM_OP_EXEC_REGION_WIN,
- IFACE_("Cancel"),
- max_x - loadbutton,
- line2_y,
- loadbutton,
- btn_h,
- "");
- }
-
- UI_block_end(C, block);
- UI_block_draw(C, block);
-}
-
static void draw_tile(int sx, int sy, int width, int height, int colorid, int shade)
{
float color[4];
@@ -349,7 +122,7 @@ static void file_draw_string(int sx,
rcti rect;
char fname[FILE_MAXFILE];
- if (string[0] == '\0') {
+ if (string[0] == '\0' || width < 1) {
return;
}
@@ -362,7 +135,7 @@ static void file_draw_string(int sx,
/* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict
* (for buttons it works) */
rect.xmin = sx;
- rect.xmax = (int)(sx + ceil(width + 5.0f / UI_DPI_FAC));
+ rect.xmax = sx + round_fl_to_int(width);
rect.ymin = sy - height;
rect.ymax = sy;
@@ -404,8 +177,8 @@ static void file_draw_preview(uiBlock *block,
float scaledx, scaledy;
float scale;
int ex, ey;
- bool use_dropshadow = !is_icon && (typeflags & FILE_TYPE_IMAGE);
- float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ bool use_dropshadow = !is_icon &&
+ (typeflags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_BLENDER));
BLI_assert(imb != NULL);
@@ -442,13 +215,27 @@ static void file_draw_preview(uiBlock *block,
/* shadow */
if (use_dropshadow) {
- UI_draw_box_shadow(220, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ UI_draw_box_shadow(128, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
}
GPU_blend(true);
- /* the image */
- if (!is_icon && typeflags & FILE_TYPE_FTFONT) {
+ /* the large image */
+
+ float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ if (is_icon) {
+ /* File and Folder icons draw with lowered opacity until we add themes */
+ col[3] = 0.6f;
+ /* Use dark images if background is light */
+ float bg[3];
+ UI_GetThemeColor3fv(TH_BACK, bg);
+ if (rgb_to_grayscale(bg) > 0.5f) {
+ col[0] = 0;
+ col[1] = 0;
+ col[2] = 0;
+ }
+ }
+ else if (typeflags & FILE_TYPE_FTFONT) {
UI_GetThemeColor4fv(TH_TEXT, col);
}
@@ -477,30 +264,61 @@ static void file_draw_preview(uiBlock *block,
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- if (icon) {
- UI_icon_draw_ex((float)xco + (7 * UI_DPI_FAC),
- (float)yco + (7 * UI_DPI_FAC),
- icon,
- icon_aspect,
- 1.0f,
- 0.0f,
- NULL,
- false);
+ if (icon && (icon != ICON_FILE_FONT)) {
+ /* size of center icon is scaled to fit container and UI scale */
+ float icon_x, icon_y;
+
+ if (is_icon) {
+ const float icon_size = 16.0f / icon_aspect * U.dpi_fac;
+ float icon_opacity = MIN2(icon_aspect, 0.7);
+ uchar icon_color[4] = {255, 255, 255, 255};
+ float bg[3];
+ /* base this off theme color of file or folder later */
+ UI_GetThemeColor3fv(TH_BACK, bg);
+ if (rgb_to_grayscale(bg) > 0.5f) {
+ icon_color[0] = 0;
+ icon_color[1] = 0;
+ icon_color[2] = 0;
+ }
+ icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
+ icon_y = yco + (ey / 2.0f) - (icon_size * ((typeflags & FILE_TYPE_DIR) ? 0.78f : 0.65f));
+ UI_icon_draw_ex(
+ icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
+ }
+ else {
+ const uchar dark[4] = {0, 0, 0, 255};
+ const uchar light[4] = {255, 255, 255, 255};
+
+ /* Smaller, fainter icon for preview image thumbnail. */
+ icon_x = xco + (2.0f * UI_DPI_FAC);
+ icon_y = yco + (2.0f * UI_DPI_FAC);
+
+ UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
+ UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ }
}
/* border */
if (use_dropshadow) {
GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos_attr = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col_attr = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
- imm_draw_box_wire_2d(pos, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
+ immAttr4f(col_attr, 1.0f, 1.0f, 1.0f, 0.15f);
+ immVertex2f(pos_attr, (float)xco + 1, (float)(yco + ey));
+ immAttr4f(col_attr, 1.0f, 1.0f, 1.0f, 0.2f);
+ immVertex2f(pos_attr, (float)(xco + ex), (float)(yco + ey));
+ immAttr4f(col_attr, 0.0f, 0.0f, 0.0f, 0.2f);
+ immVertex2f(pos_attr, (float)(xco + ex), (float)yco + 1);
+ immAttr4f(col_attr, 0.0f, 0.0f, 0.0f, 0.3f);
+ immVertex2f(pos_attr, (float)xco + 1, (float)yco + 1);
+ immEnd();
immUnbindProgram();
}
but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL);
- UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
/* dragregion */
if (drag) {
@@ -557,6 +375,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
static void draw_background(FileLayout *layout, View2D *v2d)
{
+ const int item_height = layout->tile_h + (2 * layout->tile_border_y);
int i;
int sy;
@@ -565,9 +384,11 @@ static void draw_background(FileLayout *layout, View2D *v2d)
immUniformThemeColorShade(TH_BACK, -7);
/* alternating flat shade background */
- for (i = 0; (i <= layout->rows); i += 2) {
- sy = (int)v2d->cur.ymax - i * (layout->tile_h + 2 * layout->tile_border_y) -
- layout->tile_border_y;
+ for (i = 2; (i <= layout->rows + 1); i += 2) {
+ sy = (int)v2d->cur.ymax - layout->offset_top - i * item_height - layout->tile_border_y;
+
+ /* Offsett pattern slightly to add scroll effect. */
+ sy += round_fl_to_int(item_height * (v2d->tot.ymax - v2d->cur.ymax) / item_height);
immRectf(pos,
v2d->cur.xmin,
@@ -632,6 +453,176 @@ static void draw_dividers(FileLayout *layout, View2D *v2d)
}
}
+static void draw_columnheader_background(const FileLayout *layout, const View2D *v2d)
+{
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, 11);
+
+ immRectf(pos,
+ v2d->cur.xmin,
+ v2d->cur.ymax - layout->attribute_column_header_h,
+ v2d->cur.xmax,
+ v2d->cur.ymax);
+
+ immUnbindProgram();
+}
+
+static void draw_columnheader_columns(const FileSelectParams *params,
+ FileLayout *layout,
+ const View2D *v2d,
+ const uchar text_col[4])
+{
+ const float divider_pad = 0.2 * layout->attribute_column_header_h;
+ int sx = v2d->cur.xmin, sy = v2d->cur.ymax;
+
+ for (FileAttributeColumnType column_type = 0; column_type < ATTRIBUTE_COLUMN_MAX;
+ column_type++) {
+ if (!file_attribute_column_type_enabled(params, column_type)) {
+ continue;
+ }
+ const FileAttributeColumn *column = &layout->attribute_columns[column_type];
+
+ /* Active sort type triangle */
+ if (params->sort == column->sort_type) {
+ float tri_color[4];
+
+ rgba_uchar_to_float(tri_color, text_col);
+ UI_draw_icon_tri(sx + column->width - (0.3f * U.widget_unit) -
+ ATTRIBUTE_COLUMN_PADDING / 2.0f,
+ sy + (0.1f * U.widget_unit) - (layout->attribute_column_header_h / 2),
+ (params->flag & FILE_SORT_INVERT) ? 't' : 'v',
+ tri_color);
+ }
+
+ file_draw_string(sx + ATTRIBUTE_COLUMN_PADDING,
+ sy - layout->tile_border_y,
+ IFACE_(column->name),
+ column->width - 2 * ATTRIBUTE_COLUMN_PADDING,
+ layout->attribute_column_header_h - layout->tile_border_y,
+ UI_STYLE_TEXT_LEFT,
+ text_col);
+
+ /* Separator line */
+ if (column_type != COLUMN_NAME) {
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, -10);
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, sx - 1, sy - divider_pad);
+ immVertex2f(pos, sx - 1, sy - layout->attribute_column_header_h + divider_pad);
+ immEnd();
+ immUnbindProgram();
+ }
+
+ sx += column->width;
+ }
+
+ /* Vertical separator lines line */
+ {
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, -10);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, v2d->cur.xmin, sy);
+ immVertex2f(pos, v2d->cur.xmax, sy);
+ immVertex2f(pos, v2d->cur.xmin, sy - layout->attribute_column_header_h);
+ immVertex2f(pos, v2d->cur.xmax, sy - layout->attribute_column_header_h);
+ immEnd();
+ immUnbindProgram();
+ }
+}
+
+/**
+ * Updates the stat string stored in file->entry if necessary.
+ */
+static const char *filelist_get_details_column_string(FileAttributeColumnType column,
+ const FileDirEntry *file,
+ const bool small_size,
+ const bool update_stat_strings)
+{
+ switch (column) {
+ case COLUMN_DATETIME:
+ if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
+ if ((file->entry->datetime_str[0] == '\0') || update_stat_strings) {
+ char date[FILELIST_DIRENTRY_DATE_LEN], time[FILELIST_DIRENTRY_TIME_LEN];
+ bool is_today, is_yesterday;
+
+ BLI_filelist_entry_datetime_to_string(
+ NULL, file->entry->time, small_size, time, date, &is_today, &is_yesterday);
+
+ if (is_today || is_yesterday) {
+ BLI_strncpy(date, is_today ? N_("Today") : N_("Yesterday"), sizeof(date));
+ }
+ BLI_snprintf(
+ file->entry->datetime_str, sizeof(file->entry->datetime_str), "%s %s", date, time);
+ }
+
+ return file->entry->datetime_str;
+ }
+ break;
+ case COLUMN_SIZE:
+ if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
+ !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
+ if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
+ BLI_filelist_entry_size_to_string(
+ NULL, file->entry->size, small_size, file->entry->size_str);
+ }
+
+ return file->entry->size_str;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static void draw_details_columns(const FileSelectParams *params,
+ const FileLayout *layout,
+ const FileDirEntry *file,
+ const int pos_x,
+ const int pos_y,
+ const uchar text_col[4])
+{
+ const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
+ const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size);
+ int sx = pos_x - layout->tile_border_x - (UI_UNIT_X * 0.1f), sy = pos_y;
+
+ for (FileAttributeColumnType column_type = 0; column_type < ATTRIBUTE_COLUMN_MAX;
+ column_type++) {
+ const FileAttributeColumn *column = &layout->attribute_columns[column_type];
+
+ /* Name column is not a detail column (should already be drawn), always skip here. */
+ if (column_type == COLUMN_NAME) {
+ sx += column->width;
+ continue;
+ }
+ if (!file_attribute_column_type_enabled(params, column_type)) {
+ continue;
+ }
+
+ const char *str = filelist_get_details_column_string(
+ column_type, file, small_size, update_stat_strings);
+
+ if (str) {
+ file_draw_string(sx + ATTRIBUTE_COLUMN_PADDING,
+ sy - layout->tile_border_y,
+ IFACE_(str),
+ column->width - 2 * ATTRIBUTE_COLUMN_PADDING,
+ layout->tile_h,
+ column->text_align,
+ text_col);
+ }
+
+ sx += column->width;
+ }
+}
+
void file_draw_list(const bContext *C, ARegion *ar)
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -652,18 +643,14 @@ void file_draw_list(const bContext *C, ARegion *ar)
bool is_icon;
eFontStyle_Align align;
bool do_drag;
- int column_space = 0.6f * UI_UNIT_X;
unsigned char text_col[4];
- const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
- const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size);
- const float thumb_icon_aspect = sqrtf(64.0f / (float)(params->thumbnail_size));
+ const bool draw_columnheader = (params->display == FILE_VERTICALDISPLAY);
+ const float thumb_icon_aspect = MIN2(64.0f / (float)(params->thumbnail_size), 1.0f);
numfiles = filelist_files_ensure(files);
if (params->display != FILE_IMGDISPLAY) {
-
draw_background(layout, v2d);
-
draw_dividers(layout, v2d);
}
@@ -679,13 +666,14 @@ void file_draw_list(const bContext *C, ARegion *ar)
numfiles_layout += layout->rows;
}
else {
- numfiles_layout += layout->columns;
+ numfiles_layout += layout->flow_columns;
}
filelist_file_cache_slidingwindow_set(files, numfiles_layout);
- textwidth = (FILE_IMGDISPLAY == params->display) ? layout->tile_w :
- (int)layout->column_widths[COLUMN_NAME];
+ textwidth = (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;
@@ -719,11 +707,16 @@ void file_draw_list(const bContext *C, ARegion *ar)
BLF_batch_draw_begin();
+ UI_GetThemeColor4ubv(TH_TEXT, text_col);
+
for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
unsigned int file_selflag;
char path[FILE_MAX_LIBEXTRA];
+ int padx = 0.1f * UI_UNIT_X;
+ int icon_ofs = 0;
+
ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
- sx += (int)(v2d->tot.xmin + 0.1f * UI_UNIT_X);
+ sx += (int)(v2d->tot.xmin + padx);
sy = (int)(v2d->tot.ymax - sy);
file = filelist_file(files, i);
@@ -737,15 +730,14 @@ void file_draw_list(const bContext *C, ARegion *ar)
int colorid = (file_selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK;
int shade = (params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ? 35 :
0;
+ const short width = ELEM(params->display, FILE_VERTICALDISPLAY, FILE_HORIZONTALDISPLAY) ?
+ layout->tile_w - (2 * padx) :
+ layout->tile_w;
BLI_assert(i == 0 || !FILENAME_IS_CURRPAR(file->relpath));
- draw_tile(sx,
- sy - 1,
- layout->tile_w + 4,
- sfile->layout->tile_h + layout->tile_border_y,
- colorid,
- shade);
+ draw_tile(
+ sx, sy - 1, width, sfile->layout->tile_h + layout->tile_border_y, colorid, shade);
}
}
UI_draw_roundbox_corner_set(UI_CNR_NONE);
@@ -778,38 +770,28 @@ void file_draw_list(const bContext *C, ARegion *ar)
file_draw_icon(block,
path,
sx,
- sy - (UI_UNIT_Y / 6),
+ sy - layout->tile_border_y,
filelist_geticon(files, i, true),
ICON_DEFAULT_WIDTH_SCALE,
ICON_DEFAULT_HEIGHT_SCALE,
do_drag);
- sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
+ icon_ofs += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
}
- UI_GetThemeColor4ubv(TH_TEXT, text_col);
-
if (file_selflag & FILE_SEL_EDITING) {
uiBut *but;
- short width;
-
- if (params->display == FILE_SHORTDISPLAY) {
- width = layout->tile_w - (ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X);
- }
- else if (params->display == FILE_LONGDISPLAY) {
- width = layout->column_widths[COLUMN_NAME] + (column_space * 3.5f);
- }
- else {
- BLI_assert(params->display == FILE_IMGDISPLAY);
- width = textwidth;
- }
+ const short width = (params->display == FILE_IMGDISPLAY) ?
+ textwidth :
+ layout->attribute_columns[COLUMN_NAME].width -
+ ATTRIBUTE_COLUMN_PADDING;
but = uiDefBut(block,
UI_BTYPE_TEXT,
1,
"",
- sx,
+ sx + icon_ofs,
sy - layout->tile_h - 0.15f * UI_UNIT_X,
- width,
+ width - icon_ofs,
textheight,
sfile->params->renamefile,
1.0f,
@@ -825,74 +807,19 @@ void file_draw_list(const bContext *C, ARegion *ar)
sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL);
}
}
-
- if (!(file_selflag & FILE_SEL_EDITING)) {
- int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight :
- sy;
- file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align, text_col);
- }
-
- sx += (int)layout->column_widths[COLUMN_NAME] + column_space;
- if (params->display == FILE_SHORTDISPLAY) {
- if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
- !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
- if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
- BLI_filelist_entry_size_to_string(
- NULL, file->entry->size, small_size, file->entry->size_str);
- }
- file_draw_string(sx,
- sy,
- file->entry->size_str,
- layout->column_widths[COLUMN_SIZE],
- layout->tile_h,
- align,
- text_col);
- }
- sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
+ else {
+ const int txpos = (params->display == FILE_IMGDISPLAY) ? sx : sx + 1 + icon_ofs;
+ const int typos = (params->display == FILE_IMGDISPLAY) ?
+ sy - layout->tile_h + layout->textheight :
+ sy - layout->tile_border_y;
+ const int twidth = (params->display == FILE_IMGDISPLAY) ?
+ textwidth :
+ textwidth - 1 - icon_ofs - padx - layout->tile_border_x;
+ file_draw_string(txpos, typos, file->name, (float)twidth, textheight, align, text_col);
}
- else if (params->display == FILE_LONGDISPLAY) {
- if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
- if ((file->entry->date_str[0] == '\0') || update_stat_strings) {
- BLI_filelist_entry_datetime_to_string(
- NULL, file->entry->time, small_size, file->entry->time_str, file->entry->date_str);
- }
- file_draw_string(sx,
- sy,
- file->entry->date_str,
- layout->column_widths[COLUMN_DATE],
- layout->tile_h,
- align,
- text_col);
- sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
- file_draw_string(sx,
- sy,
- file->entry->time_str,
- layout->column_widths[COLUMN_TIME],
- layout->tile_h,
- align,
- text_col);
- sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
- }
- else {
- sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
- sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
- }
- if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
- !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
- if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
- BLI_filelist_entry_size_to_string(
- NULL, file->entry->size, small_size, file->entry->size_str);
- }
- file_draw_string(sx,
- sy,
- file->entry->size_str,
- layout->column_widths[COLUMN_SIZE],
- layout->tile_h,
- align,
- text_col);
- }
- sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
+ if (params->display != FILE_IMGDISPLAY) {
+ draw_details_columns(params, layout, file, sx, sy, text_col);
}
}
@@ -901,5 +828,11 @@ void file_draw_list(const bContext *C, ARegion *ar)
UI_block_end(C, block);
UI_block_draw(C, block);
+ /* Draw last, on top of file list. */
+ if (draw_columnheader) {
+ draw_columnheader_background(layout, v2d);
+ draw_columnheader_columns(params, layout, v2d, text_col);
+ }
+
layout->curr_size = params->thumbnail_size;
}