11use crate :: app:: EguiApp ;
2+ use bit_set:: BitSet ;
23use egui:: containers:: PopupCloseBehavior ;
3- use egui:: { popup_below_widget, Context , Id , Response , TextEdit , Ui } ;
4+ use egui:: text:: LayoutJob ;
5+ use egui:: { popup_below_widget, Context , Id , Response , TextEdit , TextFormat , TextStyle , Ui } ;
46use java_asm_server:: AsmServer ;
57use std:: ops:: Deref ;
68
@@ -58,7 +60,7 @@ impl EguiApp {
5860 let search_results = locked_top. search_result . clone ( ) ;
5961 drop ( locked_top) ;
6062
61- if search_results. is_empty ( ) { return ; }
63+ if search_results. items . is_empty ( ) { return ; }
6264 popup_below_widget (
6365 ui, popup_id, & edit_path_ui,
6466 PopupCloseBehavior :: CloseOnClickOutside , |ui| {
@@ -88,13 +90,65 @@ impl EguiApp {
8890
8991 fn popup_file_path_ui ( & mut self , ui : & mut Ui ) {
9092 let search_results = self . server_app . top ( ) . lock ( ) . search_result . clone ( ) ;
91- for result in search_results {
92- let selectable_label = ui. selectable_label ( false , result. to_string ( ) ) ;
93+ let style = ui. style ( ) ;
94+ let font = TextStyle :: Monospace . resolve ( & style) ;
95+
96+ let dark_mode = style. visuals . dark_mode ;
97+ let smali_style = if dark_mode { crate :: smali:: SmaliStyle :: DARK } else { crate :: smali:: SmaliStyle :: LIGHT } ;
98+
99+ let dft_color = style. visuals . text_color ( ) ;
100+ let dft_text_format = TextFormat :: simple ( font. clone ( ) , dft_color) ;
101+ let highlight_color = smali_style. desc ;
102+ let highlight_text_format = TextFormat :: simple ( font, highlight_color) ;
103+
104+
105+ for result in search_results. items {
106+ let path = result. item . to_string ( ) ;
107+ let sections = Self :: get_highlight_sections ( & path, result. indices ) ;
108+ let mut text_layout_job = LayoutJob :: default ( ) ;
109+ for ( section, highlighted) in sections {
110+ if highlighted {
111+ text_layout_job. append ( & section, 0.0 , highlight_text_format. clone ( ) )
112+ } else {
113+ text_layout_job. append ( & section, 0.0 , dft_text_format. clone ( ) )
114+ }
115+ }
116+ let selectable_label = ui. selectable_label ( false , text_layout_job) ;
93117 if selectable_label. clicked ( ) {
94118 let server_locked = self . server . lock ( ) ;
95119 let Some ( server) = server_locked. deref ( ) else { return ; } ;
96- server. switch_or_open ( & result, & self . server_app ) ;
120+ server. switch_or_open ( & result. item , & self . server_app ) ;
121+ ui. memory_mut ( |m| m. close_popup ( ) ) ;
97122 }
98123 }
99124 }
125+
126+ fn get_highlight_sections ( path : & str , bits : BitSet ) -> Vec < ( String , bool ) > {
127+ let mut current_section = String :: new ( ) ;
128+ let mut cur_highlighted = false ;
129+
130+ let mut sections = vec ! [ ] ;
131+ for ( index, ch) in path. chars ( ) . enumerate ( ) {
132+ let target_highlighted = bits. contains ( index) ;
133+ if current_section. is_empty ( ) {
134+ // first char in this section, init
135+ current_section. push ( ch) ;
136+ cur_highlighted = target_highlighted;
137+ } else if cur_highlighted == target_highlighted {
138+ // same highlight
139+ current_section. push ( ch) ;
140+ } else {
141+ // different color, start new section
142+ sections. push ( ( current_section, cur_highlighted) ) ;
143+ current_section = ch. to_string ( ) ;
144+ cur_highlighted = target_highlighted;
145+ }
146+ }
147+
148+ // last section
149+ if !current_section. is_empty ( ) {
150+ sections. push ( ( current_section, cur_highlighted) ) ;
151+ }
152+ sections
153+ }
100154}
0 commit comments