Skip to content

Commit 86cdf73

Browse files
committed
message system for ui
1 parent 87b8dae commit 86cdf73

6 files changed

Lines changed: 103 additions & 45 deletions

File tree

asm_egui/src/app.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::sync::Arc;
1313
pub struct EguiApp {
1414
pub server: ServerMut,
1515
pub log_holder: Arc<LogHolder>,
16-
pub server_app: AppContainer,
16+
pub ui_app: AppContainer,
1717
}
1818

1919
impl EguiApp {
@@ -22,9 +22,9 @@ impl EguiApp {
2222
inject_log(Arc::clone(&log_holder));
2323
inject_sys_font(context);
2424
Self {
25-
server: Default::default(),
2625
log_holder,
27-
server_app: Default::default(),
26+
server: Default::default(),
27+
ui_app: Default::default(),
2828
}
2929
}
3030
}
@@ -69,13 +69,13 @@ impl EguiApp {
6969
let Some(server) = server_locked.as_ref() else {
7070
return;
7171
};
72-
let server_app = &self.server_app;
72+
let server_app = &self.ui_app;
7373

7474
render_tabs(ui, server_app);
7575

7676
ui.separator();
7777

78-
smali_layout(ui, server, &self.server_app);
78+
smali_layout(ui, server, &self.ui_app);
7979
});
8080
}
8181
}
@@ -87,7 +87,7 @@ impl EguiApp {
8787
if let Some(DroppedFile { path, .. }) = input.raw.dropped_files.get(0) {
8888
if let Some(path) = path {
8989
let path = path.display().to_string();
90-
AsmServer::smart_open(self.server.clone(), &path, self.server_app.clone());
90+
AsmServer::smart_open(self.server.clone(), &path, self.ui_app.clone());
9191
}
9292
}
9393
})
@@ -96,6 +96,11 @@ impl EguiApp {
9696

9797
impl eframe::App for EguiApp {
9898
fn update(&mut self, ctx: &Context, _frame: &mut Frame) {
99+
let mut mutex = self.server.lock();
100+
if let Some(server) = mutex.as_mut() {
101+
self.ui_app.process_messages(server);
102+
}
103+
drop(mutex);
99104
self.top_bar(ctx);
100105
self.bottom_log_panel(ctx);
101106
self.left_bar(ctx);

asm_egui/src/file_tree.rs

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,46 @@
11
use crate::app::EguiApp;
22
use egui::text::LayoutJob;
33
use egui::{ScrollArea, TextStyle};
4-
use java_asm_server::ui::{AppContainer, FileEntry, FileInfo, RawDirInfo};
5-
use java_asm_server::AsmServer;
6-
use std::ops::Deref;
4+
use java_asm_server::ui::{AppContainer, FileEntry, FileInfo, OpenFileMessage, RawDirInfo, UIMessage};
75

86
pub fn render_dir(ui: &mut egui::Ui, app: &mut EguiApp) {
9-
let server_app = &app.server_app;
10-
let mut server_app_left = server_app.left().lock();
11-
let entries = &mut server_app_left.root_node.visible_items();
7+
let server_app = &app.ui_app;
8+
let mut left = server_app.left().lock();
9+
let entries = &mut left.root_node.visible_items();
1210
let server = app.server.lock();
13-
if let Some(server) = server.deref() {
14-
let row_height = ui.spacing().interact_size.y;
15-
ScrollArea::vertical().auto_shrink(false)
16-
.show_rows(ui, row_height, entries.len(), |ui, range| {
17-
for i in range {
18-
let entry = &mut entries[i];
19-
match entry {
20-
FileEntry::Dir(raw_dir) => {
21-
render_dir_raw(ui, raw_dir);
22-
}
23-
FileEntry::File(file_info) => {
24-
render_file(ui, file_info, server, server_app);
25-
}
11+
if server.is_none() { return; }
12+
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);
2623
}
2724
}
28-
});
29-
}
25+
}
26+
});
3027
}
3128

3229
fn render_file(
33-
ui: &mut egui::Ui, file_info: &mut FileInfo,
34-
server: &AsmServer, app: &AppContainer,
30+
ui: &mut egui::Ui, file_info: &mut FileInfo, app: &AppContainer,
3531
) {
3632
let FileInfo { title, file_key, level } = file_info;
3733
ui.horizontal(|ui| {
3834
ui.add_space((*level as f32) * 12.0);
3935
let layout_job = layout_string(ui, title.to_string());
4036
let label = ui.selectable_label(false, layout_job);
4137
if label.clicked() {
42-
server.switch_or_open(file_key, app);
38+
let message = UIMessage::OpenFile(
39+
OpenFileMessage {
40+
path: file_key.clone(),
41+
}
42+
);
43+
app.send_message(message);
4344
}
4445
});
4546
}

asm_egui/src/smali.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ use egui::text::LayoutJob;
33
use egui::{CursorIcon, FontId, Response, ScrollArea, TextStyle, Ui, Vec2};
44
use java_asm::smali::SmaliToken;
55
use java_asm::StrRef;
6-
use java_asm_server::ui::{AppContainer, Content, Top};
6+
use java_asm_server::ui::{AppContainer, Content, Left, Top};
77
use java_asm_server::AsmServer;
88
use std::ops::{Deref, DerefMut};
99

1010
pub fn smali_layout(ui: &mut Ui, server: &AsmServer, app: &AppContainer) {
1111
let mut content_locked = app.content().lock();
12+
let mut left_locked = app.left().lock();
1213
let selected_tab_index = content_locked.selected;
1314
let Some(selected_tab_index) = selected_tab_index else { return; };
1415

@@ -36,6 +37,7 @@ pub fn smali_layout(ui: &mut Ui, server: &AsmServer, app: &AppContainer) {
3637
font: &font,
3738
content: content_mut,
3839
top: &mut top_locked,
40+
left: &mut left_locked,
3941
lines: &lines,
4042
smali_style: &smali_style,
4143
dft_color,
@@ -51,6 +53,7 @@ pub fn smali_layout(ui: &mut Ui, server: &AsmServer, app: &AppContainer) {
5153

5254
struct RenderContext<'a> {
5355
pub server: &'a AsmServer,
56+
pub left: &'a mut Left,
5457
pub top: &'a mut Top,
5558
pub content: &'a mut Content,
5659
pub lines: &'a Vec<Vec<SmaliToken>>,
@@ -256,7 +259,7 @@ impl<'a> RenderContext<'a> {
256259
&mut self, ui: &mut Ui, descriptor: &str,
257260
) {
258261
let RenderContext {
259-
server, content, top, ..
262+
server, content, top, left, ..
260263
} = self;
261264
let existed = server.find_class(descriptor);
262265
if !existed {
@@ -266,7 +269,7 @@ impl<'a> RenderContext<'a> {
266269
let Some(accessor) = accessor_locked.deref() else { return };
267270
let link = ui.link(descriptor);
268271
if link.clicked() {
269-
server.switch_or_open_lock_free(descriptor, accessor, content, top)
272+
server.switch_or_open_lock_free(descriptor, accessor, left, content, top)
270273
}
271274
}
272275
}

asm_egui/src/top_bar.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ use bit_set::BitSet;
33
use egui::containers::PopupCloseBehavior;
44
use egui::text::LayoutJob;
55
use egui::{popup_below_widget, Context, Id, Response, TextEdit, TextFormat, TextStyle, Ui};
6+
use java_asm_server::ui::{OpenFileMessage, UIMessage};
67
use java_asm_server::AsmServer;
78
use std::ops::Deref;
89

910
impl EguiApp {
1011
pub(crate) fn top_bar(&mut self, ctx: &Context) {
1112
egui::TopBottomPanel::top("top_bar").show(ctx, |ui| {
1213
ui.vertical(|ui| {
13-
let server_app = &mut self.server_app;
14+
let server_app = &mut self.ui_app;
1415
// loading state
1516
let locked_top = server_app.top().lock();
1617
let loading_state = &locked_top.loading_state;
@@ -30,15 +31,15 @@ impl EguiApp {
3031
ui.horizontal(|ui| {
3132
if ui.button("📂 Open...").clicked() {
3233
AsmServer::dialog_to_open_file(
33-
self.server.clone(), self.server_app.clone(),
34+
self.server.clone(), self.ui_app.clone(),
3435
);
3536
}
3637
self.file_path_input(ui);
3738
});
3839
}
3940

4041
fn file_path_input(&mut self, ui: &mut Ui) {
41-
let mut locked_top = self.server_app.top().lock();
42+
let mut locked_top = self.ui_app.top().lock();
4243
let Some(file_path) = &mut locked_top.file_path else { return; };
4344

4445
let edit_path_ui = Self::file_path_input_area(ui, file_path);
@@ -89,7 +90,7 @@ impl EguiApp {
8990
}
9091

9192
fn popup_file_path_ui(&mut self, ui: &mut Ui) {
92-
let search_results = self.server_app.top().lock().search_result.clone();
93+
let search_results = self.ui_app.top().lock().search_result.clone();
9394
let style = ui.style();
9495
let font = TextStyle::Monospace.resolve(&style);
9596

@@ -115,9 +116,10 @@ impl EguiApp {
115116
}
116117
let selectable_label = ui.selectable_label(false, text_layout_job);
117118
if selectable_label.clicked() {
118-
let server_locked = self.server.lock();
119-
let Some(server) = server_locked.deref() else { return; };
120-
server.switch_or_open(&result.item, &self.server_app);
119+
let message = UIMessage::OpenFile(
120+
OpenFileMessage { path: result.item }
121+
);
122+
self.ui_app.send_message(message);
121123
ui.memory_mut(|m| m.close_popup());
122124
}
123125
}

asm_server/src/server.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::impls::fuzzy::FuzzyMatchModel;
22
use crate::impls::server::FileOpenContext;
33
use crate::impls::util::new_tokio_thread;
4-
use crate::ui::{AppContainer, Content, Tab, Top};
4+
use crate::ui::{AppContainer, Content, DirInfo, Left, Tab, Top};
55
use crate::{Accessor, AccessorEnum, ArcVarOpt, AsmServer, ExportableSource, LoadingState, ServerMut};
66
use java_asm::smali::SmaliNode;
77
use java_asm::{AsmErr, StrRef};
@@ -89,14 +89,17 @@ impl AsmServer {
8989
pub fn switch_or_open(&self, file_key: &str, render_target: &AppContainer) {
9090
let accessor_locked = self.accessor.lock();
9191
let Some(accessor) = accessor_locked.deref() else { return; };
92+
let mut left = render_target.left().lock();
9293
let mut content = render_target.content().lock();
9394
let mut top = render_target.top().lock();
94-
self.switch_or_open_lock_free(file_key, accessor, &mut content, &mut top);
95+
self.switch_or_open_lock_free(file_key, accessor, &mut left, &mut content, &mut top);
9596
}
9697

9798
pub fn switch_or_open_lock_free(
98-
&self, file_key: &str, accessor: &AccessorEnum, content: &mut Content, top: &mut Top,
99+
&self, file_key: &str, accessor: &AccessorEnum,
100+
left: &mut Left, content: &mut Content, top: &mut Top,
99101
) {
102+
self.switch_file_tree(left, file_key);
100103
let existed_tab = content.opened_tabs.iter().position(|tab| *tab.file_key == *file_key);
101104
if let Some(existed_tab) = existed_tab {
102105
content.selected = Some(existed_tab);
@@ -121,6 +124,22 @@ impl AsmServer {
121124
top.file_path = Some(file_key.to_string());
122125
}
123126

127+
fn switch_file_tree(&self, left: &mut Left, file_key: &str) {
128+
let root_node = &mut left.root_node;
129+
let parts: Vec<&str> = file_key.split('/').collect();
130+
if parts.is_empty() { return; }
131+
132+
let mut current_node = root_node;
133+
for part in parts {
134+
current_node.raw.opened = true;
135+
if let Some(child) = current_node.dirs.get_mut(part) {
136+
current_node = child;
137+
} else {
138+
break;
139+
}
140+
}
141+
}
142+
124143
pub fn search(&self, top: &mut Top) {
125144
let Some(query) = &top.file_path else { return; };
126145
let query: StrRef = query.as_str().into();

asm_server/src/ui/mod.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ pub mod log;
22
pub mod msg;
33
pub mod font;
44

5+
use crate::impls::fuzzy::SearchResult;
56
use crate::ui::log::LogHolder;
67
use crate::ui::AbsFile::{Dir, File};
7-
use crate::LoadingState;
8+
use crate::{AsmServer, LoadingState};
89
use java_asm::smali::SmaliNode;
910
use java_asm::StrRef;
1011
use ::log::Level;
@@ -13,7 +14,6 @@ use std::collections::BTreeMap;
1314
use std::iter::{Enumerate, Peekable};
1415
use std::str::Split;
1516
use std::sync::Arc;
16-
use crate::impls::fuzzy::SearchResult;
1717

1818
/// contains all states of the app.
1919
/// It's not like the [crate::AsmServer] which only contains the information of a file.
@@ -23,8 +23,20 @@ pub struct App {
2323
pub top: Arc<Mutex<Top>>,
2424
pub left: Arc<Mutex<Left>>,
2525
pub content: Arc<Mutex<Content>>,
26+
pub messages: Arc<Mutex<Vec<UIMessage>>>,
27+
}
28+
29+
#[derive(Clone, Debug)]
30+
pub enum UIMessage {
31+
OpenFile(OpenFileMessage),
2632
}
2733

34+
#[derive(Clone, Debug)]
35+
pub struct OpenFileMessage {
36+
pub path: StrRef,
37+
}
38+
39+
2840
#[derive(Default, Clone, Debug)]
2941
pub struct AppContainer(Arc<App>);
3042

@@ -36,6 +48,22 @@ impl AppContainer {
3648
pub fn set_left(&self, left: Left) { *self.0.left.lock() = left; }
3749

3850
pub fn content(&self) -> &Arc<Mutex<Content>> { &self.0.content }
51+
52+
pub fn send_message(&self, message: UIMessage) {
53+
self.0.messages.lock().push(message);
54+
}
55+
}
56+
57+
impl AppContainer {
58+
pub fn process_messages(&mut self, server: &mut AsmServer) {
59+
for message in self.0.messages.lock().drain(..) {
60+
match message {
61+
UIMessage::OpenFile(message) => {
62+
server.switch_or_open(&message.path, self);
63+
}
64+
}
65+
}
66+
}
3967
}
4068

4169
#[derive(Default, Clone, Debug)]

0 commit comments

Comments
 (0)