1
1
// Copyright © SixtyFPS GmbH <info@slint.dev>
2
2
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
3
4
+ use std:: cell:: RefCell ;
5
+ use std:: num:: NonZeroUsize ;
6
+
4
7
use i_slint_compiler:: diagnostics:: { BuildDiagnostics , SourceFile } ;
5
8
use i_slint_compiler:: parser:: { syntax_nodes, SyntaxKind , SyntaxNode } ;
6
9
use i_slint_core:: lengths:: { LogicalPoint , LogicalRect , LogicalSize } ;
@@ -601,7 +604,7 @@ fn find_filtered_location(
601
604
602
605
/// Find the Element to insert into. None means we can not insert at this point.
603
606
pub fn can_drop_at ( position : LogicalPoint , component_type : & str ) -> bool {
604
- let dm = & super :: component_instance ( )
607
+ let dm = & preview :: component_instance ( )
605
608
. and_then ( |ci| find_drop_location ( & ci, position, component_type) ) ;
606
609
607
610
preview:: set_drop_mark ( & dm. as_ref ( ) . and_then ( |dm| dm. drop_mark . clone ( ) ) ) ;
@@ -616,27 +619,21 @@ pub fn workspace_edit_compiles(
616
619
return false ;
617
620
} ;
618
621
619
- let Some ( mut tmp_document_cache) = document_cache. snapshot ( ) else {
620
- return false ;
621
- } ;
622
622
let mut diag = BuildDiagnostics :: default ( ) ;
623
623
624
+ let mut document_cache = document_cache. snapshot ( ) . expect ( "This is not loading anything!" ) ;
625
+
624
626
// Fill in changed sources:
625
627
for ( u, c) in result. drain ( ..) . map ( |mut r| {
626
628
let contents = std:: mem:: take ( & mut r. contents ) ;
627
629
( r. url . clone ( ) , contents)
628
630
} ) {
629
- diag = BuildDiagnostics :: default ( ) ; // reset errors that might be due to missing changes elsewhere..
630
- // <debug>
631
- let _ = crate :: preview:: poll_once ( tmp_document_cache. load_url ( & u, None , c, & mut diag) ) ;
632
- }
631
+ diag = BuildDiagnostics :: default ( ) ; // reset errors that might be due to missing changes elsewhere
633
632
634
- if diag. has_error ( ) {
635
- eprintln ! ( "Compilation failed! Diagnostics:\n {}" , diag. diagnostics_as_string( ) ) ;
636
- return false ;
633
+ let _ = preview:: poll_once ( document_cache. load_url ( & u, None , c, & mut diag) ) ;
637
634
}
638
635
639
- true
636
+ !diag . has_error ( )
640
637
}
641
638
642
639
/// Find the Element to insert into. None means we can not insert at this point.
@@ -654,39 +651,57 @@ pub fn can_move_to(
654
651
let dm =
655
652
find_move_location ( & component_instance, mouse_position, & element_node, & component_type) ;
656
653
657
- if let Some ( dm) = & dm {
658
- if let Some ( ( edit, _) ) =
659
- create_move_element_workspace_edit ( & component_instance, dm, & element_node, position)
660
- {
661
- if let Some ( lsp_types:: DocumentChanges :: Edits ( e) ) = & edit. document_changes {
662
- for e in e {
663
- eprintln ! ( "Edit: {}" , e. text_document. uri) ;
664
- for e in & e. edits {
665
- match & e {
666
- lsp_types:: OneOf :: Left ( e) => {
667
- eprintln ! ( " {:?} => \" {}\" " , e. range, e. new_text) ;
668
- }
669
- _ => {
670
- eprintln ! ( "Annotated edit. No idea how that got here" ) ;
671
- }
672
- }
673
- }
674
- }
675
- } else {
676
- eprintln ! ( "No docuemnt changes in WorkspaceEdit!" ) ;
677
- }
654
+ let can_move = if let Some ( dm) = & dm {
655
+ // Cache compilation results:
656
+ #[ derive( Clone , Debug , Hash , Eq , PartialEq ) ]
657
+ struct CacheEntry {
658
+ source_element : by_address:: ByAddress < i_slint_compiler:: object_tree:: ElementRc > ,
659
+ source_node_index : usize ,
660
+ target_element : by_address:: ByAddress < i_slint_compiler:: object_tree:: ElementRc > ,
661
+ target_node_index : usize ,
662
+ child_index : usize ,
663
+ }
664
+ static mut CACHE : std:: cell:: OnceCell < RefCell < clru:: CLruCache < CacheEntry , bool > > > =
665
+ std:: cell:: OnceCell :: new ( ) ;
678
666
679
- if !workspace_edit_compiles ( document_cache, & edit) {
680
- preview:: set_drop_mark ( & None ) ;
681
- return false ;
682
- }
667
+ // SAFETY: This uses the document_cache, which means it runs in the UI thread.
668
+ let cache = unsafe {
669
+ CACHE . get_or_init ( || RefCell :: new ( clru:: CLruCache :: new ( NonZeroUsize :: new ( 10 ) . unwrap ( ) ) ) )
670
+ } ;
671
+ let mut cache = cache. borrow_mut ( ) ;
672
+
673
+ let cache_entry = CacheEntry {
674
+ source_element : by_address:: ByAddress ( element_node. element . clone ( ) ) ,
675
+ source_node_index : element_node. debug_index ,
676
+ target_element : by_address:: ByAddress ( dm. target_element_node . element . clone ( ) ) ,
677
+ target_node_index : dm. target_element_node . debug_index ,
678
+ child_index : dm. child_index ,
679
+ } ;
680
+
681
+ if let Some ( does_compile) = cache. get ( & cache_entry) {
682
+ * does_compile
683
+ } else {
684
+ let does_compile = if let Some ( ( edit, _) ) =
685
+ create_move_element_workspace_edit ( & component_instance, dm, & element_node, position)
686
+ {
687
+ workspace_edit_compiles ( document_cache, & edit)
688
+ } else {
689
+ false
690
+ } ;
691
+ cache. put ( cache_entry, does_compile) ;
692
+ does_compile
683
693
}
684
- preview:: set_drop_mark ( & dm. drop_mark ) ;
694
+ } else {
695
+ false
696
+ } ;
697
+
698
+ if can_move {
699
+ preview:: set_drop_mark ( & dm. unwrap ( ) . drop_mark ) ;
685
700
} else {
686
701
preview:: set_drop_mark ( & None ) ;
687
702
}
688
703
689
- dm . is_some ( )
704
+ can_move
690
705
}
691
706
692
707
/// Extra data on an added Element, relevant to the Preview side only.
@@ -1069,7 +1084,6 @@ pub fn move_element_to(
1069
1084
// Can not drop here: Ignore the move
1070
1085
return None ;
1071
1086
} ;
1072
-
1073
1087
create_move_element_workspace_edit ( & component_instance, & drop_info, & element, position)
1074
1088
. and_then ( |( e, d) | workspace_edit_compiles ( document_cache, & e) . then_some ( ( e, d) ) )
1075
1089
}
0 commit comments