Files
AX-Copilot-Codex/.decompiledproj/AxCopilot/Handlers/ColorHandler.cs

334 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using AxCopilot.SDK;
namespace AxCopilot.Handlers;
public class ColorHandler : IActionHandler
{
private static readonly Dictionary<string, string> _namedColors = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["red"] = "#FF0000",
["빨강"] = "#FF0000",
["빨간색"] = "#FF0000",
["green"] = "#008000",
["초록"] = "#008000",
["초록색"] = "#008000",
["blue"] = "#0000FF",
["파랑"] = "#0000FF",
["파란색"] = "#0000FF",
["white"] = "#FFFFFF",
["흰색"] = "#FFFFFF",
["하양"] = "#FFFFFF",
["black"] = "#000000",
["검정"] = "#000000",
["검은색"] = "#000000",
["yellow"] = "#FFFF00",
["노랑"] = "#FFFF00",
["노란색"] = "#FFFF00",
["orange"] = "#FFA500",
["주황"] = "#FFA500",
["주황색"] = "#FFA500",
["purple"] = "#800080",
["보라"] = "#800080",
["보라색"] = "#800080",
["pink"] = "#FFC0CB",
["분홍"] = "#FFC0CB",
["분홍색"] = "#FFC0CB",
["hotpink"] = "#FF69B4",
["핫핑크"] = "#FF69B4",
["cyan"] = "#00FFFF",
["시안"] = "#00FFFF",
["magenta"] = "#FF00FF",
["마젠타"] = "#FF00FF",
["brown"] = "#A52A2A",
["갈색"] = "#A52A2A",
["gray"] = "#808080",
["grey"] = "#808080",
["회색"] = "#808080",
["회"] = "#808080",
["silver"] = "#C0C0C0",
["은색"] = "#C0C0C0",
["gold"] = "#FFD700",
["금색"] = "#FFD700",
["navy"] = "#000080",
["남색"] = "#000080",
["teal"] = "#008080",
["틸"] = "#008080",
["lime"] = "#00FF00",
["라임"] = "#00FF00",
["maroon"] = "#800000",
["밤색"] = "#800000",
["olive"] = "#808000",
["올리브"] = "#808000",
["coral"] = "#FF7F50",
["코랄"] = "#FF7F50",
["salmon"] = "#FA8072",
["연어색"] = "#FA8072",
["skyblue"] = "#87CEEB",
["하늘색"] = "#87CEEB",
["lightblue"] = "#ADD8E6",
["연파랑"] = "#ADD8E6",
["darkblue"] = "#00008B",
["진파랑"] = "#00008B",
["darkgreen"] = "#006400",
["진초록"] = "#006400",
["lightgreen"] = "#90EE90",
["연초록"] = "#90EE90",
["indigo"] = "#4B0082",
["인디고"] = "#4B0082",
["violet"] = "#EE82EE",
["바이올렛"] = "#EE82EE",
["beige"] = "#F5F5DC",
["베이지"] = "#F5F5DC",
["ivory"] = "#FFFFF0",
["아이보리"] = "#FFFFF0",
["khaki"] = "#F0E68C",
["카키"] = "#F0E68C",
["lavender"] = "#E6E6FA",
["라벤더"] = "#E6E6FA",
["turquoise"] = "#40E0D0",
["터키옥"] = "#40E0D0",
["chocolate"] = "#D2691E",
["초콜릿"] = "#D2691E",
["crimson"] = "#DC143C",
["크림슨"] = "#DC143C",
["transparent"] = "#00000000"
};
private static readonly Regex _hexRe = new Regex("^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$");
private static readonly Regex _rgbRe = new Regex("^(?:rgb\\s*\\()?\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*\\)?$", RegexOptions.IgnoreCase);
private static readonly Regex _rgbaRe = new Regex("^rgba\\s*\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*([\\d.]+)\\s*\\)$", RegexOptions.IgnoreCase);
private static readonly Regex _hslRe = new Regex("^hsl\\s*\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)%?\\s*,\\s*([\\d.]+)%?\\s*\\)$", RegexOptions.IgnoreCase);
public string? Prefix => "color";
public PluginMetadata Metadata => new PluginMetadata("Color", "색상 변환기 — color #FF5500 · color 255,85,0 · color red", "1.0", "AX");
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
{
if (string.IsNullOrWhiteSpace(query))
{
return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("색상 코드를 입력하세요", "예: #FF5500 · 255,85,0 · red · hsl(20,100%,50%)", null, null, null, "\ue771")));
}
string text = query.Trim();
List<LauncherItem> list = new List<LauncherItem>();
if (_hexRe.IsMatch(text))
{
string text2 = text.TrimStart('#');
if (text2.Length == 3)
{
text2 = $"{text2[0]}{text2[0]}{text2[1]}{text2[1]}{text2[2]}{text2[2]}";
}
byte a = byte.MaxValue;
int r;
int g;
int b;
if (text2.Length == 8)
{
a = Convert.ToByte(text2.Substring(0, 2), 16);
r = Convert.ToInt32(text2.Substring(2, 2), 16);
g = Convert.ToInt32(text2.Substring(4, 2), 16);
b = Convert.ToInt32(text2.Substring(6, 2), 16);
}
else
{
r = Convert.ToInt32(text2.Substring(0, 2), 16);
g = Convert.ToInt32(text2.Substring(2, 2), 16);
b = Convert.ToInt32(text2.Substring(4, 2), 16);
}
AddColorItems(list, r, g, b, a, "#" + text2.ToUpperInvariant());
return Task.FromResult((IEnumerable<LauncherItem>)list);
}
Match match = _rgbRe.Match(text);
if (match.Success)
{
int num = int.Parse(match.Groups[1].Value);
int num2 = int.Parse(match.Groups[2].Value);
int num3 = int.Parse(match.Groups[3].Value);
if (num <= 255 && num2 <= 255 && num3 <= 255)
{
AddColorItems(list, num, num2, num3, byte.MaxValue, $"rgb({num},{num2},{num3})");
return Task.FromResult((IEnumerable<LauncherItem>)list);
}
}
Match match2 = _rgbaRe.Match(text);
if (match2.Success)
{
int num4 = int.Parse(match2.Groups[1].Value);
int num5 = int.Parse(match2.Groups[2].Value);
int num6 = int.Parse(match2.Groups[3].Value);
double num7 = double.Parse(match2.Groups[4].Value, CultureInfo.InvariantCulture);
byte a2 = (byte)Math.Clamp((int)(num7 * 255.0), 0, 255);
if (num4 <= 255 && num5 <= 255 && num6 <= 255)
{
AddColorItems(list, num4, num5, num6, a2, $"rgba({num4},{num5},{num6},{num7:G3})");
return Task.FromResult((IEnumerable<LauncherItem>)list);
}
}
Match match3 = _hslRe.Match(text);
if (match3.Success)
{
double num8 = double.Parse(match3.Groups[1].Value, CultureInfo.InvariantCulture);
double num9 = double.Parse(match3.Groups[2].Value, CultureInfo.InvariantCulture) / 100.0;
double num10 = double.Parse(match3.Groups[3].Value, CultureInfo.InvariantCulture) / 100.0;
var (r2, g2, b2) = HslToRgb(num8, num9, num10);
AddColorItems(list, r2, g2, b2, byte.MaxValue, $"hsl({num8:G},{num9 * 100.0:G}%,{num10 * 100.0:G}%)");
return Task.FromResult((IEnumerable<LauncherItem>)list);
}
if (_namedColors.TryGetValue(text, out string value))
{
string text3 = value.TrimStart('#');
int r3 = Convert.ToInt32(text3.Substring(0, 2), 16);
int g3 = Convert.ToInt32(text3.Substring(2, 2), 16);
int b3 = Convert.ToInt32(text3.Substring(4, 2), 16);
AddColorItems(list, r3, g3, b3, byte.MaxValue, value.ToUpperInvariant());
return Task.FromResult((IEnumerable<LauncherItem>)list);
}
string searchQ = text.ToLowerInvariant();
IEnumerable<KeyValuePair<string, string>> enumerable = _namedColors.Where<KeyValuePair<string, string>>((KeyValuePair<string, string> kv) => kv.Key.Contains(searchQ, StringComparison.OrdinalIgnoreCase)).Take(8);
foreach (KeyValuePair<string, string> item in enumerable)
{
list.Add(new LauncherItem(item.Key + " → " + item.Value.ToUpperInvariant(), "Enter로 HEX 복사", null, item.Value.ToUpperInvariant(), null, "\ue771"));
}
if (!list.Any())
{
list.Add(new LauncherItem("인식할 수 없는 색상", "#RRGGBB · RGB(r,g,b) · hsl(h,s%,l%) · red 등 색상 이름", null, null, null, "\uea39"));
}
return Task.FromResult((IEnumerable<LauncherItem>)list);
}
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
{
if (item.Data is string text)
{
try
{
Clipboard.SetText(text);
}
catch
{
}
}
return Task.CompletedTask;
}
private static void AddColorItems(List<LauncherItem> items, int r, int g, int b, byte a, string source)
{
string text = ((a == byte.MaxValue) ? $"#{r:X2}{g:X2}{b:X2}" : $"#{a:X2}{r:X2}{g:X2}{b:X2}");
string text2 = ((a == byte.MaxValue) ? $"rgb({r}, {g}, {b})" : $"rgba({r}, {g}, {b}, {(double)(int)a / 255.0:G3})");
(double h, double s, double l) tuple = RgbToHsl(r, g, b);
double item = tuple.h;
double item2 = tuple.s;
double item3 = tuple.l;
string text3 = $"hsl({item:G3}, {item2 * 100.0:G3}%, {item3 * 100.0:G3}%)";
(double h, double s, double v) tuple2 = RgbToHsv(r, g, b);
double item4 = tuple2.h;
double item5 = tuple2.s;
double item6 = tuple2.v;
string text4 = $"hsv({item4:G3}, {item5 * 100.0:G3}%, {item6 * 100.0:G3}%)";
items.Add(new LauncherItem("HEX → " + text.ToUpperInvariant(), source + " · Enter로 복사", null, text.ToUpperInvariant(), null, "\ue771"));
items.Add(new LauncherItem("RGB → " + text2, source + " · Enter로 복사", null, text2, null, "\ue771"));
items.Add(new LauncherItem("HSL → " + text3, source + " · Enter로 복사", null, text3, null, "\ue771"));
items.Add(new LauncherItem("HSV → " + text4, source + " · Enter로 복사", null, text4, null, "\ue771"));
}
private static (double h, double s, double l) RgbToHsl(int r, int g, int b)
{
double num = (double)r / 255.0;
double num2 = (double)g / 255.0;
double num3 = (double)b / 255.0;
double num4 = Math.Max(num, Math.Max(num2, num3));
double num5 = Math.Min(num, Math.Min(num2, num3));
double num6 = (num4 + num5) / 2.0;
double num7 = 0.0;
double value = 0.0;
if (num4 != num5)
{
double num8 = num4 - num5;
value = ((num6 > 0.5) ? (num8 / (2.0 - num4 - num5)) : (num8 / (num4 + num5)));
num7 = ((num4 == num) ? ((num2 - num3) / num8 + (double)((num2 < num3) ? 6 : 0)) : ((num4 == num2) ? ((num3 - num) / num8 + 2.0) : ((num - num2) / num8 + 4.0)));
num7 /= 6.0;
}
return (h: Math.Round(num7 * 360.0, 1), s: Math.Round(value, 4), l: Math.Round(num6, 4));
}
private static (double h, double s, double v) RgbToHsv(int r, int g, int b)
{
double num = (double)r / 255.0;
double num2 = (double)g / 255.0;
double num3 = (double)b / 255.0;
double num4 = Math.Max(num, Math.Max(num2, num3));
double num5 = Math.Min(num, Math.Min(num2, num3));
double value = num4;
double value2 = 0.0;
double num6 = 0.0;
double num7 = num4 - num5;
if (num4 != 0.0)
{
value2 = num7 / num4;
}
if (num7 != 0.0)
{
num6 = ((num4 == num) ? ((num2 - num3) / num7 + (double)((num2 < num3) ? 6 : 0)) : ((num4 == num2) ? ((num3 - num) / num7 + 2.0) : ((num - num2) / num7 + 4.0)));
num6 /= 6.0;
}
return (h: Math.Round(num6 * 360.0, 1), s: Math.Round(value2, 4), v: Math.Round(value, 4));
}
private static (int r, int g, int b) HslToRgb(double h, double s, double l)
{
double num;
double num2;
double num3;
if (s == 0.0)
{
num = (num2 = (num3 = l));
}
else
{
double num4 = ((l < 0.5) ? (l * (1.0 + s)) : (l + s - l * s));
double p = 2.0 * l - num4;
h /= 360.0;
num = Hue2Rgb(p, num4, h + 1.0 / 3.0);
num2 = Hue2Rgb(p, num4, h);
num3 = Hue2Rgb(p, num4, h - 1.0 / 3.0);
}
return (r: (int)Math.Round(num * 255.0), g: (int)Math.Round(num2 * 255.0), b: (int)Math.Round(num3 * 255.0));
}
private static double Hue2Rgb(double p, double q, double t)
{
if (t < 0.0)
{
t += 1.0;
}
if (t > 1.0)
{
t -= 1.0;
}
if (t < 1.0 / 6.0)
{
return p + (q - p) * 6.0 * t;
}
if (t < 0.5)
{
return q;
}
if (t < 2.0 / 3.0)
{
return p + (q - p) * (2.0 / 3.0 - t) * 6.0;
}
return p;
}
}