1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! # iced-swdir-tree
//!
//! A reusable [`iced`] widget for displaying a directory tree with lazy
//! loading, filtering, selection, and asynchronous traversal.
//!
//! Built on top of [`swdir`]'s `scan_dir` for single-level, non-recursive
//! directory listings — perfect for GUI trees that expand one folder at a
//! time.
//!
//! ## Minimal example
//!
//! ```no_run
//! use std::path::PathBuf;
//! use iced::{Element, Task};
//! use iced_swdir_tree::{DirectoryFilter, DirectoryTree, DirectoryTreeEvent};
//!
//! #[derive(Debug, Clone)]
//! enum Message {
//! Tree(DirectoryTreeEvent),
//! }
//!
//! struct App {
//! tree: DirectoryTree,
//! }
//!
//! impl App {
//! fn new() -> (Self, Task<Message>) {
//! let tree = DirectoryTree::new(PathBuf::from("."))
//! .with_filter(DirectoryFilter::FilesAndFolders);
//! (Self { tree }, Task::none())
//! }
//!
//! fn update(&mut self, message: Message) -> Task<Message> {
//! match message {
//! Message::Tree(event) => {
//! // Observe app-level side effects BEFORE passing to the widget.
//! // The third field is the `SelectionMode` (Replace/Toggle/ExtendRange);
//! // match it with `_` when you only care about which path was clicked.
//! if let DirectoryTreeEvent::Selected(path, is_dir, _) = &event {
//! println!("selected {:?} (dir={})", path, is_dir);
//! }
//! self.tree.update(event).map(Message::Tree)
//! }
//! }
//! }
//!
//! fn view(&self) -> Element<'_, Message> {
//! self.tree.view(Message::Tree)
//! }
//! }
//! # fn main() {}
//! ```
//!
//! ## Multi-select
//!
//! Shift/Ctrl-click support is covered in `examples/multi_select.rs`
//! — the built-in view always emits `SelectionMode::Replace` because
//! iced 0.14's button `on_press` can't observe modifier keys.
//! Applications that want multi-select track modifier state via a
//! keyboard subscription and rewrite the mode in their own update
//! handler using [`SelectionMode::from_modifiers`].
//!
//! ## Drag-and-drop
//!
//! The widget tracks drag gestures internally and emits a
//! [`DragCompleted`](DirectoryTreeEvent::DragCompleted)`{ sources,
//! destination }` event when the user releases the mouse over a
//! valid folder row. The widget performs **no** filesystem
//! operation — the app reacts to `DragCompleted` and does move /
//! copy / symlink / upload however it likes, then re-scans the
//! affected folders by emitting a `Toggled` collapse+expand to
//! refresh. See `examples/drag_drop.rs` for a worked example that
//! performs `fs::rename` on drop.
//!
//! ## Feature flags
//!
//! * **`icons`** (off by default) — when enabled, uses [`lucide-icons`] for
//! folder/file graphics. When disabled, icons fall back to short text
//! labels (`▸ `, `▾ `, etc.). The public API is identical either way.
//!
//! [`iced`]: https://docs.rs/iced
//! [`swdir`]: https://docs.rs/swdir
//! [`lucide-icons`]: https://docs.rs/lucide-icons
pub use crate;
pub use LUCIDE_FONT_BYTES;
/// **Not part of the public API.** Shim exposed for the crate's own
/// integration tests in `tests/`.
///
/// Integration tests need to drive the state machine without running
/// an iced executor, which means they have to build `Loaded` payloads
/// whose fields are crate-private. This module exposes a tiny set of
/// operations that let tests poke at the otherwise-private surface.
/// It is `#[doc(hidden)]` and not covered by SemVer; downstream
/// crates must not depend on it.