Skip to main content

FileManager

Struct FileManager 

Source
pub struct FileManager<'a, Msg> { /* private fields */ }
Expand description

A folder as a tree, with every file operation on it.

The manager is a file view, not an application: it reads the folder, draws it, does the file operations and says what happened. What opening a file means is always the application’s: on_open says a path was asked to be opened and nothing more.

The application owns a FileManagerState, hands it every FileManagerMsg and draws it here. Folders are read on a background thread, never while drawing; a read that takes longer than about 300 ms shows a small spinner on the folder’s own row, which then stays about 500 ms, so quick reads never flash one.

What it does: opening and closing folders, one and several selections, the keyboard’s own way through the rows, dragging entries onto a folder to move them, cut and paste, a new file or folder, renaming with the name checked as it is typed, and deleting behind a question. Each operation says what it changed or why it was refused, entry by entry when there were several.

The mouse works as it does in a desktop file explorer, in all three views. A click only selects; a double click or Enter opens: a file through on_open, a folder by stepping into it in the list and the icons and by opening or closing it in the tree, where its chevron and ← and → still do that with one click. Ctrl+click adds an entry to the selection or takes it out, and Shift+click selects the entries from the last one clicked. A drag from the free space draws a box, a tone over the cells it covers, and selects the entries inside it, adding to the selection when Ctrl was held. A drag from a selected entry carries the whole selection: released on a folder it moves there, or is copied there when Ctrl is held at the release, and released anywhere else it does nothing. A terminal that does not report Ctrl with the pointer always moves. A name already taken in the folder is never overwritten; the entry says why it stayed. A right click on a selected entry opens the menu of the selection, and on any other entry selects it and opens its menu. open_on(Click::Single) opens with one click instead.

What it draws: the root as the top row, so the folder itself has a place for its menu; folders then files, each in name order; an entry whose name the platform does not spell as text shown lossily rather than left out; what was cut faint until it is pasted or let go.

See FileManagerState for a whole application, and FileManagerState::confined for keeping operations inside the root.

Keys: the tree’s own (↑/↓ between rows, ←/→ and Enter to open and close a folder, Enter on a file to open it, Space to select several, Home and End, the menu key on the row the cursor is on), and a desktop file explorer’s Ctrl+X, Ctrl+C and Ctrl+V. Ctrl+X cuts the selection and Ctrl+C copies it, the entry under the cursor when nothing is selected; Ctrl+V pastes what waits into the folder the list and the icons show, and in the tree into the folder under the cursor, or the folder holding the file under it. A name already taken there is refused and said, as a paste from the menu is. The keys are the manager’s only while its rows have focus and no text is selected with the mouse: a text field keeps copying and pasting text, and selected text is what Ctrl+C copies, see NodeMut::on_clipboard. Copy and paste follow the keymap’s copy and paste.

What it can add: each row’s icon by the kind of the entry, see kind_icons, and those icons in the colours of their families, see kind_tones.

Style keys: the tree’s (list-item, tree-chevron, tree-drop, list-detail, spinner), the context menu’s and the dialog’s. Texts: quvyta.file-manager.*.

Implementations§

Source§

impl<'a, Msg: Clone + 'static> FileManager<'a, Msg>

Source

pub fn new( state: &'a FileManagerState, wrap: impl Fn(FileManagerMsg) -> Msg + 'static, ) -> Self

A manager showing state; wrap turns the manager’s messages into the application’s.

wrap is a function such as Msg::Files, or a closure that captures what it needs, such as a screen’s own conversion: move |message| convert(screen::Msg::Files(message)).

Source

pub fn root_label(self, label: impl Into<String>) -> Self

What the top row says. The name of the root folder by default; an application with a name of its own for it, such as a project’s, gives that instead.

Source

pub fn on_open(self, message: impl Fn(&Path) -> Msg + 'static) -> Self

A file was asked to be opened: a double click or Enter on its row, or a click with open_on(Click::Single).

The manager has no viewer, tab or window of its own; one application opens the path in a tab, another in a window, and a dialog returns it as the answer. Without this a double click on a file only selects it.

Source

pub fn open_on(self, click: Click) -> Self

How many clicks open an entry: Click::Double, the default, the way a desktop file explorer opens, so a click is free to select or to start a drag; or Click::Single, a click that selects and opens at once, for a picker whose rows are only ever opened.

A double click is two presses on the same entry within Click::INTERVAL. Enter opens either way, and a folder’s chevron in the tree opens and closes it with one click.

Source

pub fn on_open_terminal(self, message: impl Fn(&Path) -> Msg + 'static) -> Self

Offers “Open a terminal here” on a folder’s menu, with the folder’s path.

The wording is the framework’s, so every application says it the same way; what a terminal is stays the application’s own.

Source

pub fn menu_items( self, items: impl Fn(&str, &[String]) -> Vec<ContextItem<Msg>> + 'static, ) -> Self

The application’s own items on a row’s menu, in a group of their own between the manager’s editing items and its last, destructive one.

The row’s key comes first and what an action there acts on second: the whole selection when the row is one of several selected, the row alone otherwise, as FileManagerState::targets works it out.

Source

pub fn row_mark(self, mark: impl Fn(&str) -> RowMark + 'static) -> Self

What the application says about the look of a row, by key: a sign in a tone, a faint row, or both. See RowMark.

The manager knows names and folders; what an entry means to the application it cannot know. qcode marks an entry its backup leaves out with a warning sign and draws the row faint; a version control panel marks what is ignored. Return RowMark::new() for a row with nothing to say, which is every row by default.

A mark cannot make a row louder than the manager’s own states: a cut entry and a disabled manager stay faint whatever the mark says, because they are about what can be done rather than about what the entry is.

Source

pub fn view(self, view: FileView) -> Self

The shape the folder is drawn in: the tree it is without being asked, a list of rows with their size, date and permissions, or a grid of icons.

The tree shows folders inside folders, opened where they stand. The other two show one folder at a time: its own row comes first, so the folder has a place for its menu and a way back out of it, and stepping into a folder shows that folder instead. Which folder is shown is FileManagerState::folder, and the keys, the menus and every operation are the same in all three.

The list reads the size, the date and the permissions of a page of entries around the cursor, never of a whole folder; the tree and the icons read none.

Source

pub fn kind_icons(self, on: bool) -> Self

Draws each row’s icon by the kind of its entry: the Rust logo on a Rust file, a zipper on an archive, a folder with a branch on .git, the downloads folder in the home. Off, every row is a plain folder or file.

A person knows what a file is from its icon before reading its name. The kind comes from the name alone, see file_kind, so no file is opened to draw it; whether a file whose name says nothing may be run is the one thing read, with the folder. Outside a Nerd Font each icon is its family’s shape, so code, pictures and archives are still told apart.

The icons have no colour of their own, as the plain ones have none: they are drawn in the row’s quiet colour and take the selected row’s colour with the rest of it. A sign an application gives with row_mark says something the kind cannot, so it wins over the kind. Colours by kind are a further layer, kind_tones.

The folders of the home are found by the names the person’s language gives them, read from user-dirs.dirs once the home is on screen; user_folders gives them instead.

Source

pub fn kind_tones(self, on: bool) -> Self

Colours the icons of kind_icons by their family: folders take the accent and the files the theme’s series tones, see KindFamily::tone. A file whose kind is not known keeps the row’s colour.

The colour only repeats what the shape says, so it adds nothing where tones cannot be told apart: in sixteen colours and in ASCII it is not drawn. It does nothing without kind_icons.

Source

pub fn user_folders(self, folders: &'a UserFolders) -> Self

The home and its folders kind_icons recognises, in place of the person’s own, UserFolders::current.

For a manager showing another person’s home, or a test that means a home of its own.

Source

pub fn id(self, name: impl Into<String>) -> Self

Names the rows, so Command::focus(name) gives them the keyboard: an application that takes the person to another folder, from a list of places, a path bar or a back button, sends it so ↑ and ↓ move through the new folder at once.

The name is on the rows themselves, the tree, the list or the icons, whichever is drawn, not on the column show answers with, which holds the foot too and takes no focus. The rows are the same widget in all three views, so rows that have the keyboard keep it when the view changes, named or not.

Source

pub fn disabled(self, disabled: bool) -> Self

Draws the rows faint and answers nothing: no click, key, drag or menu, while the application has taken the folder away from the person.

Source

pub fn show<'v>(self, ui: &'v mut View<'_, Msg>) -> NodeMut<'v, Msg>

Adds the manager to ui and answers with the column that holds it, to be given a size.

The column holds the rows and, in the list and the icons, the foot under them. It takes no focus itself; id names the rows inside it, which do.

The dialog that asks for a name is added too while one is asked for; it is a layer and takes no room of its own.

Auto Trait Implementations§

§

impl<'a, Msg> !RefUnwindSafe for FileManager<'a, Msg>

§

impl<'a, Msg> !Send for FileManager<'a, Msg>

§

impl<'a, Msg> !Sync for FileManager<'a, Msg>

§

impl<'a, Msg> !UnwindSafe for FileManager<'a, Msg>

§

impl<'a, Msg> Freeze for FileManager<'a, Msg>
where Rc<dyn Fn(FileManagerMsg) -> Msg>: Freeze, Option<Rc<dyn Fn(&Path) -> Msg>>: Freeze, Option<Rc<dyn Fn(&str, &[String]) -> Vec<ContextItem<Msg>>>>: Freeze,

§

impl<'a, Msg> Unpin for FileManager<'a, Msg>
where Rc<dyn Fn(FileManagerMsg) -> Msg>: Unpin, Option<Rc<dyn Fn(&Path) -> Msg>>: Unpin, Option<Rc<dyn Fn(&str, &[String]) -> Vec<ContextItem<Msg>>>>: Unpin,

§

impl<'a, Msg> UnsafeUnpin for FileManager<'a, Msg>
where Rc<dyn Fn(FileManagerMsg) -> Msg>: UnsafeUnpin, Option<Rc<dyn Fn(&Path) -> Msg>>: UnsafeUnpin, Option<Rc<dyn Fn(&str, &[String]) -> Vec<ContextItem<Msg>>>>: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.