diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 8d0eab92fb..6a818ece7f 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -511,6 +511,10 @@ + + + AsynchronousWaitDialog.cs + Form @@ -679,6 +683,9 @@ + + AsynchronousWaitDialog.cs + diff --git a/src/Main/Base/Project/Src/Gui/Components/StatusBar/SdStatusBar.cs b/src/Main/Base/Project/Src/Gui/Components/StatusBar/SdStatusBar.cs index f44d994ca1..b29bfe2b9a 100644 --- a/src/Main/Base/Project/Src/Gui/Components/StatusBar/SdStatusBar.cs +++ b/src/Main/Base/Project/Src/Gui/Components/StatusBar/SdStatusBar.cs @@ -35,17 +35,6 @@ namespace ICSharpCode.SharpDevelop.Gui } } - bool cancelEnabled; - - public bool CancelEnabled { - get { - return cancelEnabled; - } - set { - cancelEnabled = value; - } - } - public SdStatusBar() { @@ -133,7 +122,7 @@ namespace ICSharpCode.SharpDevelop.Gui // Progress Monitor implementation int totalWork; - public void BeginTask(string name, int totalWork) + public void BeginTask(string name, int totalWork, bool allowCancel) { taskName = name; this.totalWork = totalWork; @@ -203,5 +192,16 @@ namespace ICSharpCode.SharpDevelop.Gui { jobNamePanel.Text = StringParser.Parse(taskName); } + + bool showingDialog; + + public bool ShowingDialog { + get { return showingDialog; } + set { showingDialog = value; } + } + + public bool IsCancelled { + get { return false; } + } } } diff --git a/src/Main/Base/Project/Src/Gui/IProgressMonitor.cs b/src/Main/Base/Project/Src/Gui/IProgressMonitor.cs index 7c2669da63..c2b7411a0f 100644 --- a/src/Main/Base/Project/Src/Gui/IProgressMonitor.cs +++ b/src/Main/Base/Project/Src/Gui/IProgressMonitor.cs @@ -13,25 +13,57 @@ namespace ICSharpCode.SharpDevelop.Gui /// public interface IProgressMonitor { - void BeginTask(string name, int totalWork); + /// + /// Begins a new task with the specified name and total amount of work. + /// + /// Name of the task. Use null to display a default message + /// Total amount of work in work units. Use 0 for unknown amount of work. + /// Specifies whether the task can be cancelled. + void BeginTask(string name, int totalWork, bool allowCancel); + /// + /// Gets/Sets the amount of work already done + /// int WorkDone { get; set; } + /// + /// Marks the current task as Done. + /// void Done(); + /// + /// Gets/Sets the current task name. + /// string TaskName { get; set; } + + /// + /// Gets/sets if the task current shows a modal dialog. Set this property to true to make progress dialogs windows + /// temporarily invisible while your modal dialog is showing. + /// + bool ShowingDialog { + get; + set; + } + + /// + /// Gets whether the user has cancelled the operation. + /// + bool IsCancelled { + get; + } } internal class DummyProgressMonitor : IProgressMonitor { int workDone; string taskName; + bool showingDialog; public int WorkDone { get { return workDone; } @@ -43,7 +75,7 @@ namespace ICSharpCode.SharpDevelop.Gui set { taskName = value; } } - public void BeginTask(string name, int totalWork) + public void BeginTask(string name, int totalWork, bool allowCancel) { taskName = name; workDone = 0; @@ -52,5 +84,14 @@ namespace ICSharpCode.SharpDevelop.Gui public void Done() { } + + public bool IsCancelled { + get { return false; } + } + + public bool ShowingDialog { + get { return showingDialog; } + set { showingDialog = value; } + } } } diff --git a/src/Main/Base/Project/Src/Project/CustomTool.cs b/src/Main/Base/Project/Src/Project/CustomTool.cs index 62626c5661..efbc132fe6 100644 --- a/src/Main/Base/Project/Src/Project/CustomTool.cs +++ b/src/Main/Base/Project/Src/Project/CustomTool.cs @@ -183,6 +183,9 @@ namespace ICSharpCode.SharpDevelop.Project }); } + /// + /// Gets/Sets the progress monitor this tool can report progress to. This property can never be null. + /// public IProgressMonitor ProgressMonitor { get { return progressMonitor; } set { diff --git a/src/Main/Base/Project/Src/Services/ParserService/DomHostCallback.cs b/src/Main/Base/Project/Src/Services/ParserService/DomHostCallback.cs index 811ce94f56..a2608f87a0 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/DomHostCallback.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/DomHostCallback.cs @@ -34,7 +34,7 @@ namespace ICSharpCode.SharpDevelop HostCallback.BeginAssemblyLoad = delegate(string shortName) { StatusBarService.ProgressMonitor.BeginTask( StringParser.Parse("${res:ICSharpCode.SharpDevelop.LoadingFile}", new string[,] {{"Filename", shortName}}), - 100 + 100, false ); }; HostCallback.FinishAssemblyLoad = StatusBarService.ProgressMonitor.Done; diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index 1ad06a9231..b4db1011ed 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -184,7 +184,7 @@ namespace ICSharpCode.SharpDevelop MessageService.ShowError(e, "Error while initializing project references:" + newContent); } } - StatusBarService.ProgressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount); + StatusBarService.ProgressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount, false); foreach (ParseProjectContent newContent in createdContents) { if (abortLoadSolutionProjectsThread) break; try { @@ -200,7 +200,7 @@ namespace ICSharpCode.SharpDevelop { ParseProjectContent newContent = (ParseProjectContent)state; newContent.Initialize1(); - StatusBarService.ProgressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", newContent.GetInitializationWorkAmount()); + StatusBarService.ProgressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", newContent.GetInitializationWorkAmount(), false); newContent.Initialize2(); StatusBarService.ProgressMonitor.Done(); } @@ -235,7 +235,7 @@ namespace ICSharpCode.SharpDevelop foreach (ParseProjectContent ppc in reParse2) { workAmount += ppc.GetInitializationWorkAmount(); } - StatusBarService.ProgressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount); + StatusBarService.ProgressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount, false); } parsing = true; job = reParse2.Dequeue(); diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs b/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs index 2b4b91041f..8f79d4777d 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs @@ -27,7 +27,10 @@ namespace ICSharpCode.SharpDevelop.Refactoring string newName = MessageService.ShowInputBox("${res:SharpDevelop.Refactoring.Rename}", "${res:SharpDevelop.Refactoring.RenameClassText}", c.Name); if (!FindReferencesAndRenameHelper.CheckName(newName, c.Name)) return; - RenameClass(c, newName); + using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("${res:SharpDevelop.Refactoring.Rename}")) + { + RenameClass(c, newName); + } } public static void RenameClass(IClass c, string newName) @@ -92,9 +95,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring public static bool RenameMember(IMember member, string newName) { - List list = RefactoringService.FindReferences(member, null); - if (list == null) return false; - FindReferencesAndRenameHelper.RenameReferences(list, newName); + List list; + using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("${res:SharpDevelop.Refactoring.Rename}")) + { + list = RefactoringService.FindReferences(member, monitor); + if (list == null) return false; + FindReferencesAndRenameHelper.RenameReferences(list, newName); + } if (member is IField) { IProperty property = FindProperty((IField)member); @@ -102,9 +109,12 @@ namespace ICSharpCode.SharpDevelop.Refactoring string newPropertyName = member.DeclaringType.ProjectContent.Language.CodeGenerator.GetPropertyName(newName); if (newPropertyName != newName && newPropertyName != property.Name) { if (MessageService.AskQuestionFormatted("${res:SharpDevelop.Refactoring.Rename}", "${res:SharpDevelop.Refactoring.RenameFieldAndProperty}", property.FullyQualifiedName, newPropertyName)) { - list = RefactoringService.FindReferences(property, null); - if (list != null) { - FindReferencesAndRenameHelper.RenameReferences(list, newPropertyName); + using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("${res:SharpDevelop.Refactoring.Rename}")) + { + list = RefactoringService.FindReferences(property, monitor); + if (list != null) { + FindReferencesAndRenameHelper.RenameReferences(list, newPropertyName); + } } } } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs index c75104e80b..248e5fc399 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs @@ -126,7 +126,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring IProgressMonitor progressMonitor) { if (ParserService.LoadSolutionProjectsThreadRunning) { + progressMonitor.ShowingDialog = true; MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}"); + progressMonitor.ShowingDialog = false; return null; } List files; @@ -141,7 +143,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring List references = new List(); try { if (progressMonitor != null) { - progressMonitor.BeginTask("${res:SharpDevelop.Refactoring.FindingReferences}", files.Count); + progressMonitor.BeginTask("${res:SharpDevelop.Refactoring.FindingReferences}", files.Count, true); } #if DEBUG if (System.Windows.Forms.Control.ModifierKeys == System.Windows.Forms.Keys.Control) { @@ -151,6 +153,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring while (enumerator.MoveNext()) { if (progressMonitor != null) { progressMonitor.WorkDone = enumerator.Index; + if (progressMonitor.IsCancelled) { + return null; + } } AddReferences(references, ownerClass, member, isLocal, enumerator.CurrentFileName, enumerator.CurrentFileContent); diff --git a/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs b/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs index 61b4126dbd..e262cab971 100644 --- a/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs +++ b/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs @@ -48,16 +48,6 @@ namespace ICSharpCode.SharpDevelop } } - public static bool CancelEnabled { - get { - return statusBar != null && statusBar.CancelEnabled; - } - set { - System.Diagnostics.Debug.Assert(statusBar != null); - statusBar.CancelEnabled = value; - } - } - public static void SetCaretPosition(int x, int y, int charOffset) { statusBar.CursorStatusBarPanel.Text = StringParser.Parse("${res:StatusBarService.CursorStatusBarPanelText}", diff --git a/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs b/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs index 01039acc9c..a6395e0027 100644 --- a/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs +++ b/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs @@ -270,8 +270,14 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands { MenuCommand item = (MenuCommand)sender; IClass c = (IClass)item.Tag; - FindReferencesAndRenameHelper.ShowAsSearchResults(StringParser.Parse("${res:SharpDevelop.Refactoring.ReferencesTo}", new string[,] {{ "Name", c.Name }}), - RefactoringService.FindReferences(c, null)); + using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("${res:SharpDevelop.Refactoring.FindReferencesCommand}")) + { + FindReferencesAndRenameHelper.ShowAsSearchResults( + StringParser.Parse("${res:SharpDevelop.Refactoring.ReferencesTo}", + new string[,] {{ "Name", c.Name }}), + RefactoringService.FindReferences(c, monitor) + ); + } } } } diff --git a/src/Main/Base/Project/Src/TextEditor/Commands/ClassMemberMenuBuilder.cs b/src/Main/Base/Project/Src/TextEditor/Commands/ClassMemberMenuBuilder.cs index 1abd1dd8e5..b61a68ef2d 100644 --- a/src/Main/Base/Project/Src/TextEditor/Commands/ClassMemberMenuBuilder.cs +++ b/src/Main/Base/Project/Src/TextEditor/Commands/ClassMemberMenuBuilder.cs @@ -202,7 +202,11 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands } else { memberName = member.Name; } - FindReferencesAndRenameHelper.ShowAsSearchResults("References to " + memberName, RefactoringService.FindReferences(member, null)); + using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("${res:SharpDevelop.Refactoring.FindReferencesCommand}")) + { + FindReferencesAndRenameHelper.ShowAsSearchResults("References to " + memberName, + RefactoringService.FindReferences(member, monitor)); + } } } } diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Dialogs/GotoDialog.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Dialogs/GotoDialog.cs index bbe9ff4123..13cf4bef24 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Dialogs/GotoDialog.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Dialogs/GotoDialog.cs @@ -122,21 +122,25 @@ namespace ICSharpCode.SharpDevelop.Gui base.OnClosed(e); } - Hashtable visibleEntries = new Hashtable(); + Dictionary visibleEntries = new Dictionary(); double bestPriority; ListViewItem bestItem; void TextBoxTextChanged(object sender, EventArgs e) { string text = textBox.Text.Trim(); + listView.BeginUpdate(); listView.Items.Clear(); visibleEntries.Clear(); bestItem = null; - if (text.Length == 0) + if (text.Length == 0) { + listView.EndUpdate(); return; - if (text.Length == 1 && !char.IsDigit(text, 0)) + } + if (text.Length == 1 && !char.IsDigit(text, 0)) { + listView.EndUpdate(); return; - listView.BeginUpdate(); + } int dotPos = text.IndexOf('.'); int commaPos = text.IndexOf(','); if (commaPos < 0) { diff --git a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.Designer.cs b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.Designer.cs index 4ec2187243..f48d2ed865 100644 --- a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.Designer.cs +++ b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.Designer.cs @@ -6,7 +6,7 @@ // namespace SearchAndReplace { - partial class AsynchronousWaitDialog : System.Windows.Forms.Form + partial class AsynchronousWaitDialogForm : System.Windows.Forms.Form { /// /// Designer variable used to keep track of non-visual components. @@ -34,41 +34,43 @@ namespace SearchAndReplace /// private void InitializeComponent() { - this.label1 = new System.Windows.Forms.Label(); - this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.taskLabel = new System.Windows.Forms.Label(); + this.progressBar = new System.Windows.Forms.ProgressBar(); this.SuspendLayout(); // - // label1 + // taskLabel // - this.label1.Location = new System.Drawing.Point(93, 23); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(100, 23); - this.label1.TabIndex = 0; - this.label1.Text = "Please wait..."; + this.taskLabel.Location = new System.Drawing.Point(12, 9); + this.taskLabel.Name = "taskLabel"; + this.taskLabel.Size = new System.Drawing.Size(311, 46); + this.taskLabel.TabIndex = 0; + this.taskLabel.Text = "Please wait..."; + this.taskLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // - // progressBar1 + // progressBar // - this.progressBar1.Location = new System.Drawing.Point(12, 49); - this.progressBar1.Name = "progressBar1"; - this.progressBar1.Size = new System.Drawing.Size(264, 23); - this.progressBar1.Style = System.Windows.Forms.ProgressBarStyle.Marquee; - this.progressBar1.TabIndex = 1; + this.progressBar.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.progressBar.Location = new System.Drawing.Point(12, 58); + this.progressBar.Name = "progressBar"; + this.progressBar.Size = new System.Drawing.Size(311, 27); + this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Marquee; + this.progressBar.TabIndex = 1; // - // AsynchronousWaitDialog + // AsynchronousWaitDialogForm // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(288, 84); + this.ClientSize = new System.Drawing.Size(336, 97); this.ControlBox = false; - this.Controls.Add(this.progressBar1); - this.Controls.Add(this.label1); + this.Controls.Add(this.progressBar); + this.Controls.Add(this.taskLabel); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.Name = "AsynchronousWaitDialog"; + this.Name = "AsynchronousWaitDialogForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "AsynchronousWaitDialog"; this.ResumeLayout(false); } - private System.Windows.Forms.ProgressBar progressBar1; - private System.Windows.Forms.Label label1; + internal System.Windows.Forms.ProgressBar progressBar; + internal System.Windows.Forms.Label taskLabel; } } diff --git a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.cs b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.cs index bde781564d..f57bafc5fe 100644 --- a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.cs +++ b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.cs @@ -9,64 +9,236 @@ using System; using System.Drawing; using System.Threading; using System.Windows.Forms; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.Core; namespace SearchAndReplace { + internal sealed partial class AsynchronousWaitDialogForm + { + internal AsynchronousWaitDialogForm() + { + InitializeComponent(); + } + } + /// - /// Shows an wait dialog on a separate thread if the action takes longer than 200ms. + /// Shows an wait dialog on a separate thread if the action takes longer than 500ms. /// Usage: - /// using (AsynchronousWaitDialog.ShowWaitDialog()) { + /// using (AsynchronousWaitDialog.ShowWaitDialog("title")) { /// long_running_action(); /// } + /// or: + /// using (IProgressMonitor monitor = AsynchronousWaitDialog.ShowWaitDialog("title")) { + /// long_running_action(monitor); + /// } /// - public sealed partial class AsynchronousWaitDialog + public sealed class AsynchronousWaitDialog : IProgressMonitor, IDisposable { - class WaitHandle : IDisposable + /// + /// Delay until the wait dialog becomes visible, in ms. + /// + public const int ShowWaitDialogDelay = 500; + + bool disposed; + AsynchronousWaitDialogForm dlg; + object lockObject = new object(); + volatile int totalWork; + volatile string titleName; + volatile string taskName; + volatile int workDone; + + /// + /// Shows a wait dialog. + /// + /// Title of the wait dialog + /// Name of the current task + /// WaitHandle object - you can use it to access the wait dialog's properties. + /// To close the wait dialog, call Dispose() on the WaitHandle + public static AsynchronousWaitDialog ShowWaitDialog(string titleName) { - bool disposed; - AsynchronousWaitDialog dlg; + if (titleName == null) + throw new ArgumentNullException("titleName"); + AsynchronousWaitDialog h = new AsynchronousWaitDialog(titleName); + h.Start(); + return h; + } + + private AsynchronousWaitDialog(string titleName) + { + this.titleName = titleName; + Done(); // set default values for titleName + } + + #region Start waiting thread + /// + /// Start waiting thread + /// + internal void Start() + { + Thread newThread = new Thread(Run); + newThread.Name = "AsynchronousWaitDialog thread"; + newThread.Start(); - [STAThread] - public void Run() - { - Thread.Sleep(500); - lock (this) { - if (disposed) - return; - dlg = new AsynchronousWaitDialog(); - dlg.CreateControl(); - } + Thread.Sleep(0); // allow new thread to start + } + + [STAThread] + void Run() + { + Thread.Sleep(ShowWaitDialogDelay); + lock (lockObject) { + if (disposed) + return; + dlg = new AsynchronousWaitDialogForm(); + dlg.Text = StringParser.Parse(titleName); + UpdateTask(); + dlg.CreateControl(); + IntPtr h = dlg.Handle; // force handle creation + } + if (showingDialog) { + Application.Run(); + } else { Application.Run(dlg); } - - public void Dispose() - { - lock (this) { - disposed = true; - if (dlg != null) { - dlg.BeginInvoke(new MethodInvoker(dlg.Close)); + } + #endregion + + /// + /// Closes the wait dialog. + /// + public void Dispose() + { + lock (lockObject) { + if (disposed) return; + disposed = true; + if (dlg != null) { + dlg.BeginInvoke(new MethodInvoker(DisposeInvoked)); + } + } + } + + void DisposeInvoked() + { + dlg.Dispose(); + Application.ExitThread(); + } + + public int WorkDone { + get { + return workDone; + } + set { + if (workDone != value) { + lock (lockObject) { + workDone = value; + if (dlg != null && disposed == false) { + dlg.BeginInvoke(new MethodInvoker(UpdateProgress)); + } + } + } + } + } + + public string TaskName { + get { + lock (lockObject) { + return taskName; + } + } + set { + if (taskName != value) { + lock (lockObject) { + taskName = value; + if (dlg != null && disposed == false) { + dlg.BeginInvoke(new MethodInvoker(UpdateTask)); + } } } } } - public static IDisposable ShowWaitDialog() + /// + /// Begins a new task with the specified name and total amount of work. + /// + /// Name of the task. Use null to display "please wait..." message + /// Total amount of work in work units. Use 0 for unknown amount of work. + public void BeginTask(string name, int totalWork, bool allowCancel) { - WaitHandle h = new WaitHandle(); - Thread thread = new Thread(h.Run); - thread.Name = "AsynchronousWaitDialog thread"; - thread.Start(); + if (name == null) + name = "${res:Global.PleaseWait}"; + if (totalWork < 0) + totalWork = 0; - Thread.Sleep(0); // allow new thread to start - return h; + lock (lockObject) { + this.totalWork = totalWork; + this.taskName = name; + if (dlg != null && disposed == false) { + dlg.BeginInvoke(new MethodInvoker(UpdateTask)); + } + } } - private AsynchronousWaitDialog() + /// + /// Resets the task to a generic "please wait" with marquee progress bar. + /// + public void Done() { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); + workDone = 0; + BeginTask(null, 0, false); + } + + void UpdateTask() + { + int totalWork = this.totalWork; + + dlg.taskLabel.Text = StringParser.Parse(taskName); + + if (totalWork > 0) { + if (dlg.progressBar.Value > totalWork) { + dlg.progressBar.Value = 0; + } + dlg.progressBar.Maximum = totalWork + 1; + dlg.progressBar.Style = ProgressBarStyle.Continuous; + } else { + dlg.progressBar.Style = ProgressBarStyle.Marquee; + } + UpdateProgress(); + } + + void UpdateProgress() + { + int workDone = this.workDone; + if (workDone < 0) workDone = 0; + if (workDone > dlg.progressBar.Maximum) + workDone = dlg.progressBar.Maximum; + dlg.progressBar.Value = workDone; + } + + bool showingDialog; + + public bool ShowingDialog { + get { return showingDialog; } + set { + if (showingDialog != value) { + showingDialog = value; + lock (lockObject) { + if (dlg != null && disposed == false) { + if (value) { + dlg.BeginInvoke(new MethodInvoker(dlg.Hide)); + } else { + dlg.BeginInvoke(new MethodInvoker(dlg.Show)); + } + } + } + } + } + } + + public bool IsCancelled { + get { + return false; + } } } } diff --git a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.resx b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.resx new file mode 100644 index 0000000000..7080a7d118 --- /dev/null +++ b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/SearchAndReplacePanel.cs b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/SearchAndReplacePanel.cs index 7d9be38378..01c212c224 100644 --- a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/SearchAndReplacePanel.cs +++ b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/SearchAndReplacePanel.cs @@ -94,7 +94,10 @@ namespace SearchAndReplace FindNextInSelection(); } } else { - SearchReplaceManager.FindNext(); + using (AsynchronousWaitDialog.ShowWaitDialog("Search")) + { + SearchReplaceManager.FindNext(); + } } Focus(); } @@ -107,7 +110,10 @@ namespace SearchAndReplace RunAllInSelection(0); } } else { - SearchInFilesManager.FindAll(); + using (AsynchronousWaitDialog.ShowWaitDialog("Search")) + { + SearchInFilesManager.FindAll(); + } } } @@ -119,7 +125,10 @@ namespace SearchAndReplace RunAllInSelection(1); } } else { - SearchReplaceManager.MarkAll(); + using (AsynchronousWaitDialog.ShowWaitDialog("Search")) + { + SearchReplaceManager.MarkAll(); + } } } @@ -131,7 +140,10 @@ namespace SearchAndReplace RunAllInSelection(2); } } else { - SearchReplaceManager.ReplaceAll(); + using (AsynchronousWaitDialog.ShowWaitDialog("Search")) + { + SearchReplaceManager.ReplaceAll(); + } } } @@ -143,7 +155,10 @@ namespace SearchAndReplace ReplaceInSelection(); } } else { - SearchReplaceManager.Replace(); + using (AsynchronousWaitDialog.ShowWaitDialog("Search")) + { + SearchReplaceManager.Replace(); + } } Focus(); } @@ -440,7 +455,7 @@ namespace SearchAndReplace } /// - /// Enables the various find, bookmark and replace buttons + /// Enables the various find, bookmark and replace buttons /// depending on whether any find string has been entered. The buttons /// are disabled otherwise. /// diff --git a/src/Main/Core/Project/Src/AddInTree/AddIn/Codon.cs b/src/Main/Core/Project/Src/AddInTree/AddIn/Codon.cs index 39f77dac0d..b3614a674b 100644 --- a/src/Main/Core/Project/Src/AddInTree/AddIn/Codon.cs +++ b/src/Main/Core/Project/Src/AddInTree/AddIn/Codon.cs @@ -104,18 +104,17 @@ namespace ICSharpCode.Core // public object BuildItem(object owner, ArrayList subItems) { - try { - IDoozer doozer = AddInTree.Doozers[Name]; - if (!doozer.HandleConditions && conditions.Length > 0) { - ConditionFailedAction action = GetFailedAction(owner); - if (action != ConditionFailedAction.Nothing) { - return null; - } - } - return doozer.BuildItem(owner, this, subItems); - } catch (KeyNotFoundException) { + IDoozer doozer; + if (!AddInTree.Doozers.TryGetValue(Name, out doozer)) throw new CoreException("Doozer " + Name + " not found!"); + + if (!doozer.HandleConditions && conditions.Length > 0) { + ConditionFailedAction action = GetFailedAction(owner); + if (action != ConditionFailedAction.Nothing) { + return null; + } } + return doozer.BuildItem(owner, this, subItems); } public override string ToString()