Horizon

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 11  →  ?path2? @ 12
/Horizon/Snapshots/SnapshotManagerForm.cs
@@ -6,8 +6,11 @@
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -14,8 +17,13 @@
using Horizon.Database;
using Horizon.Utilities;
using Microsoft.WindowsAPICodePack.Dialogs;
using Mono.Zeroconf;
using Mono.Zeroconf.Providers.Bonjour;
using Newtonsoft.Json;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Utilities.Net;
using Serilog;
using WatsonTcp;
 
namespace Horizon.Snapshots
{
@@ -55,6 +63,12 @@
 
private readonly CancellationToken _localCancellationToken;
 
private readonly Mono.Zeroconf.ServiceBrowser _horizonServiceBrowser;
 
private IResolvableService _resolvedService;
 
private readonly ConcurrentDictionary<string, Service> _discoveredHorizonNetworkShares;
 
#endregion
 
#region Constructors, Destructors and Finalizers
@@ -69,6 +83,10 @@
 
_localCancellationTokenSource = new CancellationTokenSource();
_localCancellationToken = _localCancellationTokenSource.Token;
 
_discoveredHorizonNetworkShares = new ConcurrentDictionary<string, Service>();
_horizonServiceBrowser = new Mono.Zeroconf.ServiceBrowser();
_horizonServiceBrowser.ServiceAdded += OnHorizonServiceBrowserOnServiceAdded;
}
 
public SnapshotManagerForm(MainForm mainForm, SnapshotDatabase snapshotDatabase,
@@ -96,6 +114,8 @@
 
_snapshotDatabase.SnapshotCreate -= SnapshotManager_SnapshotCreate;
 
_horizonServiceBrowser.ServiceAdded -= OnHorizonServiceBrowserOnServiceAdded;
_horizonServiceBrowser.Dispose();
_localCancellationTokenSource.Cancel();
 
base.Dispose(disposing);
@@ -104,6 +124,16 @@
#endregion
 
#region Event Handlers
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
}
 
private void contextMenuStrip1_Opened(object sender, EventArgs e)
{
_horizonServiceBrowser.Browse("_horizon._tcp", "local");
}
 
private void DataGridView1_MouseDown(object sender, MouseEventArgs e)
{
var dataGridView = (DataGridView)sender;
@@ -588,6 +618,10 @@
 
private async void SnapshotManagerForm_Load(object sender, EventArgs e)
{
// Start browsing for network services.
_horizonServiceBrowser.Browse("_horizon._tcp", "local");
 
// Load snapshots.
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = (int)await _snapshotDatabase.CountSnapshotsAsync(_cancellationToken);
 
@@ -647,6 +681,77 @@
}
}
 
private void OnHorizonServiceBrowserOnServiceAdded(object o, Mono.Zeroconf.ServiceBrowseEventArgs args)
{
_resolvedService = args.Service;
 
Log.Information("Found Service: {0}", _resolvedService.Name);
 
_resolvedService.Resolved += OnServiceOnResolved;
 
_resolvedService.Resolve();
 
_resolvedService.Resolved -= OnServiceOnResolved;
}
 
private void OnServiceOnResolved(object o, ServiceResolvedEventArgs args)
{
var service = (Service) args.Service;
 
Log.Information("Resolved Service: {0} - {1}:{2} ({3} TXT record entries)", service.FullName, service.HostEntry.AddressList[0], service.UPort, service.TxtRecord.Count);
 
_discoveredHorizonNetworkShares.TryAdd(service.Name, service);
var discoveredServiceMenuItem = new ToolStripMenuItem(service.Name, null, OnShareWithNodeClicked);
discoveredServiceMenuItem.Tag = service;
 
shareToToolStripMenuItem.DropDownItems.Add(discoveredServiceMenuItem);
}
 
private async void OnShareWithNodeClicked(object sender, EventArgs e)
{
var toolStripMenuItem = (ToolStripMenuItem)sender;
 
var service = (Service)toolStripMenuItem.Tag;
 
var rows = GetSelectedDataGridViewRows(dataGridView1);
 
var count = rows.Count;
 
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = count;
 
var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
{
if (rowProgress is DataGridViewRowProgressFailure rowProgressFailure)
{
Log.Error(rowProgressFailure.Exception, "Unable to transfer data.");
 
toolStripStatusLabel1.Text =
$"Could not transfer {rowProgress.Row.Cells["NameColumn"].Value}...";
toolStripProgressBar1.Value = rowProgress.Index + 1;
 
statusStrip1.Update();
 
return;
}
 
toolStripStatusLabel1.Text =
$"Transferred {rowProgress.Row.Cells["NameColumn"].Value}...";
toolStripProgressBar1.Value = rowProgress.Index + 1;
 
statusStrip1.Update();
});
 
await Task.Run(() => TransferFiles(rows, service, progress, _cancellationToken), _cancellationToken);
 
if (_cancellationToken.IsCancellationRequested)
{
toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
toolStripStatusLabel1.Text = "Done.";
}
}
 
private void SnapshotManagerForm_Closing(object sender, FormClosingEventArgs e)
{
_cancellationTokenSource.Cancel();
@@ -1307,7 +1412,42 @@
#endregion
 
#region Private Methods
private void DataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
DataGridView dataGridView = sender as DataGridView;
foreach (DataGridViewCell cell in dataGridView.Rows[e.RowIndex].Cells)
{
if (cell.Selected == false) { continue; }
var bgColorCell = Color.White;
if (cell.Style.BackColor != Color.Empty) { bgColorCell = cell.Style.BackColor; }
else if (cell.InheritedStyle.BackColor != Color.Empty) { bgColorCell = cell.InheritedStyle.BackColor; }
cell.Style.SelectionBackColor = MixColor(bgColorCell, Color.FromArgb(0, 150, 255), 10, 4);
}
}
 
//Mix two colors
//Example: Steps=10 & Position=4 makes Color2 mix 40% into Color1
/// <summary>
/// Mix two colors.
/// </summary>
/// <param name="Color1"></param>
/// <param name="Color2"></param>
/// <param name="Steps"></param>
/// <param name="Position"></param>
/// <example>Steps=10 & Positon=4 makes Color2 mix 40% into Color1</example>
/// <remarks>https://stackoverflow.com/questions/38337849/transparent-selectionbackcolor-for-datagridview-cell</remarks>
/// <returns></returns>
public static Color MixColor(Color Color1, Color Color2, int Steps, int Position)
{
if (Position <= 0 || Steps <= 1) { return Color1; }
if (Position >= Steps) { return Color2; }
return Color.FromArgb(
Color1.R + ((Color2.R - Color1.R) / Steps * Position),
Color1.G + ((Color2.G - Color1.G) / Steps * Position),
Color1.B + ((Color2.B - Color1.B) / Steps * Position)
);
}
 
private async Task DeleteFiles(IReadOnlyList<DataGridViewRow> rows, IProgress<DataGridViewRowProgress> progress,
CancellationToken cancellationToken)
{
@@ -1410,6 +1550,48 @@
}
}
 
 
private async Task TransferFiles(IReadOnlyList<DataGridViewRow> rows, Service service,
IProgress<DataGridViewRowProgress> progress, CancellationToken cancellationToken)
{
var client = new WatsonTcpClient($"{service.HostEntry.AddressList[0]}", service.UPort);
client.Events.MessageReceived += (sender, args) =>
{
Log.Information($"{args.Data.Length} byte long message received from {args.Client.IpPort}");
};
 
try
{
client.Connect();
 
var count = rows.Count;
 
for (var i = 0; i < count && !cancellationToken.IsCancellationRequested; ++i)
{
try
{
var completeSnapshot = await _snapshotDatabase.GetCompleteSnapshot((string)rows[i].Cells["HashColumn"].Value, cancellationToken);
 
var jsonSnapshot = JsonConvert.SerializeObject(completeSnapshot);
 
await client.SendAsync(jsonSnapshot, null, cancellationToken);
 
progress.Report(new DataGridViewRowProgressSuccess(rows[i], i));
}
catch (Exception exception)
{
progress.Report(new DataGridViewRowProgressFailure(rows[i], i, exception));
}
}
}
finally
{
client.Dispose();
}
}
 
private async Task RevertFile(IReadOnlyList<DataGridViewRow> rows, IProgress<DataGridViewRowProgress> progress,
CancellationToken cancellationToken)
{
@@ -1656,41 +1838,5 @@
}
 
#endregion
 
private void DataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
DataGridView dataGridView = sender as DataGridView;
foreach (DataGridViewCell cell in dataGridView.Rows[e.RowIndex].Cells)
{
if (cell.Selected == false) { continue; }
var bgColorCell = Color.White;
if (cell.Style.BackColor != Color.Empty) { bgColorCell = cell.Style.BackColor; }
else if (cell.InheritedStyle.BackColor != Color.Empty) { bgColorCell = cell.InheritedStyle.BackColor; }
cell.Style.SelectionBackColor = MixColor(bgColorCell, Color.FromArgb(0, 150, 255), 10, 4);
}
}
 
//Mix two colors
//Example: Steps=10 & Position=4 makes Color2 mix 40% into Color1
/// <summary>
/// Mix two colors.
/// </summary>
/// <param name="Color1"></param>
/// <param name="Color2"></param>
/// <param name="Steps"></param>
/// <param name="Position"></param>
/// <example>Steps=10 & Positon=4 makes Color2 mix 40% into Color1</example>
/// <remarks>https://stackoverflow.com/questions/38337849/transparent-selectionbackcolor-for-datagridview-cell</remarks>
/// <returns></returns>
public static Color MixColor(Color Color1, Color Color2, int Steps, int Position)
{
if (Position <= 0 || Steps <= 1) { return Color1; }
if (Position >= Steps) { return Color2; }
return Color.FromArgb(
Color1.R + ((Color2.R - Color1.R) / Steps * Position),
Color1.G + ((Color2.G - Color1.G) / Steps * Position),
Color1.B + ((Color2.B - Color1.B) / Steps * Position)
);
}
}
}