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