namespace SolutionOpen { using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Text.RegularExpressions; using System.Windows.Forms; using EnvDTE; using EnvDTE80; using Microsoft.Win32; public class MyTextBox : System.Windows.Forms.TextBox { protected override bool IsInputKey(Keys keyData) { if (keyData.Equals(System.Windows.Forms.Keys.Down) || keyData.Equals(System.Windows.Forms.Keys.Escape)) return true; return base.IsInputKey(keyData); } } public class MyNumericTextBox : System.Windows.Forms.TextBox { protected override void OnKeyPress(KeyPressEventArgs e) { base.OnKeyPress(e); if (!Char.IsDigit(e.KeyChar) && e.KeyChar != '\b') e.Handled = true; } } public class MyListView : System.Windows.Forms.ListView { protected override bool IsInputKey(Keys keyData) { if (keyData.Equals(System.Windows.Forms.Keys.Escape)) return true; return base.IsInputKey(keyData); } } partial class ChooseFile { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } private void Abort() { SaveToRegistry(); DialogResult = DialogResult.Abort; Close(); } private void Accept() { SaveToRegistry(); DialogResult = DialogResult.OK; Close(); } private void LoadFromRegistry() { RegistryKey key = Registry.CurrentUser.OpenSubKey(registryKeyName); if (key != null) { object value = key.GetValue(lastSearchRegistryValueName); if (value != null) { string text = value as string; if (text != null) searchTokens.Text = text; } value = key.GetValue(displayLimitRegistryValueName); if (value != null) { string text = value as string; if (text != null) displayLimit.Text = text; } } } private void SaveToRegistry() { RegistryKey key = Registry.CurrentUser.CreateSubKey(registryKeyName); if (key != null) { key.SetValue(lastSearchRegistryValueName, searchTokens.Text); key.SetValue(displayLimitRegistryValueName, displayLimit.Text); } } private void searchTokens_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) { if (e.KeyData.Equals(System.Windows.Forms.Keys.Down)) { e.Handled = true; matchingFiles.Focus(); } else if (e.KeyData.Equals(System.Windows.Forms.Keys.Enter)) { e.Handled = true; Accept(); } else if (e.KeyData.Equals(System.Windows.Forms.Keys.Escape)) { e.Handled = true; Abort(); } } private void searchTokens_TextChanged(object sender, EventArgs e) { RebuildListViewItems(); } private void displayLimit_TextChanged(object sender, EventArgs e) { RebuildListViewItems(); } private void RebuildListViewItems() { // build the patterns to match against string text = searchTokens.Text.ToLower(); string []tokens = text.Split(' '); List<Regex> regularExpressions = new List<Regex>(); foreach (string token in tokens) { if (token != "") regularExpressions.Add(new System.Text.RegularExpressions.Regex(token)); } // build the list of items to add List<ListViewItem> newItems = new List<ListViewItem>(); foreach (string pathName in pathNames.Values) { int slash = pathName.LastIndexOf('\\'); if (slash > 0) { // separate the file name and the path string fileNameMixedCase = pathName.Substring(slash + 1); string fileNameLowerCase = fileNameMixedCase.ToLower(); string path = pathName.Substring(0, slash); // validate this file matches all search parameters bool pass = true; foreach (Regex regex in regularExpressions) { if (!regex.IsMatch(fileNameLowerCase)) { pass = false; break; } } // add the item to the list if it passed all the search parameters if (pass) newItems.Add(new ListViewItem(new String[] { fileNameMixedCase, path })); } } matchingFiles.BeginUpdate(); try { matchingFiles.Items.Clear(); matchingFiles.SelectedItems.Clear(); numberOfMatchingFiles.Text = newItems.Count.ToString(); // get the limit int maximum = -1; try { maximum = System.Convert.ToInt32(displayLimit.Text, 10); } catch { } if (maximum < 0 || newItems.Count < maximum) matchingFiles.Items.AddRange(newItems.ToArray()); // auto select the first element if any elements passed the search if (matchingFiles.Items.Count > 0) { matchingFiles.Items[0].Selected = true; matchingFiles.FocusedItem = matchingFiles.Items[0]; } } finally { matchingFiles.EndUpdate(); } } private void listBox1_DoubleClick(object sender, System.EventArgs e) { Accept(); } private void listBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) { if (e.KeyData.Equals(System.Windows.Forms.Keys.Enter)) { e.Handled = true; Accept(); } else if (e.KeyData.Equals(System.Windows.Forms.Keys.Escape)) { e.Handled = true; Abort(); } } private void button1_Click(object sender, System.EventArgs e) { Accept(); } private void button2_Click(object sender, System.EventArgs e) { Abort(); } public void OpenSelectedFiles() { // open all the selected items foreach (ListViewItem item in matchingFiles.SelectedItems) { // recompile the path and file name to get the path name string pathName = ""; foreach (ListViewItem.ListViewSubItem piece in item.SubItems) { if (pathName.Length == 0) { pathName = piece.Text; } else { pathName = piece.Text + "\\" + pathName; } } applicationObject.ItemOperations.OpenFile(pathName, EnvDTE.Constants.vsViewKindPrimary); } } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.searchTokensLabel = new System.Windows.Forms.Label(); this.openButton = new System.Windows.Forms.Button(); this.matchingFilesLabel = new System.Windows.Forms.Label(); this.cancelButton = new System.Windows.Forms.Button(); this.numberOfMatchingFiles = new System.Windows.Forms.TextBox(); this.displayLimitLabel = new System.Windows.Forms.Label(); this.displayLimit = new SolutionOpen.MyNumericTextBox(); this.matchingFiles = new SolutionOpen.MyListView(); this.FileName = new System.Windows.Forms.ColumnHeader(); this.Path = new System.Windows.Forms.ColumnHeader(); this.searchTokens = new SolutionOpen.MyTextBox(); this.SuspendLayout(); // // searchTokensLabel // this.searchTokensLabel.AutoSize = true; this.searchTokensLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; this.searchTokensLabel.Location = new System.Drawing.Point(12, 9); this.searchTokensLabel.Name = "searchTokensLabel"; this.searchTokensLabel.Size = new System.Drawing.Size(134, 13); this.searchTokensLabel.TabIndex = 5; this.searchTokensLabel.Text = "File name to match (regex):"; // // openButton // this.openButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.openButton.Location = new System.Drawing.Point(658, 25); this.openButton.Name = "openButton"; this.openButton.Size = new System.Drawing.Size(69, 22); this.openButton.TabIndex = 2; this.openButton.Text = "Open"; this.openButton.Click += new System.EventHandler(this.button1_Click); // // matchingFilesLabel // this.matchingFilesLabel.AutoSize = true; this.matchingFilesLabel.Location = new System.Drawing.Point(12, 60); this.matchingFilesLabel.Name = "matchingFilesLabel"; this.matchingFilesLabel.Size = new System.Drawing.Size(75, 13); this.matchingFilesLabel.TabIndex = 6; this.matchingFilesLabel.Text = "Matching files:"; // // cancelButton // this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.cancelButton.Location = new System.Drawing.Point(658, 53); this.cancelButton.Name = "cancelButton"; this.cancelButton.Size = new System.Drawing.Size(69, 22); this.cancelButton.TabIndex = 3; this.cancelButton.Text = "Cancel"; this.cancelButton.Click += new System.EventHandler(this.button2_Click); // // numberOfMatchingFiles // this.numberOfMatchingFiles.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.numberOfMatchingFiles.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.numberOfMatchingFiles.Location = new System.Drawing.Point(93, 55); this.numberOfMatchingFiles.Name = "numberOfMatchingFiles"; this.numberOfMatchingFiles.ReadOnly = true; this.numberOfMatchingFiles.Size = new System.Drawing.Size(61, 22); this.numberOfMatchingFiles.TabIndex = 7; this.numberOfMatchingFiles.TabStop = false; // // displayLimitLabel // this.displayLimitLabel.AutoSize = true; this.displayLimitLabel.Location = new System.Drawing.Point(193, 60); this.displayLimitLabel.Name = "displayLimitLabel"; this.displayLimitLabel.Size = new System.Drawing.Size(64, 13); this.displayLimitLabel.TabIndex = 8; this.displayLimitLabel.Text = "Display limit:"; // // displayLimit // this.displayLimit.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.displayLimit.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.displayLimit.Location = new System.Drawing.Point(265, 55); this.displayLimit.MaxLength = 6; this.displayLimit.Name = "displayLimit"; this.displayLimit.Size = new System.Drawing.Size(61, 22); this.displayLimit.TabIndex = 4; this.displayLimit.TextChanged += new System.EventHandler(this.displayLimit_TextChanged); // // matchingFiles // this.matchingFiles.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.matchingFiles.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.FileName, this.Path}); this.matchingFiles.FullRowSelect = true; this.matchingFiles.GridLines = true; this.matchingFiles.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; this.matchingFiles.HideSelection = false; this.matchingFiles.Location = new System.Drawing.Point(12, 82); this.matchingFiles.Name = "matchingFiles"; this.matchingFiles.Size = new System.Drawing.Size(715, 273); this.matchingFiles.Sorting = System.Windows.Forms.SortOrder.Ascending; this.matchingFiles.TabIndex = 1; this.matchingFiles.UseCompatibleStateImageBehavior = false; this.matchingFiles.View = System.Windows.Forms.View.Details; this.matchingFiles.DoubleClick += new System.EventHandler(this.listBox1_DoubleClick); this.matchingFiles.KeyDown += new System.Windows.Forms.KeyEventHandler(this.listBox1_KeyDown); // // FileName // this.FileName.Text = "File Name"; this.FileName.Width = 275; // // Path // this.Path.Text = "Path"; this.Path.Width = 408; // // searchTokens // this.searchTokens.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.searchTokens.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.searchTokens.Location = new System.Drawing.Point(12, 25); this.searchTokens.Name = "searchTokens"; this.searchTokens.Size = new System.Drawing.Size(631, 22); this.searchTokens.TabIndex = 0; this.searchTokens.TextChanged += new System.EventHandler(this.searchTokens_TextChanged); this.searchTokens.KeyDown += new System.Windows.Forms.KeyEventHandler(this.searchTokens_KeyDown); // // ChooseFile // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(740, 367); this.Controls.Add(this.displayLimit); this.Controls.Add(this.displayLimitLabel); this.Controls.Add(this.numberOfMatchingFiles); this.Controls.Add(this.cancelButton); this.Controls.Add(this.matchingFiles); this.Controls.Add(this.matchingFilesLabel); this.Controls.Add(this.openButton); this.Controls.Add(this.searchTokensLabel); this.Controls.Add(this.searchTokens); this.Name = "ChooseFile"; this.Text = "SolutionOpen"; this.ResumeLayout(false); this.PerformLayout(); } #endregion #region Member Variables private MyTextBox searchTokens; private System.Windows.Forms.Label searchTokensLabel; private System.Windows.Forms.Button openButton; private System.Windows.Forms.Button cancelButton; private System.Windows.Forms.Label matchingFilesLabel; private Label displayLimitLabel; private TextBox numberOfMatchingFiles; private MyNumericTextBox displayLimit; private MyListView matchingFiles; private System.Windows.Forms.ColumnHeader FileName; private System.Windows.Forms.ColumnHeader Path; private StringDictionary pathNames; private DTE2 applicationObject; private readonly static String registryKeyName = "Software\\JeffGrills\\SolutionOpen"; private readonly static String lastSearchRegistryValueName = "LastSearch"; private readonly static String displayLimitRegistryValueName = "DisplayLimit"; #endregion } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#7 | 6274 | Jeff Grills |
Fix minor bug when a solution contains the same source file in multiple projects. Fix occasional focusing issue with the first element. Properly preserve the case of the file names and paths in the selection window. |
||
#6 | 6273 | Jeff Grills |
Add display limit to alleviate performance problems for very large solutions. Minor code clean up. |
||
#5 | 5230 | Jeff Grills |
Fix bug where the wrong window would have input focus. Bind child windows to the edges so resizing works sensibly. Add release build version of the DLL. |
||
#4 | 5151 | Jeff Grills |
Attempt to get newly opened windows to have the focus, but it didn't work. I think this fix should be corrent, and that it's really a bug in MS' code. I'm going to upgrade to the newest version of the compiler and try again. |
||
#3 | 5150 | Jeff Grills | Preserve and restore the last search contents when the dialog is opened and closed. | ||
#2 | 5043 | Jeff Grills | Make the dialog modal and remove the now-useless semaphore junk | ||
#1 | 5042 | Jeff Grills |
Add first pass of SolutionOpen project, which can open a file listed anywhere within a visual studio solution. This is supposed to be very similar to the WorkspaceWhiz workspace open functionality. |