11use eframe:: epaint:: Color32 ;
22use egui:: text:: LayoutJob ;
3- use egui:: { FontId , Response , ScrollArea , TextStyle , Ui } ;
3+ use egui:: { CursorIcon , FontId , Response , ScrollArea , TextStyle , Ui , Vec2 } ;
44use java_asm:: smali:: SmaliToken ;
55use java_asm_server:: ui:: { AppContainer , Content } ;
66use java_asm_server:: AsmServer ;
@@ -23,61 +23,120 @@ pub fn smali_layout(ui: &mut Ui, server: &AsmServer, app: &AppContainer) {
2323 let smali_style = if dark_mode { SmaliStyle :: DARK } else { SmaliStyle :: LIGHT } ;
2424
2525 let lines = smali_node. render_to_lines ( ) ;
26- let row_height = font . size ;
26+ let row_height = ui . text_style_height ( & TextStyle :: Monospace ) ;
2727
2828 let content_mut = content_locked. deref_mut ( ) ;
29- ScrollArea :: vertical ( ) . auto_shrink ( false ) . show_rows ( ui, row_height, lines. len ( ) , |ui, range| {
29+ let scroll_area = ScrollArea :: vertical ( ) . auto_shrink ( false ) ;
30+ let spacing_y = ui. spacing ( ) . item_spacing . y ;
31+ let mut render_context = RenderContext {
32+ server,
33+ font : & font,
34+ content : content_mut,
35+ lines : & lines,
36+ smali_style : & smali_style,
37+ dft_color,
38+ row_height,
39+ spacing_y,
40+ } ;
41+ scroll_area. show_rows ( ui, row_height, lines. len ( ) , |ui, range| {
3042 for i in range {
31- let line = & lines[ i] ;
32- render_line ( ui, server, content_mut, line, & font, & smali_style, dft_color) ;
43+ render_context. render_line ( ui, i) ;
3344 }
3445 } ) ;
3546}
3647
37- fn render_line (
38- ui : & mut Ui , server : & AsmServer , content : & mut Content , line : & [ SmaliToken ] ,
39- font : & FontId , smali_style : & SmaliStyle , dft_color : Color32 ,
40- ) {
41- ui . horizontal ( |ui| {
42- ui . spacing_mut ( ) . item_spacing . x = 0.0 ;
43- for token_item in line {
44- token ( ui , server , content , token_item , font , smali_style , dft_color ) ;
45- }
46- } ) ;
48+ struct RenderContext < ' a > {
49+ pub server : & ' a AsmServer ,
50+ pub content : & ' a mut Content ,
51+ pub lines : & ' a Vec < Vec < SmaliToken > > ,
52+
53+ pub font : & ' a FontId ,
54+ pub smali_style : & ' a SmaliStyle ,
55+ pub dft_color : Color32 ,
56+ pub row_height : f32 ,
57+ pub spacing_y : f32 ,
4758}
4859
49- fn token (
50- ui : & mut Ui , server : & AsmServer , content : & mut Content , token : & SmaliToken ,
51- font : & FontId , smali_style : & SmaliStyle , dft_color : Color32 ,
52- ) -> Response {
53- match token {
54- SmaliToken :: Raw ( s) => simple_text ( ui, s. to_string ( ) , font, dft_color) ,
55- SmaliToken :: Op ( s) => simple_text ( ui, s. to_string ( ) , font, smali_style. op ) ,
56- SmaliToken :: Offset { relative, absolute } => {
57- let text = format ! ( "@{absolute}({relative:+})" ) ;
58- simple_text ( ui, text, font, smali_style. offset )
59- }
60- SmaliToken :: Register ( s) => simple_text ( ui, format ! ( "v{s}" ) , font, smali_style. register ) ,
61- SmaliToken :: RegisterRange ( start, end) => {
62- let text = format ! ( "v{start}..v{end}" ) ;
63- simple_text ( ui, text, font, smali_style. register )
60+ impl < ' a > RenderContext < ' a > {
61+ pub fn render_line ( & mut self , ui : & mut Ui , line_index : usize ) {
62+ let line = & self . lines [ line_index] ;
63+ ui. horizontal ( |ui| {
64+ ui. spacing_mut ( ) . item_spacing . x = 0.0 ;
65+ for token_item in line {
66+ self . token ( ui, token_item, line_index) ;
67+ }
68+ } ) ;
69+ }
70+
71+ fn scroll_lines ( & self , ui : & mut Ui , line_delta : usize ) {
72+ let row_height_with_spacing = self . row_height + self . spacing_y ;
73+ let y_delta = line_delta as f32 * row_height_with_spacing;
74+ let delta = Vec2 :: new ( 0.0 , -y_delta) ;
75+ ui. scroll_with_delta ( delta)
76+ }
77+
78+ fn scroll_to_offset ( & self , ui : & mut Ui , current_line : usize , target_offset : u32 ) {
79+ let start = current_line;
80+ let mut i = current_line;
81+ loop {
82+ let current = i;
83+ i += 1 ;
84+ let Some ( current_line) = self . lines . get ( current) else { continue ; } ;
85+ let Some ( first_node) = current_line. first ( ) else { continue ; } ;
86+ let SmaliToken :: LineStartOffsetMarker { offset : Some ( current_offset) , .. } = first_node else { continue ; } ;
87+ if * current_offset >= target_offset {
88+ self . scroll_lines ( ui, current - start) ;
89+ break ;
90+ }
6491 }
65- SmaliToken :: Descriptor ( s) => {
66- let text_ui = simple_text ( ui, s. to_string ( ) , font, smali_style. desc )
67- . on_hover_ui ( |ui| {
68- ui. style_mut ( ) . interaction . selectable_labels = true ;
92+ }
93+
94+
95+ fn token (
96+ & mut self , ui : & mut Ui , token : & SmaliToken , line_index : usize ,
97+ ) -> Response {
98+ let RenderContext {
99+ server, content, font, smali_style, dft_color, ..
100+ } = self ;
101+ let dft_color = * dft_color;
102+ match token {
103+ SmaliToken :: Raw ( s) => simple_text ( ui, s. to_string ( ) , font, dft_color) ,
104+ SmaliToken :: Op ( s) => simple_text ( ui, s. to_string ( ) , font, smali_style. op ) ,
105+ SmaliToken :: LineStartOffsetMarker { raw, .. } => {
106+ simple_text ( ui, raw. to_string ( ) , font, dft_color)
107+ } ,
108+ SmaliToken :: Offset { relative, absolute } => {
109+ let text = format ! ( "@{absolute}({relative:+})" ) ;
110+ let text_ui = simple_text ( ui, text, font, smali_style. offset )
111+ . on_hover_cursor ( CursorIcon :: PointingHand ) ;
112+ if text_ui. clicked ( ) {
113+ self . scroll_to_offset ( ui, line_index, * absolute) ;
114+ }
115+ text_ui
116+ }
117+ SmaliToken :: Register ( s) => simple_text ( ui, format ! ( "v{s}" ) , font, smali_style. register ) ,
118+ SmaliToken :: RegisterRange ( start, end) => {
119+ let text = format ! ( "v{start}..v{end}" ) ;
120+ simple_text ( ui, text, font, smali_style. register )
121+ }
122+ SmaliToken :: Descriptor ( s) => {
123+ let text_ui = simple_text ( ui, s. to_string ( ) , font, smali_style. desc )
124+ . on_hover_ui ( |ui| {
125+ ui. style_mut ( ) . interaction . selectable_labels = true ;
126+ descriptor_menu ( ui, s, server, content) ;
127+ } ) ;
128+ text_ui. context_menu ( |ui| {
69129 descriptor_menu ( ui, s, server, content) ;
70130 } ) ;
71- text_ui. context_menu ( |ui| {
72- descriptor_menu ( ui, s, server, content) ;
73- } ) ;
74- text_ui
75- } ,
76- SmaliToken :: Literal ( s) => simple_text ( ui, s. to_string ( ) , font, smali_style. literal ) ,
77- SmaliToken :: Other ( s) => simple_text ( ui, s. to_string ( ) , font, dft_color) ,
131+ text_ui
132+ } ,
133+ SmaliToken :: Literal ( s) => simple_text ( ui, s. to_string ( ) , font, smali_style. literal ) ,
134+ SmaliToken :: Other ( s) => simple_text ( ui, s. to_string ( ) , font, dft_color) ,
135+ }
78136 }
79137}
80138
139+
81140fn descriptor_menu (
82141 ui : & mut Ui , descriptor : & str ,
83142 server : & AsmServer , content : & mut Content ,
0 commit comments