@@ -27,10 +27,86 @@ impl LogEntry {
2727 }
2828}
2929
30- #[ allow( dead_code) ]
30+ #[ derive( Clone , Copy ) ]
31+ pub enum LogTextCtrl {
32+ Styled ( StyledTextCtrl ) ,
33+ Plain ( TextCtrl ) ,
34+ }
35+
36+ impl LogTextCtrl {
37+ pub fn append_text ( & self , text : & str ) {
38+ match self {
39+ LogTextCtrl :: Styled ( ctrl) => ctrl. append_text ( text) ,
40+ LogTextCtrl :: Plain ( ctrl) => ctrl. append_text ( text) ,
41+ }
42+ }
43+
44+ pub fn clear_all ( & self ) {
45+ match self {
46+ LogTextCtrl :: Styled ( ctrl) => ctrl. clear_all ( ) ,
47+ LogTextCtrl :: Plain ( ctrl) => ctrl. clear ( ) ,
48+ }
49+ }
50+
51+ pub fn get_end_position ( & self ) -> i64 {
52+ match self {
53+ LogTextCtrl :: Styled ( ctrl) => ctrl. get_length ( ) as i64 ,
54+ LogTextCtrl :: Plain ( ctrl) => ctrl. get_last_position ( ) ,
55+ }
56+ }
57+
58+ #[ allow( dead_code) ]
59+ pub fn set_selection_mode_typed ( & self , mode : SelectionMode ) {
60+ if let LogTextCtrl :: Styled ( ctrl) = self {
61+ ctrl. set_selection_mode_typed ( mode) ;
62+ }
63+ }
64+
65+ pub fn start_styling ( & self , start : i32 ) {
66+ if let LogTextCtrl :: Styled ( ctrl) = self {
67+ ctrl. start_styling ( start) ;
68+ }
69+ }
70+
71+ pub fn set_styling ( & self , length : i32 , style : i32 ) {
72+ if let LogTextCtrl :: Styled ( ctrl) = self {
73+ ctrl. set_styling ( length, style) ;
74+ }
75+ }
76+
77+ pub fn goto_end ( & self ) {
78+ match self {
79+ LogTextCtrl :: Styled ( ctrl) => {
80+ let end = ctrl. get_length ( ) ;
81+ ctrl. goto_pos ( end) ;
82+ ctrl. ensure_caret_visible ( ) ;
83+ }
84+ LogTextCtrl :: Plain ( ctrl) => {
85+ ctrl. set_insertion_point_end ( ) ;
86+ }
87+ }
88+ }
89+
90+ pub fn scroll_to_end ( & self ) {
91+ match self {
92+ LogTextCtrl :: Styled ( ctrl) => ctrl. scroll_to_end ( ) ,
93+ LogTextCtrl :: Plain ( ctrl) => ctrl. scroll_to_end ( ) ,
94+ }
95+ }
96+ }
97+
3198pub struct LogViewPanel {
3299 pub panel : Panel ,
33- pub text_ctrl : StyledTextCtrl ,
100+ pub text_ctrl : LogTextCtrl ,
101+ }
102+
103+ impl LogTextCtrl {
104+ pub fn add_to_sizer ( & self , sizer : & BoxSizer , proportion : i32 , flag : SizerFlag , border : i32 ) {
105+ match self {
106+ LogTextCtrl :: Styled ( ctrl) => sizer. add ( ctrl, proportion, flag, border) ,
107+ LogTextCtrl :: Plain ( ctrl) => sizer. add ( ctrl, proportion, flag, border) ,
108+ } ;
109+ }
34110}
35111
36112impl LogViewPanel {
@@ -62,39 +138,50 @@ impl LogViewPanel {
62138 ctrl. style_set_size ( STYLE_TRACE , 10 ) ;
63139 }
64140
65- pub fn new ( parent : & Panel ) -> Self {
141+ pub fn new ( parent : & Panel , use_color : bool ) -> Self {
66142 let panel = Panel :: builder ( parent) . build ( ) ;
67143 let sizer = BoxSizer :: builder ( Orientation :: Vertical ) . build ( ) ;
68- let text_ctrl = StyledTextCtrl :: builder ( & panel) . with_size ( Size :: new ( -1 , 200 ) ) . build ( ) ;
69- text_ctrl. set_min_size ( Size :: new ( -1 , 200 ) ) ;
70- text_ctrl. set_selection_mode_typed ( SelectionMode :: Stream ) ;
71- Self :: init_log_styles ( & text_ctrl) ;
72- sizer. add ( & text_ctrl, 1 , SizerFlag :: Expand | SizerFlag :: All , crate :: settings:: WIDGET_MARGIN ) ;
144+ let text_ctrl = if use_color {
145+ let ctrl = StyledTextCtrl :: builder ( & panel) . with_size ( Size :: new ( -1 , 200 ) ) . build ( ) ;
146+ ctrl. set_min_size ( Size :: new ( -1 , 200 ) ) ;
147+ ctrl. set_selection_mode_typed ( SelectionMode :: Stream ) ;
148+ Self :: init_log_styles ( & ctrl) ;
149+ LogTextCtrl :: Styled ( ctrl)
150+ } else {
151+ let ctrl = TextCtrl :: builder ( & panel)
152+ . with_size ( Size :: new ( -1 , 200 ) )
153+ . with_style ( TextCtrlStyle :: MultiLine | TextCtrlStyle :: ReadOnly )
154+ . build ( ) ;
155+ ctrl. set_min_size ( Size :: new ( -1 , 200 ) ) ;
156+ LogTextCtrl :: Plain ( ctrl)
157+ } ;
158+
159+ text_ctrl. add_to_sizer ( & sizer, 1 , SizerFlag :: Expand | SizerFlag :: All , crate :: settings:: WIDGET_MARGIN ) ;
73160 panel. set_sizer ( sizer, true ) ;
74161 Self { panel, text_ctrl }
75162 }
76163}
77164
78- // UI-thread local storage for the log StyledTextCtrl . This avoids Send/Sync issues
165+ // UI-thread local storage for the log control . This avoids Send/Sync issues
79166// by ensuring the control is only ever accessed on the UI thread.
80167thread_local ! {
81- pub static LOG_TEXT_CTRL : RefCell <Option <StyledTextCtrl >> = const { RefCell :: new( None ) } ;
168+ pub static LOG_TEXT_CTRL : RefCell <Option <LogTextCtrl >> = const { RefCell :: new( None ) } ;
82169 // A UI-thread log ring buffer; we render from here instead of reading back from the control
83170 pub static LOG_RING : RefCell <VecDeque <LogEntry >> = const { RefCell :: new( VecDeque :: new( ) ) } ;
84171}
85172
86- fn append_text_entry ( ctrl : & StyledTextCtrl , entry : & LogEntry ) {
87- let start = ctrl. get_length ( ) ;
173+ fn append_text_entry ( ctrl : & LogTextCtrl , entry : & LogEntry ) {
174+ let start = ctrl. get_end_position ( ) ;
88175 ctrl. append_text ( & entry. text ) ;
89- let end = ctrl. get_length ( ) ;
90- let length = end. saturating_sub ( start) ;
176+ let end = ctrl. get_end_position ( ) ;
177+ let length = end. saturating_sub ( start) as i32 ;
91178 if length > 0 {
92- ctrl. start_styling ( start) ;
179+ ctrl. start_styling ( start as i32 ) ;
93180 ctrl. set_styling ( length, entry. style ( ) ) ;
94181 }
95182}
96183
97- fn rebuild_log_text ( ctrl : & StyledTextCtrl , ring : & VecDeque < LogEntry > ) {
184+ fn rebuild_log_text ( ctrl : & LogTextCtrl , ring : & VecDeque < LogEntry > ) {
98185 ctrl. clear_all ( ) ;
99186 for entry in ring. iter ( ) {
100187 append_text_entry ( ctrl, entry) ;
@@ -131,12 +218,9 @@ pub fn ui_append_logs(lines: Vec<(log::Level, String)>, max_lines: usize, auto_s
131218 }
132219 }
133220
134- let end = ctrl. get_length ( ) ;
135- ctrl. goto_pos ( end) ;
136- ctrl. ensure_caret_visible ( ) ;
221+ ctrl. goto_end ( ) ;
137222 if auto_scroll {
138- let last_line = ctrl. get_line_count ( ) . saturating_sub ( 1 ) ;
139- ctrl. scroll_to_line ( last_line) ;
223+ ctrl. scroll_to_end ( ) ;
140224 }
141225 }
142226 } ) ;
0 commit comments