Skip to content

Commit c8579f1

Browse files
committed
optimize folder close logic
1 parent 86cdf73 commit c8579f1

8 files changed

Lines changed: 77 additions & 28 deletions

File tree

asm/src/impls/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ pub(crate) mod node;
55
pub(crate) mod smali;
66
pub(crate) mod dex;
77

8-
mod util;
8+
pub(crate) mod util;

asm/src/impls/util/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ mod ex;
88
mod mutf8;
99
mod once_vec;
1010
mod computable;
11-
mod refs;
11+
pub(crate) mod refs;

asm/src/pub_refs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::sync::Arc;
22

33
pub type ConstStr = &'static str;
44

5+
/// for impl, check [crate::impls::util::refs::ToStringRef]
56
pub type StrRef = Arc<str>;
67

78
/// e.g.: java/lang/Class

asm_egui/src/file_tree.rs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,21 @@ pub fn render_dir(ui: &mut egui::Ui, app: &mut EguiApp) {
1010
let server = app.server.lock();
1111
if server.is_none() { return; }
1212
let row_height = ui.spacing().interact_size.y;
13-
ScrollArea::vertical().auto_shrink(false)
14-
.show_rows(ui, row_height, entries.len(), |ui, range| {
15-
for i in range {
16-
let entry = &mut entries[i];
17-
match entry {
18-
FileEntry::Dir(raw_dir) => {
19-
render_dir_raw(ui, raw_dir);
20-
}
21-
FileEntry::File(file_info) => {
22-
render_file(ui, file_info, server_app);
23-
}
13+
let scroll_area = ScrollArea::vertical().auto_shrink(false);
14+
// scroll_area.vertical_scroll_offset();
15+
scroll_area.show_rows(ui, row_height, entries.len(), |ui, range| {
16+
for i in range {
17+
let entry = &mut entries[i];
18+
match entry {
19+
FileEntry::Dir(raw_dir) => {
20+
render_dir_raw(ui, raw_dir, server_app);
21+
}
22+
FileEntry::File(file_info) => {
23+
render_file(ui, file_info, server_app);
2424
}
2525
}
26-
});
26+
}
27+
});
2728
}
2829

2930
fn render_file(
@@ -46,9 +47,9 @@ fn render_file(
4647
}
4748

4849
fn render_dir_raw(
49-
ui: &mut egui::Ui, dir_info: &mut RawDirInfo,
50+
ui: &mut egui::Ui, dir_info: &mut RawDirInfo, app_container: &AppContainer,
5051
) {
51-
let RawDirInfo { opened, level, title } = dir_info;
52+
let RawDirInfo { opened, level, title, dir_key } = dir_info;
5253
ui.horizontal(|ui| {
5354
ui.add_space((*level as f32) * 12.0);
5455
let font = TextStyle::Body.resolve(ui.style());
@@ -61,7 +62,13 @@ fn render_dir_raw(
6162
let layout_job = LayoutJob::simple_singleline(title, font.clone(), color);
6263
let label = ui.selectable_label(false, layout_job);
6364
if label.clicked() {
64-
*opened = !*opened;
65+
let new_opened = !*opened;
66+
if new_opened {
67+
*opened = true;
68+
} else {
69+
// closed, close all child dir
70+
app_container.send_message(UIMessage::CloseDir(dir_info.dir_key.clone()))
71+
}
6572
}
6673
});
6774
}

asm_egui/src/smali.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,6 @@ impl<'a> RenderContext<'a> {
194194
fn descriptor_menu_for_fn(
195195
&mut self, ui: &mut Ui, descriptor: &str,
196196
) -> Option<()> {
197-
let RenderContext {
198-
server, content, ..
199-
} = self;
200197
let descriptor = descriptor.strip_prefix('(')?;
201198
let mut split = descriptor.split(')');
202199

asm_server/src/impls/server.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl AsmServer {
8787
fn render_to_app(&self, app: AppContainer) {
8888
let classes = self.read_classes();
8989
let start = Instant::now();
90-
let dir_info = DirInfo::from_classes(Arc::from("Root"), &classes);
90+
let dir_info = DirInfo::from_classes(&classes);
9191
info!("resolve dir info cost: {:?}", start.elapsed());
9292
app.set_left(Left { root_node: dir_info });
9393
}

asm_server/src/server.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,30 @@ impl AsmServer {
9595
self.switch_or_open_lock_free(file_key, accessor, &mut left, &mut content, &mut top);
9696
}
9797

98+
pub fn close_dir(&self, file_key: &str, render_target: &AppContainer) {
99+
let mut left = render_target.left().lock();
100+
let mut current_node = &mut left.root_node;
101+
let path_parts: Vec<&str> = file_key.split('/').collect();
102+
for part in path_parts {
103+
let Some(dir) = current_node.dirs.get_mut(part) else {
104+
return;
105+
};
106+
if !dir.raw.opened {
107+
return;
108+
}
109+
current_node = dir;
110+
}
111+
current_node.raw.opened = false;
112+
let mut child_nodes: Vec<&mut DirInfo> = vec![current_node];
113+
while let Some(child_node) = child_nodes.pop() {
114+
for child in child_node.dirs.values_mut() {
115+
if !child.raw.opened { continue; }
116+
child.raw.opened = false;
117+
child_nodes.push(child);
118+
}
119+
}
120+
}
121+
98122
pub fn switch_or_open_lock_free(
99123
&self, file_key: &str, accessor: &AccessorEnum,
100124
left: &mut Left, content: &mut Content, top: &mut Top,
@@ -124,6 +148,7 @@ impl AsmServer {
124148
top.file_path = Some(file_key.to_string());
125149
}
126150

151+
// switch left side file tree to correct place.
127152
fn switch_file_tree(&self, left: &mut Left, file_key: &str) {
128153
let root_node = &mut left.root_node;
129154
let parts: Vec<&str> = file_key.split('/').collect();

asm_server/src/ui/mod.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use std::str::Split;
1616
use std::sync::Arc;
1717

1818
/// contains all states of the app.
19-
/// It's not like the [crate::AsmServer] which only contains the information of a file.
20-
/// App will exists even no file opened. (no [crate::AsmServer] exists)
19+
/// It's not like the [AsmServer] which only contains the information of a file.
20+
/// App will exists even no file opened. (no [AsmServer] exists)
2121
#[derive(Default, Clone, Debug)]
2222
pub struct App {
2323
pub top: Arc<Mutex<Top>>,
@@ -29,6 +29,7 @@ pub struct App {
2929
#[derive(Clone, Debug)]
3030
pub enum UIMessage {
3131
OpenFile(OpenFileMessage),
32+
CloseDir(StrRef),
3233
}
3334

3435
#[derive(Clone, Debug)]
@@ -61,6 +62,9 @@ impl AppContainer {
6162
UIMessage::OpenFile(message) => {
6263
server.switch_or_open(&message.path, self);
6364
}
65+
UIMessage::CloseDir(path) => {
66+
server.close_dir(&path, self);
67+
}
6468
}
6569
}
6670
}
@@ -99,6 +103,7 @@ pub struct RawDirInfo {
99103
pub opened: bool,
100104
pub level: u16,
101105
pub title: StrRef,
106+
pub dir_key: StrRef,
102107
}
103108

104109
pub type DirMap = BTreeMap<StrRef, DirInfo>;
@@ -124,8 +129,14 @@ fn visible_items<'a, 'b>(dir_info: &'b mut DirInfo, container: &'a mut Vec<FileE
124129
}
125130

126131
impl DirInfo {
127-
pub fn from_classes(title: StrRef, class_names: &[StrRef]) -> Self {
128-
let mut root_node = DirInfo { raw: RawDirInfo { title, ..Default::default() }, ..Default::default() };
132+
pub fn from_classes(class_names: &[StrRef]) -> Self {
133+
let root_raw_dir = RawDirInfo {
134+
title: Arc::from("Root"),
135+
dir_key: Arc::from(""),
136+
level: 0,
137+
opened: true,
138+
};
139+
let mut root_node = DirInfo { raw: root_raw_dir, ..Default::default() };
129140
for class_name in class_names {
130141
root_node.put_entry_if_absent(class_name.clone());
131142
}
@@ -170,7 +181,7 @@ impl DirInfo {
170181
}
171182

172183
fn entry_parts(path: &str) -> Peekable<Enumerate<Split<char>>> {
173-
path[1..(path.len() - 1)].split('/').enumerate().peekable()
184+
path.split('/').enumerate().peekable()
174185
}
175186

176187
fn put_file_if_absent(&mut self, level: u16, file_key: StrRef, file_name: StrRef) -> &mut FileInfo {
@@ -182,8 +193,16 @@ impl DirInfo {
182193

183194
fn put_dir_if_absent(&mut self, level: u16, folder_name: StrRef) -> &mut DirInfo {
184195
let title = folder_name.clone();
185-
self.dirs.entry(folder_name).or_insert_with(|| {
186-
let raw = RawDirInfo { title, level, ..Default::default() };
196+
let parent_dir_key = &self.raw.dir_key;
197+
let dir_key: StrRef;
198+
if parent_dir_key.is_empty() {
199+
// direct n
200+
dir_key = folder_name.into();
201+
} else {
202+
dir_key = format!("{}/{}", parent_dir_key, folder_name).into();
203+
}
204+
self.dirs.entry(title.clone()).or_insert_with(|| {
205+
let raw = RawDirInfo { title, level, dir_key, ..Default::default() };
187206
DirInfo { raw, ..Default::default() }
188207
})
189208
}

0 commit comments

Comments
 (0)