diff options
Diffstat (limited to 'source/blender/editors/space_file/file_ops.c')
-rw-r--r-- | source/blender/editors/space_file/file_ops.c | 218 |
1 files changed, 129 insertions, 89 deletions
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index eb5f02b6e13..b4b51de302d 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -78,7 +78,12 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const r BLI_rctf_rcti_copy(&rect_region_fl, rect_region); + /* Okay, manipulating v2d rects here is hacky... */ + v2d->mask.ymax -= sfile->layout->offset_top; + v2d->cur.ymax -= sfile->layout->offset_top; UI_view2d_region_to_view_rctf(v2d, &rect_region_fl, &rect_view_fl); + v2d->mask.ymax += sfile->layout->offset_top; + v2d->cur.ymax += sfile->layout->offset_top; BLI_rcti_init(&rect_view, (int)(v2d->tot.xmin + rect_view_fl.xmin), @@ -190,7 +195,6 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen) const bool is_parent_dir = FILENAME_IS_PARENT(file->relpath); if (do_diropen == false) { - params->file[0] = '\0'; retval = FILE_SELECT_DIR; } /* the path is too long and we are not going up! */ @@ -235,7 +239,7 @@ static bool file_is_any_selected(struct FileList *files) int i; /* Is any file selected ? */ - for (i = 0; i < numfiles; ++i) { + for (i = 0; i < numfiles; i++) { if (filelist_entry_select_index_get(files, i, CHECK_ALL)) { return true; } @@ -262,8 +266,8 @@ static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const i cur->ymax = cur->ymin + ar->winy; } /* up */ - else if (cur->ymax < rect.ymax) { - cur->ymax = rect.ymax + layout->tile_border_y; + else if ((cur->ymax - layout->offset_top) < rect.ymax) { + cur->ymax = rect.ymax + layout->tile_border_y + layout->offset_top; cur->ymin = cur->ymax - ar->winy; } /* left - also use if tile is wider than viewbounds so view is aligned to file name */ @@ -278,7 +282,7 @@ static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const i } else { BLI_assert(cur->xmin <= rect.xmin && cur->xmax >= rect.xmax && cur->ymin <= rect.ymin && - cur->ymax >= rect.ymax); + (cur->ymax - layout->offset_top) >= rect.ymax); changed = false; } @@ -384,7 +388,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve if (result == OPERATOR_RUNNING_MODAL) { WM_operator_properties_border_to_rcti(op, &rect); - BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect); + ED_fileselect_layout_isect_rect(sfile->layout, &ar->v2d, &rect, &rect); sel = file_selection_get(C, &rect, 0); if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) { @@ -440,13 +444,13 @@ static int file_box_select_exec(bContext *C, wmOperator *op) file_deselect_all(sfile, FILE_SEL_SELECTED); } - BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect); + ED_fileselect_layout_isect_rect(sfile->layout, &ar->v2d, &rect, &rect); ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, false, false); /* unselect '..' parent entry - it's not supposed to be selected if more than * one file is selected */ - filelist_entry_select_index_set(sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); + filelist_entry_parent_select_set(sfile->files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); if (FILE_SELECT_DIR == ret) { WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); @@ -485,6 +489,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) const bool extend = RNA_boolean_get(op->ptr, "extend"); const bool fill = RNA_boolean_get(op->ptr, "fill"); const bool do_diropen = RNA_boolean_get(op->ptr, "open"); + const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); if (ar->regiontype != RGN_TYPE_WINDOW) { return OPERATOR_CANCELLED; @@ -493,7 +498,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) rect.xmin = rect.xmax = event->mval[0]; rect.ymin = rect.ymax = event->mval[1]; - if (!BLI_rcti_isect_pt(&ar->v2d.mask, rect.xmin, rect.ymin)) { + if (!ED_fileselect_layout_is_inside_pt(sfile->layout, &ar->v2d, rect.xmin, rect.ymin)) { return OPERATOR_CANCELLED; } @@ -514,14 +519,18 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (extend) { /* unselect '..' parent entry - it's not supposed to be selected if more * than one file is selected */ - filelist_entry_select_index_set( - sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); + filelist_entry_parent_select_set(sfile->files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); } - if (FILE_SELECT_DIR == ret) { + if (ret == FILE_SELECT_NOTHING) { + if (deselect_all) { + file_deselect_all(sfile, FILE_SEL_SELECTED); + } + } + else if (ret == FILE_SELECT_DIR) { WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } - else if (FILE_SELECT_FILE == ret) { + else if (ret == FILE_SELECT_FILE) { WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); } @@ -537,8 +546,8 @@ void FILE_OT_select(wmOperatorType *ot) /* identifiers */ ot->name = "Select"; - ot->description = "Activate/select file"; ot->idname = "FILE_OT_select"; + ot->description = "Handle mouse clicks to select and activate items"; /* api callbacks */ ot->invoke = file_select_invoke; @@ -556,6 +565,12 @@ void FILE_OT_select(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "open", true, "Open", "Open a directory when selecting it"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, + "deselect_all", + false, + "Deselect On Nothing", + "Deselect all when nothing under the cursor"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** @@ -580,6 +595,11 @@ static bool file_walk_select_selection_set(bContext *C, BLI_assert(params); + if (numfiles == 0) { + /* No files visible, nothing to do. */ + return false; + } + if (has_selection) { if (extend && filelist_entry_select_index_get(files, active_old, CHECK_ALL) && filelist_entry_select_index_get(files, active_new, CHECK_ALL)) { @@ -609,7 +629,7 @@ static bool file_walk_select_selection_set(bContext *C, } /* select first file */ else if (ELEM(direction, FILE_SELECT_WALK_DOWN, FILE_SELECT_WALK_RIGHT)) { - params->active_file = active = extend ? 1 : 0; + params->active_file = active = 0; } else { BLI_assert(0); @@ -626,7 +646,7 @@ static bool file_walk_select_selection_set(bContext *C, /* unselect '..' parent entry - it's not supposed to be selected if more * than one file is selected */ - filelist_entry_select_index_set(files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); + filelist_entry_parent_select_set(files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); } else { /* deselect all first */ @@ -641,11 +661,6 @@ static bool file_walk_select_selection_set(bContext *C, if (fill) { FileSelection sel = {MIN2(active, last_sel), MAX2(active, last_sel)}; - /* clamping selection to not include '..' parent entry */ - if (sel.first == 0) { - sel.first = 1; - } - /* fill selection between last and first selected file */ filelist_entries_select_index_range_set( files, &sel, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); @@ -653,6 +668,12 @@ static bool file_walk_select_selection_set(bContext *C, if (deselect) { filelist_entry_select_index_set(files, active, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); } + + /* unselect '..' parent entry - it's not supposed to be selected if more + * than one file is selected */ + if ((sel.last - sel.first) > 1) { + filelist_entry_parent_select_set(files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); + } } else { filelist_entry_select_index_set( @@ -688,10 +709,15 @@ static bool file_walk_select_do(bContext *C, /* *** get all needed files for handling selection *** */ + if (numfiles == 0) { + /* No files visible, nothing to do. */ + return false; + } + if (has_selection) { ARegion *ar = CTX_wm_region(C); FileLayout *layout = ED_fileselect_get_layout(sfile, ar); - const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->columns; + const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->flow_columns; if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_UP) || (layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_LEFT)) { @@ -718,7 +744,7 @@ static bool file_walk_select_do(bContext *C, BLI_assert(0); } - if (!IN_RANGE(active_new, 0, numfiles)) { + if (!IN_RANGE(active_new, -1, numfiles)) { if (extend) { /* extend to invalid file -> abort */ return false; @@ -1185,7 +1211,7 @@ int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my) mx -= ar->winrct.xmin; my -= ar->winrct.ymin; - if (BLI_rcti_isect_pt(&ar->v2d.mask, mx, my)) { + if (ED_fileselect_layout_is_inside_pt(sfile->layout, v2d, mx, my)) { float fx, fy; int highlight_file; @@ -1234,6 +1260,53 @@ void FILE_OT_highlight(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; } +static int file_column_sort_ui_context_invoke(bContext *C, + wmOperator *UNUSED(op), + const wmEvent *event) +{ + const ARegion *ar = CTX_wm_region(C); + SpaceFile *sfile = CTX_wm_space_file(C); + + if (file_attribute_column_header_is_inside( + &ar->v2d, sfile->layout, event->mval[0], event->mval[1])) { + const FileAttributeColumnType column_type = file_attribute_column_type_find_isect( + &ar->v2d, sfile->params, sfile->layout, event->mval[0]); + + if (column_type != COLUMN_NONE) { + const FileAttributeColumn *column = &sfile->layout->attribute_columns[column_type]; + + if (column->sort_type != FILE_SORT_NONE) { + if (sfile->params->sort == column->sort_type) { + /* Already sorting by selected column -> toggle sort invert (three state logic). */ + sfile->params->flag ^= FILE_SORT_INVERT; + } + else { + sfile->params->sort = column->sort_type; + sfile->params->flag &= ~FILE_SORT_INVERT; + } + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + } + } + } + + return OPERATOR_PASS_THROUGH; +} + +void FILE_OT_sort_column_ui_context(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Sort from Column"; + ot->description = "Change sorting to use column under cursor"; + ot->idname = "FILE_OT_sort_column_ui_context"; + + /* api callbacks */ + ot->invoke = file_column_sort_ui_context_invoke; + ot->poll = ED_operator_file_active; + + ot->flag = OPTYPE_INTERNAL; +} + int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused)) { wmWindowManager *wm = CTX_wm_manager(C); @@ -1433,14 +1506,11 @@ void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2)) bool file_draw_check_exists(SpaceFile *sfile) { if (sfile->op) { /* fails on reload */ - PropertyRNA *prop; - if ((prop = RNA_struct_find_property(sfile->op->ptr, "check_existing"))) { - if (RNA_property_boolean_get(sfile->op->ptr, prop)) { - char filepath[FILE_MAX]; - BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file); - if (BLI_is_file(filepath)) { - return true; - } + if (sfile->params && (sfile->params->flag & FILE_CHECK_EXISTING)) { + char filepath[FILE_MAX]; + BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file); + if (BLI_is_file(filepath)) { + return true; } } } @@ -1683,7 +1753,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w /* check if we are editing a name */ int edit_idx = -1; - for (i = 0; i < numfiles; ++i) { + for (i = 0; i < numfiles; i++) { if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL) & (FILE_SEL_EDITING | FILE_SEL_HIGHLIGHTED)) { edit_idx = i; @@ -1713,7 +1783,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w /* Number of items in a block (i.e. lines in a column in horizontal layout, or columns in a line * in vertical layout). */ - const int items_block_size = is_horizontal ? sfile->layout->rows : sfile->layout->columns; + const int items_block_size = is_horizontal ? sfile->layout->rows : sfile->layout->flow_columns; /* Scroll offset is the first file in the row/column we are editing in. */ if (sfile->scroll_offset == 0) { @@ -1915,6 +1985,7 @@ int file_directory_new_exec(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); ScrArea *sa = CTX_wm_area(C); + const bool do_diropen = RNA_boolean_get(op->ptr, "open"); if (!sfile->params) { BKE_report(op->reports, RPT_WARNING, "No parent directory given"); @@ -1963,9 +2034,11 @@ int file_directory_new_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* now remember file to jump into editing */ - BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE); - sfile->params->rename_flag = FILE_PARAMS_RENAME_PENDING; + /* If we don't enter the directory directly, remember file to jump into editing. */ + if (do_diropen == false) { + 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 */ @@ -1978,7 +2051,7 @@ int file_directory_new_exec(bContext *C, wmOperator *op) /* reload dir to make sure we're seeing what's in the directory */ ED_fileselect_clear(wm, sa, sfile); - if (RNA_boolean_get(op->ptr, "open")) { + if (do_diropen) { BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir)); ED_file_change_dir(C); } @@ -1998,7 +2071,7 @@ void FILE_OT_directory_new(struct wmOperatorType *ot) ot->idname = "FILE_OT_directory_new"; /* api callbacks */ - ot->invoke = WM_operator_confirm; + ot->invoke = WM_operator_confirm_or_exec; ot->exec = file_directory_new_exec; ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ @@ -2007,6 +2080,7 @@ void FILE_OT_directory_new(struct wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "open", false, "Open", "Open new directory"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + WM_operator_properties_confirm_or_exec(ot); } /* TODO This should go to BLI_path_utils. */ @@ -2075,6 +2149,10 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN SpaceFile *sfile = CTX_wm_space_file(C); if (sfile->params) { + char old_dir[sizeof(sfile->params->dir)]; + + BLI_strncpy(old_dir, sfile->params->dir, sizeof(old_dir)); + file_expand_directory(C); /* special case, user may have pasted a filepath into the directory */ @@ -2108,8 +2186,10 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN BLI_cleanup_dir(BKE_main_blendfile_path(bmain), sfile->params->dir); if (filelist_is_dir(sfile->files, sfile->params->dir)) { - /* if directory exists, enter it immediately */ - ED_file_change_dir(C); + if (!STREQ(sfile->params->dir, old_dir)) { /* Avoids flickering when nothing's changed. */ + /* if directory exists, enter it immediately */ + ED_file_change_dir(C); + } /* don't do for now because it selects entire text instead of * placing cursor at the end */ @@ -2138,6 +2218,8 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN WM_operator_properties_create_ptr(&ptr, ot); RNA_string_set(&ptr, "directory", sfile->params->dir); RNA_boolean_set(&ptr, "open", true); + /* Enable confirmation prompt, else it's too easy to accidentaly create new directories. */ + RNA_boolean_set(&ptr, "confirm", true); if (lastdir) { BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir)); @@ -2239,57 +2321,15 @@ void FILE_OT_hidedot(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ } -ARegion *file_tools_region(ScrArea *sa) +static bool file_filenum_poll(bContext *C) { - ARegion *ar, *arnew; - - if ((ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS)) != NULL) { - return ar; - } - - /* add subdiv level; after header */ - ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); - - /* is error! */ - if (ar == NULL) { - return NULL; - } - - arnew = MEM_callocN(sizeof(ARegion), "tools for file"); - BLI_insertlinkafter(&sa->regionbase, ar, arnew); - arnew->regiontype = RGN_TYPE_TOOLS; - arnew->alignment = RGN_ALIGN_LEFT; - - ar = MEM_callocN(sizeof(ARegion), "tool props for file"); - BLI_insertlinkafter(&sa->regionbase, arnew, ar); - ar->regiontype = RGN_TYPE_TOOL_PROPS; - ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV; - - return arnew; -} - -static int file_bookmark_toggle_exec(bContext *C, wmOperator *UNUSED(unused)) -{ - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = file_tools_region(sa); + SpaceFile *sfile = CTX_wm_space_file(C); - if (ar) { - ED_region_toggle_hidden(C, ar); + if (!ED_operator_file_active(C)) { + return false; } - return OPERATOR_FINISHED; -} - -void FILE_OT_bookmark_toggle(struct wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Bookmarks"; - ot->description = "Toggle bookmarks display"; - ot->idname = "FILE_OT_bookmark_toggle"; - - /* api callbacks */ - ot->exec = file_bookmark_toggle_exec; - ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ + return sfile->params && (sfile->params->flag & FILE_CHECK_EXISTING); } /** @@ -2349,7 +2389,7 @@ void FILE_OT_filenum(struct wmOperatorType *ot) /* api callbacks */ ot->exec = file_filenum_exec; - ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ + ot->poll = file_filenum_poll; /* props */ RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100); |