1
1
use eframe:: epaint:: Color32 ;
2
2
use egui:: text:: LayoutJob ;
3
- use egui:: { FontId , Response , ScrollArea , TextStyle , Ui } ;
3
+ use egui:: { CursorIcon , FontId , Response , ScrollArea , TextStyle , Ui , Vec2 } ;
4
4
use java_asm:: smali:: SmaliToken ;
5
5
use java_asm_server:: ui:: { AppContainer , Content } ;
6
6
use java_asm_server:: AsmServer ;
@@ -23,61 +23,120 @@ pub fn smali_layout(ui: &mut Ui, server: &AsmServer, app: &AppContainer) {
23
23
let smali_style = if dark_mode { SmaliStyle :: DARK } else { SmaliStyle :: LIGHT } ;
24
24
25
25
let lines = smali_node. render_to_lines ( ) ;
26
- let row_height = font . size ;
26
+ let row_height = ui . text_style_height ( & TextStyle :: Monospace ) ;
27
27
28
28
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| {
30
42
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) ;
33
44
}
34
45
} ) ;
35
46
}
36
47
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 ,
47
58
}
48
59
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
+ }
64
91
}
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| {
69
129
descriptor_menu ( ui, s, server, content) ;
70
130
} ) ;
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
+ }
78
136
}
79
137
}
80
138
139
+
81
140
fn descriptor_menu (
82
141
ui : & mut Ui , descriptor : & str ,
83
142
server : & AsmServer , content : & mut Content ,
0 commit comments