@@ -67,8 +67,6 @@ pub enum FileBrowserMessage {
6767 Root ( Option < PathBuf > ) ,
6868 Path ( PathBuf ) ,
6969 Filter ( PathFilter ) ,
70- Add ( PathBuf ) ,
71- Remove ( PathBuf ) ,
7270 FocusCurrentPath ,
7371 Rescan ,
7472 Drop {
@@ -81,6 +79,13 @@ pub enum FileBrowserMessage {
8179}
8280impl MessageData for FileBrowserMessage { }
8381
82+ #[ derive( Debug , Clone , PartialEq ) ]
83+ enum FsEventMessage {
84+ Add ( PathBuf ) ,
85+ Remove ( PathBuf ) ,
86+ }
87+ impl MessageData for FsEventMessage { }
88+
8489#[ derive( Default , Clone , PartialEq , Eq , Hash , Debug , Visit , Reflect ) ]
8590pub enum FileBrowserMode {
8691 #[ default]
@@ -210,6 +215,88 @@ impl FileBrowser {
210215 self . rebuild_fs_tree ( ui)
211216 }
212217 }
218+
219+ fn set_root ( & mut self , root : & Option < PathBuf > , ui : & mut UserInterface ) {
220+ let watcher_replacement = match self . watcher . take ( ) {
221+ Some ( ( mut watcher, converter) ) => {
222+ let current_root = match & self . root {
223+ Some ( path) => path. clone ( ) ,
224+ None => self . path . clone ( ) ,
225+ } ;
226+ if current_root. exists ( ) {
227+ let _ = watcher. unwatch ( & current_root) ;
228+ }
229+ let new_root = match & root {
230+ Some ( path) => path. clone ( ) ,
231+ None => self . path . clone ( ) ,
232+ } ;
233+ let _ = watcher. watch ( & new_root, notify:: RecursiveMode :: Recursive ) ;
234+ Some ( ( watcher, converter) )
235+ }
236+ None => None ,
237+ } ;
238+ self . root . clone_from ( root) ;
239+ self . path = root. clone ( ) . unwrap_or_default ( ) ;
240+ self . rebuild_fs_tree ( ui) ;
241+ self . watcher = watcher_replacement;
242+ }
243+
244+ fn make_root_relative_path ( & self , path : & Path ) -> PathBuf {
245+ match self . root {
246+ Some ( ref root) => {
247+ let remove_prefix = if root == Path :: new ( "." ) {
248+ std:: env:: current_dir ( ) . unwrap ( )
249+ } else {
250+ root. clone ( )
251+ } ;
252+ PathBuf :: from ( "./" ) . join ( path. strip_prefix ( remove_prefix) . unwrap_or ( path) )
253+ }
254+ None => path. to_owned ( ) ,
255+ }
256+ }
257+
258+ fn on_file_added ( & mut self , path : & Path , ui : & mut UserInterface ) {
259+ let path = self . make_root_relative_path ( path) ;
260+ if !self . filter . passes ( & path) {
261+ return ;
262+ }
263+ let parent_path = parent_path ( & path) ;
264+ let existing_parent_node = fs_tree:: find_tree_item ( self . tree_root , & parent_path, ui) ;
265+ if existing_parent_node. is_some ( ) {
266+ if let Some ( tree) = ui. node ( existing_parent_node) . cast :: < Tree > ( ) {
267+ if tree. is_expanded {
268+ fs_tree:: build_tree (
269+ existing_parent_node,
270+ existing_parent_node == self . tree_root ,
271+ path,
272+ parent_path,
273+ self . item_context_menu . clone ( ) ,
274+ self . root_title . as_deref ( ) ,
275+ ui,
276+ ) ;
277+ } else if !tree. always_show_expander {
278+ ui. send ( tree. handle ( ) , TreeMessage :: SetExpanderShown ( true ) )
279+ }
280+ }
281+ }
282+ }
283+
284+ fn on_file_removed ( & mut self , path : & Path , ui : & mut UserInterface ) {
285+ let path = self . make_root_relative_path ( path) ;
286+ let node = fs_tree:: find_tree_item ( self . tree_root , & path, ui) ;
287+ if node. is_some ( ) {
288+ let parent_path = parent_path ( & path) ;
289+ let parent_node = fs_tree:: find_tree_item ( self . tree_root , & parent_path, ui) ;
290+ ui. send ( parent_node, TreeMessage :: RemoveItem ( node) )
291+ }
292+ }
293+
294+ fn handle_fs_event_message ( & mut self , msg : & FsEventMessage , ui : & mut UserInterface ) {
295+ match msg {
296+ FsEventMessage :: Add ( path) => self . on_file_added ( path, ui) ,
297+ FsEventMessage :: Remove ( path) => self . on_file_removed ( path, ui) ,
298+ }
299+ }
213300}
214301
215302uuid_provider ! ( FileBrowser = "b7f4610e-4b0c-4671-9b4a-60bb45268928" ) ;
@@ -218,7 +305,9 @@ impl Control for FileBrowser {
218305 fn handle_routed_message ( & mut self , ui : & mut UserInterface , message : & mut UiMessage ) {
219306 self . widget . handle_routed_message ( ui, message) ;
220307
221- if let Some ( msg) = message. data :: < FileBrowserMessage > ( ) {
308+ if let Some ( msg) = message. data_for :: < FsEventMessage > ( self . handle ( ) ) {
309+ self . handle_fs_event_message ( msg, ui) ;
310+ } else if let Some ( msg) = message. data :: < FileBrowserMessage > ( ) {
222311 if message. destination ( ) == self . handle ( ) {
223312 match msg {
224313 FileBrowserMessage :: Path ( path) => {
@@ -229,29 +318,7 @@ impl Control for FileBrowser {
229318 }
230319 FileBrowserMessage :: Root ( root) => {
231320 if & self . root != root {
232- let watcher_replacement = match self . watcher . take ( ) {
233- Some ( ( mut watcher, converter) ) => {
234- let current_root = match & self . root {
235- Some ( path) => path. clone ( ) ,
236- None => self . path . clone ( ) ,
237- } ;
238- if current_root. exists ( ) {
239- let _ = watcher. unwatch ( & current_root) ;
240- }
241- let new_root = match & root {
242- Some ( path) => path. clone ( ) ,
243- None => self . path . clone ( ) ,
244- } ;
245- let _ =
246- watcher. watch ( & new_root, notify:: RecursiveMode :: Recursive ) ;
247- Some ( ( watcher, converter) )
248- }
249- None => None ,
250- } ;
251- self . root . clone_from ( root) ;
252- self . path = root. clone ( ) . unwrap_or_default ( ) ;
253- self . rebuild_fs_tree ( ui) ;
254- self . watcher = watcher_replacement;
321+ self . set_root ( root, ui)
255322 }
256323 }
257324 FileBrowserMessage :: Filter ( filter) => {
@@ -260,44 +327,6 @@ impl Control for FileBrowser {
260327 self . rebuild_fs_tree ( ui) ;
261328 }
262329 }
263- FileBrowserMessage :: Add ( path) => {
264- let path =
265- make_fs_watcher_event_path_relative_to_tree_root ( & self . root , path) ;
266- if !self . filter . passes ( & path) {
267- return ;
268- }
269- let parent_path = parent_path ( & path) ;
270- let existing_parent_node =
271- fs_tree:: find_tree_item ( self . tree_root , & parent_path, ui) ;
272- if existing_parent_node. is_some ( ) {
273- if let Some ( tree) = ui. node ( existing_parent_node) . cast :: < Tree > ( ) {
274- if tree. is_expanded {
275- fs_tree:: build_tree (
276- existing_parent_node,
277- existing_parent_node == self . tree_root ,
278- path,
279- parent_path,
280- self . item_context_menu . clone ( ) ,
281- self . root_title . as_deref ( ) ,
282- ui,
283- ) ;
284- } else if !tree. always_show_expander {
285- ui. send ( tree. handle ( ) , TreeMessage :: SetExpanderShown ( true ) )
286- }
287- }
288- }
289- }
290- FileBrowserMessage :: Remove ( path) => {
291- let path =
292- make_fs_watcher_event_path_relative_to_tree_root ( & self . root , path) ;
293- let node = fs_tree:: find_tree_item ( self . tree_root , & path, ui) ;
294- if node. is_some ( ) {
295- let parent_path = parent_path ( & path) ;
296- let parent_node =
297- fs_tree:: find_tree_item ( self . tree_root , & parent_path, ui) ;
298- ui. send ( parent_node, TreeMessage :: RemoveItem ( node) )
299- }
300- }
301330 FileBrowserMessage :: Rescan | FileBrowserMessage :: Drop { .. } => ( ) ,
302331 FileBrowserMessage :: FocusCurrentPath => {
303332 if let Ok ( canonical_path) = self . path . canonicalize ( ) {
@@ -452,10 +481,10 @@ impl Control for FileBrowser {
452481 for path in event. paths . iter ( ) {
453482 match event. kind {
454483 notify:: EventKind :: Remove ( _) => {
455- ui. send ( self . handle , FileBrowserMessage :: Remove ( path. clone ( ) ) ) ;
484+ ui. send ( self . handle , FsEventMessage :: Remove ( path. clone ( ) ) ) ;
456485 }
457486 notify:: EventKind :: Create ( _) => {
458- ui. send ( self . handle , FileBrowserMessage :: Add ( path. clone ( ) ) ) ;
487+ ui. send ( self . handle , FsEventMessage :: Add ( path. clone ( ) ) ) ;
459488 }
460489 _ => ( ) ,
461490 }
@@ -478,23 +507,6 @@ fn parent_path(path: &Path) -> PathBuf {
478507 parent_path
479508}
480509
481- fn make_fs_watcher_event_path_relative_to_tree_root (
482- root : & Option < PathBuf > ,
483- path : & Path ,
484- ) -> PathBuf {
485- match root {
486- Some ( ref root) => {
487- let remove_prefix = if root == Path :: new ( "." ) {
488- std:: env:: current_dir ( ) . unwrap ( )
489- } else {
490- root. clone ( )
491- } ;
492- PathBuf :: from ( "./" ) . join ( path. strip_prefix ( remove_prefix) . unwrap_or ( path) )
493- }
494- None => path. to_owned ( ) ,
495- }
496- }
497-
498510pub struct FileBrowserBuilder {
499511 widget_builder : WidgetBuilder ,
500512 path : PathBuf ,
0 commit comments