Lua Console - add a button that installs auto-complete for all bizhawk's lua library to Sublime Text 2's lua syntax, still todo - notepad++

This commit is contained in:
adelikat 2016-02-07 08:27:25 -05:00
parent 3b9796232c
commit 36b82c3563
6 changed files with 401 additions and 71 deletions

View File

@ -3,6 +3,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Newtonsoft.Json;
namespace BizHawk.Client.Common
{
@ -53,6 +54,93 @@ namespace BizHawk.Client.Common
return sb.ToString();
}
private class SublimeCompletions
{
public SublimeCompletions()
{
Scope = "source.lua";
}
[JsonProperty(PropertyName = "scope")]
public string Scope { get; set; }
[JsonProperty(PropertyName = "completions")]
public List<Completion> Completions = new List<Completion>();
public class Completion
{
[JsonProperty(PropertyName = "trigger")]
public string Trigger { get; set; }
[JsonProperty(PropertyName = "contents")]
public string Contents { get; set; }
}
}
public string ToSublime2CompletionList()
{
var sc = new SublimeCompletions();
foreach (var f in this.OrderBy(lf => lf.Library).ThenBy(lf => lf.Name))
{
var completion = new SublimeCompletions.Completion
{
Trigger = f.Library + "." + f.Name
};
var sb = new StringBuilder();
if (f.ParameterList.Any())
{
sb
.Append(string.Format("{0}.{1}(", f.Library, f.Name));
var parameters = f.Method.GetParameters()
.ToList();
for (int i = 0; i < parameters.Count; i++)
{
sb
.Append("${")
.Append(i + 1)
.Append(":");
if (parameters[i].IsOptional)
{
sb.Append(string.Format("[{0}]", parameters[i].Name));
}
else
{
sb.Append(parameters[i].Name);
}
sb.Append("}");
if (i < parameters.Count - 1)
{
sb.Append(",");
}
}
sb.Append(")");
}
else
{
sb.Append(string.Format("{0}.{1}()", f.Library, f.Name));
}
completion.Contents = sb.ToString();
sc.Completions.Add(completion);
}
return JsonConvert.SerializeObject(sc);
}
public string ToNotepadPlusPlusAutoComplete()
{
return string.Empty; // TODO
}
}
public class LibraryFunction
@ -73,6 +161,8 @@ namespace BizHawk.Client.Common
public string Library { get; private set; }
public string LibraryDescription { get; private set; }
public MethodInfo Method { get { return _method; } }
public string Name
{
get { return _luaAttributes.Name; }

View File

@ -829,6 +829,7 @@
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Input.cs" />
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Savestate.cs" />
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Tastudio.cs" />
<Compile Include="tools\Lua\LuaAutocompleteInstaller.cs" />
<Compile Include="tools\Lua\LuaCanvas.cs">
<SubType>Form</SubType>
</Compile>

View File

@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk
{
public class LuaAutocompleteInstaller
{
#region API
public enum TextEditors { Sublime2, NotePad }
public bool IsInstalled(TextEditors editor)
{
switch(editor)
{
case TextEditors.Sublime2:
return IsSublimeInstalled();
case TextEditors.NotePad:
return IsNotepadInstalled();
}
return false;
}
public bool IsBizLuaRegistered(TextEditors editor)
{
switch (editor)
{
case TextEditors.Sublime2:
return IsBizLuaSublimeInstalled();
case TextEditors.NotePad:
return IsBizLuaNotepadInstalled();
}
return false;
}
public void InstallBizLua(TextEditors editor)
{
switch(editor)
{
case TextEditors.Sublime2:
InstallBizLuaToSublime2();
break;
case TextEditors.NotePad:
InstallBizLuaToNotepad();
break;
}
}
#endregion
private string AppDataFolder
{
get { return Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); }
}
private bool IsSublimeInstalled()
{
// The most likely location of the app, eventually we should consider looking through the registry or installed apps as a more robust way to detect it;
string exePath = @"C:\Program Files\Sublime Text 2\sublime_text.exe";
if (File.Exists(exePath))
{
return true;
}
return false;
}
private bool IsNotepadInstalled()
{
// The most likely location of the app, eventually we should consider looking through the registry or installed apps as a more robust way to detect it;
string exePath = @"C:\Program Files (x86)\Notepad++\notepad++.exe";
if (File.Exists(exePath))
{
return true;
}
return false;
}
private string SublimeLuaPath = @"Sublime Text 2\Packages\Lua";
private string SublimeCompletionsFilename = "bizhawk.lua.sublime-completions";
private bool IsBizLuaSublimeInstalled()
{
var bizCompletions = Path.Combine(AppDataFolder, SublimeLuaPath, SublimeCompletionsFilename);
if (File.Exists(bizCompletions))
{
return true;
}
return false;
}
private string NotepadPath = "TODO";
private string NotepadAutoCompleteFileName = "TODO";
private bool IsBizLuaNotepadInstalled()
{
var bizCompletions = Path.Combine(AppDataFolder, NotepadPath, NotepadAutoCompleteFileName);
if (File.Exists(bizCompletions))
{
return true;
}
return false;
}
private void InstallBizLuaToSublime2()
{
var bizCompletions = Path.Combine(AppDataFolder, SublimeLuaPath, SublimeCompletionsFilename);
var text = GlobalWin.Tools.LuaConsole.LuaImp.Docs.ToSublime2CompletionList();
File.WriteAllText(bizCompletions, text);
}
private void InstallBizLuaToNotepad()
{
var bizAutocomplete = Path.Combine(AppDataFolder, NotepadPath, NotepadAutoCompleteFileName);
var text = GlobalWin.Tools.LuaConsole.LuaImp.Docs.ToNotepadPlusPlusAutoComplete();
// TODO
//File.WriteAllText(bizCompletions, text);
}
}
}

View File

@ -72,6 +72,10 @@
this.DisableScriptsOnLoadMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ReturnAllIfNoneSelectedMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.RemoveRegisteredFunctionsOnToggleMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ReloadWhenScriptFileChangesMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
this.RegisterToTextEditorsSubMenu = new System.Windows.Forms.ToolStripMenuItem();
this.RegisterSublimeText2MenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.HelpSubMenu = new System.Windows.Forms.ToolStripMenuItem();
this.FunctionsListMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.OnlineDocsMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@ -103,7 +107,7 @@
this.PathName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.imageList1 = new System.Windows.Forms.ImageList(this.components);
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.ReloadWhenScriptFileChangesMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.RegisterNotePadMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ScriptListContextMenu.SuspendLayout();
this.menuStrip1.SuspendLayout();
this.ConsoleContextMenu.SuspendLayout();
@ -458,7 +462,9 @@
this.DisableScriptsOnLoadMenuItem,
this.ReturnAllIfNoneSelectedMenuItem,
this.RemoveRegisteredFunctionsOnToggleMenuItem,
this.ReloadWhenScriptFileChangesMenuItem});
this.ReloadWhenScriptFileChangesMenuItem,
this.toolStripSeparator4,
this.RegisterToTextEditorsSubMenu});
this.SettingsSubMenu.Name = "SettingsSubMenu";
this.SettingsSubMenu.Size = new System.Drawing.Size(61, 20);
this.SettingsSubMenu.Text = "&Settings";
@ -485,6 +491,36 @@
this.RemoveRegisteredFunctionsOnToggleMenuItem.Text = "Remove Registered Functions on Toggle";
this.RemoveRegisteredFunctionsOnToggleMenuItem.Click += new System.EventHandler(this.RemoveRegisteredFunctionsOnToggleMenuItem_Click);
//
// ReloadWhenScriptFileChangesMenuItem
//
this.ReloadWhenScriptFileChangesMenuItem.Name = "ReloadWhenScriptFileChangesMenuItem";
this.ReloadWhenScriptFileChangesMenuItem.Size = new System.Drawing.Size(286, 22);
this.ReloadWhenScriptFileChangesMenuItem.Text = "Reload When Script File Changes";
this.ReloadWhenScriptFileChangesMenuItem.Click += new System.EventHandler(this.ReloadWhenScriptFileChangesMenuItem_Click);
//
// toolStripSeparator4
//
this.toolStripSeparator4.Name = "toolStripSeparator4";
this.toolStripSeparator4.Size = new System.Drawing.Size(283, 6);
//
// RegisterToTextEditorsSubMenu
//
this.RegisterToTextEditorsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.RegisterSublimeText2MenuItem,
this.RegisterNotePadMenuItem});
this.RegisterToTextEditorsSubMenu.Name = "RegisterToTextEditorsSubMenu";
this.RegisterToTextEditorsSubMenu.Size = new System.Drawing.Size(286, 22);
this.RegisterToTextEditorsSubMenu.Text = "Register To Text Editors";
this.RegisterToTextEditorsSubMenu.DropDownOpened += new System.EventHandler(this.RegisterToTextEditorsSubMenu_DropDownOpened);
//
// RegisterSublimeText2MenuItem
//
this.RegisterSublimeText2MenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GreenCheck;
this.RegisterSublimeText2MenuItem.Name = "RegisterSublimeText2MenuItem";
this.RegisterSublimeText2MenuItem.Size = new System.Drawing.Size(152, 22);
this.RegisterSublimeText2MenuItem.Text = "&Sublime Text 2";
this.RegisterSublimeText2MenuItem.Click += new System.EventHandler(this.RegisterSublimeText2MenuItem_Click);
//
// HelpSubMenu
//
this.HelpSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -809,12 +845,12 @@
this.splitContainer1.SplitterDistance = 280;
this.splitContainer1.TabIndex = 7;
//
// ReloadWhenScriptFileChangesMenuItem
// RegisterNotePadMenuItem
//
this.ReloadWhenScriptFileChangesMenuItem.Name = "ReloadWhenScriptFileChangesMenuItem";
this.ReloadWhenScriptFileChangesMenuItem.Size = new System.Drawing.Size(286, 22);
this.ReloadWhenScriptFileChangesMenuItem.Text = "Reload When Script File Changes";
this.ReloadWhenScriptFileChangesMenuItem.Click += new System.EventHandler(this.ReloadWhenScriptFileChangesMenuItem_Click);
this.RegisterNotePadMenuItem.Name = "RegisterNotePadMenuItem";
this.RegisterNotePadMenuItem.Size = new System.Drawing.Size(152, 22);
this.RegisterNotePadMenuItem.Text = "Notepad++";
this.RegisterNotePadMenuItem.Click += new System.EventHandler(this.RegisterNotePadMenuItem_Click);
//
// LuaConsole
//
@ -929,5 +965,9 @@
private System.Windows.Forms.ToolStripMenuItem ReturnAllIfNoneSelectedMenuItem;
private System.Windows.Forms.ToolStripMenuItem RemoveRegisteredFunctionsOnToggleMenuItem;
private System.Windows.Forms.ToolStripMenuItem ReloadWhenScriptFileChangesMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
private System.Windows.Forms.ToolStripMenuItem RegisterToTextEditorsSubMenu;
private System.Windows.Forms.ToolStripMenuItem RegisterSublimeText2MenuItem;
private System.Windows.Forms.ToolStripMenuItem RegisterNotePadMenuItem;
}
}

View File

@ -1060,6 +1060,68 @@ namespace BizHawk.Client.EmuHawk
}
}
private readonly LuaAutocompleteInstaller LuaAutoInstaller = new LuaAutocompleteInstaller();
private void RegisterToTextEditorsSubMenu_DropDownOpened(object sender, EventArgs e)
{
// Hide until this one is implemented
RegisterNotePadMenuItem.Visible = false;
if (LuaAutoInstaller.IsInstalled(LuaAutocompleteInstaller.TextEditors.Sublime2))
{
if (LuaAutoInstaller.IsBizLuaRegistered(LuaAutocompleteInstaller.TextEditors.Sublime2))
{
RegisterSublimeText2MenuItem.Text = "Sublime Text 2 (installed)";
RegisterSublimeText2MenuItem.Font = new Font(RegisterSublimeText2MenuItem.Font, FontStyle.Regular);
RegisterSublimeText2MenuItem.Image = Properties.Resources.GreenCheck;
}
else
{
RegisterSublimeText2MenuItem.Text = "Sublime Text 2 (detected)";
RegisterSublimeText2MenuItem.Font = new Font(RegisterSublimeText2MenuItem.Font, FontStyle.Italic);
RegisterSublimeText2MenuItem.Image = null;
}
}
else
{
RegisterSublimeText2MenuItem.Text = "Sublime Text 2";
RegisterSublimeText2MenuItem.Font = new Font(RegisterSublimeText2MenuItem.Font, FontStyle.Regular);
RegisterSublimeText2MenuItem.Image = null;
}
if (LuaAutoInstaller.IsInstalled(LuaAutocompleteInstaller.TextEditors.NotePad))
{
if (LuaAutoInstaller.IsBizLuaRegistered(LuaAutocompleteInstaller.TextEditors.NotePad))
{
RegisterNotePadMenuItem.Text = "Notepad++ (installed)";
RegisterNotePadMenuItem.Font = new Font(RegisterNotePadMenuItem.Font, FontStyle.Regular);
RegisterNotePadMenuItem.Image = Properties.Resources.GreenCheck;
}
else
{
RegisterNotePadMenuItem.Text = "Notepad++ (detected)";
RegisterNotePadMenuItem.Font = new Font(RegisterNotePadMenuItem.Font, FontStyle.Italic);
RegisterNotePadMenuItem.Image = null;
}
}
else
{
RegisterNotePadMenuItem.Text = "Notepad++";
RegisterNotePadMenuItem.Font = new Font(RegisterNotePadMenuItem.Font, FontStyle.Regular);
RegisterNotePadMenuItem.Image = null;
}
}
private void RegisterSublimeText2MenuItem_Click(object sender, EventArgs e)
{
LuaAutoInstaller.InstallBizLua(LuaAutocompleteInstaller.TextEditors.Sublime2);
}
private void RegisterNotePadMenuItem_Click(object sender, EventArgs e)
{
LuaAutoInstaller.InstallBizLua(LuaAutocompleteInstaller.TextEditors.NotePad);
}
#endregion
#region Help

View File

@ -153,70 +153,69 @@
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACE
DgAAAk1TRnQBSQFMAgEBAwEAASgBAAEoAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
AwABEAMAAQEBAAEgBgABECoAAXYBTwFUAeUBsgG0AdIB/wG7Ab4B1wH/AXgBUwFVAecwAAF2AVQBTwHl
AbIB0gG2Af8BuwHXAb4B/wF4AVUBUwHnMAABewFQAU8B5QHSAb4BsgH/AdcBxQG7Af8BfAJTAedoAAFu
AVkBewH1ATsBQgGXAf8BBwESAYcB/wEIARIBhwH/AQYBEQGHAf8BDQEXAYgB/wEQARoBiQH/AWkBXgGK
AfkgAAFuAXsBYAH1ATsBlwFHAf8BBwGHARYB/wEIAYcBFwH/AQYBhwEUAf8BDQGIARsB/wEQAYkBHgH/
AWkBigFeAfkgAAGOAWkBWQH1AZcBXQE7Af8BhwE1AQcB/wGHATYBCAH/AYcBNAEGAf8BiAE5AQ0B/wGJ
ATwBEAH/AZQBaAFaAflcAAE2AT4BmAH/ATMBOwGYAf8BsAGyAcsB/wHaAdsB2gH/AtEB1QH/AcsBzAHS
Af8BxAHHAc4B/wFaAWABpQH/AUwBRQF6AfkBKwE0AY8B/xgAASgBkgE0Af8BMwGYAT8B/wGwAcsBswH/
AdsC2gH/AdEB1QHSAf8BywHSAcsB/wHFAc4BxAH/AVoBpQFjAf8BTAF6AUYB+QErAY8BNgH/GAABkgFO
ASgB/wGYAVgBMwH/AcsBugGwAf8C2gHbAf8B1QHTAdEB/wHSAc0BywH/Ac4BxgHEAf8BpQF1AVoB/wGK
AVwBQAH5AY8BTgErAf9UAAJAAY0B/QF0AUsBTgHjAv4B/QH/Af4B/QH1Af8C9wHzAf8B7wLuAf8C7QHr
Af8B2QLbAf8B4wHkAeIB/wLAAcwB/wFxAVIBXQHtAUwBSQGDAfsQAAFAAY0BQAH9AXQBTgFLAeMB/wH+
Av8B/gH1Af0B/wH3AfMB9gH/Au4B7wH/Ae0B6wHtAf8C2wHZAf8B5AHiAeMB/wHAAcwBwgH/AXEBXQFS
Ae0BTAGDAUsB+xAAAZMBTAE+Af0BdQFMAUsB4wH+A/8B9QH7Af4B/wHzAfUB9wH/Ae4B7wHuAf8B6wHs
Ae0B/wHbAdkB2gH/AuIB5AH/AcwBxQHAAf8BfAFTAVEB7QGMAVkBQwH7TAABcAFdAXMB8wF7AVcBYAHr
Bf8B/gH9F/8B/gH/AfAB7wHwAf8BzwHQAdYB/wFpAUoBWwHtAXABUwFmAe8IAAFwAXMBXQHzAXsBYAFZ
AesF/wH9Bv8B4wHwAeMB/wGcAc0BnAr/Af4C/wHvAvAB/wHPAdYBzwH/AWkBWwFMAe0BcAFmAVMB7wgA
AY0BYgFXAfMBgwFbAVYB6wT/Af0X/wH+A/8C4wHgAf8BzwHJAccB/wF6AVIBSQHtAYABWwFSAe9IAAFq
AV4BjwH5A/4l/wHwAfIB8AH/AsYBzQH/AUkBPwF1AfkIAAFqAY8BXgH5EP8B3AHtAdwB/wETAXsBEwH/
AYMBwQGDDf8B8gHxAfAB/wHHAc4ByAH/AUkBdQFBAfkIAAGaAW8BXgH5DP8B4QHNAb4B/wG+AZIBjQH/
AfcB8QHvAf8B+wH4AfcB/wHBAZgBjwH/AeoB2gHRBf8B5QHiAeYB/wHOAcoBxwH/AYYBVwE/AflEAAF+
AWYBgAHzAX0BXQFpAe0I/wL1AfsB/wFvAWsB1AH/AaEBnwHnAf8BowGhAeYB/wGiAaEB5QH/AZQBkQHh
Af8BngGcAeYF/wH5AfgB9wH/AecB5AHeAf8BXgFRAXAB9QFdAVkBjwH7AX4BgAFmAfMBfQFpAV0B7RD/
AeQB8QHkAf8BAwF3AQMB/wETAX0BEwH/AZwBzgGcCf8B+QH3AfkB/wHmAd4B5wH/AV4BcAFWAfUBXQGP
AVkB+wGWAW8BZAHzAYkBYAFdAe0M/wGuAXgBVgH/AVsCAgH/AfgB9QHyAf8B+gH3AfUB/wFbAgIB/wGz
AX0BXAX/AfEB9AH1Af8B3gHmAecB/wGFAVkBTgH1AZcBXwFUAftAAAGCAYgBygH/AdAB0gHtCf8C9QH6
Af8BPQE6AbsB/wFpAWYB3gH/AWYBYgHYAf8BYQFdAdMB/wFVAVAB0QH/AaIBoQHpBf8C+QH4Af8B/AH7
AeoB/wGjAaYBvgH/AUUBTAGgAf8BggHKAYoB/wHQAe0B1BH/AeIB8AHiAf8BBAF4AQQB/wECAXgBAgH/
ARMBhAETAf8BmAHMAZgF/wH5AfgB+QH/AfwB6gH6Af8BowG+AaUB/wFFAaABUAH/AcoBnAGCAf8B7QHb
AdAN/wG6AYwBbAH/AY0BJAECAv8C/gH/A/4B/wGNASMBAgH/AbsBiQFqBf8B8gH0AfUB/wHqAfUB/AH/
Ab4BrAGjAf8BoAFmAUUB/0AAAXYBfAHCAf8B5QHmAfQJ/wL3AfsB/wFMAUkBwwH/AXcBdQHjAf8BcgFv
Ad0B/wFtAWoB2AH/AWEBXAHTAf8BqwGpAeoF/wP5Af8B/gH7Ae8B/wG0AbYBxQH/AUMBSwGfAf8BdgHC
AYEB/wHlAfQB5xH/AeIB8AHiAf8BAwF6AQMB/wECAXwBAgH/AQIBdAECAf8BEwGEARMB/wH6AfwB+gH/
A/kB/wH+Ae8B/gH/AbQBxQG2Af8BQwGfAU4B/wHCAZMBdgH/AfQB6wHlDf8BuQGMAW0B/wGnAToBDQH/
AfsB+QH4Af8B+wH6AfkB/wGnAToBDQH/Ab0BjAFtBf8D9AH/Ae8B+gH+Af8BxQG6AbQB/wGfAWQBQwH/
QAABcgF5Ab0B/wLaAe8J/wL3AfsB/wFQAU0BxwH/AX0BewHqAf8BeAF3AeMB/wF1AXMB3wH/AWgBZQHa
Af8BrQGrAesF/wL6AfgB/wH9AfwB7gH/AZ0BoAG7Af8BSwFTAaMB/wFyAb0BegH/AdoB7wHeEf8B4gHw
AeIB/wEEAXoBBAH/AQIBcgECAf8BLgGOAS4B/wHiAfAB4gX/AfoB+AH6Af8B/QHuAfsB/wGdAbsBoQH/
AUsBowFUAf8BvQGOAXIB/wHvAeMB2g3/AbcBiAFoAf8BxAFJASYB/wL9AfwB/wH8AfoB+QH/AcYBTAEo
Af8BwgGPAXIF/wHyAfUB9wH/Ae4B9wH9Af8BuwGoAZ0B/wGjAWoBSwH/QAABegFbAW8B7wGEAWkBeQHx
CP8C9gH7Af8BTQFJAcUB/wF8AXsB6wH/AXgBdwHkAf8BdgFzAeEB/wFmAWMB2wH/AakBpwHrBf8C+wH5
Af8B+wH8Ae4B/wFNAUoBhwH7AXQBWwFnAe8BegFvAVsB7wGEAXkBagHxEP8B4gHwAeIB/wECAXABAgH/
ASoBhwEqAf8B5wHzAecJ/wH7AfkB+wH/AfwB7gH5Af8BTQGHAUwB+wF0AWcBWwHvAYsBZAFbAe8BlwFv
AWgB8Qz/AcEBlwF8Af8BpAFAARgB/wH9AfsB+gH/AfwB+gH5Af8BkwE7AREB/wHMAakBlAX/AfQB9wH5
Af8B7gH1AfwB/wGQAVkBRQH7AYcBWwFaAe9EAAF9AYEBzwn/AvMB+QH/AUsBSAG5Af8BhwGGAdYB/wGH
AYUB1QH/AYcBhQHVAf8BZwFkAcgB/wFvAW4BzAb/Af4B/AH/As4B1wH/ATsBQwGYAf8IAAF9Ac8BjRH/
AdMB6AHTAf8BJgGHASYB/wHiAfAB4g3/Af4B/AL/Ac4B1wHQAf8BOwGYAUUB/wgAAc8BoQF9Kf8B+wP/
AdcB0gHOAf8BmAFcATsB/0gAAYgBeQGkAfkBjgFvAYUB8ST/AfwB+wH2Af8BOQFBAZYB/wF2AVQBWwHp
CAABiAGkAXsB+QGOAYUBdQHxDP8B+gH8AfoB/wHvAfYB7xH/AfwB9gH8Af8BOQGWAUMB/wF2AVsBUgHp
CAABswGHAXgB+QGfAXYBbwHxJP8B9QH6AfwB/wGWAVoBOQH/AX4BVwFSAelMAAKDAb4B/QF/AV0BYgHp
HP8B8gH1AfgB/wFcAVQBcAH1AW8BXAF/AfUQAAGDAb4BiAH9AX8BYgFdAekc/wH0AfgB8gH/AVwBcAFU
AfUBbwF/AWIB9RAAAcMBnQF9Af0BgwFfAV0B6Rz/AfgC8gH/AYYBWQFLAfUBkgFpAVkB9VQAAYIBfwGx
AfsBjwGCAa8B+QLTAfcB/wHxAfAB+wH/AfYB9wL/AfcB+AH9Af8B5AHnAfMB/wF0AVsBagHvAXQBXwF0
AfMBfQFZAWIB6xgAAYIBsQGDAfsBjwGvAYoB+QHTAfcB2gH/AfAB+wHzAf8B9gH/AfcB/wH3Af0B+AH/
AeQB8wHkAf8BdAFqAVsB7wJ0AWAB8wF9AWIBWQHrGAABuwGOAXgB+wG6AZQBgQH5AfcB4wHTAf8B+wH2
AfAC/wH5AfYB/wH9AfkB9wH/AfMB6AHkAf8BiQFeAVsB7wGOAWYBXwHzAYUBXgFZAetcAAGBAV4BaQHr
AY0BkwHXAf8BjgGUAd0B/wGPAZUB4AH/AY0BlAHbAf8BmgGfAdoB/wF4AVMBWwHnJAABgQFpAWAB6wGN
AdcBlgH/AY4B3QGYAf8BjwHgAZkB/wGNAdsBlgH/AZoB2gGiAf8BeAFbAVQB5yQAAYoBYQFeAesB1wGo
AY0B/wHdAawBjgH/AeABrQGPAf8B2wGpAY0B/wHaAbIBmgH/AX4BVQFTAedUAAFCAU0BPgcAAT4DAAEo
AwABQAMAARADAAEBAQABAQUAAYAXAAP/AQAB/AE/AfwBPwH8AT8CAAHwAQ8B8AEPAfABDwIAAeABBwHg
AQcB4AEHAgABwAEDAcABAwHAAQMCAAGAAQEBgAEBAYABAQIAAYABAQGAAQEBgAEBKgABgAEBAYABAQGA
AQECAAGAAQEBgAEBAYABAQIAAcABAwHAAQMBwAEDAgAB4AEHAeABBwHgAQcCAAHwAR8B8AEfAfABHwIA
Cw==
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACA
DgAAAk1TRnQBSQFMAgEBAwEAATgBAAE4AQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
AwABEAMAAQEBAAEgBgABECoAAW4BVgFXAeUBsgG0AdIB/wG7Ab4B1wH/AXEBVQFYAecwAAFuAVcBVgHl
AbIB0gG2Af8BuwHXAb4B/wFxAVgBVQHnMAABcwJWAeUB0gG+AbIB/wHXAcUBuwH/AXQCVQHnaAABbAFZ
AXMB9QE5AUABlwH/AQUBEAGHAf8BBgEQAYcB/wEEAQ8BhwH/AQsBFQGIAf8BDgEYAYkB/wFpAV4BiAH5
IAABbAFzAVwB9QE5AZcBRQH/AQUBhwEUAf8BBgGHARUB/wEEAYcBEgH/AQsBiAEZAf8BDgGJARwB/wFp
AYgBXgH5IAABhgFnAVkB9QGXAVsBOQH/AYcBMwEFAf8BhwE0AQYB/wGHATIBBAH/AYgBNwELAf8BiQE6
AQ4B/wGQAWgBWgH5XAABNAE8AZgB/wExATkBmAH/AbABsgHLAf8B2gHbAdoB/wLRAdUB/wHLAcwB0gH/
AcQBxwHOAf8BWAFeAaUB/wFKAUUBdAH5ASkBMgGPAf8YAAEmAZIBMgH/ATEBmAE9Af8BsAHLAbMB/wHb
AtoB/wHRAdUB0gH/AcsB0gHLAf8BxQHOAcQB/wFYAaUBYQH/AUoBdAFGAfkBKQGPATQB/xgAAZIBTAEm
Af8BmAFWATEB/wHLAboBsAH/AtoB2wH/AdUB0wHRAf8B0gHNAcsB/wHOAcYBxAH/AaUBcwFYAf8BiAFc
AUEB+QGPAUwBKQH/VAACQAGNAf0BawFRAVMB4wL+Af0B/wH+Af0B9QH/AvcB8wH/Ae8C7gH/Au0B6wH/
AdkC2wH/AeMB5AHiAf8CwAHMAf8BawFUAV0B7QFMAUkBgQH7EAABQAGNAUAB/QFrAVMBUQHjAf8B/gL/
Af4B9QH9Af8B9wHzAfYB/wLuAe8B/wHtAesB7QH/AtsB2QH/AeQB4gHjAf8BwAHMAcIB/wFrAV0BVAHt
AUwBgQFLAfsQAAGTAUoBQAH9AWwBUgFRAeMB/gP/AfUB+wH+Af8B8wH1AfcB/wHuAe8B7gH/AesB7AHt
Af8B2wHZAdoB/wLiAeQB/wHMAcUBwAH/AXUBVQFTAe0BigFZAUMB+0wAAW4BXQFwAfMBdAFZAWAB6wX/
Af4B/Rf/Af4B/wHwAe8B8AH/Ac8B0AHWAf8BZwFQAV0B7QFrAVUBZAHvCAABbgFwAV0B8wF0AWABWQHr
Bf8B/Qb/AeMB8AHjAf8BnAHNAZwK/wH+Av8B7wLwAf8BzwHWAc8B/wFnAV0BUAHtAWsBZAFVAe8IAAGF
AV8BWQHzAXsBXQFYAesE/wH9F/8B/gP/AuMB4AH/Ac8ByQHHAf8BcgFUAU8B7QF5AVkBVQHvSAABagFe
AY0B+QP+Jf8B8AHyAfAB/wLGAc0B/wFHAUEBbwH5CAABagGNAV4B+RD/AdwB7QHcAf8BEQF5AREB/wGD
AcEBgw3/AfIB8QHwAf8BxwHOAcgB/wFHAW8BQQH5CAABkgFqAV4B+Qz/AeEBzQG+Af8BvgGSAY0B/wH3
AfEB7wH/AfsB+AH3Af8BwQGYAY8B/wHqAdoB0QX/AeUB4gHmAf8BzgHKAccB/wGEAVcBQQH5RAABdwFi
AXsB8wF1AV0BZwHtCP8C9QH7Af8BbQFpAdQB/wGhAZ8B5wH/AaMBoQHmAf8BogGhAeUB/wGUAZEB4QH/
AZ4BnAHmBf8B+QH4AfcB/wHnAeQB3gH/AVoBUwFuAfUBXQFZAY0B+wF3AXsBYgHzAXUBZwFdAe0Q/wHk
AfEB5AH/AQEBdQEBAf8BEQF7AREB/wGcAc4BnAn/AfkB9wH5Af8B5gHeAecB/wFaAW4BWAH1AV0BjQFZ
AfsBjQFtAWAB8wF/AV4BXQHtDP8BrgF2AVQB/wFZAgAB/wH4AfUB8gH/AfoB9wH1Af8BWQIAAf8BswF7
AVoF/wHxAfQB9QH/Ad4B5gHnAf8BgQFZAVAB9QGVAV8BVAH7QAABggGIAcoB/wHQAdIB7Qn/AvUB+gH/
ATsBOAG7Af8BZwFkAd4B/wFkAWAB2AH/AV8BWwHTAf8BUwFOAdEB/wGiAaEB6QX/AvkB+AH/AfwB+wHq
Af8BowGmAb4B/wFDAUoBoAH/AYIBygGKAf8B0AHtAdQR/wHiAfAB4gH/AQIBdgECAf8BAAF2AQAB/wER
AYQBEQH/AZgBzAGYBf8B+QH4AfkB/wH8AeoB+gH/AaMBvgGlAf8BQwGgAU4B/wHKAZwBggH/Ae0B2wHQ
Df8BugGMAWoB/wGNASIBAAL/Av4B/wP+Af8BjQEhAQAB/wG7AYkBaAX/AfIB9AH1Af8B6gH1AfwB/wG+
AawBowH/AaABZAFDAf9AAAF0AXoBwgH/AeUB5gH0Cf8C9wH7Af8BSgFHAcMB/wF1AXMB4wH/AXABbQHd
Af8BawFoAdgB/wFfAVoB0wH/AasBqQHqBf8D+QH/Af4B+wHvAf8BtAG2AcUB/wFBAUkBnwH/AXQBwgGB
Af8B5QH0AecR/wHiAfAB4gH/AQEBeAEBAf8BAAF6AQAB/wEAAXIBAAH/AREBhAERAf8B+gH8AfoB/wP5
Af8B/gHvAf4B/wG0AcUBtgH/AUEBnwFMAf8BwgGTAXQB/wH0AesB5Q3/AbkBjAFrAf8BpwE4AQsB/wH7
AfkB+AH/AfsB+gH5Af8BpwE4AQsB/wG9AYwBawX/A/QB/wHvAfoB/gH/AcUBugG0Af8BnwFiAUEB/0AA
AXABdwG9Af8C2gHvCf8C9wH7Af8BTgFLAccB/wF7AXkB6gH/AXYBdQHjAf8BcwFxAd8B/wFmAWMB2gH/
Aa0BqwHrBf8C+gH4Af8B/QH8Ae4B/wGdAaABuwH/AUkBUQGjAf8BcAG9AXgB/wHaAe8B3hH/AeIB8AHi
Af8BAgF4AQIB/wEAAXABAAH/ASwBjgEsAf8B4gHwAeIF/wH6AfgB+gH/Af0B7gH7Af8BnQG7AaEB/wFJ
AaMBUgH/Ab0BjgFwAf8B7wHjAdoN/wG3AYgBZgH/AcQBRwEkAf8C/QH8Af8B/AH6AfkB/wHGAUoBJgH/
AcIBjwFwBf8B8gH1AfcB/wHuAfcB/QH/AbsBqAGdAf8BowFoAUkB/0AAAXIBWQFpAe8BfwFlAXMB8Qj/
AvYB+wH/AUsBRwHFAf8BegF5AesB/wF2AXUB5AH/AXQBcQHhAf8BZAFhAdsB/wGpAacB6wX/AvsB+QH/
AfsB/AHuAf8BTQFKAYUB+wFvAVkBZQHvAXIBaQFZAe8BfwFzAWYB8RD/AeIB8AHiAf8BAAFuAQAB/wEo
AYcBKAH/AecB8wHnCf8B+wH5AfsB/wH8Ae4B+QH/AU0BhQFMAfsBbwFlAVkB7wGBAWIBWQHvAY4BbQFk
AfEM/wHBAZcBegH/AaQBPgEWAf8B/QH7AfoB/wH8AfoB+QH/AZMBOQEPAf8BzAGpAZQF/wH0AfcB+QH/
Ae4B9QH8Af8BjgFZAUUB+wF/AVkBWAHvRAABewGBAc8J/wLzAfkB/wFJAUYBuQH/AYcBhgHWAf8BhwGF
AdUB/wGHAYUB1QH/AWUBYgHIAf8BbQFsAcwG/wH+AfwB/wLOAdcB/wE5AUEBmAH/CAABewHPAY0R/wHT
AegB0wH/ASQBhwEkAf8B4gHwAeIN/wH+AfwC/wHOAdcB0AH/ATkBmAFDAf8IAAHPAaEBeyn/AfsD/wHX
AdIBzgH/AZgBWgE5Af9IAAGGAXMBnAH5AYUBbQGAAfEk/wH8AfsB9gH/ATcBPwGWAf8BbgFYAVsB6QgA
AYYBnAF1AfkBhQGAAXEB8Qz/AfoB/AH6Af8B7wH2Ae8R/wH8AfYB/AH/ATcBlgFBAf8BbgFbAVYB6QgA
Aa0BhQFyAfkBkwFyAW0B8ST/AfUB+gH8Af8BlgFYATcB/wF2AVgBVgHpTAACgwG8Af0BdgFdAWIB6Rz/
AfIB9QH4Af8BWQFWAW4B9QFtAVkBeAH1EAABgwG8AYgB/QF2AWIBXQHpHP8B9AH4AfIB/wFZAW4BVgH1
AW0BeAFeAfUQAAG+AZ0BeQH9AXkBXwFdAekc/wH4AvIB/wGCAVkBSwH1AYkBZwFZAfVUAAGAAXkBqQH7
AY0BgAGpAfkC0wH3Af8B8QHwAfsB/wH2AfcC/wH3AfgB/QH/AeQB5wHzAf8BbwFZAWYB7wFwAV8BcAHz
AXcBWQFgAesYAAGAAakBgQH7AY0BqQGIAfkB0wH3AdoB/wHwAfsB8wH/AfYB/wH3Af8B9wH9AfgB/wHk
AfMB5AH/AW8BZgFZAe8CcAFfAfMBdwFgAVkB6xgAAbMBjAFyAfsBsgGQAX8B+QH3AeMB0wH/AfsB9gHw
Av8B+QH2Af8B/QH5AfcB/wHzAegB5AH/AX8BXAFZAe8BhgFiAV8B8wF9AWABWQHrXAABeQFgAWcB6wGN
AZMB1wH/AY4BlAHdAf8BjwGVAeAB/wGNAZQB2wH/AZoBnwHaAf8BcQFVAVwB5yQAAXkBZwFgAesBjQHX
AZYB/wGOAd0BmAH/AY8B4AGZAf8BjQHbAZYB/wGaAdoBogH/AXEBXAFWAeckAAGAAmAB6wHXAagBjQH/
Ad0BrAGOAf8B4AGtAY8B/wHbAakBjQH/AdoBsgGaAf8BdQFYAVUB51QAAUIBTQE+BwABPgMAASgDAAFA
AwABEAMAAQEBAAEBBQABgBcAA/8BAAH8AT8B/AE/AfwBPwIAAfABDwHwAQ8B8AEPAgAB4AEHAeABBwHg
AQcCAAHAAQMBwAEDAcABAwIAAYABAQGAAQEBgAEBAgABgAEBAYABAQGAAQEqAAGAAQEBgAEBAYABAQIA
AYABAQGAAQEBgAEBAgABwAEDAcABAwHAAQMCAAHgAQcB4AEHAeABBwIAAfABHwHwAR8B8AEfAgAL
</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">