Browse Source

Show "Please wait..."-dialog during actions that might block the main thread for a long time (search, find references, etc.)

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2059 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
a40a3cee90
  1. 7
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  2. 24
      src/Main/Base/Project/Src/Gui/Components/StatusBar/SdStatusBar.cs
  3. 45
      src/Main/Base/Project/Src/Gui/IProgressMonitor.cs
  4. 3
      src/Main/Base/Project/Src/Project/CustomTool.cs
  5. 2
      src/Main/Base/Project/Src/Services/ParserService/DomHostCallback.cs
  6. 6
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  7. 24
      src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs
  8. 7
      src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs
  9. 10
      src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs
  10. 10
      src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs
  11. 6
      src/Main/Base/Project/Src/TextEditor/Commands/ClassMemberMenuBuilder.cs
  12. 12
      src/Main/Base/Project/Src/TextEditor/Gui/Dialogs/GotoDialog.cs
  13. 50
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.Designer.cs
  14. 242
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.cs
  15. 120
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.resx
  16. 27
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/SearchAndReplacePanel.cs
  17. 19
      src/Main/Core/Project/Src/AddInTree/AddIn/Codon.cs

7
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -511,6 +511,10 @@ @@ -511,6 +511,10 @@
<Compile Include="Src\TextEditor\SearchAndReplace\Engine\SearchReplaceInFilesManager.cs" />
<Compile Include="Src\TextEditor\SearchAndReplace\Engine\SearchReplaceManager.cs" />
<Compile Include="Src\TextEditor\SearchAndReplace\Engine\SearchReplaceUtilities.cs" />
<Compile Include="Src\TextEditor\SearchAndReplace\Gui\AsynchronousWaitDialog.cs" />
<Compile Include="Src\TextEditor\SearchAndReplace\Gui\AsynchronousWaitDialog.Designer.cs">
<DependentUpon>AsynchronousWaitDialog.cs</DependentUpon>
</Compile>
<Compile Include="Src\TextEditor\SearchAndReplace\Gui\SearchAndReplaceDialog.cs">
<SubType>Form</SubType>
</Compile>
@ -679,6 +683,9 @@ @@ -679,6 +683,9 @@
<Compile Include="Src\TextEditor\Gui\Editor\IncrementalSearch.cs" />
<EmbeddedResource Include="Resources\IncrementalSearchCursor.cur" />
<EmbeddedResource Include="Resources\ReverseIncrementalSearchCursor.cur" />
<EmbeddedResource Include="Src\TextEditor\SearchAndReplace\Gui\AsynchronousWaitDialog.resx">
<DependentUpon>AsynchronousWaitDialog.cs</DependentUpon>
</EmbeddedResource>
<Compile Include="Src\Gui\Dialogs\SharpDevelopColorDialog.cs" />
<Compile Include="Src\Util\Linq.cs" />
<Compile Include="Src\Util\DebugTimer.cs" />

24
src/Main/Base/Project/Src/Gui/Components/StatusBar/SdStatusBar.cs

@ -35,17 +35,6 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -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 @@ -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 @@ -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; }
}
}
}

45
src/Main/Base/Project/Src/Gui/IProgressMonitor.cs

@ -13,25 +13,57 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -13,25 +13,57 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public interface IProgressMonitor
{
void BeginTask(string name, int totalWork);
/// <summary>
/// Begins a new task with the specified name and total amount of work.
/// </summary>
/// <param name="name">Name of the task. Use null to display a default message</param>
/// <param name="totalWork">Total amount of work in work units. Use 0 for unknown amount of work.</param>
/// <param name="allowCancel">Specifies whether the task can be cancelled.</param>
void BeginTask(string name, int totalWork, bool allowCancel);
/// <summary>
/// Gets/Sets the amount of work already done
/// </summary>
int WorkDone {
get;
set;
}
/// <summary>
/// Marks the current task as Done.
/// </summary>
void Done();
/// <summary>
/// Gets/Sets the current task name.
/// </summary>
string TaskName {
get;
set;
}
/// <summary>
/// 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.
/// </summary>
bool ShowingDialog {
get;
set;
}
/// <summary>
/// Gets whether the user has cancelled the operation.
/// </summary>
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 @@ -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 @@ -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; }
}
}
}

3
src/Main/Base/Project/Src/Project/CustomTool.cs

@ -183,6 +183,9 @@ namespace ICSharpCode.SharpDevelop.Project @@ -183,6 +183,9 @@ namespace ICSharpCode.SharpDevelop.Project
});
}
/// <summary>
/// Gets/Sets the progress monitor this tool can report progress to. This property can never be null.
/// </summary>
public IProgressMonitor ProgressMonitor {
get { return progressMonitor; }
set {

2
src/Main/Base/Project/Src/Services/ParserService/DomHostCallback.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.SharpDevelop @@ -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;

6
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -184,7 +184,7 @@ namespace ICSharpCode.SharpDevelop @@ -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 @@ -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 @@ -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();

24
src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs

@ -27,7 +27,10 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -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 @@ -92,9 +95,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public static bool RenameMember(IMember member, string newName)
{
List<Reference> list = RefactoringService.FindReferences(member, null);
if (list == null) return false;
FindReferencesAndRenameHelper.RenameReferences(list, newName);
List<Reference> 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 @@ -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);
}
}
}
}

7
src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs

@ -126,7 +126,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -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<ProjectItem> files;
@ -141,7 +143,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -141,7 +143,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
List<Reference> references = new List<Reference>();
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 @@ -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);

10
src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs

@ -48,16 +48,6 @@ namespace ICSharpCode.SharpDevelop @@ -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}",

10
src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs

@ -270,8 +270,14 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands @@ -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)
);
}
}
}
}

6
src/Main/Base/Project/Src/TextEditor/Commands/ClassMemberMenuBuilder.cs

@ -202,7 +202,11 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands @@ -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));
}
}
}
}

12
src/Main/Base/Project/Src/TextEditor/Gui/Dialogs/GotoDialog.cs

@ -122,21 +122,25 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -122,21 +122,25 @@ namespace ICSharpCode.SharpDevelop.Gui
base.OnClosed(e);
}
Hashtable visibleEntries = new Hashtable();
Dictionary<string, object> visibleEntries = new Dictionary<string, object>();
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) {

50
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.Designer.cs generated

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
// </file>
namespace SearchAndReplace
{
partial class AsynchronousWaitDialog : System.Windows.Forms.Form
partial class AsynchronousWaitDialogForm : System.Windows.Forms.Form
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
@ -34,41 +34,43 @@ namespace SearchAndReplace @@ -34,41 +34,43 @@ namespace SearchAndReplace
/// </summary>
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;
}
}

242
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.cs

@ -9,64 +9,236 @@ using System; @@ -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();
}
}
/// <summary>
/// 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);
/// }
/// </summary>
public sealed partial class AsynchronousWaitDialog
public sealed class AsynchronousWaitDialog : IProgressMonitor, IDisposable
{
class WaitHandle : IDisposable
/// <summary>
/// Delay until the wait dialog becomes visible, in ms.
/// </summary>
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;
/// <summary>
/// Shows a wait dialog.
/// </summary>
/// <param name="titleName">Title of the wait dialog</param>
/// <param name="taskName">Name of the current task</param>
/// <returns>WaitHandle object - you can use it to access the wait dialog's properties.
/// To close the wait dialog, call Dispose() on the WaitHandle</returns>
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
/// <summary>
/// Start waiting thread
/// </summary>
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
/// <summary>
/// Closes the wait dialog.
/// </summary>
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()
/// <summary>
/// Begins a new task with the specified name and total amount of work.
/// </summary>
/// <param name="name">Name of the task. Use null to display "please wait..." message</param>
/// <param name="totalWork">Total amount of work in work units. Use 0 for unknown amount of work.</param>
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()
/// <summary>
/// Resets the task to a generic "please wait" with marquee progress bar.
/// </summary>
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;
}
}
}
}

120
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/AsynchronousWaitDialog.resx

@ -0,0 +1,120 @@ @@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

27
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/SearchAndReplacePanel.cs

@ -94,7 +94,10 @@ namespace SearchAndReplace @@ -94,7 +94,10 @@ namespace SearchAndReplace
FindNextInSelection();
}
} else {
SearchReplaceManager.FindNext();
using (AsynchronousWaitDialog.ShowWaitDialog("Search"))
{
SearchReplaceManager.FindNext();
}
}
Focus();
}
@ -107,7 +110,10 @@ namespace SearchAndReplace @@ -107,7 +110,10 @@ namespace SearchAndReplace
RunAllInSelection(0);
}
} else {
SearchInFilesManager.FindAll();
using (AsynchronousWaitDialog.ShowWaitDialog("Search"))
{
SearchInFilesManager.FindAll();
}
}
}
@ -119,7 +125,10 @@ namespace SearchAndReplace @@ -119,7 +125,10 @@ namespace SearchAndReplace
RunAllInSelection(1);
}
} else {
SearchReplaceManager.MarkAll();
using (AsynchronousWaitDialog.ShowWaitDialog("Search"))
{
SearchReplaceManager.MarkAll();
}
}
}
@ -131,7 +140,10 @@ namespace SearchAndReplace @@ -131,7 +140,10 @@ namespace SearchAndReplace
RunAllInSelection(2);
}
} else {
SearchReplaceManager.ReplaceAll();
using (AsynchronousWaitDialog.ShowWaitDialog("Search"))
{
SearchReplaceManager.ReplaceAll();
}
}
}
@ -143,7 +155,10 @@ namespace SearchAndReplace @@ -143,7 +155,10 @@ namespace SearchAndReplace
ReplaceInSelection();
}
} else {
SearchReplaceManager.Replace();
using (AsynchronousWaitDialog.ShowWaitDialog("Search"))
{
SearchReplaceManager.Replace();
}
}
Focus();
}
@ -440,7 +455,7 @@ namespace SearchAndReplace @@ -440,7 +455,7 @@ namespace SearchAndReplace
}
/// <summary>
/// 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.
/// </summary>

19
src/Main/Core/Project/Src/AddInTree/AddIn/Codon.cs

@ -104,18 +104,17 @@ namespace ICSharpCode.Core @@ -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()

Loading…
Cancel
Save