diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs index daa26395..fe0e3c04 100755 --- a/shadowsocks-csharp/Model/Server.cs +++ b/shadowsocks-csharp/Model/Server.cs @@ -58,11 +58,7 @@ namespace Shadowsocks.Model return server.GetHashCode() ^ server_port; } - public override bool Equals(object obj) - { - Server o2 = (Server)obj; - return server == o2.server && server_port == o2.server_port; - } + public override bool Equals(object obj) => obj is Server o2 && server == o2.server && server_port == o2.server_port; public override string ToString() { diff --git a/shadowsocks-csharp/View/QRCodeForm.Designer.cs b/shadowsocks-csharp/View/QRCodeForm.Designer.cs index 0dbc2da3..7e83616a 100755 --- a/shadowsocks-csharp/View/QRCodeForm.Designer.cs +++ b/shadowsocks-csharp/View/QRCodeForm.Designer.cs @@ -28,73 +28,39 @@ /// private void InitializeComponent() { - this.pictureBox1 = new System.Windows.Forms.PictureBox(); - this.listBox1 = new System.Windows.Forms.ListBox(); - this.textBoxURL = new System.Windows.Forms.TextBox(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.elementHost1 = new System.Windows.Forms.Integration.ElementHost(); + this.serverSharingView1 = new Shadowsocks.Views.ServerSharingView(); this.SuspendLayout(); // - // pictureBox1 + // elementHost1 // - this.pictureBox1.Location = new System.Drawing.Point(10, 10); - this.pictureBox1.Margin = new System.Windows.Forms.Padding(0); - this.pictureBox1.Name = "pictureBox1"; - this.pictureBox1.Size = new System.Drawing.Size(210, 210); - this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; - this.pictureBox1.TabIndex = 1; - this.pictureBox1.TabStop = false; - // - // listBox1 - // - this.listBox1.DisplayMember = "Value"; - this.listBox1.FormattingEnabled = true; - this.listBox1.ItemHeight = 12; - this.listBox1.Location = new System.Drawing.Point(224, 10); - this.listBox1.Name = "listBox1"; - this.listBox1.ScrollAlwaysVisible = true; - this.listBox1.Size = new System.Drawing.Size(227, 208); - this.listBox1.TabIndex = 2; - this.listBox1.ValueMember = "Key"; - this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); - // - // textBoxURL - // - this.textBoxURL.Location = new System.Drawing.Point(10, 227); - this.textBoxURL.Name = "textBoxURL"; - this.textBoxURL.ReadOnly = true; - this.textBoxURL.Size = new System.Drawing.Size(441, 21); - this.textBoxURL.TabIndex = 3; - this.textBoxURL.Click += new System.EventHandler(this.textBoxURL_Click); + this.elementHost1.Dock = System.Windows.Forms.DockStyle.Fill; + this.elementHost1.Location = new System.Drawing.Point(0, 0); + this.elementHost1.Margin = new System.Windows.Forms.Padding(0); + this.elementHost1.Name = "elementHost1"; + this.elementHost1.Size = new System.Drawing.Size(600, 340); + this.elementHost1.TabIndex = 0; + this.elementHost1.Text = "elementHost1"; + this.elementHost1.Child = this.serverSharingView1; // // QRCodeForm // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.AutoSize = true; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.BackColor = System.Drawing.Color.White; - this.ClientSize = new System.Drawing.Size(457, 257); - this.Controls.Add(this.textBoxURL); - this.Controls.Add(this.listBox1); - this.Controls.Add(this.pictureBox1); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.MaximizeBox = false; - this.MinimizeBox = false; + this.ClientSize = new System.Drawing.Size(600, 340); + this.Controls.Add(this.elementHost1); + this.Margin = new System.Windows.Forms.Padding(8); this.Name = "QRCodeForm"; - this.Padding = new System.Windows.Forms.Padding(10); this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "QRCode and URL"; this.Load += new System.EventHandler(this.QRCodeForm_Load); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); this.ResumeLayout(false); - this.PerformLayout(); - } #endregion - private System.Windows.Forms.PictureBox pictureBox1; - private System.Windows.Forms.ListBox listBox1; - private System.Windows.Forms.TextBox textBoxURL; + private System.Windows.Forms.Integration.ElementHost elementHost1; + private Views.ServerSharingView serverSharingView1; } } \ No newline at end of file diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs index d8fc8c60..4ff0838a 100755 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -27,64 +27,9 @@ namespace Shadowsocks.View this.Text = I18N.GetString("QRCode and URL"); } - private void GenQR(string ssconfig) - { - string qrText = ssconfig; - QRCode code = ZXing.QrCode.Internal.Encoder.encode(qrText, ErrorCorrectionLevel.M); - ByteMatrix m = code.Matrix; - int blockSize = Math.Max(pictureBox1.Height/m.Height, 1); - - var qrWidth = m.Width*blockSize; - var qrHeight = m.Height*blockSize; - var dWidth = pictureBox1.Width - qrWidth; - var dHeight = pictureBox1.Height - qrHeight; - var maxD = Math.Max(dWidth, dHeight); - pictureBox1.SizeMode = maxD >= 7*blockSize ? PictureBoxSizeMode.Zoom : PictureBoxSizeMode.CenterImage; - - Bitmap drawArea = new Bitmap((m.Width*blockSize), (m.Height*blockSize)); - using (Graphics g = Graphics.FromImage(drawArea)) - { - g.Clear(Color.White); - using (Brush b = new SolidBrush(Color.Black)) - { - for (int row = 0; row < m.Width; row++) - { - for (int col = 0; col < m.Height; col++) - { - if (m[row, col] != 0) - { - g.FillRectangle(b, blockSize*row, blockSize*col, blockSize, blockSize); - } - } - } - } - } - pictureBox1.Image = drawArea; - } - private void QRCodeForm_Load(object sender, EventArgs e) { - Configuration config = Configuration.Load(); - List> serverDatas = config.configs.Select( - server => - new KeyValuePair(server.GetURL(config.generateLegacyUrl), server.ToString()) - ).ToList(); - listBox1.DataSource = serverDatas; - int selectIndex = serverDatas.FindIndex(serverData => serverData.Key.StartsWith(code)); - if (selectIndex >= 0) listBox1.SetSelected(selectIndex, true); - } - - private void listBox1_SelectedIndexChanged(object sender, EventArgs e) - { - var url = (sender as ListBox)?.SelectedValue.ToString(); - GenQR(url); - textBoxURL.Text = url; - } - - private void textBoxURL_Click(object sender, EventArgs e) - { - textBoxURL.SelectAll(); } } } diff --git a/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs b/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs new file mode 100644 index 00000000..24e4096e --- /dev/null +++ b/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs @@ -0,0 +1,109 @@ +using ReactiveUI; +using Shadowsocks.Model; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Windows.Media.Imaging; + +namespace Shadowsocks.ViewModels +{ + public class ServerSharingViewModel : ReactiveObject + { + /// + /// The view model class for the server sharing user control. + /// + public ServerSharingViewModel() + { + _config = Configuration.Load(); + _servers = _config.configs; + _selectedServer = _servers.First(); + //_selectedServerUrlImage = new BitmapImage(); + UpdateUrlAndImage(); + } + + private readonly Configuration _config; + + private List _servers; + private Server _selectedServer; + private string _selectedServerUrl; + private BitmapImage _selectedServerUrlImage; + + /// + /// Called when SelectedServer changed + /// to update SelectedServerUrl and SelectedServerUrlImage + /// + private void UpdateUrlAndImage() + { + // update SelectedServerUrl + SelectedServerUrl = _selectedServer.GetURL(_config.generateLegacyUrl); + + // generate QR code + var qrCode = ZXing.QrCode.Internal.Encoder.encode(_selectedServerUrl, ZXing.QrCode.Internal.ErrorCorrectionLevel.L); + var byteMatrix = qrCode.Matrix; + + // paint bitmap + int blockSize = Math.Max(1024 / byteMatrix.Height, 1); + Bitmap drawArea = new Bitmap((byteMatrix.Width * blockSize), (byteMatrix.Height * blockSize)); + using (var graphics = Graphics.FromImage(drawArea)) + { + graphics.Clear(Color.White); + using (var solidBrush = new SolidBrush(Color.Black)) + { + for (int row = 0; row < byteMatrix.Width; row++) + { + for (int column = 0; column < byteMatrix.Height; column++) + { + if (byteMatrix[row, column] != 0) + { + graphics.FillRectangle(solidBrush, blockSize * row, blockSize * column, blockSize, blockSize); + } + } + } + } + } + + // transform to BitmapImage for binding + BitmapImage bitmapImage = new BitmapImage(); + using (MemoryStream memoryStream = new MemoryStream()) + { + drawArea.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Bmp); + memoryStream.Position = 0; + bitmapImage.BeginInit(); + bitmapImage.StreamSource = memoryStream; + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.EndInit(); + } + SelectedServerUrlImage = bitmapImage; + } + + public List Servers + { + get => _servers; + set => this.RaiseAndSetIfChanged(ref _servers, value); + } + + public Server SelectedServer + { + get => _selectedServer; + set + { + this.RaiseAndSetIfChanged(ref _selectedServer, value); + UpdateUrlAndImage(); + } + } + + public string SelectedServerUrl + { + get => _selectedServerUrl; + set => this.RaiseAndSetIfChanged(ref _selectedServerUrl, value); + } + + public BitmapImage SelectedServerUrlImage + { + get => _selectedServerUrlImage; + set => this.RaiseAndSetIfChanged(ref _selectedServerUrlImage, value); + } + } +} diff --git a/shadowsocks-csharp/Views/ServerSharingView.xaml b/shadowsocks-csharp/Views/ServerSharingView.xaml new file mode 100644 index 00000000..dbce7e27 --- /dev/null +++ b/shadowsocks-csharp/Views/ServerSharingView.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/shadowsocks-csharp/Views/ServerSharingView.xaml.cs b/shadowsocks-csharp/Views/ServerSharingView.xaml.cs new file mode 100644 index 00000000..64aca9a5 --- /dev/null +++ b/shadowsocks-csharp/Views/ServerSharingView.xaml.cs @@ -0,0 +1,24 @@ +using Shadowsocks.ViewModels; +using System.Windows.Controls; +using System.Windows.Input; + +namespace Shadowsocks.Views +{ + /// + /// Interaction logic for ServerSharingView.xaml + /// + public partial class ServerSharingView : UserControl + { + public ServerSharingView() + { + InitializeComponent(); + + DataContext = new ServerSharingViewModel(); + } + + private void urlTextBox_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) + { + urlTextBox.SelectAll(); + } + } +} diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 1f9e1655..c9414a2b 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -268,6 +268,7 @@ + Form @@ -320,6 +321,9 @@ Form + + ServerSharingView.xaml + Form @@ -416,6 +420,12 @@ true + + + Designer + MSBuild:Compile + +