diff --git a/CodeMaid.config b/CodeMaid.config
new file mode 100644
index 0000000..cf6d626
--- /dev/null
+++ b/CodeMaid.config
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+ //**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+
+
+ False
+
+
+
+
\ No newline at end of file
diff --git a/Helpers/IconListJsonConverter.cs b/Helpers/IconListJsonConverter.cs
deleted file mode 100644
index 6d43d13..0000000
--- a/Helpers/IconListJsonConverter.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-//**********************
-//MyToolbar
-//Copyright(C) 2018 www.codestack.net
-//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
-//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
-//**********************
-
-using CodeStack.Community.Sw.MyToolbar.Preferences;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Linq;
-
-namespace CodeStack.Community.Sw.MyToolbar.Helpers
-{
- public class IconListJsonConverter : JsonConverter
- {
- private readonly Type[] m_KnownTypes = new Type[]
- {
- typeof(HighResIcons),
- typeof(BasicIcons),
- typeof(MasterIcons)
- };
-
- public override bool CanConvert(Type objectType)
- {
- return objectType == typeof(IIconList);
- }
-
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
- {
- var jObj = JObject.Load(reader);
-
- var type = m_KnownTypes.FirstOrDefault(t => Matches(t, jObj));
-
- if (type == null)
- {
- throw new InvalidCastException("Failed to extract the icon information. Make sure that correct format is used");
- }
-
- return jObj.ToObject(type);
- }
-
- private bool Matches(Type type, JObject jObj)
- {
- var jPrps = jObj.Children().Select(p => p.Name).ToList();
- var tPrps = type.GetProperties().Select(p => p.Name).ToList();
-
- jPrps.Sort();
- tPrps.Sort();
-
- return jPrps.SequenceEqual(tPrps);
- }
-
- public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/Helpers/IconsConverter.cs b/Helpers/IconsConverter.cs
deleted file mode 100644
index 5527c6a..0000000
--- a/Helpers/IconsConverter.cs
+++ /dev/null
@@ -1,204 +0,0 @@
-//**********************
-//MyToolbar
-//Copyright(C) 2018 www.codestack.net
-//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
-//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
-//**********************
-
-using CodeStack.Community.Sw.MyToolbar.Preferences;
-using CodeStack.Community.Sw.MyToolbar.Properties;
-using System;
-using System.Drawing;
-using System.Drawing.Drawing2D;
-using System.Drawing.Imaging;
-using System.IO;
-using System.Linq;
-
-namespace CodeStack.Community.Sw.MyToolbar.Helpers
-{
- internal static class IconsConverter
- {
- private class IconData
- {
- internal string SourceIconPath { get; set; }
- internal Size TargetSize { get; set; }
- internal string TargetIconPath { get; private set; }
-
- internal IconData(string sourceIconPath, Size targetSize)
- {
- var destDir = Path.Combine(Locations.AppDirectoryPath,
- Settings.Default.IconsCacheFolder);
-
- SourceIconPath = sourceIconPath;
- TargetSize = targetSize;
- TargetIconPath = Path.Combine(destDir, $"icon_{targetSize.Width}x{targetSize.Height}.bmp");
- }
- }
-
- internal static string[] ConvertIcons(IIconList icons, bool highRes)
- {
- if (icons == null)
- {
- throw new ArgumentException("Icons are not specified");
- }
-
- IconData[] iconsData;
-
- if (icons is HighResIcons)
- {
- var highResIcons = icons as HighResIcons;
-
- if (highRes)
- {
- iconsData = new IconData[]
- {
- new IconData(highResIcons.Size20x20, new Size(20,20)),
- new IconData(highResIcons.Size32x32, new Size(32,32)),
- new IconData(highResIcons.Size40x40, new Size(40,40)),
- new IconData(highResIcons.Size64x64, new Size(64,64)),
- new IconData(highResIcons.Size96x96, new Size(96,96)),
- new IconData(highResIcons.Size128x128, new Size(128,128))
- };
- }
- else
- {
- iconsData = new IconData[]
- {
- new IconData(highResIcons.Size20x20, new Size(16,16)),
- new IconData(highResIcons.Size32x32, new Size(24,24)),
- };
- }
- }
- else if (icons is BasicIcons)
- {
- var basicIcons = icons as BasicIcons;
-
- if (highRes)
- {
- iconsData = new IconData[]
- {
- new IconData(basicIcons.Size16x16, new Size(20,20)),
- new IconData(basicIcons.Size24x24, new Size(32,32)),
- new IconData(basicIcons.Size24x24, new Size(40,40)),
- new IconData(basicIcons.Size24x24, new Size(64,64)),
- new IconData(basicIcons.Size24x24, new Size(96,96)),
- new IconData(basicIcons.Size24x24, new Size(128,128))
- };
- }
- else
- {
- iconsData = new IconData[]
- {
- new IconData(basicIcons.Size16x16, new Size(16,16)),
- new IconData(basicIcons.Size24x24, new Size(24,24)),
- };
- }
- }
- else if (icons is MasterIcons)
- {
- var masterIcons = icons as MasterIcons;
-
- if (highRes)
- {
- iconsData = new IconData[]
- {
- new IconData(masterIcons.IconPath, new Size(20,20)),
- new IconData(masterIcons.IconPath, new Size(32,32)),
- new IconData(masterIcons.IconPath, new Size(40,40)),
- new IconData(masterIcons.IconPath, new Size(64,64)),
- new IconData(masterIcons.IconPath, new Size(96,96)),
- new IconData(masterIcons.IconPath, new Size(128,128))
- };
- }
- else
- {
- iconsData = new IconData[]
- {
- new IconData(masterIcons.IconPath, new Size(16,16)),
- new IconData(masterIcons.IconPath, new Size(24,24)),
- };
- }
- }
- else
- {
- throw new NotSupportedException($"Specified icons '{icons.GetType().FullName}' are not supported");
- }
-
- foreach (var iconData in iconsData)
- {
- CreateBitmap(iconData.SourceIconPath,
- iconData.TargetIconPath,
- iconData.TargetSize, Color.FromArgb(192, 192, 192));
- }
-
- return iconsData.Select(i => i.TargetIconPath).ToArray();
- }
-
- private static void CreateBitmap(string sourceIcon,
- string targetIcon, Size size, Color background)
- {
- if (File.Exists(sourceIcon))
- {
- using (var srcImg = Image.FromFile(sourceIcon))
- {
- using (var bmp = new Bitmap(size.Width,
- size.Height, PixelFormat.Format24bppRgb))
- {
- bmp.SetResolution(
- srcImg.HorizontalResolution,
- srcImg.VerticalResolution);
-
- var widthScale = (double)size.Width / (double)srcImg.Width;
- var heightScale = (double)size.Height / (double)srcImg.Height;
- var scale = Math.Min(widthScale, heightScale);
-
- int destX = 0;
- int destY = 0;
-
- if (heightScale < widthScale)
- {
- destX = (int)(size.Width - srcImg.Width * scale) / 2;
- }
- else
- {
- destY = (int)(size.Height - srcImg.Height * scale) / 2;
- }
-
- int destWidth = (int)(srcImg.Width * scale);
- int destHeight = (int)(srcImg.Height * scale);
-
- using (var graph = Graphics.FromImage(bmp))
- {
- graph.InterpolationMode = InterpolationMode.HighQualityBicubic;
- graph.SmoothingMode = SmoothingMode.HighQuality;
- graph.PixelOffsetMode = PixelOffsetMode.HighQuality;
-
- using (var brush = new SolidBrush(background))
- {
- graph.FillRectangle(brush, 0, 0, bmp.Width, bmp.Height);
- }
-
- graph.DrawImage(srcImg,
- new Rectangle(destX, destY, destWidth, destHeight),
- new Rectangle(0, 0, srcImg.Width, srcImg.Height),
- GraphicsUnit.Pixel);
- }
-
- var dir = Path.GetDirectoryName(targetIcon);
-
- if (!Directory.Exists(dir))
- {
- Directory.CreateDirectory(dir);
- }
-
- bmp.Save(targetIcon);
- }
- }
- }
- else
- {
- throw new FileNotFoundException($"Specified icon '{sourceIcon}' doesn't exist");
- }
- }
- }
-}
diff --git a/Installer/AddInReg.wxs b/Installer/AddInReg.wxs
new file mode 100644
index 0000000..80be75c
--- /dev/null
+++ b/Installer/AddInReg.wxs
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Installer/AddInRegistry.wxs b/Installer/AddInRegistry.wxs
new file mode 100644
index 0000000..b9491e3
--- /dev/null
+++ b/Installer/AddInRegistry.wxs
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Installer/Addin11.wxs b/Installer/Addin11.wxs
new file mode 100644
index 0000000..7e2455c
--- /dev/null
+++ b/Installer/Addin11.wxs
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Installer/DirectoryHeatTransform.xslt b/Installer/DirectoryHeatTransform.xslt
new file mode 100644
index 0000000..3dde9f2
--- /dev/null
+++ b/Installer/DirectoryHeatTransform.xslt
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Installer/Files.wxs b/Installer/Files.wxs
new file mode 100644
index 0000000..686fd5e
--- /dev/null
+++ b/Installer/Files.wxs
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Installer/Installer.wixproj b/Installer/Installer.wixproj
new file mode 100644
index 0000000..7c232cd
--- /dev/null
+++ b/Installer/Installer.wixproj
@@ -0,0 +1,60 @@
+
+
+
+ Debug
+ x64
+ 3.10
+ CF763A1B-6456-4152-B987-4F4FA05B74F3
+ 2.0
+ my-toolbar
+ Package
+
+
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+ Debug;
+
+
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+ SourceOutDir=..\Build
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(WixExtDir)\WixUtilExtension.dll
+ WixUtilExtension
+
+
+ $(WixExtDir)\WixUIExtension.dll
+ WixUIExtension
+
+
+
+
+
+
+
+
+
+
+
+
+ "%25Wix%25bin\heat" file "$(SolutionDir)Build\CodeStack.Sw.MyToolbar.dll" -gg -srd -sfrag -template fragment -cg AddinComponents -var var.SourceOutDir -dr INSTALLFOLDER -out "$(ProjectDir)Addin11.wxs"
+
+
\ No newline at end of file
diff --git a/Installer/Product.wxs b/Installer/Product.wxs
new file mode 100644
index 0000000..648505d
--- /dev/null
+++ b/Installer/Product.wxs
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Installer/Resources/banner.bmp b/Installer/Resources/banner.bmp
index 986a608..fdb527a 100644
Binary files a/Installer/Resources/banner.bmp and b/Installer/Resources/banner.bmp differ
diff --git a/Installer/Resources/dialog.bmp b/Installer/Resources/dialog.bmp
index ac7fcfc..67cb1a8 100644
Binary files a/Installer/Resources/dialog.bmp and b/Installer/Resources/dialog.bmp differ
diff --git a/Installer/Resources/eula.rtf b/Installer/Resources/eula.rtf
index eab115f..0ec9224 100644
--- a/Installer/Resources/eula.rtf
+++ b/Installer/Resources/eula.rtf
@@ -1,228 +1,72 @@
-{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff39\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang3081\deflangfe3081\themelang3081\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}
-{\f39\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Liberation Serif{\*\falt Times New Roman};}{\f40\fbidi \fswiss\fcharset204\fprq2{\*\panose 020b0604020202020204}Liberation Sans{\*\falt Arial};}
-{\f41\fbidi \fmodern\fcharset204\fprq1{\*\panose 02070409020205020404}Liberation Mono{\*\falt Courier New};}{\flomajor\f31500\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}
-{\fdbmajor\f31501\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset204\fprq2{\*\panose 02040503050406030204}Cambria;}
-{\fbimajor\f31503\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}
-{\fdbminor\f31505\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset204\fprq2{\*\panose 020f0502020204030204}Calibri;}
-{\fbiminor\f31507\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f47\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\f45\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
-{\f48\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f49\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f50\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f51\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
-{\f52\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f53\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f437\fbidi \froman\fcharset0\fprq2 Liberation Serif{\*\falt Times New Roman};}
-{\f435\fbidi \froman\fcharset238\fprq2 Liberation Serif CE{\*\falt Times New Roman};}{\f438\fbidi \froman\fcharset161\fprq2 Liberation Serif Greek{\*\falt Times New Roman};}
-{\f439\fbidi \froman\fcharset162\fprq2 Liberation Serif Tur{\*\falt Times New Roman};}{\f440\fbidi \froman\fcharset177\fprq2 Liberation Serif (Hebrew){\*\falt Times New Roman};}
-{\f442\fbidi \froman\fcharset186\fprq2 Liberation Serif Baltic{\*\falt Times New Roman};}{\f443\fbidi \froman\fcharset163\fprq2 Liberation Serif (Vietnamese){\*\falt Times New Roman};}{\f447\fbidi \fswiss\fcharset0\fprq2 Liberation Sans{\*\falt Arial};}
-{\f445\fbidi \fswiss\fcharset238\fprq2 Liberation Sans CE{\*\falt Arial};}{\f448\fbidi \fswiss\fcharset161\fprq2 Liberation Sans Greek{\*\falt Arial};}{\f449\fbidi \fswiss\fcharset162\fprq2 Liberation Sans Tur{\*\falt Arial};}
-{\f450\fbidi \fswiss\fcharset177\fprq2 Liberation Sans (Hebrew){\*\falt Arial};}{\f452\fbidi \fswiss\fcharset186\fprq2 Liberation Sans Baltic{\*\falt Arial};}{\f453\fbidi \fswiss\fcharset163\fprq2 Liberation Sans (Vietnamese){\*\falt Arial};}
-{\f457\fbidi \fmodern\fcharset0\fprq1 Liberation Mono{\*\falt Courier New};}{\f455\fbidi \fmodern\fcharset238\fprq1 Liberation Mono CE{\*\falt Courier New};}{\f458\fbidi \fmodern\fcharset161\fprq1 Liberation Mono Greek{\*\falt Courier New};}
-{\f459\fbidi \fmodern\fcharset162\fprq1 Liberation Mono Tur{\*\falt Courier New};}{\f460\fbidi \fmodern\fcharset177\fprq1 Liberation Mono (Hebrew){\*\falt Courier New};}{\f462\fbidi \fmodern\fcharset186\fprq1 Liberation Mono Baltic{\*\falt Courier New};}
-{\f463\fbidi \fmodern\fcharset163\fprq1 Liberation Mono (Vietnamese){\*\falt Courier New};}{\flomajor\f31510\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
-{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
-{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
-{\fdbmajor\f31520\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
-{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
-{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31530\fbidi \froman\fcharset0\fprq2 Cambria;}
-{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
-{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31540\fbidi \froman\fcharset0\fprq2 Times New Roman;}
-{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
-{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
-{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31550\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
-{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
-{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
-{\fdbminor\f31560\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
-{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
-{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31570\fbidi \fswiss\fcharset0\fprq2 Calibri;}
-{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
-{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31580\fbidi \froman\fcharset0\fprq2 Times New Roman;}
-{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
-{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
-{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;
-\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;
-\chyperlink\ctint255\cshade255\red0\green0\blue255;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{
-\ql \li0\ri0\widctlpar\wrapdefault\hyphpar0\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1081 \ltrch\fcs0 \f39\fs24\lang3081\langfe2052\kerning1\cgrid\langnp3081\langfenp2052 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive
-\ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
-\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang3081\langfe3081\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp3081 \snext11 \ssemihidden \sunhideused
-Normal Table;}{\*\cs15 \additive \ul\cf9\lang255\langfe255\langnp255\langfenp255 Internet Link;}{\s16\ql \li0\ri0\sb240\sa120\keepn\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af40\afs28\alang1025 \ltrch\fcs0
-\fs28\lang3081\langfe3081\loch\f40\hich\af39\dbch\af0\cgrid\langnp3081\langfenp3081 \sbasedon0 \snext17 Heading;}{\s17\ql \li0\ri0\sa140\sl288\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
-\fs24\lang3081\langfe3081\loch\f39\hich\af39\dbch\af31505\cgrid\langnp3081\langfenp3081 \sbasedon0 \snext17 Text Body;}{\s18\ql \li0\ri0\sa140\sl288\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
-\f39\fs24\lang3081\langfe3081\cgrid\langnp3081\langfenp3081 \sbasedon17 \snext18 List;}{\s19\ql \li0\ri0\sb120\sa120\nowidctlpar\noline\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs24\alang1025 \ltrch\fcs0
-\i\f39\fs24\lang3081\langfe3081\cgrid\langnp3081\langfenp3081 \sbasedon0 \snext19 \sqformat caption;}{\s20\ql \li0\ri0\nowidctlpar\noline\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
-\f39\fs24\lang3081\langfe3081\cgrid\langnp3081\langfenp3081 \sbasedon0 \snext20 Index;}{\s21\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af41\afs20\alang1025 \ltrch\fcs0
-\fs20\lang3081\langfe3081\loch\f41\hich\af39\dbch\af0\cgrid\langnp3081\langfenp3081 \sbasedon0 \snext21 Preformatted Text;}{\*\cs22 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf17 \sbasedon10 \sunhideused \styrsid12742888 Hyperlink;}}
-{\*\rsidtbl \rsid3086748\rsid12742888}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Artem Taturevich}{\creatim\yr2018\mo7\dy15\hr16\min48}
-{\revtim\yr2018\mo7\dy15\hr19\min54}{\version2}{\edmins1}{\nofpages1}{\nofwords273}{\nofchars1560}{\nofcharsws1830}{\vern49167}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}
-\paperw11906\paperh16838\margl1134\margr1134\margt1134\margb1134\gutter0\ltrsect
-\deftab709\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\formshade\horzdoc\dghspace120\dgvspace120
-\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot12742888 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0{\*\ftnsep \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\hyphpar0\faauto\rin0\lin0\itap0
-\rtlch\fcs1 \af39\afs24\alang1081 \ltrch\fcs0 \f39\fs24\lang3081\langfe2052\kerning1\cgrid\langnp3081\langfenp2052 {\rtlch\fcs1 \af0\alang1025 \ltrch\fcs0 \lang3081\langfe3081\kerning0\dbch\af31505\langfenp3081\insrsid3086748 \chftnsep }{\rtlch\fcs1
-\af39 \ltrch\fcs0 \insrsid3086748
-\par }}{\*\ftnsepc \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\hyphpar0\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1081 \ltrch\fcs0 \f39\fs24\lang3081\langfe2052\kerning1\cgrid\langnp3081\langfenp2052 {\rtlch\fcs1 \af39 \ltrch\fcs0
-\insrsid3086748 \chftnsepc
-\par }}{\*\aftnsep \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\hyphpar0\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1081 \ltrch\fcs0 \f39\fs24\lang3081\langfe2052\kerning1\cgrid\langnp3081\langfenp2052 {\rtlch\fcs1 \af39 \ltrch\fcs0
-\insrsid3086748 \chftnsep
-\par }}{\*\aftnsepc \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\hyphpar0\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1081 \ltrch\fcs0 \f39\fs24\lang3081\langfe2052\kerning1\cgrid\langnp3081\langfenp2052 {\rtlch\fcs1 \af39 \ltrch\fcs0
-\insrsid3086748 \chftnsepc
-\par }}\ltrpar \sectd \ltrsect\sbknone\linex0\sectunlocked1\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang
-{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7
-\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar
-\ql \li0\ri0\widctlpar\wrapdefault\hyphpar0\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1081 \ltrch\fcs0 \f39\fs24\lang3081\langfe2052\kerning1\cgrid\langnp3081\langfenp2052 {\rtlch\fcs1 \ab\af39 \ltrch\fcs0 \b\insrsid3086748 Terms & Conditions}{
-\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748
-\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3086748
-\par By using the Software you agree to the following terms of this End User License Agreement (EULA).
-\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid3086748
-\par License}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3086748
-\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid3086748
-\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\hyphpar0\faauto\rin0\lin0\itap0\pararsid12742888 {\field\flddirty{\*\fldinst {\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 HYPERLINK "https://www.codestack.net/LICENSE.md" }{\rtlch\fcs1
-\af39 \ltrch\fcs0 \insrsid12742888\charrsid12742888 {\*\datafield
-00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b62000000680074007400700073003a002f002f007700770077002e0063006f006400650073007400610063006b002e006e00650074002f004c004900430045004e00530045002e006d0064000000795881f43b1d7f48
-af2c825dc485276300000000a5ab0000}}}{\fldrslt {\rtlch\fcs1 \af39 \ltrch\fcs0 \cs22\ul\cf17\insrsid3086748\charrsid12742888 MIT License}}}\sectd \ltrsect\sbknone\linex0\sectunlocked1\sectdefaultcl\sftnbj {\rtlch\fcs1 \af39 \ltrch\fcs0
-\insrsid3086748\charrsid12742888
-\par
-\par Copyright (c) 2018 }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 HYPERLINK "https://www.codestack.net/" }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888\charrsid12742888 {\*\datafield
-00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b4e000000680074007400700073003a002f002f007700770077002e0063006f006400650073007400610063006b002e006e00650074002f000000795881f43b1d7f48af2c825dc485276300000000a5ab0000}}
-}{\fldrslt {\rtlch\fcs1 \af39 \ltrch\fcs0 \cs22\ul\cf17\insrsid3086748\charrsid12742888 www.codestack.net}}}\sectd \ltrsect\sbknone\linex0\sectunlocked1\sectdefaultcl\sftnbj {\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888
-\par
-\par Permission is hereby granted, free of charge, to any person obtaining a copy}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888
-of this software and associated documentation files (the "Software"), to deal}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 in th
-e Software without restriction, including without limitation the rights}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888
-copies of the Software, and to permit persons to whom the Software is}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 furnished to do so, subject to the following conditions:
-\par
-\par The above copyright notice and this permission notice shall be included in all}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 copies or substantial portions of the Software.
-\par
-\par THE SOFTWARE IS PROVIDED "AS IS", WITHOU}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 T WARRANTY OF ANY KIND, EXPRESS }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 OR}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1
-\af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 IMPLIED, INCLUDING BUT N}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 OT LIMITED TO THE WARRANTIES OF }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 MERCHANTABILITY,}{\rtlch\fcs1
-\af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39
-\ltrch\fcs0 \insrsid3086748\charrsid12742888 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888 }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 SOFTWARE.}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748
+{\rtf1\ansi\deff3\adeflang1025
+{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\froman\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f5\froman\fprq2\fcharset0 Calibri;}{\f6\froman\fprq2\fcharset0 Liberation Mono{\*\falt Courier New};}{\f7\fnil\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f8\fnil\fprq2\fcharset0 Times New Roman;}{\f9\fswiss\fprq0\fcharset128 Arial;}{\f10\fnil\fprq2\fcharset0 Calibri;}}
+{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
+{\stylesheet{\s0\snext0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081 Normal;}
+{\*\cs15\snext15 Default Paragraph Font;}
+{\*\cs16\sbasedon15\snext16\cf2\ul\ulc0\dbch\af8 Internet Link;}
+{\*\cs17\snext17\kerning1\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3081 ListLabel 1;}
+{\s18\sbasedon0\snext19\ql\nowidctlpar\hyphpar0\faauto\sb240\sa120\keepn\ltrpar\kerning1\dbch\af8\langfe3081\dbch\af7\afs28\alang1025\loch\f4\fs28\lang3081 Heading;}
+{\s19\sbasedon0\snext19\sl288\slmult1\ql\nowidctlpar\hyphpar0\faauto\sb0\sa140\ltrpar\kerning1\dbch\af8\langfe3081\dbch\af7\afs24\alang1025\loch\f3\fs24\lang3081 Text Body;}
+{\s20\sbasedon19\snext20\sl288\slmult1\ql\nowidctlpar\hyphpar0\faauto\sb0\sa140\ltrpar\kerning1\dbch\af8\langfe3081\dbch\af8\afs24\alang1025\loch\f3\fs24\lang3081 List;}
+{\s21\sbasedon0\snext21\ql\widctlpar\hyphpar0\faauto\sb120\sa120\noline\ltrpar\i\kerning1\dbch\af7\langfe2052\dbch\af9\afs24\alang1081\ai\loch\f3\fs24\lang3081 Caption;}
+{\s22\sbasedon0\snext22\ql\nowidctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe3081\dbch\af8\afs24\alang1025\loch\f3\fs24\lang3081 Index;}
+{\s23\snext23\sl276\slmult1\ql\widctlpar\faauto\sb0\sa200\ltrpar\hyphpar0\dbch\af8\langfe3081\dbch\af10\afs22\alang1025\cf0\kerning1\loch\f5\fs22\lang3081 DocumentMap;}
+{\s24\sbasedon0\snext24\ql\nowidctlpar\hyphpar0\faauto\sb120\sa120\ltrpar\i\kerning1\dbch\af7\langfe3081\dbch\af8\afs24\alang1025\ai\loch\f3\fs24\lang3081 caption;}
+{\s25\sbasedon0\snext25\ql\nowidctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af8\langfe3081\dbch\af7\afs20\alang1025\loch\f6\fs20\lang3081 Preformatted Text;}
+}{\*\generator LibreOffice/6.0.6.2$Windows_X86_64 LibreOffice_project/0c292870b25a325b5ed35f6b45599d2ea4458e77}{\info{\creatim\yr2018\mo7\dy15\hr16\min48}{\revtim\yr2019\mo6\dy11\hr21\min47}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops{\propname Operator}\proptype30{\staticval Artem Taturevich}}\deftab709\deftab709
+\hyphauto0\viewscale100
+{\*\pgdsctbl
+{\pgdsc0\pgdscuse451\pgwsxn11906\pghsxn16838\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0 Default Style;}}
+\formshade{\*\pgdscno0}\paperh16838\paperw11906\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\sectunlocked1\pgndec\pgwsxn11906\pghsxn16838\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
+{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar{\b\kerning1\langfe2052\dbch\af7\afs24\alang1081\ab\rtlch \ltrch\loch\fs24\lang3081
+Terms & Conditions}
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
-\par }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888\charrsid12742888
-\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\hyphpar0\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid3086748 Recovered Information}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3086748
-\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid3086748
-\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\hyphpar0\faauto\rin0\lin0\itap0\pararsid12742888 {\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 You fully acknowledge and give permissions to }{\field\flddirty{\*\fldinst {\rtlch\fcs1
-\af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 HYPERLINK "http://www.codestack.net/" }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888\charrsid12742888 {\*\datafield
-00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b4c00000068007400740070003a002f002f007700770077002e0063006f006400650073007400610063006b002e006e00650074002f000000795881f43b1d7f48af2c825dc485276300000000a5ab0000}}}{\fldrslt
-{\rtlch\fcs1 \af39 \ltrch\fcs0 \cs22\ul\cf17\insrsid3086748\charrsid12742888 www.codestack.net}}}\sectd \ltrsect\sbknone\linex0\sectunlocked1\sectdefaultcl\sftnbj {\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888
- to gather and collect information with respect to download and use of the Software. Such informatio{\*\bkmkstart __DdeLink__1_2299311773}n{\*\bkmkend __DdeLink__1_2299311773} may include IP, location, date and time of download or use. Please visit }
-{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 HYPERLINK "https://www.codestack.net/terms-of-use" }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888\charrsid12742888 {\*\datafield
-00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b66000000680074007400700073003a002f002f007700770077002e0063006f006400650073007400610063006b002e006e00650074002f007400650072006d0073002d006f0066002d007500730065000000795881f4
-3b1d7f48af2c825dc485276300000000a5ab0000}}}{\fldrslt {\rtlch\fcs1 \af39 \ltrch\fcs0 \cs22\ul\cf17\insrsid3086748\charrsid12742888 Terms Of Use}}}\sectd \ltrsect\sbknone\linex0\sectunlocked1\sectdefaultcl\sftnbj {\rtlch\fcs1 \af39 \ltrch\fcs0
-\insrsid3086748\charrsid12742888 , }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 HYPERLINK "https://www.codestack.net/privacy-policy" }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888\charrsid12742888
-{\*\datafield
-00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6a000000680074007400700073003a002f002f007700770077002e0063006f006400650073007400610063006b002e006e00650074002f0070007200690076006100630079002d0070006f006c006900630079000000
-795881f43b1d7f48af2c825dc485276300000000a5ab0000}}}{\fldrslt {\rtlch\fcs1 \af39 \ltrch\fcs0 \cs22\ul\cf17\insrsid3086748\charrsid12742888 Privacy}}}\sectd \ltrsect\sbknone\linex0\sectunlocked1\sectdefaultcl\sftnbj {\rtlch\fcs1 \af39 \ltrch\fcs0
-\insrsid3086748\charrsid12742888 and }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888 HYPERLINK "https://www.codestack.net/cookies-policy" }{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid12742888\charrsid12742888
-{\*\datafield
-00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6a000000680074007400700073003a002f002f007700770077002e0063006f006400650073007400610063006b002e006e00650074002f0063006f006f006b006900650073002d0070006f006c006900630079000000
-795881f43b1d7f48af2c825dc485276300000000a5ab0000}}}{\fldrslt {\rtlch\fcs1 \af39 \ltrch\fcs0 \cs22\ul\cf17\insrsid3086748\charrsid12742888 Cookies}}}\sectd \ltrsect\sbknone\linex0\sectunlocked1\sectdefaultcl\sftnbj {\rtlch\fcs1 \af39 \ltrch\fcs0
-\insrsid3086748\charrsid12742888 pages for more information.}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid3086748\charrsid12742888
-\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
-9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
-5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
-b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
-0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
-a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
-c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
-0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
-a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
-6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
-4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
-4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210030dd4329a8060000a41b0000160000007468656d652f7468656d652f
-7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87
-615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad
-79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b
-5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab
-999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9
-699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586
-8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6
-0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f
-9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be
-15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979
-3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d
-32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a
-f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86
-e877f0034e16bafb0e258ebb4faf06b769e888340b103d331115bebc4eb813bf83291b63624a0d1475a756c734f9bbc2cd28546ecbe1e20a3794ca175f3fae90
-fb6d2dd99bb07b55e5ccf68942bd0877b23c77b908e8db5f9db7f024d9239010f35bd4bbe2fcae387bfff9e2bc289f2fbe24cfaa301468dd8bd846dbb4ddf1c2
-ae7b4c191ba8292337a469bc25ec3d411f06f53a73e224c5292c8de0516732307070a1c0660d125c7d44553488700a4d7bddd3444299910e254ab984c3a219ae
-a4adf1d0f82b7bd46cea4388ad1c12ab5d1ed8e1153d9c9f350a3246aad01c6873462b9ac05999ad5cc988826eafc3acae853a33b7ba11cd1445875ba1b236b1
-399483c90bd560b0b0263435085a21b0f22a9cf9356b38ec6046026d77eba3dc2dc60b17e92219e180643ed27acffba86e9c94c7ca9c225a0f1b0cfae0788ad5
-4adc5a9aec1b703b8b93caec1a0bd8e5de7b132fe5113cf312503b998e2c2927274bd051db6b35979b1ef271daf6c6704e86c73805af4bdd476216c26593af84
-0dfb5393d964f9cc9bad5c313709ea70f561ed3ea7b053075221d51696910d0d339585004b34272bff7213cc7a510a5454a3b349b1b206c1f0af490176745d4b
-c663e2abb2b34b23da76f6352ba57ca2881844c1111ab189d8c7e07e1daaa04f40255c77988aa05fe06e4e5bdb4cb9c5394bbaf28d98c1d971ccd20867e556a7
-689ec9166e0a522183792b8907ba55ca6e943bbf2a26e52f48957218ffcf54d1fb09dc3eac04da033e5c0d0b8c74a6b43d2e54c4a10aa511f5fb021a07533b20
-5ae07e17a621a8e082dafc17e450ffb739676998b48643a4daa7211214f623150942f6a02c99e83b85583ddbbb2c4996113211551257a656ec1139246ca86be0
-aadedb3d1441a89b6a929501833b197fee7b9641a3503739e57c732a59b1f7da1cf8a73b1f9bcca0945b874d4393dbbf10b1680f66bbaa5d6f96e77b6f59113d
-316bb31a795600b3d256d0cad2fe354538e7566b2bd69cc6cbcd5c38f0e2bcc63058344429dc2121fd07f63f2a7c66bf76e80d75c8f7a1b622f878a18941d840
-545fb28d07d205d20e8ea071b283369834296bdaac75d256cb37eb0bee740bbe278cad253b8bbfcf69eca23973d939b97891c6ce2cecd8da8e2d343578f6648a
-c2d0383fc818c798cf64e52f597c740f1cbd05df0c264c49134cf09d4a60e8a107260f20f92d47b374e32f000000ffff0300504b030414000600080000002100
-0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7
-8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89
-d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500
-1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f
-bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6
-a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a
-0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021
-0030dd4329a8060000a41b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008
-00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000}
-{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
-617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
-6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
-656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
-{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
-\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;
-\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7;
-\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdlocked0 caption;\lsdunhideused0 \lsdlocked0 List;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;
-\lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;
-\lsdunhideused0 \lsdlocked0 Revision;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;
-\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 0105000002000000180000004d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000
-d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e50000000000000000000000000087
-dada211cd401feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000105000000000000}}
\ No newline at end of file
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar{\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+By using the Software you agree to the following terms of this End User License Agreement (EULA).}
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar\b\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar{\b\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+License}
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar\b\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar{{\field{\*\fldinst HYPERLINK "https://www.codestack.net/LICENSE.md" }{\fldrslt {\cs16\cf2\ul\ulc0\dbch\af8\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+MIT License}}}}
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar{\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+Copyright (c) 201}{\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+9}{\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+ }{{\field{\*\fldinst HYPERLINK "https://www.codestack.net/" }{\fldrslt {\cs16\cf2\ul\ulc0\dbch\af8\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+www.codestack.net}}}}
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar{\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:}
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar{\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.}
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar{\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.}
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar{\b\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+Recovered Information}
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar\b\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+
+\par \pard\plain \s0\ql\widctlpar\hyphpar0\faauto\ltrpar\kerning1\dbch\af7\langfe2052\dbch\af7\afs24\alang1081\cf0\loch\f3\fs24\lang3081\li0\ri0\lin0\rin0\fi0\ltrpar{\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+You fully acknowledge and give permissions to }{{\field{\*\fldinst HYPERLINK "http://www.codestack.net/" }{\fldrslt {\cs16\cf2\ul\ulc0\dbch\af8\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+www.codestack.net}{}}}\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+ to gather and collect information with respect to download and use of the Software. Such informatio}{{\*\bkmkstart __DdeLink__1_2299311773}\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+n}{{\*\bkmkend __DdeLink__1_2299311773}\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+ may include IP, location, date and time of download or use. Please visit }{{\field{\*\fldinst HYPERLINK "https://www.codestack.net/terms-of-use" }{\fldrslt {\cs16\cf2\ul\ulc0\dbch\af8\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+Terms Of Use}{}}}\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+, }{{\field{\*\fldinst HYPERLINK "https://www.codestack.net/privacy-policy" }{\fldrslt {\cs16\cf2\ul\ulc0\dbch\af8\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+Privacy}{}}}\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+ and }{{\field{\*\fldinst HYPERLINK "https://www.codestack.net/cookies-policy" }{\fldrslt {\cs16\cf2\ul\ulc0\dbch\af8\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+Cookies}{}}}\kerning1\langfe2052\dbch\af7\afs24\alang1081\rtlch \ltrch\loch\fs24\lang3081
+ pages for more information.}
+\par }
\ No newline at end of file
diff --git a/Installer/Resources/icon.ico b/Installer/Resources/icon.ico
index cf905b6..2fbac29 100644
Binary files a/Installer/Resources/icon.ico and b/Installer/Resources/icon.ico differ
diff --git a/Installer/register.cmd b/Installer/register.cmd
deleted file mode 100644
index 7f68e4a..0000000
--- a/Installer/register.cmd
+++ /dev/null
@@ -1 +0,0 @@
-"%Windir%\Microsoft.NET\Framework64\v4.0.30319\regasm" /codebase "%~dp0CodeStack.Sw.MyToolbar.dll"
\ No newline at end of file
diff --git a/Installer/unregister.cmd b/Installer/unregister.cmd
deleted file mode 100644
index c52ff47..0000000
--- a/Installer/unregister.cmd
+++ /dev/null
@@ -1 +0,0 @@
-"%Windir%\Microsoft.NET\Framework64\v4.0.30319\regasm" /codebase "%~dp0CodeStack.Sw.MyToolbar.dll" /u
\ No newline at end of file
diff --git a/MyToolbar.Tests/MyToolbar.Tests.csproj b/MyToolbar.Tests/MyToolbar.Tests.csproj
new file mode 100644
index 0000000..e2f2409
--- /dev/null
+++ b/MyToolbar.Tests/MyToolbar.Tests.csproj
@@ -0,0 +1,142 @@
+
+
+
+ true
+ true
+
+
+ Debug
+ AnyCPU
+ {1CBA952C-5E75-41E0-829C-146647F33567}
+ Library
+ Properties
+ MyToolbar.Tests
+ MyToolbar.Tests
+ v4.6.1
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 10.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
+ False
+ UnitTest
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll
+ True
+
+
+ ..\packages\CodeStack.SwEx.AddIn.0.7.0\lib\net40\CodeStack.SwEx.AddIn.dll
+ True
+
+
+ ..\packages\CodeStack.SwEx.Common.0.9.6\lib\net40\CodeStack.SwEx.Common.dll
+ True
+
+
+ ..\packages\Moq.4.11.0\lib\net45\Moq.dll
+ True
+
+
+
+
+ ..\packages\CodeStack.SwEx.Common.0.9.6\lib\net40\SolidWorks.Interop.sldworks.dll
+ False
+
+
+ ..\packages\CodeStack.SwEx.Common.0.9.6\lib\net40\SolidWorks.Interop.swconst.dll
+ False
+
+
+ ..\packages\CodeStack.SwEx.Common.0.9.6\lib\net40\SolidWorks.Interop.swpublished.dll
+ False
+
+
+ ..\packages\CodeStack.SwEx.Common.0.9.6\lib\net40\SolidWorksTools.dll
+ True
+
+
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll
+ True
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {7acedaa9-2de8-4485-837a-e7d58812a6dc}
+ MyToolbar
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyToolbar.Tests/Properties/AssemblyInfo.cs b/MyToolbar.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..63cd6c9
--- /dev/null
+++ b/MyToolbar.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,22 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("MyToolbar.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MyToolbar.Tests")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("1cba952c-5e75-41e0-829c-146647f33567")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
\ No newline at end of file
diff --git a/MyToolbar.Tests/UITests.cs b/MyToolbar.Tests/UITests.cs
new file mode 100644
index 0000000..8e7b551
--- /dev/null
+++ b/MyToolbar.Tests/UITests.cs
@@ -0,0 +1,89 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar;
+using CodeStack.Sw.MyToolbar.Services;
+using CodeStack.Sw.MyToolbar.Structs;
+using CodeStack.Sw.MyToolbar.UI.Forms;
+using CodeStack.Sw.MyToolbar.UI.ViewModels;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+
+namespace MyToolbar.Tests
+{
+ [TestClass]
+ public class UITests
+ {
+ private ServicesContainer m_Services;
+
+ [TestInitialize]
+ public void Setup()
+ {
+ var appMock = new Mock();
+ var frameMock = new Mock();
+ frameMock.Setup(m => m.GetHWnd()).Returns(0);
+
+ appMock.Setup(a => a.IFrameObject()).Returns(frameMock.Object);
+
+ m_Services = new ServicesContainer(
+ appMock.Object,
+ new Mock().Object);
+ }
+
+ [TestMethod]
+ public void DisplayCommandManagerView()
+ {
+ var toolbar = new CustomToolbarInfo();
+
+ toolbar.Groups = new CommandGroupInfo[]
+ {
+ new CommandGroupInfo()
+ {
+ Title = "Toolbar1",
+ Commands = new CommandMacroInfo[]
+ {
+ new CommandMacroInfo() { Title = "Command1", Description="Sample command in toolbar which will invoke some macro" },
+ new CommandMacroInfo() { Title = "Command2" },
+ new CommandMacroInfo() { Title = "Command3" }
+ }
+ },
+ new CommandGroupInfo()
+ {
+ Title = "Toolbar2",
+ Commands = new CommandMacroInfo[]
+ {
+ new CommandMacroInfo() { Title = "Command4" },
+ new CommandMacroInfo() { Title = "Command5" },
+ new CommandMacroInfo() { Title = "Command6" },
+ new CommandMacroInfo() { Title = "Command7" },
+ new CommandMacroInfo() { Title = "Command8" },
+ new CommandMacroInfo() { Title = "Command9" },
+ new CommandMacroInfo() { Title = "Command10" },
+ new CommandMacroInfo() { Title = "Command11" },
+ new CommandMacroInfo() { Title = "Command12" },
+ new CommandMacroInfo() { Title = "Command13" }
+ }
+ }
+ };
+
+ var confProviderMock = new Mock();
+ var settsProviderMock = new Mock();
+
+ confProviderMock.Setup(m => m.GetToolbar(out It.Ref.IsAny, It.IsAny())).
+ Returns(toolbar);
+
+ settsProviderMock.Setup(p => p.GetSettings())
+ .Returns(new ToolbarSettings());
+
+ var vm = new CommandManagerVM(confProviderMock.Object, settsProviderMock.Object,
+ new Mock().Object);
+
+ new CommandManagerForm(vm, IntPtr.Zero).ShowDialog();
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar.Tests/app.config b/MyToolbar.Tests/app.config
new file mode 100644
index 0000000..0fe8f22
--- /dev/null
+++ b/MyToolbar.Tests/app.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyToolbar.Tests/packages.config b/MyToolbar.Tests/packages.config
new file mode 100644
index 0000000..71d4b92
--- /dev/null
+++ b/MyToolbar.Tests/packages.config
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyToolbar/AppInfo.cs b/MyToolbar/AppInfo.cs
new file mode 100644
index 0000000..1e99db7
--- /dev/null
+++ b/MyToolbar/AppInfo.cs
@@ -0,0 +1,40 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Properties;
+using CodeStack.Sw.MyToolbar.Structs;
+using System.Drawing;
+
+namespace CodeStack.Sw.MyToolbar
+{
+ internal static class AppInfo
+ {
+ internal static string WorkingDir
+ {
+ get
+ {
+ return Locations.AppDirectoryPath;
+ }
+ }
+
+ internal static string Title
+ {
+ get
+ {
+ return Resources.AppTitle;
+ }
+ }
+
+ internal static Icon Icon
+ {
+ get
+ {
+ return Resources.custom_toolbars_icon;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Base/CommandGroupInfoSpec.cs b/MyToolbar/Base/CommandGroupInfoSpec.cs
new file mode 100644
index 0000000..92060aa
--- /dev/null
+++ b/MyToolbar/Base/CommandGroupInfoSpec.cs
@@ -0,0 +1,47 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Structs;
+using CodeStack.SwEx.AddIn.Core;
+using System;
+using System.Linq;
+
+namespace CodeStack.Sw.MyToolbar.Base
+{
+ internal class CommandGroupInfoSpec : CommandGroupSpec
+ {
+ public event Action MacroCommandClick;
+
+ internal CommandGroupInfoSpec(CommandGroupInfo info)
+ {
+ Id = info.Id;
+ Title = info.Title;
+ Tooltip = info.Description;
+ Icon = info.GetCommandIcon();
+
+ if (info.Commands != null)
+ {
+ Commands = info.Commands.Select(
+ c =>
+ {
+ var spec = new CommandItemInfoSpec(c);
+ spec.MacroCommandClick += OnMacroCommandClick;
+ return spec;
+ }).ToArray();
+ }
+ else
+ {
+ Commands = new CommandItemInfoSpec[0];
+ }
+ }
+
+ private void OnMacroCommandClick(CommandMacroInfo cmd)
+ {
+ MacroCommandClick?.Invoke(cmd);
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Base/CommandItemInfoExtension.cs b/MyToolbar/Base/CommandItemInfoExtension.cs
new file mode 100644
index 0000000..41ed82a
--- /dev/null
+++ b/MyToolbar/Base/CommandItemInfoExtension.cs
@@ -0,0 +1,41 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Properties;
+using CodeStack.Sw.MyToolbar.Structs;
+using CodeStack.SwEx.AddIn.Icons;
+using System.Drawing;
+using System.IO;
+
+namespace CodeStack.Sw.MyToolbar.Base
+{
+ internal static class CommandItemInfoExtension
+ {
+ internal static CommandGroupIcon GetCommandIcon(this CommandItemInfo info)
+ {
+ Image icon = null;
+
+ try
+ {
+ if (File.Exists(info.IconPath))
+ {
+ icon = Image.FromFile(info.IconPath);
+ }
+ }
+ catch
+ {
+ }
+
+ if (icon == null)
+ {
+ icon = Resources.macro_icon_default;
+ }
+
+ return new MacroButtonIcon(icon);
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Base/CommandItemInfoSpec.cs b/MyToolbar/Base/CommandItemInfoSpec.cs
new file mode 100644
index 0000000..c735e71
--- /dev/null
+++ b/MyToolbar/Base/CommandItemInfoSpec.cs
@@ -0,0 +1,36 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Structs;
+using CodeStack.SwEx.AddIn.Core;
+using System;
+
+namespace CodeStack.Sw.MyToolbar.Base
+{
+ internal class CommandItemInfoSpec : CommandSpec
+ {
+ public event Action MacroCommandClick;
+
+ private readonly CommandMacroInfo m_Info;
+
+ internal CommandItemInfoSpec(CommandMacroInfo info)
+ {
+ m_Info = info;
+ UserId = info.Id;
+ Title = info.Title;
+ Tooltip = info.Description;
+ Icon = info.GetCommandIcon();
+ HasMenu = true;
+ HasToolbar = true;
+ }
+
+ public override void OnClick()
+ {
+ MacroCommandClick?.Invoke(m_Info);
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Base/MacroButtonIcon.cs b/MyToolbar/Base/MacroButtonIcon.cs
new file mode 100644
index 0000000..79c57b0
--- /dev/null
+++ b/MyToolbar/Base/MacroButtonIcon.cs
@@ -0,0 +1,38 @@
+using CodeStack.SwEx.AddIn.Icons;
+using CodeStack.SwEx.Common.Icons;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CodeStack.Sw.MyToolbar.Base
+{
+ public class MacroButtonIcon : CommandGroupIcon
+ {
+ private readonly Image m_Icon;
+
+ //TODO: once MasterIcon constructor in SwEx.AddIn is made to protected internal call it from here and remove all overloads
+ internal MacroButtonIcon(Image icon)
+ {
+ m_Icon = icon;
+ }
+
+ public override IEnumerable GetHighResolutionIconSizes()
+ {
+ yield return new IconSizeInfo(m_Icon, new Size(20, 20));
+ yield return new IconSizeInfo(m_Icon, new Size(32, 32));
+ yield return new IconSizeInfo(m_Icon, new Size(40, 40));
+ yield return new IconSizeInfo(m_Icon, new Size(64, 64));
+ yield return new IconSizeInfo(m_Icon, new Size(96, 96));
+ yield return new IconSizeInfo(m_Icon, new Size(128, 128));
+ }
+
+ public override IEnumerable GetIconSizes()
+ {
+ yield return new IconSizeInfo(m_Icon, new Size(16, 16));
+ yield return new IconSizeInfo(m_Icon, new Size(24, 24));
+ }
+ }
+}
diff --git a/MyToolbar/Commands.cs b/MyToolbar/Commands.cs
new file mode 100644
index 0000000..b4a9739
--- /dev/null
+++ b/MyToolbar/Commands.cs
@@ -0,0 +1,30 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Properties;
+using CodeStack.SwEx.Common.Attributes;
+using System.ComponentModel;
+
+namespace CodeStack.Sw.MyToolbar
+{
+ [SwEx.AddIn.Attributes.CommandGroupInfo(999)]
+ [Title("MyToolbar")]
+ [Description("Custom toolbar")]
+ [Icon(typeof(Resources), nameof(Resources.toolbar_icon))]
+ public enum Commands_e
+ {
+ [Icon(typeof(Resources), nameof(Resources.configure_icon))]
+ [Title("Configure...")]
+ [Description("Configure toolbar")]
+ Configuration,
+
+ [Icon(typeof(Resources), nameof(Resources.about_icon))]
+ [Title("About...")]
+ [Description("About MyToolbar")]
+ About
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Exceptions/MacroRunFailedException.cs b/MyToolbar/Exceptions/MacroRunFailedException.cs
new file mode 100644
index 0000000..5bbfe2a
--- /dev/null
+++ b/MyToolbar/Exceptions/MacroRunFailedException.cs
@@ -0,0 +1,33 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using SolidWorks.Interop.swconst;
+
+namespace CodeStack.Sw.MyToolbar.Exceptions
+{
+ public class MacroRunFailedException : UserException
+ {
+ private static string GetError(swRunMacroError_e err)
+ {
+ const string MACRO_PREFIX = "swRunMacroError_";
+
+ string errorDesc = err.ToString();
+
+ if (errorDesc.StartsWith(MACRO_PREFIX))
+ {
+ errorDesc = errorDesc.Substring(MACRO_PREFIX.Length);
+ }
+
+ return $"Failed to run macro: {errorDesc}";
+ }
+
+ public MacroRunFailedException(swRunMacroError_e err)
+ : base(GetError(err))
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Exceptions/UserException.cs b/MyToolbar/Exceptions/UserException.cs
new file mode 100644
index 0000000..b425866
--- /dev/null
+++ b/MyToolbar/Exceptions/UserException.cs
@@ -0,0 +1,18 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using System;
+
+namespace CodeStack.Sw.MyToolbar.Exceptions
+{
+ public class UserException : Exception
+ {
+ public UserException(string userMessage) : base(userMessage)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Helpers/DataContextProxy.cs b/MyToolbar/Helpers/DataContextProxy.cs
new file mode 100644
index 0000000..e4697ec
--- /dev/null
+++ b/MyToolbar/Helpers/DataContextProxy.cs
@@ -0,0 +1,31 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using System.Windows;
+
+namespace CodeStack.Sw.MyToolbar.Helpers
+{
+ public class DataContextProxy : Freezable
+ {
+ public static readonly DependencyProperty DataProperty = DependencyProperty.Register(
+ nameof(DataSource),
+ typeof(object),
+ typeof(DataContextProxy),
+ new UIPropertyMetadata(null));
+
+ public object DataSource
+ {
+ get { return (object)GetValue(DataProperty); }
+ set { SetValue(DataProperty, value); }
+ }
+
+ protected override Freezable CreateInstanceCore()
+ {
+ return new DataContextProxy();
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Helpers/ExceptionHelper.cs b/MyToolbar/Helpers/ExceptionHelper.cs
new file mode 100644
index 0000000..cc5a4d0
--- /dev/null
+++ b/MyToolbar/Helpers/ExceptionHelper.cs
@@ -0,0 +1,42 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Exceptions;
+using CodeStack.Sw.MyToolbar.Services;
+using CodeStack.SwEx.Common.Diagnostics;
+using System;
+
+namespace CodeStack.Sw.MyToolbar.Helpers
+{
+ internal static class ExceptionHelper
+ {
+ private static readonly IMessageService s_MsgService
+ = ServicesContainer.Instance.GetService();
+
+ private static readonly ILogger s_Logger
+ = ServicesContainer.Instance.GetService();
+
+ internal static void ExecuteUserCommand(Action cmd, Func unknownErrorDescriptionHandler)
+ {
+ try
+ {
+ cmd.Invoke();
+ }
+ catch (UserException ex)
+ {
+ s_Logger.Log(ex);
+ s_MsgService.ShowMessage(ex.Message, MessageType_e.Error);
+ }
+ catch (Exception ex)
+ {
+ var errDesc = unknownErrorDescriptionHandler.Invoke(ex);
+ s_Logger.Log(ex);
+ s_MsgService.ShowMessage(errDesc, MessageType_e.Error);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Helpers/FileBrowseHelper.cs b/MyToolbar/Helpers/FileBrowseHelper.cs
new file mode 100644
index 0000000..b86a8f5
--- /dev/null
+++ b/MyToolbar/Helpers/FileBrowseHelper.cs
@@ -0,0 +1,62 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace CodeStack.Sw.MyToolbar.Helpers
+{
+ public class FileFilterExtensions
+ {
+ public string[] Extensions { get; private set; }
+
+ public FileFilterExtensions(params string[] extensions)
+ {
+ Extensions = extensions;
+ }
+ }
+
+ public class FileFilter : Dictionary
+ {
+ }
+
+ public static class FileBrowseHelper
+ {
+ public static string BrowseFile(string caption,
+ FileFilter filters, string initialFile = "", bool includeAllFiles = true)
+ {
+ if (includeAllFiles)
+ {
+ filters.Add("All Files", new FileFilterExtensions("*"));
+ }
+
+ var filterStr = string.Join("|",
+ filters.Select(f =>
+ {
+ var exts = string.Join(";", f.Value.Extensions?.Select(e => $"*.{e}").ToArray());
+ return $"{f.Key} ({exts})|{exts}";
+ }).ToArray());
+
+ var dlg = new OpenFileDialog()
+ {
+ Filter = filterStr,
+ Title = caption,
+ FileName = initialFile
+ };
+
+ if (dlg.ShowDialog() == DialogResult.OK)
+ {
+ return dlg.FileName;
+ }
+ else
+ {
+ return "";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/MyToolbar.csproj b/MyToolbar/MyToolbar.csproj
new file mode 100644
index 0000000..6c9ef16
--- /dev/null
+++ b/MyToolbar/MyToolbar.csproj
@@ -0,0 +1,325 @@
+
+
+
+ Local
+ 8.0.50727
+ 2.0
+ {7ACEDAA9-2DE8-4485-837A-E7D58812A6DC}
+ Debug
+ AnyCPU
+
+
+
+
+ CodeStack.Sw.MyToolbar
+
+
+ JScript
+ Grid
+ IE50
+ false
+ Library
+ CodeStack.Sw.MyToolbar
+ OnBuildSuccess
+
+
+
+
+
+
+ Program
+ v4.6.1
+ 2.0
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+
+
+
+ bin\Debug\
+ false
+ 285212672
+ false
+
+
+ DEBUG;TRACE
+
+
+ true
+ 4096
+ false
+
+
+ false
+ true
+ false
+ false
+ 4
+ full
+ prompt
+ false
+
+
+ ..\Build\
+ false
+ 285212672
+ false
+
+
+ TRACE
+
+
+ false
+ 4096
+ false
+
+
+ true
+ true
+ false
+ false
+ 4
+ none
+ prompt
+ false
+
+
+
+ ..\packages\CodeStack.SwEx.AddIn.0.7.0\lib\net40\CodeStack.SwEx.AddIn.dll
+ True
+
+
+ ..\packages\CodeStack.SwEx.Common.0.9.6\lib\net40\CodeStack.SwEx.Common.dll
+ True
+
+
+ ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
+ True
+
+
+
+
+ ..\packages\CodeStack.SwEx.Common.0.9.6\lib\net40\SolidWorks.Interop.sldworks.dll
+ False
+
+
+ ..\packages\CodeStack.SwEx.Common.0.9.6\lib\net40\SolidWorks.Interop.swconst.dll
+ False
+
+
+ ..\packages\CodeStack.SwEx.Common.0.9.6\lib\net40\SolidWorks.Interop.swpublished.dll
+ False
+
+
+ ..\packages\CodeStack.SwEx.Common.0.9.6\lib\net40\SolidWorksTools.dll
+ True
+
+
+ System
+
+
+ System.Data
+
+
+ System.Drawing
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
+
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll
+
+
+
+
+ System.XML
+
+
+ ..\packages\Unity.5.10.3\lib\net46\Unity.Abstractions.dll
+ True
+
+
+ ..\packages\Unity.5.10.3\lib\net46\Unity.Container.dll
+ True
+
+
+
+ ..\packages\Xarial.Signal2Go.0.2.1\lib\net461\Xarial.Signal2Go.dll
+ True
+
+
+ ..\packages\Xarial.Signal2Go.Services.UserSettings.0.2.1\lib\net461\Xarial.Signal2Go.Services.UserSettings.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ True
+ Settings.settings
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CommandManagerForm.xaml
+
+
+
+
+
+
+
+ CommandBaseView.xaml
+
+
+ CommandMacroView.xaml
+
+
+ CommandManagerView.xaml
+
+
+
+
+ False
+ .NET Framework 3.5 SP1
+ true
+
+
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyToolbar/MyToolbarSwAddin.cs b/MyToolbar/MyToolbarSwAddin.cs
new file mode 100644
index 0000000..de847aa
--- /dev/null
+++ b/MyToolbar/MyToolbarSwAddin.cs
@@ -0,0 +1,195 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Base;
+using CodeStack.Sw.MyToolbar.Exceptions;
+using CodeStack.Sw.MyToolbar.Helpers;
+using CodeStack.Sw.MyToolbar.Services;
+using CodeStack.Sw.MyToolbar.Structs;
+using CodeStack.Sw.MyToolbar.UI.Forms;
+using CodeStack.Sw.MyToolbar.UI.ViewModels;
+using CodeStack.SwEx.AddIn;
+using CodeStack.SwEx.AddIn.Attributes;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Threading;
+using Xarial.AppLaunchKit.Base.Services;
+
+namespace CodeStack.Sw.MyToolbar
+{
+ [Guid("63496b16-e9ad-4d3a-8473-99d124a1672b"), ComVisible(true)]
+ [AutoRegister("MyToolbar", "Add-in for managing custom toolbars", true)]
+ public class MyToolbarSwAddin : SwAddInEx
+ {
+ private ServicesContainer m_Services;
+
+ public override bool OnConnect()
+ {
+ try
+ {
+ if (Dispatcher.CurrentDispatcher != null)
+ {
+ Dispatcher.CurrentDispatcher.UnhandledException += OnDispatcherUnhandledException;
+ }
+
+ AppDomain.CurrentDomain.UnhandledException += OnDomainUnhandledException;
+ m_Services = new ServicesContainer(App, Logger);
+
+ ExceptionHelper.ExecuteUserCommand(LoadUserToolbar, e => "Failed to load toolbar specification");
+
+ AddCommandGroup(OnButtonClick);
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Logger.Log(ex);
+ new MessageService().ShowMessage("Critical error while loading add-in", MessageType_e.Error);
+ throw;
+ }
+ }
+
+ private void OnDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
+ {
+ Logger.Log(e.ExceptionObject as Exception);
+ MessageService.ShowMessage("Unknown domain error", MessageType_e.Error);
+ }
+
+ private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
+ {
+ e.Handled = true;
+ Logger.Log(e.Exception);
+ MessageService.ShowMessage("Unknown dispatcher error", MessageType_e.Error);
+ }
+
+ private void LoadUserToolbar()
+ {
+ bool isReadOnly;
+ var toolbarInfo = ToolbarProvider.GetToolbar(out isReadOnly,
+ ToolbarSpecificationFile);
+
+ if (toolbarInfo?.Groups != null)
+ {
+ foreach (var grp in toolbarInfo.Groups)
+ {
+ var cmdGrp = new CommandGroupInfoSpec(grp);
+ cmdGrp.MacroCommandClick += OnMacroCommandClick;
+ AddCommandGroup(cmdGrp);
+ }
+ }
+ }
+
+ private void OnMacroCommandClick(CommandMacroInfo cmd)
+ {
+ RunMacroCommand(cmd);
+ }
+
+ private void RunMacroCommand(CommandMacroInfo cmd)
+ {
+ ExceptionHelper.ExecuteUserCommand(() => m_Services.GetService().RunMacro(cmd.MacroPath, cmd.EntryPoint),
+ e => "Failed to run macro");
+ }
+
+ private void OnButtonClick(Commands_e cmd)
+ {
+ switch (cmd)
+ {
+ case Commands_e.Configuration:
+
+ var vm = m_Services.GetService();
+
+ if (new CommandManagerForm(vm,
+ new IntPtr(App.IFrameObject().GetHWnd())).ShowDialog() == true)
+ {
+ ExceptionHelper.ExecuteUserCommand(() =>
+ {
+ UpdatedToolbarConfiguration(vm.Settings, vm.ToolbarInfo, vm.IsEditable);
+ }, e => "Failed to save toolbar specification");
+ }
+ break;
+
+ case Commands_e.About:
+ m_Services.GetService().ShowAboutForm();
+ break;
+ }
+ }
+
+ private void UpdatedToolbarConfiguration(ToolbarSettings toolbarSets, CustomToolbarInfo toolbarConf, bool isEditable)
+ {
+ bool isToolbarChanged;
+
+ SaveSettingChanges(toolbarSets, toolbarConf, isEditable, out isToolbarChanged);
+
+ if (isToolbarChanged)
+ {
+ MessageService.ShowMessage("Toolbar specification has changed. Please restart SOLIDWORKS",
+ MessageType_e.Info);
+ }
+ }
+
+ private void SaveSettingChanges(ToolbarSettings toolbarSets, CustomToolbarInfo toolbarConf,
+ bool isEditable, out bool isToolbarChanged)
+ {
+ isToolbarChanged = false;
+
+ var settsProvider = m_Services.GetService();
+ var oldToolbarSetts = settsProvider.GetSettings();
+
+ if (!DeepCompare(toolbarSets, oldToolbarSetts))
+ {
+ settsProvider.SaveSettings(toolbarSets);
+ }
+
+ var toolbarConfProvider = ToolbarProvider;
+
+ bool isReadOnly;
+
+ var oldToolbarConf = toolbarConfProvider
+ .GetToolbar(out isReadOnly, oldToolbarSetts.SpecificationFile);
+
+ isToolbarChanged = !DeepCompare(toolbarConf, oldToolbarConf);
+
+ if (isToolbarChanged)
+ {
+ if (isEditable)
+ {
+ toolbarConfProvider.SaveToolbar(toolbarConf, toolbarSets.SpecificationFile);
+ }
+ }
+ }
+
+ private bool DeepCompare(object obj1, object obj2)
+ {
+ return JToken.DeepEquals(JToken.FromObject(obj1), JToken.FromObject(obj2));
+ }
+
+ private IToolbarConfigurationProvider ToolbarProvider
+ {
+ get
+ {
+ return m_Services.GetService();
+ }
+ }
+
+ private string ToolbarSpecificationFile
+ {
+ get
+ {
+ return m_Services.GetService().GetSettings().SpecificationFile;
+ }
+ }
+
+ private IMessageService MessageService
+ {
+ get
+ {
+ return m_Services.GetService();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Properties/AssemblyInfo.cs b/MyToolbar/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4578d74
--- /dev/null
+++ b/MyToolbar/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar;
+using CodeStack.Sw.MyToolbar.Properties;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Xarial.AppLaunchKit.Attributes;
+using Xarial.AppLaunchKit.Services.Attributes;
+
+[assembly: AssemblyTitle("MyToolbar")]
+[assembly: AssemblyDescription("Add-in to manage custom toolbars in SOLIDWORKS")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("CodeStack")]
+[assembly: AssemblyProduct("MyToolbar")]
+[assembly: AssemblyCopyright("Copyright(C) 2019 www.codestack.net")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: ComVisible(false)]
+[assembly: ApplicationInfo(typeof(AppInfo),
+ nameof(AppInfo.WorkingDir), nameof(AppInfo.Title), nameof(AppInfo.Icon))]
+[assembly: UpdatesUrl(typeof(Settings), nameof(Settings.Default) + "." + nameof(Settings.Default.UpgradeUrl))]
+[assembly: About(typeof(Resources), nameof(Resources.eula), nameof(Resources.Licenses), nameof(Resources.custom_toolbars_toolbar))]
+[assembly: UserSettings("Settings", true, typeof(ToolbarInfoVersionConverter))]
\ No newline at end of file
diff --git a/Properties/Resources.Designer.cs b/MyToolbar/Properties/Resources.Designer.cs
similarity index 52%
rename from Properties/Resources.Designer.cs
rename to MyToolbar/Properties/Resources.Designer.cs
index e8b7263..6c626ca 100644
--- a/Properties/Resources.Designer.cs
+++ b/MyToolbar/Properties/Resources.Designer.cs
@@ -8,7 +8,7 @@
//
//------------------------------------------------------------------------------
-namespace CodeStack.Community.Sw.MyToolbar.Properties {
+namespace CodeStack.Sw.MyToolbar.Properties {
using System;
@@ -19,7 +19,7 @@ namespace CodeStack.Community.Sw.MyToolbar.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -39,7 +39,7 @@ internal Resources() {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeStack.Community.Sw.MyToolbar.Properties.Resources", typeof(Resources).Assembly);
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeStack.Sw.MyToolbar.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -60,6 +60,16 @@ internal Resources() {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap about_icon {
+ get {
+ object obj = ResourceManager.GetObject("about_icon", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized string similar to MyToolbar.
///
@@ -69,6 +79,16 @@ internal static string AppTitle {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap configure_icon {
+ get {
+ object obj = ResourceManager.GetObject("configure_icon", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
///
@@ -91,12 +111,91 @@ internal static System.Drawing.Bitmap custom_toolbars_toolbar {
///
/// Looks up a localized string similar to {\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff39\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang3081\deflangfe3081\themelang3081\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}
- ///{\f39\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Liberation Serif{\*\falt Times New Roman};}{\f40\fbidi \fswiss\fcharset204\fprq2{\*\pano [rest of string was truncated]";.
+ ///{\f39\fbidi \froman\fcharset204\fprq2{\*\panose 02020603050405020304}Liberation Serif{\*\falt Times New Roman};}{\f40\fbidi \fswiss\fcharset204\fprq2{\*\panos [rest of string was truncated]";.
///
internal static string eula {
get {
return ResourceManager.GetString("eula", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap icon_add_after {
+ get {
+ object obj = ResourceManager.GetObject("icon_add_after", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap icon_add_before {
+ get {
+ object obj = ResourceManager.GetObject("icon_add_before", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap icon_move_left {
+ get {
+ object obj = ResourceManager.GetObject("icon_move_left", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap icon_move_right {
+ get {
+ object obj = ResourceManager.GetObject("icon_move_right", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap icon_remove {
+ get {
+ object obj = ResourceManager.GetObject("icon_remove", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to .
+ ///
+ internal static string Licenses {
+ get {
+ return ResourceManager.GetString("Licenses", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap macro_icon_default {
+ get {
+ object obj = ResourceManager.GetObject("macro_icon_default", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap toolbar_icon {
+ get {
+ object obj = ResourceManager.GetObject("toolbar_icon", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
}
}
diff --git a/Properties/Resources.resx b/MyToolbar/Properties/Resources.resx
similarity index 72%
rename from Properties/Resources.resx
rename to MyToolbar/Properties/Resources.resx
index 35c89d0..fbc4374 100644
--- a/Properties/Resources.resx
+++ b/MyToolbar/Properties/Resources.resx
@@ -130,4 +130,34 @@
..\Resources\eula.rtf;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ ..\Resources\Licenses.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;windows-1251
+
+
+ ..\Resources\macro_icon_default.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\about-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\configure-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\toolbar-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\icon-add-after.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\icon-add-before.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\icon-move-left.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\icon-move-right.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\icon-remove.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
\ No newline at end of file
diff --git a/Properties/Settings.Designer.cs b/MyToolbar/Properties/Settings.Designer.cs
similarity index 75%
rename from Properties/Settings.Designer.cs
rename to MyToolbar/Properties/Settings.Designer.cs
index b6794a2..89f6c73 100644
--- a/Properties/Settings.Designer.cs
+++ b/MyToolbar/Properties/Settings.Designer.cs
@@ -8,11 +8,11 @@
//
//------------------------------------------------------------------------------
-namespace CodeStack.Community.Sw.MyToolbar.Properties {
+namespace CodeStack.Sw.MyToolbar.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -25,10 +25,10 @@ public static Settings Default {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("data.json")]
- public string DataFile {
+ [global::System.Configuration.DefaultSettingValueAttribute("toolbars.setts")]
+ public string ToolbarsSpecFile {
get {
- return ((string)(this["DataFile"]));
+ return ((string)(this["ToolbarsSpecFile"]));
}
}
@@ -41,18 +41,6 @@ public string AppRootDir {
}
}
- [global::System.Configuration.UserScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("IconsCache")]
- public string IconsCacheFolder {
- get {
- return ((string)(this["IconsCacheFolder"]));
- }
- set {
- this["IconsCacheFolder"] = value;
- }
- }
-
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("https://www.codestack.net/labs/solidworks/my-toolbar/version-info.json")]
@@ -67,13 +55,13 @@ public string UpgradeUrl {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("System")]
- public string SystemDir {
+ [global::System.Configuration.DefaultSettingValueAttribute("settings")]
+ public string SettingsStoreName {
get {
- return ((string)(this["SystemDir"]));
+ return ((string)(this["SettingsStoreName"]));
}
set {
- this["SystemDir"] = value;
+ this["SettingsStoreName"] = value;
}
}
}
diff --git a/Properties/Settings.settings b/MyToolbar/Properties/Settings.settings
similarity index 56%
rename from Properties/Settings.settings
rename to MyToolbar/Properties/Settings.settings
index c1855ae..2ecf3c5 100644
--- a/Properties/Settings.settings
+++ b/MyToolbar/Properties/Settings.settings
@@ -1,21 +1,18 @@
-
+
-
- data.json
+
+ toolbars.setts
CodeStack\MyToolbar
-
- IconsCache
-
https://www.codestack.net/labs/solidworks/my-toolbar/version-info.json
-
- System
+
+ settings
\ No newline at end of file
diff --git a/MyToolbar/Resources/Licenses.txt b/MyToolbar/Resources/Licenses.txt
new file mode 100644
index 0000000..e69de29
diff --git a/MyToolbar/Resources/about-icon.png b/MyToolbar/Resources/about-icon.png
new file mode 100644
index 0000000..4ccd697
Binary files /dev/null and b/MyToolbar/Resources/about-icon.png differ
diff --git a/Resources/codestack-toolbar.png b/MyToolbar/Resources/codestack-toolbar.png
similarity index 100%
rename from Resources/codestack-toolbar.png
rename to MyToolbar/Resources/codestack-toolbar.png
diff --git a/MyToolbar/Resources/configure-icon.png b/MyToolbar/Resources/configure-icon.png
new file mode 100644
index 0000000..70e195f
Binary files /dev/null and b/MyToolbar/Resources/configure-icon.png differ
diff --git a/MyToolbar/Resources/custom-toolbars-toolbar.png b/MyToolbar/Resources/custom-toolbars-toolbar.png
new file mode 100644
index 0000000..cdce089
Binary files /dev/null and b/MyToolbar/Resources/custom-toolbars-toolbar.png differ
diff --git a/MyToolbar/Resources/custom_toolbars_icon.ico b/MyToolbar/Resources/custom_toolbars_icon.ico
new file mode 100644
index 0000000..2fbac29
Binary files /dev/null and b/MyToolbar/Resources/custom_toolbars_icon.ico differ
diff --git a/Resources/eula.rtf b/MyToolbar/Resources/eula.rtf
similarity index 100%
rename from Resources/eula.rtf
rename to MyToolbar/Resources/eula.rtf
diff --git a/MyToolbar/Resources/icon-add-after.png b/MyToolbar/Resources/icon-add-after.png
new file mode 100644
index 0000000..b1829a0
Binary files /dev/null and b/MyToolbar/Resources/icon-add-after.png differ
diff --git a/MyToolbar/Resources/icon-add-before.png b/MyToolbar/Resources/icon-add-before.png
new file mode 100644
index 0000000..92e52a8
Binary files /dev/null and b/MyToolbar/Resources/icon-add-before.png differ
diff --git a/MyToolbar/Resources/icon-move-left.png b/MyToolbar/Resources/icon-move-left.png
new file mode 100644
index 0000000..0c6a5b1
Binary files /dev/null and b/MyToolbar/Resources/icon-move-left.png differ
diff --git a/MyToolbar/Resources/icon-move-right.png b/MyToolbar/Resources/icon-move-right.png
new file mode 100644
index 0000000..928d14c
Binary files /dev/null and b/MyToolbar/Resources/icon-move-right.png differ
diff --git a/MyToolbar/Resources/icon-remove.png b/MyToolbar/Resources/icon-remove.png
new file mode 100644
index 0000000..510fc23
Binary files /dev/null and b/MyToolbar/Resources/icon-remove.png differ
diff --git a/MyToolbar/Resources/macro_icon_default.png b/MyToolbar/Resources/macro_icon_default.png
new file mode 100644
index 0000000..69db0d9
Binary files /dev/null and b/MyToolbar/Resources/macro_icon_default.png differ
diff --git a/MyToolbar/Resources/toolbar-icon.png b/MyToolbar/Resources/toolbar-icon.png
new file mode 100644
index 0000000..21c9690
Binary files /dev/null and b/MyToolbar/Resources/toolbar-icon.png differ
diff --git a/MyToolbar/Services/MacroEntryPointsExtractor.cs b/MyToolbar/Services/MacroEntryPointsExtractor.cs
new file mode 100644
index 0000000..11f2c4b
--- /dev/null
+++ b/MyToolbar/Services/MacroEntryPointsExtractor.cs
@@ -0,0 +1,78 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Structs;
+using SolidWorks.Interop.sldworks;
+using SolidWorks.Interop.swconst;
+using System.Collections.Generic;
+using System.Linq;
+using System;
+
+namespace CodeStack.Sw.MyToolbar.Services
+{
+ public interface IMacroEntryPointsExtractor
+ {
+ MacroEntryPoint[] GetEntryPoints(string macroPath);
+ }
+
+ public class MacroEntryPointsExtractor : IMacroEntryPointsExtractor
+ {
+ private class EntryPointComparer : IComparer
+ {
+ private const string MAIN_NAME = "main";
+
+ public int Compare(MacroEntryPoint x, MacroEntryPoint y)
+ {
+ if (object.ReferenceEquals(x, y) || x == null || y == null)
+ {
+ return 0;
+ }
+
+ if (string.Equals(x.SubName, MAIN_NAME, StringComparison.CurrentCultureIgnoreCase))
+ {
+ return -1;
+ }
+ else if (string.Equals(y.SubName, MAIN_NAME, StringComparison.CurrentCultureIgnoreCase))
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+
+ private readonly ISldWorks m_App;
+
+ public MacroEntryPointsExtractor(ISldWorks app)
+ {
+ m_App = app;
+ }
+
+ public MacroEntryPoint[] GetEntryPoints(string macroPath)
+ {
+ var methods = m_App.GetMacroMethods(macroPath,
+ (int)swMacroMethods_e.swMethodsWithoutArguments) as string[];
+
+ if (methods != null)
+ {
+ return methods.Select(m =>
+ {
+ var ep = m.Split('.');
+ return new MacroEntryPoint()
+ {
+ ModuleName = ep[0],
+ SubName = ep[1]
+ };
+ }).OrderBy(e => e, new EntryPointComparer()).ToArray();
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Services/MacroRunner.cs b/MyToolbar/Services/MacroRunner.cs
new file mode 100644
index 0000000..50a94da
--- /dev/null
+++ b/MyToolbar/Services/MacroRunner.cs
@@ -0,0 +1,39 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Exceptions;
+using CodeStack.Sw.MyToolbar.Structs;
+using SolidWorks.Interop.sldworks;
+using SolidWorks.Interop.swconst;
+
+namespace CodeStack.Sw.MyToolbar.Services
+{
+ public interface IMacroRunner
+ {
+ void RunMacro(string macroPath, MacroEntryPoint entryPoint);
+ }
+
+ public class MacroRunner : IMacroRunner
+ {
+ private readonly ISldWorks m_App;
+
+ public MacroRunner(ISldWorks app)
+ {
+ m_App = app;
+ }
+
+ public void RunMacro(string macroPath, MacroEntryPoint entryPoint)
+ {
+ int err;
+
+ if (!m_App.RunMacro2(macroPath, entryPoint.ModuleName, entryPoint.SubName, 0, out err))
+ {
+ throw new MacroRunFailedException((swRunMacroError_e)err);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Services/MessageService.cs b/MyToolbar/Services/MessageService.cs
new file mode 100644
index 0000000..c7bdd86
--- /dev/null
+++ b/MyToolbar/Services/MessageService.cs
@@ -0,0 +1,49 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Properties;
+using System.Windows;
+
+namespace CodeStack.Sw.MyToolbar.Services
+{
+ public enum MessageType_e
+ {
+ Info,
+ Warning,
+ Error
+ }
+
+ public interface IMessageService
+ {
+ void ShowMessage(string message, MessageType_e type);
+ }
+
+ public class MessageService : IMessageService
+ {
+ public void ShowMessage(string message, MessageType_e type)
+ {
+ var icon = MessageBoxImage.Information;
+
+ switch (type)
+ {
+ case MessageType_e.Info:
+ icon = MessageBoxImage.Information;
+ break;
+
+ case MessageType_e.Warning:
+ icon = MessageBoxImage.Warning;
+ break;
+
+ case MessageType_e.Error:
+ icon = MessageBoxImage.Error;
+ break;
+ }
+
+ MessageBox.Show(message, Resources.AppTitle, MessageBoxButton.OK, icon);
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Services/SettingsProvider.cs b/MyToolbar/Services/SettingsProvider.cs
new file mode 100644
index 0000000..1dd9f6b
--- /dev/null
+++ b/MyToolbar/Services/SettingsProvider.cs
@@ -0,0 +1,65 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Properties;
+using CodeStack.Sw.MyToolbar.Structs;
+using System.IO;
+using Xarial.AppLaunchKit.Base.Services;
+
+namespace CodeStack.Sw.MyToolbar.Services
+{
+ public interface ISettingsProvider
+ {
+ ToolbarSettings GetSettings();
+
+ void SaveSettings(ToolbarSettings setts);
+ }
+
+ public class SettingsProvider : ISettingsProvider
+ {
+ private readonly IUserSettingsService m_UserSettsSrv;
+
+ public SettingsProvider(IUserSettingsService userSettsSrv)
+ {
+ m_UserSettsSrv = userSettsSrv;
+ }
+
+ public ToolbarSettings GetSettings()
+ {
+ ToolbarSettings setts;
+ try
+ {
+ setts = m_UserSettsSrv.ReadSettings(Settings.Default.SettingsStoreName);
+ }
+ catch
+ {
+ setts = new ToolbarSettings()
+ {
+ SpecificationFile = ToolbarsDefaultSpecFilePath
+ };
+ }
+
+ return setts;
+ }
+
+ public void SaveSettings(ToolbarSettings setts)
+ {
+ m_UserSettsSrv.StoreSettings(setts, Settings.Default.SettingsStoreName);
+ }
+
+ private string ToolbarsDefaultSpecFilePath
+ {
+ get
+ {
+ var dataFile = Path.Combine(Locations.AppDirectoryPath,
+ Settings.Default.ToolbarsSpecFile);
+
+ return dataFile;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Services/ToolbarConfigurationProvider.cs b/MyToolbar/Services/ToolbarConfigurationProvider.cs
new file mode 100644
index 0000000..87fab67
--- /dev/null
+++ b/MyToolbar/Services/ToolbarConfigurationProvider.cs
@@ -0,0 +1,69 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Structs;
+using System;
+using System.IO;
+using System.Security;
+using System.Security.Permissions;
+using Xarial.AppLaunchKit.Base.Services;
+
+namespace CodeStack.Sw.MyToolbar.Services
+{
+ public interface IToolbarConfigurationProvider
+ {
+ CustomToolbarInfo GetToolbar(out bool isReadOnly, string toolbarSpecFilePath);
+
+ void SaveToolbar(CustomToolbarInfo toolbar, string toolbarSpecFilePath);
+ }
+
+ public class ToolbarConfigurationProvider : IToolbarConfigurationProvider
+ {
+ private readonly IUserSettingsService m_UserSettsSrv;
+
+ public ToolbarConfigurationProvider(IUserSettingsService userSettsSrv)
+ {
+ m_UserSettsSrv = userSettsSrv;
+ }
+
+ public CustomToolbarInfo GetToolbar(out bool isReadOnly, string toolbarSpecFilePath)
+ {
+ if (File.Exists(toolbarSpecFilePath))
+ {
+ isReadOnly = !IsEditable(toolbarSpecFilePath);
+ return m_UserSettsSrv.ReadSettings(toolbarSpecFilePath);
+ }
+ else
+ {
+ isReadOnly = false;
+ return new CustomToolbarInfo();
+ }
+ }
+
+ private bool IsEditable(string filePath)
+ {
+ if (!new FileInfo(filePath).IsReadOnly)
+ {
+ var permissionSet = new PermissionSet(PermissionState.None);
+ var writePermission = new FileIOPermission(
+ FileIOPermissionAccess.Write, filePath);
+ permissionSet.AddPermission(writePermission);
+
+ return permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public void SaveToolbar(CustomToolbarInfo toolbar, string toolbarSpecFilePath)
+ {
+ m_UserSettsSrv.StoreSettings(toolbar, toolbarSpecFilePath);
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/ServicesContainer.cs b/MyToolbar/ServicesContainer.cs
new file mode 100644
index 0000000..4f39d57
--- /dev/null
+++ b/MyToolbar/ServicesContainer.cs
@@ -0,0 +1,96 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Services;
+using CodeStack.Sw.MyToolbar.UI.ViewModels;
+using CodeStack.SwEx.Common.Diagnostics;
+using SolidWorks.Interop.sldworks;
+using System;
+using Unity;
+using Unity.Lifetime;
+using Xarial.AppLaunchKit;
+using Xarial.AppLaunchKit.Base.Services;
+using Xarial.AppLaunchKit.Services.About;
+using Xarial.AppLaunchKit.Services.Updates;
+using Xarial.AppLaunchKit.Services.UserSettings;
+
+namespace CodeStack.Sw.MyToolbar
+{
+ public class ServicesContainer
+ {
+ public static ServicesContainer Instance
+ {
+ get;
+ private set;
+ }
+
+ private readonly UnityContainer m_Container;
+ private readonly ServicesManager m_Kit;
+ private readonly ILogger m_Logger;
+
+ public ServicesContainer(ISldWorks app, ILogger logger)
+ {
+ Instance = this;
+
+ m_Logger = logger;
+
+ m_Container = new UnityContainer();
+
+ m_Kit = RegisterServicesManager(app);
+
+ m_Container.RegisterInstance(app);
+
+ m_Container.RegisterType(
+ new ContainerControlledLifetimeManager());
+
+ m_Container.RegisterType(
+ new ContainerControlledLifetimeManager());
+
+ m_Container.RegisterType(
+ new ContainerControlledLifetimeManager());
+
+ m_Container.RegisterType(
+ new ContainerControlledLifetimeManager());
+
+ m_Container.RegisterType(
+ new ContainerControlledLifetimeManager());
+
+ m_Container.RegisterType(new TransientLifetimeManager());
+
+ m_Container.RegisterInstance(m_Logger);
+
+ m_Container.RegisterInstance(m_Kit.GetService());
+ m_Container.RegisterInstance(m_Kit.GetService());
+ }
+
+ internal TService GetService()
+ {
+ return m_Container.Resolve();
+ }
+
+ private ServicesManager RegisterServicesManager(ISldWorks app)
+ {
+ var srv = new ServicesManager(this.GetType().Assembly, new IntPtr(app.IFrameObject().GetHWnd()),
+ typeof(UpdatesService),
+ typeof(UserSettingsService),
+ typeof(AboutApplicationService));
+
+ srv.HandleError += OnHandleError;
+
+ srv.StartServicesInBackground();
+
+ return srv;
+ }
+
+ private bool OnHandleError(Exception ex)
+ {
+ m_Logger.Log(ex);
+
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Structs/CommandGroupInfo.cs b/MyToolbar/Structs/CommandGroupInfo.cs
new file mode 100644
index 0000000..bad4c3e
--- /dev/null
+++ b/MyToolbar/Structs/CommandGroupInfo.cs
@@ -0,0 +1,14 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+namespace CodeStack.Sw.MyToolbar.Structs
+{
+ public class CommandGroupInfo : CommandItemInfo
+ {
+ public CommandMacroInfo[] Commands { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Structs/CommandItemInfo.cs b/MyToolbar/Structs/CommandItemInfo.cs
new file mode 100644
index 0000000..c5a777c
--- /dev/null
+++ b/MyToolbar/Structs/CommandItemInfo.cs
@@ -0,0 +1,20 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+namespace CodeStack.Sw.MyToolbar.Structs
+{
+ public abstract class CommandItemInfo
+ {
+ public int Id { get; set; }
+
+ public string Title { get; set; }
+
+ public string Description { get; set; }
+
+ public string IconPath { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/Structs/CommandMacroInfo.cs b/MyToolbar/Structs/CommandMacroInfo.cs
new file mode 100644
index 0000000..312ffcb
--- /dev/null
+++ b/MyToolbar/Structs/CommandMacroInfo.cs
@@ -0,0 +1,15 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+namespace CodeStack.Sw.MyToolbar.Structs
+{
+ public class CommandMacroInfo : CommandItemInfo
+ {
+ public string MacroPath { get; set; }
+ public MacroEntryPoint EntryPoint { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Preferences/CustomToolbarInfo.cs b/MyToolbar/Structs/CustomToolbarInfo.cs
similarity index 51%
rename from Preferences/CustomToolbarInfo.cs
rename to MyToolbar/Structs/CustomToolbarInfo.cs
index b3167a0..094842d 100644
--- a/Preferences/CustomToolbarInfo.cs
+++ b/MyToolbar/Structs/CustomToolbarInfo.cs
@@ -1,21 +1,21 @@
//**********************
-//MyToolbar
-//Copyright(C) 2018 www.codestack.net
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
//**********************
-using System.Runtime.Serialization;
+using Xarial.AppLaunchKit.Services.UserSettings.Attributes;
-namespace CodeStack.Community.Sw.MyToolbar.Preferences
+namespace CodeStack.Sw.MyToolbar.Structs
{
- [DataContract]
- [KnownType(typeof(BasicIcons))]
- [KnownType(typeof(HighResIcons))]
- [KnownType(typeof(MasterIcons))]
+ [UserSettingVersion("1.0")]
public class CustomToolbarInfo
{
- [DataMember]
public CommandGroupInfo[] Groups { get; set; }
+
+ public CustomToolbarInfo()
+ {
+ }
}
-}
+}
\ No newline at end of file
diff --git a/Preferences/Locations.cs b/MyToolbar/Structs/Locations.cs
similarity index 59%
rename from Preferences/Locations.cs
rename to MyToolbar/Structs/Locations.cs
index 988f319..3112e56 100644
--- a/Preferences/Locations.cs
+++ b/MyToolbar/Structs/Locations.cs
@@ -1,15 +1,15 @@
//**********************
-//MyToolbar
-//Copyright(C) 2018 www.codestack.net
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
//**********************
-using CodeStack.Community.Sw.MyToolbar.Properties;
+using CodeStack.Sw.MyToolbar.Properties;
using System;
using System.IO;
-namespace CodeStack.Community.Sw.MyToolbar.Preferences
+namespace CodeStack.Sw.MyToolbar.Structs
{
internal static class Locations
{
@@ -24,16 +24,5 @@ internal static string AppDirectoryPath
return appDir;
}
}
-
- internal static string DataFilePath
- {
- get
- {
- var dataFile = Path.Combine(AppDirectoryPath,
- Settings.Default.DataFile);
-
- return dataFile;
- }
- }
}
-}
+}
\ No newline at end of file
diff --git a/MyToolbar/Structs/MacroEntryPoint.cs b/MyToolbar/Structs/MacroEntryPoint.cs
new file mode 100644
index 0000000..d8c72d0
--- /dev/null
+++ b/MyToolbar/Structs/MacroEntryPoint.cs
@@ -0,0 +1,64 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using System;
+
+namespace CodeStack.Sw.MyToolbar.Structs
+{
+ public class MacroEntryPoint
+ {
+ public string ModuleName { get; set; }
+ public string SubName { get; set; }
+
+ public static bool operator ==(MacroEntryPoint x, MacroEntryPoint y)
+ {
+ if (ReferenceEquals(x, y))
+ {
+ return true;
+ }
+
+ if (ReferenceEquals(x, null))
+ {
+ return false;
+ }
+ if (ReferenceEquals(y, null))
+ {
+ return false;
+ }
+
+ return string.Equals(x.ModuleName, y.ModuleName, StringComparison.CurrentCultureIgnoreCase)
+ && string.Equals(x.SubName, y.SubName, StringComparison.CurrentCultureIgnoreCase);
+ }
+
+ public static bool operator !=(MacroEntryPoint x, MacroEntryPoint y)
+ {
+ return !(x == y);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is MacroEntryPoint)
+ {
+ return this == obj as MacroEntryPoint;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return 0;
+ }
+
+ public override string ToString()
+ {
+ return $"{ModuleName}.{SubName}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Preferences/IIconList.cs b/MyToolbar/Structs/ToolbarSettings.cs
similarity index 50%
rename from Preferences/IIconList.cs
rename to MyToolbar/Structs/ToolbarSettings.cs
index 7f890da..06e3e5d 100644
--- a/Preferences/IIconList.cs
+++ b/MyToolbar/Structs/ToolbarSettings.cs
@@ -1,13 +1,14 @@
//**********************
-//MyToolbar
-//Copyright(C) 2018 www.codestack.net
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
//**********************
-namespace CodeStack.Community.Sw.MyToolbar.Preferences
-{
- public interface IIconList
+namespace CodeStack.Sw.MyToolbar.Structs
+{
+ public class ToolbarSettings
{
+ public string SpecificationFile { get; set; }
}
-}
+}
\ No newline at end of file
diff --git a/MyToolbar/ToolbarInfoVersionConverter.cs b/MyToolbar/ToolbarInfoVersionConverter.cs
new file mode 100644
index 0000000..d6d2c4f
--- /dev/null
+++ b/MyToolbar/ToolbarInfoVersionConverter.cs
@@ -0,0 +1,47 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.Structs;
+using Newtonsoft.Json.Linq;
+using System;
+using System.IO;
+using System.Linq;
+using Xarial.AppLaunchKit.Services.UserSettings.Data;
+
+namespace CodeStack.Sw.MyToolbar
+{
+ public class ToolbarInfoVersionConverter : BaseUserSettingsVersionsTransformer
+ {
+ public ToolbarInfoVersionConverter()
+ {
+ Add(new Version(), new Version("1.0"),
+ t =>
+ {
+ var oldFile = Path.Combine(Locations.AppDirectoryPath, "data.json");
+
+ if (File.Exists(oldFile))
+ {
+ var token = JToken.Parse(File.ReadAllText(oldFile));
+
+ foreach (var grp in token["Groups"].Children())
+ {
+ var prop = grp.Children().FirstOrDefault(p => p.Name == "Icons");
+ if (prop != null)
+ {
+ var iconPath = prop.Children().FirstOrDefault()?["IconPath"]?.ToString();
+ prop.Replace(new JProperty("IconPath", iconPath));
+ }
+ }
+
+ return token;
+ }
+
+ return null;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/UI/Base/CommandDataTemplateSelector.cs b/MyToolbar/UI/Base/CommandDataTemplateSelector.cs
new file mode 100644
index 0000000..992b915
--- /dev/null
+++ b/MyToolbar/UI/Base/CommandDataTemplateSelector.cs
@@ -0,0 +1,31 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.UI.ViewModels;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace CodeStack.Sw.MyToolbar.UI.Base
+{
+ public class CommandDataTemplateSelector : DataTemplateSelector
+ {
+ public DataTemplate NewCommandTemplate { get; set; }
+ public DataTemplate CommandTemplate { get; set; }
+
+ public override DataTemplate SelectTemplate(object item, DependencyObject container)
+ {
+ if (item is NewCommandPlaceholderVM)
+ {
+ return NewCommandTemplate;
+ }
+ else
+ {
+ return CommandTemplate;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/UI/Base/CommandPropertiesDataTemplateSelector.cs b/MyToolbar/UI/Base/CommandPropertiesDataTemplateSelector.cs
new file mode 100644
index 0000000..b6f32b1
--- /dev/null
+++ b/MyToolbar/UI/Base/CommandPropertiesDataTemplateSelector.cs
@@ -0,0 +1,36 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.UI.ViewModels;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace CodeStack.Sw.MyToolbar.UI.Base
+{
+ public class CommandPropertiesDataTemplateSelector : DataTemplateSelector
+ {
+ public DataTemplate CommandMacroTemplate { get; set; }
+ public DataTemplate CommandGroupTemplate { get; set; }
+ public DataTemplate DefaultTemplate { get; set; }
+
+ public override DataTemplate SelectTemplate(object item, DependencyObject container)
+ {
+ if (item?.GetType() == typeof(CommandMacroVM))
+ {
+ return CommandMacroTemplate;
+ }
+ if (item?.GetType() == typeof(CommandGroupVM))
+ {
+ return CommandGroupTemplate;
+ }
+ else
+ {
+ return DefaultTemplate;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/UI/Base/CommandsCollection.cs b/MyToolbar/UI/Base/CommandsCollection.cs
new file mode 100644
index 0000000..b1f2e53
--- /dev/null
+++ b/MyToolbar/UI/Base/CommandsCollection.cs
@@ -0,0 +1,135 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using CodeStack.Sw.MyToolbar.UI.ViewModels;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows.Data;
+
+namespace CodeStack.Sw.MyToolbar.UI.Base
+{
+ public interface ICommandsCollection
+ {
+ IList Commands { get; }
+
+ ICommandVM AddNewCommand(int index);
+ }
+
+ public class CommandsCollection : CompositeCollection, ICommandsCollection
+ where TCommandVM : ICommandVM, new()
+ {
+ public event Action NewCommandCreated;
+
+ public event Action> CommandsChanged;
+
+ private readonly ObservableCollection m_Commands;
+
+ private readonly List m_AvailableIds;
+
+ public ObservableCollection Commands
+ {
+ get
+ {
+ return m_Commands;
+ }
+ }
+
+ IList ICommandsCollection.Commands
+ {
+ get
+ {
+ return Commands;
+ }
+ }
+
+ public CommandsCollection(IEnumerable commands)
+ {
+ m_Commands = new ObservableCollection(commands);
+ m_Commands.CollectionChanged += OnCommandsCollectionChanged;
+
+ m_AvailableIds = new List(GetAvailableIds(m_Commands));
+
+ Add(new CollectionContainer()
+ {
+ Collection = m_Commands
+ });
+
+ var newCmdPlc = new NewCommandPlaceholderVM();
+ newCmdPlc.AddNewCommand += OnAddNewCommand;
+
+ Add(newCmdPlc);
+ }
+
+ private void OnAddNewCommand()
+ {
+ AddNewCommand(m_Commands.Count);
+ }
+
+ public ICommandVM AddNewCommand(int index)
+ {
+ var newCmd = new TCommandVM();
+
+ newCmd.Command.Id = GetNextId();
+
+ m_Commands.Insert(index, newCmd);
+
+ NewCommandCreated?.Invoke(newCmd);
+
+ return newCmd;
+ }
+
+ private IEnumerable GetAvailableIds(IEnumerable commands)
+ {
+ var availableIds = new List();
+
+ var usedIds = commands.Select(c => c.Command.Id).ToList();
+
+ if (usedIds.Any())
+ {
+ for (int i = 1; i < usedIds.Max(); i++)
+ {
+ if (!usedIds.Contains(i))
+ {
+ availableIds.Add(i);
+ }
+ }
+ }
+
+ return availableIds;
+ }
+
+ private int GetNextId()
+ {
+ if (m_AvailableIds.Any())
+ {
+ var id = m_AvailableIds.First();
+ m_AvailableIds.RemoveAt(0);
+ return id;
+ }
+ else
+ {
+ if (m_Commands.Any())
+ {
+ return m_Commands.Max(c => c.Command.Id) + 1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ }
+
+ private void OnCommandsCollectionChanged(object sender,
+ System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ {
+ CommandsChanged?.Invoke(m_Commands);
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/UI/Base/NotifyPropertyChanged.cs b/MyToolbar/UI/Base/NotifyPropertyChanged.cs
new file mode 100644
index 0000000..c27d211
--- /dev/null
+++ b/MyToolbar/UI/Base/NotifyPropertyChanged.cs
@@ -0,0 +1,22 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace CodeStack.Sw.MyToolbar.UI.Base
+{
+ public class NotifyPropertyChanged : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected void NotifyChanged([CallerMemberName] string prpName = "")
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prpName));
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyToolbar/UI/Base/RelayCommand.cs b/MyToolbar/UI/Base/RelayCommand.cs
new file mode 100644
index 0000000..4841457
--- /dev/null
+++ b/MyToolbar/UI/Base/RelayCommand.cs
@@ -0,0 +1,61 @@
+//**********************
+//MyToolbar - Custom toolbar manager
+//Copyright(C) 2019 www.codestack.net
+//License: https://github.com/codestack-net-dev/my-toolbar/blob/master/LICENSE
+//Product URL: https://www.codestack.net/labs/solidworks/my-toolbar/
+//**********************
+
+using System;
+using System.Windows.Input;
+
+namespace CodeStack.Sw.MyToolbar.UI.Base
+{
+ public class RelayCommand : ICommand
+ {
+ private readonly Action m_ExecuteFunc = null;
+ private readonly Predicate m_CanExecuteFunc = null;
+
+ public RelayCommand(Action executeFunc, Predicate canExecuteFunc = null)
+ {
+ if (executeFunc == null)
+ {
+ throw new ArgumentNullException(nameof(executeFunc));
+ }
+
+ m_ExecuteFunc = executeFunc;
+ m_CanExecuteFunc = canExecuteFunc;
+ }
+
+ public event EventHandler CanExecuteChanged
+ {
+ add
+ {
+ CommandManager.RequerySuggested += value;
+ }
+ remove
+ {
+ CommandManager.RequerySuggested -= value;
+ }
+ }
+
+ public bool CanExecute(object parameter)
+ {
+ return m_CanExecuteFunc == null
+ || m_CanExecuteFunc((T)parameter);
+ }
+
+ public void Execute(object parameter)
+ {
+ m_ExecuteFunc.Invoke((T)parameter);
+ }
+ }
+
+ public class RelayCommand : RelayCommand