diff options
8 files changed, 114 insertions, 11 deletions
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 949cfcae2b1..577448554b7 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -2011,7 +2011,6 @@ def km_file_browser_main(params): # operator (i.e. in regular editor mode). ("file.select", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, {"properties": [("open", True), ("deselect_all", not params.legacy)]}), - ("file.refresh", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None), ("file.select", {"type": 'LEFTMOUSE', "value": 'PRESS'}, {"properties": [("open", False), ("deselect_all", not params.legacy)]}), ("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True}, @@ -2053,6 +2052,7 @@ def km_file_browser_main(params): {"properties": [("mode", 'SUB')]}), ("file.highlight", {"type": 'MOUSEMOVE', "value": 'ANY', "any": True}, None), ("file.sort_column_ui_context", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None), + ("file.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None), ]) return keymap diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index 234781b7bc8..214b8f98ff6 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -1309,6 +1309,7 @@ def km_file_browser_main(params): {"properties": [("mode", 'ADD')]}), ("file.highlight", {"type": 'MOUSEMOVE', "value": 'ANY', "any": True}, None), ("file.sort_column_ui_context", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None), + ("file.view_selected", {"type": 'F', "value": 'PRESS'}, None), ]) return keymap diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index ef4f47c9399..b236b2ee7cf 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -494,6 +494,7 @@ class FILEBROWSER_MT_view(Menu): layout.prop(st, "show_region_toolbar", text="Source List") layout.prop(st, "show_region_ui", text="File Path") + layout.operator("file.view_selected") layout.separator() diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index deb32812f44..309b280177c 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -75,6 +75,7 @@ void FILE_OT_rename(struct wmOperatorType *ot); void FILE_OT_smoothscroll(struct wmOperatorType *ot); void FILE_OT_filepath_drop(struct wmOperatorType *ot); void FILE_OT_start_filter(struct wmOperatorType *ot); +void FILE_OT_view_selected(struct wmOperatorType *ot); void file_directory_enter_handle(bContext *C, void *arg_unused, void *arg_but); void file_filename_enter_handle(bContext *C, void *arg_unused, void *arg_but); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 985c92f19b6..b82290205c7 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -256,6 +256,33 @@ static bool file_is_any_selected(struct FileList *files) return false; } +static FileSelection file_current_selection_range_get(struct FileList *files) +{ + const int numfiles = filelist_files_ensure(files); + FileSelection selection = {-1, -1}; + + /* Iterate over the files once but in two loops, one to find the first selected file, and the + * other to find the last. */ + + int file_index; + for (file_index = 0; file_index < numfiles; file_index++) { + if (filelist_entry_is_selected(files, file_index)) { + /* First selected entry found. */ + selection.first = file_index; + break; + } + } + + for (; file_index < numfiles; file_index++) { + if (filelist_entry_is_selected(files, file_index)) { + selection.last = file_index; + /* Keep looping, we may find more selected files. */ + } + } + + return selection; +} + /** * If \a file is outside viewbounds, this adjusts view to make sure it's inside */ @@ -299,6 +326,24 @@ static void file_ensure_inside_viewbounds(ARegion *region, SpaceFile *sfile, con } } +static void file_ensure_selection_inside_viewbounds(ARegion *region, + SpaceFile *sfile, + FileSelection *sel) +{ + const FileLayout *layout = ED_fileselect_get_layout(sfile, region); + + if (((layout->flag & FILE_LAYOUT_HOR) && region->winx <= (1.2f * layout->tile_w)) && + ((layout->flag & FILE_LAYOUT_VER) && region->winy <= (2.0f * layout->tile_h))) { + return; + } + + /* Adjust view to display selection. Doing iterations for first and last + * selected item makes view showing as much of the selection possible. + * Not really useful if tiles are (almost) bigger than viewbounds though. */ + file_ensure_inside_viewbounds(region, sfile, sel->last); + file_ensure_inside_viewbounds(region, sfile, sel->first); +} + static FileSelect file_select( bContext *C, const rcti *rect, FileSelType select, bool fill, bool do_diropen) { @@ -330,16 +375,7 @@ static FileSelect file_select( } else if (sel.last >= 0) { ARegion *region = CTX_wm_region(C); - const FileLayout *layout = ED_fileselect_get_layout(sfile, region); - - /* Adjust view to display selection. Doing iterations for first and last - * selected item makes view showing as much of the selection possible. - * Not really useful if tiles are (almost) bigger than viewbounds though. */ - if (((layout->flag & FILE_LAYOUT_HOR) && region->winx > (1.2f * layout->tile_w)) || - ((layout->flag & FILE_LAYOUT_VER) && region->winy > (2.0f * layout->tile_h))) { - file_ensure_inside_viewbounds(region, sfile, sel.last); - file_ensure_inside_viewbounds(region, sfile, sel.first); - } + file_ensure_selection_inside_viewbounds(region, sfile, &sel); } /* update operator for name change event */ @@ -926,6 +962,55 @@ void FILE_OT_select_all(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Select All Operator + * \{ */ + +static int file_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceFile *sfile = CTX_wm_space_file(C); + FileSelection sel = file_current_selection_range_get(sfile->files); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + + if (sel.first == -1 && sel.last == -1 && params->active_file == -1) { + /* Nothing was selected. */ + return OPERATOR_CANCELLED; + } + + /* Extend the selection area with the active file, as it may not be selected but still is + * important to have in view. */ + if (sel.first == -1 || params->active_file < sel.first) { + sel.first = params->active_file; + } + if (sel.last == -1 || params->active_file > sel.last) { + sel.last = params->active_file; + } + + ScrArea *area = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + file_ensure_selection_inside_viewbounds(region, sfile, &sel); + + file_draw_check(C); + WM_event_add_mousemove(CTX_wm_window(C)); + ED_area_tag_redraw(area); + + return OPERATOR_FINISHED; +} + +void FILE_OT_view_selected(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Frame Selected"; + ot->description = "Scroll the selected files into view"; + ot->idname = "FILE_OT_view_selected"; + + /* api callbacks */ + ot->exec = file_view_selected_exec; + ot->poll = ED_operator_file_active; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Select Bookmark Operator * \{ */ diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 757ec7c741f..f5ec9a0e8a1 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -2701,6 +2701,19 @@ uint filelist_entry_select_index_get(FileList *filelist, const int index, FileCh return 0; } +bool filelist_entry_is_selected(FileList *filelist, const int index) +{ + BLI_assert(index >= 0 && index < filelist->filelist.nbr_entries_filtered); + FileListInternEntry *intern_entry = filelist->filelist_intern.filtered[index]; + + /* BLI_ghash_lookup returns NULL if not found, which gets mapped to 0, which gets mapped to + * "not selected". */ + const uint selection_state = POINTER_AS_UINT( + BLI_ghash_lookup(filelist->selection_state, intern_entry->uuid)); + + return selection_state != 0; +} + /** * Set selection of the '..' parent entry, but only if it's actually visible. */ diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 7eecd7a05de..9eb70dd8437 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -128,6 +128,7 @@ unsigned int filelist_entry_select_get(struct FileList *filelist, unsigned int filelist_entry_select_index_get(struct FileList *filelist, const int index, FileCheckType check); +bool filelist_entry_is_selected(struct FileList *filelist, const int index); void filelist_entry_parent_select_set(struct FileList *filelist, FileSelType select, unsigned int flag, diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 2c9c2688e88..4373bd88473 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -659,6 +659,7 @@ static void file_operatortypes(void) WM_operatortype_append(FILE_OT_smoothscroll); WM_operatortype_append(FILE_OT_filepath_drop); WM_operatortype_append(FILE_OT_start_filter); + WM_operatortype_append(FILE_OT_view_selected); } /* NOTE: do not add .blend file reading on this level */ |