mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-05 15:38:29 -04:00
8001515b7e
add enable/disable to mavlinkcheckbox modify my button to curved add delay to progress reporter dialog. to ensure correct parent Fix Mount screen for AP Fix Hardware screen Text display roi difrently modify HIL/Quad Hil update dataflashlog format (thanks randy) update mavcmd format for roi
253 lines
9.1 KiB
C#
253 lines
9.1 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
|
|
namespace ArdupilotMega.Controls
|
|
{
|
|
/// <summary>
|
|
/// Form that is shown to the user during a background operation
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Performs operation excplicitely on a threadpool thread due to
|
|
/// Mono not playing nice with the BackgroundWorker
|
|
/// </remarks>
|
|
public partial class ProgressReporterDialogue : Form
|
|
{
|
|
private Exception workerException;
|
|
public ProgressWorkerEventArgs doWorkArgs;
|
|
|
|
internal int _progress = -1;
|
|
internal string _status = "";
|
|
|
|
public delegate void DoWorkEventHandler(object sender, ProgressWorkerEventArgs e);
|
|
|
|
// This is the event that will be raised on the BG thread
|
|
public event DoWorkEventHandler DoWork;
|
|
|
|
public ProgressReporterDialogue()
|
|
{
|
|
InitializeComponent();
|
|
doWorkArgs = new ProgressWorkerEventArgs();
|
|
this.btnClose.Visible = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called at setup - will kick off the background process on a thread pool thread
|
|
/// </summary>
|
|
public void RunBackgroundOperationAsync()
|
|
{
|
|
ThreadPool.QueueUserWorkItem(RunBackgroundOperation);
|
|
this.ShowDialog();
|
|
}
|
|
|
|
private void RunBackgroundOperation(object o)
|
|
{
|
|
try
|
|
{
|
|
Thread.CurrentThread.Name = "ProgressReporterDialogue Background thread";
|
|
}
|
|
catch { } // ok on windows - fails on mono
|
|
|
|
// mono fix - ensure the dialog is running
|
|
while (this.IsHandleCreated == false)
|
|
System.Threading.Thread.Sleep(1);
|
|
|
|
this.Invoke((MethodInvoker)delegate
|
|
{
|
|
// if this windows isnt the current active windows, popups inherit the wrong parent.
|
|
this.Focus();
|
|
Application.DoEvents();
|
|
});
|
|
|
|
try
|
|
{
|
|
if (this.DoWork != null) this.DoWork(this, doWorkArgs);
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
// The background operation thew an exception.
|
|
// Examine the work args, if there is an error, then display that and the exception details
|
|
// Otherwise display 'Unexpected error' and exception details
|
|
timer1.Stop();
|
|
ShowDoneWithError(e, doWorkArgs.ErrorMessage);
|
|
return;
|
|
}
|
|
|
|
// stop the timer
|
|
timer1.Stop();
|
|
// run once more to do final message and progressbar
|
|
this.Invoke((MethodInvoker)delegate
|
|
{
|
|
timer1_Tick(null, null);
|
|
});
|
|
|
|
if (doWorkArgs.CancelRequested && doWorkArgs.CancelAcknowledged)
|
|
{
|
|
ShowDoneCancelled();
|
|
return;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(doWorkArgs.ErrorMessage))
|
|
{
|
|
ShowDoneWithError(null, doWorkArgs.ErrorMessage);
|
|
return;
|
|
}
|
|
|
|
if (doWorkArgs.CancelRequested)
|
|
{
|
|
ShowDoneWithError(null, "Operation could not cancel");
|
|
return;
|
|
}
|
|
|
|
ShowDone();
|
|
}
|
|
|
|
// Called as a possible last operation of the bg thread that was cancelled
|
|
// - Hide progress bar
|
|
// - Set label text
|
|
private void ShowDoneCancelled()
|
|
{
|
|
this.Invoke((MethodInvoker)delegate
|
|
{
|
|
this.progressBar1.Visible = false;
|
|
this.lblProgressMessage.Text = "Cancelled";
|
|
this.btnClose.Visible = true;
|
|
});
|
|
}
|
|
|
|
// Called as a possible last operation of the bg thread
|
|
// - Set progress bar to 100%
|
|
// - Wait a little bit to allow the Aero progress animatiom to catch up
|
|
// - Signal that we can close
|
|
private void ShowDone()
|
|
{
|
|
this.Invoke((MethodInvoker) delegate
|
|
{
|
|
this.progressBar1.Style = ProgressBarStyle.Continuous;
|
|
this.progressBar1.Value = 100;
|
|
this.btnCancel.Visible = false;
|
|
this.btnClose.Visible = false;
|
|
});
|
|
|
|
Thread.Sleep(1000);
|
|
|
|
this.BeginInvoke((MethodInvoker) this.Close);
|
|
}
|
|
|
|
// Called as a possible last operation of the bg thread
|
|
// There was an exception on the worker event, so:
|
|
// - Show the error message supplied by the worker, or a default message
|
|
// - Make visible the error icon
|
|
// - Make the progress bar invisible to make room for:
|
|
// - Add the exception details and stack trace in an expansion panel
|
|
// - Change the Cancel button to 'Close', so that the user can look at the exception message a bit
|
|
private void ShowDoneWithError(Exception exception, string doWorkArgs)
|
|
{
|
|
var errMessage = doWorkArgs ?? "There was an unexpected error";
|
|
|
|
if (this.InvokeRequired)
|
|
{
|
|
this.Invoke((MethodInvoker) delegate
|
|
{
|
|
this.Text = "Error";
|
|
this.lblProgressMessage.Left = 65;
|
|
this.lblProgressMessage.Text = errMessage;
|
|
this.imgWarning.Visible = true;
|
|
this.progressBar1.Visible = false;
|
|
this.btnCancel.Visible = false;
|
|
this.btnClose.Visible = true;
|
|
this.linkLabel1.Visible = exception != null;
|
|
this.workerException = exception;
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
|
|
private void btnCancel_Click(object sender, EventArgs e)
|
|
{
|
|
// User wants to cancel -
|
|
// * Set the text of the Cancel button to 'Close'
|
|
// * Set the cancel button to disabled, will enable it and let the user dismiss the dialogue
|
|
// when the async operation is complete
|
|
// * Set the status text to 'Cancelling...'
|
|
// * Set the progress bar to marquee, we don't know how long the worker will take to cancel
|
|
// * Signal the worker.
|
|
this.btnCancel.Visible = false;
|
|
this.lblProgressMessage.Text = "Cancelling...";
|
|
this.progressBar1.Style = ProgressBarStyle.Marquee;
|
|
|
|
doWorkArgs.CancelRequested = true;
|
|
}
|
|
|
|
|
|
private void btn_Close_Click(object sender, EventArgs e)
|
|
{
|
|
// we have already cancelled, and this now a 'close' button
|
|
this.Close();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called from the BG thread
|
|
/// </summary>
|
|
/// <param name="progress">progress in %, -1 means inderteminate</param>
|
|
/// <param name="status"></param>
|
|
public void UpdateProgressAndStatus(int progress, string status)
|
|
{
|
|
// we don't let the worker update progress when a cancel has been
|
|
// requested, unless the cancel has been acknowleged, so we know that
|
|
// this progress update pertains to the cancellation cleanup
|
|
if (doWorkArgs.CancelRequested && !doWorkArgs.CancelAcknowledged)
|
|
return;
|
|
|
|
_progress = progress;
|
|
_status = status;
|
|
|
|
}
|
|
|
|
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
|
{
|
|
var message = this.workerException.Message
|
|
+ Environment.NewLine + Environment.NewLine
|
|
+ this.workerException.StackTrace;
|
|
|
|
CustomMessageBox.Show(message,"Exception Details",MessageBoxButtons.OK,MessageBoxIcon.Information);
|
|
}
|
|
|
|
/// <summary>
|
|
/// prevent using invokes on main update status call "UpdateProgressAndStatus", as this is slow on mono
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void timer1_Tick(object sender, EventArgs e)
|
|
{
|
|
// this value is being currupted - not thread safe
|
|
int pgv = _progress;
|
|
|
|
lblProgressMessage.Text = _status;
|
|
if (pgv == -1)
|
|
{
|
|
this.progressBar1.Style = ProgressBarStyle.Marquee;
|
|
}
|
|
else
|
|
{
|
|
this.progressBar1.Style = ProgressBarStyle.Continuous;
|
|
try
|
|
{
|
|
this.progressBar1.Value = pgv;
|
|
}
|
|
catch { } // clean fail. and ignore, chances are we will hit this again in the next 100 ms
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public class ProgressWorkerEventArgs : EventArgs
|
|
{
|
|
public string ErrorMessage;
|
|
public volatile bool CancelRequested;
|
|
public volatile bool CancelAcknowledged;
|
|
}
|
|
}
|