1use std::path::PathBuf;
25use std::sync::Arc;
26
27use iced::widget::{column, container, pick_list, row, text};
28use iced::{Element, Length, Task};
29use iced_swdir_tree::{
30 DirectoryFilter, DirectoryTree, DirectoryTreeEvent, IconRole, IconSpec, IconTheme, UnicodeTheme,
31};
32
33#[derive(Debug)]
36struct LabelTheme;
37
38impl IconTheme for LabelTheme {
39 fn glyph(&self, role: IconRole) -> IconSpec {
40 let s: &'static str = match role {
43 IconRole::FolderClosed => "[D]",
44 IconRole::FolderOpen => "[O]",
45 IconRole::File => "[F]",
46 IconRole::Error => "[!]",
47 IconRole::CaretRight => ">",
48 IconRole::CaretDown => "v",
49 _ => "?",
50 };
51 IconSpec::new(s)
52 }
53}
54
55#[derive(Debug)]
59struct AsciiTheme;
60
61impl IconTheme for AsciiTheme {
62 fn glyph(&self, role: IconRole) -> IconSpec {
63 let s: &'static str = match role {
64 IconRole::FolderClosed => "+",
65 IconRole::FolderOpen => "-",
66 IconRole::File => ".",
67 IconRole::Error => "!",
68 IconRole::CaretRight => ">",
69 IconRole::CaretDown => "v",
70 _ => "?",
71 };
72 IconSpec::new(s)
73 }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77enum ThemeChoice {
78 Unicode,
79 Label,
80 Ascii,
81}
82
83impl ThemeChoice {
84 const ALL: [ThemeChoice; 3] = [ThemeChoice::Unicode, ThemeChoice::Label, ThemeChoice::Ascii];
85
86 fn to_theme(self) -> Arc<dyn IconTheme> {
87 match self {
88 ThemeChoice::Unicode => Arc::new(UnicodeTheme),
89 ThemeChoice::Label => Arc::new(LabelTheme),
90 ThemeChoice::Ascii => Arc::new(AsciiTheme),
91 }
92 }
93}
94
95impl std::fmt::Display for ThemeChoice {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 f.write_str(match self {
98 ThemeChoice::Unicode => "Unicode",
99 ThemeChoice::Label => "Label",
100 ThemeChoice::Ascii => "Ascii",
101 })
102 }
103}
104
105#[derive(Debug, Clone)]
106enum Message {
107 Tree(DirectoryTreeEvent),
108 ThemePicked(ThemeChoice),
109}
110
111struct App {
112 tree: DirectoryTree,
113 choice: ThemeChoice,
114 root: PathBuf,
115}
116
117impl App {
118 fn new() -> (Self, Task<Message>) {
119 let root = resolve_root();
120 let tree = DirectoryTree::new(root.clone())
121 .with_filter(DirectoryFilter::FilesAndFolders)
122 .with_icon_theme(ThemeChoice::Unicode.to_theme());
123 let mut app = App {
124 tree,
125 choice: ThemeChoice::Unicode,
126 root: root.clone(),
127 };
128 let task = app
129 .tree
130 .update(DirectoryTreeEvent::Toggled(root))
131 .map(Message::Tree);
132 (app, task)
133 }
134
135 fn update(&mut self, msg: Message) -> Task<Message> {
136 match msg {
137 Message::Tree(ev) => self.tree.update(ev).map(Message::Tree),
138 Message::ThemePicked(choice) => {
139 self.choice = choice;
146 self.tree = DirectoryTree::new(self.root.clone())
147 .with_filter(DirectoryFilter::FilesAndFolders)
148 .with_icon_theme(choice.to_theme());
149 self.tree
150 .update(DirectoryTreeEvent::Toggled(self.root.clone()))
151 .map(Message::Tree)
152 }
153 }
154 }
155
156 fn view(&self) -> Element<'_, Message> {
157 let picker = pick_list(
158 &ThemeChoice::ALL[..],
159 Some(self.choice),
160 Message::ThemePicked,
161 );
162 let header = row![text("Theme:").size(13), picker].spacing(8);
163
164 column![
165 header,
166 container(self.tree.view(Message::Tree))
167 .width(Length::Fill)
168 .height(Length::Fill),
169 text(
170 "Switch themes to see the icon trait in action. \
171 The 'Label' and 'Ascii' themes are defined in \
172 this example file; 'Unicode' is shipped with \
173 the crate."
174 )
175 .size(12),
176 ]
177 .spacing(8)
178 .padding(10)
179 .into()
180 }
181}
182
183fn resolve_root() -> PathBuf {
184 if let Some(arg) = std::env::args().nth(1) {
185 return PathBuf::from(arg);
186 }
187 let scratch = std::env::temp_dir().join("iced-swdir-tree-icon-theme-demo");
188 let _ = std::fs::create_dir_all(&scratch);
189 for dir in &["src", "src/widgets", "tests", "docs"] {
190 let _ = std::fs::create_dir_all(scratch.join(dir));
191 }
192 for (path, body) in &[
193 ("Cargo.toml", "[package]\n"),
194 ("README.md", "demo\n"),
195 ("src/main.rs", "fn main() {}\n"),
196 ("src/widgets/button.rs", ""),
197 ("tests/basic.rs", ""),
198 ("docs/ROADMAP.md", ""),
199 ] {
200 let p = scratch.join(path);
201 if !p.exists() {
202 let _ = std::fs::write(p, body);
203 }
204 }
205 scratch
206}
207
208fn main() -> iced::Result {
209 iced::application(App::new, App::update, App::view)
210 .title("iced-swdir-tree ยท icon-theme example")
211 .run()
212}