Merge pull request #1275 from ranma42/fix-lib64
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / FolderBrowserDialog.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2006 Alexander Olk
21 //
22 // Authors:
23 //      Alexander Olk (alex.olk@googlemail.com)
24 //      Gert Driesen (drieseng@users.sourceforge.net)
25 //
26 //
27
28 using System;
29 using System.Drawing;
30 using System.ComponentModel;
31 using System.Resources;
32 using System.IO;
33 using System.Collections;
34
35 namespace System.Windows.Forms {
36         [DefaultEvent ("HelpRequest")]
37         [DefaultProperty ("SelectedPath")]
38         [Designer ("System.Windows.Forms.Design.FolderBrowserDialogDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
39         public sealed class FolderBrowserDialog : CommonDialog
40         {
41                 #region Local Variables
42                 private Environment.SpecialFolder rootFolder = Environment.SpecialFolder.Desktop;
43                 private string selectedPath = string.Empty;
44                 private bool showNewFolderButton = true;
45                 
46                 private Label descriptionLabel;
47                 private Button cancelButton;
48                 private Button okButton;
49                 private FolderBrowserTreeView folderBrowserTreeView;
50                 private Button newFolderButton;
51                 private ContextMenu folderBrowserTreeViewContextMenu;
52                 private MenuItem newFolderMenuItem;
53                 
54                 private string old_selectedPath = string.Empty;
55                 
56                 private readonly string folderbrowserdialog_string = "FolderBrowserDialog";
57                 private readonly string width_string = "Width";
58                 private readonly string height_string = "Height";
59                 private readonly string x_string = "X";
60                 private readonly string y_string = "Y";
61                 #endregion      // Local Variables
62                 
63                 #region Public Constructors
64                 public FolderBrowserDialog ()
65                 {
66                         form = new DialogForm (this);
67                         Size formConfigSize = Size.Empty;
68                         Point formConfigLocation = Point.Empty;
69                         
70                         object formWidth = MWFConfig.GetValue (folderbrowserdialog_string, width_string);
71                         
72                         object formHeight = MWFConfig.GetValue (folderbrowserdialog_string, height_string);
73                         
74                         if (formHeight != null && formWidth != null)
75                                 formConfigSize = new Size ((int)formWidth, (int)formHeight);
76                         
77                         object formLocationX = MWFConfig.GetValue (folderbrowserdialog_string, x_string);
78                         object formLocationY = MWFConfig.GetValue (folderbrowserdialog_string, y_string);
79                         
80                         if (formLocationX != null && formLocationY != null)
81                                 formConfigLocation = new Point ((int)formLocationX, (int)formLocationY);
82                         
83                         newFolderButton = new Button ();
84                         folderBrowserTreeView = new FolderBrowserTreeView (this);
85                         okButton = new Button ();
86                         cancelButton = new Button ();
87                         descriptionLabel = new Label ();
88                         folderBrowserTreeViewContextMenu = new ContextMenu ();
89                         
90                         form.AcceptButton = okButton;
91                         form.CancelButton = cancelButton;
92                         
93                         form.SuspendLayout ();
94                         form.ClientSize = new Size (322, 324);
95                         form.MinimumSize = new Size (310, 254);
96                         form.Text = "Browse For Folder";
97                         form.SizeGripStyle = SizeGripStyle.Show;
98
99                         newFolderMenuItem = new MenuItem("New Folder", new EventHandler (OnClickNewFolderButton));
100                         folderBrowserTreeViewContextMenu.MenuItems.Add(newFolderMenuItem);
101                         
102                         // descriptionLabel
103                         descriptionLabel.Anchor = ((AnchorStyles)(((AnchorStyles.Top | AnchorStyles.Left)
104                                 | AnchorStyles.Right)));
105                         descriptionLabel.Location = new Point (15, 14);
106                         descriptionLabel.Size = new Size (292, 40);
107                         descriptionLabel.TabIndex = 0;
108                         descriptionLabel.Text = string.Empty;
109                         
110                         // folderBrowserTreeView
111                         folderBrowserTreeView.Anchor = ((AnchorStyles)((((AnchorStyles.Top | AnchorStyles.Bottom)
112                                 | AnchorStyles.Left)
113                                 | AnchorStyles.Right)));
114                         folderBrowserTreeView.ImageIndex = -1;
115                         folderBrowserTreeView.Location = new Point (15, 60);
116                         folderBrowserTreeView.SelectedImageIndex = -1;
117                         folderBrowserTreeView.Size = new Size (292, 212);
118                         folderBrowserTreeView.TabIndex = 3;
119                         folderBrowserTreeView.ShowLines = false;
120                         folderBrowserTreeView.ShowPlusMinus = true;
121                         folderBrowserTreeView.HotTracking = true;
122                         folderBrowserTreeView.BorderStyle = BorderStyle.Fixed3D;
123                         folderBrowserTreeView.ContextMenu = folderBrowserTreeViewContextMenu;
124                         //folderBrowserTreeView.Indent = 2;
125                         
126                         // newFolderButton
127                         newFolderButton.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Left)));
128                         newFolderButton.FlatStyle = FlatStyle.System;
129                         newFolderButton.Location = new Point (15, 285);
130                         newFolderButton.Size = new Size (105, 23);
131                         newFolderButton.TabIndex = 4;
132                         newFolderButton.Text = "Make New Folder";
133                         newFolderButton.Enabled = true;
134                         
135                         // okButton
136                         okButton.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Right)));
137                         okButton.FlatStyle = FlatStyle.System;
138                         okButton.Location = new Point (135, 285);
139                         okButton.Size = new Size (80, 23);
140                         okButton.TabIndex = 1;
141                         okButton.Text = "OK";
142                         
143                         // cancelButton
144                         cancelButton.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Right)));
145                         cancelButton.DialogResult = DialogResult.Cancel;
146                         cancelButton.FlatStyle = FlatStyle.System;
147                         cancelButton.Location = new Point (227, 285);
148                         cancelButton.Size = new Size (80, 23);
149                         cancelButton.TabIndex = 2;
150                         cancelButton.Text = "Cancel";
151                         
152                         form.Controls.Add (cancelButton);
153                         form.Controls.Add (okButton);
154                         form.Controls.Add (newFolderButton);
155                         form.Controls.Add (folderBrowserTreeView);
156                         form.Controls.Add (descriptionLabel);
157                         
158                         form.ResumeLayout (false);
159                         
160                         if (formConfigSize != Size.Empty) {
161                                 form.Size = formConfigSize;
162                         }
163                         
164                         if (formConfigLocation != Point.Empty) {
165                                 form.Location = formConfigLocation;
166                         }
167                         
168                         okButton.Click += new EventHandler (OnClickOKButton);
169                         cancelButton.Click += new EventHandler (OnClickCancelButton);
170                         newFolderButton.Click += new EventHandler (OnClickNewFolderButton);
171
172                         form.VisibleChanged += new EventHandler (OnFormVisibleChanged);
173                         
174                         RootFolder = rootFolder;
175                 }
176                 
177                 #endregion      // Public Constructors
178                 
179                 #region Public Instance Properties
180                 [Browsable(true)]
181                 [DefaultValue("")]
182                 [Localizable(true)]
183                 public string Description {
184                         set {
185                                 descriptionLabel.Text = value;
186                         }
187                         
188                         get {
189                                 return descriptionLabel.Text;
190                         }
191                 }
192                 
193                 [Browsable(true)]
194                 [DefaultValue(Environment.SpecialFolder.Desktop)]
195                 [Localizable(false)]
196                 [TypeConverter (typeof (SpecialFolderEnumConverter))]
197                 public Environment.SpecialFolder RootFolder {
198                         set {
199                                 int v = (int)value;
200
201                                 Type enumType = typeof (Environment.SpecialFolder);
202                                 if (!Enum.IsDefined (enumType, v))
203                                         throw new InvalidEnumArgumentException (
204                                                 "value", v, enumType);
205                                 
206                                 rootFolder = value;
207                         }
208                         get {
209                                 return rootFolder;
210                         }
211                 }
212                 
213                 [Browsable(true)]
214                 [DefaultValue("")]
215                 [Editor("System.Windows.Forms.Design.SelectedPathEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
216                 [Localizable(true)]
217                 public string SelectedPath {
218                         set {
219                                 if (value == null)
220                                         value = string.Empty;
221                                 selectedPath = value;
222                                 old_selectedPath = value;
223                         }
224                         get {
225                                 return selectedPath;
226                         }
227                 }
228                 
229                 [Browsable(true)]
230                 [DefaultValue(true)]
231                 [Localizable(false)]
232                 public bool ShowNewFolderButton {
233                         set {
234                                 if (value != showNewFolderButton) {
235                                         newFolderButton.Visible = value;
236                                         showNewFolderButton = value;
237                                 }
238                         }
239                         
240                         get {
241                                 return showNewFolderButton;
242                         }
243                 }
244                 #endregion      // Public Instance Properties
245                 
246                 #region Public Instance Methods
247                 public override void Reset ()
248                 {
249                         Description = string.Empty;
250                         RootFolder = Environment.SpecialFolder.Desktop;
251                         selectedPath = string.Empty;
252                         ShowNewFolderButton = true;
253                 }
254                 
255                 protected override bool RunDialog (IntPtr hWndOwner)
256                 {
257                         folderBrowserTreeView.RootFolder = RootFolder;
258                         folderBrowserTreeView.SelectedPath = SelectedPath;
259
260                         form.Refresh ();
261                         
262                         return true;
263                 }
264                 #endregion      // Public Instance Methods
265                 
266                 #region Internal Methods
267                 void OnClickOKButton (object sender, EventArgs e)
268                 {
269                         WriteConfigValues ();
270                         
271                         form.DialogResult = DialogResult.OK;
272                 }
273                 
274                 void OnClickCancelButton (object sender, EventArgs e)
275                 {
276                         WriteConfigValues ();
277                         
278                         selectedPath = old_selectedPath;
279                         form.DialogResult = DialogResult.Cancel;
280                 }
281                 
282                 void OnClickNewFolderButton (object sender, EventArgs e)
283                 {
284                         folderBrowserTreeView.CreateNewFolder ();
285                 }
286
287                 void OnFormVisibleChanged (object sender, EventArgs e)
288                 {
289                         if (form.Visible && okButton.Enabled)
290                                 okButton.Select ();
291                 }
292                 
293                 private void WriteConfigValues ()
294                 {
295                         MWFConfig.SetValue (folderbrowserdialog_string, width_string, form.Width);
296                         MWFConfig.SetValue (folderbrowserdialog_string, height_string, form.Height);
297                         MWFConfig.SetValue (folderbrowserdialog_string, x_string, form.Location.X);
298                         MWFConfig.SetValue (folderbrowserdialog_string, y_string, form.Location.Y);
299                 }
300                 #endregion      // Internal Methods
301                 
302                 #region Events
303                 [Browsable(false)]
304                 [EditorBrowsable(EditorBrowsableState.Never)]
305                 public new event EventHandler HelpRequest {
306                         add { base.HelpRequest += value; }
307                         remove { base.HelpRequest -= value; }
308                 }
309                 #endregion
310                 
311                 internal class FolderBrowserTreeView : TreeView
312                 {
313                         private MWFVFS vfs = new MWFVFS ();
314                         new private FBTreeNode root_node;
315                         private FolderBrowserDialog parentDialog;
316                         private ImageList imageList = new ImageList ();
317                         private Environment.SpecialFolder rootFolder;
318                         private bool dont_enable = false;
319                         private TreeNode node_under_mouse;
320                         
321                         public FolderBrowserTreeView (FolderBrowserDialog parent_dialog)
322                         {
323                                 parentDialog = parent_dialog;
324                                 HideSelection = false;
325                                 ImageList = imageList;
326                                 SetupImageList ();
327                         }
328                         
329                         public Environment.SpecialFolder RootFolder {
330                                 set {
331                                         rootFolder = value;
332                                         
333                                         string root_path = string.Empty;
334                                         
335                                         switch (rootFolder) {
336                                                 case Environment.SpecialFolder.Desktop:
337                                                         root_node = new FBTreeNode ("Desktop");
338                                                         root_node.RealPath = ThemeEngine.Current.Places (UIIcon.PlacesDesktop);
339                                                         root_path = MWFVFS.DesktopPrefix;
340                                                         break;
341                                                 case Environment.SpecialFolder.Recent:
342                                                         root_node = new FBTreeNode ("My Recent Documents");
343                                                         root_node.RealPath = ThemeEngine.Current.Places (UIIcon.PlacesRecentDocuments);
344                                                         root_path = MWFVFS.RecentlyUsedPrefix;
345                                                         break;
346                                                 case Environment.SpecialFolder.MyComputer:
347                                                         root_node = new FBTreeNode ("My Computer");
348                                                         root_path = MWFVFS.MyComputerPrefix;
349                                                         break;
350                                                 case Environment.SpecialFolder.Personal:
351                                                         root_node = new FBTreeNode ("Personal");
352                                                         root_path = MWFVFS.PersonalPrefix;
353                                                         root_node.RealPath = ThemeEngine.Current.Places (UIIcon.PlacesPersonal);
354                                                         break;
355                                                 default:
356                                                         root_node = new FBTreeNode (rootFolder.ToString ());
357                                                         root_node.RealPath = Environment.GetFolderPath (rootFolder);
358                                                         root_path = root_node.RealPath;
359                                                         break;
360                                         }
361                                         
362                                         root_node.Tag = root_path;
363                                         root_node.ImageIndex = NodeImageIndex (root_path);
364
365                                         BeginUpdate ();
366                                         Nodes.Clear ();
367                                         EndUpdate ();
368
369                                         FillNode (root_node);
370                                         
371                                         root_node.Expand ();
372                                         
373                                         Nodes.Add (root_node);
374                                 }
375                         }
376                         
377                         public string SelectedPath {
378                                 set {
379                                         if (value.Length == 0)
380                                                 return;
381
382                                         if (!Path.IsPathRooted (value))
383                                                 return;
384
385                                         try {
386                                                 if (Check_if_path_is_child_of_RootFolder (value))
387                                                         SetSelectedPath (Path.GetFullPath (value));
388                                         } catch (Exception) {
389                                                 // If we can't set the user's requested path, the
390                                                 // best we can do is not crash and reset to the default
391                                                 EndUpdate ();
392                                                 RootFolder = rootFolder;
393                                         }
394                                 }
395                         }
396                         
397                         private string parent_real_path;
398                         private bool dont_do_onbeforeexpand;
399                         
400                         public void CreateNewFolder ()
401                         {
402                                 FBTreeNode fbnode = node_under_mouse == null ? SelectedNode as FBTreeNode : node_under_mouse as FBTreeNode;
403                                 
404                                 if (fbnode == null || fbnode.RealPath == null)
405                                         return;
406                                 
407                                 string tmp_filename = "New Folder";
408                                 
409                                 if (Directory.Exists (Path.Combine (fbnode.RealPath, tmp_filename))) {
410                                         int i = 1;
411
412                                         if (XplatUI.RunningOnUnix) {
413                                                 tmp_filename = tmp_filename + "-" + i;
414                                         } else {
415                                                 tmp_filename = tmp_filename + " (" + i + ")";
416                                         }
417                                         
418                                         while (Directory.Exists (Path.Combine (fbnode.RealPath, tmp_filename))) {
419                                                 i++;
420                                                 if (XplatUI.RunningOnUnix) {
421                                                         tmp_filename = "New Folder" + "-" + i;
422                                                 } else {
423                                                         tmp_filename = "New Folder" + " (" + i + ")";
424                                                 }
425                                         }
426                                 }
427
428                                 parent_real_path = fbnode.RealPath;
429                                 
430                                 FillNode (fbnode);
431                                 dont_do_onbeforeexpand = true;
432                                 fbnode.Expand ();
433                                 dont_do_onbeforeexpand = false;
434
435                                 // to match MS, immediately create the new folder
436                                 // and rename it once the label edit completes
437                                 string fullPath = Path.Combine (fbnode.RealPath, tmp_filename);
438                                 if (!vfs.CreateFolder (fullPath))
439                                         return;
440
441                                 FBTreeNode new_node = new FBTreeNode (tmp_filename);
442                                 new_node.ImageIndex = NodeImageIndex (tmp_filename);
443                                 new_node.Tag = new_node.RealPath = fullPath;
444                                 fbnode.Nodes.Add (new_node);
445
446                                 LabelEdit = true;
447                                 new_node.BeginEdit();
448                         }
449                         
450                         protected override void OnAfterLabelEdit (NodeLabelEditEventArgs e)
451                         {
452                                 if (e.Label != null) {
453                                         if (e.Label.Length > 0) {
454                                                 FBTreeNode fbnode = e.Node as FBTreeNode;
455
456                                                 string originalPath = fbnode.RealPath;
457                                                 string newPath = Path.Combine (parent_real_path, e.Label);
458
459                                                 if (vfs.MoveFolder (originalPath, newPath)) {
460                                                         fbnode.Tag = fbnode.RealPath = newPath;
461                                                 } else {
462                                                         e.CancelEdit = true;
463                                                         e.Node.BeginEdit ();
464                                                         return;
465                                                 }
466                                         } else {
467                                                 e.CancelEdit = true;
468                                                 e.Node.BeginEdit ();
469                                                 return;
470                                         }
471                                 }
472
473                                 // select new folder only if both the curren node under
474                                 // mouse pointer and SelectedNode are the same (match .Net)
475                                 if (node_under_mouse == SelectedNode)
476                                         SelectedNode = e.Node;
477
478                                 // disable LabelEdit when either edit has finished
479                                 // or has been cancelled, to prevent the user from
480                                 // editing label of existing folders
481                                 LabelEdit = false;
482                         }
483                         
484                         private void SetSelectedPath (string path)
485                         {
486                                 BeginUpdate ();
487                                 
488                                 FBTreeNode node = FindPathInNodes (path, Nodes);
489                                 
490                                 if (node == null) {
491                                         Stack stack = new Stack ();
492                                         
493                                         string path_cut = path.Substring (0, path.LastIndexOf (Path.DirectorySeparatorChar));
494                                         if (!XplatUI.RunningOnUnix && path_cut.Length == 2)
495                                                 path_cut += Path.DirectorySeparatorChar;
496                                         
497                                         while (node == null && path_cut.Length > 0) {
498                                                 node = FindPathInNodes (path_cut, Nodes);
499                                                 
500                                                 if (node == null) {
501                                                         string path_cut_new = path_cut.Substring (0, path_cut.LastIndexOf (Path.DirectorySeparatorChar));
502                                                         string leftover = path_cut.Replace (path_cut_new, string.Empty);
503                                                         
504                                                         stack.Push (leftover);
505                                                         
506                                                         path_cut = path_cut_new;
507                                                 }
508                                         }
509
510                                         // If we didn't find anything, just display the full, unselected tree
511                                         if (node == null) {
512                                                 EndUpdate ();
513                                                 RootFolder = rootFolder;
514                                                 return;
515                                         }
516                                         
517                                         FillNode (node);
518                                         node.Expand ();
519
520                                         // walk through the subdirs and fill the nodes
521                                         while (stack.Count > 0) {
522                                                 string part_name = stack.Pop () as string;
523
524                                                 foreach (TreeNode treeNode in node.Nodes) {
525                                                         FBTreeNode fbnode = treeNode as FBTreeNode;
526
527                                                         if (path_cut + part_name == fbnode.RealPath) {
528                                                                 node = fbnode;
529                                                                 path_cut += part_name;
530
531                                                                 FillNode (node);
532                                                                 node.Expand ();
533                                                                 break;
534                                                         }
535                                                 }
536                                         }
537
538                                         // finally find the node for the complete path
539                                         foreach (TreeNode treeNode in node.Nodes) {
540                                                 FBTreeNode fbnode = treeNode as FBTreeNode;
541
542                                                 if (path == fbnode.RealPath) {
543                                                         node = fbnode;
544                                                         break;
545                                                 }
546                                         }
547                                 }
548                                 
549                                 if (node != null) {
550                                         SelectedNode = node;
551                                         node.EnsureVisible ();
552                                 }
553                                 
554                                 EndUpdate ();
555                         }
556                         
557                         private FBTreeNode FindPathInNodes (string path, TreeNodeCollection nodes)
558                         {
559                                 // On Windows the devices can be passed as C: yet match
560                                 // the C:\ form
561                                 //
562                                 // Hackish, but works
563                                 if (!XplatUI.RunningOnUnix && path.Length == 2)
564                                         path += Path.DirectorySeparatorChar;
565
566                                 foreach (TreeNode node in nodes) {
567                                         FBTreeNode fbnode = node as FBTreeNode;
568                                         
569                                         if (fbnode != null && fbnode.RealPath != null) {
570                                                 if (fbnode.RealPath == path)
571                                                         return fbnode;
572                                         }
573                                         
574                                         FBTreeNode n = FindPathInNodes (path, node.Nodes);
575                                         if (n != null)
576                                                 return n;
577                                 }
578                                 
579                                 return null;
580                         }
581                         
582                         private bool Check_if_path_is_child_of_RootFolder (string path)
583                         {
584                                 string root_path = (string) root_node.RealPath;
585                                 
586                                 if (root_path != null || rootFolder == Environment.SpecialFolder.MyComputer) {
587                                         try {
588                                                 if (!Directory.Exists (path))
589                                                         return false;
590                                                 
591                                                 switch (rootFolder) {
592                                                         case Environment.SpecialFolder.Desktop:
593                                                         case Environment.SpecialFolder.MyComputer:
594                                                                 return true;
595                                                         case Environment.SpecialFolder.Personal:
596                                                                 if (!path.StartsWith (root_path))
597                                                                         return false;
598                                                                 else
599                                                                         return true;
600                                                         default:
601                                                                 return false;
602                                                 }
603                                         } catch {}
604                                 }
605                                 
606                                 return false;
607                         }
608                         
609                         private void FillNode (TreeNode node)
610                         {
611                                 BeginUpdate ();
612                                 
613                                 node.Nodes.Clear ();
614                                 vfs.ChangeDirectory ((string)node.Tag);
615                                 ArrayList folders = vfs.GetFoldersOnly ();
616                                 
617                                 foreach (FSEntry fsentry in folders) {
618                                         if (fsentry.Name.StartsWith ("."))
619                                                 continue;
620                                         
621                                         FBTreeNode child = new FBTreeNode (fsentry.Name);
622                                         child.Tag = fsentry.FullName;
623                                         child.RealPath = fsentry.RealName == null ? fsentry.FullName : fsentry.RealName;
624                                         child.ImageIndex = NodeImageIndex (fsentry.FullName);
625                                         
626                                         vfs.ChangeDirectory (fsentry.FullName);
627                                         ArrayList sub_folders = vfs.GetFoldersOnly ();
628                                         
629                                         foreach (FSEntry fsentry_sub in sub_folders) {
630                                                 if (!fsentry_sub.Name.StartsWith (".")) {
631                                                         child.Nodes.Add (new TreeNode (String.Empty));
632                                                         break;
633                                                 }
634                                         }
635                                         
636                                         node.Nodes.Add (child);
637                                 }
638                                 
639                                 EndUpdate ();
640                         }
641                         
642                         private void SetupImageList ()
643                         {
644                                 imageList.ColorDepth = ColorDepth.Depth32Bit;
645                                 imageList.ImageSize = new Size (16, 16);
646                                 imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesRecentDocuments, 16));
647                                 imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesDesktop, 16));
648                                 imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesPersonal, 16));
649                                 imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesMyComputer, 16));
650                                 imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesMyNetwork, 16));
651                                 imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.NormalFolder, 16));
652                                 imageList.TransparentColor = Color.Transparent;
653                         }
654                         
655                         private int NodeImageIndex (string path)
656                         {
657                                 int index = 5;
658                                 
659                                 if (path == MWFVFS.DesktopPrefix)
660                                         index = 1;
661                                 else if (path == MWFVFS.RecentlyUsedPrefix)
662                                         index = 0;
663                                 else if (path == MWFVFS.PersonalPrefix)
664                                         index = 2;
665                                 else if (path == MWFVFS.MyComputerPrefix)
666                                         index = 3;
667                                 else if (path == MWFVFS.MyNetworkPrefix)
668                                         index = 4;
669                                 
670                                 return index;
671                         }
672                         
673                         protected override void OnAfterSelect (TreeViewEventArgs e)
674                         {
675                                 if (e.Node == null)
676                                         return;
677                                 
678                                 FBTreeNode fbnode = e.Node as FBTreeNode;
679                                 
680                                 if (fbnode.RealPath == null || fbnode.RealPath.IndexOf ("://") != -1) {
681                                         parentDialog.okButton.Enabled = false;
682                                         parentDialog.newFolderButton.Enabled = false;
683                                         parentDialog.newFolderMenuItem.Enabled = false;
684                                         dont_enable = true;
685                                 } else {
686                                         parentDialog.okButton.Enabled = true;
687                                         parentDialog.newFolderButton.Enabled = true;
688                                         parentDialog.newFolderMenuItem.Enabled = true;
689                                         parentDialog.selectedPath = fbnode.RealPath;
690                                         dont_enable = false;
691                                 }
692                                 
693                                 base.OnAfterSelect (e);
694                         }
695                         
696                         protected internal override void OnBeforeExpand (TreeViewCancelEventArgs e)
697                         {
698                                 if (!dont_do_onbeforeexpand) {
699                                         if (e.Node == root_node)
700                                                 return;
701                                         FillNode (e.Node);
702                                 }
703                                 
704                                 base.OnBeforeExpand (e);
705                         }
706
707                         protected override void OnMouseDown (MouseEventArgs e)
708                         {
709                                 node_under_mouse = GetNodeAt (e.X, e.Y);
710                                 base.OnMouseDown (e);
711                         }
712                         
713                         protected override void OnMouseUp (MouseEventArgs e)
714                         {
715                                 if (SelectedNode == null) {
716                                         parentDialog.okButton.Enabled = false;
717                                         parentDialog.newFolderButton.Enabled = false;
718                                         parentDialog.newFolderMenuItem.Enabled = false;
719                                 } else
720                                 if (!dont_enable) {
721                                         parentDialog.okButton.Enabled = true;
722                                         parentDialog.newFolderButton.Enabled = true;
723                                         parentDialog.newFolderMenuItem.Enabled = true;
724                                 }
725
726                                 node_under_mouse = null;
727                                 
728                                 base.OnMouseUp (e);
729                         }
730                 }
731                 
732                 internal class FBTreeNode : TreeNode
733                 {
734                         private string realPath = null;
735                         
736                         public FBTreeNode (string text)
737                         {
738                                 Text = text;
739                         }
740                         
741                         public string RealPath {
742                                 set {
743                                         realPath = value;
744                                 }
745                                 
746                                 get {
747                                         return realPath;
748                                 }
749                         }
750                 }
751         }
752         
753         internal class SpecialFolderEnumConverter : TypeConverter
754         {
755                 public override object ConvertFrom (ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
756                 {
757                         if ((value == null) || !(value is String))
758                                 return base.ConvertFrom (context, culture, value);
759
760                         return Enum.Parse (typeof (Environment.SpecialFolder), (string)value, true);
761                 }
762
763                 public override object ConvertTo (ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
764                 {
765                         if ((value == null) || !(value is Environment.SpecialFolder) || (destinationType != typeof (string)))
766                                 return base.ConvertTo (context, culture, value, destinationType);
767                                 
768                         return ((Environment.SpecialFolder)value).ToString ();
769                 }
770         }
771 }