refactoring
This commit is contained in:
+32
-34
@@ -92,6 +92,7 @@ pub enum TreeKeyResult {
|
||||
}
|
||||
|
||||
/// Состояние абстрактного дерева.
|
||||
#[derive(Default)]
|
||||
pub struct TreeState {
|
||||
nodes: HashMap<String, NodeRecord>,
|
||||
roots: Vec<String>,
|
||||
@@ -108,21 +109,6 @@ pub struct TreeState {
|
||||
scroll: ScrollHandle,
|
||||
}
|
||||
|
||||
impl Default for TreeState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
nodes: HashMap::new(),
|
||||
roots: Vec::new(),
|
||||
toggle_callback: None,
|
||||
click_callback: None,
|
||||
selected: None,
|
||||
focus_handle: None,
|
||||
focus_requested: false,
|
||||
scroll: ScrollHandle::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeState {
|
||||
/// Создаёт пустое дерево.
|
||||
pub fn new() -> Self {
|
||||
@@ -153,11 +139,8 @@ impl TreeState {
|
||||
return false;
|
||||
}
|
||||
self.expand_ancestors(id);
|
||||
self.selected = Some(id.to_owned());
|
||||
self.focus_requested = true;
|
||||
if let Some(index) = self.rows().iter().position(|row| row.id == id) {
|
||||
self.scroll.scroll_to_item(index);
|
||||
}
|
||||
self.select_and_scroll(id);
|
||||
true
|
||||
}
|
||||
|
||||
@@ -259,6 +242,16 @@ impl TreeState {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Удаляет все узлы и сбрасывает выбор.
|
||||
///
|
||||
/// Обработчики раскрытия и клика сохраняются: сценарий может наполнять
|
||||
/// дерево заново, например при обновлении списка диагностики.
|
||||
pub fn clear(&mut self) {
|
||||
self.nodes.clear();
|
||||
self.roots.clear();
|
||||
self.selected = None;
|
||||
}
|
||||
|
||||
/// Удаляет узел и все его дочерние узлы рекурсивно.
|
||||
///
|
||||
/// Возвращает `false`, если узла с таким `id` нет.
|
||||
@@ -340,6 +333,14 @@ impl TreeState {
|
||||
entries.into_iter().map(|(_, _, id)| id).collect()
|
||||
}
|
||||
|
||||
/// Делает строку выбранной и прокручивает её в видимую часть.
|
||||
fn select_and_scroll(&mut self, id: &str) {
|
||||
self.selected = Some(id.to_owned());
|
||||
if let Some(index) = self.rows().iter().position(|row| row.id == id) {
|
||||
self.scroll.scroll_to_item(index);
|
||||
}
|
||||
}
|
||||
|
||||
/// Сдвигает выборку по видимым строкам.
|
||||
fn move_selection(&mut self, delta: isize) {
|
||||
let rows = self.rows();
|
||||
@@ -357,8 +358,8 @@ impl TreeState {
|
||||
None if delta < 0 => rows.len() - 1,
|
||||
None => 0,
|
||||
};
|
||||
self.selected = Some(rows[next].id.clone());
|
||||
self.scroll.scroll_to_item(next);
|
||||
let id = rows[next].id.clone();
|
||||
self.select_and_scroll(&id);
|
||||
}
|
||||
|
||||
/// Enter: раскрывает папку или вызывает обработчик клика конечной ноды.
|
||||
@@ -383,10 +384,7 @@ impl TreeState {
|
||||
};
|
||||
}
|
||||
if let Some(parent) = self.nodes.get(&id).and_then(|record| record.parent.clone()) {
|
||||
self.selected = Some(parent.clone());
|
||||
if let Some(index) = self.rows().iter().position(|row| row.id == parent) {
|
||||
self.scroll.scroll_to_item(index);
|
||||
}
|
||||
self.select_and_scroll(&parent);
|
||||
}
|
||||
TreeKeyResult::Handled
|
||||
}
|
||||
@@ -399,20 +397,20 @@ impl TreeState {
|
||||
let Some(record) = self.nodes.get(&id) else {
|
||||
return TreeKeyResult::Ignored;
|
||||
};
|
||||
if record.node.expandable && !record.node.expanded {
|
||||
let expandable = record.node.expandable;
|
||||
let expanded = record.node.expanded;
|
||||
let first_child = expanded
|
||||
.then(|| self.sorted(&record.children).first().cloned())
|
||||
.flatten();
|
||||
|
||||
if expandable && !expanded {
|
||||
return match self.activate(&id) {
|
||||
Some(action) => TreeKeyResult::Action(action),
|
||||
None => TreeKeyResult::Handled,
|
||||
};
|
||||
}
|
||||
if record.node.expanded
|
||||
&& let Some(child) = self.sorted(&record.children).first().cloned()
|
||||
{
|
||||
let index = self.rows().iter().position(|row| row.id == child);
|
||||
self.selected = Some(child);
|
||||
if let Some(index) = index {
|
||||
self.scroll.scroll_to_item(index);
|
||||
}
|
||||
if let Some(child) = first_child {
|
||||
self.select_and_scroll(&child);
|
||||
}
|
||||
TreeKeyResult::Handled
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user