using System;
using System.Globalization;
using System.Threading;
namespace DelftTools.Utils.Globalization
{
///
/// TODO: extend with DateTime formatting
/// TODO: extend with IntegerNumber formatting
/// TODO: extend with custom formatters (e.g. variable specific)
/// ...
///
public static class RegionalSettingsManager
{
public static event Action LanguageChanged;
public static event Action FormatChanged;
private static readonly CustomFormatProvider customFormatProvider = new CustomFormatProvider();
private static string realNumberFormat = "G5";
///
/// Language in the form of standard cultures "en-US", "ru-RU" ...
///
public static string Language
{
set
{
var ci = new CultureInfo(value)
{
NumberFormat = Thread.CurrentThread.CurrentCulture.NumberFormat,
DateTimeFormat = CreateDateTimeFormatFromSystemSettingsWithoutNameLocalization(),
};
Thread.CurrentThread.CurrentUICulture = ci;
Thread.CurrentThread.CurrentCulture = ci;
if (LanguageChanged != null)
{
LanguageChanged();
}
}
get
{
return Thread.CurrentThread.CurrentCulture.Name;
}
}
public static CultureInfo CurrentCulture
{
get
{
return Thread.CurrentThread.CurrentCulture;
}
}
///
/// TODO: make it configurable
///
public static string DateTimeFormat
{
get
{
return String.Format("yyyy{0}MM{0}dd HH{1}mm{1}ss",
CurrentCulture.DateTimeFormat.DateSeparator,
CurrentCulture.DateTimeFormat.TimeSeparator);
}
}
///
/// Set formatting for real numbers (double, float). See standard .NET formatting strings for more info: http://msdn.microsoft.com/en-us/library/0c899ak8.aspx
/// http://www.csharp-examples.net/string-format-double/
///
public static string RealNumberFormat
{
get
{
return realNumberFormat;
}
set
{
realNumberFormat = value;
if (FormatChanged != null)
{
FormatChanged();
}
}
}
public static IFormatProvider GetCustomFormatProvider()
{
return customFormatProvider;
}
public static string ConvertToString(object value, bool truncateNumbers = true)
{
if (value is DateTime)
{
return ((DateTime) value).ToString(DateTimeFormat);
}
if (truncateNumbers && (value is double || value is float || value is decimal))
{
return ((double) value).ToString(RealNumberFormat);
}
return Convert.ToString(value, CurrentCulture);
}
private static DateTimeFormatInfo CreateDateTimeFormatFromSystemSettingsWithoutNameLocalization()
{
var systemCulture = Thread.CurrentThread.CurrentCulture.DateTimeFormat;
var ci = CultureInfo.InvariantCulture;
var localMachineDateTimeFormat = (DateTimeFormatInfo) systemCulture.Clone();
//don't take the localized names!
localMachineDateTimeFormat.DayNames = ci.DateTimeFormat.DayNames;
localMachineDateTimeFormat.MonthNames = ci.DateTimeFormat.MonthNames;
localMachineDateTimeFormat.AbbreviatedDayNames = ci.DateTimeFormat.AbbreviatedDayNames;
localMachineDateTimeFormat.AbbreviatedMonthGenitiveNames = ci.DateTimeFormat.AbbreviatedMonthGenitiveNames;
localMachineDateTimeFormat.AbbreviatedMonthNames = ci.DateTimeFormat.AbbreviatedMonthNames;
return localMachineDateTimeFormat;
}
///
/// TODO: how to make .NET use this FormatProvider instead of CurrentCulture.NumberInfo? Sealed class problem
///
private class CustomFormatProvider : IFormatProvider, ICustomFormatter
{
public string Format(string format, object arg, IFormatProvider formatProvider)
{
var argType = arg.GetType();
if ((argType == typeof(double) || argType == typeof(float)))
{
return string.Format(CurrentCulture, "{" + realNumberFormat + "}", arg);
}
return string.Format(CurrentCulture, format, arg);
}
public object GetFormat(Type formatType)
{
return (formatType == typeof(ICustomFormatter)) ? this : null;
}
}
}
}