| 0: | // FileScout.cs | |
| 1: | // Copyright (C) 2001 Mike Krueger | |
| 2: | // the ShellTree came orginaly from a ShellTree implementation sample from HyunKeun Cho | |
| 3: | // (thanx for this piece of code) | |
| 4: | // with contributions from : | |
| 5: | // Patrick Steele (pj_steele@yahoo.com) | |
| 6: | // | |
| 7: | // This program is free software; you can redistribute it and/or modify | |
| 8: | // it under the terms of the GNU General Public License as published by | |
| 9: | // the Free Software Foundation; either version 2 of the License, or | |
| 10: | // (at your option) any later version. | |
| 11: | // | |
| 12: | // This program is distributed in the hope that it will be useful, | |
| 13: | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14: | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15: | // GNU General Public License for more details. | |
| 16: | // | |
| 17: | // You should have received a copy of the GNU General Public License | |
| 18: | // along with this program; if not, write to the Free Software | |
| 19: | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20: | ||
| 21: | using System; | |
| 22: | using System.IO; | |
| 23: | using System.ComponentModel; | |
| 24: | using System.Windows.Forms; | |
| 25: | using System.Drawing; | |
| 26: | using System.Drawing.Drawing2D; | |
| 27: | using System.Collections; | |
| 28: | using System.Reflection; | |
| 29: | using System.Resources; | |
| 30: | using System.Threading; | |
| 31: | using System.Xml; | |
| 32: | ||
| 33: | using SharpDevelop.Tool.Function; | |
| 34: | using SharpDevelop.Tool.Data; | |
| 35: | ||
| 36: | namespace SharpDevelop.Gui.Navigation { | |
| 37: | ||
| 38: | public class DriveObject | |
| 39: | { | |
| 40: | string text = null; | |
| 41: | string drive = null; | |
| 42: | ||
| 43: | public string Drive { | |
| 44: | get { | |
| 45: | return drive; | |
| 46: | } | |
| 47: | } | |
| 48: | ||
| 49: | /// <summary> | |
| 50: | /// For reading the volume label I create a thread, which prevents | |
| 51: | /// too long wait times for getting a volume lable (e.g. floppys, network devices | |
| 52: | /// are slow). | |
| 53: | /// </summary> | |
| 54: | void GetBetterName() | |
| 55: | { | |
| 56: | string label = FSTypeUtility.VolumeLabel(drive); // contributed from Patrick Steele | |
| 57: | if (label.Length > 0) { | |
| 58: | text = label + " ("+ drive.Substring(0, 2) + ")"; | |
| 59: | } else | |
| 60: | return; | |
| 61: | } | |
| 62: | ||
| 63: | public DriveObject(string drive) | |
| 64: | { | |
| 65: | this.drive = drive; | |
| 66: | ||
| 67: | // string label = FSTypeUtility.VolumeLabel(drive); // contributed from Patrick Steele | |
| 68: | string label = ""; | |
| 69: | if (label.Length > 0) { | |
| 70: | text = label; | |
| 71: | } else { | |
| 72: | switch(FSTypeUtility.GetDriveType(drive)) { | |
| 73: | case DriveType.Removeable: | |
| 74: | text += "Removeable"; | |
| 75: | break; | |
| 76: | case DriveType.Fixed: | |
| 77: | text += "Fixed"; | |
| 78: | break; | |
| 79: | case DriveType.Cdrom: | |
| 80: | text += "CD"; | |
| 81: | break; | |
| 82: | case DriveType.Remote: | |
| 83: | text += "Remote"; | |
| 84: | break; | |
| 85: | default: | |
| 86: | text += "Unknown"; | |
| 87: | break; | |
| 88: | } | |
| 89: | } | |
| 90: | text += " ("+ drive.Substring(0, 2) + ")"; | |
| 91: | Thread t = new Thread(new ThreadStart(GetBetterName)); | |
| 92: | t.Start(); | |
| 93: | } | |
| 94: | ||
| 95: | public override string ToString() | |
| 96: | { | |
| 97: | return text; | |
| 98: | } | |
| 99: | } | |
| 100: | ||
| 101: | public class DriveSelector : ComboBox | |
| 102: | { | |
| 103: | public DriveSelector() | |
| 104: | { | |
| 105: | DropDownStyle = ComboBoxStyle.DropDownList; | |
| 106: | ScanDrives(); | |
| 107: | } | |
| 108: | ||
| 109: | void ScanDrives() | |
| 110: | { | |
| 111: | string[] drivelist = Directory.GetLogicalDrives(); | |
| 112: | int selecteddrive = 0; | |
| 113: | ||
| 114: | foreach (string drive in drivelist) { | |
| 115: | Items.Add(new DriveObject(drive)); | |
| 116: | if (drive[0] >= 'C' && selecteddrive == 0) | |
| 117: | selecteddrive = Items.Count - 1; | |
| 118: | } | |
| 119: | SelectedIndex = selecteddrive; | |
| 120: | } | |
| 121: | ||
| 122: | public string GetDrive() | |
| 123: | { | |
| 124: | return ((DriveObject)SelectedItem).Drive; | |
| 125: | } | |
| 126: | } | |
| 127: | ||
| 128: | public class FileList : ListView | |
| 129: | { | |
| 130: | public FileList() | |
| 131: | { | |
| 132: | ResourceManager resources = new ResourceManager("ProjectComponentResources", this.GetType().Module.Assembly); | |
| 133: | ||
| 134: | Columns.Add("File", 100, HorizontalAlignment.Left); | |
| 135: | SmallImageList = FileUtility.ImageList; | |
| 136: | HeaderStyle = ColumnHeaderStyle.None; | |
| 137: | View = View.Details; | |
| 138: | Alignment = ListViewAlignment.Left; | |
| 139: | } | |
| 140: | ||
| 141: | protected override void OnResize(EventArgs e) | |
| 142: | { | |
| 143: | base.OnResize(e); | |
| 144: | if (Columns != null && Columns.Count > 0) | |
| 145: | Columns[0].Width = Width; | |
| 146: | } | |
| 147: | ||
| 148: | public void ShowFilesInPath(string path) | |
| 149: | { | |
| 150: | string[] files; | |
| 151: | try { | |
| 152: | files = Directory.GetFiles(path); | |
| 153: | } catch (Exception) { | |
| 154: | return; | |
| 155: | } | |
| 156: | BeginUpdate(); | |
| 157: | Items.Clear(); | |
| 158: | foreach (string file in files) { | |
| 159: | Items.Add(new FileListItem(file)); | |
| 160: | } | |
| 161: | EndUpdate(); | |
| 162: | } | |
| 163: | ||
| 164: | public class FileListItem : ListViewItem | |
| 165: | { | |
| 166: | string fullname; | |
| 167: | public string FullName { | |
| 168: | get { | |
| 169: | return fullname; | |
| 170: | } | |
| 171: | } | |
| 172: | ||
| 173: | public FileListItem(string fullname) : base(Path.GetFileName(fullname)) | |
| 174: | { | |
| 175: | this.fullname = fullname; | |
| 176: | ImageIndex = FileUtility.GetImageIndexFor(fullname); | |
| 177: | } | |
| 178: | } | |
| 179: | ||
| 180: | } | |
| 181: | ||
| 182: | public class FileScout : UserControl | |
| 183: | { | |
| 184: | MainWindow main; | |
| 185: | DriveSelector driveselector = new DriveSelector(); | |
| 186: | Splitter splitter1 = new Splitter(); | |
| 187: | ||
| 188: | FileList filelister = new FileList(); | |
| 189: | ShellTree filetree = new ShellTree(); | |
| 190: | ||
| 191: | public FileScout(MainWindow main) | |
| 192: | { | |
| 193: | this.main = main; | |
| 194: | Dock = DockStyle.Fill; | |
| 195: | ||
| 196: | filetree.Dock = DockStyle.Fill; | |
| 197: | filetree.BorderStyle = BorderStyle.Fixed3D; | |
| 198: | filetree.Location = new System.Drawing.Point(0, 22); | |
| 199: | filetree.Size = new System.Drawing.Size(184, 157); | |
| 200: | filetree.TabIndex = 1; | |
| 201: | filetree.AfterSelect += new TreeViewEventHandler(DirectorySelected); | |
| 202: | ImageList imglist = new ImageList(); | |
| 203: | ||
| 204: | imglist.Images.Add(Resource.GetBitmap("Icons.16x16.ClosedFolderBitmap")); | |
| 205: | imglist.Images.Add(Resource.GetBitmap("Icons.16x16.OpenFolderBitmap")); | |
| 206: | imglist.Images.Add(Resource.GetBitmap("Icons.16x16.FLOPPY")); | |
| 207: | imglist.Images.Add(Resource.GetBitmap("Icons.16x16.DRIVE")); | |
| 208: | imglist.Images.Add(Resource.GetBitmap("Icons.16x16.CDROM")); | |
| 209: | imglist.Images.Add(Resource.GetBitmap("Icons.16x16.NETWORK")); | |
| 210: | ||
| 211: | filetree.ImageList = imglist; | |
| 212: | ||
| 213: | filelister.Dock = DockStyle.Bottom; | |
| 214: | filelister.BorderStyle = BorderStyle.Fixed3D; | |
| 215: | filelister.Location = new System.Drawing.Point(0, 184); | |
| 216: | ||
| 217: | filelister.Sorting = SortOrder.Ascending; | |
| 218: | filelister.Size = new System.Drawing.Size(184, 450); | |
| 219: | filelister.TabIndex = 3; | |
| 220: | filelister.ItemActivate += new EventHandler(FileSelected); | |
| 221: | ||
| 222: | splitter1.Dock = DockStyle.Bottom; | |
| 223: | splitter1.Location = new System.Drawing.Point(0, 179); | |
| 224: | splitter1.Size = new System.Drawing.Size(184, 5); | |
| 225: | splitter1.TabIndex = 2; | |
| 226: | splitter1.TabStop = false; | |
| 227: | ||
| 228: | driveselector.Size = new System.Drawing.Size(184, 21); | |
| 229: | driveselector.Dock = DockStyle.Top; | |
| 230: | driveselector.TabIndex = 0; | |
| 231: | driveselector.SelectedIndexChanged += new EventHandler(DriveSelectionChange); | |
| 232: | ||
| 233: | this.Controls.Add(filetree); | |
| 234: | this.Controls.Add(splitter1); | |
| 235: | this.Controls.Add(filelister); | |
| 236: | this.Controls.Add(driveselector); | |
| 237: | DriveSelectionChange(null, null); | |
| 238: | } | |
| 239: | ||
| 240: | void DriveSelectionChange(object sender, EventArgs e) | |
| 241: | { | |
| 242: | filetree.InitializeShellTree(driveselector.GetDrive()); | |
| 243: | ||
| 244: | filelister.Items.Clear(); // clear all file entries | |
| 245: | } | |
| 246: | ||
| 247: | void DirectorySelected(object sender, TreeViewEventArgs e) | |
| 248: | { | |
| 249: | filelister.ShowFilesInPath(filetree.NodePath + Path.DirectorySeparatorChar); | |
| 250: | } | |
| 251: | ||
| 252: | void FileSelected(object sender, EventArgs e) | |
| 253: | { | |
| 254: | foreach (FileList.FileListItem item in filelister.SelectedItems) { | |
| 255: | FileType filetype = FSTypeUtility.GetFileType(item.FullName); | |
| 256: | switch (filetype) { | |
| 257: | case FileType.SharpDevelopProject: | |
| 258: | main.ProjectBrowser.OpenProject(item.FullName); | |
| 259: | main.ProjectMode = true; | |
| 260: | break; | |
| 261: | default: | |
| 262: | main.OpenWindow(item.FullName); | |
| 263: | break; | |
| 264: | } | |
| 265: | } | |
| 266: | } | |
| 267: | } | |
| 268: | ||
| 269: | ||
| 270: | public class ShellTree : TreeView | |
| 271: | { | |
| 272: | public string NodePath { | |
| 273: | get { | |
| 274: | return SelectedNode.FullPath; | |
| 275: | } | |
| 276: | set { | |
| 277: | PopulateShellTree(value); | |
| 278: | } | |
| 279: | } | |
| 280: | ||
| 281: | public ShellTree() | |
| 282: | { | |
| 283: | InitializeComponent(); | |
| 284: | Sorted = true; | |
| 285: | } | |
| 286: | ||
| 287: | void InitializeComponent () | |
| 288: | { | |
| 289: | BeforeSelect += new TreeViewCancelEventHandler(SetClosedIcon); | |
| 290: | AfterSelect += new TreeViewEventHandler(SetOpenedIcon); | |
| 291: | } | |
| 292: | ||
| 293: | void SetClosedIcon(object sender, TreeViewCancelEventArgs e) // Set icon as closed | |
| 294: | { | |
| 295: | if (SelectedNode != null && SelectedNode.Parent != null) | |
| 296: | SelectedNode.ImageIndex = SelectedNode.SelectedImageIndex = 0; | |
| 297: | } | |
| 298: | ||
| 299: | void SetOpenedIcon(object sender, TreeViewEventArgs e) // Set icon as opened | |
| 300: | { | |
| 301: | if (e.Node.Parent != null) | |
| 302: | e.Node.ImageIndex = e.Node.SelectedImageIndex = 1; | |
| 303: | } | |
| 304: | ||
| 305: | void PopulateShellTree(string path) | |
| 306: | { | |
| 307: | string[] pathlist = path.Split(new char[] { Path.DirectorySeparatorChar }); | |
| 308: | TreeNodeCollection curnode = Nodes; | |
| 309: | ||
| 310: | foreach(string dir in pathlist) { | |
| 311: | ||
| 312: | foreach(TreeNode childnode in curnode) { | |
| 313: | if (childnode.Text.ToUpper().Equals(dir.ToUpper())) { | |
| 314: | SelectedNode = childnode; | |
| 315: | ||
| 316: | PopulateSubDirectory(childnode, 2); | |
| 317: | childnode.Expand(); | |
| 318: | ||
| 319: | curnode = childnode.Nodes; | |
| 320: | break; | |
| 321: | } | |
| 322: | } | |
| 323: | } | |
| 324: | } | |
| 325: | ||
| 326: | void PopulateSubDirectory(TreeNode curNode, int depth) | |
| 327: | { | |
| 328: | if (--depth < 0) { | |
| 329: | return; | |
| 330: | } | |
| 331: | ||
| 332: | if (curNode.Nodes.Count == 1 && curNode.Nodes[0].Text.Equals("")) { | |
| 333: | string[] directories = Directory.GetDirectories(curNode.FullPath + Path.DirectorySeparatorChar); | |
| 334: | ||
| 335: | curNode.Nodes.Clear(); | |
| 336: | ||
| 337: | foreach (string fulldir in directories) { | |
| 338: | string dir = System.IO.Path.GetFileName(fulldir); | |
| 339: | ||
| 340: | FileAttributes attr = File.GetAttributes(fulldir); | |
| 341: | if ((attr & FileAttributes.Hidden) == 0) { | |
| 342: | TreeNode node = curNode.Nodes.Add(dir); | |
| 343: | node.ImageIndex = node.SelectedImageIndex = 0; | |
| 344: | ||
| 345: | node.Nodes.Add(""); // Add dummy child node to make node expandable | |
| 346: | ||
| 347: | PopulateSubDirectory(node, depth); | |
| 348: | } | |
| 349: | } | |
| 350: | } else { | |
| 351: | foreach (TreeNode node in curNode.Nodes) { | |
| 352: | PopulateSubDirectory(node, depth); // Populate sub directory | |
| 353: | } | |
| 354: | } | |
| 355: | } | |
| 356: | ||
| 357: | ||
| 358: | protected override void OnBeforeExpand(TreeViewCancelEventArgs e) | |
| 359: | { | |
| 360: | Cursor.Current = Cursors.WaitCursor; | |
| 361: | ||
| 362: | try { | |
| 363: | PopulateSubDirectory(e.Node, 2); | |
| 364: | Cursor.Current = Cursors.Default; | |
| 365: | // SetOpenedIcon(null, null); // optional | |
| 366: | } catch (Exception excpt) { | |
| 367: | MessageBox.Show(excpt.Message, "Device error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); | |
| 368: | e.Cancel = true; | |
| 369: | } | |
| 370: | ||
| 371: | Cursor.Current = Cursors.Default; | |
| 372: | } | |
| 373: |