Skip to content

Commit eb41a62

Browse files
committed
p0.19
1 parent a4126c0 commit eb41a62

3 files changed

Lines changed: 351 additions & 367 deletions

File tree

otty-v3/src/widgets/explorer/view/sidebar_tree.rs

Lines changed: 54 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
use iced::widget::text::Wrapping;
22
use iced::widget::{column, container, row, scrollable, svg, text};
33
use iced::{Element, Length, alignment};
4+
use otty_ui_tree::{TreeNode, TreeRowContext, TreeView};
45

56
use crate::icons::{FILE, FOLDER, FOLDER_OPENED};
67
use crate::style::{thin_scroll_style, tree_row_style};
78
use crate::theme::{IcedColorPalette, ThemeProps};
89
use crate::widgets::explorer::event::ExplorerIntent;
9-
use crate::widgets::explorer::model::{
10-
ExplorerTreeViewModel, FileNode, TreePath,
11-
};
10+
use crate::widgets::explorer::model::{ExplorerTreeViewModel, FileNode};
1211

1312
const HEADER_HEIGHT: f32 = 22.0;
1413
const HEADER_PADDING_X: f32 = 10.0;
@@ -117,24 +116,19 @@ fn explorer_tree<'a>(
117116
vm: &ExplorerTreeViewModel<'a>,
118117
palette: &'a IcedColorPalette,
119118
) -> Element<'a, ExplorerIntent, iced::Theme, iced::Renderer> {
120-
let mut entries: Vec<
121-
Element<'_, ExplorerIntent, iced::Theme, iced::Renderer>,
122-
> = Vec::new();
123-
124-
render_children(vm.tree, &[], 0, vm, palette, &mut entries);
125-
126-
if entries.is_empty() {
127-
entries.push(
128-
container(iced::widget::Space::new())
129-
.width(Length::Fill)
130-
.height(Length::Fill)
131-
.into(),
132-
);
133-
}
134-
135-
let content = column(entries).width(Length::Fill).spacing(0);
136-
137-
let scrollable = scrollable::Scrollable::new(content)
119+
let icon_color = palette.dim_foreground;
120+
let tree_view = TreeView::new(vm.tree, move |context| {
121+
render_entry(context, icon_color)
122+
})
123+
.selected_row(vm.selected_path)
124+
.hovered_row(vm.hovered_path)
125+
.on_press(|path| ExplorerIntent::NodePressed { path })
126+
.on_hover(|path| ExplorerIntent::NodeHovered { path })
127+
.row_style(move |context| nav_row_style(palette, context))
128+
.indent_size(TREE_INDENT)
129+
.spacing(0.0);
130+
131+
let scrollable = scrollable::Scrollable::new(tree_view.view())
138132
.width(Length::Fill)
139133
.height(Length::Fill)
140134
.direction(scrollable::Direction::Vertical(
@@ -151,59 +145,12 @@ fn explorer_tree<'a>(
151145
.into()
152146
}
153147

154-
/// Recursively render tree children.
155-
fn render_children<'a>(
156-
children: &'a [FileNode],
157-
parent_path: &[String],
158-
depth: usize,
159-
vm: &ExplorerTreeViewModel<'a>,
160-
palette: &'a IcedColorPalette,
161-
entries: &mut Vec<Element<'a, ExplorerIntent, iced::Theme, iced::Renderer>>,
162-
) {
163-
for node in children {
164-
let mut path = parent_path.to_vec();
165-
path.push(node.name().to_string());
166-
167-
let is_selected = vm.selected_path.map(|s| s == &path).unwrap_or(false);
168-
let is_hovered = vm.hovered_path.map(|h| h == &path).unwrap_or(false);
169-
170-
entries.push(render_tree_row(
171-
node,
172-
&path,
173-
depth,
174-
is_selected,
175-
is_hovered,
176-
palette,
177-
));
178-
179-
// Recurse into expanded folders.
180-
if node.is_folder() && node.is_expanded() {
181-
render_children(
182-
node.children(),
183-
&path,
184-
depth + 1,
185-
vm,
186-
palette,
187-
entries,
188-
);
189-
}
190-
}
191-
}
192-
193-
/// Render a single tree row with icon, label, and interaction events.
194-
fn render_tree_row<'a>(
195-
node: &'a FileNode,
196-
path: &TreePath,
197-
depth: usize,
198-
is_selected: bool,
199-
is_hovered: bool,
200-
palette: &'a IcedColorPalette,
148+
fn render_entry<'a>(
149+
context: &TreeRowContext<'a, FileNode>,
150+
icon_color: iced::Color,
201151
) -> Element<'a, ExplorerIntent, iced::Theme, iced::Renderer> {
202-
let indent = depth as f32 * TREE_INDENT;
203-
204-
let icon_color = palette.dim_foreground;
205-
let icon_data = if node.is_folder() {
206-
if node.is_expanded() {
152+
let icon_data = if context.entry.node.is_folder() {
153+
if context.entry.node.is_expanded() {
207154
FOLDER_OPENED
208155
} else {
209156
FOLDER
@@ -228,7 +175,7 @@ fn render_tree_row<'a>(
228175
};
229176

230177
let title = container(
231-
text(node.name())
178+
text(context.entry.node.name())
232179
.size(TREE_FONT_SIZE)
233180
.width(Length::Fill)
234181
.wrapping(Wrapping::None)
@@ -242,32 +189,42 @@ fn render_tree_row<'a>(
242189
.spacing(0)
243190
.align_y(alignment::Vertical::Center);
244191

245-
let content = row![
246-
iced::widget::Space::new().width(Length::Fixed(indent)),
247-
leading,
248-
title,
249-
]
250-
.spacing(TREE_ROW_SPACING)
251-
.align_y(alignment::Vertical::Center);
192+
container(
193+
row![leading, title]
194+
.spacing(TREE_ROW_SPACING)
195+
.align_y(alignment::Vertical::Center),
196+
)
197+
.width(Length::Fill)
198+
.height(Length::Fixed(TREE_ROW_HEIGHT))
199+
.padding([0.0, TREE_ROW_PADDING_X])
200+
.into()
201+
}
252202

253-
let row_style = tree_row_style(palette, is_selected, is_hovered);
203+
fn nav_row_style(
204+
palette: &IcedColorPalette,
205+
context: &TreeRowContext<'_, FileNode>,
206+
) -> iced::widget::container::Style {
207+
tree_row_style(palette, context.is_selected, context.is_hovered)
208+
}
254209

255-
let styled_row = container(content)
256-
.width(Length::Fill)
257-
.height(Length::Fixed(TREE_ROW_HEIGHT))
258-
.padding([0.0, TREE_ROW_PADDING_X])
259-
.style(move |_| row_style);
210+
impl TreeNode for FileNode {
211+
fn title(&self) -> &str {
212+
self.name()
213+
}
260214

261-
let path_for_hover = path.clone();
262-
let path_for_press = path.clone();
215+
fn children(&self) -> Option<&[Self]> {
216+
if self.is_folder() {
217+
Some(self.children())
218+
} else {
219+
None
220+
}
221+
}
263222

264-
let interactive = iced::widget::mouse_area(styled_row)
265-
.on_enter(ExplorerIntent::NodeHovered {
266-
path: Some(path_for_hover),
267-
})
268-
.on_press(ExplorerIntent::NodePressed {
269-
path: path_for_press,
270-
});
223+
fn expanded(&self) -> bool {
224+
self.is_expanded()
225+
}
271226

272-
interactive.into()
227+
fn is_folder(&self) -> bool {
228+
self.is_folder()
229+
}
273230
}

0 commit comments

Comments
 (0)