private void OnFileSystemItemCreated(object sender, FileSystemEventArgs e)
 {
     if (System.IO.Directory.Exists(e.FullPath))
     {
         var createdDirectoryInfo = new DirectoryInfo(e.FullPath);
         if (!Index.TryGetValue(createdDirectoryInfo.Parent.FullName, out IFileSystemItemModel parentFileSystemItem) ||
             parentFileSystemItem is not IDirectory parentDirectoryItem)
         {
             // File system item is not indexed/never visited before.
             // Changes will be visible the first time this folder or its child items are indexed/visited
             return;
         }
         var createdDirectoryItem = DirectoryFactory.Invoke(createdDirectoryInfo, parentDirectoryItem);
         AddNewFileSystemInfo(createdDirectoryItem, parentDirectoryItem);
     }
     else if (System.IO.File.Exists(e.FullPath))
     {
         var createdFileInfo = new FileInfo(e.FullPath);
         if (!Index.TryGetValue(createdFileInfo.DirectoryName, out IFileSystemItemModel parentFileSystemItem) ||
             parentFileSystemItem is not IDirectory parentDirectoryItem)
         {
             // File system item is not indexed/never visited before.
             // Changes will be visible the first time this folder or its child items are indexed/visited
             return;
         }
         var createdFileItem = FileFactory.Invoke(createdFileInfo, parentDirectoryItem);
         AddNewFileSystemInfo(createdFileItem, parentDirectoryItem);
     }
 }
        public FileSystem()
        {
            FileSystemEnumerationOptions = new EnumerationOptions()
            {
                AttributesToSkip         = 0,
                ReturnSpecialDirectories = false,
                IgnoreInaccessible       = true
            };

            IsShowingFileExtensions = true;
            FileSystemItemFactory   = (fileSystemInfo, parent, isDrive) => new FileSystemItemModel(fileSystemInfo, parent, isDrive);
            FileFactory             = (fileInfo, parent) => new File(fileInfo, parent);
            DirectoryFactory        = (directoryInfo, parent) => new Directory(directoryInfo, parent);
            DriveFactory            = (driveInfo) => new Drive(driveInfo, FileSystemMount);
            InternalDrives          = new ObservableCollection <DriveInfo>();
            Drives = new ReadOnlyObservableCollection <DriveInfo>(InternalDrives);
            InternalFileSystemRoot        = new ObservableCollection <IFileSystemItemModel>();
            FileSystemRoot                = new ReadOnlyObservableCollection <IFileSystemItemModel>(InternalFileSystemRoot);
            FileSystemRootChangeObservers = new Dictionary <string, FileSystemWatcher>();
            Index       = new Dictionary <string, IFileSystemItemModel>();
            HiddenIndex = new Dictionary <string, IFileSystemItemModel>();
            SystemIndex = new Dictionary <string, IFileSystemItemModel>();

            FileSystemMount = DirectoryFactory.Invoke(null, null);
            SyncObject      = new object();
            Application.Current.Dispatcher.Invoke(() =>
            {
                BindingOperations.EnableCollectionSynchronization(InternalDrives, SyncObject);
                BindingOperations.EnableCollectionSynchronization(Drives, SyncObject);
                BindingOperations.EnableCollectionSynchronization(InternalFileSystemRoot, SyncObject);
                BindingOperations.EnableCollectionSynchronization(FileSystemRoot, SyncObject);
            }, System.Windows.Threading.DispatcherPriority.Normal);
        }
        private bool TryRealizeChildren(IEnumerable <IDirectory> treeLevelDirectories, CancellationToken cancellationToken, int levelCount, bool isSortingEnabled)
        {
            if (levelCount < 1)
            {
                throw new ArgumentOutOfRangeException("Level count can't be smaller than 1");
            }

            bool hasRealizedItem = false;

            if (treeLevelDirectories == null)
            {
                return(false);
            }

            cancellationToken.ThrowIfCancellationRequested();

            int remainingLevelCount = levelCount;
            var breadthFirstQueue   = new List <IDirectory>();

            foreach (IDirectory parentDirectory in treeLevelDirectories.Where(directory => !directory.IsRealized))
            {
                foreach (FileSystemInfo childInfo in parentDirectory.Info.EnumerateFileSystemInfos("*", FileSystemEnumerationOptions))
                {
                    IFileSystemItemModel childItem;
                    if (childInfo is DirectoryInfo directory)
                    {
                        childItem = DirectoryFactory.Invoke(directory, parentDirectory);
                        breadthFirstQueue.Add((IDirectory)childItem);
                    }
                    else
                    {
                        childItem = FileFactory.Invoke(childInfo as FileInfo, parentDirectory);
                    }

                    IndexFileSystemItem(childItem);
                    parentDirectory.ChildFileSystemItems.Add(childItem);
                    hasRealizedItem = true;
                }
                if (isSortingEnabled)
                {
                    parentDirectory.Sort();
                }
            }

            if (--remainingLevelCount > 0)
            {
                cancellationToken.ThrowIfCancellationRequested();
                TryRealizeChildren(breadthFirstQueue, cancellationToken, remainingLevelCount, isSortingEnabled);
            }
            return(hasRealizedItem);
        }
        private bool RealizeFromRoot(int levelCount, CancellationToken cancellationToken, bool isSortingEnabled)
        {
            bool hasRealizedItem            = false;
            var  nextLevelBreadthFirstQueue = new Queue <IDirectory>(InternalFileSystemRoot
                                                                     .OfType <IDrive>()
                                                                     .Where(rootItem => rootItem.IsReady));

            int remainingLevels = levelCount;

            while (remainingLevels > 0 && nextLevelBreadthFirstQueue.Any())
            {
                remainingLevels--;
                var currentLevelBreadthFirstQueue = new Queue <IDirectory>(nextLevelBreadthFirstQueue);
                nextLevelBreadthFirstQueue.Clear();
                while (currentLevelBreadthFirstQueue.TryDequeue(out IDirectory parentDirectory))
                {
                    parentDirectory.ChildFileSystemItems.Clear();
                    foreach (FileSystemInfo childInfo in parentDirectory.Info.EnumerateFileSystemInfos("*", FileSystemEnumerationOptions))
                    {
                        IFileSystemItemModel childItem;
                        if (childInfo is DirectoryInfo directory)
                        {
                            childItem = DirectoryFactory.Invoke(directory, parentDirectory);
                            nextLevelBreadthFirstQueue.Enqueue((IDirectory)childItem);
                        }
                        else
                        {
                            childItem = FileFactory.Invoke(childInfo as FileInfo, parentDirectory);
                        }

                        IndexFileSystemItem(childItem);
                        parentDirectory.ChildFileSystemItems.Add(childItem);
                        hasRealizedItem = true;
                    }

                    if (isSortingEnabled)

                    {
                        parentDirectory.Sort();
                    }
                }
                cancellationToken.ThrowIfCancellationRequested();
            }
            return(hasRealizedItem);
        }