HamBook – Blame information for rev 54
?pathlinks?
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 | } |