Flow.Launcher/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs

205 lines
7 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.Globalization;
2016-01-06 21:34:42 +00:00
using System.Runtime.InteropServices;
2014-03-17 16:43:20 +00:00
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using Mages.Core;
2020-04-21 09:12:17 +00:00
using Flow.Launcher.Plugin.Caculator.ViewModels;
using Flow.Launcher.Plugin.Caculator.Views;
2014-03-17 16:43:20 +00:00
2020-04-21 09:12:17 +00:00
namespace Flow.Launcher.Plugin.Caculator
2014-03-17 16:43:20 +00:00
{
public class Main : IPlugin, IPluginI18n, ISettingProvider
2014-03-17 16:43:20 +00:00
{
private static readonly Regex RegValidExpressChar = new Regex(
2014-03-17 16:43:20 +00:00
@"^(" +
@"ceil|floor|exp|pi|e|max|min|det|abs|log|ln|sqrt|" +
@"sin|cos|tan|arcsin|arccos|arctan|" +
2014-03-17 16:43:20 +00:00
@"eigval|eigvec|eig|sum|polar|plot|round|sort|real|zeta|" +
@"bin2dec|hex2dec|oct2dec|" +
@"==|~=|&&|\|\||" +
@"[ei]|[0-9]|[\+\-\*\/\^\., ""]|[\(\)\|\!\[\]]" +
@")+$", RegexOptions.Compiled);
private static readonly Regex RegBrackets = new Regex(@"[\(\)\[\]]", RegexOptions.Compiled);
2021-03-20 10:02:35 +00:00
private static Engine MagesEngine;
private const string comma = ",";
private const string dot = ".";
private PluginInitContext Context { get; set; }
2014-03-17 16:43:20 +00:00
private static Settings _settings;
private static SettingsViewModel _viewModel;
public void Init(PluginInitContext context)
{
Context = context;
_settings = context.API.LoadSettingJsonStorage<Settings>();
_viewModel = new SettingsViewModel(_settings);
MagesEngine = new Engine(new Configuration
{
Scope = new Dictionary<string, object>
{
{ "e", Math.E }, // e is not contained in the default mages engine
}
});
}
2014-03-17 16:43:20 +00:00
public List<Result> Query(Query query)
2014-03-17 16:43:20 +00:00
{
if (!CanCalculate(query))
{
return new List<Result>();
}
2014-03-17 16:43:20 +00:00
try
{
string expression;
switch (_settings.DecimalSeparator)
{
case DecimalSeparator.Comma:
case DecimalSeparator.UseSystemLocale when CultureInfo.DefaultThreadCurrentCulture.NumberFormat.NumberDecimalSeparator == ",":
expression = query.Search.Replace(",", ".");
break;
default:
expression = query.Search;
break;
}
var result = MagesEngine.Interpret(expression);
if (result?.ToString() == "NaN")
2020-04-21 12:54:41 +00:00
result = Context.API.GetTranslation("flowlauncher_plugin_calculator_not_a_number");
if (result is Function)
2020-04-21 12:54:41 +00:00
result = Context.API.GetTranslation("flowlauncher_plugin_calculator_expression_not_complete");
if (!string.IsNullOrEmpty(result?.ToString()))
2014-03-17 16:43:20 +00:00
{
decimal roundedResult = Math.Round(Convert.ToDecimal(result), _settings.MaxDecimalPlaces, MidpointRounding.AwayFromZero);
string newResult = ChangeDecimalSeparator(roundedResult, GetDecimalSeparator());
2016-01-06 21:34:42 +00:00
return new List<Result>
{
new Result
2014-03-17 16:43:20 +00:00
{
Title = newResult,
IcoPath = "Images/calculator.png",
Score = 300,
2020-04-21 12:54:41 +00:00
SubTitle = Context.API.GetTranslation("flowlauncher_plugin_calculator_copy_number_to_clipboard"),
CopyText = newResult,
Action = c =>
{
try
{
Clipboard.SetDataObject(newResult);
return true;
}
catch (ExternalException)
{
MessageBox.Show("Copy failed, please try later");
return false;
}
}
}
};
2014-03-17 16:43:20 +00:00
}
}
2021-01-05 08:11:38 +00:00
catch (Exception)
{
// ignored
}
2014-03-17 16:43:20 +00:00
return new List<Result>();
}
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;
}
if ((query.Search.Contains(dot) && GetDecimalSeparator() != dot) ||
(query.Search.Contains(comma) && GetDecimalSeparator() != comma))
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.DefaultThreadCurrentCulture.NumberFormat.NumberDecimalSeparator;
switch (_settings.DecimalSeparator)
{
case DecimalSeparator.UseSystemLocale: return systemDecimalSeperator;
case DecimalSeparator.Dot: return dot;
case DecimalSeparator.Comma: return comma;
default: return systemDecimalSeperator;
}
}
2014-03-17 16:43:20 +00:00
private bool IsBracketComplete(string query)
{
var matchs = RegBrackets.Matches(query);
2014-03-17 16:43:20 +00:00
var leftBracketCount = 0;
foreach (Match match in matchs)
{
if (match.Value == "(" || match.Value == "[")
{
leftBracketCount++;
}
else
{
leftBracketCount--;
}
}
return leftBracketCount == 0;
}
2015-02-07 13:27:48 +00:00
public string GetTranslatedPluginTitle()
{
2020-04-21 12:54:41 +00:00
return Context.API.GetTranslation("flowlauncher_plugin_caculator_plugin_name");
2015-02-07 13:27:48 +00:00
}
public string GetTranslatedPluginDescription()
{
2020-04-21 12:54:41 +00:00
return Context.API.GetTranslation("flowlauncher_plugin_caculator_plugin_description");
2015-02-07 13:27:48 +00:00
}
public Control CreateSettingPanel()
{
return new CalculatorSettings(_viewModel);
}
2014-03-17 16:43:20 +00:00
}
}