@@ -5,7 +5,7 @@ use std::rc::Rc;
55
66use spring_native:: {
77 prelude:: { Error , NativeInterfaceRef } ,
8- RmlDataTextRows , RmlDataVariable ,
8+ RmlDataLogRows , RmlDataTextRows , RmlDataVariable , RmlLogRow , RmlLogSeverity ,
99} ;
1010
1111use crate :: sbc:: devconsole:: actions:: Action ;
@@ -98,13 +98,13 @@ pub(crate) struct DevConsoleView {
9898 status_position : Option < RmlDataVariable < ' static , String > > ,
9999 status_version : Option < RmlDataVariable < ' static , String > > ,
100100 status_metrics : Option < StatusMetricBindings > ,
101+ status_action_disabled : [ Option < RmlDataVariable < ' static , bool > > ; 3 ] ,
101102 status_history : Option < RmlDataTextRows < ' static > > ,
102- status_history_muted : Vec < bool > ,
103103 error_count : Option < RmlDataVariable < ' static , String > > ,
104104 line_count : Option < RmlDataVariable < ' static , String > > ,
105- log_rows : Option < RmlDataTextRows < ' static > > ,
106- rendered_log_rows : Vec < RenderedLogRow > ,
107- log_rows_dirty : bool ,
105+ log_rows : Option < RmlDataLogRows < ' static > > ,
106+ log_row_listeners_bound : usize ,
107+ log_row_count : usize ,
108108 /// Last history rendered into the command list. Metrics refresh regularly,
109109 /// but rebuilding this scroll container each frame would steal its scroll
110110 /// position from someone reading older edits.
@@ -127,14 +127,13 @@ struct SelectionState {
127127}
128128
129129struct StatusMetricBindings {
130- performance : [ RmlDataVariable < ' static , String > ; 3 ] ,
131- system : [ RmlDataVariable < ' static , String > ; 4 ] ,
130+ performance : [ StatusMetricBinding ; 3 ] ,
131+ system : [ StatusMetricBinding ; 4 ] ,
132132}
133133
134- #[ derive( Clone , Copy ) ]
135- struct RenderedLogRow {
136- severity : crate :: sbc:: devconsole:: log:: Severity ,
137- selected : bool ,
134+ struct StatusMetricBinding {
135+ value : RmlDataVariable < ' static , String > ,
136+ tones : [ RmlDataVariable < ' static , bool > ; 4 ] ,
138137}
139138
140139impl SelectionState {
@@ -159,13 +158,13 @@ impl Default for DevConsoleView {
159158 status_position : None ,
160159 status_version : None ,
161160 status_metrics : None ,
161+ status_action_disabled : [ None ; 3 ] ,
162162 status_history : None ,
163- status_history_muted : Vec :: new ( ) ,
164163 error_count : None ,
165164 line_count : None ,
166165 log_rows : None ,
167- rendered_log_rows : Vec :: new ( ) ,
168- log_rows_dirty : false ,
166+ log_row_listeners_bound : 0 ,
167+ log_row_count : 0 ,
169168 rendered_command_log : None ,
170169 hidden : None ,
171170 toolbar_pressed : [ None ; 10 ] ,
@@ -255,7 +254,7 @@ impl DevConsoleView {
255254 let data_model = rml. create_data_model ( ctx, "dev_console" ) ?;
256255 self . error_count = Some ( data_model. bind ( "error_count" , String :: new ( ) ) ?) ;
257256 self . line_count = Some ( data_model. bind ( "line_count" , String :: new ( ) ) ?) ;
258- self . log_rows = Some ( data_model. bind_text_rows ( "log_lines" ) ?) ;
257+ self . log_rows = Some ( data_model. bind_log_rows ( "log_lines" ) ?) ;
259258 self . hidden = Some ( data_model. bind ( "hidden" , !self . visible ) ?) ;
260259 for ( index, action) in Action :: ALL . iter ( ) . copied ( ) . enumerate ( ) {
261260 self . toolbar_pressed [ index] = Some ( data_model. bind ( action. pressed_binding ( ) , false ) ?) ;
@@ -311,16 +310,16 @@ impl DevConsoleView {
311310 return Ok ( ( ) ) ;
312311 } ;
313312 let mut rows = Vec :: new ( ) ;
314- let mut rendered_rows = Vec :: new ( ) ;
315313 let mut count = 0usize ;
316314 for ( index, line) in lines. enumerate ( ) {
317315 count = index + 1 ;
318- rows. push ( spring_native :: RmlTextRow {
316+ rows. push ( RmlLogRow {
319317 text : clamp_line ( & line. text ) . into_owned ( ) ,
320- muted : false ,
321- } ) ;
322- rendered_rows. push ( RenderedLogRow {
323- severity : line. severity ,
318+ severity : match line. severity {
319+ crate :: sbc:: devconsole:: log:: Severity :: Info => RmlLogSeverity :: Info ,
320+ crate :: sbc:: devconsole:: log:: Severity :: Warning => RmlLogSeverity :: Warning ,
321+ crate :: sbc:: devconsole:: log:: Severity :: Error => RmlLogSeverity :: Error ,
322+ } ,
324323 selected : self . selection . contains ( index) ,
325324 } ) ;
326325 }
@@ -331,8 +330,7 @@ impl DevConsoleView {
331330 }
332331 if let Some ( log_rows) = & self . log_rows {
333332 log_rows. set ( & rows) ?;
334- self . rendered_log_rows = rendered_rows;
335- self . log_rows_dirty = true ;
333+ self . log_row_count = rows. len ( ) ;
336334 }
337335 if scroll_to_bottom {
338336 let _ = interface. rml_ui ( ) . element_set_scroll_top ( log, 1_000_000 ) ;
@@ -415,7 +413,6 @@ impl DevConsoleView {
415413 geometry. viewSizeY ,
416414 ) ;
417415 interface. rml_ui ( ) . context_update ( context) ?;
418- self . sync_status_history_tones ( interface) ?;
419416 }
420417 Ok ( ( ) )
421418 }
@@ -429,15 +426,15 @@ impl DevConsoleView {
429426 self . status_position = None ;
430427 self . status_version = None ;
431428 self . status_metrics = None ;
429+ self . status_action_disabled = [ None ; 3 ] ;
432430 self . status_history = None ;
433- self . status_history_muted . clear ( ) ;
434431 self . error_count = None ;
435432 self . line_count = None ;
436433 self . log_rows = None ;
437434 self . hidden = None ;
438435 self . toolbar_pressed = [ None ; 10 ] ;
439- self . rendered_log_rows . clear ( ) ;
440- self . log_rows_dirty = false ;
436+ self . log_row_listeners_bound = 0 ;
437+ self . log_row_count = 0 ;
441438 self . rendered_command_log = None ;
442439 self . log = None ;
443440 self . actions . borrow_mut ( ) . clear ( ) ;
@@ -459,15 +456,15 @@ impl DevConsoleView {
459456 self . status_position = None ;
460457 self . status_version = None ;
461458 self . status_metrics = None ;
459+ self . status_action_disabled = [ None ; 3 ] ;
462460 self . status_history = None ;
463- self . status_history_muted . clear ( ) ;
464461 self . error_count = None ;
465462 self . line_count = None ;
466463 self . log_rows = None ;
467464 self . hidden = None ;
468465 self . toolbar_pressed = [ None ; 10 ] ;
469- self . rendered_log_rows . clear ( ) ;
470- self . log_rows_dirty = false ;
466+ self . log_row_listeners_bound = 0 ;
467+ self . log_row_count = 0 ;
471468 if let Some ( doc) = self . document . take ( ) {
472469 let _ = rml. document_close ( doc) ;
473470 }
@@ -491,26 +488,17 @@ impl DevConsoleView {
491488 }
492489
493490 fn sync_log_rows ( & mut self , interface : & NativeInterfaceRef ) -> Result < ( ) , Error > {
494- if !self . log_rows_dirty {
495- return Ok ( ( ) ) ;
496- }
497491 let Some ( log) = self . log else {
498492 return Ok ( ( ) ) ;
499493 } ;
500494 let rml = interface. rml_ui ( ) ;
501- for ( index, row) in self . rendered_log_rows . iter ( ) . copied ( ) . enumerate ( ) {
495+ let mut bound = self . log_row_listeners_bound ;
496+ while bound < self . log_row_count {
497+ let index = bound;
502498 let ( line, exists) = rml. element_get_child ( log, index as i32 ) ?;
503499 if !exists {
504- continue ;
500+ break ;
505501 }
506- for severity in [
507- crate :: sbc:: devconsole:: log:: Severity :: Info ,
508- crate :: sbc:: devconsole:: log:: Severity :: Warning ,
509- crate :: sbc:: devconsole:: log:: Severity :: Error ,
510- ] {
511- rml. element_set_class ( line, severity. css_class ( ) , row. severity == severity) ?;
512- }
513- rml. element_set_class ( line, "selected" , row. selected ) ?;
514502 let queue = self . selection_events . clone ( ) ;
515503 rml. element_add_event_listener ( line, "mousedown" , false , move || {
516504 queue. borrow_mut ( ) . push ( SelectionEvent :: Start ( index) )
@@ -519,28 +507,9 @@ impl DevConsoleView {
519507 rml. element_add_event_listener ( line, "mouseover" , false , move || {
520508 queue. borrow_mut ( ) . push ( SelectionEvent :: Extend ( index) )
521509 } ) ?;
510+ bound += 1 ;
522511 }
523- self . log_rows_dirty = false ;
524- Ok ( ( ) )
525- }
526-
527- /// RmlUi currently evaluates `data-class-*` on a generated `data-for`
528- /// child after that child was removed from a shrinking collection. Apply
529- /// this semantic class after the collection's structural update instead;
530- /// values remain native data bindings and no row markup is rebuilt.
531- fn sync_status_history_tones ( & self , interface : & NativeInterfaceRef ) -> Result < ( ) , Error > {
532- let Some ( document) = self . status_document else {
533- return Ok ( ( ) ) ;
534- } ;
535- let Some ( list) = element_by_id ( interface, document, "command-list" ) else {
536- return Ok ( ( ) ) ;
537- } ;
538- for ( index, muted) in self . status_history_muted . iter ( ) . copied ( ) . enumerate ( ) {
539- let ( row, exists) = interface. rml_ui ( ) . element_get_child ( list, index as i32 ) ?;
540- if exists {
541- interface. rml_ui ( ) . element_set_class ( row, "undone" , muted) ?;
542- }
543- }
512+ self . log_row_listeners_bound = bound;
544513 Ok ( ( ) )
545514 }
546515}
0 commit comments