From babb48ac51f8b0885063ed97834e7495221c07a1 Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Tue, 12 Dec 2017 21:49:44 +0100 Subject: [PATCH 01/15] Add UseLang key to settings --- DS4Windows/DS4Control/ScpUtil.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index 084ecd1..0e7c0dd 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -441,6 +441,12 @@ namespace DS4Windows get { return m_Config.formLocationY; } } + public static string UseLang + { + set { m_Config.useLang = value; } + get { return m_Config.useLang; } + } + public static bool DownloadLang { set { m_Config.downloadLang = value; } @@ -1345,6 +1351,7 @@ namespace DS4Windows { new Dictionary(), new Dictionary(), new Dictionary(), new Dictionary(), new Dictionary() }; + public string useLang = ""; public bool downloadLang = true; public bool useWhiteIcon; public bool flashWhenLate = true; @@ -2832,6 +2839,8 @@ namespace DS4Windows catch { missingSetting = true; } try { Item = m_Xdoc.SelectSingleNode("/Profile/CloseMinimizes"); Boolean.TryParse(Item.InnerText, out closeMini); } catch { missingSetting = true; } + try { Item = m_Xdoc.SelectSingleNode("/Profile/UseLang"); useLang = Item.InnerText; } + catch { missingSetting = true; } try { Item = m_Xdoc.SelectSingleNode("/Profile/DownloadLang"); Boolean.TryParse(Item.InnerText, out downloadLang); } catch { missingSetting = true; } try { Item = m_Xdoc.SelectSingleNode("/Profile/FlashWhenLate"); Boolean.TryParse(Item.InnerText, out flashWhenLate); } @@ -2902,6 +2911,7 @@ namespace DS4Windows XmlNode xmlQuickCharge = m_Xdoc.CreateNode(XmlNodeType.Element, "QuickCharge", null); xmlQuickCharge.InnerText = quickCharge.ToString(); Node.AppendChild(xmlQuickCharge); XmlNode xmlFirstXinputPort = m_Xdoc.CreateNode(XmlNodeType.Element, "FirstXinputPort", null); xmlFirstXinputPort.InnerText = firstXinputPort.ToString(); Node.AppendChild(xmlFirstXinputPort); XmlNode xmlCloseMini = m_Xdoc.CreateNode(XmlNodeType.Element, "CloseMinimizes", null); xmlCloseMini.InnerText = closeMini.ToString(); Node.AppendChild(xmlCloseMini); + XmlNode xmlUseLang = m_Xdoc.CreateNode(XmlNodeType.Element, "UseLang", null); xmlUseLang.InnerText = useLang.ToString(); Node.AppendChild(xmlUseLang); XmlNode xmlDownloadLang = m_Xdoc.CreateNode(XmlNodeType.Element, "DownloadLang", null); xmlDownloadLang.InnerText = downloadLang.ToString(); Node.AppendChild(xmlDownloadLang); XmlNode xmlFlashWhenLate = m_Xdoc.CreateNode(XmlNodeType.Element, "FlashWhenLate", null); xmlFlashWhenLate.InnerText = flashWhenLate.ToString(); Node.AppendChild(xmlFlashWhenLate); XmlNode xmlFlashWhenLateAt = m_Xdoc.CreateNode(XmlNodeType.Element, "FlashWhenLateAt", null); xmlFlashWhenLateAt.InnerText = flashWhenLateAt.ToString(); Node.AppendChild(xmlFlashWhenLateAt); From f0b645b7e5bbf92561814e0ff376a6f9b2c46ca6 Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Tue, 12 Dec 2017 21:50:29 +0100 Subject: [PATCH 02/15] Add Language picker control --- .../DS4Forms/LanguagePackComboBox.Designer.cs | 79 ++++++++++++ DS4Windows/DS4Forms/LanguagePackComboBox.cs | 92 ++++++++++++++ DS4Windows/DS4Forms/LanguagePackComboBox.resx | 120 ++++++++++++++++++ DS4Windows/DS4Windows.csproj | 9 ++ 4 files changed, 300 insertions(+) create mode 100644 DS4Windows/DS4Forms/LanguagePackComboBox.Designer.cs create mode 100644 DS4Windows/DS4Forms/LanguagePackComboBox.cs create mode 100644 DS4Windows/DS4Forms/LanguagePackComboBox.resx diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.Designer.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.Designer.cs new file mode 100644 index 0000000..de400a5 --- /dev/null +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.Designer.cs @@ -0,0 +1,79 @@ +namespace DS4Windows.DS4Forms +{ + partial class LanguagePackComboBox + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Код, автоматически созданный конструктором компонентов + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.cbCulture = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // cbCulture + // + this.cbCulture.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.cbCulture.DisplayMember = "Value"; + this.cbCulture.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cbCulture.FormattingEnabled = true; + this.cbCulture.Location = new System.Drawing.Point(112, 3); + this.cbCulture.Name = "cbCulture"; + this.cbCulture.Size = new System.Drawing.Size(145, 21); + this.cbCulture.TabIndex = 61; + this.cbCulture.ValueMember = "Key"; + // + // label1 + // + this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 6); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(100, 13); + this.label1.TabIndex = 62; + this.label1.Text = "Use language pack"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.label1.SizeChanged += new System.EventHandler(this.LanguagePackComboBox_SizeChanged); + // + // LanguagePackComboBox + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.cbCulture); + this.Controls.Add(this.label1); + this.Name = "LanguagePackComboBox"; + this.Size = new System.Drawing.Size(260, 27); + this.SizeChanged += new System.EventHandler(this.LanguagePackComboBox_SizeChanged); + this.Resize += new System.EventHandler(this.LanguagePackComboBox_SizeChanged); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ComboBox cbCulture; + private System.Windows.Forms.Label label1; + } +} diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.cs new file mode 100644 index 0000000..efb75f7 --- /dev/null +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Windows.Forms; + +namespace DS4Windows.DS4Forms +{ + public partial class LanguagePackComboBox : UserControl + { + [Category("Action")] + [Description("Fires when the combo box selected index is changed.")] + public event EventHandler SelectedIndexChanged; + + [Category("Action")] + [Description("Fires when the combo box selected value is changed.")] + public event EventHandler SelectedValueChanged; + + [Category("Data")] + [Description("Text used for invariant culture name in the combo box.")] + [Localizable(true)] + public string InvariantCultureText { get; set; } + + [Category("Data")] + [Description("Text for label before the combo box.")] + [Localizable(true)] + public string LabelText { + get { return label1.Text; } + set { label1.Text = value; } + } + + public int SelectedIndex + { + get { return cbCulture.SelectedIndex; } + set { cbCulture.SelectedIndex = value; } + } + + public string SelectedText + { + get { return cbCulture.SelectedText; } + set { cbCulture.SelectedText = value; } + } + + public object SelectedValue + { + get { return cbCulture.SelectedValue; } + set { cbCulture.SelectedValue = value; } + } + + public LanguagePackComboBox() + { + InitializeComponent(); + + // Find the location where application installed. + string exeLocation = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)); + + // Get all culture for which satellite folder found with culture code. + Dictionary cultures = CultureInfo.GetCultures(CultureTypes.AllCultures) + .Where(c => Directory.Exists(Path.Combine(exeLocation, c.Name))) + .ToDictionary(c => c.Name, c => c.Equals(CultureInfo.InvariantCulture) ? this.InvariantCultureText : c.NativeName); + + cbCulture.DataSource = new BindingSource(cultures, null); + cbCulture.SelectedValue = Thread.CurrentThread.CurrentUICulture.Name; + + // This must be set here instead of Designer or event would fire at initial selected value setting above. + cbCulture.SelectedIndexChanged += new EventHandler(CbCulture_SelectedIndexChanged); + cbCulture.SelectedValueChanged += new EventHandler(CbCulture_SelectedValueChanged); + } + + private void LanguagePackComboBox_SizeChanged(object sender, EventArgs e) + { + cbCulture.Left = label1.Margin.Left + label1.Width + label1.Margin.Right; + cbCulture.Width = this.Width - cbCulture.Left - cbCulture.Margin.Right - cbCulture.Margin.Left; + } + + private void CbCulture_SelectedIndexChanged(object sender, EventArgs e) + { + + this.SelectedIndexChanged?.Invoke(this, e); + + } + + private void CbCulture_SelectedValueChanged(object sender, EventArgs e) + { + this.SelectedValueChanged?.Invoke(this, e); + } + } +} diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.resx b/DS4Windows/DS4Forms/LanguagePackComboBox.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/DS4Windows/DS4Windows.csproj b/DS4Windows/DS4Windows.csproj index 0798107..ac6d445 100644 --- a/DS4Windows/DS4Windows.csproj +++ b/DS4Windows/DS4Windows.csproj @@ -164,6 +164,12 @@ X360Device.cs + + UserControl + + + LanguagePackComboBox.cs + @@ -594,6 +600,9 @@ KBM360.cs + + LanguagePackComboBox.cs + Options.cs From a794d2c718c97c9c6ccbc3ab452423eac1c8c2cf Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Tue, 12 Dec 2017 21:52:13 +0100 Subject: [PATCH 03/15] Load settings from Global sooner, set culture from settings, add event handler for language picker change --- DS4Windows/DS4Forms/DS4Form.cs | 11 ++++++++++- DS4Windows/Program.cs | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/DS4Windows/DS4Forms/DS4Form.cs b/DS4Windows/DS4Forms/DS4Form.cs index 3ce1eb1..236a0d0 100644 --- a/DS4Windows/DS4Forms/DS4Form.cs +++ b/DS4Windows/DS4Forms/DS4Form.cs @@ -88,6 +88,9 @@ namespace DS4Windows public DS4Form(string[] args) { + Global.Load(); + Program.SetCulture(UseLang); + InitializeComponent(); ThemeUtil.SetTheme(lvDebug); @@ -181,7 +184,6 @@ namespace DS4Windows Log.TrayIconLog += ShowNotification; Directory.CreateDirectory(appdatapath); - Global.Load(); if (!Save()) //if can't write to file { if (MessageBox.Show("Cannot write at current location\nCopy Settings to appdata?", "DS4Windows", @@ -2487,6 +2489,13 @@ namespace DS4Windows } } + private void languagePackComboBox1_SelectedValueChanged(object sender, EventArgs e) + { + UseLang = ((DS4Forms.LanguagePackComboBox)sender).SelectedValue.ToString(); + Save(); + MessageBox.Show("DS4Windows must be restarted in order to have an effect."); + } + private void cBFlashWhenLate_CheckedChanged(object sender, EventArgs e) { FlashWhenLate = cBFlashWhenLate.Checked; diff --git a/DS4Windows/Program.cs b/DS4Windows/Program.cs index 8436793..163e85e 100644 --- a/DS4Windows/Program.cs +++ b/DS4Windows/Program.cs @@ -120,6 +120,18 @@ namespace DS4Windows threadComEvent.Close(); } + public static void SetCulture(string culture) + { + foreach (Thread t in new Thread[] { Thread.CurrentThread, controlThread }) + { + if (t != null && !t.CurrentUICulture.Equals(culture)) + { + try { t.CurrentUICulture = CultureInfo.GetCultureInfo(culture); } + catch { /* Skip setting culture that we cannot set */ } + } + } + } + private static void createControlService() { controlThread = new Thread(() => { rootHub = new ControlService(); }); From 60916e10800b9b1cc97b2e0dd5d73c0ba4a63784 Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Thu, 14 Dec 2017 19:40:44 +0100 Subject: [PATCH 04/15] Fix setting UI culture for other threads --- DS4Windows/Program.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/DS4Windows/Program.cs b/DS4Windows/Program.cs index 163e85e..6f2eaad 100644 --- a/DS4Windows/Program.cs +++ b/DS4Windows/Program.cs @@ -122,14 +122,12 @@ namespace DS4Windows public static void SetCulture(string culture) { - foreach (Thread t in new Thread[] { Thread.CurrentThread, controlThread }) + try { - if (t != null && !t.CurrentUICulture.Equals(culture)) - { - try { t.CurrentUICulture = CultureInfo.GetCultureInfo(culture); } - catch { /* Skip setting culture that we cannot set */ } - } + Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture); + CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo(culture); } + catch { /* Skip setting culture that we cannot set */ } } private static void createControlService() From 8297f4cd75d63a1a39f999b8ff306873d0e2995f Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Thu, 14 Dec 2017 19:42:08 +0100 Subject: [PATCH 05/15] Hide properties from designer, it should not autogenerate any code for them --- DS4Windows/DS4Forms/LanguagePackComboBox.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.cs index efb75f7..aa38b5b 100644 --- a/DS4Windows/DS4Forms/LanguagePackComboBox.cs +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.cs @@ -33,18 +33,21 @@ namespace DS4Windows.DS4Forms set { label1.Text = value; } } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int SelectedIndex { get { return cbCulture.SelectedIndex; } set { cbCulture.SelectedIndex = value; } } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public string SelectedText { get { return cbCulture.SelectedText; } set { cbCulture.SelectedText = value; } } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public object SelectedValue { get { return cbCulture.SelectedValue; } From 847e0bd6b928d6717a205d6a903ecc8de82537ce Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Sat, 16 Dec 2017 13:24:57 +0100 Subject: [PATCH 06/15] Move set culture method to DS4Form class --- DS4Windows/DS4Forms/DS4Form.cs | 12 +++++++++++- DS4Windows/Program.cs | 10 ---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/DS4Windows/DS4Forms/DS4Form.cs b/DS4Windows/DS4Forms/DS4Form.cs index 236a0d0..635b3e4 100644 --- a/DS4Windows/DS4Forms/DS4Form.cs +++ b/DS4Windows/DS4Forms/DS4Form.cs @@ -89,7 +89,7 @@ namespace DS4Windows public DS4Form(string[] args) { Global.Load(); - Program.SetCulture(UseLang); + this.setCulture(UseLang); InitializeComponent(); ThemeUtil.SetTheme(lvDebug); @@ -430,6 +430,16 @@ namespace DS4Windows } } + private void setCulture(string culture) + { + try + { + Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture); + CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo(culture); + } + catch { /* Skip setting culture that we cannot set */ } + } + private void populateHoverTextDict() { hoverTextDict.Clear(); diff --git a/DS4Windows/Program.cs b/DS4Windows/Program.cs index 6f2eaad..8436793 100644 --- a/DS4Windows/Program.cs +++ b/DS4Windows/Program.cs @@ -120,16 +120,6 @@ namespace DS4Windows threadComEvent.Close(); } - public static void SetCulture(string culture) - { - try - { - Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture); - CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo(culture); - } - catch { /* Skip setting culture that we cannot set */ } - } - private static void createControlService() { controlThread = new Thread(() => { rootHub = new ControlService(); }); From d0ad9d89cb2285b3d616e82ff2a64f8447bd3db6 Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Tue, 19 Dec 2017 13:56:54 +0100 Subject: [PATCH 07/15] Implement language assemblies lookup for ability to find with different probing paths specified in App.config --- DS4Windows/DS4Forms/LanguagePackComboBox.cs | 46 +++++++++++++++++---- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.cs index aa38b5b..6cfe670 100644 --- a/DS4Windows/DS4Forms/LanguagePackComboBox.cs +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.cs @@ -12,6 +12,8 @@ namespace DS4Windows.DS4Forms { public partial class LanguagePackComboBox : UserControl { + private string _probingPath = ""; + [Category("Action")] [Description("Fires when the combo box selected index is changed.")] public event EventHandler SelectedIndexChanged; @@ -33,6 +35,14 @@ namespace DS4Windows.DS4Forms set { label1.Text = value; } } + [Category("Data")] + [Description("If probing path has been changed in App.config, add the same string here.")] + public string ProbingPath + { + get { return this._probingPath; } + set { this._probingPath = value; } + } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int SelectedIndex { @@ -58,15 +68,8 @@ namespace DS4Windows.DS4Forms { InitializeComponent(); - // Find the location where application installed. - string exeLocation = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)); - - // Get all culture for which satellite folder found with culture code. - Dictionary cultures = CultureInfo.GetCultures(CultureTypes.AllCultures) - .Where(c => Directory.Exists(Path.Combine(exeLocation, c.Name))) - .ToDictionary(c => c.Name, c => c.Equals(CultureInfo.InvariantCulture) ? this.InvariantCultureText : c.NativeName); - - cbCulture.DataSource = new BindingSource(cultures, null); + // Find available language assemblies and bind the list to the combo box. + cbCulture.DataSource = this.CreateLanguageAssembliesBindingSource(); cbCulture.SelectedValue = Thread.CurrentThread.CurrentUICulture.Name; // This must be set here instead of Designer or event would fire at initial selected value setting above. @@ -74,6 +77,31 @@ namespace DS4Windows.DS4Forms cbCulture.SelectedValueChanged += new EventHandler(CbCulture_SelectedValueChanged); } + private BindingSource CreateLanguageAssembliesBindingSource() + { + // Find the location where application installed. + string exeLocation = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)); + List lookupPaths = this.ProbingPath.Split(';') + .Select(path => Path.Combine(exeLocation, path)) + .Where(path => path != exeLocation) + .ToList(); + lookupPaths.Insert(0, exeLocation); + + // Get all culture for which satellite folder found with culture code. + Dictionary cultures = CultureInfo.GetCultures(CultureTypes.AllCultures) + .Where(c => this.IsLanguageAssemblyAvailable(lookupPaths, c)) + .ToDictionary(c => c.Name, c => c.Equals(CultureInfo.InvariantCulture) ? this.InvariantCultureText : c.NativeName); + + return new BindingSource(cultures, null); + } + + private bool IsLanguageAssemblyAvailable(List lookupPaths, CultureInfo culture) + { + return lookupPaths.Select(path => Path.Combine(path, culture.Name)) + .Where(path => Directory.Exists(path)) + .Count() > 0; + } + private void LanguagePackComboBox_SizeChanged(object sender, EventArgs e) { cbCulture.Left = label1.Margin.Left + label1.Width + label1.Margin.Right; From 300e842cb2c4995eba38706dad4751f258e5ca01 Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Tue, 19 Dec 2017 14:13:43 +0100 Subject: [PATCH 08/15] Filter language assemblies by name --- DS4Windows/DS4Forms/LanguagePackComboBox.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.cs index 6cfe670..3ee31dc 100644 --- a/DS4Windows/DS4Forms/LanguagePackComboBox.cs +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.cs @@ -13,6 +13,7 @@ namespace DS4Windows.DS4Forms public partial class LanguagePackComboBox : UserControl { private string _probingPath = ""; + private string _languageAssemblyName = "DS4Windows.resources.dll"; [Category("Action")] [Description("Fires when the combo box selected index is changed.")] @@ -43,6 +44,14 @@ namespace DS4Windows.DS4Forms set { this._probingPath = value; } } + [Category("Data")] + [Description("Filter language assembly file names in order to ont include irrelevant assemblies to the combo box.")] + public string LanguageAssemblyName + { + get { return this._languageAssemblyName; } + set { this._languageAssemblyName = value; } + } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int SelectedIndex { @@ -89,7 +98,7 @@ namespace DS4Windows.DS4Forms // Get all culture for which satellite folder found with culture code. Dictionary cultures = CultureInfo.GetCultures(CultureTypes.AllCultures) - .Where(c => this.IsLanguageAssemblyAvailable(lookupPaths, c)) + .Where(c => c.Equals(CultureInfo.InvariantCulture) || this.IsLanguageAssemblyAvailable(lookupPaths, c)) .ToDictionary(c => c.Name, c => c.Equals(CultureInfo.InvariantCulture) ? this.InvariantCultureText : c.NativeName); return new BindingSource(cultures, null); @@ -97,8 +106,8 @@ namespace DS4Windows.DS4Forms private bool IsLanguageAssemblyAvailable(List lookupPaths, CultureInfo culture) { - return lookupPaths.Select(path => Path.Combine(path, culture.Name)) - .Where(path => Directory.Exists(path)) + return lookupPaths.Select(path => Path.Combine(path, culture.Name, this.LanguageAssemblyName)) + .Where(path => File.Exists(path)) .Count() > 0; } From 0ea620ffa03be35b137358bce403727ed7481bee Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Tue, 19 Dec 2017 14:14:13 +0100 Subject: [PATCH 09/15] Remove extra whitespace --- DS4Windows/DS4Forms/LanguagePackComboBox.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.cs index 3ee31dc..dcab72d 100644 --- a/DS4Windows/DS4Forms/LanguagePackComboBox.cs +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.cs @@ -119,9 +119,7 @@ namespace DS4Windows.DS4Forms private void CbCulture_SelectedIndexChanged(object sender, EventArgs e) { - this.SelectedIndexChanged?.Invoke(this, e); - } private void CbCulture_SelectedValueChanged(object sender, EventArgs e) From acfb9b262979e39c3d9fa0b21290ac7b1dd2ee37 Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Tue, 19 Dec 2017 14:24:50 +0100 Subject: [PATCH 10/15] Initialize languages list asynchronously --- DS4Windows/DS4Forms/LanguagePackComboBox.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.cs index dcab72d..2b4e6fb 100644 --- a/DS4Windows/DS4Forms/LanguagePackComboBox.cs +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; namespace DS4Windows.DS4Forms @@ -76,14 +77,19 @@ namespace DS4Windows.DS4Forms public LanguagePackComboBox() { InitializeComponent(); + cbCulture.Enabled = false; - // Find available language assemblies and bind the list to the combo box. - cbCulture.DataSource = this.CreateLanguageAssembliesBindingSource(); - cbCulture.SelectedValue = Thread.CurrentThread.CurrentUICulture.Name; + Task.Run(() => { + // Find available language assemblies and bind the list to the combo box. + cbCulture.DataSource = this.CreateLanguageAssembliesBindingSource(); + cbCulture.SelectedValue = Thread.CurrentThread.CurrentUICulture.Name; - // This must be set here instead of Designer or event would fire at initial selected value setting above. - cbCulture.SelectedIndexChanged += new EventHandler(CbCulture_SelectedIndexChanged); - cbCulture.SelectedValueChanged += new EventHandler(CbCulture_SelectedValueChanged); + // This must be set here instead of Designer or event would fire at initial selected value setting above. + cbCulture.SelectedIndexChanged += new EventHandler(CbCulture_SelectedIndexChanged); + cbCulture.SelectedValueChanged += new EventHandler(CbCulture_SelectedValueChanged); + + cbCulture.Enabled = true; + }); } private BindingSource CreateLanguageAssembliesBindingSource() From 40b0c9490537e1ab0ebbc31ee0b68caf33b14e63 Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Tue, 19 Dec 2017 18:14:22 +0100 Subject: [PATCH 11/15] Make control localizable --- .../DS4Forms/LanguagePackComboBox.Designer.cs | 17 +---- DS4Windows/DS4Forms/LanguagePackComboBox.cs | 31 ++++++-- DS4Windows/DS4Forms/LanguagePackComboBox.resx | 75 +++++++++++++++++++ 3 files changed, 105 insertions(+), 18 deletions(-) diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.Designer.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.Designer.cs index de400a5..1ed1ff2 100644 --- a/DS4Windows/DS4Forms/LanguagePackComboBox.Designer.cs +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.Designer.cs @@ -28,42 +28,33 @@ /// private void InitializeComponent() { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LanguagePackComboBox)); this.cbCulture = new System.Windows.Forms.ComboBox(); this.label1 = new System.Windows.Forms.Label(); this.SuspendLayout(); // // cbCulture // - this.cbCulture.Anchor = System.Windows.Forms.AnchorStyles.Right; + resources.ApplyResources(this.cbCulture, "cbCulture"); this.cbCulture.DisplayMember = "Value"; this.cbCulture.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cbCulture.FormattingEnabled = true; - this.cbCulture.Location = new System.Drawing.Point(112, 3); this.cbCulture.Name = "cbCulture"; - this.cbCulture.Size = new System.Drawing.Size(145, 21); - this.cbCulture.TabIndex = 61; this.cbCulture.ValueMember = "Key"; // // label1 // - this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(3, 6); + resources.ApplyResources(this.label1, "label1"); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(100, 13); - this.label1.TabIndex = 62; - this.label1.Text = "Use language pack"; - this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; this.label1.SizeChanged += new System.EventHandler(this.LanguagePackComboBox_SizeChanged); // // LanguagePackComboBox // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.cbCulture); this.Controls.Add(this.label1); this.Name = "LanguagePackComboBox"; - this.Size = new System.Drawing.Size(260, 27); this.SizeChanged += new System.EventHandler(this.LanguagePackComboBox_SizeChanged); this.Resize += new System.EventHandler(this.LanguagePackComboBox_SizeChanged); this.ResumeLayout(false); diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.cs index 2b4e6fb..c85898c 100644 --- a/DS4Windows/DS4Forms/LanguagePackComboBox.cs +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.cs @@ -13,8 +13,10 @@ namespace DS4Windows.DS4Forms { public partial class LanguagePackComboBox : UserControl { + private string _invariantCultureText = "No (English UI)"; private string _probingPath = ""; private string _languageAssemblyName = "DS4Windows.resources.dll"; + private TaskCompletionSource _languageListInitialized = new TaskCompletionSource(); [Category("Action")] [Description("Fires when the combo box selected index is changed.")] @@ -27,7 +29,15 @@ namespace DS4Windows.DS4Forms [Category("Data")] [Description("Text used for invariant culture name in the combo box.")] [Localizable(true)] - public string InvariantCultureText { get; set; } + public string InvariantCultureText + { + get { return _invariantCultureText; } + [System.Diagnostics.CodeAnalysis.SuppressMessage("InvariantCultureText_Changed call will complete when ready, no need for a warning", "CS4014:Await.Warning")] + set { + _invariantCultureText = value; + InvariantCultureText_Changed(value); + } + } [Category("Data")] [Description("Text for label before the combo box.")] @@ -89,6 +99,7 @@ namespace DS4Windows.DS4Forms cbCulture.SelectedValueChanged += new EventHandler(CbCulture_SelectedValueChanged); cbCulture.Enabled = true; + _languageListInitialized.SetResult(true); }); } @@ -102,10 +113,12 @@ namespace DS4Windows.DS4Forms .ToList(); lookupPaths.Insert(0, exeLocation); - // Get all culture for which satellite folder found with culture code. - Dictionary cultures = CultureInfo.GetCultures(CultureTypes.AllCultures) - .Where(c => c.Equals(CultureInfo.InvariantCulture) || this.IsLanguageAssemblyAvailable(lookupPaths, c)) - .ToDictionary(c => c.Name, c => c.Equals(CultureInfo.InvariantCulture) ? this.InvariantCultureText : c.NativeName); + // Get all culture for which satellite folder found with culture code, then insert invariant culture at the beginning. + List> cultures = CultureInfo.GetCultures(CultureTypes.AllCultures) + .Where(c => this.IsLanguageAssemblyAvailable(lookupPaths, c)) + .Select(c => new KeyValuePair(c.Name, c.NativeName)) + .ToList(); + cultures.Insert(0, new KeyValuePair("", this.InvariantCultureText)); return new BindingSource(cultures, null); } @@ -117,6 +130,14 @@ namespace DS4Windows.DS4Forms .Count() > 0; } + private async Task InvariantCultureText_Changed(string value) + { + // Normally the completion flag will be long set by the time this method is called. + await _languageListInitialized.Task; + BindingSource dataSource = ((BindingSource)cbCulture.DataSource); + dataSource[0] = new KeyValuePair("", value); + } + private void LanguagePackComboBox_SizeChanged(object sender, EventArgs e) { cbCulture.Left = label1.Margin.Left + label1.Width + label1.Margin.Right; diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.resx b/DS4Windows/DS4Forms/LanguagePackComboBox.resx index 1af7de1..175e22a 100644 --- a/DS4Windows/DS4Forms/LanguagePackComboBox.resx +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.resx @@ -117,4 +117,79 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Right + + + + 112, 3 + + + 145, 21 + + + + 61 + + + cbCulture + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + Left + + + True + + + 3, 6 + + + 100, 13 + + + 62 + + + Use language pack + + + MiddleLeft + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + True + + + 6, 13 + + + 260, 27 + + + LanguagePackComboBox + + + System.Windows.Forms.UserControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file From a06b1d6e276e187a8b6b623f4f85449523e8222d Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Tue, 19 Dec 2017 18:15:50 +0100 Subject: [PATCH 12/15] Review code simplify suggestion, reorder private properties --- DS4Windows/DS4Forms/LanguagePackComboBox.cs | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.cs index c85898c..995468e 100644 --- a/DS4Windows/DS4Forms/LanguagePackComboBox.cs +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.cs @@ -14,9 +14,9 @@ namespace DS4Windows.DS4Forms public partial class LanguagePackComboBox : UserControl { private string _invariantCultureText = "No (English UI)"; - private string _probingPath = ""; private string _languageAssemblyName = "DS4Windows.resources.dll"; private TaskCompletionSource _languageListInitialized = new TaskCompletionSource(); + private string _probingPath = ""; [Category("Action")] [Description("Fires when the combo box selected index is changed.")] @@ -51,16 +51,16 @@ namespace DS4Windows.DS4Forms [Description("If probing path has been changed in App.config, add the same string here.")] public string ProbingPath { - get { return this._probingPath; } - set { this._probingPath = value; } + get { return _probingPath; } + set { _probingPath = value; } } [Category("Data")] [Description("Filter language assembly file names in order to ont include irrelevant assemblies to the combo box.")] public string LanguageAssemblyName { - get { return this._languageAssemblyName; } - set { this._languageAssemblyName = value; } + get { return _languageAssemblyName; } + set { _languageAssemblyName = value; } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] @@ -91,7 +91,7 @@ namespace DS4Windows.DS4Forms Task.Run(() => { // Find available language assemblies and bind the list to the combo box. - cbCulture.DataSource = this.CreateLanguageAssembliesBindingSource(); + cbCulture.DataSource = CreateLanguageAssembliesBindingSource(); cbCulture.SelectedValue = Thread.CurrentThread.CurrentUICulture.Name; // This must be set here instead of Designer or event would fire at initial selected value setting above. @@ -107,7 +107,7 @@ namespace DS4Windows.DS4Forms { // Find the location where application installed. string exeLocation = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)); - List lookupPaths = this.ProbingPath.Split(';') + List lookupPaths = ProbingPath.Split(';') .Select(path => Path.Combine(exeLocation, path)) .Where(path => path != exeLocation) .ToList(); @@ -115,17 +115,17 @@ namespace DS4Windows.DS4Forms // Get all culture for which satellite folder found with culture code, then insert invariant culture at the beginning. List> cultures = CultureInfo.GetCultures(CultureTypes.AllCultures) - .Where(c => this.IsLanguageAssemblyAvailable(lookupPaths, c)) + .Where(c => IsLanguageAssemblyAvailable(lookupPaths, c)) .Select(c => new KeyValuePair(c.Name, c.NativeName)) .ToList(); - cultures.Insert(0, new KeyValuePair("", this.InvariantCultureText)); + cultures.Insert(0, new KeyValuePair("", InvariantCultureText)); return new BindingSource(cultures, null); } private bool IsLanguageAssemblyAvailable(List lookupPaths, CultureInfo culture) { - return lookupPaths.Select(path => Path.Combine(path, culture.Name, this.LanguageAssemblyName)) + return lookupPaths.Select(path => Path.Combine(path, culture.Name, LanguageAssemblyName)) .Where(path => File.Exists(path)) .Count() > 0; } @@ -141,17 +141,17 @@ namespace DS4Windows.DS4Forms private void LanguagePackComboBox_SizeChanged(object sender, EventArgs e) { cbCulture.Left = label1.Margin.Left + label1.Width + label1.Margin.Right; - cbCulture.Width = this.Width - cbCulture.Left - cbCulture.Margin.Right - cbCulture.Margin.Left; + cbCulture.Width = Width - cbCulture.Left - cbCulture.Margin.Right - cbCulture.Margin.Left; } private void CbCulture_SelectedIndexChanged(object sender, EventArgs e) { - this.SelectedIndexChanged?.Invoke(this, e); + SelectedIndexChanged?.Invoke(this, e); } private void CbCulture_SelectedValueChanged(object sender, EventArgs e) { - this.SelectedValueChanged?.Invoke(this, e); + SelectedValueChanged?.Invoke(this, e); } } } From ae294d8926a693b0b87f6ffbda1ac166c25c2cde Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Wed, 20 Dec 2017 07:03:34 +0100 Subject: [PATCH 13/15] Get rid of properties starting with underscore --- DS4Windows/DS4Forms/LanguagePackComboBox.cs | 26 +++++++-------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/DS4Windows/DS4Forms/LanguagePackComboBox.cs b/DS4Windows/DS4Forms/LanguagePackComboBox.cs index 995468e..f2b86f7 100644 --- a/DS4Windows/DS4Forms/LanguagePackComboBox.cs +++ b/DS4Windows/DS4Forms/LanguagePackComboBox.cs @@ -13,10 +13,8 @@ namespace DS4Windows.DS4Forms { public partial class LanguagePackComboBox : UserControl { - private string _invariantCultureText = "No (English UI)"; - private string _languageAssemblyName = "DS4Windows.resources.dll"; - private TaskCompletionSource _languageListInitialized = new TaskCompletionSource(); - private string _probingPath = ""; + private string InvariantCultureTextValue = "No (English UI)"; + private TaskCompletionSource LanguageListInitialized = new TaskCompletionSource(); [Category("Action")] [Description("Fires when the combo box selected index is changed.")] @@ -31,10 +29,10 @@ namespace DS4Windows.DS4Forms [Localizable(true)] public string InvariantCultureText { - get { return _invariantCultureText; } + get { return InvariantCultureTextValue; } [System.Diagnostics.CodeAnalysis.SuppressMessage("InvariantCultureText_Changed call will complete when ready, no need for a warning", "CS4014:Await.Warning")] set { - _invariantCultureText = value; + InvariantCultureTextValue = value; InvariantCultureText_Changed(value); } } @@ -49,19 +47,11 @@ namespace DS4Windows.DS4Forms [Category("Data")] [Description("If probing path has been changed in App.config, add the same string here.")] - public string ProbingPath - { - get { return _probingPath; } - set { _probingPath = value; } - } + public string ProbingPath { get; set; } = ""; [Category("Data")] [Description("Filter language assembly file names in order to ont include irrelevant assemblies to the combo box.")] - public string LanguageAssemblyName - { - get { return _languageAssemblyName; } - set { _languageAssemblyName = value; } - } + public string LanguageAssemblyName { get; set; } = "DS4Windows.resources.dll"; [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int SelectedIndex @@ -99,7 +89,7 @@ namespace DS4Windows.DS4Forms cbCulture.SelectedValueChanged += new EventHandler(CbCulture_SelectedValueChanged); cbCulture.Enabled = true; - _languageListInitialized.SetResult(true); + LanguageListInitialized.SetResult(true); }); } @@ -133,7 +123,7 @@ namespace DS4Windows.DS4Forms private async Task InvariantCultureText_Changed(string value) { // Normally the completion flag will be long set by the time this method is called. - await _languageListInitialized.Task; + await LanguageListInitialized.Task; BindingSource dataSource = ((BindingSource)cbCulture.DataSource); dataSource[0] = new KeyValuePair("", value); } From 02d94876c34d5fff349e8476666a66d447487b8e Mon Sep 17 00:00:00 2001 From: Korney Czukowski Date: Wed, 20 Dec 2017 07:29:16 +0100 Subject: [PATCH 14/15] Add language switch control to form, localization strings --- DS4Windows/DS4Forms/DS4Form.Designer.cs | 11 + DS4Windows/DS4Forms/DS4Form.cs | 10 +- DS4Windows/DS4Forms/DS4Form.cs.resx | 716 ++++++------- DS4Windows/DS4Forms/DS4Form.resx | 638 +++++++----- DS4Windows/DS4Forms/DS4Form.ru-RU.resx | 986 +++++++++--------- DS4Windows/Properties/Resources.Designer.cs | 11 +- DS4Windows/Properties/Resources.cs.resx | 3 + DS4Windows/Properties/Resources.resx | 1015 ++++++++++--------- 8 files changed, 1797 insertions(+), 1593 deletions(-) diff --git a/DS4Windows/DS4Forms/DS4Form.Designer.cs b/DS4Windows/DS4Forms/DS4Form.Designer.cs index 413fabd..ad45738 100644 --- a/DS4Windows/DS4Forms/DS4Form.Designer.cs +++ b/DS4Windows/DS4Forms/DS4Form.Designer.cs @@ -146,6 +146,7 @@ this.lbUseXIPorts = new System.Windows.Forms.Label(); this.nUDXIPorts = new System.Windows.Forms.NumericUpDown(); this.lbLastXIPort = new System.Windows.Forms.Label(); + this.languagePackComboBox1 = new DS4Windows.DS4Forms.LanguagePackComboBox(); this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.linkProfiles = new System.Windows.Forms.LinkLabel(); this.lnkControllers = new System.Windows.Forms.LinkLabel(); @@ -892,6 +893,7 @@ this.fLPSettings.Controls.Add(this.cBUpdate); this.fLPSettings.Controls.Add(this.pNUpdate); this.fLPSettings.Controls.Add(this.pnlXIPorts); + this.fLPSettings.Controls.Add(this.languagePackComboBox1); this.fLPSettings.Controls.Add(this.flowLayoutPanel1); this.fLPSettings.Name = "fLPSettings"; // @@ -1136,6 +1138,14 @@ resources.ApplyResources(this.lbLastXIPort, "lbLastXIPort"); this.lbLastXIPort.Name = "lbLastXIPort"; // + // languagePackComboBox1 + // + resources.ApplyResources(this.languagePackComboBox1, "languagePackComboBox1"); + this.languagePackComboBox1.LanguageAssemblyName = "DS4Windows.resources.dll"; + this.languagePackComboBox1.Name = "languagePackComboBox1"; + this.languagePackComboBox1.ProbingPath = "Lang"; + this.languagePackComboBox1.SelectedValueChanged += new System.EventHandler(this.languagePackComboBox1_SelectedValueChanged); + // // flowLayoutPanel1 // resources.ApplyResources(this.flowLayoutPanel1, "flowLayoutPanel1"); @@ -1430,6 +1440,7 @@ private System.Windows.Forms.Panel panel3; private System.Windows.Forms.Button exportLogTxtBtn; private System.Windows.Forms.Button btnClear; + private DS4Forms.LanguagePackComboBox languagePackComboBox1; //private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2; } } diff --git a/DS4Windows/DS4Forms/DS4Form.cs b/DS4Windows/DS4Forms/DS4Form.cs index 635b3e4..c9fdb8e 100644 --- a/DS4Windows/DS4Forms/DS4Form.cs +++ b/DS4Windows/DS4Forms/DS4Form.cs @@ -2501,9 +2501,13 @@ namespace DS4Windows private void languagePackComboBox1_SelectedValueChanged(object sender, EventArgs e) { - UseLang = ((DS4Forms.LanguagePackComboBox)sender).SelectedValue.ToString(); - Save(); - MessageBox.Show("DS4Windows must be restarted in order to have an effect."); + string newValue = ((DS4Forms.LanguagePackComboBox)sender).SelectedValue.ToString(); + if (newValue != UseLang) + { + UseLang = newValue; + Save(); + MessageBox.Show(Properties.Resources.LanguagePackApplyRestartRequired, Text, MessageBoxButtons.OK, MessageBoxIcon.Information); + } } private void cBFlashWhenLate_CheckedChanged(object sender, EventArgs e) diff --git a/DS4Windows/DS4Forms/DS4Form.cs.resx b/DS4Windows/DS4Forms/DS4Form.cs.resx index 75ce899..393b2fa 100644 --- a/DS4Windows/DS4Forms/DS4Form.cs.resx +++ b/DS4Windows/DS4Forms/DS4Form.cs.resx @@ -1,4 +1,4 @@ - +