@@ -36,12 +36,6 @@ public Location(string volume, string label, string path, bool isDrive)
3636 public readonly string Label ;
3737 public readonly string Path ;
3838 public readonly bool IsDrive ;
39-
40- public bool TryAccess ( ) => TryAccess ( this . Path ) ;
41- public static bool TryAccess ( string path )
42- {
43- throw new NotImplementedException ( ) ;
44- }
4539 }
4640
4741 private const int ImageTextSpacing = 4 ;
@@ -117,7 +111,8 @@ public string FilePath
117111 }
118112
119113 public bool AutoAddFilterExtension { get ; set ; }
120-
114+ public bool ShowHiddenFiles { get ; set ; }
115+
121116 public IImage IconFolder { get ; set ; }
122117 public IImage IconDrive { get ; set ; }
123118
@@ -182,6 +177,9 @@ public FileDialog(FileDialogMode mode) : base(null)
182177 SetStyle ( Stylesheet . DefaultStyleName ) ;
183178 }
184179
180+ /// <summary>
181+ /// Create the navigation menu of places we can visit.
182+ /// </summary>
185183 protected virtual void PopulatePlacesListUI ( ListView listView )
186184 {
187185 List < Location > placeList = new List < Location > ( 8 ) ;
@@ -201,6 +199,9 @@ protected virtual void PopulatePlacesListUI(ListView listView)
201199 listView . Widgets . Add ( CreateListItem ( placeList [ index ] ) ) ;
202200 }
203201
202+ /// <summary>
203+ /// Create a display widget for the given location
204+ /// </summary>
204205 protected virtual Widget CreateListItem ( Location location )
205206 {
206207 var item = new HorizontalStackPanel
@@ -217,6 +218,44 @@ protected virtual Widget CreateListItem(Location location)
217218 item . Widgets . Add ( new Label { Text = label } ) ;
218219 return item ;
219220 }
221+
222+ /// <summary>
223+ /// Return true if <paramref name="path"/> is a valid directory, and we have permissions to access it.
224+ /// </summary>
225+ protected bool TryAccessDirectory ( string path )
226+ {
227+ if ( ! Directory . Exists ( path ) )
228+ return false ;
229+ if ( ! TryGetFileAttributes ( path , out FileAttributes att ) )
230+ return false ;
231+ return FileAttributeFilter ( att , _mode , ShowHiddenFiles ) ;
232+ }
233+
234+ protected virtual bool FileAttributeFilter ( FileAttributes attributes , FileDialogMode mode , bool showHidden )
235+ {
236+ bool discard =
237+ attributes . HasFlag ( FileAttributes . System ) |
238+ attributes . HasFlag ( FileAttributes . Offline ) |
239+ ( attributes . HasFlag ( FileAttributes . Hidden ) & ! showHidden ) ;
240+
241+ switch ( mode )
242+ {
243+ case FileDialogMode . SaveFile :
244+ discard |= attributes . HasFlag ( FileAttributes . ReadOnly ) ;
245+ break ;
246+ case FileDialogMode . ChooseFolder :
247+ discard |= ! attributes . HasFlag ( FileAttributes . Directory ) ;
248+ break ;
249+ default :
250+ break ;
251+ }
252+ return ! discard ;
253+ }
254+
255+ protected void ShowIOError ( string path , string exceptionMsg )
256+ {
257+ CreateMessageBox ( "I/O Error" , exceptionMsg ) ;
258+ }
220259
221260 private void UpdateEnabled ( )
222261 {
@@ -279,7 +318,7 @@ private void OnButtonForward(object sender, EventArgs args)
279318
280319 private void SetFolder ( string value , bool storeInHistory )
281320 {
282- if ( ! Directory . Exists ( value ) )
321+ if ( ! TryAccessDirectory ( value ) )
283322 {
284323 return ;
285324 }
@@ -362,23 +401,28 @@ private void UpdateFolder()
362401 _paths . Clear ( ) ;
363402
364403 _scrollPane . ScrollPosition = Mathematics . PointZero ;
365-
404+
366405 var path = _textFieldPath . Text ;
367- var folders = Directory . EnumerateDirectories ( path ) ;
368-
406+
407+ // Enumerate folders in directory
408+ bool success = TryEnumerateDirectoryFolders ( path , out IEnumerable < string > collection , out string exceptionMsg ) ;
409+ if ( ! success )
410+ {
411+ ShowIOError ( path , exceptionMsg ) ;
412+ return ;
413+ }
414+
369415 var gridY = 0 ;
370- foreach ( var f in folders )
416+ foreach ( string folder in collection )
371417 {
372- var fileInfo = new FileInfo ( f ) ;
373- if ( fileInfo . Attributes . HasFlag ( FileAttributes . Hidden ) )
374- {
418+ success = TryGetFileAttributes ( folder , out FileAttributes att ) ;
419+ if ( success )
420+ success &= FileAttributeFilter ( att , _mode , ShowHiddenFiles ) ;
421+ if ( ! success )
375422 continue ;
376- }
377-
378- var prop = new Proportion ( ) ;
379-
380- _gridFiles . RowsProportions . Add ( prop ) ;
381-
423+
424+ _gridFiles . RowsProportions . Add ( new Proportion ( ) ) ;
425+
382426 var image = new Image
383427 {
384428 Renderable = IconFolder ,
@@ -391,14 +435,14 @@ private void UpdateFolder()
391435
392436 var name = new Label
393437 {
394- Text = Path . GetFileName ( f ) ,
438+ Text = Path . GetFileName ( folder ) ,
395439 } ;
396440 Grid . SetColumn ( name , 1 ) ;
397441 Grid . SetRow ( name , gridY ) ;
398442
399443 _gridFiles . Widgets . Add ( name ) ;
400444
401- _paths . Add ( f ) ;
445+ _paths . Add ( folder ) ;
402446
403447 ++ gridY ;
404448 }
@@ -408,47 +452,34 @@ private void UpdateFolder()
408452 return ;
409453 }
410454
411- IEnumerable < string > files ;
412-
413- if ( string . IsNullOrEmpty ( Filter ) )
455+ // Enumerate files in directory
456+ success = TryEnumerateDirectoryFiles ( path , Filter , out collection , out exceptionMsg ) ;
457+ if ( ! success )
414458 {
415- files = Directory . EnumerateFiles ( path ) ;
416- }
417- else
418- {
419- var parts = Filter . Split ( '|' ) ;
420- var result = new List < string > ( ) ;
421-
422- foreach ( var part in parts )
423- {
424- result . AddRange ( Directory . EnumerateFiles ( path , part ) ) ;
425- }
426-
427- files = result ;
459+ ShowIOError ( path , exceptionMsg ) ;
460+ return ;
428461 }
429462
430- foreach ( var f in files )
463+ foreach ( string file in collection )
431464 {
432- var fileInfo = new FileInfo ( f ) ;
433- if ( fileInfo . Attributes . HasFlag ( FileAttributes . Hidden ) )
434- {
465+ success = TryGetFileAttributes ( file , out FileAttributes att ) ;
466+ if ( success )
467+ success &= FileAttributeFilter ( att , _mode , ShowHiddenFiles ) ;
468+ if ( ! success )
435469 continue ;
436- }
437-
438- var prop = new Proportion ( ) ;
439-
440- _gridFiles . RowsProportions . Add ( prop ) ;
470+
471+ _gridFiles . RowsProportions . Add ( new Proportion ( ) ) ;
441472
442473 var name = new Label
443474 {
444- Text = Path . GetFileName ( f ) ,
475+ Text = Path . GetFileName ( file ) ,
445476 } ;
446477 Grid . SetColumn ( name , 1 ) ;
447478 Grid . SetRow ( name , gridY ) ;
448479
449480 _gridFiles . Widgets . Add ( name ) ;
450481
451- _paths . Add ( f ) ;
482+ _paths . Add ( file ) ;
452483
453484 ++ gridY ;
454485 }
@@ -536,7 +567,7 @@ public void ApplyFileDialogStyle(FileDialogStyle style)
536567 image . Renderable = pathInfo . IsDrive ? IconDrive : IconFolder ;
537568 }
538569 }
539-
570+
540571 protected override void InternalSetStyle ( Stylesheet stylesheet , string name )
541572 {
542573 ApplyFileDialogStyle ( stylesheet . FileDialogStyles . SafelyGetStyle ( name ) ) ;
0 commit comments