File Editor: Refactor 'new dir' / renaming code.

We really do not need two 256 chars variables to hanlde renaming, a mere
pair of flags can handle the situation just as well.

Also, scroll to newly renamed item, will help when one want to find
again the directory they just added and rename.

At some point we'll probably want to refactor scrolling further (to make
it fully out of rename code/context e.g.), but for now think this will do.
This commit is contained in:
Bastien Montagne 2019-03-05 21:01:45 +01:00
parent 8858311463
commit 4326f8af08
5 changed files with 72 additions and 21 deletions

View File

@ -434,7 +434,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
const char *blendfile_path = BKE_main_blendfile_path(bmain);
BLI_make_file_string(blendfile_path, orgname, sfile->params->dir, oldname);
BLI_strncpy(filename, sfile->params->renameedit, sizeof(filename));
BLI_strncpy(filename, sfile->params->renamefile, sizeof(filename));
BLI_filename_make_safe(filename);
BLI_make_file_string(blendfile_path, newname, sfile->params->dir, filename);
@ -449,6 +449,17 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
errno ? strerror(errno) : "unknown error");
WM_report_banner_show();
}
else {
/* If rename is sucessfull, scroll to newly renamed entry. */
BLI_strncpy(sfile->params->renamefile, filename, sizeof(sfile->params->renamefile));
sfile->params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING;
if (sfile->smoothscroll_timer != NULL) {
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
}
sfile->smoothscroll_timer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER1, 1.0 / 1000.0);
sfile->scroll_offset = 0;
}
/* to make sure we show what is on disk */
ED_fileselect_clear(wm, sa, sfile);
@ -677,8 +688,8 @@ void file_draw_list(const bContext *C, ARegion *ar)
}
but = uiDefBut(block, UI_BTYPE_TEXT, 1, "", sx, sy - layout->tile_h - 0.15f * UI_UNIT_X,
width, textheight, sfile->params->renameedit, 1.0f,
(float)sizeof(sfile->params->renameedit), 0, 0, "");
width, textheight, sfile->params->renamefile, 1.0f,
(float)sizeof(sfile->params->renamefile), 0, 0, "");
UI_but_func_rename_set(but, renamebutton_cb, file);
UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */
UI_but_flag_disable(but, UI_BUT_UNDO);

View File

@ -21,9 +21,11 @@
* \ingroup spfile
*/
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLO_readfile.h"
@ -1593,13 +1595,13 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
/* Due to async nature of file listing, we may execute this code before `file_refresh()`
* editing entry is available in our listing, so we also have to handle switching to rename mode here. */
FileSelectParams *params = ED_fileselect_get_params(sfile);
if (params->renamefile[0] != '\0') {
if ((params->rename_flag & (FILE_PARAMS_RENAME_PENDING | FILE_PARAMS_RENAME_POSTSCROLL_PENDING)) != 0) {
file_params_renamefile_activate(sfile, params);
}
/* check if we are editing a name */
for (i = 0; i < numfiles; ++i) {
if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL) ) {
if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL) & (FILE_SEL_EDITING | FILE_SEL_HIGHLIGHTED)) {
edit_idx = i;
break;
}
@ -1609,7 +1611,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
if (edit_idx == -1) {
/* Do not invalidate timer if filerename is still pending, we might still be building the filelist
* and yet have to find edited entry... */
if (params->renamefile[0] == '\0') {
if (params->rename_flag == 0) {
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
sfile->smoothscroll_timer = NULL;
}
@ -1624,8 +1626,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
return OPERATOR_PASS_THROUGH;
}
offset = ED_fileselect_layout_offset(sfile->layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax);
if (offset < 0) offset = 0;
offset = max_ii(0, ED_fileselect_layout_offset(sfile->layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax));
/* scroll offset is the first file in the row/column we are editing in */
if (sfile->scroll_offset == 0) {
@ -1640,11 +1641,20 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
}
numfiles_layout = ED_fileselect_layout_numfiles(sfile->layout, ar);
/* Using margins helps avoiding scrolling to stop when target item is barely visible on one side of the screen
* (i.e. it centers a bit more the target). */
int numfiles_layout_margin = max_ii(0, numfiles_layout / 3);
/* check if we have reached our final scroll position */
if ( (sfile->scroll_offset >= offset) && (sfile->scroll_offset < offset + numfiles_layout) ) {
if ((sfile->scroll_offset >= offset + numfiles_layout_margin) &&
(sfile->scroll_offset < offset + numfiles_layout - numfiles_layout_margin)) {
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
sfile->smoothscroll_timer = NULL;
/* Postscroll (after rename has been validated by user) is done, rename process is totally finisehd, cleanup. */
if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE) != 0) {
params->renamefile[0] = '\0';
params->rename_flag = 0;
}
return OPERATOR_FINISHED;
}
@ -1812,9 +1822,13 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
/* now remember file to jump into editing */
BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE);
sfile->params->rename_flag = FILE_PARAMS_RENAME_PENDING;
/* set timer to smoothly view newly generated file */
/* max 30 frs/sec */
if (sfile->smoothscroll_timer != NULL) {
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
}
sfile->smoothscroll_timer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER1, 1.0 / 1000.0);
sfile->scroll_offset = 0;
@ -2203,8 +2217,9 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
if ((0 <= idx) && (idx < numfiles)) {
FileDirEntry *file = filelist_file(sfile->files, idx);
filelist_entry_select_index_set(sfile->files, idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
BLI_strncpy(sfile->params->renameedit, file->relpath, FILE_MAXFILE);
sfile->params->renamefile[0] = '\0';
BLI_strncpy(sfile->params->renamefile, file->relpath, FILE_MAXFILE);
/* We can skip the pending state, as we can directly set FILE_SEL_EDITING on the expected entry here. */
sfile->params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
}
ED_area_tag_redraw(sa);
}

View File

@ -738,19 +738,33 @@ void ED_fileselect_exit(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
* params->renamefile name. */
void file_params_renamefile_activate(SpaceFile *sfile, FileSelectParams *params)
{
BLI_assert(params->rename_flag != 0);
if ((params->rename_flag & (FILE_PARAMS_RENAME_ACTIVE | FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE)) != 0) {
return;
}
BLI_assert(params->renamefile[0] != '\0');
const int idx = filelist_file_findpath(sfile->files, params->renamefile);
if (idx >= 0) {
FileDirEntry *file = filelist_file(sfile->files, idx);
if (file) {
BLI_assert(file != NULL);
if ((params->rename_flag & FILE_PARAMS_RENAME_PENDING) != 0) {
filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
}
else if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_PENDING) != 0) {
filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
params->renamefile[0] = '\0';
params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE;
}
}
BLI_strncpy(sfile->params->renameedit, sfile->params->renamefile, sizeof(sfile->params->renameedit));
/* File listing is now async, do not clear renamefile if matching entry not found
* and dirlist is not finished! */
if (idx >= 0 || filelist_is_ready(sfile->files)) {
/* File listing is now async, only reset renaming if matching entry is not found
* when file listing is not done. */
else if (filelist_is_ready(sfile->files)) {
params->renamefile[0] = '\0';
params->rename_flag = 0;
}
}

View File

@ -259,7 +259,7 @@ static void file_refresh(const bContext *C, ScrArea *sa)
}
}
if (params->renamefile[0] != '\0') {
if (params->rename_flag != 0) {
file_params_renamefile_activate(sfile, params);
}

View File

@ -638,11 +638,10 @@ typedef struct FileSelectParams {
* needs to be linked in, where foo.blend/Armature need adding
*/
char dir[1090];
char _pad0[2];
char file[256];
char renamefile[256];
/** Annoying but the first is only used for initialization. */
char renameedit[256];
short rename_flag;
/** List of filetypes to filter (FILE_MAXFILE). */
char filter_glob[256];
@ -781,6 +780,18 @@ typedef enum eFileSel_Params_Flag {
FILE_GROUP_INSTANCE = (1 << 10),
} eFileSel_Params_Flag;
/* sfile->params->rename_flag */
/* Note: short flag. Defined as bitflags, but currently only used as exclusive status markers... */
typedef enum eFileSel_Params_RenameFlag {
/* Used when we only have the name of the entry we want to rename, but not yet access to its matching file entry. */
FILE_PARAMS_RENAME_PENDING = 1 << 0,
/* We are actually renaming an entry. */
FILE_PARAMS_RENAME_ACTIVE = 1 << 1,
/* Used to scroll to newly renamed entry. */
FILE_PARAMS_RENAME_POSTSCROLL_PENDING = 1 << 2,
FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE = 1 << 3,
} eFileSel_Params_RenameFlag;
/* files in filesel list: file types
* Note we could use mere values (instead of bitflags) for file types themselves,
* but since we do not lack of bytes currently...