HamBook – Blame information for rev 54

Subversion Repositories:
Rev:
Rev Author Line No. Line
54 office 1 using System;
15 office 2 using System.Collections.Concurrent;
3 using System.Collections.Generic;
4 using System.ComponentModel;
53 office 5 using System.Drawing;
15 office 6 using System.Linq;
51 office 7 using System.Media;
8 using System.Reflection;
49 office 9 using System.Threading;
15 office 10 using System.Threading.Tasks;
11 using System.Windows.Forms;
54 office 12 using HamBook.Properties;
13 using HamBook.Radios;
14 using HamBook.Radios.Generic;
15 using HamBook.Utilities.Serialization;
16 using Serilog;
17 using MemoryRadioMode = HamBook.Radios.Yaesu.FT_891.MemoryRadioMode;
15 office 18  
19 namespace HamBook
20 {
21 public partial class MemoryOrganizerForm : Form
22 {
54 office 23 private readonly CancellationTokenSource _cancellationTokenSource;
15 office 24  
54 office 25 private readonly CatAssemblies _catAssemblies;
26 private readonly CancellationToken _localCancellationToken;
27 private readonly CancellationTokenSource _localCancellationTokenSource;
28 private readonly MemoryBanks _memoryBanks;
15 office 29 private CancellationToken _cancellationToken;
52 office 30 private List<DataGridViewRow> _clipboardRows;
54 office 31 private CancellationTokenSource _writeCancellationTokenSource;
32 private CancellationTokenSource _writeLinkedCancellationTokenSource;
33 private Task _writeMemoryBanksTask;
34 private CancellationTokenSource _readCancellationTokenSource;
35 private CancellationTokenSource _readLinkedCancellationTokenSource;
36 private Task _readMemoryBanksTask;
15 office 37  
38 public MemoryOrganizerForm()
39 {
40 InitializeComponent();
53 office 41 Utilities.WindowState.FormTracker.Track(this);
22 office 42  
43 _localCancellationTokenSource = new CancellationTokenSource();
44 _localCancellationToken = _localCancellationTokenSource.Token;
15 office 45 }
46  
54 office 47 public MemoryOrganizerForm(Configuration.Configuration configuration, CatAssemblies catAssemblies,
48 CancellationToken cancellationToken) : this()
15 office 49 {
50 Configuration = configuration;
51 _catAssemblies = catAssemblies;
22 office 52  
54 office 53 _cancellationTokenSource =
54 CancellationTokenSource.CreateLinkedTokenSource(_localCancellationToken, cancellationToken);
22 office 55 _cancellationToken = _cancellationTokenSource.Token;
41 office 56  
54 office 57 _memoryBanks = MemoryBanks.Create(Configuration.Radio);
15 office 58 }
59  
54 office 60 private Configuration.Configuration Configuration { get; }
61  
15 office 62 /// <summary>
54 office 63 /// Clean up any resources being used.
15 office 64 /// </summary>
65 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
66 protected override void Dispose(bool disposing)
67 {
54 office 68 if (disposing && components != null)
15 office 69 {
54 office 70 if (_cancellationTokenSource != null) _cancellationTokenSource.Cancel();
22 office 71  
15 office 72 components.Dispose();
73 }
54 office 74  
15 office 75 base.Dispose(disposing);
76 }
77  
78 private async void button1_Click(object sender, EventArgs e)
79 {
41 office 80 var rows = dataGridView1.Rows.OfType<DataGridViewRow>().OrderBy(row => row.Index).ToList();
22 office 81 var count = rows.Count;
82  
83 toolStripProgressBar1.Minimum = 0;
84 toolStripProgressBar1.Maximum = count;
54 office 85 toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
22 office 86  
87 var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
88 {
89 try
90 {
91 switch (rowProgress)
92 {
93 case DataGridViewRowProgressSuccess<MemoryChannel> rowProgressSuccess:
54 office 94 dataGridView1.Rows[rowProgressSuccess.Row.Index].DefaultCellStyle.BackColor =
95 DefaultBackColor;
22 office 96  
53 office 97 switch (Configuration.Radio)
47 office 98 {
99 case "Yaesu FT-891":
100 var result = (Radios.Yaesu.FT_891.MemoryChannel)rowProgressSuccess.Data;
22 office 101  
47 office 102 rowProgress.Row.Cells["FrequencyColumn"].Value = result.Frequency;
54 office 103 rowProgress.Row.Cells["ClarifierDirectionColumn"].Value =
104 (char)result.ClarifierDirection;
47 office 105 rowProgress.Row.Cells["ClarifierOffsetColumn"].Value = result.ClarifierOffset;
106 rowProgress.Row.Cells["ClarColumn"].Value = result.Clar;
107 rowProgress.Row.Cells["ModeColumn"].Value = result.MemoryRadioMode.Name;
108 rowProgress.Row.Cells["CtcssColumn"].Value = (string)result.Ctcss;
109 rowProgress.Row.Cells["PhaseColumn"].Value = (string)result.Phase;
110 rowProgress.Row.Cells["TagColumn"].Value = result.Tag;
111 rowProgress.Row.Cells["TextColumn"].Value = result.Text;
112 rowProgress.Row.Tag = rowProgressSuccess.Data;
113 break;
114 }
41 office 115  
116 toolStripStatusLabel1.Text = $"{Resources.Read_memory_bank} {rowProgress.Index + 1}";
22 office 117 break;
54 office 118 case DataGridViewRowProgressFailure<int> rowProgressFailure:
22 office 119 Log.Error(rowProgressFailure.Exception, $"{Resources.Could_not_read_memory_bank}");
53 office 120 dataGridView1.Rows[rowProgressFailure.Row.Index].DefaultCellStyle.BackColor = Color.Red;
22 office 121  
54 office 122 toolStripStatusLabel1.Text =
123 $"{Resources.Could_not_read_memory_bank} {rowProgress.Index + 1}";
22 office 124 break;
125 }
126  
127 toolStripProgressBar1.Increment(1);
128 statusStrip1.Update();
129 }
41 office 130 catch (Exception exception)
22 office 131 {
41 office 132 Log.Error(exception, Resources.Unexpected_error_while_reading_memory_bank);
22 office 133 }
134 });
135  
136 await Task.Run(() => ReadMemoryBanks(rows, progress, _cancellationToken), _cancellationToken);
137  
138 if (!_cancellationToken.IsCancellationRequested)
139 {
140 toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
141 toolStripStatusLabel1.Text = "Done.";
142 }
15 office 143 }
144  
145 private async void button2_Click(object sender, EventArgs e)
146 {
41 office 147 var rows = dataGridView1.Rows.OfType<DataGridViewRow>().OrderBy(row => row.Index).ToList();
22 office 148 var count = rows.Count;
149  
150 toolStripProgressBar1.Minimum = 0;
151 toolStripProgressBar1.Maximum = count;
54 office 152 toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
22 office 153  
154 var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
155 {
156 try
157 {
158 switch (rowProgress)
159 {
160 case DataGridViewRowProgressSuccess<bool> rowProgressSuccess:
54 office 161 dataGridView1.Rows[rowProgressSuccess.Row.Index].DefaultCellStyle.BackColor =
162 DefaultBackColor;
22 office 163 var success = rowProgressSuccess.Data;
54 office 164  
41 office 165 if (success)
22 office 166 {
167 toolStripStatusLabel1.Text =
54 office 168 $"{Resources.Wrote_memory_bank} {rowProgress.Index + 1}";
22 office 169 toolStripProgressBar1.Increment(1);
170 statusStrip1.Update();
171 return;
172 }
173  
41 office 174 Log.Error($"{Resources.Could_not_write_memory_bank}");
22 office 175 break;
54 office 176 case DataGridViewRowProgressFailure<int> rowProgressFailure:
53 office 177 dataGridView1.Rows[rowProgressFailure.Row.Index].DefaultCellStyle.BackColor = Color.Red;
22 office 178 Log.Error(rowProgressFailure.Exception, $"{Resources.Could_not_write_memory_bank}");
179 break;
180 }
181  
41 office 182 toolStripStatusLabel1.Text =
183 $"{Resources.Could_not_write_memory_bank} {rowProgress.Index + 1}";
184 toolStripProgressBar1.Increment(1);
185 statusStrip1.Update();
22 office 186 }
41 office 187 catch (Exception exception)
188 {
189 Log.Error(exception, Resources.Unexpected_error_while_writing_memory_bank);
190 }
22 office 191 });
192  
193 await Task.Run(() => WriteMemoryBanks(rows, progress, _cancellationToken), _cancellationToken);
194  
195 if (!_cancellationToken.IsCancellationRequested)
196 {
197 toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
198 toolStripStatusLabel1.Text = "Done.";
199 }
15 office 200 }
201  
202 private void MemoryOrganizerForm_Load(object sender, EventArgs e)
203 {
47 office 204 // Generate columns based on radio type.
54 office 205 switch (Configuration.Radio)
47 office 206 {
207 case "Yaesu FT-891":
54 office 208 dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
209 { Name = "LocationColumn", HeaderText = "Location", ReadOnly = true });
210 dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
211 { Name = "FrequencyColumn", HeaderText = "Frequency" });
212 var clarifierDropDownColumn = new DataGridViewComboBoxColumn
213 { Name = "ClarifierDirectionColumn", HeaderText = "Clarifier" };
47 office 214 clarifierDropDownColumn.Items.AddRange(
215 "+",
216 "-"
217 );
218 dataGridView1.Columns.Add(clarifierDropDownColumn);
54 office 219 dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
220 { Name = "ClarifierOffsetColumn", HeaderText = "Offset" });
221 dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn
222 { Name = "ClarColumn", HeaderText = "Clar" });
223 var modeComboBoxColumn = new DataGridViewComboBoxColumn
224 { Name = "ModeColumn", HeaderText = "Mode" };
225 foreach (var name in MemoryRadioMode.Names)
51 office 226 modeComboBoxColumn.Items.Add(
227 name
228 );
54 office 229  
47 office 230 dataGridView1.Columns.Add(modeComboBoxColumn);
54 office 231 var ctcssComboBoxColumn = new DataGridViewComboBoxColumn
232 { Name = "CtcssColumn", HeaderText = "CTCSS" };
47 office 233 ctcssComboBoxColumn.Items.AddRange(
234 "Off",
235 "Enc/Dec",
236 "Enc"
237 );
238 dataGridView1.Columns.Add(ctcssComboBoxColumn);
54 office 239 var phaseComboBoxColumn = new DataGridViewComboBoxColumn
240 { Name = "PhaseColumn", HeaderText = "Phase" };
47 office 241 phaseComboBoxColumn.Items.AddRange(
242 "Simplex",
243 "Plus Shift",
244 "Minus Shift"
245 );
246 dataGridView1.Columns.Add(phaseComboBoxColumn);
54 office 247 dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn
248 { Name = "TagColumn", HeaderText = "Tag" });
249 dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
250 {
251 Name = "TextColumn", HeaderText = "Text",
252 MaxInputLength = Radios.Yaesu.FT_891.Constants.MaxTagCharacters
253 });
47 office 254 break;
255 }
256  
15 office 257 toolStripProgressBar1.Minimum = 0;
258 toolStripProgressBar1.Maximum = 98;
54 office 259 toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
15 office 260  
41 office 261 var memoryBankQueue = new ConcurrentQueue<string>();
262 var memoryBankAddRowsTaskCompletionSource = new TaskCompletionSource<object>();
15 office 263  
264 async void IdleHandler(object idleHandlerSender, EventArgs idleHandlerArgs)
265 {
41 office 266 await memoryBankAddRowsTaskCompletionSource.Task;
15 office 267  
268 try
269 {
270 if (!memoryBankQueue.TryDequeue(out var memoryBank))
271 {
272 Application.Idle -= IdleHandler;
273  
274 dataGridView1.Sort(dataGridView1.Columns["LocationColumn"], ListSortDirection.Ascending);
275 toolStripStatusLabel1.Text = "Done.";
276  
277 return;
278 }
279  
280 var index = dataGridView1.Rows.Add();
281  
54 office 282 switch (Configuration.Radio)
47 office 283 {
284 case "Yaesu FT-891":
285 dataGridView1.Rows[index].Cells["LocationColumn"].Value = memoryBank;
286 dataGridView1.Rows[index].Cells["FrequencyColumn"].Value = default;
287 dataGridView1.Rows[index].Cells["ClarifierDirectionColumn"].Value = default;
288 dataGridView1.Rows[index].Cells["ClarifierOffsetColumn"].Value = default;
289 dataGridView1.Rows[index].Cells["ClarColumn"].Value = default;
290 dataGridView1.Rows[index].Cells["ModeColumn"].Value = default;
291 dataGridView1.Rows[index].Cells["CtcssColumn"].Value = default;
292 dataGridView1.Rows[index].Cells["PhaseColumn"].Value = default;
293 dataGridView1.Rows[index].Cells["TagColumn"].Value = default;
294 dataGridView1.Rows[index].Cells["TextColumn"].Value = default;
295 break;
296 }
15 office 297  
47 office 298 toolStripStatusLabel1.Text = $"{Resources.Created_memory_bank} {memoryBank}";
15 office 299 toolStripProgressBar1.Increment(1);
300 statusStrip1.Update();
301 }
302 catch (Exception exception)
303 {
304 Log.Error(exception, Resources.Could_not_update_data_grid_view);
305 }
306 }
307  
308 Application.Idle += IdleHandler;
309 try
310 {
54 office 311 foreach (var memoryBank in _memoryBanks.GetMemoryBanks()) memoryBankQueue.Enqueue(memoryBank);
15 office 312  
41 office 313 memoryBankAddRowsTaskCompletionSource.TrySetResult(new { });
15 office 314 }
315 catch (Exception exception)
316 {
317 Application.Idle -= IdleHandler;
318  
319 Log.Error(exception, Resources.Unable_to_create_memory_banks);
320 }
321 }
322  
323 private void DataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
324 {
325 var dataGridView = (DataGridView)sender;
326  
327 if (dataGridView.CurrentCell is DataGridViewCheckBoxCell)
328 dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
329 }
330  
331 private void DataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
332 {
333 var dataGridView = (DataGridView)sender;
334  
335 dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
336 }
337  
338 private void DataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
339 {
340 }
341  
342 private void DataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
343 {
344 var dataGridView = (DataGridView)sender;
345  
54 office 346 if (e.RowIndex == -1 || e.ColumnIndex == -1) return;
15 office 347  
348 switch (dataGridView.Columns[e.ColumnIndex].Name)
349 {
350 case "EnableColumn":
351 //ProcessEnable(dataGridView.Rows[e.RowIndex]);
352 break;
353 }
354 }
355  
356 private void DataGridView1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
357 {
358 var dataGridView = (DataGridView)sender;
359  
360 if (e.RowIndex == -1 || e.ColumnIndex == -1 ||
361 !(dataGridView.Columns[e.ColumnIndex] is DataGridViewCheckBoxColumn))
362 return;
363  
364 dataGridView.EndEdit();
365 }
366  
367 private void DataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
368 {
369 var dataGridView = (DataGridView)sender;
370  
371 if (e.RowIndex == -1 || e.ColumnIndex == -1 ||
372 !(dataGridView.Columns[e.ColumnIndex] is DataGridViewCheckBoxColumn))
373 return;
374  
375 dataGridView.EndEdit();
376 }
377  
378 private void DataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
379 {
380 // @(-.-)@ -(o.o)- @(o_o)@
381 }
382  
51 office 383 private static IEnumerable<DataGridViewRow> GetSelectedDataGridViewRows(DataGridView dataGridView)
15 office 384 {
51 office 385 return dataGridView.SelectedRows.OfType<DataGridViewRow>().OrderBy(row => row.Index);
15 office 386 }
387  
54 office 388 private async Task ReadMemoryBanks(IReadOnlyList<DataGridViewRow> rows,
389 IProgress<DataGridViewRowProgress> progress,
390 CancellationToken cancellationToken)
15 office 391 {
392 var count = rows.Count;
393  
394 for (var i = 0; i < count && !cancellationToken.IsCancellationRequested; ++i)
395 try
396 {
41 office 397 var location = $"{rows[i].Cells["LocationColumn"].Value}";
15 office 398  
54 office 399 var result =
400 await _catAssemblies.CatReadAsync<MemoryChannel>("MT", new object[] { location },
401 cancellationToken);
15 office 402  
403 progress.Report(new DataGridViewRowProgressSuccess<MemoryChannel>(rows[i], i, result));
404 }
405 catch (UnexpectedRadioResponseException exception)
406 {
54 office 407 progress.Report(new DataGridViewRowProgressFailure<int>(rows[i], i, exception));
15 office 408 }
409 catch (Exception exception)
410 {
54 office 411 progress.Report(new DataGridViewRowProgressFailure<int>(rows[i], i, exception));
15 office 412 }
413 }
414  
54 office 415 private async Task WriteMemoryBanks(IReadOnlyList<DataGridViewRow> rows,
416 IProgress<DataGridViewRowProgress> progress,
417 CancellationToken cancellationToken)
15 office 418 {
419 var count = rows.Count;
420  
421 for (var i = 0; i < count && !cancellationToken.IsCancellationRequested; ++i)
422 try
423 {
47 office 424 var success = false;
15 office 425  
54 office 426 switch (Configuration.Radio)
47 office 427 {
428 case "Yaesu FT-891":
54 office 429 var memoryChannel =
430 (Radios.Yaesu.FT_891.MemoryChannel)MemoryChannel.Create(Configuration.Radio);
15 office 431  
47 office 432 memoryChannel.CurrentLocation = $"{rows[i].Cells["LocationColumn"].Value}";
433 memoryChannel.Frequency = int.Parse($"{rows[i].Cells["FrequencyColumn"].Value}");
54 office 434 memoryChannel.ClarifierDirection =
435 char.Parse($"{rows[i].Cells["ClarifierDirectionColumn"].Value}");
436 memoryChannel.ClarifierOffset =
437 int.Parse($"{rows[i].Cells["ClarifierOffsetColumn"].Value}");
47 office 438 memoryChannel.Clar = Convert.ToBoolean(rows[i].Cells["ClarColumn"].Value);
54 office 439 memoryChannel.MemoryRadioMode = Radios.Generic.MemoryRadioMode.Create(Configuration.Radio,
440 $"{rows[i].Cells["ModeColumn"].Value}");
47 office 441 memoryChannel.Ctcss = new Ctcss($"{rows[i].Cells["CtcssColumn"].Value}");
442 memoryChannel.Phase = new Phase($"{rows[i].Cells["PhaseColumn"].Value}");
443 memoryChannel.Tag = Convert.ToBoolean(rows[i].Cells["TagColumn"].Value);
444 memoryChannel.Text = $"{rows[i].Cells["TextColumn"].Value,-12}";
15 office 445  
54 office 446 success = await _catAssemblies.CatSetAsync<MemoryChannel, bool>("MT",
447 new object[] { memoryChannel }, cancellationToken);
47 office 448 break;
449 }
450  
451 progress.Report(new DataGridViewRowProgressSuccess<bool>(rows[i], i, success));
15 office 452 }
453 catch (UnexpectedRadioResponseException exception)
454 {
54 office 455 progress.Report(new DataGridViewRowProgressFailure<int>(rows[i], i, exception));
15 office 456 }
457 catch (Exception exception)
458 {
54 office 459 progress.Report(new DataGridViewRowProgressFailure<int>(rows[i], i, exception));
15 office 460 }
461 }
16 office 462  
463 private void importToolStripMenuItem_Click(object sender, EventArgs e)
464 {
465 openFileDialog1.ShowDialog();
466 }
467  
468 private void exportToolStripMenuItem_Click(object sender, EventArgs e)
469 {
470 saveFileDialog1.ShowDialog();
471 }
472  
473 private async void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
474 {
54 office 475 if (e.Cancel) return;
16 office 476  
477 var fileName = saveFileDialog1.FileName;
26 office 478 var list = new List<MemoryChannelIndexed>();
54 office 479 foreach (var row in dataGridView1.Rows.OfType<DataGridViewRow>().OrderBy(row => row.Index))
48 office 480 if (row.Tag is MemoryChannel memoryChannel)
16 office 481 {
26 office 482 var memoryChannelOrganizerBanks = new MemoryChannelIndexed(row.Index, memoryChannel);
16 office 483 list.Add(memoryChannelOrganizerBanks);
484 }
485  
486 var memoryBanks = list.ToArray();
487  
488 switch (await Serialization.Serialize(memoryBanks, fileName, "MemoryChannelOrganizerBank",
489 "<!ATTLIST MemoryChannelOrganizerBank xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>",
490 CancellationToken.None))
491 {
26 office 492 case SerializationSuccess<MemoryChannelIndexed[]> configuration:
16 office 493 Log.Information(Resources.Serialized_memory_banks);
494 break;
495 case SerializationFailure serializationFailure:
496 Log.Warning(serializationFailure.Exception.Message, Resources.Failed_to_serialize_memory_banks);
497 break;
498 }
499 }
500  
501 private async void openFileDialog1_FileOk(object sender, CancelEventArgs e)
502 {
54 office 503 if (e.Cancel) return;
16 office 504  
505 var fileName = openFileDialog1.FileName;
26 office 506 MemoryChannelIndexed[] memoryBanks = null;
16 office 507  
508 var deserializationResult =
26 office 509 await Serialization.Deserialize<MemoryChannelIndexed[]>(fileName,
54 office 510 "urn:hambook-memorychannelorganizerbank-schema", "MemoryChannelIndexed.xsd",
511 CancellationToken.None);
16 office 512  
513 switch (deserializationResult)
514 {
26 office 515 case SerializationSuccess<MemoryChannelIndexed[]> serializationSuccess:
16 office 516 Log.Information(Resources.Deserialized_memory_banks);
517 memoryBanks = serializationSuccess.Result;
518 break;
519 case SerializationFailure serializationFailure:
520 Log.Warning(serializationFailure.Exception, Resources.Failed_to_deserialize_memory_banks);
521 return;
522 }
523  
524 toolStripProgressBar1.Minimum = 0;
525 toolStripProgressBar1.Maximum = 98;
54 office 526 toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
16 office 527  
26 office 528 var memoryBankQueue = new ConcurrentQueue<MemoryChannelIndexed>();
16 office 529 var snapshotsQueuedTaskCompletionSource = new TaskCompletionSource<object>();
530  
531 async void IdleHandler(object idleHandlerSender, EventArgs idleHandlerArgs)
532 {
533 await snapshotsQueuedTaskCompletionSource.Task;
534  
535 try
536 {
537 if (!memoryBankQueue.TryDequeue(out var memoryBank))
538 {
539 Application.Idle -= IdleHandler;
540  
541 dataGridView1.Sort(dataGridView1.Columns["LocationColumn"], ListSortDirection.Ascending);
542 toolStripStatusLabel1.Text = "Done.";
543  
544 return;
545 }
54 office 546  
547 switch (Configuration.Radio)
47 office 548 {
549 case "Yaesu FT-891":
48 office 550 var memoryChannel = (Radios.Yaesu.FT_891.MemoryChannel)memoryBank.MemoryChannel;
551  
54 office 552 dataGridView1.Rows[memoryBank.Index].Cells["FrequencyColumn"].Value =
553 memoryBank.MemoryChannel.Frequency;
554 dataGridView1.Rows[memoryBank.Index].Cells["ClarifierDirectionColumn"].Value =
555 (char)memoryChannel.ClarifierDirection;
556 dataGridView1.Rows[memoryBank.Index].Cells["ClarifierOffsetColumn"].Value =
557 memoryChannel.ClarifierOffset;
48 office 558 dataGridView1.Rows[memoryBank.Index].Cells["ClarColumn"].Value = memoryChannel.Clar;
54 office 559 dataGridView1.Rows[memoryBank.Index].Cells["ModeColumn"].Value =
560 memoryBank.MemoryChannel.MemoryRadioMode.Name;
561 dataGridView1.Rows[memoryBank.Index].Cells["CtcssColumn"].Value =
562 (string)memoryChannel.Ctcss;
563 dataGridView1.Rows[memoryBank.Index].Cells["PhaseColumn"].Value =
564 (string)memoryChannel.Phase;
565 dataGridView1.Rows[memoryBank.Index].Cells["TagColumn"].Value =
566 memoryBank.MemoryChannel.Tag;
567 dataGridView1.Rows[memoryBank.Index].Cells["TextColumn"].Value =
568 memoryBank.MemoryChannel.Text;
47 office 569 dataGridView1.Rows[memoryBank.Index].Tag = memoryBank.MemoryChannel;
570 break;
571 }
16 office 572  
573 toolStripProgressBar1.Increment(1);
574 statusStrip1.Update();
575 }
576 catch (Exception exception)
577 {
578 Log.Error(exception, Resources.Could_not_update_data_grid_view);
579 }
580 }
581  
582 Application.Idle += IdleHandler;
583 try
584 {
54 office 585 foreach (var memoryChannel in memoryBanks) memoryBankQueue.Enqueue(memoryChannel);
16 office 586  
587 snapshotsQueuedTaskCompletionSource.TrySetResult(new { });
588 }
589 catch (Exception exception)
590 {
591 Application.Idle -= IdleHandler;
592  
593 Log.Error(exception, Resources.Unable_to_create_memory_banks);
594 }
595 }
22 office 596  
597 private void MemoryOrganizerForm_FormClosing(object sender, FormClosingEventArgs e)
598 {
54 office 599 if (_cancellationTokenSource != null) _cancellationTokenSource.Cancel();
22 office 600 }
40 office 601  
41 office 602 private async void readToolStripMenuItem_Click(object sender, EventArgs e)
40 office 603 {
54 office 604 if (_readLinkedCancellationTokenSource != null)
605 {
606 _readLinkedCancellationTokenSource.Cancel();
607 _readLinkedCancellationTokenSource = null;
608 }
41 office 609  
54 office 610 if (_readMemoryBanksTask != null)
51 office 611 {
54 office 612 await _readMemoryBanksTask;
613 _readMemoryBanksTask = null;
51 office 614 }
41 office 615  
54 office 616 _readCancellationTokenSource = new CancellationTokenSource();
617 _readLinkedCancellationTokenSource =
618 CancellationTokenSource.CreateLinkedTokenSource(new[]
619 { _cancellationTokenSource.Token, _cancellationToken });
620  
621 _readMemoryBanksTask = ReadMemoryBanks(_readLinkedCancellationTokenSource.Token);
622 }
623  
624 private async Task ReadMemoryBanks(CancellationToken cancellationToken)
625 {
626 var rows = GetSelectedDataGridViewRows(dataGridView1);
627  
628 if (!rows.Any()) return;
629  
51 office 630 var list = rows.ToList();
631  
632 var count = list.Count;
633  
41 office 634 toolStripProgressBar1.Minimum = 0;
635 toolStripProgressBar1.Maximum = count;
54 office 636 toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
41 office 637  
638 var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
639 {
640 try
641 {
642 switch (rowProgress)
643 {
47 office 644 case DataGridViewRowProgressSuccess<MemoryChannel> rowProgressSuccess:
54 office 645 dataGridView1.Rows[rowProgressSuccess.Row.Index].DefaultCellStyle.BackColor =
646 DefaultBackColor;
53 office 647  
648 switch (rowProgressSuccess.Data)
47 office 649 {
650 case Radios.Yaesu.FT_891.MemoryChannel memoryChannel:
651 rowProgress.Row.Cells["FrequencyColumn"].Value = memoryChannel.Frequency;
54 office 652 rowProgress.Row.Cells["ClarifierDirectionColumn"].Value =
653 (char)memoryChannel.ClarifierDirection;
654 rowProgress.Row.Cells["ClarifierOffsetColumn"].Value =
655 memoryChannel.ClarifierOffset;
47 office 656 rowProgress.Row.Cells["ClarColumn"].Value = memoryChannel.Clar;
657 rowProgress.Row.Cells["ModeColumn"].Value = memoryChannel.MemoryRadioMode.Name;
658 rowProgress.Row.Cells["CtcssColumn"].Value = (string)memoryChannel.Ctcss;
659 rowProgress.Row.Cells["PhaseColumn"].Value = (string)memoryChannel.Phase;
660 rowProgress.Row.Cells["TagColumn"].Value = memoryChannel.Tag;
661 rowProgress.Row.Cells["TextColumn"].Value = memoryChannel.Text;
662 rowProgress.Row.Tag = rowProgressSuccess.Data;
663 break;
664 }
41 office 665  
666 toolStripStatusLabel1.Text = $"{Resources.Read_memory_bank} {rowProgress.Index + 1}";
667 break;
54 office 668 case DataGridViewRowProgressFailure<int> rowProgressFailure:
41 office 669 Log.Error(rowProgressFailure.Exception, $"{Resources.Could_not_read_memory_bank}");
53 office 670 dataGridView1.Rows[rowProgressFailure.Row.Index].DefaultCellStyle.BackColor = Color.Red;
41 office 671  
54 office 672 toolStripStatusLabel1.Text =
673 $"{Resources.Could_not_read_memory_bank} {rowProgress.Index + 1}";
41 office 674 break;
675 }
676  
677 toolStripProgressBar1.Increment(1);
678 statusStrip1.Update();
679 }
680 catch (Exception exception)
681 {
682 Log.Error(exception, Resources.Unexpected_error_while_reading_memory_bank);
683 }
684 });
685  
54 office 686 await Task.Run(() => ReadMemoryBanks(list, progress, cancellationToken), cancellationToken);
41 office 687  
688 if (!_cancellationToken.IsCancellationRequested)
689 {
690 toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
691 toolStripStatusLabel1.Text = "Done.";
692 }
40 office 693 }
41 office 694  
695 private async void writeToolStripMenuItem_Click(object sender, EventArgs e)
696 {
54 office 697 if (_writeLinkedCancellationTokenSource != null)
698 {
699 _writeLinkedCancellationTokenSource.Cancel();
700 _writeLinkedCancellationTokenSource = null;
701 }
41 office 702  
54 office 703 if (_writeMemoryBanksTask != null)
51 office 704 {
54 office 705 await _writeMemoryBanksTask;
706 _writeMemoryBanksTask = null;
51 office 707 }
708  
54 office 709 _writeCancellationTokenSource = new CancellationTokenSource();
710 _writeLinkedCancellationTokenSource =
711 CancellationTokenSource.CreateLinkedTokenSource(new[]
712 { _cancellationTokenSource.Token, _cancellationToken });
713  
714 _writeMemoryBanksTask = WriteMemoryBanks(_writeLinkedCancellationTokenSource.Token);
715 }
716  
717 private async Task WriteMemoryBanks(CancellationToken cancellationToken)
718 {
719 var rows = GetSelectedDataGridViewRows(dataGridView1);
720  
721 if (!rows.Any()) return;
722  
51 office 723 var list = rows.ToList();
724  
725 var count = list.Count;
726  
41 office 727 toolStripProgressBar1.Minimum = 0;
728 toolStripProgressBar1.Maximum = count;
54 office 729 toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
41 office 730  
731 var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
732 {
733 try
734 {
735 switch (rowProgress)
736 {
737 case DataGridViewRowProgressSuccess<bool> rowProgressSuccess:
54 office 738 dataGridView1.Rows[rowProgressSuccess.Row.Index].DefaultCellStyle.BackColor =
739 DefaultBackColor;
41 office 740 var success = rowProgressSuccess.Data;
741  
742 if (success)
743 {
744 toolStripStatusLabel1.Text =
54 office 745 $"{Resources.Wrote_memory_bank} {rowProgress.Index + 1}";
41 office 746 toolStripProgressBar1.Increment(1);
747 statusStrip1.Update();
54 office 748  
41 office 749 return;
750 }
751  
752 Log.Error($"{Resources.Could_not_write_memory_bank}");
753 break;
54 office 754 case DataGridViewRowProgressFailure<int> rowProgressFailure:
41 office 755 Log.Error(rowProgressFailure.Exception, $"{Resources.Could_not_write_memory_bank}");
53 office 756 dataGridView1.Rows[rowProgressFailure.Row.Index].DefaultCellStyle.BackColor = Color.Red;
41 office 757 break;
758 }
759  
760 toolStripStatusLabel1.Text =
761 $"{Resources.Could_not_write_memory_bank} {rowProgress.Index + 1}";
762 toolStripProgressBar1.Increment(1);
763 statusStrip1.Update();
764 }
765 catch (Exception exception)
766 {
767 Log.Error(exception, Resources.Unexpected_error_while_writing_memory_bank);
768 }
769 });
770  
54 office 771 await Task.Run(() => WriteMemoryBanks(list, progress, cancellationToken), cancellationToken);
41 office 772  
773 if (!_cancellationToken.IsCancellationRequested)
774 {
775 toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
776 toolStripStatusLabel1.Text = "Done.";
777 }
778 }
51 office 779  
780 private async void readFromVFOAToolStripMenuItem_Click(object sender, EventArgs e)
781 {
782 var rows = GetSelectedDataGridViewRows(dataGridView1);
783  
54 office 784 if (!rows.Any()) return;
51 office 785  
786 var list = rows.ToList();
787  
788 try
789 {
790 foreach (var row in list)
791 {
792 var fa = await _catAssemblies.CatReadAsync<int>("FA", new object[] { }, _cancellationToken);
793  
54 office 794 row.Cells["FrequencyColumn"].Value = $"{fa}";
51 office 795 }
796 }
797 catch (Exception exception)
798 {
799 Log.Error(exception, Resources.Failed_to_read_VFO_A);
800 }
801 }
802  
803 private async void readFromVFOBToolStripMenuItem_Click(object sender, EventArgs e)
804 {
805 var rows = GetSelectedDataGridViewRows(dataGridView1);
806  
54 office 807 if (!rows.Any()) return;
51 office 808  
809 var list = rows.ToList();
810  
811 try
812 {
813 foreach (var row in list)
814 {
815 var fb = await _catAssemblies.CatReadAsync<int>("FB", new object[] { }, _cancellationToken);
816  
817 row.Cells["FrequencyColumn"].Value = $"{fb}";
818 }
819 }
820 catch (Exception exception)
821 {
822 Log.Error(exception, Resources.Failed_to_read_VFO_B);
823 }
824 }
825  
826 private async void memoryChannelToolStripMenuItem_Click(object sender, EventArgs e)
827 {
828 var rows = GetSelectedDataGridViewRows(dataGridView1);
829  
54 office 830 if (!rows.Any()) return;
51 office 831  
832 var row = rows.First();
833  
834 try
835 {
54 office 836 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly()
837 .GetManifestResourceStream("HamBook.Effects.pot.wav")))
51 office 838 {
54 office 839 await _catAssemblies.CatWriteAsync<string>("MC", new[] { row.Cells["LocationColumn"].Value },
840 _cancellationToken);
51 office 841  
842 soundPlayer.Play();
843 }
844 }
845 catch (Exception exception)
846 {
847 Log.Error(exception, Resources.Failed_to_set_memory_channel);
848 }
849 }
850  
851 private async void frequencyToolStripMenuItem_Click(object sender, EventArgs e)
852 {
853 var rows = GetSelectedDataGridViewRows(dataGridView1);
854  
54 office 855 if (!rows.Any()) return;
51 office 856  
857 var row = rows.First();
858  
859 try
860 {
54 office 861 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly()
862 .GetManifestResourceStream("HamBook.Effects.pot.wav")))
51 office 863 {
54 office 864 if (await _catAssemblies.CatSetAsync<int, bool>("FA", new[] { row.Cells["FrequencyColumn"].Value },
865 _cancellationToken))
51 office 866 if (Configuration.Navigation.MouseScrollSound)
867 soundPlayer.Play();
868 }
869 }
870 catch (Exception exception)
871 {
872 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
873 }
874 }
875  
876 private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
877 {
878 var dataGridView = (DataGridView)sender;
879  
880 var hitTest = dataGridView.HitTest(e.X, e.Y);
881  
882 switch (e.Button)
883 {
884 case MouseButtons.Right:
54 office 885 if (GetSelectedDataGridViewRows(dataGridView).Count() > 1) return;
51 office 886  
887 dataGridView.ClearSelection();
54 office 888 if (hitTest.RowIndex != -1) dataGridView.Rows[hitTest.RowIndex].Selected = true;
51 office 889 break;
890 }
891 }
52 office 892  
893 private IEnumerable<DataGridViewRow> CopySelectedRows(DataGridView dataGridView)
894 {
895 foreach (var row in GetSelectedDataGridViewRows(dataGridView))
896 {
897 var clone = row.Clone() as DataGridViewRow;
898  
899 for (var i = 0; i < row.Cells.Count; ++i)
900 {
54 office 901 if (row.Cells[i].ReadOnly) continue;
52 office 902  
903 clone.Cells[i].Value = row.Cells[i].Value;
904 }
905  
906 yield return clone;
907 }
908 }
54 office 909  
52 office 910 private void DeleteSelectedRows(DataGridView dataGridView)
911 {
912 foreach (var row in GetSelectedDataGridViewRows(dataGridView))
913 for (var i = 0; i < row.Cells.Count; ++i)
914 {
54 office 915 if (row.Cells[i].ReadOnly) continue;
52 office 916  
917 row.Cells[i].Value = default;
918 }
919 }
920  
921  
922 private void PasteSelectedRows(DataGridView dataGridView, IEnumerable<DataGridViewRow> pasteRows)
923 {
924 var rows = pasteRows.ToList();
54 office 925 if (rows.Count == 0) return;
52 office 926  
927 foreach (var row in GetSelectedDataGridViewRows(dataGridView))
928 {
54 office 929 if (rows.Count == 0) return;
52 office 930  
931 var paste = rows[0];
932 for (var i = 0; i < paste.Cells.Count; ++i)
933 {
54 office 934 if (row.Cells[i].ReadOnly) continue;
52 office 935 row.Cells[i].Value = paste.Cells[i].Value;
936 }
937  
938 rows.RemoveAt(0);
939 }
940 }
941  
942 private IEnumerable<DataGridViewRow> CutSelectedRows(DataGridView dataGridView)
943 {
944 foreach (var row in GetSelectedDataGridViewRows(dataGridView))
945 {
946 var clone = row.Clone() as DataGridViewRow;
947  
948 for (var i = 0; i < row.Cells.Count; ++i)
949 {
54 office 950 if (row.Cells[i].ReadOnly) continue;
52 office 951  
952 clone.Cells[i].Value = row.Cells[i].Value;
953  
954 row.Cells[i].Value = default;
955 }
54 office 956  
52 office 957 yield return clone;
958 }
959 }
960  
961 private void cutToolStripMenuItem1_Click(object sender, EventArgs e)
962 {
963 _clipboardRows = new List<DataGridViewRow>();
54 office 964 foreach (var row in CutSelectedRows(dataGridView1)) _clipboardRows.Add(row);
52 office 965 }
966  
967 private void copyToolStripMenuItem1_Click(object sender, EventArgs e)
968 {
969 _clipboardRows = new List<DataGridViewRow>();
54 office 970 foreach (var row in CopySelectedRows(dataGridView1)) _clipboardRows.Add(row);
52 office 971 }
972  
973 private void pasteToolStripMenuItem1_Click(object sender, EventArgs e)
974 {
975 PasteSelectedRows(dataGridView1, _clipboardRows);
976 }
977  
978 private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
979 {
980 DeleteSelectedRows(dataGridView1);
981 }
53 office 982  
983 private void dataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
984 {
54 office 985 var dataGridView = sender as DataGridView;
53 office 986 foreach (DataGridViewCell cell in dataGridView.Rows[e.RowIndex].Cells)
987 {
54 office 988 if (cell.Selected == false) continue;
53 office 989 var bgColorCell = Color.White;
54 office 990 if (cell.Style.BackColor != Color.Empty)
991 bgColorCell = cell.Style.BackColor;
992 else if (cell.InheritedStyle.BackColor != Color.Empty) bgColorCell = cell.InheritedStyle.BackColor;
53 office 993 cell.Style.SelectionBackColor = MixColor(bgColorCell, Color.FromArgb(0, 150, 255), 10, 4);
994 }
995 }
996  
997 //Mix two colors
998 //Example: Steps=10 & Position=4 makes Color2 mix 40% into Color1
999 /// <summary>
54 office 1000 /// Mix two colors.
53 office 1001 /// </summary>
54 office 1002 /// <param name="color1"></param>
1003 /// <param name="color2"></param>
1004 /// <param name="steps"></param>
1005 /// <param name="position"></param>
53 office 1006 /// <example>Steps=10 & Positon=4 makes Color2 mix 40% into Color1</example>
1007 /// <remarks>https://stackoverflow.com/questions/38337849/transparent-selectionbackcolor-for-datagridview-cell</remarks>
1008 /// <returns></returns>
54 office 1009 public static Color MixColor(Color color1, Color color2, int steps, int position)
53 office 1010 {
54 office 1011 if (position <= 0 || steps <= 1) return color1;
1012 if (position >= steps) return color2;
53 office 1013 return Color.FromArgb(
54 office 1014 color1.R + (color2.R - color1.R) / steps * position,
1015 color1.G + (color2.G - color1.G) / steps * position,
1016 color1.B + (color2.B - color1.B) / steps * position
1017 );
53 office 1018 }
15 office 1019 }
54 office 1020 }