// Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // Copyright (c) 2006 Alexander Olk // // Authors: // // Alexander Olk alex.olk@googlemail.com // Gert Driesen (drieseng@users.sourceforge.net) // Eric Petit (surfzoid2002@yahoo.fr) // // TODO: // Keyboard shortcuts (DEL, F5, F2) // ?? using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Drawing; using System.IO; using System.Resources; using System.Text; using System.Threading; using System.Xml; namespace System.Windows.Forms { #region FileDialog [DefaultProperty ("FileName")] [DefaultEvent ("FileOk")] public abstract class FileDialog : CommonDialog { protected static readonly object EventFileOk = new object (); private static int MaxFileNameItems = 10; internal enum FileDialogType { OpenFileDialog, SaveFileDialog } private bool addExtension = true; private bool checkFileExists; private bool checkPathExists = true; private string defaultExt; private bool dereferenceLinks = true; private string[] fileNames; private string filter = ""; private int filterIndex = 1; private string initialDirectory; private bool restoreDirectory; private bool showHelp; private string title; private bool validateNames = true; private bool auto_upgrade_enable = true; private FileDialogCustomPlacesCollection custom_places; private bool supportMultiDottedExtensions; private bool checkForIllegalChars = true; private Button cancelButton; private ToolBarButton upToolBarButton; private PopupButtonPanel popupButtonPanel; private Button openSaveButton; private Button helpButton; private Label fileTypeLabel; private ToolBarButton menueToolBarButton; private ContextMenu menueToolBarButtonContextMenu; private ToolBar smallButtonToolBar; private DirComboBox dirComboBox; private ComboBox fileNameComboBox; private Label fileNameLabel; private MWFFileView mwfFileView; private MwfFileViewItemComparer file_view_comparer; private Label searchSaveLabel; private ToolBarButton newdirToolBarButton; private ToolBarButton backToolBarButton; private ComboBox fileTypeComboBox; private ImageList imageListTopToolbar; private CheckBox readonlyCheckBox; private bool multiSelect; private string restoreDirectoryString = String.Empty; internal FileDialogType fileDialogType; private bool do_not_call_OnSelectedIndexChangedFileTypeComboBox; private bool showReadOnly; private bool readOnlyChecked; internal bool createPrompt; internal bool overwritePrompt = true; private FileFilter fileFilter; private string[] configFileNames = null; private string lastFolder = String.Empty; private MWFVFS vfs; private const string filedialog_string = "FileDialog"; private const string lastfolder_string = "LastFolder"; private const string width_string = "Width"; private const string height_string = "Height"; private const string filenames_string = "FileNames"; private const string x_string = "X"; private const string y_string = "Y"; private readonly char [] wildcard_chars = new char [] { '*', '?' }; private bool disable_form_closed_event; internal FileDialog () { form = new DialogForm (this); vfs = new MWFVFS (); Size formConfigSize = Size.Empty; Point formConfigLocation = Point.Empty; object formWidth = MWFConfig.GetValue (filedialog_string, width_string); object formHeight = MWFConfig.GetValue (filedialog_string, height_string); if (formHeight != null && formWidth != null) formConfigSize = new Size ((int)formWidth, (int)formHeight); object formLocationX = MWFConfig.GetValue (filedialog_string, x_string); object formLocationY = MWFConfig.GetValue (filedialog_string, y_string); if (formLocationX != null && formLocationY != null) formConfigLocation = new Point ((int)formLocationX, (int)formLocationY); configFileNames = (string[])MWFConfig.GetValue (filedialog_string, filenames_string); fileTypeComboBox = new ComboBox (); backToolBarButton = new ToolBarButton (); newdirToolBarButton = new ToolBarButton (); searchSaveLabel = new Label (); mwfFileView = new MWFFileView (vfs); fileNameLabel = new Label (); fileNameComboBox = new ComboBox (); dirComboBox = new DirComboBox (vfs); smallButtonToolBar = new ToolBar (); menueToolBarButton = new ToolBarButton (); fileTypeLabel = new Label (); openSaveButton = new Button (); helpButton = new Button (); popupButtonPanel = new PopupButtonPanel (); upToolBarButton = new ToolBarButton (); cancelButton = new Button (); form.CancelButton = cancelButton; imageListTopToolbar = new ImageList (); menueToolBarButtonContextMenu = new ContextMenu (); readonlyCheckBox = new CheckBox (); form.SuspendLayout (); //imageListTopToolbar imageListTopToolbar.ColorDepth = ColorDepth.Depth32Bit; imageListTopToolbar.ImageSize = new Size (16, 16); // 16, 16 imageListTopToolbar.Images.Add (ResourceImageLoader.Get ("go-previous.png")); imageListTopToolbar.Images.Add (ResourceImageLoader.Get ("go-top.png")); imageListTopToolbar.Images.Add (ResourceImageLoader.Get ("folder-new.png")); imageListTopToolbar.Images.Add (ResourceImageLoader.Get ("preferences-system-windows.png")); imageListTopToolbar.TransparentColor = Color.Transparent; // searchLabel searchSaveLabel.FlatStyle = FlatStyle.System; searchSaveLabel.Location = new Point (6, 6); searchSaveLabel.Size = new Size (86, 22); searchSaveLabel.TextAlign = ContentAlignment.MiddleRight; // dirComboBox dirComboBox.Anchor = ((AnchorStyles)(((AnchorStyles.Top | AnchorStyles.Left) | AnchorStyles.Right))); dirComboBox.DropDownStyle = ComboBoxStyle.DropDownList; dirComboBox.Location = new Point (99, 6); dirComboBox.Size = new Size (261, 22); dirComboBox.TabIndex = 7; // smallButtonToolBar smallButtonToolBar.Anchor = ((AnchorStyles)((AnchorStyles.Top | AnchorStyles.Right))); smallButtonToolBar.Appearance = ToolBarAppearance.Flat; smallButtonToolBar.AutoSize = false; smallButtonToolBar.Buttons.AddRange (new ToolBarButton [] { backToolBarButton, upToolBarButton, newdirToolBarButton, menueToolBarButton}); smallButtonToolBar.ButtonSize = new Size (24, 24); // 21, 16 smallButtonToolBar.Divider = false; smallButtonToolBar.Dock = DockStyle.None; smallButtonToolBar.DropDownArrows = true; smallButtonToolBar.ImageList = imageListTopToolbar; smallButtonToolBar.Location = new Point (372, 6); smallButtonToolBar.ShowToolTips = true; smallButtonToolBar.Size = new Size (140, 28); smallButtonToolBar.TabIndex = 8; smallButtonToolBar.TextAlign = ToolBarTextAlign.Right; // buttonPanel popupButtonPanel.Dock = DockStyle.None; popupButtonPanel.Anchor = ((AnchorStyles)((((AnchorStyles.Top | AnchorStyles.Bottom) | AnchorStyles.Left)))); popupButtonPanel.Location = new Point (6, 35); popupButtonPanel.Size = new Size (87, 338); popupButtonPanel.TabIndex = 9; // mwfFileView mwfFileView.Anchor = ((AnchorStyles)((((AnchorStyles.Top | AnchorStyles.Bottom) | AnchorStyles.Left) | AnchorStyles.Right))); mwfFileView.Location = new Point (99, 35); mwfFileView.Size = new Size (450, 283); mwfFileView.MultiSelect = false; mwfFileView.TabIndex = 10; mwfFileView.RegisterSender (dirComboBox); mwfFileView.RegisterSender (popupButtonPanel); // fileNameLabel fileNameLabel.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Left))); fileNameLabel.FlatStyle = FlatStyle.System; fileNameLabel.Location = new Point (101, 326); fileNameLabel.Size = new Size (70, 21); fileNameLabel.Text = "File name:"; fileNameLabel.TextAlign = ContentAlignment.MiddleLeft; // fileNameComboBox fileNameComboBox.Anchor = ((AnchorStyles)(((AnchorStyles.Bottom | AnchorStyles.Left) | AnchorStyles.Right))); fileNameComboBox.Location = new Point (195, 326); fileNameComboBox.Size = new Size (246, 22); fileNameComboBox.TabIndex = 1; fileNameComboBox.MaxDropDownItems = MaxFileNameItems; fileNameComboBox.RestoreContextMenu (); UpdateRecentFiles (); // fileTypeLabel fileTypeLabel.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Left))); fileTypeLabel.FlatStyle = FlatStyle.System; fileTypeLabel.Location = new Point (101, 355); fileTypeLabel.Size = new Size (90, 21); fileTypeLabel.Text = "Files of type:"; fileTypeLabel.TextAlign = ContentAlignment.MiddleLeft; // fileTypeComboBox fileTypeComboBox.Anchor = ((AnchorStyles)(((AnchorStyles.Bottom | AnchorStyles.Left) | AnchorStyles.Right))); fileTypeComboBox.DropDownStyle = ComboBoxStyle.DropDownList; fileTypeComboBox.Location = new Point (195, 355); fileTypeComboBox.Size = new Size (246, 22); fileTypeComboBox.TabIndex = 2; // backToolBarButton backToolBarButton.ImageIndex = 0; backToolBarButton.Enabled = false; backToolBarButton.Style = ToolBarButtonStyle.PushButton; mwfFileView.AddControlToEnableDisableByDirStack (backToolBarButton); // upToolBarButton upToolBarButton.ImageIndex = 1; upToolBarButton.Style = ToolBarButtonStyle.PushButton; mwfFileView.SetFolderUpToolBarButton (upToolBarButton); // newdirToolBarButton newdirToolBarButton.ImageIndex = 2; newdirToolBarButton.Style = ToolBarButtonStyle.PushButton; // menueToolBarButton menueToolBarButton.ImageIndex = 3; menueToolBarButton.DropDownMenu = menueToolBarButtonContextMenu; menueToolBarButton.Style = ToolBarButtonStyle.DropDownButton; // menueToolBarButtonContextMenu menueToolBarButtonContextMenu.MenuItems.AddRange (mwfFileView.ViewMenuItems); // openSaveButton openSaveButton.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Right))); openSaveButton.FlatStyle = FlatStyle.System; openSaveButton.Location = new Point (474, 326); openSaveButton.Size = new Size (75, 23); openSaveButton.TabIndex = 4; openSaveButton.FlatStyle = FlatStyle.System; // cancelButton cancelButton.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Right))); cancelButton.FlatStyle = FlatStyle.System; cancelButton.Location = new Point (474, 353); cancelButton.Size = new Size (75, 23); cancelButton.TabIndex = 5; cancelButton.Text = "Cancel"; cancelButton.FlatStyle = FlatStyle.System; // helpButton helpButton.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Right))); helpButton.FlatStyle = FlatStyle.System; helpButton.Location = new Point (474, 353); helpButton.Size = new Size (75, 23); helpButton.TabIndex = 6; helpButton.Text = "Help"; helpButton.FlatStyle = FlatStyle.System; helpButton.Visible = false; // checkBox readonlyCheckBox.Anchor = ((AnchorStyles)(((AnchorStyles.Bottom | AnchorStyles.Left) | AnchorStyles.Right))); readonlyCheckBox.Text = "Open Readonly"; readonlyCheckBox.Location = new Point (195, 350); readonlyCheckBox.Size = new Size (245, 21); readonlyCheckBox.TabIndex = 3; readonlyCheckBox.FlatStyle = FlatStyle.System; readonlyCheckBox.Visible = false; form.SizeGripStyle = SizeGripStyle.Show; form.AcceptButton = openSaveButton; form.MaximizeBox = true; form.MinimizeBox = true; form.FormBorderStyle = FormBorderStyle.Sizable; form.ClientSize = new Size (555, 385); form.MinimumSize = form.Size; form.Controls.Add (smallButtonToolBar); form.Controls.Add (cancelButton); form.Controls.Add (openSaveButton); form.Controls.Add (mwfFileView); form.Controls.Add (fileTypeLabel); form.Controls.Add (fileNameLabel); form.Controls.Add (fileTypeComboBox); form.Controls.Add (fileNameComboBox); form.Controls.Add (dirComboBox); form.Controls.Add (searchSaveLabel); form.Controls.Add (popupButtonPanel); form.Controls.Add (helpButton); form.Controls.Add (readonlyCheckBox); form.ResumeLayout (true); if (formConfigSize != Size.Empty) { form.ClientSize = formConfigSize; } if (formConfigLocation != Point.Empty) { form.Location = formConfigLocation; } openSaveButton.Click += new EventHandler (OnClickOpenSaveButton); cancelButton.Click += new EventHandler (OnClickCancelButton); helpButton.Click += new EventHandler (OnClickHelpButton); smallButtonToolBar.ButtonClick += new ToolBarButtonClickEventHandler (OnClickSmallButtonToolBar); fileTypeComboBox.SelectedIndexChanged += new EventHandler (OnSelectedIndexChangedFileTypeComboBox); mwfFileView.SelectedFileChanged += new EventHandler (OnSelectedFileChangedFileView); mwfFileView.ForceDialogEnd += new EventHandler (OnForceDialogEndFileView); mwfFileView.SelectedFilesChanged += new EventHandler (OnSelectedFilesChangedFileView); mwfFileView.ColumnClick += new ColumnClickEventHandler(OnColumnClickFileView); dirComboBox.DirectoryChanged += new EventHandler (OnDirectoryChangedDirComboBox); popupButtonPanel.DirectoryChanged += new EventHandler (OnDirectoryChangedPopupButtonPanel); readonlyCheckBox.CheckedChanged += new EventHandler (OnCheckCheckChanged); form.FormClosed += new FormClosedEventHandler (OnFileDialogFormClosed); custom_places = new FileDialogCustomPlacesCollection (); } [DefaultValue(true)] public bool AddExtension { get { return addExtension; } set { addExtension = value; } } [MonoTODO ("Stub, value not respected")] [DefaultValue (true)] public bool AutoUpgradeEnabled { get { return auto_upgrade_enable; } set { auto_upgrade_enable = value; } } [DefaultValue(false)] public virtual bool CheckFileExists { get { return checkFileExists; } set { checkFileExists = value; } } [DefaultValue(true)] public bool CheckPathExists { get { return checkPathExists; } set { checkPathExists = value; } } [MonoTODO ("Stub, collection not used")] [Browsable (false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public FileDialogCustomPlacesCollection CustomPlaces { get { return custom_places; } } [DefaultValue("")] public string DefaultExt { get { if (defaultExt == null) return string.Empty; return defaultExt; } set { if (value != null && value.Length > 0) { // remove leading dot if (value [0] == '.') value = value.Substring (1); } defaultExt = value; } } // in MS.NET it doesn't make a difference if // DerefenceLinks is true or false // if the selected file is a link FileDialog // always returns the link [DefaultValue(true)] public bool DereferenceLinks { get { return dereferenceLinks; } set { dereferenceLinks = value; } } [DefaultValue("")] public string FileName { get { if (fileNames == null || fileNames.Length == 0) return string.Empty; if (fileNames [0].Length == 0) return string.Empty; // skip check for illegal characters if the filename was set // through FileDialog API if (!checkForIllegalChars) return fileNames [0]; // ensure filename contains only valid characters Path.GetFullPath (fileNames [0]); // but return filename as is return fileNames [0]; } set { if (value != null) { fileNames = new string [1] { value }; } else { fileNames = new string [0]; } // skip check for illegal characters if the filename was set // through FileDialog API checkForIllegalChars = false; } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public string[] FileNames { get { if (fileNames == null || fileNames.Length == 0) { return new string [0]; } string[] new_filenames = new string [fileNames.Length]; fileNames.CopyTo (new_filenames, 0); // skip check for illegal characters if the filename was set // through FileDialog API if (!checkForIllegalChars) return new_filenames; foreach (string fileName in new_filenames) { // ensure filename contains only valid characters Path.GetFullPath (fileName); } return new_filenames; } } [DefaultValue("")] [Localizable(true)] public string Filter { get { return filter; } set { if (value == null) { filter = ""; if (fileFilter != null) fileFilter.FilterArrayList.Clear (); } else { if (FileFilter.CheckFilter (value)) { filter = value; fileFilter = new FileFilter (filter); } else throw new ArgumentException ("The provided filter string" + " is invalid. The filter string should contain a" + " description of the filter, followed by the " + " vertical bar (|) and the filter pattern. The" + " strings for different filtering options should" + " also be separated by the vertical bar. Example:" + " Text files (*.txt)|*.txt|All files (*.*)|*.*"); } UpdateFilters (); } } [DefaultValue(1)] public int FilterIndex { get { return filterIndex; } set { filterIndex = value; } } [DefaultValue("")] public string InitialDirectory { get { if (initialDirectory == null) return string.Empty; return initialDirectory; } set { initialDirectory = value; } } [DefaultValue(false)] public bool RestoreDirectory { get { return restoreDirectory; } set { restoreDirectory = value; } } [DefaultValue(false)] public bool ShowHelp { get { return showHelp; } set { showHelp = value; ResizeAndRelocateForHelpOrReadOnly (); } } [DefaultValue(false)] public bool SupportMultiDottedExtensions { get { return supportMultiDottedExtensions; } set { supportMultiDottedExtensions = value; } } [DefaultValue("")] [Localizable(true)] public string Title { get { if (title == null) return string.Empty; return title; } set { title = value; } } // this one is a hard one ;) // Win32 filename: // - up to MAX_PATH characters (windef.h) = 260 // - no trailing dots or spaces // - case preserving // - etc... // NTFS/Posix filename: // - up to 32,768 Unicode characters // - trailing periods or spaces // - case sensitive // - etc... [DefaultValue(true)] public bool ValidateNames { get { return validateNames; } set { validateNames = value; } } public override void Reset () { addExtension = true; checkFileExists = false; checkPathExists = true; DefaultExt = null; dereferenceLinks = true; FileName = null; Filter = String.Empty; FilterIndex = 1; InitialDirectory = null; restoreDirectory = false; SupportMultiDottedExtensions = false; ShowHelp = false; Title = null; validateNames = true; UpdateFilters (); } public override string ToString () { return String.Format("{0}: Title: {1}, FileName: {2}", base.ToString (), Title, FileName); } public event CancelEventHandler FileOk { add { Events.AddHandler (EventFileOk, value); } remove { Events.RemoveHandler (EventFileOk, value); } } protected virtual IntPtr Instance { get { if (form == null) return IntPtr.Zero; return form.Handle; } } // This is just for internal use with MSs version, so it doesn't need to be implemented // as it can't really be accessed anyways protected int Options { get { return -1; } } internal virtual string DialogTitle { get { return Title; } } [MonoTODO ("Not implemented, will throw NotImplementedException")] protected override IntPtr HookProc (IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) { throw new NotImplementedException (); } protected void OnFileOk (CancelEventArgs e) { CancelEventHandler fo = (CancelEventHandler) Events [EventFileOk]; if (fo != null) fo (this, e); } private void CleanupOnClose () { WriteConfigValues (); Mime.CleanFileCache (); disable_form_closed_event = true; } protected override bool RunDialog (IntPtr hWndOwner) { ReadConfigValues (); form.Text = DialogTitle; // avoid using the FileNames property to skip the invalid characters // check string fileName = null; if (fileNames != null && fileNames.Length != 0) fileName = fileNames [0]; else fileName = string.Empty; SelectFilter (); form.Refresh (); SetFileAndDirectory (fileName); fileNameComboBox.Select (); return true; } internal virtual bool ShowReadOnly { set { showReadOnly = value; ResizeAndRelocateForHelpOrReadOnly (); } get { return showReadOnly; } } internal virtual bool ReadOnlyChecked { set { readOnlyChecked = value; readonlyCheckBox.Checked = value; } get { return readOnlyChecked; } } internal bool BMultiSelect { set { multiSelect = value; mwfFileView.MultiSelect = value; } get { return multiSelect; } } internal string OpenSaveButtonText { set { openSaveButton.Text = value; } } internal string SearchSaveLabel { set { searchSaveLabel.Text = value; } } internal string FileTypeLabel { set { fileTypeLabel.Text = value; } } internal string CustomFilter { get { string fname = fileNameComboBox.Text; if (fname.IndexOfAny (wildcard_chars) == -1) return null; return fname; } } private void SelectFilter () { int filter_to_select = (filterIndex - 1); if (mwfFileView.FilterArrayList == null || mwfFileView.FilterArrayList.Count == 0) { filter_to_select = -1; } else { if (filter_to_select < 0 || filter_to_select >= mwfFileView.FilterArrayList.Count) filter_to_select = 0; } do_not_call_OnSelectedIndexChangedFileTypeComboBox = true; fileTypeComboBox.BeginUpdate (); fileTypeComboBox.SelectedIndex = filter_to_select; fileTypeComboBox.EndUpdate (); do_not_call_OnSelectedIndexChangedFileTypeComboBox = false; mwfFileView.FilterIndex = filter_to_select + 1; } private void SetFileAndDirectory (string fname) { if (fname.Length != 0) { bool rooted = Path.IsPathRooted (fname); if (!rooted) { mwfFileView.ChangeDirectory (null, lastFolder); fileNameComboBox.Text = fname; } else { string dirname = Path.GetDirectoryName (fname); if (dirname != null && dirname.Length > 0 && Directory.Exists (dirname)) { fileNameComboBox.Text = Path.GetFileName (fname); mwfFileView.ChangeDirectory (null, dirname); } else { fileNameComboBox.Text = fname; mwfFileView.ChangeDirectory (null, lastFolder); } } } else { mwfFileView.ChangeDirectory (null, lastFolder); fileNameComboBox.Text = null; } } void OnClickOpenSaveButton (object sender, EventArgs e) { // for filenames typed or selected by user, enable check for // illegal characters in filename(s) checkForIllegalChars = true; if (fileDialogType == FileDialogType.OpenFileDialog) { ListView.SelectedListViewItemCollection sl = mwfFileView.SelectedItems; if (sl.Count > 0 && sl [0] != null) { if (sl.Count == 1) { FileViewListViewItem item = sl [0] as FileViewListViewItem; FSEntry fsEntry = item.FSEntry; if ((fsEntry.Attributes & FileAttributes.Directory) == FileAttributes.Directory) { mwfFileView.ChangeDirectory (null, fsEntry.FullName, CustomFilter); return; } } else { foreach (FileViewListViewItem item in sl) { FSEntry fsEntry = item.FSEntry; if ((fsEntry.Attributes & FileAttributes.Directory) == FileAttributes.Directory) { mwfFileView.ChangeDirectory (null, fsEntry.FullName, CustomFilter); return; } } } } } // Custom filter, typed by the user, ignoring the stored filters if (fileNameComboBox.Text.IndexOfAny (wildcard_chars) != -1) { mwfFileView.UpdateFileView (fileNameComboBox.Text); return; } ArrayList files = new ArrayList (); FileNamesTokenizer tokenizer = new FileNamesTokenizer ( fileNameComboBox.Text, multiSelect); tokenizer.GetNextFile (); while (tokenizer.CurrentToken != TokenType.EOF) { string fileName = tokenizer.TokenText; string internalfullfilename; if (!Path.IsPathRooted (fileName)) { // on unix currentRealFolder for "Recently used files" is null, // because recently used files don't get saved as links in a directory // recently used files get saved in a xml file if (mwfFileView.CurrentRealFolder != null) fileName = Path.Combine (mwfFileView.CurrentRealFolder, fileName); else if (mwfFileView.CurrentFSEntry != null) { fileName = mwfFileView.CurrentFSEntry.FullName; } } FileInfo fileInfo = new FileInfo (fileName); if (fileInfo.Exists || fileDialogType == FileDialogType.SaveFileDialog) { internalfullfilename = fileName; } else { DirectoryInfo dirInfo = new DirectoryInfo (fileName); if (dirInfo.Exists) { mwfFileView.ChangeDirectory (null, dirInfo.FullName, CustomFilter); fileNameComboBox.Text = null; return; } else { internalfullfilename = fileName; } } if (addExtension) { string current_extension = Path.GetExtension (fileName); if (current_extension.Length == 0) { string filter_extension = string.Empty; if (AddFilterExtension (internalfullfilename)) filter_extension = GetExtension (internalfullfilename); if (filter_extension.Length == 0 && DefaultExt.Length > 0) { filter_extension = "." + DefaultExt; if (checkFileExists) { // ignore DefaultExt if file not exist if (!File.Exists (internalfullfilename + filter_extension)) filter_extension = string.Empty; } } internalfullfilename += filter_extension; } } if (checkFileExists) { if (!File.Exists (internalfullfilename)) { string message = "\"" + internalfullfilename + "\" does not exist. Please verify that you have entered the correct file name."; MessageBox.Show (message, openSaveButton.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } } if (fileDialogType == FileDialogType.SaveFileDialog) { if (overwritePrompt) { if (File.Exists (internalfullfilename)) { string message = "\"" + internalfullfilename + "\" already exists. Do you want to overwrite it?"; DialogResult dr = MessageBox.Show (message, openSaveButton.Text, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); if (dr == DialogResult.Cancel) return; } } if (createPrompt) { if (!File.Exists (internalfullfilename)) { string message = "\"" + internalfullfilename + "\" does not exist. Do you want to create it?"; DialogResult dr = MessageBox.Show (message, openSaveButton.Text, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); if (dr == DialogResult.Cancel) return; } } } files.Add (internalfullfilename); tokenizer.GetNextFile (); } if (files.Count > 0) { fileNames = new string [files.Count]; for (int i = 0; i < files.Count; i++) { string fileName = (string) files [i]; fileNames [i] = fileName; mwfFileView.WriteRecentlyUsed (fileName); if (!File.Exists (fileName)) // ignore files that do not exist continue; if (fileNameComboBox.Items.IndexOf (fileName) == -1) fileNameComboBox.Items.Insert (0, fileName); } // remove items above the maximum items that we want to display while (fileNameComboBox.Items.Count > MaxFileNameItems) fileNameComboBox.Items.RemoveAt (MaxFileNameItems); } else { // If a directory is selected, navigate into it foreach (FileViewListViewItem item in mwfFileView.SelectedItems) { FSEntry fsEntry = item.FSEntry; if ((fsEntry.Attributes & FileAttributes.Directory) == FileAttributes.Directory) { mwfFileView.ChangeDirectory (null, fsEntry.FullName, CustomFilter); return; } } return; } if (checkPathExists && mwfFileView.CurrentRealFolder != null) { if (!Directory.Exists (mwfFileView.CurrentRealFolder)) { string message = "\"" + mwfFileView.CurrentRealFolder + "\" does not exist. Please verify that you have entered the correct directory name."; MessageBox.Show (message, openSaveButton.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning); if (InitialDirectory.Length == 0 || !Directory.Exists (InitialDirectory)) mwfFileView.ChangeDirectory (null, lastFolder, CustomFilter); else mwfFileView.ChangeDirectory (null, InitialDirectory, CustomFilter); return; } } if (restoreDirectory) { lastFolder = restoreDirectoryString; } else { lastFolder = mwfFileView.CurrentFolder; } // update value of FilterIndex with user-selected filter filterIndex = fileTypeComboBox.SelectedIndex + 1; CancelEventArgs cancelEventArgs = new CancelEventArgs (); OnFileOk (cancelEventArgs); if (cancelEventArgs.Cancel) return; CleanupOnClose (); form.DialogResult = DialogResult.OK; } bool AddFilterExtension (string fileName) { if (fileDialogType == FileDialogType.OpenFileDialog) { if (DefaultExt.Length == 0) return true; if (checkFileExists) { // if CheckFileExists is true, only add filter extension if // file with DefaultExt does not exist string fullFileName = fileName + "." + DefaultExt; return !File.Exists (fullFileName); } else { // if CheckFileExists is false, only add filter extension // if specified file does not exist return !File.Exists (fileName); } } return true; } string GetExtension (string fileName) { string filter_extension = String.Empty; if (fileFilter == null || fileTypeComboBox.SelectedIndex == -1) return filter_extension; FilterStruct filterstruct = (FilterStruct) fileFilter.FilterArrayList [fileTypeComboBox.SelectedIndex]; for (int i = 0; i < filterstruct.filters.Count; i++) { string extension = filterstruct.filters [i]; if (extension.StartsWith ("*")) extension = extension.Remove (0, 1); if (extension.IndexOf ('*') != -1) continue; if (!supportMultiDottedExtensions) { int lastdot = extension.LastIndexOf('.'); if (lastdot > 0) { if (extension.LastIndexOf('.', lastdot - 1) != -1) { extension = extension.Remove(0, lastdot); } } } if (!checkFileExists) { filter_extension = extension; break; } if (fileDialogType == FileDialogType.SaveFileDialog) { // when DefaultExt is set, only consider first filter // extension (and do not check if file exists) if (DefaultExt.Length > 0) { filter_extension = extension; break; } } // MSDN: If the CheckFileExists property is true, // the dialog box adds the first extension from the // current file filter that matches an existing file string fullfilename = fileName + extension; if (File.Exists (fullfilename)) { filter_extension = extension; break; } else { if (fileDialogType == FileDialogType.SaveFileDialog) { // when DefaultExt is set, only consider first filter // extension if (DefaultExt.Length > 0) { filter_extension = extension; break; } } } } return filter_extension; } void OnClickCancelButton (object sender, EventArgs e) { if (restoreDirectory) mwfFileView.CurrentFolder = restoreDirectoryString; CleanupOnClose (); form.DialogResult = DialogResult.Cancel; } void OnClickHelpButton (object sender, EventArgs e) { OnHelpRequest (e); } void OnClickSmallButtonToolBar (object sender, ToolBarButtonClickEventArgs e) { if (e.Button == upToolBarButton) { mwfFileView.OneDirUp (CustomFilter); } else if (e.Button == backToolBarButton) { mwfFileView.PopDir (CustomFilter); } else if (e.Button == newdirToolBarButton) { mwfFileView.CreateNewFolder (); } } void OnSelectedIndexChangedFileTypeComboBox (object sender, EventArgs e) { if (do_not_call_OnSelectedIndexChangedFileTypeComboBox) { do_not_call_OnSelectedIndexChangedFileTypeComboBox = false; return; } UpdateRecentFiles (); mwfFileView.FilterIndex = fileTypeComboBox.SelectedIndex + 1; } void OnSelectedFileChangedFileView (object sender, EventArgs e) { fileNameComboBox.Text = mwfFileView.CurrentFSEntry.Name; } void OnSelectedFilesChangedFileView (object sender, EventArgs e) { string selectedFiles = mwfFileView.SelectedFilesString; if (selectedFiles != null && selectedFiles.Length != 0) fileNameComboBox.Text = selectedFiles; } void OnForceDialogEndFileView (object sender, EventArgs e) { OnClickOpenSaveButton (this, EventArgs.Empty); } void OnDirectoryChangedDirComboBox (object sender, EventArgs e) { mwfFileView.ChangeDirectory (sender, dirComboBox.CurrentFolder, CustomFilter); } void OnDirectoryChangedPopupButtonPanel (object sender, EventArgs e) { mwfFileView.ChangeDirectory (sender, popupButtonPanel.CurrentFolder, CustomFilter); } void OnCheckCheckChanged (object sender, EventArgs e) { ReadOnlyChecked = readonlyCheckBox.Checked; } void OnFileDialogFormClosed (object sender, FormClosedEventArgs e) { HandleFormClosedEvent (sender); } private void OnColumnClickFileView (object sender, ColumnClickEventArgs e) { if (file_view_comparer == null) file_view_comparer = new MwfFileViewItemComparer (true); file_view_comparer.ColumnIndex = e.Column; file_view_comparer.Ascendent = !file_view_comparer.Ascendent; if (mwfFileView.ListViewItemSorter == null) mwfFileView.ListViewItemSorter = file_view_comparer; else mwfFileView.Sort (); } void HandleFormClosedEvent (object sender) { if (!disable_form_closed_event) OnClickCancelButton (sender, EventArgs.Empty); disable_form_closed_event = false; } private void UpdateFilters () { if (fileFilter == null) fileFilter = new FileFilter (); ArrayList filters = fileFilter.FilterArrayList; fileTypeComboBox.BeginUpdate (); fileTypeComboBox.Items.Clear (); foreach (FilterStruct fs in filters) { fileTypeComboBox.Items.Add (fs.filterName); } fileTypeComboBox.EndUpdate (); mwfFileView.FilterArrayList = filters; } private void UpdateRecentFiles () { fileNameComboBox.Items.Clear (); if (configFileNames != null) { foreach (string configFileName in configFileNames) { if (configFileName == null || configFileName.Trim ().Length == 0) continue; // add no more than 10 items if (fileNameComboBox.Items.Count >= MaxFileNameItems) break; fileNameComboBox.Items.Add (configFileName); } } } private void ResizeAndRelocateForHelpOrReadOnly () { form.SuspendLayout (); int fx = form.Size.Width - form.MinimumSize.Width; int fy = form.Size.Height - form.MinimumSize.Height; if (!ShowHelp && !ShowReadOnly) fy += 29; mwfFileView.Size = new Size (450 + fx, 254 + fy); fileNameLabel.Location = new Point (101, 298 + fy); fileNameComboBox.Location = new Point (195, 298 + fy); fileTypeLabel.Location = new Point (101, 326 + fy); fileTypeComboBox.Location = new Point (195, 326 + fy); openSaveButton.Location = new Point (474 + fx, 298 + fy); cancelButton.Location = new Point (474 + fx, 324 + fy); helpButton.Location = new Point (474 + fx, 353 + fy); readonlyCheckBox.Location = new Point (195, 350 + fy); helpButton.Visible = ShowHelp; readonlyCheckBox.Visible = ShowReadOnly; form.ResumeLayout (); } private void WriteConfigValues () { MWFConfig.SetValue (filedialog_string, width_string, form.ClientSize.Width); MWFConfig.SetValue (filedialog_string, height_string, form.ClientSize.Height); MWFConfig.SetValue (filedialog_string, x_string, form.Location.X); MWFConfig.SetValue (filedialog_string, y_string, form.Location.Y); MWFConfig.SetValue (filedialog_string, lastfolder_string, lastFolder); string[] fileNameCBItems = new string [fileNameComboBox.Items.Count]; fileNameComboBox.Items.CopyTo (fileNameCBItems, 0); MWFConfig.SetValue (filedialog_string, filenames_string, fileNameCBItems); } private void ReadConfigValues () { lastFolder = (string)MWFConfig.GetValue (filedialog_string, lastfolder_string); if (lastFolder != null && lastFolder.IndexOf ("://") == -1) { if (!Directory.Exists (lastFolder)) { lastFolder = MWFVFS.DesktopPrefix; } } if (InitialDirectory.Length > 0 && Directory.Exists (InitialDirectory)) lastFolder = InitialDirectory; else if (lastFolder == null || lastFolder.Length == 0) lastFolder = Environment.CurrentDirectory; if (RestoreDirectory) restoreDirectoryString = lastFolder; } class FileNamesTokenizer { public FileNamesTokenizer (string text, bool allowMultiple) { _text = text; _position = 0; _tokenType = TokenType.BOF; _allowMultiple = allowMultiple; } public TokenType CurrentToken { get { return _tokenType; } } public string TokenText { get { return _tokenText; } } public bool AllowMultiple { get { return _allowMultiple; } } private int ReadChar () { if (_position < _text.Length) { return _text [_position++]; } else { return -1; } } private int PeekChar () { if (_position < _text.Length) { return _text [_position]; } else { return -1; } } private void SkipWhitespaceAndQuotes () { int ch; while ((ch = PeekChar ()) != -1) { if ((char) ch != '"' && !char.IsWhiteSpace ((char) ch)) break; ReadChar (); } } public void GetNextFile () { if (_tokenType == TokenType.EOF) throw new Exception (""); int ch; SkipWhitespaceAndQuotes (); if (PeekChar () == -1) { _tokenType = TokenType.EOF; return; } _tokenType = TokenType.FileName; StringBuilder sb = new StringBuilder (); while ((ch = PeekChar ()) != -1) { if ((char) ch == '"') { ReadChar (); if (AllowMultiple) break; int pos = _position; SkipWhitespaceAndQuotes (); if (PeekChar () == -1) { break; } _position = ++pos; sb.Append ((char) ch); } else { sb.Append ((char) ReadChar ()); } } _tokenText = sb.ToString (); } private readonly bool _allowMultiple; private int _position; private readonly string _text; private TokenType _tokenType; private string _tokenText; } internal enum TokenType { BOF, EOF, FileName, } } #endregion #region PopupButtonPanel internal class PopupButtonPanel : Control, IUpdateFolder { #region PopupButton internal class PopupButton : Control { internal enum PopupButtonState { Normal, Down, Up} private Image image = null; private PopupButtonState popupButtonState = PopupButtonState.Normal; private StringFormat text_format = new StringFormat(); private Rectangle text_rect = Rectangle.Empty; public PopupButton () { text_format.Alignment = StringAlignment.Center; text_format.LineAlignment = StringAlignment.Near; SetStyle (ControlStyles.DoubleBuffer, true); SetStyle (ControlStyles.AllPaintingInWmPaint, true); SetStyle (ControlStyles.UserPaint, true); SetStyle (ControlStyles.Selectable, false); } public Image Image { set { image = value; Invalidate (); } get { return image; } } public PopupButtonState ButtonState { set { popupButtonState = value; Invalidate (); } get { return popupButtonState; } } #region UIA Framework Members internal void PerformClick () { OnClick (EventArgs.Empty); } #endregion protected override void OnPaint (PaintEventArgs pe) { Draw (pe); base.OnPaint (pe); } private void Draw (PaintEventArgs pe) { Graphics gr = pe.Graphics; gr.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), ClientRectangle); // draw image if (image != null) { int i_x = (ClientSize.Width - image.Width) / 2; int i_y = 4; gr.DrawImage (image, i_x, i_y); } if (Text != String.Empty) { if (text_rect == Rectangle.Empty) text_rect = new Rectangle (0, Height - 30, Width, Height - 30); gr.DrawString (Text, Font, Brushes.White, text_rect, text_format); } switch (popupButtonState) { case PopupButtonState.Up: gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.White), 0, 0, ClientSize.Width - 1, 0); gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.White), 0, 0, 0, ClientSize.Height - 1); gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.Black), ClientSize.Width - 1, 0, ClientSize.Width - 1, ClientSize.Height - 1); gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.Black), 0, ClientSize.Height - 1, ClientSize.Width - 1, ClientSize.Height - 1); break; case PopupButtonState.Down: gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.Black), 0, 0, ClientSize.Width - 1, 0); gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.Black), 0, 0, 0, ClientSize.Height - 1); gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.White), ClientSize.Width - 1, 0, ClientSize.Width - 1, ClientSize.Height - 1); gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.White), 0, ClientSize.Height - 1, ClientSize.Width - 1, ClientSize.Height - 1); break; } } protected override void OnMouseEnter (EventArgs e) { if (popupButtonState != PopupButtonState.Down) popupButtonState = PopupButtonState.Up; PopupButtonPanel panel = Parent as PopupButtonPanel; if (panel.focusButton != null && panel.focusButton.ButtonState == PopupButtonState.Up) { panel.focusButton.ButtonState = PopupButtonState.Normal; panel.SetFocusButton (null); } Invalidate (); base.OnMouseEnter (e); } protected override void OnMouseLeave (EventArgs e) { if (popupButtonState == PopupButtonState.Up) popupButtonState = PopupButtonState.Normal; Invalidate (); base.OnMouseLeave (e); } protected override void OnClick (EventArgs e) { popupButtonState = PopupButtonState.Down; Invalidate (); base.OnClick (e); } } #endregion private PopupButton recentlyusedButton; private PopupButton desktopButton; private PopupButton personalButton; private PopupButton mycomputerButton; private PopupButton networkButton; private PopupButton lastPopupButton = null; private PopupButton focusButton = null; private string currentPath; private int currentFocusIndex; public PopupButtonPanel () { SuspendLayout (); BackColor = Color.FromArgb (128, 128, 128); Size = new Size (85, 336); InternalBorderStyle = BorderStyle.Fixed3D; recentlyusedButton = new PopupButton (); desktopButton = new PopupButton (); personalButton = new PopupButton (); mycomputerButton = new PopupButton (); networkButton = new PopupButton (); recentlyusedButton.Size = new Size (81, 64); recentlyusedButton.Image = ThemeEngine.Current.Images (UIIcon.PlacesRecentDocuments, 32); recentlyusedButton.BackColor = BackColor; recentlyusedButton.ForeColor = Color.Black; recentlyusedButton.Location = new Point (2, 2); recentlyusedButton.Text = "Recently\nused"; recentlyusedButton.Click += new EventHandler (OnClickButton); desktopButton.Image = ThemeEngine.Current.Images (UIIcon.PlacesDesktop, 32); desktopButton.BackColor = BackColor; desktopButton.ForeColor = Color.Black; desktopButton.Size = new Size (81, 64); desktopButton.Location = new Point (2, 66); desktopButton.Text = "Desktop"; desktopButton.Click += new EventHandler (OnClickButton); personalButton.Image = ThemeEngine.Current.Images (UIIcon.PlacesPersonal, 32); personalButton.BackColor = BackColor; personalButton.ForeColor = Color.Black; personalButton.Size = new Size (81, 64); personalButton.Location = new Point (2, 130); personalButton.Text = "Personal"; personalButton.Click += new EventHandler (OnClickButton); mycomputerButton.Image = ThemeEngine.Current.Images (UIIcon.PlacesMyComputer, 32); mycomputerButton.BackColor = BackColor; mycomputerButton.ForeColor = Color.Black; mycomputerButton.Size = new Size (81, 64); mycomputerButton.Location = new Point (2, 194); mycomputerButton.Text = "My Computer"; mycomputerButton.Click += new EventHandler (OnClickButton); networkButton.Image = ThemeEngine.Current.Images (UIIcon.PlacesMyNetwork, 32); networkButton.BackColor = BackColor; networkButton.ForeColor = Color.Black; networkButton.Size = new Size (81, 64); networkButton.Location = new Point (2, 258); networkButton.Text = "My Network"; networkButton.Click += new EventHandler (OnClickButton); Controls.Add (recentlyusedButton); Controls.Add (desktopButton); Controls.Add (personalButton); Controls.Add (mycomputerButton); Controls.Add (networkButton); ResumeLayout (false); KeyDown += new KeyEventHandler (Key_Down); SetStyle (ControlStyles.StandardClick, false); } void OnClickButton (object sender, EventArgs e) { if (lastPopupButton != null && lastPopupButton != sender as PopupButton) lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal; lastPopupButton = sender as PopupButton; if (sender == recentlyusedButton) { currentPath = MWFVFS.RecentlyUsedPrefix; } else if (sender == desktopButton) { currentPath = MWFVFS.DesktopPrefix; } else if (sender == personalButton) { currentPath = MWFVFS.PersonalPrefix; } else if (sender == mycomputerButton) { currentPath = MWFVFS.MyComputerPrefix; } else if (sender == networkButton) { currentPath = MWFVFS.MyNetworkPrefix; } EventHandler eh = (EventHandler)(Events [PDirectoryChangedEvent]); if (eh != null) eh (this, EventArgs.Empty); } static object UIAFocusedItemChangedEvent = new object (); internal event EventHandler UIAFocusedItemChanged { add { Events.AddHandler (UIAFocusedItemChangedEvent, value); } remove { Events.RemoveHandler (UIAFocusedItemChangedEvent, value); } } internal void OnUIAFocusedItemChanged () { EventHandler eh = (EventHandler) Events [UIAFocusedItemChangedEvent]; if (eh != null) eh (this, EventArgs.Empty); } internal PopupButton UIAFocusButton { get { return focusButton; } } public string CurrentFolder { set { string currentPath = value; if (currentPath == MWFVFS.RecentlyUsedPrefix) { if (lastPopupButton != recentlyusedButton) { if (lastPopupButton != null) lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal; recentlyusedButton.ButtonState = PopupButton.PopupButtonState.Down; lastPopupButton = recentlyusedButton; } } else if (currentPath == MWFVFS.DesktopPrefix) { if (lastPopupButton != desktopButton) { if (lastPopupButton != null) lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal; desktopButton.ButtonState = PopupButton.PopupButtonState.Down; lastPopupButton = desktopButton; } } else if (currentPath == MWFVFS.PersonalPrefix) { if (lastPopupButton != personalButton) { if (lastPopupButton != null) lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal; personalButton.ButtonState = PopupButton.PopupButtonState.Down; lastPopupButton = personalButton; } } else if (currentPath == MWFVFS.MyComputerPrefix) { if (lastPopupButton != mycomputerButton) { if (lastPopupButton != null) lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal; mycomputerButton.ButtonState = PopupButton.PopupButtonState.Down; lastPopupButton = mycomputerButton; } } else if (currentPath == MWFVFS.MyNetworkPrefix) { if (lastPopupButton != networkButton) { if (lastPopupButton != null) lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal; networkButton.ButtonState = PopupButton.PopupButtonState.Down; lastPopupButton = networkButton; } } else { if (lastPopupButton != null) { lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal; lastPopupButton = null; } } } get { return currentPath; } } protected override void OnGotFocus (EventArgs e) { if (lastPopupButton != recentlyusedButton) { recentlyusedButton.ButtonState = PopupButton.PopupButtonState.Up; SetFocusButton (recentlyusedButton); } currentFocusIndex = 0; base.OnGotFocus (e); } protected override void OnLostFocus (EventArgs e) { if (focusButton != null && focusButton.ButtonState != PopupButton.PopupButtonState.Down) focusButton.ButtonState = PopupButton.PopupButtonState.Normal; base.OnLostFocus (e); } protected override bool IsInputKey (Keys key) { switch (key) { case Keys.Up: case Keys.Down: case Keys.Right: case Keys.Left: case Keys.Enter: return true; } return base.IsInputKey (key); } private void Key_Down (object sender, KeyEventArgs e) { bool update_focus = false; if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Up) { currentFocusIndex --; if (currentFocusIndex < 0) currentFocusIndex = Controls.Count - 1; update_focus = true; } else if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Right) { currentFocusIndex++; if (currentFocusIndex == Controls.Count) currentFocusIndex = 0; update_focus = true; } else if (e.KeyCode == Keys.Enter) { focusButton.ButtonState = PopupButton.PopupButtonState.Down; OnClickButton (focusButton, EventArgs.Empty); } if (update_focus) { PopupButton newfocusButton = Controls [currentFocusIndex] as PopupButton; if (focusButton != null && focusButton.ButtonState != PopupButton.PopupButtonState.Down) focusButton.ButtonState = PopupButton.PopupButtonState.Normal; if (newfocusButton.ButtonState != PopupButton.PopupButtonState.Down) newfocusButton.ButtonState = PopupButton.PopupButtonState.Up; SetFocusButton (newfocusButton); } e.Handled = true; } static object PDirectoryChangedEvent = new object (); public event EventHandler DirectoryChanged { add { Events.AddHandler (PDirectoryChangedEvent, value); } remove { Events.RemoveHandler (PDirectoryChangedEvent, value); } } internal void SetFocusButton (PopupButton button) { if (button == focusButton) return; focusButton = button; OnUIAFocusedItemChanged (); } } #endregion #region DirComboBox internal class DirComboBox : ComboBox, IUpdateFolder { #region DirComboBoxItem internal class DirComboBoxItem { private int imageIndex; private string name; private string path; private int xPos; private ImageList imageList; public DirComboBoxItem (ImageList imageList, int imageIndex, string name, string path, int xPos) { this.imageList = imageList; this.imageIndex = imageIndex; this.name = name; this.path = path; this.xPos = xPos; } public int ImageIndex { get { return imageIndex; } } public string Name { get { return name; } } public string Path { get { return path; } } public int XPos { get { return xPos; } } public ImageList ImageList { set { imageList = value; } get { return imageList; } } #region UIA Framework Members public override string ToString () { return name; } #endregion } #endregion private ImageList imageList = new ImageList(); private string currentPath; private Stack folderStack = new Stack(); private static readonly int indent = 6; private DirComboBoxItem recentlyUsedDirComboboxItem; private DirComboBoxItem desktopDirComboboxItem; private DirComboBoxItem personalDirComboboxItem; private DirComboBoxItem myComputerDirComboboxItem; private DirComboBoxItem networkDirComboboxItem; private ArrayList myComputerItems = new ArrayList (); private DirComboBoxItem mainParentDirComboBoxItem = null; private DirComboBoxItem real_parent = null; private MWFVFS vfs; public DirComboBox (MWFVFS vfs) { this.vfs = vfs; SuspendLayout (); DrawMode = DrawMode.OwnerDrawFixed; imageList.ColorDepth = ColorDepth.Depth32Bit; imageList.ImageSize = new Size (16, 16); imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesRecentDocuments, 16)); imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesDesktop, 16)); imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesPersonal, 16)); imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesMyComputer, 16)); imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesMyNetwork, 16)); imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.NormalFolder, 16)); imageList.TransparentColor = Color.Transparent; recentlyUsedDirComboboxItem = new DirComboBoxItem (imageList, 0, "Recently used", MWFVFS.RecentlyUsedPrefix, 0); desktopDirComboboxItem = new DirComboBoxItem (imageList, 1, "Desktop", MWFVFS.DesktopPrefix, 0); personalDirComboboxItem = new DirComboBoxItem (imageList, 2, "Personal folder", MWFVFS.PersonalPrefix, indent); myComputerDirComboboxItem = new DirComboBoxItem (imageList, 3, "My Computer", MWFVFS.MyComputerPrefix, indent); networkDirComboboxItem = new DirComboBoxItem (imageList, 4, "My Network", MWFVFS.MyNetworkPrefix, indent); ArrayList al = this.vfs.GetMyComputerContent (); foreach (FSEntry fsEntry in al) { myComputerItems.Add (new DirComboBoxItem (MimeIconEngine.LargeIcons, fsEntry.IconIndex, fsEntry.Name, fsEntry.FullName, indent * 2)); } al.Clear (); al = null; mainParentDirComboBoxItem = myComputerDirComboboxItem; ResumeLayout (false); } public string CurrentFolder { set { currentPath = value; CreateComboList (); } get { return currentPath; } } private void CreateComboList () { real_parent = null; DirComboBoxItem selection = null; if (currentPath == MWFVFS.RecentlyUsedPrefix) { mainParentDirComboBoxItem = recentlyUsedDirComboboxItem; selection = recentlyUsedDirComboboxItem; } else if (currentPath == MWFVFS.DesktopPrefix) { selection = desktopDirComboboxItem; mainParentDirComboBoxItem = desktopDirComboboxItem; } else if (currentPath == MWFVFS.PersonalPrefix) { selection = personalDirComboboxItem; mainParentDirComboBoxItem = personalDirComboboxItem; } else if (currentPath == MWFVFS.MyComputerPrefix) { selection = myComputerDirComboboxItem; mainParentDirComboBoxItem = myComputerDirComboboxItem; } else if (currentPath == MWFVFS.MyNetworkPrefix) { selection = networkDirComboboxItem; mainParentDirComboBoxItem = networkDirComboboxItem; } else { foreach (DirComboBoxItem dci in myComputerItems) { if (dci.Path == currentPath) { mainParentDirComboBoxItem = selection = dci; break; } } } BeginUpdate (); Items.Clear (); Items.Add (recentlyUsedDirComboboxItem); Items.Add (desktopDirComboboxItem); Items.Add (personalDirComboboxItem); Items.Add (myComputerDirComboboxItem); Items.AddRange (myComputerItems); Items.Add (networkDirComboboxItem); if (selection == null) real_parent = CreateFolderStack (); if (real_parent != null) { int local_indent = 0; if (real_parent == desktopDirComboboxItem) local_indent = 1; else if (real_parent == personalDirComboboxItem || real_parent == networkDirComboboxItem) local_indent = 2; else local_indent = 3; selection = AppendToParent (local_indent, real_parent); } EndUpdate (); if (selection != null) SelectedItem = selection; } private DirComboBoxItem CreateFolderStack () { folderStack.Clear (); DirectoryInfo di = new DirectoryInfo (currentPath); folderStack.Push (di); bool ignoreCase = !XplatUI.RunningOnUnix; while (di.Parent != null) { di = di.Parent; if (mainParentDirComboBoxItem != personalDirComboboxItem && string.Compare (di.FullName, ThemeEngine.Current.Places (UIIcon.PlacesDesktop), ignoreCase) == 0) return desktopDirComboboxItem; else if (mainParentDirComboBoxItem == personalDirComboboxItem) { if (string.Compare (di.FullName, ThemeEngine.Current.Places (UIIcon.PlacesPersonal), ignoreCase) == 0) return personalDirComboboxItem; } else foreach (DirComboBoxItem dci in myComputerItems) { if (string.Compare (dci.Path, di.FullName, ignoreCase) == 0) { return dci; } } folderStack.Push (di); } return null; } private DirComboBoxItem AppendToParent (int nr_indents, DirComboBoxItem parentDirComboBoxItem) { DirComboBoxItem selection = null; int index = Items.IndexOf (parentDirComboBoxItem) + 1; int xPos = indent * nr_indents; while (folderStack.Count != 0) { DirectoryInfo dii = folderStack.Pop () as DirectoryInfo; DirComboBoxItem dci = new DirComboBoxItem (imageList, 5, dii.Name, dii.FullName, xPos); Items.Insert (index, dci); index++; selection = dci; xPos += indent; } return selection; } protected override void OnDrawItem (DrawItemEventArgs e) { if (e.Index == -1) return; DirComboBoxItem dcbi = Items [e.Index] as DirComboBoxItem; Bitmap bmp = new Bitmap (e.Bounds.Width, e.Bounds.Height, e.Graphics); Graphics gr = Graphics.FromImage (bmp); Color backColor = e.BackColor; Color foreColor = e.ForeColor; int xPos = dcbi.XPos; if ((e.State & DrawItemState.ComboBoxEdit) != 0) xPos = 0; gr.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (backColor), new Rectangle (0, 0, bmp.Width, bmp.Height)); if ((e.State & DrawItemState.Selected) == DrawItemState.Selected && (!DroppedDown || (e.State & DrawItemState.ComboBoxEdit) != DrawItemState.ComboBoxEdit)) { foreColor = ThemeEngine.Current.ColorHighlightText; int w = (int) gr.MeasureString (dcbi.Name, e.Font).Width; gr.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorHighlight), new Rectangle (xPos + 23, 1, w + 3, e.Bounds.Height - 2)); if ((e.State & DrawItemState.Focus) == DrawItemState.Focus) { ControlPaint.DrawFocusRectangle (gr, new Rectangle (xPos + 22, 0, w + 5, e.Bounds.Height), foreColor, ThemeEngine.Current.ColorHighlight); } } gr.DrawString (dcbi.Name, e.Font , ThemeEngine.Current.ResPool.GetSolidBrush (foreColor), new Point (24 + xPos, (bmp.Height - e.Font.Height) / 2)); gr.DrawImage (dcbi.ImageList.Images [dcbi.ImageIndex], new Rectangle (new Point (xPos + 2, 0), new Size (16, 16))); e.Graphics.DrawImage (bmp, e.Bounds.X, e.Bounds.Y); gr.Dispose (); bmp.Dispose (); } protected override void OnSelectedIndexChanged (EventArgs e) { if (Items.Count > 0) { DirComboBoxItem dcbi = Items [SelectedIndex] as DirComboBoxItem; currentPath = dcbi.Path; } } protected override void OnSelectionChangeCommitted (EventArgs e) { EventHandler eh = (EventHandler)(Events [CDirectoryChangedEvent]); if (eh != null) eh (this, EventArgs.Empty); } static object CDirectoryChangedEvent = new object (); public event EventHandler DirectoryChanged { add { Events.AddHandler (CDirectoryChangedEvent, value); } remove { Events.RemoveHandler (CDirectoryChangedEvent, value); } } } #endregion #region FilterStruct internal struct FilterStruct { public string filterName; public StringCollection filters; public FilterStruct (string filterName, string filter) { this.filterName = filterName; filters = new StringCollection (); SplitFilters (filter); } private void SplitFilters (string filter) { string[] split = filter.Split (new char [] {';'}); foreach (string s in split) { filters.Add (s.Trim ()); } } } #endregion #region FileFilter internal class FileFilter { private ArrayList filterArrayList = new ArrayList(); private string filter; public FileFilter () {} public FileFilter (string filter) : base () { this.filter = filter; SplitFilter (); } public static bool CheckFilter (string val) { if (val.Length == 0) return true; string[] filters = val.Split (new char [] {'|'}); if ((filters.Length % 2) != 0) return false; return true; } public ArrayList FilterArrayList { set { filterArrayList = value; } get { return filterArrayList; } } public string Filter { set { filter = value; SplitFilter (); } get { return filter; } } private void SplitFilter () { filterArrayList.Clear (); if (filter.Length == 0) return; string[] filters = filter.Split (new char [] {'|'}); for (int i = 0; i < filters.Length; i += 2) { FilterStruct filterStruct = new FilterStruct (filters [i], filters [i + 1]); filterArrayList.Add (filterStruct); } } } #endregion #region MWFFileView internal class MWFFileView : ListView { private ArrayList filterArrayList; private bool showHiddenFiles = false; private string selectedFilesString; private int filterIndex = 1; private ToolTip toolTip; private int oldItemIndexForToolTip = -1; private ContextMenu contextMenu; private MenuItem menuItemView; private MenuItem menuItemNew; private MenuItem smallIconMenutItem; private MenuItem tilesMenutItem; private MenuItem largeIconMenutItem; private MenuItem listMenutItem; private MenuItem detailsMenutItem; private MenuItem newFolderMenuItem; private MenuItem showHiddenFilesMenuItem; private int previousCheckedMenuItemIndex; private ArrayList viewMenuItemClones = new ArrayList (); private FSEntry currentFSEntry = null; private string currentFolder; private string currentRealFolder; private FSEntry currentFolderFSEntry; // store DirectoryInfo for a back button for example private Stack directoryStack = new Stack(); // list of controls(components to enable or disable depending on current directoryStack.Count private ArrayList dirStackControlsOrComponents = new ArrayList (); private ToolBarButton folderUpToolBarButton; private ArrayList registered_senders = new ArrayList (); private bool should_push = true; private MWFVFS vfs; private View old_view; private int old_menuitem_index; private bool do_update_view = false; private ColumnHeader [] columns; public MWFFileView (MWFVFS vfs) { this.vfs = vfs; this.vfs.RegisterUpdateDelegate (new MWFVFS.UpdateDelegate (RealFileViewUpdate), this); SuspendLayout (); contextMenu = new ContextMenu (); toolTip = new ToolTip (); toolTip.InitialDelay = 300; toolTip.ReshowDelay = 0; // contextMenu // View menu item menuItemView = new MenuItem ("View"); smallIconMenutItem = new MenuItem ("Small Icon", new EventHandler (OnClickViewMenuSubItem)); smallIconMenutItem.RadioCheck = true; menuItemView.MenuItems.Add (smallIconMenutItem); tilesMenutItem = new MenuItem ("Tiles", new EventHandler (OnClickViewMenuSubItem)); tilesMenutItem.RadioCheck = true; menuItemView.MenuItems.Add (tilesMenutItem); largeIconMenutItem = new MenuItem ("Large Icon", new EventHandler (OnClickViewMenuSubItem)); largeIconMenutItem.RadioCheck = true; menuItemView.MenuItems.Add (largeIconMenutItem); listMenutItem = new MenuItem ("List", new EventHandler (OnClickViewMenuSubItem)); listMenutItem.RadioCheck = true; listMenutItem.Checked = true; menuItemView.MenuItems.Add (listMenutItem); previousCheckedMenuItemIndex = listMenutItem.Index; detailsMenutItem = new MenuItem ("Details", new EventHandler (OnClickViewMenuSubItem)); detailsMenutItem.RadioCheck = true; menuItemView.MenuItems.Add (detailsMenutItem); contextMenu.MenuItems.Add (menuItemView); contextMenu.MenuItems.Add (new MenuItem ("-")); // New menu item menuItemNew = new MenuItem ("New"); newFolderMenuItem = new MenuItem ("New Folder", new EventHandler (OnClickNewFolderMenuItem)); menuItemNew.MenuItems.Add (newFolderMenuItem); contextMenu.MenuItems.Add (menuItemNew); contextMenu.MenuItems.Add (new MenuItem ("-")); // Show hidden files menu item showHiddenFilesMenuItem = new MenuItem ("Show hidden files", new EventHandler (OnClickContextMenu)); showHiddenFilesMenuItem.Checked = showHiddenFiles; contextMenu.MenuItems.Add (showHiddenFilesMenuItem); LabelWrap = true; SmallImageList = MimeIconEngine.SmallIcons; LargeImageList = MimeIconEngine.LargeIcons; View = old_view = View.List; LabelEdit = true; ContextMenu = contextMenu; // Create columns, but only add them when view changes to Details columns = new ColumnHeader [4]; columns [0] = CreateColumnHeader (" Name", 170, HorizontalAlignment.Left); columns [1] = CreateColumnHeader ("Size ", 80, HorizontalAlignment.Right); columns [2] = CreateColumnHeader (" Type", 100, HorizontalAlignment.Left); columns [3] = CreateColumnHeader (" Last Access", 150, HorizontalAlignment.Left); AllowColumnReorder = true; ResumeLayout (false); KeyDown += new KeyEventHandler (MWF_KeyDown); } ColumnHeader CreateColumnHeader (string text, int width, HorizontalAlignment alignment) { ColumnHeader col = new ColumnHeader (); col.Text = text; col.Width = width; col.TextAlign = alignment; return col; } public string CurrentFolder { get { return currentFolder; } set { currentFolder = value; } } public string CurrentRealFolder { get { return currentRealFolder; } } public FSEntry CurrentFSEntry { get { return currentFSEntry; } } public MenuItem[] ViewMenuItems { get { MenuItem[] menuItemClones = new MenuItem [] { smallIconMenutItem.CloneMenu (), tilesMenutItem.CloneMenu (), largeIconMenutItem.CloneMenu (), listMenutItem.CloneMenu (), detailsMenutItem.CloneMenu () }; viewMenuItemClones.Add (menuItemClones); return menuItemClones; } } public ArrayList FilterArrayList { set { filterArrayList = value; } get { return filterArrayList; } } public bool ShowHiddenFiles { set { showHiddenFiles = value; } get { return showHiddenFiles; } } public int FilterIndex { set { filterIndex = value; if (Visible) UpdateFileView (); } get { return filterIndex; } } public string SelectedFilesString { set { selectedFilesString = value; } get { return selectedFilesString; } } public void PushDir () { if (currentFolder != null) directoryStack.Push (currentFolder); EnableOrDisableDirstackObjects (); } public void PopDir () { PopDir (null); } public void PopDir (string filter) { if (directoryStack.Count == 0) return; string new_folder = directoryStack.Pop () as string; EnableOrDisableDirstackObjects (); should_push = false; ChangeDirectory (null, new_folder, filter); } public void RegisterSender (IUpdateFolder iud) { registered_senders.Add (iud); } public void CreateNewFolder () { if (currentFolder == MWFVFS.MyComputerPrefix || currentFolder == MWFVFS.RecentlyUsedPrefix) return; FSEntry fsEntry = new FSEntry (); fsEntry.Attributes = FileAttributes.Directory; fsEntry.FileType = FSEntry.FSEntryType.Directory; fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("inode/directory"); fsEntry.LastAccessTime = DateTime.Now; // FIXME: when ListView.LabelEdit is available use it // listViewItem.BeginEdit(); TextEntryDialog ted = new TextEntryDialog (); ted.IconPictureBoxImage = MimeIconEngine.LargeIcons.Images.GetImage (fsEntry.IconIndex); string folder = String.Empty; if (currentFolderFSEntry.RealName != null) folder = currentFolderFSEntry.RealName; else folder = currentFolder; string tmp_filename = "New Folder"; if (Directory.Exists (Path.Combine (folder, tmp_filename))) { int i = 1; if (XplatUI.RunningOnUnix) { tmp_filename = tmp_filename + "-" + i; } else { tmp_filename = tmp_filename + " (" + i + ")"; } while (Directory.Exists (Path.Combine (folder, tmp_filename))) { i++; if (XplatUI.RunningOnUnix) { tmp_filename = "New Folder" + "-" + i; } else { tmp_filename = "New Folder" + " (" + i + ")"; } } } ted.FileName = tmp_filename; if (ted.ShowDialog () == DialogResult.OK) { string new_folder = Path.Combine (folder, ted.FileName); if (vfs.CreateFolder (new_folder)) { fsEntry.FullName = new_folder; fsEntry.Name = ted.FileName; FileViewListViewItem listViewItem = new FileViewListViewItem (fsEntry); BeginUpdate (); Items.Add (listViewItem); EndUpdate (); listViewItem.EnsureVisible (); } } } public void SetSelectedIndexTo (string fname) { foreach (FileViewListViewItem item in Items) { if (item.Text == fname) { BeginUpdate (); SelectedItems.Clear (); item.Selected = true; EndUpdate (); break; } } } public void OneDirUp () { OneDirUp (null); } public void OneDirUp (string filter) { string parent_folder = vfs.GetParent (); if (parent_folder != null) ChangeDirectory (null, parent_folder, filter); } public void ChangeDirectory (object sender, string folder) { ChangeDirectory (sender, folder, null); } public void ChangeDirectory (object sender, string folder, string filter) { if (folder == MWFVFS.DesktopPrefix || folder == MWFVFS.RecentlyUsedPrefix) folderUpToolBarButton.Enabled = false; else folderUpToolBarButton.Enabled = true; foreach (IUpdateFolder iuf in registered_senders) { iuf.CurrentFolder = folder; } if (should_push) PushDir (); else should_push = true; currentFolderFSEntry = vfs.ChangeDirectory (folder); currentFolder = folder; if (currentFolder.IndexOf ("://") != -1) currentRealFolder = currentFolderFSEntry.RealName; else currentRealFolder = currentFolder; BeginUpdate (); Items.Clear (); SelectedItems.Clear (); if (folder == MWFVFS.RecentlyUsedPrefix) { old_view = View; View = View.Details; old_menuitem_index = previousCheckedMenuItemIndex; UpdateMenuItems (detailsMenutItem); do_update_view = true; } else if (View != old_view && do_update_view) { UpdateMenuItems (menuItemView.MenuItems [old_menuitem_index]); View = old_view; do_update_view = false; } EndUpdate (); try { UpdateFileView (filter); } catch (Exception e) { if (should_push) PopDir (); MessageBox.Show (e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public void UpdateFileView () { UpdateFileView (null); } public void UpdateFileView (string custom_filter) { if (custom_filter != null) { StringCollection custom_filters = new StringCollection (); custom_filters.Add (custom_filter); vfs.GetFolderContent (custom_filters); } else if (filterArrayList != null && filterArrayList.Count != 0) { FilterStruct fs = (FilterStruct)filterArrayList [filterIndex - 1]; vfs.GetFolderContent (fs.filters); } else vfs.GetFolderContent (); } public void RealFileViewUpdate (ArrayList directoriesArrayList, ArrayList fileArrayList) { BeginUpdate (); Items.Clear (); SelectedItems.Clear (); foreach (FSEntry directoryFSEntry in directoriesArrayList) { if (!ShowHiddenFiles) if (directoryFSEntry.Name.StartsWith (".") || (directoryFSEntry.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) continue; FileViewListViewItem listViewItem = new FileViewListViewItem (directoryFSEntry); Items.Add (listViewItem); } StringCollection collection = new StringCollection (); foreach (FSEntry fsEntry in fileArrayList) { // remove duplicates. that can happen when you read recently used files for example if (collection.Contains (fsEntry.Name)) { string fileName = fsEntry.Name; if (collection.Contains (fileName)) { int i = 1; while (collection.Contains (fileName + "(" + i + ")")) { i++; } fileName = fileName + "(" + i + ")"; } fsEntry.Name = fileName; } collection.Add (fsEntry.Name); DoOneFSEntry (fsEntry); } EndUpdate (); collection.Clear (); collection = null; directoriesArrayList.Clear (); fileArrayList.Clear (); } public void AddControlToEnableDisableByDirStack (object control) { dirStackControlsOrComponents.Add (control); } public void SetFolderUpToolBarButton (ToolBarButton tb) { folderUpToolBarButton = tb; } public void WriteRecentlyUsed (string fullfilename) { vfs.WriteRecentlyUsedFiles (fullfilename); } private void EnableOrDisableDirstackObjects () { foreach (object o in dirStackControlsOrComponents) { if (o is Control) { Control c = o as Control; c.Enabled = (directoryStack.Count > 1); } else if (o is ToolBarButton) { ToolBarButton t = o as ToolBarButton; t.Enabled = (directoryStack.Count > 0); } } } private void DoOneFSEntry (FSEntry fsEntry) { if (!ShowHiddenFiles) if (fsEntry.Name.StartsWith (".") || (fsEntry.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) return; FileViewListViewItem listViewItem = new FileViewListViewItem (fsEntry); Items.Add (listViewItem); } private void MWF_KeyDown (object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Back) { OneDirUp (); } else if (e.Control && e.KeyCode == Keys.A && MultiSelect) { foreach (ListViewItem lvi in Items) lvi.Selected = true; } } #region UIA Framework Members internal void PerformClick () { OnClick (EventArgs.Empty); } internal void PerformDoubleClick () { OnDoubleClick (EventArgs.Empty); } #endregion protected override void OnClick (EventArgs e) { if (!MultiSelect) { if (SelectedItems.Count > 0) { FileViewListViewItem listViewItem = SelectedItems [0] as FileViewListViewItem; FSEntry fsEntry = listViewItem.FSEntry; if (fsEntry.FileType == FSEntry.FSEntryType.File) { currentFSEntry = fsEntry; EventHandler eh = (EventHandler)(Events [MSelectedFileChangedEvent]); if (eh != null) eh (this, EventArgs.Empty); } } } base.OnClick (e); } protected override void OnDoubleClick (EventArgs e) { if (SelectedItems.Count > 0) { FileViewListViewItem listViewItem = SelectedItems [0] as FileViewListViewItem; FSEntry fsEntry = listViewItem.FSEntry; if ((fsEntry.Attributes & FileAttributes.Directory) == FileAttributes.Directory) { ChangeDirectory (null, fsEntry.FullName); EventHandler eh = (EventHandler)(Events [MDirectoryChangedEvent]); if (eh != null) eh (this, EventArgs.Empty); } else { currentFSEntry = fsEntry; EventHandler eh = (EventHandler)(Events [MSelectedFileChangedEvent]); if (eh != null) eh (this, EventArgs.Empty); eh = (EventHandler)(Events [MForceDialogEndEvent]); if (eh != null) eh (this, EventArgs.Empty); return; } } base.OnDoubleClick (e); } protected override void OnSelectedIndexChanged (EventArgs e) { if (SelectedItems.Count > 0) { selectedFilesString = String.Empty; if (SelectedItems.Count == 1) { FileViewListViewItem listViewItem = SelectedItems [0] as FileViewListViewItem; FSEntry fsEntry = listViewItem.FSEntry; if ((fsEntry.Attributes & FileAttributes.Directory) != FileAttributes.Directory) selectedFilesString = SelectedItems [0].Text; } else { foreach (FileViewListViewItem lvi in SelectedItems) { FSEntry fsEntry = lvi.FSEntry; if ((fsEntry.Attributes & FileAttributes.Directory) != FileAttributes.Directory) selectedFilesString = selectedFilesString + "\"" + lvi.Text + "\" "; } } EventHandler eh = (EventHandler)(Events [MSelectedFilesChangedEvent]); if (eh != null) eh (this, EventArgs.Empty); } base.OnSelectedIndexChanged (e); } protected override void OnMouseMove (MouseEventArgs e) { FileViewListViewItem item = GetItemAt (e.X, e.Y) as FileViewListViewItem; if (item != null) { int currentItemIndex = item.Index; if (currentItemIndex != oldItemIndexForToolTip) { oldItemIndexForToolTip = currentItemIndex; if (toolTip != null && toolTip.Active) toolTip.Active = false; FSEntry fsEntry = item.FSEntry; string output = String.Empty; if (fsEntry.FileType == FSEntry.FSEntryType.Directory) output = "Directory: " + fsEntry.FullName; else if (fsEntry.FileType == FSEntry.FSEntryType.Device) output = "Device: "+ fsEntry.FullName; else if (fsEntry.FileType == FSEntry.FSEntryType.Network) output = "Network: " + fsEntry.FullName; else output = "File: " + fsEntry.FullName; toolTip.SetToolTip (this, output); toolTip.Active = true; } } else toolTip.Active = false; base.OnMouseMove (e); } void OnClickContextMenu (object sender, EventArgs e) { MenuItem senderMenuItem = sender as MenuItem; if (senderMenuItem == showHiddenFilesMenuItem) { senderMenuItem.Checked = !senderMenuItem.Checked; showHiddenFiles = senderMenuItem.Checked; UpdateFileView (); } } void OnClickViewMenuSubItem (object sender, EventArgs e) { MenuItem senderMenuItem = (MenuItem)sender; UpdateMenuItems (senderMenuItem); // update me - call BeginUpdate/EndUpdate to avoid flicker when columns change BeginUpdate (); switch (senderMenuItem.Index) { case 0: View = View.SmallIcon; break; case 1: View = View.Tile; break; case 2: View = View.LargeIcon; break; case 3: View = View.List; break; case 4: View = View.Details; break; default: break; } if (View == View.Details) Columns.AddRange (columns); else { ListViewItemSorter = null; Columns.Clear (); } EndUpdate (); } protected override void OnBeforeLabelEdit (LabelEditEventArgs e) { FileViewListViewItem listViewItem = SelectedItems [0] as FileViewListViewItem; FSEntry fsEntry = listViewItem.FSEntry; // only allow editing of files or directories if (fsEntry.FileType != FSEntry.FSEntryType.Directory && fsEntry.FileType != FSEntry.FSEntryType.File) e.CancelEdit = true; base.OnBeforeLabelEdit (e); } protected override void OnAfterLabelEdit (LabelEditEventArgs e) { base.OnAfterLabelEdit (e); // no changes were made if (e.Label == null || Items [e.Item].Text == e.Label) return; FileViewListViewItem listViewItem = SelectedItems [0] as FileViewListViewItem; FSEntry fsEntry = listViewItem.FSEntry; string folder = (currentFolderFSEntry.RealName != null) ? currentFolderFSEntry.RealName : currentFolder; switch (fsEntry.FileType) { case FSEntry.FSEntryType.Directory: string sourceDir = (fsEntry.RealName != null) ? fsEntry.RealName : fsEntry.FullName; string destDir = Path.Combine (folder, e.Label); if (!vfs.MoveFolder (sourceDir, destDir)) { e.CancelEdit = true; } else { if (fsEntry.RealName != null) fsEntry.RealName = destDir; else fsEntry.FullName = destDir; } break; case FSEntry.FSEntryType.File: string sourceFile = (fsEntry.RealName != null) ? fsEntry.RealName : fsEntry.FullName; string destFile = Path.Combine (folder, e.Label); if (!vfs.MoveFile (sourceFile, destFile)) { e.CancelEdit = true; } else { if (fsEntry.RealName != null) fsEntry.RealName = destFile; else fsEntry.FullName = destFile; } break; } } private void UpdateMenuItems (MenuItem senderMenuItem) { menuItemView.MenuItems [previousCheckedMenuItemIndex].Checked = false; menuItemView.MenuItems [senderMenuItem.Index].Checked = true; foreach (MenuItem[] items in viewMenuItemClones) { items [previousCheckedMenuItemIndex].Checked = false; items [senderMenuItem.Index].Checked = true; } previousCheckedMenuItemIndex = senderMenuItem.Index; } void OnClickNewFolderMenuItem (object sender, EventArgs e) { CreateNewFolder (); } static object MSelectedFileChangedEvent = new object (); static object MSelectedFilesChangedEvent = new object (); static object MDirectoryChangedEvent = new object (); static object MForceDialogEndEvent = new object (); public event EventHandler SelectedFileChanged { add { Events.AddHandler (MSelectedFileChangedEvent, value); } remove { Events.RemoveHandler (MSelectedFileChangedEvent, value); } } public event EventHandler SelectedFilesChanged { add { Events.AddHandler (MSelectedFilesChangedEvent, value); } remove { Events.RemoveHandler (MSelectedFilesChangedEvent, value); } } public event EventHandler DirectoryChanged { add { Events.AddHandler (MDirectoryChangedEvent, value); } remove { Events.RemoveHandler (MDirectoryChangedEvent, value); } } public event EventHandler ForceDialogEnd { add { Events.AddHandler (MForceDialogEndEvent, value); } remove { Events.RemoveHandler (MForceDialogEndEvent, value); } } } #endregion #region FileListViewItem internal class FileViewListViewItem : ListViewItem { private FSEntry fsEntry; public FileViewListViewItem (FSEntry fsEntry) { this.fsEntry = fsEntry; ImageIndex = fsEntry.IconIndex; Text = fsEntry.Name; switch (fsEntry.FileType) { case FSEntry.FSEntryType.Directory: SubItems.Add (String.Empty); SubItems.Add ("Directory"); SubItems.Add (fsEntry.LastAccessTime.ToShortDateString () + " " + fsEntry.LastAccessTime.ToShortTimeString ()); break; case FSEntry.FSEntryType.File: long fileLen = 1; try { if (fsEntry.FileSize > 1024) fileLen = fsEntry.FileSize / 1024; } catch (Exception) { fileLen = 1; } SubItems.Add (fileLen.ToString () + " KB"); SubItems.Add ("File"); SubItems.Add (fsEntry.LastAccessTime.ToShortDateString () + " " + fsEntry.LastAccessTime.ToShortTimeString ()); break; case FSEntry.FSEntryType.Device: SubItems.Add (String.Empty); SubItems.Add ("Device"); SubItems.Add (fsEntry.LastAccessTime.ToShortDateString () + " " + fsEntry.LastAccessTime.ToShortTimeString ()); break; case FSEntry.FSEntryType.RemovableDevice: SubItems.Add (String.Empty); SubItems.Add ("RemovableDevice"); SubItems.Add (fsEntry.LastAccessTime.ToShortDateString () + " " + fsEntry.LastAccessTime.ToShortTimeString ()); break; default: break; } } public FSEntry FSEntry { set { fsEntry = value; } get { return fsEntry; } } } #endregion #region MwfFileViewItemComparer class MwfFileViewItemComparer : IComparer { int column_index; bool asc; public MwfFileViewItemComparer (bool asc) { this.asc = asc; } public int ColumnIndex { get { return column_index; } set { column_index = value; } } public bool Ascendent { get { return asc; } set { asc = value; } } public int Compare (object a, object b) { ListViewItem item_a = (ListViewItem)a; ListViewItem item_b = (ListViewItem)b; int retval; if (asc) retval = String.Compare (item_a.SubItems [column_index].Text, item_b.SubItems [column_index].Text); else retval = String.Compare (item_b.SubItems [column_index].Text, item_a.SubItems [column_index].Text); return retval; } } #endregion #region IUpdateFolder internal interface IUpdateFolder { string CurrentFolder {get; set;} } #endregion #region TextEntryDialog // FIXME: When ListView.LabelEdit is implemented remove me internal class TextEntryDialog : Form { private Label label1; private Button okButton; private TextBox newNameTextBox; private PictureBox iconPictureBox; private Button cancelButton; private GroupBox groupBox1; public TextEntryDialog () { groupBox1 = new GroupBox (); cancelButton = new Button (); iconPictureBox = new PictureBox (); newNameTextBox = new TextBox (); okButton = new Button (); label1 = new Label (); groupBox1.SuspendLayout (); SuspendLayout (); // groupBox1 groupBox1.Controls.Add (newNameTextBox); groupBox1.Controls.Add (label1); groupBox1.Controls.Add (iconPictureBox); groupBox1.Location = new Point (8, 8); groupBox1.Size = new Size (232, 160); groupBox1.TabIndex = 5; groupBox1.TabStop = false; groupBox1.Text = "New Name"; // cancelButton cancelButton.DialogResult = DialogResult.Cancel; cancelButton.Location = new Point (168, 176); cancelButton.TabIndex = 4; cancelButton.Text = "Cancel"; // iconPictureBox iconPictureBox.BorderStyle = BorderStyle.Fixed3D; iconPictureBox.Location = new Point (86, 24); iconPictureBox.Size = new Size (60, 60); iconPictureBox.TabIndex = 3; iconPictureBox.TabStop = false; iconPictureBox.SizeMode = PictureBoxSizeMode.CenterImage; // newNameTextBox newNameTextBox.Location = new Point (16, 128); newNameTextBox.Size = new Size (200, 20); newNameTextBox.TabIndex = 5; newNameTextBox.Text = String.Empty; // okButton okButton.DialogResult = DialogResult.OK; okButton.Location = new Point (80, 176); okButton.TabIndex = 3; okButton.Text = "OK"; // label1 label1.Location = new Point (16, 96); label1.Size = new Size (200, 23); label1.TabIndex = 4; label1.Text = "Enter Name:"; label1.TextAlign = ContentAlignment.MiddleCenter; // MainForm AcceptButton = okButton; AutoScaleBaseSize = new Size (5, 13); CancelButton = cancelButton; ClientSize = new Size (248, 205); Controls.Add (groupBox1); Controls.Add (cancelButton); Controls.Add (okButton); FormBorderStyle = FormBorderStyle.FixedDialog; Text = "New Folder or File"; groupBox1.ResumeLayout (false); ResumeLayout (false); newNameTextBox.Select (); } public Image IconPictureBoxImage { set { iconPictureBox.Image = value; } } public string FileName { get { return newNameTextBox.Text; } set { newNameTextBox.Text = value; } } } #endregion #region MWFVFS internal class MWFVFS { private FileSystem fileSystem; public static readonly string DesktopPrefix = "Desktop://"; public static readonly string PersonalPrefix = "Personal://"; public static readonly string MyComputerPrefix = "MyComputer://"; public static readonly string RecentlyUsedPrefix = "RecentlyUsed://"; public static readonly string MyNetworkPrefix = "MyNetwork://"; public static readonly string MyComputerPersonalPrefix = "MyComputerPersonal://"; public static Hashtable MyComputerDevicesPrefix = new Hashtable (); public delegate void UpdateDelegate (ArrayList folders, ArrayList files); private UpdateDelegate updateDelegate; private Control calling_control; private ThreadStart get_folder_content_thread_start; private Thread worker; private WorkerThread workerThread = null; private StringCollection the_filters; public MWFVFS () { if (XplatUI.RunningOnUnix) { fileSystem = new UnixFileSystem (); } else { fileSystem = new WinFileSystem (); } } public FSEntry ChangeDirectory (string folder) { return fileSystem.ChangeDirectory (folder); } public void GetFolderContent () { GetFolderContent (null); } public void GetFolderContent (StringCollection filters) { the_filters = filters; if (workerThread != null) { workerThread.Stop (); workerThread = null; } // Added next line to ensure the control is created before BeginInvoke is called on it calling_control.CreateControl(); workerThread = new WorkerThread (fileSystem, the_filters, updateDelegate, calling_control); get_folder_content_thread_start = new ThreadStart (workerThread.GetFolderContentThread); worker = new Thread (get_folder_content_thread_start); worker.IsBackground = true; worker.Start(); } internal class WorkerThread { private FileSystem fileSystem; private StringCollection the_filters; private UpdateDelegate updateDelegate; private Control calling_control; private readonly object lockobject = new object (); private bool stopped = false; public WorkerThread (FileSystem fileSystem, StringCollection the_filters, UpdateDelegate updateDelegate, Control calling_control) { this.fileSystem = fileSystem; this.the_filters = the_filters; this.updateDelegate = updateDelegate; this.calling_control = calling_control; } public void GetFolderContentThread() { ArrayList folders; ArrayList files; fileSystem.GetFolderContent (the_filters, out folders, out files); if (stopped) return; if (updateDelegate != null) { lock (this) { object[] objectArray = new object[2]; objectArray[0] = folders; objectArray[1] = files; calling_control.BeginInvoke (updateDelegate, objectArray); } } } public void Stop () { lock (lockobject) { stopped = true; } } } public ArrayList GetFoldersOnly () { return fileSystem.GetFoldersOnly (); } public void WriteRecentlyUsedFiles (string filename) { fileSystem.WriteRecentlyUsedFiles (filename); } public ArrayList GetRecentlyUsedFiles () { return fileSystem.GetRecentlyUsedFiles (); } public ArrayList GetMyComputerContent () { return fileSystem.GetMyComputerContent (); } public ArrayList GetMyNetworkContent () { return fileSystem.GetMyNetworkContent (); } public bool CreateFolder (string new_folder) { try { if (Directory.Exists (new_folder)) { string message = "Folder \"" + new_folder + "\" already exists."; MessageBox.Show (message, new_folder, MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } else Directory.CreateDirectory (new_folder); } catch (Exception e) { MessageBox.Show (e.Message, new_folder, MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } return true; } public bool MoveFolder (string sourceDirName, string destDirName) { try { if (Directory.Exists (destDirName)) { string message = "Cannot rename " + Path.GetFileName (sourceDirName) + ": A folder with the name you specified already exists." + " Specify a different folder name."; MessageBox.Show (message, "Error Renaming Folder", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } else Directory.Move (sourceDirName, destDirName); } catch (Exception e) { MessageBox.Show (e.Message, "Error Renaming Folder", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } return true; } public bool MoveFile (string sourceFileName, string destFileName) { try { if (File.Exists (destFileName)) { string message = "Cannot rename " + Path.GetFileName (sourceFileName) + ": A file with the name you specified already exists." + " Specify a different file name."; MessageBox.Show (message, "Error Renaming File", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } else File.Move (sourceFileName, destFileName); } catch (Exception e) { MessageBox.Show (e.Message, "Error Renaming File", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } return true; } public string GetParent () { return fileSystem.GetParent (); } public void RegisterUpdateDelegate(UpdateDelegate updateDelegate, Control control) { this.updateDelegate = updateDelegate; calling_control = control; } } #endregion #region FileSystem internal abstract class FileSystem { protected string currentTopFolder = String.Empty; protected FSEntry currentFolderFSEntry = null; protected FSEntry currentTopFolderFSEntry = null; private FileInfoComparer fileInfoComparer = new FileInfoComparer (); private FSEntryComparer fsEntryComparer = new FSEntryComparer (); public FSEntry ChangeDirectory (string folder) { if (folder == MWFVFS.DesktopPrefix) { currentTopFolder = MWFVFS.DesktopPrefix; currentTopFolderFSEntry = currentFolderFSEntry = GetDesktopFSEntry (); } else if (folder == MWFVFS.PersonalPrefix) { currentTopFolder = MWFVFS.PersonalPrefix; currentTopFolderFSEntry = currentFolderFSEntry = GetPersonalFSEntry (); } else if (folder == MWFVFS.MyComputerPersonalPrefix) { currentTopFolder = MWFVFS.MyComputerPersonalPrefix; currentTopFolderFSEntry = currentFolderFSEntry = GetMyComputerPersonalFSEntry (); } else if (folder == MWFVFS.RecentlyUsedPrefix) { currentTopFolder = MWFVFS.RecentlyUsedPrefix; currentTopFolderFSEntry = currentFolderFSEntry = GetRecentlyUsedFSEntry (); } else if (folder == MWFVFS.MyComputerPrefix) { currentTopFolder = MWFVFS.MyComputerPrefix; currentTopFolderFSEntry = currentFolderFSEntry = GetMyComputerFSEntry (); } else if (folder == MWFVFS.MyNetworkPrefix) { currentTopFolder = MWFVFS.MyNetworkPrefix; currentTopFolderFSEntry = currentFolderFSEntry = GetMyNetworkFSEntry (); } else { bool found = false; foreach (DictionaryEntry entry in MWFVFS.MyComputerDevicesPrefix) { FSEntry fsEntry = entry.Value as FSEntry; if (folder == fsEntry.FullName) { currentTopFolder = entry.Key as string; currentTopFolderFSEntry = currentFolderFSEntry = fsEntry; found = true; break; } } if (!found) { currentFolderFSEntry = GetDirectoryFSEntry (new DirectoryInfo (folder), currentTopFolderFSEntry); } } return currentFolderFSEntry; } public string GetParent () { return currentFolderFSEntry.Parent; } // directories_out and files_out contain FSEntry objects public void GetFolderContent (StringCollection filters, out ArrayList directories_out, out ArrayList files_out) { directories_out = new ArrayList (); files_out = new ArrayList (); if (currentFolderFSEntry.FullName == MWFVFS.DesktopPrefix) { FSEntry personalFSEntry = GetPersonalFSEntry (); directories_out.Add (personalFSEntry); FSEntry myComputerFSEntry = GetMyComputerFSEntry (); directories_out.Add (myComputerFSEntry); FSEntry myNetworkFSEntry = GetMyNetworkFSEntry (); directories_out.Add (myNetworkFSEntry); ArrayList d_out = null; ArrayList f_out = null; GetNormalFolderContent (ThemeEngine.Current.Places (UIIcon.PlacesDesktop), filters, out d_out, out f_out); directories_out.AddRange (d_out); files_out.AddRange (f_out); } else if (currentFolderFSEntry.FullName == MWFVFS.RecentlyUsedPrefix) { files_out = GetRecentlyUsedFiles (); } else if (currentFolderFSEntry.FullName == MWFVFS.MyComputerPrefix) { directories_out.AddRange (GetMyComputerContent ()); } else if (currentFolderFSEntry.FullName == MWFVFS.PersonalPrefix || currentFolderFSEntry.FullName == MWFVFS.MyComputerPersonalPrefix) { ArrayList d_out = null; ArrayList f_out = null; GetNormalFolderContent (ThemeEngine.Current.Places (UIIcon.PlacesPersonal), filters, out d_out, out f_out); directories_out.AddRange (d_out); files_out.AddRange (f_out); } else if (currentFolderFSEntry.FullName == MWFVFS.MyNetworkPrefix) { directories_out.AddRange (GetMyNetworkContent ()); } else { GetNormalFolderContent (currentFolderFSEntry.FullName, filters, out directories_out, out files_out); } } public ArrayList GetFoldersOnly () { ArrayList directories_out = new ArrayList (); if (currentFolderFSEntry.FullName == MWFVFS.DesktopPrefix) { FSEntry personalFSEntry = GetPersonalFSEntry (); directories_out.Add (personalFSEntry); FSEntry myComputerFSEntry = GetMyComputerFSEntry (); directories_out.Add (myComputerFSEntry); FSEntry myNetworkFSEntry = GetMyNetworkFSEntry (); directories_out.Add (myNetworkFSEntry); ArrayList d_out = GetNormalFolders (ThemeEngine.Current.Places (UIIcon.PlacesDesktop)); directories_out.AddRange (d_out); } else if (currentFolderFSEntry.FullName == MWFVFS.RecentlyUsedPrefix) { //files_out = GetRecentlyUsedFiles (); } else if (currentFolderFSEntry.FullName == MWFVFS.MyComputerPrefix) { directories_out.AddRange (GetMyComputerContent ()); } else if (currentFolderFSEntry.FullName == MWFVFS.PersonalPrefix || currentFolderFSEntry.FullName == MWFVFS.MyComputerPersonalPrefix) { ArrayList d_out = GetNormalFolders (ThemeEngine.Current.Places (UIIcon.PlacesPersonal)); directories_out.AddRange (d_out); } else if (currentFolderFSEntry.FullName == MWFVFS.MyNetworkPrefix) { directories_out.AddRange (GetMyNetworkContent ()); } else { directories_out = GetNormalFolders (currentFolderFSEntry.FullName); } return directories_out; } protected void GetNormalFolderContent (string from_folder, StringCollection filters, out ArrayList directories_out, out ArrayList files_out) { DirectoryInfo dirinfo = new DirectoryInfo (from_folder); directories_out = new ArrayList (); DirectoryInfo[] dirs = null; try { dirs = dirinfo.GetDirectories (); } catch (Exception) {} if (dirs != null) for (int i = 0; i < dirs.Length; i++) { directories_out.Add (GetDirectoryFSEntry (dirs [i], currentTopFolderFSEntry)); } directories_out.Sort (fsEntryComparer); files_out = new ArrayList (); ArrayList files = new ArrayList (); try { if (filters == null) { files.AddRange (dirinfo.GetFiles ()); } else { foreach (string s in filters) files.AddRange (dirinfo.GetFiles (s)); files.Sort (fileInfoComparer); } } catch (Exception) {} for (int i = 0; i < files.Count; i++) { FSEntry fs = GetFileFSEntry (files [i] as FileInfo); if (fs != null) files_out.Add (fs); } } protected ArrayList GetNormalFolders (string from_folder) { DirectoryInfo dirinfo = new DirectoryInfo (from_folder); ArrayList directories_out = new ArrayList (); DirectoryInfo[] dirs = null; try { dirs = dirinfo.GetDirectories (); } catch (Exception) {} if (dirs != null) for (int i = 0; i < dirs.Length; i++) { directories_out.Add (GetDirectoryFSEntry (dirs [i], currentTopFolderFSEntry)); } return directories_out; } protected virtual FSEntry GetDirectoryFSEntry (DirectoryInfo dirinfo, FSEntry topFolderFSEntry) { FSEntry fs = new FSEntry (); fs.Attributes = dirinfo.Attributes; fs.FullName = dirinfo.FullName; fs.Name = dirinfo.Name; fs.MainTopNode = topFolderFSEntry; fs.FileType = FSEntry.FSEntryType.Directory; fs.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("inode/directory"); fs.LastAccessTime = dirinfo.LastAccessTime; return fs; } protected virtual FSEntry GetFileFSEntry (FileInfo fileinfo) { // *sigh* FileInfo gives us no usable information for links to directories // so, return null if ((fileinfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory) return null; FSEntry fs = new FSEntry (); fs.Attributes = fileinfo.Attributes; fs.FullName = fileinfo.FullName; fs.Name = fileinfo.Name; fs.FileType = FSEntry.FSEntryType.File; fs.IconIndex = MimeIconEngine.GetIconIndexForFile (fileinfo.FullName); fs.FileSize = fileinfo.Length; fs.LastAccessTime = fileinfo.LastAccessTime; return fs; } internal class FileInfoComparer : IComparer { public int Compare (object fileInfo1, object fileInfo2) { return String.Compare (((FileInfo)fileInfo1).Name, ((FileInfo)fileInfo2).Name); } } internal class FSEntryComparer : IComparer { public int Compare (object fileInfo1, object fileInfo2) { return String.Compare (((FSEntry)fileInfo1).Name, ((FSEntry)fileInfo2).Name); } } protected abstract FSEntry GetDesktopFSEntry (); protected abstract FSEntry GetRecentlyUsedFSEntry (); protected abstract FSEntry GetPersonalFSEntry (); protected abstract FSEntry GetMyComputerPersonalFSEntry (); protected abstract FSEntry GetMyComputerFSEntry (); protected abstract FSEntry GetMyNetworkFSEntry (); public abstract void WriteRecentlyUsedFiles (string fileToAdd); public abstract ArrayList GetRecentlyUsedFiles (); public abstract ArrayList GetMyComputerContent (); public abstract ArrayList GetMyNetworkContent (); } #endregion #region UnixFileSystem internal class UnixFileSystem : FileSystem { private MasterMount masterMount = new MasterMount (); private FSEntry desktopFSEntry = null; private FSEntry recentlyusedFSEntry = null; private FSEntry personalFSEntry = null; private FSEntry mycomputerpersonalFSEntry = null; private FSEntry mycomputerFSEntry = null; private FSEntry mynetworkFSEntry = null; private string personal_folder; private string recently_used_path; private string full_kde_recent_document_dir; public UnixFileSystem () { personal_folder = ThemeEngine.Current.Places (UIIcon.PlacesPersonal); recently_used_path = Path.Combine (personal_folder, ".recently-used"); full_kde_recent_document_dir = personal_folder + "/.kde/share/apps/RecentDocuments"; desktopFSEntry = new FSEntry (); desktopFSEntry.Attributes = FileAttributes.Directory; desktopFSEntry.FullName = MWFVFS.DesktopPrefix; desktopFSEntry.Name = "Desktop"; desktopFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesDesktop); desktopFSEntry.FileType = FSEntry.FSEntryType.Directory; desktopFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("desktop/desktop"); desktopFSEntry.LastAccessTime = DateTime.Now; recentlyusedFSEntry = new FSEntry (); recentlyusedFSEntry.Attributes = FileAttributes.Directory; recentlyusedFSEntry.FullName = MWFVFS.RecentlyUsedPrefix; recentlyusedFSEntry.Name = "Recently Used"; recentlyusedFSEntry.FileType = FSEntry.FSEntryType.Directory; recentlyusedFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("recently/recently"); recentlyusedFSEntry.LastAccessTime = DateTime.Now; personalFSEntry = new FSEntry (); personalFSEntry.Attributes = FileAttributes.Directory; personalFSEntry.FullName = MWFVFS.PersonalPrefix; personalFSEntry.Name = "Personal"; personalFSEntry.MainTopNode = GetDesktopFSEntry (); personalFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesPersonal); personalFSEntry.FileType = FSEntry.FSEntryType.Directory; personalFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("directory/home"); personalFSEntry.LastAccessTime = DateTime.Now; mycomputerpersonalFSEntry = new FSEntry (); mycomputerpersonalFSEntry.Attributes = FileAttributes.Directory; mycomputerpersonalFSEntry.FullName = MWFVFS.MyComputerPersonalPrefix; mycomputerpersonalFSEntry.Name = "Personal"; mycomputerpersonalFSEntry.MainTopNode = GetMyComputerFSEntry (); mycomputerpersonalFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesPersonal); mycomputerpersonalFSEntry.FileType = FSEntry.FSEntryType.Directory; mycomputerpersonalFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("directory/home"); mycomputerpersonalFSEntry.LastAccessTime = DateTime.Now; mycomputerFSEntry = new FSEntry (); mycomputerFSEntry.Attributes = FileAttributes.Directory; mycomputerFSEntry.FullName = MWFVFS.MyComputerPrefix; mycomputerFSEntry.Name = "My Computer"; mycomputerFSEntry.MainTopNode = GetDesktopFSEntry (); mycomputerFSEntry.FileType = FSEntry.FSEntryType.Directory; mycomputerFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("workplace/workplace"); mycomputerFSEntry.LastAccessTime = DateTime.Now; mynetworkFSEntry = new FSEntry (); mynetworkFSEntry.Attributes = FileAttributes.Directory; mynetworkFSEntry.FullName = MWFVFS.MyNetworkPrefix; mynetworkFSEntry.Name = "My Network"; mynetworkFSEntry.MainTopNode = GetDesktopFSEntry (); mynetworkFSEntry.FileType = FSEntry.FSEntryType.Directory; mynetworkFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("network/network"); mynetworkFSEntry.LastAccessTime = DateTime.Now; } public override void WriteRecentlyUsedFiles (string fileToAdd) { if (File.Exists (recently_used_path) && new FileInfo (recently_used_path).Length > 0) { XmlDocument xml_doc = new XmlDocument (); xml_doc.Load (recently_used_path); XmlNode grand_parent_node = xml_doc.SelectSingleNode ("RecentFiles"); if (grand_parent_node != null) { // create a new element XmlElement new_recent_item_node = xml_doc.CreateElement ("RecentItem"); XmlElement new_child = xml_doc.CreateElement ("URI"); UriBuilder ub = new UriBuilder (); ub.Path = fileToAdd; ub.Host = null; ub.Scheme = "file"; XmlText new_text_child = xml_doc.CreateTextNode (ub.ToString ()); new_child.AppendChild (new_text_child); new_recent_item_node.AppendChild (new_child); new_child = xml_doc.CreateElement ("Mime-Type"); new_text_child = xml_doc.CreateTextNode (Mime.GetMimeTypeForFile (fileToAdd)); new_child.AppendChild (new_text_child); new_recent_item_node.AppendChild (new_child); new_child = xml_doc.CreateElement ("Timestamp"); long seconds = (long)(DateTime.UtcNow - new DateTime (1970, 1, 1)).TotalSeconds; new_text_child = xml_doc.CreateTextNode (seconds.ToString ()); new_child.AppendChild (new_text_child); new_recent_item_node.AppendChild (new_child); new_child = xml_doc.CreateElement ("Groups"); new_recent_item_node.AppendChild (new_child); // now search the nodes in grand_parent_node for another instance of the new uri and if found remove it // so that the new node is the first one foreach (XmlNode n in grand_parent_node.ChildNodes) { XmlNode uri_node = n.SelectSingleNode ("URI"); if (uri_node != null) { XmlNode uri_node_child = uri_node.FirstChild; if (uri_node_child is XmlText) if (ub.ToString () == ((XmlText)uri_node_child).Data) { grand_parent_node.RemoveChild (n); break; } } } // prepend the new recent item to the grand parent node list grand_parent_node.PrependChild (new_recent_item_node); // limit the # of RecentItems to 10 if (grand_parent_node.ChildNodes.Count > 10) { while (grand_parent_node.ChildNodes.Count > 10) grand_parent_node.RemoveChild (grand_parent_node.LastChild); } try { xml_doc.Save (recently_used_path); } catch (Exception) { } } } else { XmlDocument xml_doc = new XmlDocument (); xml_doc.AppendChild (xml_doc.CreateXmlDeclaration ("1.0", String.Empty, String.Empty)); XmlElement recentFiles_element = xml_doc.CreateElement ("RecentFiles"); XmlElement new_recent_item_node = xml_doc.CreateElement ("RecentItem"); XmlElement new_child = xml_doc.CreateElement ("URI"); UriBuilder ub = new UriBuilder (); ub.Path = fileToAdd; ub.Host = null; ub.Scheme = "file"; XmlText new_text_child = xml_doc.CreateTextNode (ub.ToString ()); new_child.AppendChild (new_text_child); new_recent_item_node.AppendChild (new_child); new_child = xml_doc.CreateElement ("Mime-Type"); new_text_child = xml_doc.CreateTextNode (Mime.GetMimeTypeForFile (fileToAdd)); new_child.AppendChild (new_text_child); new_recent_item_node.AppendChild (new_child); new_child = xml_doc.CreateElement ("Timestamp"); long seconds = (long)(DateTime.UtcNow - new DateTime (1970, 1, 1)).TotalSeconds; new_text_child = xml_doc.CreateTextNode (seconds.ToString ()); new_child.AppendChild (new_text_child); new_recent_item_node.AppendChild (new_child); new_child = xml_doc.CreateElement ("Groups"); new_recent_item_node.AppendChild (new_child); recentFiles_element.AppendChild (new_recent_item_node); xml_doc.AppendChild (recentFiles_element); try { xml_doc.Save (recently_used_path); } catch (Exception) { } } } // return an ArrayList with FSEntry objects public override ArrayList GetRecentlyUsedFiles () { // check for GNOME and KDE ArrayList files_al = new ArrayList (); // GNOME if (File.Exists (recently_used_path)) { try { XmlTextReader xtr = new XmlTextReader (recently_used_path); while (xtr.Read ()) { if (xtr.NodeType == XmlNodeType.Element && xtr.Name.ToUpper () == "URI") { xtr.Read (); Uri uri = new Uri (xtr.Value); if (!files_al.Contains (uri.LocalPath)) if (File.Exists (uri.LocalPath)) { FSEntry fs = GetFileFSEntry (new FileInfo (uri.LocalPath)); if (fs != null) files_al.Add (fs); } } } xtr.Close (); } catch (Exception) { } } // KDE if (Directory.Exists (full_kde_recent_document_dir)) { string[] files = Directory.GetFiles (full_kde_recent_document_dir, "*.desktop"); foreach (string file_name in files) { StreamReader sr = new StreamReader (file_name); string line = sr.ReadLine (); while (line != null) { line = line.Trim (); if (line.StartsWith ("URL=")) { line = line.Replace ("URL=", String.Empty); line = line.Replace ("$HOME", personal_folder); Uri uri = new Uri (line); if (!files_al.Contains (uri.LocalPath)) if (File.Exists (uri.LocalPath)) { FSEntry fs = GetFileFSEntry (new FileInfo (uri.LocalPath)); if (fs != null) files_al.Add (fs); } break; } line = sr.ReadLine (); } sr.Close (); } } return files_al; } // return an ArrayList with FSEntry objects public override ArrayList GetMyComputerContent () { ArrayList my_computer_content_arraylist = new ArrayList (); if (masterMount.ProcMountAvailable) { masterMount.GetMounts (); foreach (MasterMount.Mount mount in masterMount.Block_devices) { FSEntry fsEntry = new FSEntry (); fsEntry.FileType = FSEntry.FSEntryType.Device; fsEntry.FullName = mount.mount_point; fsEntry.Name = "HDD (" + mount.fsType + ", " + mount.device_short + ")"; fsEntry.FsType = mount.fsType; fsEntry.DeviceShort = mount.device_short; fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("harddisk/harddisk"); fsEntry.Attributes = FileAttributes.Directory; fsEntry.MainTopNode = GetMyComputerFSEntry (); my_computer_content_arraylist.Add (fsEntry); if (!MWFVFS.MyComputerDevicesPrefix.Contains (fsEntry.FullName + "://")) MWFVFS.MyComputerDevicesPrefix.Add (fsEntry.FullName + "://", fsEntry); } foreach (MasterMount.Mount mount in masterMount.Removable_devices) { FSEntry fsEntry = new FSEntry (); fsEntry.FileType = FSEntry.FSEntryType.RemovableDevice; fsEntry.FullName = mount.mount_point; bool is_dvd_cdrom = mount.fsType == MasterMount.FsTypes.usbfs ? false : true; string type_name = is_dvd_cdrom ? "DVD/CD-Rom" : "USB"; string mime_type = is_dvd_cdrom ? "cdrom/cdrom" : "removable/removable"; fsEntry.Name = type_name +" (" + mount.device_short + ")"; fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType (mime_type); fsEntry.FsType = mount.fsType; fsEntry.DeviceShort = mount.device_short; fsEntry.Attributes = FileAttributes.Directory; fsEntry.MainTopNode = GetMyComputerFSEntry (); my_computer_content_arraylist.Add (fsEntry); string contain_string = fsEntry.FullName + "://"; if (!MWFVFS.MyComputerDevicesPrefix.Contains (contain_string)) MWFVFS.MyComputerDevicesPrefix.Add (contain_string, fsEntry); } } my_computer_content_arraylist.Add (GetMyComputerPersonalFSEntry ()); return my_computer_content_arraylist; } public override ArrayList GetMyNetworkContent () { ArrayList fsEntries = new ArrayList (); foreach (MasterMount.Mount mount in masterMount.Network_devices) { FSEntry fsEntry = new FSEntry (); fsEntry.FileType = FSEntry.FSEntryType.Network; fsEntry.FullName = mount.mount_point; fsEntry.FsType = mount.fsType; fsEntry.DeviceShort = mount.device_short; fsEntry.Name = "Network (" + mount.fsType + ", " + mount.device_short + ")"; switch (mount.fsType) { case MasterMount.FsTypes.nfs: fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("nfs/nfs"); break; case MasterMount.FsTypes.smbfs: fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("smb/smb"); break; case MasterMount.FsTypes.ncpfs: fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("network/network"); break; case MasterMount.FsTypes.cifs: fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("network/network"); break; default: break; } fsEntry.Attributes = FileAttributes.Directory; fsEntry.MainTopNode = GetMyNetworkFSEntry (); fsEntries.Add (fsEntry); } return fsEntries; } protected override FSEntry GetDesktopFSEntry () { return desktopFSEntry; } protected override FSEntry GetRecentlyUsedFSEntry () { return recentlyusedFSEntry; } protected override FSEntry GetPersonalFSEntry () { return personalFSEntry; } protected override FSEntry GetMyComputerPersonalFSEntry () { return mycomputerpersonalFSEntry; } protected override FSEntry GetMyComputerFSEntry () { return mycomputerFSEntry; } protected override FSEntry GetMyNetworkFSEntry () { return mynetworkFSEntry; } } #endregion #region WinFileSystem internal class WinFileSystem : FileSystem { private FSEntry desktopFSEntry = null; private FSEntry recentlyusedFSEntry = null; private FSEntry personalFSEntry = null; private FSEntry mycomputerpersonalFSEntry = null; private FSEntry mycomputerFSEntry = null; private FSEntry mynetworkFSEntry = null; public WinFileSystem () { desktopFSEntry = new FSEntry (); desktopFSEntry.Attributes = FileAttributes.Directory; desktopFSEntry.FullName = MWFVFS.DesktopPrefix; desktopFSEntry.Name = "Desktop"; desktopFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesDesktop); desktopFSEntry.FileType = FSEntry.FSEntryType.Directory; desktopFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("desktop/desktop"); desktopFSEntry.LastAccessTime = DateTime.Now; recentlyusedFSEntry = new FSEntry (); recentlyusedFSEntry.Attributes = FileAttributes.Directory; recentlyusedFSEntry.FullName = MWFVFS.RecentlyUsedPrefix; recentlyusedFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesRecentDocuments); recentlyusedFSEntry.Name = "Recently Used"; recentlyusedFSEntry.FileType = FSEntry.FSEntryType.Directory; recentlyusedFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("recently/recently"); recentlyusedFSEntry.LastAccessTime = DateTime.Now; personalFSEntry = new FSEntry (); personalFSEntry.Attributes = FileAttributes.Directory; personalFSEntry.FullName = MWFVFS.PersonalPrefix; personalFSEntry.Name = "Personal"; personalFSEntry.MainTopNode = GetDesktopFSEntry (); personalFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesPersonal); personalFSEntry.FileType = FSEntry.FSEntryType.Directory; personalFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("directory/home"); personalFSEntry.LastAccessTime = DateTime.Now; mycomputerpersonalFSEntry = new FSEntry (); mycomputerpersonalFSEntry.Attributes = FileAttributes.Directory; mycomputerpersonalFSEntry.FullName = MWFVFS.MyComputerPersonalPrefix; mycomputerpersonalFSEntry.Name = "Personal"; mycomputerpersonalFSEntry.MainTopNode = GetMyComputerFSEntry (); mycomputerpersonalFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesPersonal); mycomputerpersonalFSEntry.FileType = FSEntry.FSEntryType.Directory; mycomputerpersonalFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("directory/home"); mycomputerpersonalFSEntry.LastAccessTime = DateTime.Now; mycomputerFSEntry = new FSEntry (); mycomputerFSEntry.Attributes = FileAttributes.Directory; mycomputerFSEntry.FullName = MWFVFS.MyComputerPrefix; mycomputerFSEntry.Name = "My Computer"; mycomputerFSEntry.MainTopNode = GetDesktopFSEntry (); mycomputerFSEntry.FileType = FSEntry.FSEntryType.Directory; mycomputerFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("workplace/workplace"); mycomputerFSEntry.LastAccessTime = DateTime.Now; mynetworkFSEntry = new FSEntry (); mynetworkFSEntry.Attributes = FileAttributes.Directory; mynetworkFSEntry.FullName = MWFVFS.MyNetworkPrefix; mynetworkFSEntry.Name = "My Network"; mynetworkFSEntry.MainTopNode = GetDesktopFSEntry (); mynetworkFSEntry.FileType = FSEntry.FSEntryType.Directory; mynetworkFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("network/network"); mynetworkFSEntry.LastAccessTime = DateTime.Now; } public override void WriteRecentlyUsedFiles (string fileToAdd) { // TODO: Implement this method // use SHAddToRecentDocs ? } public override ArrayList GetRecentlyUsedFiles () { ArrayList al = new ArrayList (); DirectoryInfo di = new DirectoryInfo (recentlyusedFSEntry.RealName); FileInfo[] fileinfos = di.GetFiles (); foreach (FileInfo fi in fileinfos) { FSEntry fs = GetFileFSEntry (fi); if (fs != null) al.Add (fs); } return al; } public override ArrayList GetMyComputerContent () { string[] logical_drives = Directory.GetLogicalDrives (); ArrayList my_computer_content_arraylist = new ArrayList (); foreach (string drive in logical_drives) { FSEntry fsEntry = new FSEntry (); fsEntry.FileType = FSEntry.FSEntryType.Device; fsEntry.FullName = drive; fsEntry.Name = drive; fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("harddisk/harddisk"); fsEntry.Attributes = FileAttributes.Directory; fsEntry.MainTopNode = GetMyComputerFSEntry (); my_computer_content_arraylist.Add (fsEntry); string contain_string = fsEntry.FullName + "://"; if (!MWFVFS.MyComputerDevicesPrefix.Contains (contain_string)) MWFVFS.MyComputerDevicesPrefix.Add (contain_string, fsEntry); } my_computer_content_arraylist.Add (GetMyComputerPersonalFSEntry ()); return my_computer_content_arraylist; } public override ArrayList GetMyNetworkContent () { // TODO: Implement this method return new ArrayList (); } protected override FSEntry GetDesktopFSEntry () { return desktopFSEntry; } protected override FSEntry GetRecentlyUsedFSEntry () { return recentlyusedFSEntry; } protected override FSEntry GetPersonalFSEntry () { return personalFSEntry; } protected override FSEntry GetMyComputerPersonalFSEntry () { return mycomputerpersonalFSEntry; } protected override FSEntry GetMyComputerFSEntry () { return mycomputerFSEntry; } protected override FSEntry GetMyNetworkFSEntry () { return mynetworkFSEntry; } } #endregion #region FSEntry internal class FSEntry { public enum FSEntryType { Desktop, RecentlyUsed, MyComputer, File, Directory, Device, RemovableDevice, Network } private MasterMount.FsTypes fsType; private string device_short; private string fullName; private string name; private string realName = null; private FileAttributes attributes = FileAttributes.Normal; private long fileSize; private FSEntryType fileType; private DateTime lastAccessTime; private FSEntry mainTopNode = null; private int iconIndex; private string parent; public MasterMount.FsTypes FsType { set { fsType = value; } get { return fsType; } } public string DeviceShort { set { device_short = value; } get { return device_short; } } public string FullName { set { fullName = value; } get { return fullName; } } public string Name { set { name = value; } get { return name; } } public string RealName { set { realName = value; } get { return realName; } } public FileAttributes Attributes { set { attributes = value; } get { return attributes; } } public long FileSize { set { fileSize = value; } get { return fileSize; } } public FSEntryType FileType { set { fileType = value; } get { return fileType; } } public DateTime LastAccessTime { set { lastAccessTime = value; } get { return lastAccessTime; } } public int IconIndex { set { iconIndex = value; } get { return iconIndex; } } public FSEntry MainTopNode { set { mainTopNode = value; } get { return mainTopNode; } } public string Parent { set { parent = value; } get { parent = GetParent (); return parent; } } private string GetParent () { if (fullName == MWFVFS.PersonalPrefix) { return MWFVFS.DesktopPrefix; } else if (fullName == MWFVFS.MyComputerPersonalPrefix) { return MWFVFS.MyComputerPrefix; } else if (fullName == MWFVFS.MyComputerPrefix) { return MWFVFS.DesktopPrefix; } else if (fullName == MWFVFS.MyNetworkPrefix) { return MWFVFS.DesktopPrefix; } else if (fullName == MWFVFS.DesktopPrefix) { return null; } else if (fullName == MWFVFS.RecentlyUsedPrefix) { return null; } else { foreach (DictionaryEntry entry in MWFVFS.MyComputerDevicesPrefix) { FSEntry fsEntry = entry.Value as FSEntry; if (fullName == fsEntry.FullName) { return fsEntry.MainTopNode.FullName; } } DirectoryInfo dirInfo = new DirectoryInfo (fullName); DirectoryInfo dirInfoParent = dirInfo.Parent; if (dirInfoParent != null) { FSEntry fsEntry = MWFVFS.MyComputerDevicesPrefix [dirInfoParent.FullName + "://"] as FSEntry; if (fsEntry != null) { return fsEntry.FullName; } if (mainTopNode != null) { if (dirInfoParent.FullName == ThemeEngine.Current.Places (UIIcon.PlacesDesktop) && mainTopNode.FullName == MWFVFS.DesktopPrefix) { return mainTopNode.FullName; } else if (dirInfoParent.FullName == ThemeEngine.Current.Places (UIIcon.PlacesPersonal) && mainTopNode.FullName == MWFVFS.PersonalPrefix) { return mainTopNode.FullName; } else if (dirInfoParent.FullName == ThemeEngine.Current.Places (UIIcon.PlacesPersonal) && mainTopNode.FullName == MWFVFS.MyComputerPersonalPrefix) { return mainTopNode.FullName; } } return dirInfoParent.FullName; } } return null; } } #endregion #region MasterMount // Alexsantas little *nix helper internal class MasterMount { // add more... internal enum FsTypes { none, ext2, ext3, hpfs, iso9660, jfs, minix, msdos, ntfs, reiserfs, ufs, umsdos, vfat, sysv, xfs, ncpfs, nfs, smbfs, usbfs, cifs } internal struct Mount { public string device_or_filesystem; public string device_short; public string mount_point; public FsTypes fsType; } bool proc_mount_available = false; ArrayList block_devices = new ArrayList (); ArrayList network_devices = new ArrayList (); ArrayList removable_devices = new ArrayList (); private MountComparer mountComparer = new MountComparer (); public MasterMount () { // maybe check if the current user can access /proc/mounts if (XplatUI.RunningOnUnix) if (File.Exists ("/proc/mounts")) proc_mount_available = true; } public ArrayList Block_devices { get { return block_devices; } } public ArrayList Network_devices { get { return network_devices; } } public ArrayList Removable_devices { get { return removable_devices; } } public bool ProcMountAvailable { get { return proc_mount_available; } } public void GetMounts () { if (!proc_mount_available) return; block_devices.Clear (); network_devices.Clear (); removable_devices.Clear (); try { StreamReader sr = new StreamReader ("/proc/mounts"); string line = sr.ReadLine (); ArrayList lines = new ArrayList (); while (line != null) { if (lines.IndexOf (line) == -1) { // Avoid duplicates ProcessProcMountLine (line); lines.Add (line); } line = sr.ReadLine (); } sr.Close (); block_devices.Sort (mountComparer); network_devices.Sort (mountComparer); removable_devices.Sort (mountComparer); } catch { // bla } } private void ProcessProcMountLine (string line) { string[] split = line.Split (new char [] {' '}); if (split != null && split.Length > 0) { Mount mount = new Mount (); if (split [0].StartsWith ("/dev/")) mount.device_short = split [0].Replace ("/dev/", String.Empty); else mount.device_short = split [0]; mount.device_or_filesystem = split [0]; mount.mount_point = split [1]; // TODO: other removable devices, floppy // ssh // network mount if (split [2] == "nfs") { mount.fsType = FsTypes.nfs; network_devices.Add (mount); } else if (split [2] == "smbfs") { mount.fsType = FsTypes.smbfs; network_devices.Add (mount); } else if (split [2] == "cifs") { mount.fsType = FsTypes.cifs; network_devices.Add (mount); } else if (split [2] == "ncpfs") { mount.fsType = FsTypes.ncpfs; network_devices.Add (mount); } else if (split [2] == "iso9660") { //cdrom mount.fsType = FsTypes.iso9660; removable_devices.Add (mount); } else if (split [2] == "usbfs") { //usb ? not tested mount.fsType = FsTypes.usbfs; removable_devices.Add (mount); } else if (split [0].StartsWith ("/")) { //block devices if (split [1].StartsWith ("/dev/")) // root static, do not add return; if (split [2] == "ext2") mount.fsType = FsTypes.ext2; else if (split [2] == "ext3") mount.fsType = FsTypes.ext3; else if (split [2] == "reiserfs") mount.fsType = FsTypes.reiserfs; else if (split [2] == "xfs") mount.fsType = FsTypes.xfs; else if (split [2] == "vfat") mount.fsType = FsTypes.vfat; else if (split [2] == "ntfs") mount.fsType = FsTypes.ntfs; else if (split [2] == "msdos") mount.fsType = FsTypes.msdos; else if (split [2] == "umsdos") mount.fsType = FsTypes.umsdos; else if (split [2] == "hpfs") mount.fsType = FsTypes.hpfs; else if (split [2] == "minix") mount.fsType = FsTypes.minix; else if (split [2] == "jfs") mount.fsType = FsTypes.jfs; block_devices.Add (mount); } } } public class MountComparer : IComparer { public int Compare (object mount1, object mount2) { return String.Compare (((Mount)mount1).device_short, ((Mount)mount2).device_short); } } } #endregion #region MWFConfig // easy to use class to store and read internal MWF config settings. // the config values are stored in the users home dir as a hidden xml file called "mwf_config". // currently supports int, string, byte, color and arrays (including byte arrays) // don't forget, when you read a value you still have to cast this value. // // usage: // MWFConfig.SetValue ("SomeClass", "What", value); // object o = MWFConfig.GetValue ("SomeClass", "What"); // // example: // // string[] configFileNames = (string[])MWFConfig.GetValue ("FileDialog", "FileNames"); // MWFConfig.SetValue ("FileDialog", "LastFolder", "/home/user"); internal class MWFConfig { private static MWFConfigInstance Instance = new MWFConfigInstance (); private static object lock_object = new object(); public static object GetValue (string class_name, string value_name) { lock (lock_object) { return Instance.GetValue (class_name, value_name); } } public static void SetValue (string class_name, string value_name, object value) { lock (lock_object) { Instance.SetValue (class_name, value_name, value); } } public static void Flush () { lock (lock_object) { Instance.Flush (); } } public static void RemoveClass (string class_name) { lock (lock_object) { Instance.RemoveClass (class_name); } } public static void RemoveClassValue (string class_name, string value_name) { lock (lock_object) { Instance.RemoveClassValue (class_name, value_name); } } public static void RemoveAllClassValues (string class_name) { lock (lock_object) { Instance.RemoveAllClassValues (class_name); } } internal class MWFConfigInstance { Hashtable classes_hashtable = new Hashtable (); static string full_file_name; static string default_file_name; readonly string configName = "MWFConfig"; static MWFConfigInstance () { string b = "mwf_config"; string dir = Environment.GetFolderPath (Environment.SpecialFolder.Personal); if (XplatUI.RunningOnUnix) { dir = Path.Combine (dir, ".mono"); try { Directory.CreateDirectory (dir); } catch {} } default_file_name = Path.Combine (dir, b); full_file_name = default_file_name; } public MWFConfigInstance () { Open (default_file_name); } // only for testing public MWFConfigInstance (string filename) { string path = Path.GetDirectoryName (filename); if (path == null || path == String.Empty) { path = Environment.GetFolderPath (Environment.SpecialFolder.Personal); full_file_name = Path.Combine (path, filename); } else full_file_name = filename; Open (full_file_name); } ~MWFConfigInstance () { Flush (); } public object GetValue (string class_name, string value_name) { ClassEntry class_entry = classes_hashtable [class_name] as ClassEntry; if (class_entry != null) return class_entry.GetValue (value_name); return null; } public void SetValue (string class_name, string value_name, object value) { ClassEntry class_entry = classes_hashtable [class_name] as ClassEntry; if (class_entry == null) { class_entry = new ClassEntry (); class_entry.ClassName = class_name; classes_hashtable [class_name] = class_entry; } class_entry.SetValue (value_name, value); } private void Open (string filename) { try { XmlTextReader xtr = new XmlTextReader (filename); ReadConfig (xtr); xtr.Close (); } catch (Exception) { } } public void Flush () { try { XmlTextWriter xtw = new XmlTextWriter (full_file_name, null); xtw.Formatting = Formatting.Indented; WriteConfig (xtw); xtw.Close (); if (!XplatUI.RunningOnUnix) File.SetAttributes (full_file_name, FileAttributes.Hidden); } catch (Exception){ } } public void RemoveClass (string class_name) { ClassEntry class_entry = classes_hashtable [class_name] as ClassEntry; if (class_entry != null) { class_entry.RemoveAllClassValues (); classes_hashtable.Remove (class_name); } } public void RemoveClassValue (string class_name, string value_name) { ClassEntry class_entry = classes_hashtable [class_name] as ClassEntry; if (class_entry != null) { class_entry.RemoveClassValue (value_name); } } public void RemoveAllClassValues (string class_name) { ClassEntry class_entry = classes_hashtable [class_name] as ClassEntry; if (class_entry != null) { class_entry.RemoveAllClassValues (); } } private void ReadConfig (XmlTextReader xtr) { if (!CheckForMWFConfig (xtr)) return; while (xtr.Read ()) { switch (xtr.NodeType) { case XmlNodeType.Element: ClassEntry class_entry = classes_hashtable [xtr.Name] as ClassEntry; if (class_entry == null) { class_entry = new ClassEntry (); class_entry.ClassName = xtr.Name; classes_hashtable [xtr.Name] = class_entry; } class_entry.ReadXml (xtr); break; } } } private bool CheckForMWFConfig (XmlTextReader xtr) { if (xtr.Read ()) { if (xtr.NodeType == XmlNodeType.Element) { if (xtr.Name == configName) return true; } } return false; } private void WriteConfig (XmlTextWriter xtw) { if (classes_hashtable.Count == 0) return; xtw.WriteStartElement (configName); foreach (DictionaryEntry entry in classes_hashtable) { ClassEntry class_entry = entry.Value as ClassEntry; class_entry.WriteXml (xtw); } xtw.WriteEndElement (); } internal class ClassEntry { private Hashtable classvalues_hashtable = new Hashtable (); private string className; public string ClassName { set { className = value; } get { return className; } } public void SetValue (string value_name, object value) { ClassValue class_value = classvalues_hashtable [value_name] as ClassValue; if (class_value == null) { class_value = new ClassValue (); class_value.Name = value_name; classvalues_hashtable [value_name] = class_value; } class_value.SetValue (value); } public object GetValue (string value_name) { ClassValue class_value = classvalues_hashtable [value_name] as ClassValue; if (class_value == null) { return null; } return class_value.GetValue (); } public void RemoveAllClassValues () { classvalues_hashtable.Clear (); } public void RemoveClassValue (string value_name) { ClassValue class_value = classvalues_hashtable [value_name] as ClassValue; if (class_value != null) { classvalues_hashtable.Remove (value_name); } } public void ReadXml (XmlTextReader xtr) { while (xtr.Read ()) { switch (xtr.NodeType) { case XmlNodeType.Element: string name = xtr.GetAttribute ("name"); ClassValue class_value = classvalues_hashtable [name] as ClassValue; if (class_value == null) { class_value = new ClassValue (); class_value.Name = name; classvalues_hashtable [name] = class_value; } class_value.ReadXml (xtr); break; case XmlNodeType.EndElement: return; } } } public void WriteXml (XmlTextWriter xtw) { if (classvalues_hashtable.Count == 0) return; xtw.WriteStartElement (className); foreach (DictionaryEntry entry in classvalues_hashtable) { ClassValue class_value = entry.Value as ClassValue; class_value.WriteXml (xtw); } xtw.WriteEndElement (); } } internal class ClassValue { private object value; private string name; public string Name { set { name = value; } get { return name; } } public void SetValue (object value) { this.value = value; } public object GetValue () { return value; } public void ReadXml (XmlTextReader xtr) { string type; string single_value; type = xtr.GetAttribute ("type"); if (type == "byte_array" || type.IndexOf ("-array") == -1) { single_value = xtr.ReadString (); if (type == "string") { value = single_value; } else if (type == "int") { value = Int32.Parse (single_value); } else if (type == "byte") { value = Byte.Parse (single_value); } else if (type == "color") { int color = Int32.Parse (single_value); value = Color.FromArgb (color); } else if (type == "byte-array") { byte[] b_array = Convert.FromBase64String (single_value); value = b_array; } } else { ReadXmlArrayValues (xtr, type); } } private void ReadXmlArrayValues (XmlTextReader xtr, string type) { ArrayList al = new ArrayList (); while (xtr.Read ()) { switch (xtr.NodeType) { case XmlNodeType.Element: string single_value = xtr.ReadString (); if (type == "int-array") { int int_val = Int32.Parse (single_value); al.Add (int_val); } else if (type == "string-array") { string str_val = single_value; al.Add (str_val); } break; case XmlNodeType.EndElement: if (xtr.Name == "value") { if (type == "int-array") { value = al.ToArray (typeof(int)); } else if (type == "string-array") { value = al.ToArray (typeof(string)); } return; } break; } } } public void WriteXml (XmlTextWriter xtw) { xtw.WriteStartElement ("value"); xtw.WriteAttributeString ("name", name); if (value is Array) { WriteArrayContent (xtw); } else { WriteSingleContent (xtw); } xtw.WriteEndElement (); } private void WriteSingleContent (XmlTextWriter xtw) { string type_string = String.Empty; if (value is string) type_string = "string"; else if (value is int) type_string = "int"; else if (value is byte) type_string = "byte"; else if (value is Color) type_string = "color"; xtw.WriteAttributeString ("type", type_string); if (value is Color) xtw.WriteString (((Color)value).ToArgb ().ToString ()); else xtw.WriteString (value.ToString ()); } private void WriteArrayContent (XmlTextWriter xtw) { string type_string = String.Empty; string type_name = String.Empty; if (value is string[]) { type_string = "string-array"; type_name = "string"; } else if (value is int[]) { type_string = "int-array"; type_name = "int"; } else if (value is byte[]) { type_string = "byte-array"; type_name = "byte"; } xtw.WriteAttributeString ("type", type_string); if (type_string != "byte-array") { Array array = value as Array; foreach (object o in array) { xtw.WriteStartElement (type_name); xtw.WriteString (o.ToString ()); xtw.WriteEndElement (); } } else { byte[] b_array = value as byte []; xtw.WriteString (Convert.ToBase64String (b_array, 0, b_array.Length)); } } } } } #endregion }