diff --git a/Plugins/Wox.Plugin.Calculator/DecimalSeparator.cs b/Plugins/Wox.Plugin.Calculator/DecimalSeparator.cs
new file mode 100644
index 000000000..5aad9b39a
--- /dev/null
+++ b/Plugins/Wox.Plugin.Calculator/DecimalSeparator.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Wox.Core;
+
+namespace Wox.Plugin.Caculator
+{
+ [TypeConverter(typeof(LocalizationConverter))]
+ public enum DecimalSeparator
+ {
+ [LocalizedDescription("wox_plugin_calculator_decimal_seperator_use_system_locale")]
+ UseSystemLocale,
+
+ [LocalizedDescription("wox_plugin_calculator_decimal_seperator_dot")]
+ Dot,
+
+ [LocalizedDescription("wox_plugin_calculator_decimal_seperator_comma")]
+ Comma
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Wox.Plugin.Calculator/Languages/de.xaml b/Plugins/Wox.Plugin.Calculator/Languages/de.xaml
index 286e4bc9b..eb6847af0 100644
--- a/Plugins/Wox.Plugin.Calculator/Languages/de.xaml
+++ b/Plugins/Wox.Plugin.Calculator/Languages/de.xaml
@@ -7,4 +7,10 @@
Keine Zahl (NaN)
Ausdruck falsch oder nicht vollständig (Klammern vergessen?)
Diese Zahl in die Zwischenablage kopieren
+ Dezimaltrennzeichen
+ Das Dezimaltrennzeichen, welches bei der Ausgabe verwendet werden soll.
+ Systemeinstellung nutzen
+ Komma (,)
+ Punkt (.)
+ Max. Nachkommastellen
\ No newline at end of file
diff --git a/Plugins/Wox.Plugin.Calculator/Languages/en.xaml b/Plugins/Wox.Plugin.Calculator/Languages/en.xaml
index 3b5fa32b3..0df0d3342 100644
--- a/Plugins/Wox.Plugin.Calculator/Languages/en.xaml
+++ b/Plugins/Wox.Plugin.Calculator/Languages/en.xaml
@@ -7,4 +7,10 @@
Not a number (NaN)
Expression wrong or incomplete (Did you forget some parentheses?)
Copy this number to the clipboard
+ Decimal separator
+ The decimal separator to be used in the output.
+ Use system locale
+ Comma (,)
+ Dot (.)
+ Max. decimal places
\ No newline at end of file
diff --git a/Plugins/Wox.Plugin.Calculator/Main.cs b/Plugins/Wox.Plugin.Calculator/Main.cs
index fab0b8e03..f2f7f7e18 100644
--- a/Plugins/Wox.Plugin.Calculator/Main.cs
+++ b/Plugins/Wox.Plugin.Calculator/Main.cs
@@ -1,12 +1,18 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Windows;
+using System.Windows.Controls;
using Mages.Core;
+using Wox.Infrastructure.Storage;
+using Wox.Plugin.Caculator.ViewModels;
+using Wox.Plugin.Caculator.Views;
namespace Wox.Plugin.Caculator
{
- public class Main : IPlugin, IPluginI18n
+ public class Main : IPlugin, IPluginI18n, ISavable, ISettingProvider
{
private static readonly Regex RegValidExpressChar = new Regex(
@"^(" +
@@ -21,20 +27,33 @@ namespace Wox.Plugin.Caculator
private static readonly Engine MagesEngine;
private PluginInitContext Context { get; set; }
+ private static Settings _settings;
+ private static SettingsViewModel _viewModel;
+
static Main()
{
- MagesEngine = new Engine();
+ MagesEngine = new Engine();
+ }
+
+ public void Init(PluginInitContext context)
+ {
+ Context = context;
+
+ _viewModel = new SettingsViewModel();
+ _settings = _viewModel.Settings;
}
public List Query(Query query)
{
- if (query.Search.Length <= 2 // don't affect when user only input "e" or "i" keyword
- || !RegValidExpressChar.IsMatch(query.Search)
- || !IsBracketComplete(query.Search)) return new List();
+ if (!CanCalculate(query))
+ {
+ return new List();
+ }
try
{
- var result = MagesEngine.Interpret(query.Search);
+ var expression = query.Search.Replace(",", ".");
+ var result = MagesEngine.Interpret(expression);
if (result.ToString() == "NaN")
result = Context.API.GetTranslation("wox_plugin_calculator_not_a_number");
@@ -42,14 +61,16 @@ namespace Wox.Plugin.Caculator
if (result is Function)
result = Context.API.GetTranslation("wox_plugin_calculator_expression_not_complete");
-
if (!string.IsNullOrEmpty(result?.ToString()))
{
+ decimal roundedResult = Math.Round(Convert.ToDecimal(result), _settings.MaxDecimalPlaces, MidpointRounding.AwayFromZero);
+ string newResult = ChangeDecimalSeparator(roundedResult, GetDecimalSeparator());
+
return new List
{
new Result
{
- Title = result.ToString(),
+ Title = newResult,
IcoPath = "Images/calculator.png",
Score = 300,
SubTitle = Context.API.GetTranslation("wox_plugin_calculator_copy_number_to_clipboard"),
@@ -57,7 +78,7 @@ namespace Wox.Plugin.Caculator
{
try
{
- Clipboard.SetText(result.ToString());
+ Clipboard.SetText(newResult);
return true;
}
catch (ExternalException)
@@ -78,6 +99,53 @@ namespace Wox.Plugin.Caculator
return new List();
}
+ private bool CanCalculate(Query query)
+ {
+ // Don't execute when user only input "e" or "i" keyword
+ if (query.Search.Length < 2)
+ {
+ return false;
+ }
+
+ if (!RegValidExpressChar.IsMatch(query.Search))
+ {
+ return false;
+ }
+
+ if (!IsBracketComplete(query.Search))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private string ChangeDecimalSeparator(decimal value, string newDecimalSeparator)
+ {
+ if (String.IsNullOrEmpty(newDecimalSeparator))
+ {
+ return value.ToString();
+ }
+
+ var numberFormatInfo = new NumberFormatInfo
+ {
+ NumberDecimalSeparator = newDecimalSeparator
+ };
+ return value.ToString(numberFormatInfo);
+ }
+
+ private string GetDecimalSeparator()
+ {
+ string systemDecimalSeperator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
+ switch (_settings.DecimalSeparator)
+ {
+ case DecimalSeparator.UseSystemLocale: return systemDecimalSeperator;
+ case DecimalSeparator.Dot: return ".";
+ case DecimalSeparator.Comma: return ",";
+ default: return systemDecimalSeperator;
+ }
+ }
+
private bool IsBracketComplete(string query)
{
var matchs = RegBrackets.Matches(query);
@@ -96,12 +164,7 @@ namespace Wox.Plugin.Caculator
return leftBracketCount == 0;
}
-
- public void Init(PluginInitContext context)
- {
- Context = context;
- }
-
+
public string GetTranslatedPluginTitle()
{
return Context.API.GetTranslation("wox_plugin_caculator_plugin_name");
@@ -111,5 +174,15 @@ namespace Wox.Plugin.Caculator
{
return Context.API.GetTranslation("wox_plugin_caculator_plugin_description");
}
+
+ public Control CreateSettingPanel()
+ {
+ return new CalculatorSettings(_viewModel);
+ }
+
+ public void Save()
+ {
+ _viewModel.Save();
+ }
}
}
diff --git a/Plugins/Wox.Plugin.Calculator/Settings.cs b/Plugins/Wox.Plugin.Calculator/Settings.cs
new file mode 100644
index 000000000..ce01f2da0
--- /dev/null
+++ b/Plugins/Wox.Plugin.Calculator/Settings.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Wox.Plugin.Caculator
+{
+ public class Settings
+ {
+ public DecimalSeparator DecimalSeparator { get; set; } = DecimalSeparator.UseSystemLocale;
+ public int MaxDecimalPlaces { get; set; } = 10;
+ }
+}
diff --git a/Plugins/Wox.Plugin.Calculator/ViewModels/SettingsViewModel.cs b/Plugins/Wox.Plugin.Calculator/ViewModels/SettingsViewModel.cs
new file mode 100644
index 000000000..8550f47a5
--- /dev/null
+++ b/Plugins/Wox.Plugin.Calculator/ViewModels/SettingsViewModel.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Wox.Infrastructure.Storage;
+using Wox.Infrastructure.UserSettings;
+
+namespace Wox.Plugin.Caculator.ViewModels
+{
+ public class SettingsViewModel : BaseModel, ISavable
+ {
+ private readonly PluginJsonStorage _storage;
+
+ public SettingsViewModel()
+ {
+ _storage = new PluginJsonStorage();
+ Settings = _storage.Load();
+ }
+
+ public Settings Settings { get; set; }
+
+ public IEnumerable MaxDecimalPlacesRange => Enumerable.Range(1, 20);
+
+ public void Save()
+ {
+ _storage.Save();
+ }
+ }
+}
diff --git a/Plugins/Wox.Plugin.Calculator/Views/CalculatorSettings.xaml b/Plugins/Wox.Plugin.Calculator/Views/CalculatorSettings.xaml
new file mode 100644
index 000000000..183f10e5f
--- /dev/null
+++ b/Plugins/Wox.Plugin.Calculator/Views/CalculatorSettings.xaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Plugins/Wox.Plugin.Calculator/Views/CalculatorSettings.xaml.cs b/Plugins/Wox.Plugin.Calculator/Views/CalculatorSettings.xaml.cs
new file mode 100644
index 000000000..c15bdda77
--- /dev/null
+++ b/Plugins/Wox.Plugin.Calculator/Views/CalculatorSettings.xaml.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Wox.Plugin.Caculator.ViewModels;
+
+namespace Wox.Plugin.Caculator.Views
+{
+ ///
+ /// Interaction logic for CalculatorSettings.xaml
+ ///
+ public partial class CalculatorSettings : UserControl
+ {
+ private readonly SettingsViewModel _viewModel;
+ private readonly Settings _settings;
+
+ public CalculatorSettings(SettingsViewModel viewModel)
+ {
+ _viewModel = viewModel;
+ _settings = viewModel.Settings;
+ DataContext = viewModel;
+ InitializeComponent();
+ }
+
+ private void CalculatorSettings_Loaded(object sender, RoutedEventArgs e)
+ {
+ DecimalSeparatorComboBox.SelectedItem = _settings.DecimalSeparator;
+ MaxDecimalPlaces.SelectedItem = _settings.MaxDecimalPlaces;
+ }
+ }
+
+
+}
diff --git a/Plugins/Wox.Plugin.Calculator/Wox.Plugin.Calculator.csproj b/Plugins/Wox.Plugin.Calculator/Wox.Plugin.Calculator.csproj
index b0a091934..f24ad118e 100644
--- a/Plugins/Wox.Plugin.Calculator/Wox.Plugin.Calculator.csproj
+++ b/Plugins/Wox.Plugin.Calculator/Wox.Plugin.Calculator.csproj
@@ -46,14 +46,22 @@
+
+
Properties\SolutionAssemblyInfo.cs
+
+
+
+
+ CalculatorSettings.xaml
+
@@ -61,6 +69,10 @@
+
+ {B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}
+ Wox.Core
+
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}
Wox.Infrastructure
@@ -122,12 +134,18 @@
10.3.0
- 1.5.0
+ 1.6.0
4.0.0
+
+
+ Designer
+ MSBuild:Compile
+
+
diff --git a/Wox.Core/Resource/LocalizationConverter.cs b/Wox.Core/Resource/LocalizationConverter.cs
new file mode 100644
index 000000000..d86bf5f7e
--- /dev/null
+++ b/Wox.Core/Resource/LocalizationConverter.cs
@@ -0,0 +1,37 @@
+using System;
+using System.ComponentModel;
+using System.Globalization;
+using System.Reflection;
+using System.Windows.Data;
+
+namespace Wox.Core
+{
+ public class LocalizationConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (targetType == typeof(string) && value != null)
+ {
+ FieldInfo fi = value.GetType().GetField(value.ToString());
+ if (fi != null)
+ {
+ string localizedDescription = string.Empty;
+ var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
+ if ((attributes.Length > 0) && (!String.IsNullOrEmpty(attributes[0].Description)))
+ {
+ localizedDescription = attributes[0].Description;
+ }
+
+ return (!String.IsNullOrEmpty(localizedDescription)) ? localizedDescription : value.ToString();
+ }
+ }
+
+ return string.Empty;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Wox.Core/Resource/LocalizedDescriptionAttribute.cs b/Wox.Core/Resource/LocalizedDescriptionAttribute.cs
new file mode 100644
index 000000000..ef1257220
--- /dev/null
+++ b/Wox.Core/Resource/LocalizedDescriptionAttribute.cs
@@ -0,0 +1,27 @@
+using System.ComponentModel;
+using Wox.Core.Resource;
+
+namespace Wox.Core
+{
+ public class LocalizedDescriptionAttribute : DescriptionAttribute
+ {
+ private readonly Internationalization _translator;
+ private readonly string _resourceKey;
+
+ public LocalizedDescriptionAttribute(string resourceKey)
+ {
+ _translator = InternationalizationManager.Instance;
+ _resourceKey = resourceKey;
+ }
+
+ public override string Description
+ {
+ get
+ {
+ string description = _translator.GetTranslation(_resourceKey);
+ return string.IsNullOrWhiteSpace(description) ?
+ string.Format("[[{0}]]", _resourceKey) : description;
+ }
+ }
+ }
+}
diff --git a/Wox.Core/Wox.Core.csproj b/Wox.Core/Wox.Core.csproj
index bb5fbdc3c..0cdc22b52 100644
--- a/Wox.Core/Wox.Core.csproj
+++ b/Wox.Core/Wox.Core.csproj
@@ -53,6 +53,8 @@
+
+
diff --git a/Wox.Infrastructure/UI/EnumBindingSource.cs b/Wox.Infrastructure/UI/EnumBindingSource.cs
new file mode 100644
index 000000000..c23aacd81
--- /dev/null
+++ b/Wox.Infrastructure/UI/EnumBindingSource.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Windows.Markup;
+
+namespace Wox.Infrastructure.UI
+{
+ public class EnumBindingSourceExtension : MarkupExtension
+ {
+ private Type _enumType;
+ public Type EnumType
+ {
+ get { return _enumType; }
+ set
+ {
+ if (value != _enumType)
+ {
+ if (value != null)
+ {
+ Type enumType = Nullable.GetUnderlyingType(value) ?? value;
+ if (!enumType.IsEnum)
+ {
+ throw new ArgumentException("Type must represent an enum.");
+ }
+ }
+
+ _enumType = value;
+ }
+ }
+ }
+
+ public EnumBindingSourceExtension() { }
+
+ public EnumBindingSourceExtension(Type enumType)
+ {
+ EnumType = enumType;
+ }
+
+ public override object ProvideValue(IServiceProvider serviceProvider)
+ {
+ if (_enumType == null)
+ {
+ throw new InvalidOperationException("The EnumType must be specified.");
+ }
+
+ Type actualEnumType = Nullable.GetUnderlyingType(_enumType) ?? _enumType;
+ Array enumValues = Enum.GetValues(actualEnumType);
+
+ if (actualEnumType == _enumType)
+ {
+ return enumValues;
+ }
+
+ Array tempArray = Array.CreateInstance(actualEnumType, enumValues.Length + 1);
+ enumValues.CopyTo(tempArray, 1);
+ return tempArray;
+ }
+ }
+}
diff --git a/Wox.Infrastructure/Wox.Infrastructure.csproj b/Wox.Infrastructure/Wox.Infrastructure.csproj
index 16194a35a..445454093 100644
--- a/Wox.Infrastructure/Wox.Infrastructure.csproj
+++ b/Wox.Infrastructure/Wox.Infrastructure.csproj
@@ -72,6 +72,7 @@
+