pub enum SelectionMode {
Replace,
Toggle,
ExtendRange,
}Expand description
How an incoming selection event composes with the existing set.
The three modes cover the three standard click idioms:
| Mode | Effect on the selected set |
|---|---|
SelectionMode::Replace | Clear everything; the path becomes the single selection. |
SelectionMode::Toggle | Add the path if absent; remove it if present. |
SelectionMode::ExtendRange | Select every visible row between the anchor and the target, inclusive. The anchor is unchanged. |
Variants§
Replace
Clear any existing selection; the new path becomes the only selected entry. This is what a plain left-click produces from the built-in view.
Toggle
Add the path to the selection if it isn’t already there, remove it otherwise. The anchor used for range extension is updated to point at this path regardless of whether it was added or removed.
ExtendRange
Select every visible row between the current anchor and the target path, inclusive, using the row order the widget renders. The anchor itself is not moved — successive range extensions all use the same starting pivot, which matches how Windows Explorer, macOS Finder, and VS Code behave.
If the anchor is unset, or if either the anchor or the
target is not currently visible (filtered out, ancestor
collapsed, not yet loaded), the tree falls back to
SelectionMode::Replace semantics using just the target.
Implementations§
Source§impl SelectionMode
impl SelectionMode
Sourcepub fn from_modifiers(modifiers: Modifiers) -> Self
pub fn from_modifiers(modifiers: Modifiers) -> Self
Pick the mode implied by the active modifier keys.
The mapping is:
Shift→SelectionMode::ExtendRangeCtrlorLogo(Command on macOS / Windows key elsewhere) →SelectionMode::Toggle- otherwise →
SelectionMode::Replace
Shift wins over Ctrl / Logo when both are held. A
future release may distinguish “extend with toggle” (the
Windows Explorer Ctrl+Shift+click behavior) with a fourth
variant; for now Ctrl+Shift+click behaves as Shift-click.
§Example
use iced::keyboard::Modifiers;
use iced_swdir_tree::SelectionMode;
// In your update handler, when you've received a click event
// and have tracked the current modifier state:
let mode = SelectionMode::from_modifiers(current_modifiers);
// Forward a rewritten Selected event to the widget.Examples found in repository?
68 fn update(&mut self, message: Message) -> Task<Message> {
69 match message {
70 // Intercept plain-click `Selected` events and rewrite the
71 // mode based on the current modifier state. The built-in
72 // view always produces Replace; keyboard events produce
73 // the right mode already (handled by handle_key).
74 Message::Tree(DirectoryTreeEvent::Selected(path, is_dir, _from_view)) => {
75 let mode = SelectionMode::from_modifiers(self.modifiers);
76 let event = DirectoryTreeEvent::Selected(path, is_dir, mode);
77 self.tree.update(event).map(Message::Tree)
78 }
79 Message::Tree(event) => self.tree.update(event).map(Message::Tree),
80 Message::ModifiersChanged(m) => {
81 self.modifiers = m;
82 Task::none()
83 }
84 Message::Key(key, mods) => {
85 if let Some(event) = self.tree.handle_key(&key, mods) {
86 return self.tree.update(event).map(Message::Tree);
87 }
88 Task::none()
89 }
90 }
91 }More examples
77 fn update(&mut self, message: Message) -> Task<Message> {
78 match message {
79 // As in the multi-select example, rewrite the built-in
80 // view's `Replace`-only `Selected` events using the
81 // current modifier state. Keyboard events come through
82 // `handle_key` with the correct mode already.
83 Message::Tree(DirectoryTreeEvent::Selected(path, is_dir, _)) => {
84 let mode = SelectionMode::from_modifiers(self.modifiers);
85 let event = DirectoryTreeEvent::Selected(path, is_dir, mode);
86 self.tree.update(event).map(Message::Tree)
87 }
88 // The headline case: the user released the mouse over a
89 // valid drop target. Perform the actual filesystem
90 // operation, then refresh affected folders so the tree
91 // view reflects the new layout.
92 Message::Tree(DirectoryTreeEvent::DragCompleted {
93 sources,
94 destination,
95 }) => {
96 let outcome = move_paths(&sources, &destination);
97 self.status = outcome.summary();
98 // The set of folders that need re-scanning: the
99 // destination (for the newly-arrived entries) and
100 // every source's parent (for the departed entries).
101 let mut to_refresh: HashSet<PathBuf> = HashSet::new();
102 to_refresh.insert(destination);
103 for s in &sources {
104 if let Some(parent) = s.parent() {
105 to_refresh.insert(parent.to_path_buf());
106 }
107 }
108 // Issue a collapse+expand for each affected folder.
109 // A collapse followed by a `Toggled` on the same
110 // path is the simplest way in v0.4 to invalidate
111 // the cached children and re-scan from scratch.
112 let tasks: Vec<Task<Message>> = to_refresh
113 .into_iter()
114 .flat_map(|p| {
115 [
116 Task::done(Message::Tree(DirectoryTreeEvent::Toggled(p.clone()))),
117 Task::done(Message::Tree(DirectoryTreeEvent::Toggled(p))),
118 ]
119 })
120 .collect();
121 Task::batch(tasks)
122 }
123 Message::Tree(event) => self.tree.update(event).map(Message::Tree),
124 Message::ModifiersChanged(m) => {
125 self.modifiers = m;
126 Task::none()
127 }
128 Message::Key(key, mods) => {
129 if let Some(event) = self.tree.handle_key(&key, mods) {
130 return self.tree.update(event).map(Message::Tree);
131 }
132 Task::none()
133 }
134 }
135 }Trait Implementations§
Source§impl Clone for SelectionMode
impl Clone for SelectionMode
Source§fn clone(&self) -> SelectionMode
fn clone(&self) -> SelectionMode
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SelectionMode
impl Debug for SelectionMode
Source§impl Default for SelectionMode
impl Default for SelectionMode
Source§fn default() -> SelectionMode
fn default() -> SelectionMode
Source§impl PartialEq for SelectionMode
impl PartialEq for SelectionMode
impl Copy for SelectionMode
impl Eq for SelectionMode
impl StructuralPartialEq for SelectionMode
Auto Trait Implementations§
impl Freeze for SelectionMode
impl RefUnwindSafe for SelectionMode
impl Send for SelectionMode
impl Sync for SelectionMode
impl Unpin for SelectionMode
impl UnsafeUnpin for SelectionMode
impl UnwindSafe for SelectionMode
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<State, Message> IntoBoot<State, Message> for State
impl<State, Message> IntoBoot<State, Message> for State
Source§fn into_boot(self) -> (State, Task<Message>)
fn into_boot(self) -> (State, Task<Message>)
Application.Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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