Browse Source

Show build progress in status bar.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2703 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
180d7d1cf6
  1. 222
      src/Main/Base/Project/Src/Gui/Components/StatusBar/SdStatusBar.cs
  2. 1
      src/Main/Base/Project/Src/Gui/Dialogs/AsynchronousWaitDialog.Designer.cs
  3. 21
      src/Main/Base/Project/Src/Gui/Dialogs/AsynchronousWaitDialog.cs
  4. 16
      src/Main/Base/Project/Src/Gui/IProgressMonitor.cs
  5. 155
      src/Main/Base/Project/Src/Project/BuildEngine.cs
  6. 4
      src/Main/Base/Project/Src/Project/BuildResults.cs
  7. 19
      src/Main/Base/Project/Src/Services/ParserService/DomHostCallback.cs
  8. 6
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  9. 110
      src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs
  10. 6
      src/Main/Base/Project/Src/Util/ExtensionMethods.cs
  11. 1
      src/Main/Core/Project/Src/Services/LoggingService/LoggingService.cs
  12. 10
      src/Main/ICSharpCode.SharpDevelop.BuildWorker/BuildJob.cs
  13. 1
      src/Main/ICSharpCode.SharpDevelop.BuildWorker/ICSharpCode.SharpDevelop.BuildWorker.csproj
  14. 7
      src/Main/ICSharpCode.SharpDevelop.BuildWorker/Program.cs

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

@ -1,7 +1,7 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt"/> // <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/> // <license see="prj:///doc/license.txt"/>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/> // <owner name="Daniel Grunwald"/>
// <version>$Revision$</version> // <version>$Revision$</version>
// </file> // </file>
@ -13,15 +13,15 @@ using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Gui namespace ICSharpCode.SharpDevelop.Gui
{ {
public class SdStatusBar : StatusStrip, IProgressMonitor public class SdStatusBar : StatusStrip
{ {
ToolStripProgressBar statusProgressBar = new ToolStripProgressBar(); ToolStripProgressBar statusProgressBar = new ToolStripProgressBar();
ToolStripStatusLabel jobNamePanel = new ToolStripStatusLabel(); ToolStripStatusLabel jobNamePanel = new ToolStripStatusLabel();
ToolStripStatusLabel txtStatusBarPanel = new ToolStripStatusLabel(); ToolStripStatusLabel txtStatusBarPanel = new ToolStripStatusLabel();
ToolStripStatusLabel cursorStatusBarPanel = new ToolStripStatusLabel(); ToolStripStatusLabel cursorStatusBarPanel = new ToolStripStatusLabel();
ToolStripStatusLabel modeStatusBarPanel = new ToolStripStatusLabel(); ToolStripStatusLabel modeStatusBarPanel = new ToolStripStatusLabel();
ToolStripStatusLabel springLabel = new ToolStripStatusLabel(); ToolStripStatusLabel springLabel = new ToolStripStatusLabel();
public ToolStripStatusLabel CursorStatusBarPanel { public ToolStripStatusLabel CursorStatusBarPanel {
get { get {
@ -38,27 +38,27 @@ namespace ICSharpCode.SharpDevelop.Gui
public SdStatusBar() public SdStatusBar()
{ {
// txtStatusBarPanel.Width = 500; // txtStatusBarPanel.Width = 500;
// txtStatusBarPanel.AutoSize = StatusBarPanelAutoSize.Spring; // txtStatusBarPanel.AutoSize = StatusBarPanelAutoSize.Spring;
// Panels.Add(txtStatusBarPanel); // Panels.Add(txtStatusBarPanel);
// // manager.Add(new StatusBarContributionItem("TextPanel", txtStatusBarPanel)); // // manager.Add(new StatusBarContributionItem("TextPanel", txtStatusBarPanel));
// //
// statusProgressBar.Width = 200; // statusProgressBar.Width = 200;
// statusProgressBar.Height = 14; // statusProgressBar.Height = 14;
// statusProgressBar.Location = new Point(160, 6); // statusProgressBar.Location = new Point(160, 6);
// statusProgressBar.Minimum = 0; // statusProgressBar.Minimum = 0;
// statusProgressBar.Visible = false; // statusProgressBar.Visible = false;
// Controls.Add(statusProgressBar); // Controls.Add(statusProgressBar);
// //
// cursorStatusBarPanel.Width = 200; // cursorStatusBarPanel.Width = 200;
// cursorStatusBarPanel.AutoSize = StatusBarPanelAutoSize.None; // cursorStatusBarPanel.AutoSize = StatusBarPanelAutoSize.None;
// cursorStatusBarPanel.Alignment = HorizontalAlignment.Left; // cursorStatusBarPanel.Alignment = HorizontalAlignment.Left;
// Panels.Add(cursorStatusBarPanel); // Panels.Add(cursorStatusBarPanel);
// //
// modeStatusBarPanel.Width = 44; // modeStatusBarPanel.Width = 44;
// modeStatusBarPanel.AutoSize = StatusBarPanelAutoSize.None; // modeStatusBarPanel.AutoSize = StatusBarPanelAutoSize.None;
// modeStatusBarPanel.Alignment = HorizontalAlignment.Right; // modeStatusBarPanel.Alignment = HorizontalAlignment.Right;
// Panels.Add(modeStatusBarPanel); // Panels.Add(modeStatusBarPanel);
springLabel.Spring = true; springLabel.Spring = true;
cursorStatusBarPanel.AutoSize = false; cursorStatusBarPanel.AutoSize = false;
@ -71,12 +71,6 @@ namespace ICSharpCode.SharpDevelop.Gui
Items.AddRange(new ToolStripItem[] { txtStatusBarPanel, springLabel, jobNamePanel, statusProgressBar, cursorStatusBarPanel, modeStatusBarPanel }); Items.AddRange(new ToolStripItem[] { txtStatusBarPanel, springLabel, jobNamePanel, statusProgressBar, cursorStatusBarPanel, modeStatusBarPanel });
} }
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
UpdateText();
}
public void ShowErrorMessage(string message) public void ShowErrorMessage(string message)
{ {
SetMessage("Error : " + message); SetMessage("Error : " + message);
@ -87,8 +81,6 @@ namespace ICSharpCode.SharpDevelop.Gui
SetMessage(image, "Error : " + message); SetMessage(image, "Error : " + message);
} }
string currentMessage;
public void SetMessage(string message) public void SetMessage(string message)
{ {
SetMessage(message, false); SetMessage(message, false);
@ -96,22 +88,20 @@ namespace ICSharpCode.SharpDevelop.Gui
public void SetMessage(string message, bool highlighted) public void SetMessage(string message, bool highlighted)
{ {
if (highlighted) { Action setMessageAction = delegate {
txtStatusBarPanel.BackColor = SystemColors.Highlight; if (highlighted) {
txtStatusBarPanel.ForeColor = Color.White; txtStatusBarPanel.BackColor = SystemColors.Highlight;
} else if (txtStatusBarPanel.BackColor == SystemColors.Highlight) { txtStatusBarPanel.ForeColor = Color.White;
txtStatusBarPanel.BackColor = SystemColors.Control; } else if (txtStatusBarPanel.BackColor == SystemColors.Highlight) {
txtStatusBarPanel.ForeColor = SystemColors.ControlText; txtStatusBarPanel.BackColor = SystemColors.Control;
} txtStatusBarPanel.ForeColor = SystemColors.ControlText;
}
currentMessage = message; txtStatusBarPanel.Text = message;
if (this.IsHandleCreated) };
BeginInvoke(new MethodInvoker(UpdateText)); if (WorkbenchSingleton.InvokeRequired)
} WorkbenchSingleton.SafeThreadAsyncCall(setMessageAction);
else
void UpdateText() setMessageAction();
{
txtStatusBarPanel.Text = currentMessage;
} }
public void SetMessage(Image image, string message) public void SetMessage(Image image, string message)
@ -119,90 +109,56 @@ namespace ICSharpCode.SharpDevelop.Gui
SetMessage(message); SetMessage(message);
} }
// Progress Monitor implementation // Displaying progress
int totalWork;
public void BeginTask(string name, int totalWork, bool allowCancel)
{
taskName = name;
this.totalWork = totalWork;
this.workDone = 0;
if (this.IsHandleCreated) {
this.BeginInvoke(new MethodInvoker(MakeVisible));
}
}
void MakeVisible()
{
statusProgressBar.Value = 0;
statusProgressBar.Maximum = totalWork;
SetTaskName();
jobNamePanel.Visible = true;
statusProgressBar.Visible = true;
}
void MakeInvisible()
{
// Setting jobNamePanel.Visible = false will also hide the other labels to the right (WinForms Bug?)
jobNamePanel.Text = "";
statusProgressBar.Visible = false;
}
int workDone;
public int WorkDone {
get {
return workDone;
}
set {
if (workDone == value) return;
workDone = value;
this.BeginInvoke(new MethodInvoker(SetWorkDone));
}
}
void SetWorkDone() bool statusProgressBarIsVisible;
{ string currentTaskName;
if (workDone < statusProgressBar.Maximum) {
statusProgressBar.Value = workDone;
}
}
public void Done() public void DisplayProgress(string taskName, int workDone, int totalWork)
{ {
taskName = null; if (taskName == null)
if (this.IsHandleCreated) { taskName = "";
this.BeginInvoke(new MethodInvoker(MakeInvisible)); if (totalWork < 0)
} totalWork = 0;
} if (workDone < 0)
workDone = 0;
string taskName; if (workDone > totalWork)
workDone = totalWork;
public string TaskName {
get { WorkbenchSingleton.SafeThreadAsyncCall(
return taskName; delegate {
} if (!statusProgressBarIsVisible) {
set { statusProgressBar.Visible = true;
if (taskName == value) return; statusProgressBarIsVisible = true;
taskName = value; }
this.BeginInvoke(new MethodInvoker(SetTaskName));
} if (totalWork == 0) {
} statusProgressBar.Style = ProgressBarStyle.Marquee;
} else {
void SetTaskName() statusProgressBar.Style = ProgressBarStyle.Continuous;
if (statusProgressBar.Maximum != totalWork) {
if (statusProgressBar.Value > totalWork)
statusProgressBar.Value = 0;
statusProgressBar.Maximum = totalWork;
}
statusProgressBar.Value = workDone;
}
if (currentTaskName != taskName) {
currentTaskName = taskName;
jobNamePanel.Text = StringParser.Parse(taskName);
}
});
}
public void HideProgress()
{ {
jobNamePanel.Text = StringParser.Parse(taskName); WorkbenchSingleton.SafeThreadAsyncCall(
} delegate {
statusProgressBarIsVisible = false;
bool showingDialog; statusProgressBar.Visible = false;
jobNamePanel.Text = currentTaskName = "";
public bool ShowingDialog { });
get { return showingDialog; }
set { showingDialog = value; }
}
public bool IsCancelled {
get { return false; }
} }
} }
} }

1
src/Main/Base/Project/Src/Gui/Dialogs/AsynchronousWaitDialog.Designer.cs generated

@ -68,7 +68,6 @@ namespace ICSharpCode.SharpDevelop.Gui
this.cancelButton.TabIndex = 2; this.cancelButton.TabIndex = 2;
this.cancelButton.Text = "button1"; this.cancelButton.Text = "button1";
this.cancelButton.UseVisualStyleBackColor = true; this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.Click += new System.EventHandler(this.CancelButtonClick);
// //
// AsynchronousWaitDialogForm // AsynchronousWaitDialogForm
// //

21
src/Main/Base/Project/Src/Gui/Dialogs/AsynchronousWaitDialog.cs

@ -21,11 +21,6 @@ namespace ICSharpCode.SharpDevelop.Gui
InitializeComponent(); InitializeComponent();
cancelButton.Text = ResourceService.GetString("Global.CancelButtonText"); cancelButton.Text = ResourceService.GetString("Global.CancelButtonText");
} }
void CancelButtonClick(object sender, System.EventArgs e)
{
cancelButton.Enabled = false;
}
} }
/// <summary> /// <summary>
@ -100,7 +95,7 @@ namespace ICSharpCode.SharpDevelop.Gui
return; return;
dlg = new AsynchronousWaitDialogForm(); dlg = new AsynchronousWaitDialogForm();
dlg.Text = StringParser.Parse(titleName); dlg.Text = StringParser.Parse(titleName);
dlg.cancelButton.Click += delegate { cancelled = true; }; dlg.cancelButton.Click += CancelButtonClick;
UpdateTask(); UpdateTask();
dlg.CreateControl(); dlg.CreateControl();
IntPtr h = dlg.Handle; // force handle creation IntPtr h = dlg.Handle; // force handle creation
@ -257,10 +252,24 @@ namespace ICSharpCode.SharpDevelop.Gui
} }
} }
void CancelButtonClick(object sender, EventArgs e)
{
dlg.cancelButton.Enabled = false;
if (!cancelled) {
cancelled = true;
EventHandler eh = Cancelled;
if (eh != null) {
eh(this, e);
}
}
}
public bool IsCancelled { public bool IsCancelled {
get { get {
return cancelled; return cancelled;
} }
} }
public event EventHandler Cancelled;
} }
} }

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

@ -1,10 +1,12 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt"/> // <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/> // <license see="prj:///doc/license.txt"/>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/> // <owner name="Daniel Grunwald"/>
// <version>$Revision$</version> // <version>$Revision$</version>
// </file> // </file>
using System;
namespace ICSharpCode.SharpDevelop.Gui namespace ICSharpCode.SharpDevelop.Gui
{ {
/// <summary> /// <summary>
@ -43,8 +45,8 @@ namespace ICSharpCode.SharpDevelop.Gui
} }
/// <summary> /// <summary>
/// Gets/sets if the task current shows a modal dialog. Set this property to true to make progress dialogs windows /// Gets/sets if the task current shows a modal dialog. Set this property to true to make progress
/// temporarily invisible while your modal dialog is showing. /// dialogs windows temporarily invisible while your modal dialog is showing.
/// </summary> /// </summary>
bool ShowingDialog { bool ShowingDialog {
get; get;
@ -57,6 +59,12 @@ namespace ICSharpCode.SharpDevelop.Gui
bool IsCancelled { bool IsCancelled {
get; get;
} }
/// <summary>
/// Occurs when the user cancels the operation.
/// This event could be raised on any thread.
/// </summary>
event EventHandler Cancelled;
} }
internal class DummyProgressMonitor : IProgressMonitor internal class DummyProgressMonitor : IProgressMonitor
@ -93,5 +101,7 @@ namespace ICSharpCode.SharpDevelop.Gui
get { return showingDialog; } get { return showingDialog; }
set { showingDialog = value; } set { showingDialog = value; }
} }
public event EventHandler Cancelled { add { } remove { } }
} }
} }

155
src/Main/Base/Project/Src/Project/BuildEngine.cs

@ -9,6 +9,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.SharpDevelop.Gui;
using System.Text;
namespace ICSharpCode.SharpDevelop.Project namespace ICSharpCode.SharpDevelop.Project
{ {
/// <summary> /// <summary>
@ -20,19 +23,37 @@ namespace ICSharpCode.SharpDevelop.Project
public sealed class BuildEngine public sealed class BuildEngine
{ {
#region Building in the SharpDevelop GUI #region Building in the SharpDevelop GUI
static bool guiBuildRunning; static CancellableProgressMonitor guiBuildProgressMonitor;
public static void BuildInGui(IBuildable project, BuildOptions options) public static void BuildInGui(IBuildable project, BuildOptions options)
{ {
if (guiBuildRunning) { WorkbenchSingleton.DebugAssertMainThread();
if (guiBuildProgressMonitor != null) {
BuildResults results = new BuildResults(); BuildResults results = new BuildResults();
results.Add(new BuildError(null, Core.ResourceService.GetString("MainWindow.CompilerMessages.MSBuildAlreadyRunning"))); results.Add(new BuildError(null, Core.ResourceService.GetString("MainWindow.CompilerMessages.MSBuildAlreadyRunning")));
results.Result = BuildResultCode.MSBuildAlreadyRunning; results.Result = BuildResultCode.MSBuildAlreadyRunning;
options.Callback(results); options.Callback(results);
} else { } else {
guiBuildRunning = true; guiBuildProgressMonitor = new CancellableProgressMonitor(StatusBarService.CreateProgressMonitor());
Gui.WorkbenchSingleton.Workbench.GetPad(typeof(Gui.CompilerMessageView)).BringPadToFront(); Gui.WorkbenchSingleton.Workbench.GetPad(typeof(Gui.CompilerMessageView)).BringPadToFront();
StartBuild(project, options, new MessageViewSink(TaskService.BuildMessageViewCategory)); StartBuild(project, options,
new MessageViewSink(TaskService.BuildMessageViewCategory),
guiBuildProgressMonitor);
}
}
public static bool IsGuiBuildRunning {
get {
WorkbenchSingleton.DebugAssertMainThread();
return guiBuildProgressMonitor != null;
}
}
public static void CancelGuiBuild()
{
WorkbenchSingleton.DebugAssertMainThread();
if (guiBuildProgressMonitor != null) {
guiBuildProgressMonitor.Cancel();
} }
} }
@ -56,13 +77,82 @@ namespace ICSharpCode.SharpDevelop.Project
public void Done(bool success) public void Done(bool success)
{ {
guiBuildRunning = false; WorkbenchSingleton.SafeThreadAsyncCall(delegate { guiBuildProgressMonitor = null; });
}
}
sealed class CancellableProgressMonitor : IProgressMonitor
{
IProgressMonitor baseProgressMonitor;
public CancellableProgressMonitor(IProgressMonitor baseProgressMonitor)
{
this.baseProgressMonitor = baseProgressMonitor;
}
readonly object lockObject = new object();
bool isCancelAllowed;
bool isCancelled;
public bool IsCancelAllowed {
get { return isCancelAllowed; }
}
public bool IsCancelled {
get { return isCancelled; }
}
public void Cancel()
{
EventHandler eh = null;
lock (lockObject) {
if (isCancelAllowed) {
ICSharpCode.Core.LoggingService.Debug("");
isCancelled = true;
eh = Cancelled;
}
}
if (eh != null)
eh(this, EventArgs.Empty);
}
public event EventHandler Cancelled;
public void BeginTask(string name, int totalWork, bool allowCancel)
{
baseProgressMonitor.BeginTask(name, totalWork, allowCancel);
lock (lockObject) {
isCancelAllowed = allowCancel;
}
}
public void Done()
{
lock (lockObject) {
isCancelAllowed = false;
}
baseProgressMonitor.Done();
}
public int WorkDone {
get { return baseProgressMonitor.WorkDone; }
set { baseProgressMonitor.WorkDone = value; }
}
public string TaskName {
get { return baseProgressMonitor.TaskName; }
set { baseProgressMonitor.TaskName = value; }
}
public bool ShowingDialog {
get { return baseProgressMonitor.ShowingDialog; }
set { baseProgressMonitor.ShowingDialog = value; }
} }
} }
#endregion #endregion
#region StartBuild #region StartBuild
public static void StartBuild(IBuildable project, BuildOptions options, IBuildFeedbackSink realtimeBuildFeedbackSink) public static void StartBuild(IBuildable project, BuildOptions options, IBuildFeedbackSink realtimeBuildFeedbackSink, IProgressMonitor progressMonitor)
{ {
if (project == null) if (project == null)
throw new ArgumentNullException("solution"); throw new ArgumentNullException("solution");
@ -81,6 +171,7 @@ namespace ICSharpCode.SharpDevelop.Project
BuildEngine engine = new BuildEngine(options, project); BuildEngine engine = new BuildEngine(options, project);
engine.buildStart = DateTime.Now; engine.buildStart = DateTime.Now;
engine.combinedBuildFeedbackSink = realtimeBuildFeedbackSink; engine.combinedBuildFeedbackSink = realtimeBuildFeedbackSink;
engine.progressMonitor = progressMonitor;
engine.configMatchings = solution.GetActiveConfigurationsAndPlatformsForProjects(options.SolutionConfiguration, options.SolutionPlatform); engine.configMatchings = solution.GetActiveConfigurationsAndPlatformsForProjects(options.SolutionConfiguration, options.SolutionPlatform);
try { try {
engine.rootNode = engine.CreateBuildGraph(project); engine.rootNode = engine.CreateBuildGraph(project);
@ -99,8 +190,14 @@ namespace ICSharpCode.SharpDevelop.Project
if (engine.workersToStart < 1) if (engine.workersToStart < 1)
engine.workersToStart = 1; engine.workersToStart = 1;
if (progressMonitor != null) {
progressMonitor.Cancelled += engine.BuildCancelled;
progressMonitor.BeginTask("", engine.nodeDict.Count, true);
}
engine.ReportMessageInternal("${res:MainWindow.CompilerMessages.BuildStarted}"); engine.ReportMessageInternal("${res:MainWindow.CompilerMessages.BuildStarted}");
engine.StartBuildProjects(); engine.StartBuildProjects();
engine.UpdateProgressTaskName();
} }
#endregion #endregion
@ -184,12 +281,14 @@ namespace ICSharpCode.SharpDevelop.Project
#region BuildEngine fields and constructor #region BuildEngine fields and constructor
readonly Dictionary<IBuildable, BuildNode> nodeDict = new Dictionary<IBuildable, BuildNode>(); readonly Dictionary<IBuildable, BuildNode> nodeDict = new Dictionary<IBuildable, BuildNode>();
readonly BuildOptions options; readonly BuildOptions options;
IProgressMonitor progressMonitor;
List<Solution.ProjectConfigurationPlatformMatching> configMatchings; List<Solution.ProjectConfigurationPlatformMatching> configMatchings;
BuildNode rootNode; BuildNode rootNode;
IBuildable rootProject; IBuildable rootProject;
BuildResults results = new BuildResults(); BuildResults results = new BuildResults();
DateTime buildStart; DateTime buildStart;
List<BuildNode> projectsCurrentlyBuilding = new List<BuildNode>();
List<BuildNode> projectsReadyForBuildStart = new List<BuildNode>(); List<BuildNode> projectsReadyForBuildStart = new List<BuildNode>();
int workersToStart, runningWorkers; int workersToStart, runningWorkers;
@ -289,7 +388,7 @@ namespace ICSharpCode.SharpDevelop.Project
{ {
lock (this) { lock (this) {
while (workersToStart > 0) { while (workersToStart > 0) {
if (projectsReadyForBuildStart.Count == 0) { if (buildIsCancelled || projectsReadyForBuildStart.Count == 0) {
if (runningWorkers == 0) { if (runningWorkers == 0) {
BuildDone(); BuildDone();
} }
@ -319,6 +418,7 @@ namespace ICSharpCode.SharpDevelop.Project
ICSharpCode.Core.LoggingService.Debug("Start building " + node.project.Name); ICSharpCode.Core.LoggingService.Debug("Start building " + node.project.Name);
runningWorkers++; runningWorkers++;
projectsCurrentlyBuilding.Add(node);
if (hasDependencyErrors) { if (hasDependencyErrors) {
ICSharpCode.Core.LoggingService.Debug("Skipped building " + node.project.Name + " (errors in dependencies)"); ICSharpCode.Core.LoggingService.Debug("Skipped building " + node.project.Name + " (errors in dependencies)");
node.hasErrors = true; node.hasErrors = true;
@ -366,6 +466,12 @@ namespace ICSharpCode.SharpDevelop.Project
runningWorkers--; runningWorkers--;
node.buildFinished = true; node.buildFinished = true;
node.hasErrors = !success; node.hasErrors = !success;
projectsCurrentlyBuilding.Remove(node);
if (progressMonitor != null) {
progressMonitor.WorkDone += 1;
}
foreach (BuildNode n in node.dependentOnThis) { foreach (BuildNode n in node.dependentOnThis) {
n.outstandingDependencies--; n.outstandingDependencies--;
if (n.outstandingDependencies == 0) if (n.outstandingDependencies == 0)
@ -375,6 +481,7 @@ namespace ICSharpCode.SharpDevelop.Project
} }
LogBuildFinished(node); LogBuildFinished(node);
StartBuildProjects(); StartBuildProjects();
UpdateProgressTaskName();
} }
bool buildIsDone; bool buildIsDone;
@ -393,7 +500,11 @@ namespace ICSharpCode.SharpDevelop.Project
} }
string buildTime = " (" + (DateTime.Now - buildStart).ToString() + ")"; string buildTime = " (" + (DateTime.Now - buildStart).ToString() + ")";
if (rootNode.hasErrors) { if (buildIsCancelled) {
results.Result = BuildResultCode.Cancelled;
ReportMessageInternal("Build was cancelled.");
} else if (rootNode.hasErrors) {
results.Result = BuildResultCode.Error; results.Result = BuildResultCode.Error;
ReportMessageInternal("${res:MainWindow.CompilerMessages.BuildFailed}" + buildTime); ReportMessageInternal("${res:MainWindow.CompilerMessages.BuildFailed}" + buildTime);
@ -404,6 +515,9 @@ namespace ICSharpCode.SharpDevelop.Project
ReportMessageInternal("${res:MainWindow.CompilerMessages.BuildFinished}" + buildTime); ReportMessageInternal("${res:MainWindow.CompilerMessages.BuildFinished}" + buildTime);
//StatusBarService.SetMessage("${res:MainWindow.CompilerMessages.BuildFinished}"); //StatusBarService.SetMessage("${res:MainWindow.CompilerMessages.BuildFinished}");
} }
if (progressMonitor != null) {
progressMonitor.Done();
}
if (combinedBuildFeedbackSink != null) { if (combinedBuildFeedbackSink != null) {
combinedBuildFeedbackSink.Done(results.Result == BuildResultCode.Success); combinedBuildFeedbackSink.Done(results.Result == BuildResultCode.Success);
} }
@ -413,6 +527,20 @@ namespace ICSharpCode.SharpDevelop.Project
} }
#endregion #endregion
#region Cancel build
bool buildIsCancelled;
void BuildCancelled(object sender, EventArgs e)
{
lock (this) {
if (buildIsDone)
return;
buildIsCancelled = true;
}
results.Add(new BuildError(null, "Build was cancelled."));
}
#endregion
#region Logging #region Logging
IBuildFeedbackSink combinedBuildFeedbackSink; IBuildFeedbackSink combinedBuildFeedbackSink;
/// <summary> /// <summary>
@ -487,6 +615,17 @@ namespace ICSharpCode.SharpDevelop.Project
if (combinedBuildFeedbackSink != null) if (combinedBuildFeedbackSink != null)
combinedBuildFeedbackSink.ReportMessage(message); combinedBuildFeedbackSink.ReportMessage(message);
} }
void UpdateProgressTaskName()
{
lock (this) {
if (progressMonitor != null) {
progressMonitor.TaskName = "Building "
+ projectsCurrentlyBuilding.Select(n => n.project.Name).Join(", ")
+ "...";
}
}
}
#endregion #endregion
} }
} }

4
src/Main/Base/Project/Src/Project/BuildResults.cs

@ -21,7 +21,9 @@ namespace ICSharpCode.SharpDevelop.Project
/// <summary>A project build file is not valid</summary> /// <summary>A project build file is not valid</summary>
BuildFileError, BuildFileError,
/// <summary>Build was not executed because another build is running</summary> /// <summary>Build was not executed because another build is running</summary>
MSBuildAlreadyRunning MSBuildAlreadyRunning,
/// <summary>Build was cancelled.</summary>
Cancelled
} }
/// <summary> /// <summary>

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

@ -19,6 +19,8 @@ namespace ICSharpCode.SharpDevelop
/// </summary> /// </summary>
internal static class DomHostCallback internal static class DomHostCallback
{ {
static IProgressMonitor assemblyLoadProgressMonitor;
internal static void Register() internal static void Register()
{ {
HostCallback.RenameMember = Refactoring.FindReferencesAndRenameHelper.RenameMember; HostCallback.RenameMember = Refactoring.FindReferencesAndRenameHelper.RenameMember;
@ -32,13 +34,16 @@ namespace ICSharpCode.SharpDevelop
MessageService.ShowError(ex, message); MessageService.ShowError(ex, message);
}; };
HostCallback.BeginAssemblyLoad = delegate(string shortName) { if (WorkbenchSingleton.MainForm != null) {
StatusBarService.ProgressMonitor.BeginTask( assemblyLoadProgressMonitor = StatusBarService.CreateProgressMonitor();
StringParser.Parse("${res:ICSharpCode.SharpDevelop.LoadingFile}", new string[,] {{"Filename", shortName}}), HostCallback.BeginAssemblyLoad = delegate(string shortName) {
100, false assemblyLoadProgressMonitor.BeginTask(
); StringParser.Parse("${res:ICSharpCode.SharpDevelop.LoadingFile}", new string[,] {{"Filename", shortName}}),
}; 100, false
HostCallback.FinishAssemblyLoad = StatusBarService.ProgressMonitor.Done; );
};
HostCallback.FinishAssemblyLoad = assemblyLoadProgressMonitor.Done;
}
HostCallback.ShowAssemblyLoadError = delegate(string fileName, string include, string message) { HostCallback.ShowAssemblyLoadError = delegate(string fileName, string include, string message) {
WorkbenchSingleton.SafeThreadAsyncCall(ShowAssemblyLoadError, WorkbenchSingleton.SafeThreadAsyncCall(ShowAssemblyLoadError,

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

@ -154,7 +154,7 @@ namespace ICSharpCode.SharpDevelop
static void LoadSolutionProjectsInternal() static void LoadSolutionProjectsInternal()
{ {
IProgressMonitor progressMonitor = StatusBarService.ProgressMonitor; IProgressMonitor progressMonitor = StatusBarService.CreateProgressMonitor();
List<ParseProjectContent> createdContents = new List<ParseProjectContent>(); List<ParseProjectContent> createdContents = new List<ParseProjectContent>();
foreach (IProject project in ProjectService.OpenSolution.Projects) { foreach (IProject project in ProjectService.OpenSolution.Projects) {
try { try {
@ -195,7 +195,7 @@ namespace ICSharpCode.SharpDevelop
static void InitAddedProject(object state) static void InitAddedProject(object state)
{ {
ParseProjectContent newContent = (ParseProjectContent)state; ParseProjectContent newContent = (ParseProjectContent)state;
IProgressMonitor progressMonitor = StatusBarService.ProgressMonitor; IProgressMonitor progressMonitor = StatusBarService.CreateProgressMonitor();
newContent.Initialize1(progressMonitor); newContent.Initialize1(progressMonitor);
progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", newContent.GetInitializationWorkAmount(), false); progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", newContent.GetInitializationWorkAmount(), false);
newContent.Initialize2(progressMonitor); newContent.Initialize2(progressMonitor);
@ -225,7 +225,7 @@ namespace ICSharpCode.SharpDevelop
{ {
bool parsing = false; bool parsing = false;
ParseProjectContent job; ParseProjectContent job;
IProgressMonitor progressMonitor = StatusBarService.ProgressMonitor; IProgressMonitor progressMonitor = StatusBarService.CreateProgressMonitor();
while (true) { while (true) {
// get next job // get next job

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

@ -1,11 +1,12 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt"/> // <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/> // <license see="prj:///doc/license.txt"/>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/> // <owner name="Daniel Grunwald"/>
// <version>$Revision$</version> // <version>$Revision$</version>
// </file> // </file>
using System; using System;
using System.Linq;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
@ -41,19 +42,15 @@ namespace ICSharpCode.SharpDevelop
} }
} }
public static IProgressMonitor ProgressMonitor {
get {
System.Diagnostics.Debug.Assert(statusBar != null);
return statusBar;
}
}
public static void SetCaretPosition(int x, int y, int charOffset) public static void SetCaretPosition(int x, int y, int charOffset)
{ {
statusBar.CursorStatusBarPanel.Text = StringParser.Parse("${res:StatusBarService.CursorStatusBarPanelText}", statusBar.CursorStatusBarPanel.Text = StringParser.Parse(
new string[,] { {"Line", String.Format("{0,-10}", y + 1)}, "${res:StatusBarService.CursorStatusBarPanelText}",
{"Column", String.Format("{0,-5}", x + 1)}, new string[,] {
{"Character", String.Format("{0,-5}", charOffset + 1)}}); {"Line", String.Format("{0,-10}", y + 1)},
{"Column", String.Format("{0,-5}", x + 1)},
{"Character", String.Format("{0,-5}", charOffset + 1)}
});
} }
public static void SetInsertMode(bool insertMode) public static void SetInsertMode(bool insertMode)
@ -102,7 +99,7 @@ namespace ICSharpCode.SharpDevelop
public static void Update() public static void Update()
{ {
System.Diagnostics.Debug.Assert(statusBar != null); System.Diagnostics.Debug.Assert(statusBar != null);
/* statusBar.Panels.Clear(); /* statusBar.Panels.Clear();
statusBar.Controls.Clear(); statusBar.Controls.Clear();
foreach (StatusBarContributionItem item in Items) { foreach (StatusBarContributionItem item in Items) {
@ -115,5 +112,92 @@ namespace ICSharpCode.SharpDevelop
} }
}*/ }*/
} }
#region Progress Monitor
static HashSet<StatusBarProgressMonitor> activeProgressMonitors = new HashSet<StatusBarProgressMonitor>();
static StatusBarProgressMonitor currentProgressMonitor;
public static IProgressMonitor CreateProgressMonitor()
{
System.Diagnostics.Debug.Assert(statusBar != null);
return new StatusBarProgressMonitor();
}
sealed class StatusBarProgressMonitor : IProgressMonitor
{
int workDone, totalWork;
public int WorkDone {
get { return workDone; }
set {
if (workDone == value)
return;
workDone = value;
lock (activeProgressMonitors) {
if (currentProgressMonitor == this) {
UpdateDisplay();
}
}
}
}
void UpdateDisplay()
{
statusBar.DisplayProgress(taskName, workDone, totalWork);
}
string taskName;
public string TaskName {
get { return taskName; }
set {
if (taskName == value)
return;
taskName = value;
lock (activeProgressMonitors) {
if (currentProgressMonitor == this) {
UpdateDisplay();
}
}
}
}
public bool ShowingDialog { get; set; }
public bool IsCancelled {
get { return false; }
}
public void BeginTask(string name, int totalWork, bool allowCancel)
{
lock (activeProgressMonitors) {
activeProgressMonitors.Add(this);
currentProgressMonitor = this;
this.taskName = name;
this.workDone = 0;
this.totalWork = totalWork;
UpdateDisplay();
}
}
public void Done()
{
lock (activeProgressMonitors) {
activeProgressMonitors.Remove(this);
if (currentProgressMonitor == this) {
if (activeProgressMonitors.Count > 0) {
currentProgressMonitor = activeProgressMonitors.First();
currentProgressMonitor.UpdateDisplay();
} else {
currentProgressMonitor = null;
statusBar.HideProgress();
}
}
}
}
public event EventHandler Cancelled { add { } remove { } }
}
#endregion
} }
} }

6
src/Main/Base/Project/Src/Util/ExtensionMethods.cs

@ -9,6 +9,7 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.SharpDevelop namespace ICSharpCode.SharpDevelop
{ {
@ -33,5 +34,10 @@ namespace ICSharpCode.SharpDevelop
{ {
return Array.AsReadOnly(arr); return Array.AsReadOnly(arr);
} }
public static string Join(this IEnumerable<string> input, string separator)
{
return string.Join(separator, input.ToArray());
}
} }
} }

1
src/Main/Core/Project/Src/Services/LoggingService/LoggingService.cs

@ -7,6 +7,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Diagnostics;
using log4net; using log4net;
using log4net.Config; using log4net.Config;

10
src/Main/ICSharpCode.SharpDevelop.BuildWorker/BuildJob.cs

@ -68,5 +68,15 @@ namespace ICSharpCode.SharpDevelop.BuildWorker
} }
return b.ToString(); return b.ToString();
} }
[NonSerialized]
internal Action CancelCallback;
public void Cancel()
{
if (CancelCallback != null) {
CancelCallback();
}
}
} }
} }

1
src/Main/ICSharpCode.SharpDevelop.BuildWorker/ICSharpCode.SharpDevelop.BuildWorker.csproj

@ -66,7 +66,6 @@
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="WorkerManager.cs" /> <Compile Include="WorkerManager.cs" />
<None Include="app.config" /> <None Include="app.config" />
<Content Include="ICSharpCode.SharpDevelop.BuildWorker.cd" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Configuration" /> <Folder Include="Configuration" />

7
src/Main/ICSharpCode.SharpDevelop.BuildWorker/Program.cs

@ -165,6 +165,13 @@ namespace ICSharpCode.SharpDevelop.BuildWorker
requestCancellation = false; requestCancellation = false;
hostEventSource = new EventSource(); hostEventSource = new EventSource();
} }
job.CancelCallback = delegate {
lock (this) {
if (currentJob == job) {
requestCancellation = true;
}
}
};
bool success = false; bool success = false;
try { try {
if (engine == null) { if (engine == null) {

Loading…
Cancel
Save