HamBook – Rev 59
?pathlinks?
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Media;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using HamBook.Properties;
using HamBook.Radios;
using HamBook.Radios.Generic;
using HamBook.Utilities.Serialization;
using Serilog;
namespace HamBook
{
public partial class MemoryOrganizerForm : Form
{
private readonly CancellationTokenSource _cancellationTokenSource;
private readonly CatAssemblies _catAssemblies;
private readonly CancellationToken _localCancellationToken;
private readonly CancellationTokenSource _localCancellationTokenSource;
private readonly MemoryBanks _memoryBanks;
private readonly MemoryRadioMode _memoryRadioMode;
private CancellationToken _cancellationToken;
private List<DataGridViewRow> _clipboardRows;
private CancellationTokenSource _readCancellationTokenSource;
private CancellationTokenSource _readLinkedCancellationTokenSource;
private Task _readMemoryBanksTask;
private CancellationTokenSource _writeCancellationTokenSource;
private CancellationTokenSource _writeLinkedCancellationTokenSource;
private Task _writeMemoryBanksTask;
public MemoryOrganizerForm()
{
InitializeComponent();
_localCancellationTokenSource = new CancellationTokenSource();
_localCancellationToken = _localCancellationTokenSource.Token;
}
public MemoryOrganizerForm(Configuration.Configuration configuration, CatAssemblies catAssemblies,
CancellationToken cancellationToken) : this()
{
Configuration = configuration;
_catAssemblies = catAssemblies;
_cancellationTokenSource =
CancellationTokenSource.CreateLinkedTokenSource(_localCancellationToken, cancellationToken);
_cancellationToken = _cancellationTokenSource.Token;
_memoryBanks = MemoryBanks.Create(Configuration.Radio);
_memoryRadioMode = MemoryRadioMode.Create(Configuration.Radio);
}
private Configuration.Configuration Configuration { get; }
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && components != null)
{
if (_cancellationTokenSource != null) _cancellationTokenSource.Cancel();
components.Dispose();
}
base.Dispose(disposing);
}
private async void button1_Click(object sender, EventArgs e)
{
var rows = dataGridView1.Rows.OfType<DataGridViewRow>().OrderBy(row => row.Index).ToList();
var count = rows.Count;
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = count;
toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
{
try
{
switch (rowProgress)
{
case DataGridViewRowProgressSuccess<MemoryChannel> rowProgressSuccess:
dataGridView1.Rows[rowProgressSuccess.Row.Index].DefaultCellStyle.BackColor =
DefaultBackColor;
switch (Configuration.Radio)
{
case "Yaesu FT-891":
var result = (Radios.Yaesu.FT_891.MemoryChannel)rowProgressSuccess.Data;
rowProgress.Row.Cells["FrequencyColumn"].Value = result.Frequency;
rowProgress.Row.Cells["ClarifierDirectionColumn"].Value =
(char)result.ClarifierDirection;
rowProgress.Row.Cells["ClarifierOffsetColumn"].Value = result.ClarifierOffset;
rowProgress.Row.Cells["ClarColumn"].Value = result.Clar;
rowProgress.Row.Cells["ModeColumn"].Value = result.MemoryRadioMode.Name;
rowProgress.Row.Cells["CtcssColumn"].Value = (string)result.Ctcss;
rowProgress.Row.Cells["PhaseColumn"].Value = (string)result.Phase;
rowProgress.Row.Cells["TagColumn"].Value = result.Tag;
rowProgress.Row.Cells["TextColumn"].Value = result.Text;
rowProgress.Row.Tag = rowProgressSuccess.Data;
break;
}
toolStripStatusLabel1.Text = $"{Resources.Read_memory_bank} {rowProgress.Index + 1}";
break;
case DataGridViewRowProgressFailure<int> rowProgressFailure:
Log.Error(rowProgressFailure.Exception, $"{Resources.Could_not_read_memory_bank}");
dataGridView1.Rows[rowProgressFailure.Row.Index].DefaultCellStyle.BackColor = Color.Red;
toolStripStatusLabel1.Text =
$"{Resources.Could_not_read_memory_bank} {rowProgress.Index + 1}";
break;
}
toolStripProgressBar1.Increment(1);
statusStrip1.Update();
}
catch (Exception exception)
{
Log.Error(exception, Resources.Unexpected_error_while_reading_memory_bank);
}
});
await Task.Run(() => ReadMemoryBanks(rows, progress, _cancellationToken), _cancellationToken);
if (!_cancellationToken.IsCancellationRequested)
{
toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
toolStripStatusLabel1.Text = "Done.";
}
}
private async void button2_Click(object sender, EventArgs e)
{
var rows = dataGridView1.Rows.OfType<DataGridViewRow>().OrderBy(row => row.Index).ToList();
var count = rows.Count;
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = count;
toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
{
try
{
switch (rowProgress)
{
case DataGridViewRowProgressSuccess<bool> rowProgressSuccess:
dataGridView1.Rows[rowProgressSuccess.Row.Index].DefaultCellStyle.BackColor =
DefaultBackColor;
var success = rowProgressSuccess.Data;
if (success)
{
toolStripStatusLabel1.Text =
$"{Resources.Wrote_memory_bank} {rowProgress.Index + 1}";
toolStripProgressBar1.Increment(1);
statusStrip1.Update();
return;
}
Log.Error($"{Resources.Could_not_write_memory_bank}");
break;
case DataGridViewRowProgressFailure<int> rowProgressFailure:
dataGridView1.Rows[rowProgressFailure.Row.Index].DefaultCellStyle.BackColor = Color.Red;
Log.Error(rowProgressFailure.Exception, $"{Resources.Could_not_write_memory_bank}");
break;
}
toolStripStatusLabel1.Text =
$"{Resources.Could_not_write_memory_bank} {rowProgress.Index + 1}";
toolStripProgressBar1.Increment(1);
statusStrip1.Update();
}
catch (Exception exception)
{
Log.Error(exception, Resources.Unexpected_error_while_writing_memory_bank);
}
});
await Task.Run(() => WriteMemoryBanks(rows, progress, _cancellationToken), _cancellationToken);
if (!_cancellationToken.IsCancellationRequested)
{
toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
toolStripStatusLabel1.Text = "Done.";
}
}
private void MemoryOrganizerForm_Load(object sender, EventArgs e)
{
Utilities.WindowState.FormTracker.Track(this);
// Generate columns based on radio type.
switch (Configuration.Radio)
{
case "Yaesu FT-891":
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
{ Name = "LocationColumn", HeaderText = "Location", ReadOnly = true });
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
{ Name = "FrequencyColumn", HeaderText = "Frequency" });
var clarifierDropDownColumn = new DataGridViewComboBoxColumn
{ Name = "ClarifierDirectionColumn", HeaderText = "Clarifier" };
clarifierDropDownColumn.Items.AddRange(
"+",
"-"
);
dataGridView1.Columns.Add(clarifierDropDownColumn);
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
{ Name = "ClarifierOffsetColumn", HeaderText = "Offset" });
dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn
{ Name = "ClarColumn", HeaderText = "Clar" });
var modeComboBoxColumn = new DataGridViewComboBoxColumn
{ Name = "ModeColumn", HeaderText = "Mode" };
foreach (var name in _memoryRadioMode.Names)
modeComboBoxColumn.Items.Add(
name
);
dataGridView1.Columns.Add(modeComboBoxColumn);
var ctcssComboBoxColumn = new DataGridViewComboBoxColumn
{ Name = "CtcssColumn", HeaderText = "CTCSS" };
ctcssComboBoxColumn.Items.AddRange(
"Off",
"Enc/Dec",
"Enc"
);
dataGridView1.Columns.Add(ctcssComboBoxColumn);
var phaseComboBoxColumn = new DataGridViewComboBoxColumn
{ Name = "PhaseColumn", HeaderText = "Phase" };
phaseComboBoxColumn.Items.AddRange(
"Simplex",
"Plus Shift",
"Minus Shift"
);
dataGridView1.Columns.Add(phaseComboBoxColumn);
dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn
{ Name = "TagColumn", HeaderText = "Tag" });
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
{
Name = "TextColumn", HeaderText = "Text",
MaxInputLength = Radios.Yaesu.FT_891.Constants.MaxTagCharacters
});
break;
}
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = 98;
toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
var memoryBankQueue = new ConcurrentQueue<string>();
var memoryBankAddRowsTaskCompletionSource = new TaskCompletionSource<object>();
async void IdleHandler(object idleHandlerSender, EventArgs idleHandlerArgs)
{
await memoryBankAddRowsTaskCompletionSource.Task;
try
{
if (!memoryBankQueue.TryDequeue(out var memoryBank))
{
Application.Idle -= IdleHandler;
dataGridView1.Sort(dataGridView1.Columns["LocationColumn"], ListSortDirection.Ascending);
toolStripStatusLabel1.Text = "Done.";
return;
}
var index = dataGridView1.Rows.Add();
switch (Configuration.Radio)
{
case "Yaesu FT-891":
dataGridView1.Rows[index].Cells["LocationColumn"].Value = memoryBank;
dataGridView1.Rows[index].Cells["FrequencyColumn"].Value = default;
dataGridView1.Rows[index].Cells["ClarifierDirectionColumn"].Value = "+";
dataGridView1.Rows[index].Cells["ClarifierOffsetColumn"].Value = 0;
dataGridView1.Rows[index].Cells["ClarColumn"].Value = default;
dataGridView1.Rows[index].Cells["ModeColumn"].Value = default;
dataGridView1.Rows[index].Cells["CtcssColumn"].Value = "Off";
dataGridView1.Rows[index].Cells["PhaseColumn"].Value = "Simplex";
dataGridView1.Rows[index].Cells["TagColumn"].Value = default;
dataGridView1.Rows[index].Cells["TextColumn"].Value = default;
break;
}
toolStripStatusLabel1.Text = $"{Resources.Created_memory_bank} {memoryBank}";
toolStripProgressBar1.Increment(1);
statusStrip1.Update();
}
catch (Exception exception)
{
Log.Error(exception, Resources.Could_not_update_data_grid_view);
}
}
Application.Idle += IdleHandler;
try
{
foreach (var memoryBank in _memoryBanks.GetMemoryBanks()) memoryBankQueue.Enqueue(memoryBank);
memoryBankAddRowsTaskCompletionSource.TrySetResult(new { });
}
catch (Exception exception)
{
Application.Idle -= IdleHandler;
Log.Error(exception, Resources.Unable_to_create_memory_banks);
}
}
private void DataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
var dataGridView = (DataGridView)sender;
if (dataGridView.CurrentCell is DataGridViewCheckBoxCell)
dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
private void DataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
var dataGridView = (DataGridView)sender;
dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
private void DataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void DataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
var dataGridView = (DataGridView)sender;
if (e.RowIndex == -1 || e.ColumnIndex == -1) return;
switch (dataGridView.Columns[e.ColumnIndex].Name)
{
case "EnableColumn":
//ProcessEnable(dataGridView.Rows[e.RowIndex]);
break;
}
}
private void DataGridView1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
var dataGridView = (DataGridView)sender;
if (e.RowIndex == -1 || e.ColumnIndex == -1 ||
!(dataGridView.Columns[e.ColumnIndex] is DataGridViewCheckBoxColumn))
return;
dataGridView.EndEdit();
}
private void DataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
var dataGridView = (DataGridView)sender;
if (e.RowIndex == -1 || e.ColumnIndex == -1 ||
!(dataGridView.Columns[e.ColumnIndex] is DataGridViewCheckBoxColumn))
return;
dataGridView.EndEdit();
}
private void DataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
// @(-.-)@ -(o.o)- @(o_o)@
}
private static IEnumerable<DataGridViewRow> GetSelectedDataGridViewRows(DataGridView dataGridView)
{
return dataGridView.SelectedRows.OfType<DataGridViewRow>().OrderBy(row => row.Index);
}
private async Task ReadMemoryBanks(IReadOnlyList<DataGridViewRow> rows,
IProgress<DataGridViewRowProgress> progress,
CancellationToken cancellationToken)
{
var count = rows.Count;
for (var i = 0; i < count && !cancellationToken.IsCancellationRequested; ++i)
try
{
var location = $"{rows[i].Cells["LocationColumn"].Value}";
var result =
await _catAssemblies.CatReadAsync<MemoryChannel>("MT", new object[] { location },
cancellationToken);
progress.Report(new DataGridViewRowProgressSuccess<MemoryChannel>(rows[i], i, result));
}
catch (UnexpectedRadioResponseException exception)
{
progress.Report(new DataGridViewRowProgressFailure<int>(rows[i], i, exception));
}
catch (Exception exception)
{
progress.Report(new DataGridViewRowProgressFailure<int>(rows[i], i, exception));
}
}
private async Task WriteMemoryBanks(IReadOnlyList<DataGridViewRow> rows,
IProgress<DataGridViewRowProgress> progress,
CancellationToken cancellationToken)
{
var count = rows.Count;
for (var i = 0; i < count && !cancellationToken.IsCancellationRequested; ++i)
try
{
var success = false;
switch (Configuration.Radio)
{
case "Yaesu FT-891":
var memoryChannel =
(Radios.Yaesu.FT_891.MemoryChannel)MemoryChannel.Create(Configuration.Radio);
memoryChannel.CurrentLocation = $"{rows[i].Cells["LocationColumn"].Value}";
memoryChannel.Frequency = int.Parse($"{rows[i].Cells["FrequencyColumn"].Value}");
memoryChannel.ClarifierDirection =
char.Parse($"{rows[i].Cells["ClarifierDirectionColumn"].Value}");
memoryChannel.ClarifierOffset =
int.Parse($"{rows[i].Cells["ClarifierOffsetColumn"].Value}");
memoryChannel.Clar = Convert.ToBoolean(rows[i].Cells["ClarColumn"].Value);
memoryChannel.MemoryRadioMode = MemoryRadioMode.Create(Configuration.Radio,
$"{rows[i].Cells["ModeColumn"].Value}");
memoryChannel.Ctcss = new Ctcss($"{rows[i].Cells["CtcssColumn"].Value}");
memoryChannel.Phase = new Phase($"{rows[i].Cells["PhaseColumn"].Value}");
memoryChannel.Tag = Convert.ToBoolean(rows[i].Cells["TagColumn"].Value);
memoryChannel.Text = $"{rows[i].Cells["TextColumn"].Value,-12}";
success = await _catAssemblies.CatSetAsync<MemoryChannel, bool>("MT",
new object[] { memoryChannel }, cancellationToken);
break;
}
progress.Report(new DataGridViewRowProgressSuccess<bool>(rows[i], i, success));
}
catch (UnexpectedRadioResponseException exception)
{
progress.Report(new DataGridViewRowProgressFailure<int>(rows[i], i, exception));
}
catch (Exception exception)
{
progress.Report(new DataGridViewRowProgressFailure<int>(rows[i], i, exception));
}
}
private void importToolStripMenuItem_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
}
private void exportToolStripMenuItem_Click(object sender, EventArgs e)
{
saveFileDialog1.ShowDialog();
}
private async void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
{
if (e.Cancel)
{
return;
}
var list = new List<MemoryChannelIndexed>();
foreach (var row in dataGridView1.Rows.OfType<DataGridViewRow>().OrderBy(row => row.Index))
if (row.Tag is MemoryChannel memoryChannel)
{
var memoryChannelOrganizerBanks = new MemoryChannelIndexed(row.Index, memoryChannel);
list.Add(memoryChannelOrganizerBanks);
}
var memoryBanks = list.ToArray();
var fileName = saveFileDialog1.FileName;
switch (await Serialization.Serialize(memoryBanks, fileName, "MemoryChannelOrganizerBank",
"<!ATTLIST MemoryChannelOrganizerBank xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>",
CancellationToken.None))
{
case SerializationSuccess<MemoryChannelIndexed[]> configuration:
Log.Information(Resources.Serialized_memory_banks);
break;
case SerializationFailure serializationFailure:
Log.Warning(serializationFailure.Exception.Message, Resources.Failed_to_serialize_memory_banks);
break;
}
}
private async void openFileDialog1_FileOk(object sender, CancelEventArgs e)
{
if (e.Cancel)
{
return;
}
MemoryChannelIndexed[] memoryBanks = null;
var fileName = openFileDialog1.FileName;
var deserializationResult =
await Serialization.Deserialize<MemoryChannelIndexed[]>(fileName,
"urn:hambook-memorychannelorganizerbank-schema", "MemoryChannelIndexed.xsd",
_localCancellationToken);
switch (deserializationResult)
{
case SerializationSuccess<MemoryChannelIndexed[]> serializationSuccess:
Log.Information(Resources.Deserialized_memory_banks);
memoryBanks = serializationSuccess.Result;
break;
case SerializationFailure serializationFailure:
Log.Warning(serializationFailure.Exception, Resources.Failed_to_deserialize_memory_banks);
return;
}
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = 98;
toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
var memoryBankQueue = new ConcurrentQueue<MemoryChannelIndexed>();
var snapshotsQueuedTaskCompletionSource = new TaskCompletionSource<object>();
async void IdleHandler(object idleHandlerSender, EventArgs idleHandlerArgs)
{
await snapshotsQueuedTaskCompletionSource.Task;
try
{
if (!memoryBankQueue.TryDequeue(out var memoryBank))
{
Application.Idle -= IdleHandler;
dataGridView1.Sort(dataGridView1.Columns["LocationColumn"], ListSortDirection.Ascending);
toolStripStatusLabel1.Text = "Done.";
return;
}
switch (Configuration.Radio)
{
case "Yaesu FT-891":
var memoryChannel = (Radios.Yaesu.FT_891.MemoryChannel)memoryBank.MemoryChannel;
dataGridView1.Rows[memoryBank.Index].Cells["FrequencyColumn"].Value =
memoryBank.MemoryChannel.Frequency;
dataGridView1.Rows[memoryBank.Index].Cells["ClarifierDirectionColumn"].Value =
(char)memoryChannel.ClarifierDirection;
dataGridView1.Rows[memoryBank.Index].Cells["ClarifierOffsetColumn"].Value =
memoryChannel.ClarifierOffset;
dataGridView1.Rows[memoryBank.Index].Cells["ClarColumn"].Value = memoryChannel.Clar;
dataGridView1.Rows[memoryBank.Index].Cells["ModeColumn"].Value =
memoryBank.MemoryChannel.MemoryRadioMode.Name;
dataGridView1.Rows[memoryBank.Index].Cells["CtcssColumn"].Value =
(string)memoryChannel.Ctcss;
dataGridView1.Rows[memoryBank.Index].Cells["PhaseColumn"].Value =
(string)memoryChannel.Phase;
dataGridView1.Rows[memoryBank.Index].Cells["TagColumn"].Value =
memoryBank.MemoryChannel.Tag;
dataGridView1.Rows[memoryBank.Index].Cells["TextColumn"].Value =
memoryBank.MemoryChannel.Text;
dataGridView1.Rows[memoryBank.Index].Tag = memoryBank.MemoryChannel;
break;
}
toolStripProgressBar1.Increment(1);
statusStrip1.Update();
}
catch (Exception exception)
{
Log.Error(exception, Resources.Could_not_update_data_grid_view);
}
}
Application.Idle += IdleHandler;
try
{
foreach (var memoryChannel in memoryBanks) memoryBankQueue.Enqueue(memoryChannel);
snapshotsQueuedTaskCompletionSource.TrySetResult(new { });
}
catch (Exception exception)
{
Application.Idle -= IdleHandler;
Log.Error(exception, Resources.Unable_to_create_memory_banks);
}
}
private void MemoryOrganizerForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (_cancellationTokenSource != null) _cancellationTokenSource.Cancel();
}
private async void readToolStripMenuItem_Click(object sender, EventArgs e)
{
if (_readLinkedCancellationTokenSource != null)
{
_readLinkedCancellationTokenSource.Cancel();
_readLinkedCancellationTokenSource = null;
}
if (_readMemoryBanksTask != null)
{
await _readMemoryBanksTask;
_readMemoryBanksTask = null;
}
_readCancellationTokenSource = new CancellationTokenSource();
_readLinkedCancellationTokenSource =
CancellationTokenSource.CreateLinkedTokenSource(new[]
{ _cancellationTokenSource.Token, _cancellationToken });
_readMemoryBanksTask = ReadMemoryBanks(_readLinkedCancellationTokenSource.Token);
}
private async Task ReadMemoryBanks(CancellationToken cancellationToken)
{
var rows = GetSelectedDataGridViewRows(dataGridView1);
if (!rows.Any()) return;
var list = rows.ToList();
var count = list.Count;
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = count;
toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
{
try
{
switch (rowProgress)
{
case DataGridViewRowProgressSuccess<MemoryChannel> rowProgressSuccess:
dataGridView1.Rows[rowProgressSuccess.Row.Index].DefaultCellStyle.BackColor =
DefaultBackColor;
switch (rowProgressSuccess.Data)
{
case Radios.Yaesu.FT_891.MemoryChannel memoryChannel:
rowProgress.Row.Cells["FrequencyColumn"].Value = memoryChannel.Frequency;
rowProgress.Row.Cells["ClarifierDirectionColumn"].Value =
(char)memoryChannel.ClarifierDirection;
rowProgress.Row.Cells["ClarifierOffsetColumn"].Value =
memoryChannel.ClarifierOffset;
rowProgress.Row.Cells["ClarColumn"].Value = memoryChannel.Clar;
rowProgress.Row.Cells["ModeColumn"].Value = memoryChannel.MemoryRadioMode.Name;
rowProgress.Row.Cells["CtcssColumn"].Value = (string)memoryChannel.Ctcss;
rowProgress.Row.Cells["PhaseColumn"].Value = (string)memoryChannel.Phase;
rowProgress.Row.Cells["TagColumn"].Value = memoryChannel.Tag;
rowProgress.Row.Cells["TextColumn"].Value = memoryChannel.Text;
rowProgress.Row.Tag = rowProgressSuccess.Data;
break;
}
toolStripStatusLabel1.Text = $"{Resources.Read_memory_bank} {rowProgress.Index + 1}";
break;
case DataGridViewRowProgressFailure<int> rowProgressFailure:
Log.Error(rowProgressFailure.Exception, $"{Resources.Could_not_read_memory_bank}");
dataGridView1.Rows[rowProgressFailure.Row.Index].DefaultCellStyle.BackColor = Color.Red;
toolStripStatusLabel1.Text =
$"{Resources.Could_not_read_memory_bank} {rowProgress.Index + 1}";
break;
}
toolStripProgressBar1.Increment(1);
statusStrip1.Update();
}
catch (Exception exception)
{
Log.Error(exception, Resources.Unexpected_error_while_reading_memory_bank);
}
});
await Task.Run(() => ReadMemoryBanks(list, progress, cancellationToken), cancellationToken);
if (!_cancellationToken.IsCancellationRequested)
{
toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
toolStripStatusLabel1.Text = "Done.";
}
}
private async void writeToolStripMenuItem_Click(object sender, EventArgs e)
{
if (_writeLinkedCancellationTokenSource != null)
{
_writeLinkedCancellationTokenSource.Cancel();
_writeLinkedCancellationTokenSource = null;
}
if (_writeMemoryBanksTask != null)
{
await _writeMemoryBanksTask;
_writeMemoryBanksTask = null;
}
_writeCancellationTokenSource = new CancellationTokenSource();
_writeLinkedCancellationTokenSource =
CancellationTokenSource.CreateLinkedTokenSource(new[]
{ _cancellationTokenSource.Token, _cancellationToken });
_writeMemoryBanksTask = WriteMemoryBanks(_writeLinkedCancellationTokenSource.Token);
}
private async Task WriteMemoryBanks(CancellationToken cancellationToken)
{
var rows = GetSelectedDataGridViewRows(dataGridView1);
if (!rows.Any()) return;
var list = rows.ToList();
var count = list.Count;
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = count;
toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
{
try
{
switch (rowProgress)
{
case DataGridViewRowProgressSuccess<bool> rowProgressSuccess:
dataGridView1.Rows[rowProgressSuccess.Row.Index].DefaultCellStyle.BackColor =
DefaultBackColor;
var success = rowProgressSuccess.Data;
if (success)
{
toolStripStatusLabel1.Text =
$"{Resources.Wrote_memory_bank} {rowProgress.Index + 1}";
toolStripProgressBar1.Increment(1);
statusStrip1.Update();
return;
}
Log.Error($"{Resources.Could_not_write_memory_bank}");
break;
case DataGridViewRowProgressFailure<int> rowProgressFailure:
Log.Error(rowProgressFailure.Exception, $"{Resources.Could_not_write_memory_bank}");
dataGridView1.Rows[rowProgressFailure.Row.Index].DefaultCellStyle.BackColor = Color.Red;
break;
}
toolStripStatusLabel1.Text =
$"{Resources.Could_not_write_memory_bank} {rowProgress.Index + 1}";
toolStripProgressBar1.Increment(1);
statusStrip1.Update();
}
catch (Exception exception)
{
Log.Error(exception, Resources.Unexpected_error_while_writing_memory_bank);
}
});
await Task.Run(() => WriteMemoryBanks(list, progress, cancellationToken), cancellationToken);
if (!_cancellationToken.IsCancellationRequested)
{
toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
toolStripStatusLabel1.Text = "Done.";
}
}
private async void readFromVFOAToolStripMenuItem_Click(object sender, EventArgs e)
{
var rows = GetSelectedDataGridViewRows(dataGridView1);
if (!rows.Any()) return;
var list = rows.ToList();
try
{
foreach (var row in list)
{
var fa = await _catAssemblies.CatReadAsync<int>("FA", new object[] { }, _cancellationToken);
row.Cells["FrequencyColumn"].Value = $"{fa}";
}
}
catch (Exception exception)
{
Log.Error(exception, Resources.Failed_to_read_VFO_A);
}
}
private async void readFromVFOBToolStripMenuItem_Click(object sender, EventArgs e)
{
var rows = GetSelectedDataGridViewRows(dataGridView1);
if (!rows.Any()) return;
var list = rows.ToList();
try
{
foreach (var row in list)
{
var fb = await _catAssemblies.CatReadAsync<int>("FB", new object[] { }, _cancellationToken);
row.Cells["FrequencyColumn"].Value = $"{fb}";
}
}
catch (Exception exception)
{
Log.Error(exception, Resources.Failed_to_read_VFO_B);
}
}
private async void memoryChannelToolStripMenuItem_Click(object sender, EventArgs e)
{
var rows = GetSelectedDataGridViewRows(dataGridView1);
if (!rows.Any()) return;
var row = rows.First();
try
{
using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly()
.GetManifestResourceStream("HamBook.Effects.pot.wav")))
{
await _catAssemblies.CatWriteAsync<string>("MC", new[] { row.Cells["LocationColumn"].Value },
_cancellationToken);
soundPlayer.Play();
}
}
catch (Exception exception)
{
Log.Error(exception, Resources.Failed_to_set_memory_channel);
}
}
private async void frequencyToolStripMenuItem_Click(object sender, EventArgs e)
{
var rows = GetSelectedDataGridViewRows(dataGridView1);
if (!rows.Any()) return;
var row = rows.First();
try
{
using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly()
.GetManifestResourceStream("HamBook.Effects.pot.wav")))
{
if (await _catAssemblies.CatSetAsync<int, bool>("FA", new[] { row.Cells["FrequencyColumn"].Value },
_cancellationToken))
if (Configuration.Navigation.MouseScrollSound)
soundPlayer.Play();
}
}
catch (Exception exception)
{
Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
}
}
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
var dataGridView = (DataGridView)sender;
var hitTest = dataGridView.HitTest(e.X, e.Y);
switch (e.Button)
{
case MouseButtons.Right:
if (GetSelectedDataGridViewRows(dataGridView).Count() > 1) return;
dataGridView.ClearSelection();
if (hitTest.RowIndex != -1) dataGridView.Rows[hitTest.RowIndex].Selected = true;
break;
}
}
private IEnumerable<DataGridViewRow> CopySelectedRows(DataGridView dataGridView)
{
foreach (var row in GetSelectedDataGridViewRows(dataGridView))
{
var clone = row.Clone() as DataGridViewRow;
for (var i = 0; i < row.Cells.Count; ++i)
{
if (row.Cells[i].ReadOnly) continue;
clone.Cells[i].Value = row.Cells[i].Value;
}
yield return clone;
}
}
private void DeleteSelectedRows(DataGridView dataGridView)
{
foreach (var row in GetSelectedDataGridViewRows(dataGridView))
for (var i = 0; i < row.Cells.Count; ++i)
{
if (row.Cells[i].ReadOnly) continue;
row.Cells[i].Value = default;
}
}
private void PasteSelectedRows(DataGridView dataGridView, IEnumerable<DataGridViewRow> pasteRows)
{
var rows = pasteRows.ToList();
if (rows.Count == 0) return;
foreach (var row in GetSelectedDataGridViewRows(dataGridView))
{
if (rows.Count == 0) return;
var paste = rows[0];
for (var i = 0; i < paste.Cells.Count; ++i)
{
if (row.Cells[i].ReadOnly) continue;
row.Cells[i].Value = paste.Cells[i].Value;
}
rows.RemoveAt(0);
}
}
private IEnumerable<DataGridViewRow> CutSelectedRows(DataGridView dataGridView)
{
foreach (var row in GetSelectedDataGridViewRows(dataGridView))
{
var clone = row.Clone() as DataGridViewRow;
for (var i = 0; i < row.Cells.Count; ++i)
{
if (row.Cells[i].ReadOnly) continue;
clone.Cells[i].Value = row.Cells[i].Value;
row.Cells[i].Value = default;
}
yield return clone;
}
}
private void cutToolStripMenuItem1_Click(object sender, EventArgs e)
{
_clipboardRows = new List<DataGridViewRow>();
foreach (var row in CutSelectedRows(dataGridView1)) _clipboardRows.Add(row);
}
private void copyToolStripMenuItem1_Click(object sender, EventArgs e)
{
_clipboardRows = new List<DataGridViewRow>();
foreach (var row in CopySelectedRows(dataGridView1)) _clipboardRows.Add(row);
}
private void pasteToolStripMenuItem1_Click(object sender, EventArgs e)
{
PasteSelectedRows(dataGridView1, _clipboardRows);
}
private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
{
DeleteSelectedRows(dataGridView1);
}
private void dataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
var dataGridView = sender as DataGridView;
foreach (DataGridViewCell cell in dataGridView.Rows[e.RowIndex].Cells)
{
if (cell.Selected == false) continue;
var bgColorCell = Color.White;
if (cell.Style.BackColor != Color.Empty)
bgColorCell = cell.Style.BackColor;
else if (cell.InheritedStyle.BackColor != Color.Empty) bgColorCell = cell.InheritedStyle.BackColor;
cell.Style.SelectionBackColor = MixColor(bgColorCell, Color.FromArgb(0, 150, 255), 10, 4);
}
}
//Mix two colors
//Example: Steps=10 & Position=4 makes Color2 mix 40% into Color1
/// <summary>
/// Mix two colors.
/// </summary>
/// <param name="color1"></param>
/// <param name="color2"></param>
/// <param name="steps"></param>
/// <param name="position"></param>
/// <example>Steps=10 & Positon=4 makes Color2 mix 40% into Color1</example>
/// <remarks>https://stackoverflow.com/questions/38337849/transparent-selectionbackcolor-for-datagridview-cell</remarks>
/// <returns></returns>
public static Color MixColor(Color color1, Color color2, int steps, int position)
{
if (position <= 0 || steps <= 1) return color1;
if (position >= steps) return color2;
return Color.FromArgb(
color1.R + (color2.R - color1.R) / steps * position,
color1.G + (color2.G - color1.G) / steps * position,
color1.B + (color2.B - color1.B) / steps * position
);
}
private void DataGridView1_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e)
{
switch (Configuration.Radio)
{
case "Yaesu FT-891":
e.Row.Cells["LocationColumn"].Value = default;
e.Row.Cells["FrequencyColumn"].Value = default;
e.Row.Cells["ClarifierDirectionColumn"].Value = "+";
e.Row.Cells["ClarifierOffsetColumn"].Value = 0;
e.Row.Cells["ClarColumn"].Value = default;
e.Row.Cells["ModeColumn"].Value = default;
e.Row.Cells["CtcssColumn"].Value = "Off";
e.Row.Cells["PhaseColumn"].Value = "Simplex";
e.Row.Cells["TagColumn"].Value = default;
e.Row.Cells["TextColumn"].Value = default;
break;
}
}
}
}
Generated by GNU Enscript 1.6.5.90.