2017-12-12 21:50:29 +01:00
using System ;
using System.Collections.Generic ;
using System.ComponentModel ;
using System.Globalization ;
using System.IO ;
using System.Linq ;
using System.Reflection ;
using System.Threading ;
2017-12-19 14:24:50 +01:00
using System.Threading.Tasks ;
2017-12-12 21:50:29 +01:00
using System.Windows.Forms ;
namespace DS4Windows.DS4Forms
{
public partial class LanguagePackComboBox : UserControl
{
2017-12-20 07:03:34 +01:00
private string InvariantCultureTextValue = "No (English UI)" ;
private TaskCompletionSource < bool > LanguageListInitialized = new TaskCompletionSource < bool > ( ) ;
2017-12-19 13:56:54 +01:00
2017-12-12 21:50:29 +01:00
[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)]
2017-12-19 18:14:22 +01:00
public string InvariantCultureText
{
2017-12-20 07:03:34 +01:00
get { return InvariantCultureTextValue ; }
2017-12-19 18:14:22 +01:00
[System.Diagnostics.CodeAnalysis.SuppressMessage("InvariantCultureText_Changed call will complete when ready, no need for a warning", "CS4014:Await.Warning")]
set {
2017-12-20 07:03:34 +01:00
InvariantCultureTextValue = value ;
2017-12-19 18:14:22 +01:00
InvariantCultureText_Changed ( value ) ;
}
}
2017-12-12 21:50:29 +01:00
[Category("Data")]
[Description("Text for label before the combo box.")]
[Localizable(true)]
public string LabelText {
get { return label1 . Text ; }
set { label1 . Text = value ; }
}
2017-12-19 13:56:54 +01:00
[Category("Data")]
[Description("If probing path has been changed in App.config, add the same string here.")]
2017-12-20 07:03:34 +01:00
public string ProbingPath { get ; set ; } = "" ;
2017-12-19 13:56:54 +01:00
2017-12-19 14:13:43 +01:00
[Category("Data")]
[Description("Filter language assembly file names in order to ont include irrelevant assemblies to the combo box.")]
2017-12-20 07:03:34 +01:00
public string LanguageAssemblyName { get ; set ; } = "DS4Windows.resources.dll" ;
2017-12-19 14:13:43 +01:00
2017-12-14 19:42:08 +01:00
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
2017-12-12 21:50:29 +01:00
public int SelectedIndex
{
get { return cbCulture . SelectedIndex ; }
set { cbCulture . SelectedIndex = value ; }
}
2017-12-14 19:42:08 +01:00
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
2017-12-12 21:50:29 +01:00
public string SelectedText
{
get { return cbCulture . SelectedText ; }
set { cbCulture . SelectedText = value ; }
}
2017-12-14 19:42:08 +01:00
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
2017-12-12 21:50:29 +01:00
public object SelectedValue
{
get { return cbCulture . SelectedValue ; }
set { cbCulture . SelectedValue = value ; }
}
public LanguagePackComboBox ( )
{
InitializeComponent ( ) ;
2017-12-19 14:24:50 +01:00
cbCulture . Enabled = false ;
2017-12-12 21:50:29 +01:00
2017-12-19 14:24:50 +01:00
Task . Run ( ( ) = > {
// Find available language assemblies and bind the list to the combo box.
2017-12-19 18:15:50 +01:00
cbCulture . DataSource = CreateLanguageAssembliesBindingSource ( ) ;
2017-12-19 14:24:50 +01:00
cbCulture . SelectedValue = Thread . CurrentThread . CurrentUICulture . Name ;
2017-12-19 13:56:54 +01:00
2017-12-19 14:24:50 +01:00
// 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 ;
2017-12-20 07:03:34 +01:00
LanguageListInitialized . SetResult ( true ) ;
2017-12-19 14:24:50 +01:00
} ) ;
2017-12-19 13:56:54 +01:00
}
private BindingSource CreateLanguageAssembliesBindingSource ( )
{
2017-12-12 21:50:29 +01:00
// Find the location where application installed.
string exeLocation = Path . GetDirectoryName ( Uri . UnescapeDataString ( new UriBuilder ( Assembly . GetExecutingAssembly ( ) . CodeBase ) . Path ) ) ;
2017-12-19 18:15:50 +01:00
List < string > lookupPaths = ProbingPath . Split ( ';' )
2017-12-19 13:56:54 +01:00
. Select ( path = > Path . Combine ( exeLocation , path ) )
. Where ( path = > path ! = exeLocation )
. ToList ( ) ;
lookupPaths . Insert ( 0 , exeLocation ) ;
2017-12-12 21:50:29 +01:00
2017-12-19 18:14:22 +01:00
// Get all culture for which satellite folder found with culture code, then insert invariant culture at the beginning.
List < KeyValuePair < string , string > > cultures = CultureInfo . GetCultures ( CultureTypes . AllCultures )
2017-12-19 18:15:50 +01:00
. Where ( c = > IsLanguageAssemblyAvailable ( lookupPaths , c ) )
2017-12-19 18:14:22 +01:00
. Select ( c = > new KeyValuePair < string , string > ( c . Name , c . NativeName ) )
. ToList ( ) ;
2017-12-19 18:15:50 +01:00
cultures . Insert ( 0 , new KeyValuePair < string , string > ( "" , InvariantCultureText ) ) ;
2017-12-12 21:50:29 +01:00
2017-12-19 13:56:54 +01:00
return new BindingSource ( cultures , null ) ;
}
2017-12-12 21:50:29 +01:00
2017-12-19 13:56:54 +01:00
private bool IsLanguageAssemblyAvailable ( List < string > lookupPaths , CultureInfo culture )
{
2017-12-19 18:15:50 +01:00
return lookupPaths . Select ( path = > Path . Combine ( path , culture . Name , LanguageAssemblyName ) )
2017-12-19 14:13:43 +01:00
. Where ( path = > File . Exists ( path ) )
2017-12-19 13:56:54 +01:00
. Count ( ) > 0 ;
2017-12-12 21:50:29 +01:00
}
2017-12-19 18:14:22 +01:00
private async Task InvariantCultureText_Changed ( string value )
{
// Normally the completion flag will be long set by the time this method is called.
2017-12-20 07:03:34 +01:00
await LanguageListInitialized . Task ;
2017-12-19 18:14:22 +01:00
BindingSource dataSource = ( ( BindingSource ) cbCulture . DataSource ) ;
dataSource [ 0 ] = new KeyValuePair < string , string > ( "" , value ) ;
}
2017-12-12 21:50:29 +01:00
private void LanguagePackComboBox_SizeChanged ( object sender , EventArgs e )
{
cbCulture . Left = label1 . Margin . Left + label1 . Width + label1 . Margin . Right ;
2017-12-19 18:15:50 +01:00
cbCulture . Width = Width - cbCulture . Left - cbCulture . Margin . Right - cbCulture . Margin . Left ;
2017-12-12 21:50:29 +01:00
}
private void CbCulture_SelectedIndexChanged ( object sender , EventArgs e )
{
2017-12-19 18:15:50 +01:00
SelectedIndexChanged ? . Invoke ( this , e ) ;
2017-12-12 21:50:29 +01:00
}
private void CbCulture_SelectedValueChanged ( object sender , EventArgs e )
{
2017-12-19 18:15:50 +01:00
SelectedValueChanged ? . Invoke ( this , e ) ;
2017-12-12 21:50:29 +01:00
}
}
}