diff --git a/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.Designer.cs b/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.Designer.cs
new file mode 100644
index 00000000..3659c9f3
--- /dev/null
+++ b/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.Designer.cs
@@ -0,0 +1,134 @@
+namespace TestCentric.Gui.Dialogs
+{
+ partial class CategoryFilterDialog
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CategoryFilterDialog));
+ this.buttonApply = new System.Windows.Forms.Button();
+ this.buttonApplyAndClose = new System.Windows.Forms.Button();
+ this.buttonSelectAll = new System.Windows.Forms.Button();
+ this.buttonClear = new System.Windows.Forms.Button();
+ this.searchTextBox = new System.Windows.Forms.TextBox();
+ this.checkedListBoxCategory = new System.Windows.Forms.CheckedListBox();
+ this.SuspendLayout();
+ //
+ // buttonApply
+ //
+ this.buttonApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonApply.Location = new System.Drawing.Point(254, 411);
+ this.buttonApply.Name = "buttonApply";
+ this.buttonApply.Size = new System.Drawing.Size(104, 35);
+ this.buttonApply.TabIndex = 5;
+ this.buttonApply.Text = "Apply";
+ this.buttonApply.UseVisualStyleBackColor = true;
+ this.buttonApply.Click += new System.EventHandler(this.OnApplyButtonClicked);
+ //
+ // buttonApplyAndClose
+ //
+ this.buttonApplyAndClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonApplyAndClose.Location = new System.Drawing.Point(369, 411);
+ this.buttonApplyAndClose.Name = "buttonApplyAndClose";
+ this.buttonApplyAndClose.Size = new System.Drawing.Size(127, 35);
+ this.buttonApplyAndClose.TabIndex = 6;
+ this.buttonApplyAndClose.Text = "Apply + Close";
+ this.buttonApplyAndClose.UseVisualStyleBackColor = true;
+ this.buttonApplyAndClose.Click += new System.EventHandler(this.OnApplyAndCloseButtonClicked);
+ //
+ // buttonSelectAll
+ //
+ this.buttonSelectAll.Location = new System.Drawing.Point(12, 12);
+ this.buttonSelectAll.Name = "buttonSelectAll";
+ this.buttonSelectAll.Size = new System.Drawing.Size(104, 35);
+ this.buttonSelectAll.TabIndex = 1;
+ this.buttonSelectAll.Text = "Select all";
+ this.buttonSelectAll.UseVisualStyleBackColor = true;
+ this.buttonSelectAll.Click += new System.EventHandler(this.OnSelectAllButtonClicked);
+ //
+ // buttonClear
+ //
+ this.buttonClear.Location = new System.Drawing.Point(125, 12);
+ this.buttonClear.Name = "buttonClear";
+ this.buttonClear.Size = new System.Drawing.Size(104, 35);
+ this.buttonClear.TabIndex = 2;
+ this.buttonClear.Text = "Clear";
+ this.buttonClear.UseVisualStyleBackColor = true;
+ this.buttonClear.Click += new System.EventHandler(this.OnClearButtonClicked);
+ //
+ // searchTextBox
+ //
+ this.searchTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.searchTextBox.Location = new System.Drawing.Point(237, 16);
+ this.searchTextBox.Name = "searchTextBox";
+ this.searchTextBox.Size = new System.Drawing.Size(258, 26);
+ this.searchTextBox.TabIndex = 3;
+ //
+ // checkedListBoxCategory
+ //
+ this.checkedListBoxCategory.Anchor = (System.Windows.Forms.AnchorStyles)System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ this.checkedListBoxCategory.CheckOnClick = true;
+ this.checkedListBoxCategory.FormattingEnabled = true;
+ this.checkedListBoxCategory.Location = new System.Drawing.Point(12, 60);
+ this.checkedListBoxCategory.Name = "checkedListBoxCategory";
+ this.checkedListBoxCategory.Size = new System.Drawing.Size(483, 349);
+ this.checkedListBoxCategory.TabIndex = 4;
+ //
+ // CategoryFilterDialog
+ //
+ this.AcceptButton = this.buttonApply;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(508, 466);
+ this.Controls.Add(this.checkedListBoxCategory);
+ this.Controls.Add(this.searchTextBox);
+ this.Controls.Add(this.buttonClear);
+ this.Controls.Add(this.buttonSelectAll);
+ this.Controls.Add(this.buttonApplyAndClose);
+ this.Controls.Add(this.buttonApply);
+ this.MinimumSize = new System.Drawing.Size(400, 400);
+ this.Name = "CategoryFilterDialog";
+ this.ShowInTaskbar = false;
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.Text = "Category filter";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button buttonApply;
+ private System.Windows.Forms.Button buttonApplyAndClose;
+ private System.Windows.Forms.Button buttonSelectAll;
+ private System.Windows.Forms.Button buttonClear;
+ private System.Windows.Forms.TextBox searchTextBox;
+ private System.Windows.Forms.CheckedListBox checkedListBoxCategory;
+ }
+}
+
diff --git a/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.cs b/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.cs
new file mode 100644
index 00000000..49c81ffd
--- /dev/null
+++ b/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.cs
@@ -0,0 +1,114 @@
+// ***********************************************************************
+// Copyright (c) Charlie Poole and TestCentric contributors.
+// Licensed under the MIT License. See LICENSE file in root directory.
+// ***********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+using TestCentric.Gui.Elements;
+
+namespace TestCentric.Gui.Dialogs
+{
+ ///
+ /// This dialog is responsible for the selection of test categories
+ /// It displays all categories in a non-modal dialog which is on top of the main form.
+ /// Users can select categories within this dialog and can observe the impact to the tree view immediately without leaving the dialog
+ ///
+ public partial class CategoryFilterDialog : Form
+ {
+ public delegate void ApplyButtonClickedEventHandler(IList selectedCategories);
+
+ public event ApplyButtonClickedEventHandler ApplyButtonClicked;
+
+ public CategoryFilterDialog()
+ {
+ InitializeComponent();
+
+ // Init search text box with 'Search...' content
+ searchTextBox.ForeColor = System.Drawing.Color.LightGray;
+ TextBoxElement = new TextBoxElement(searchTextBox, "Search...");
+ TextBoxElement.Changed += OnTextBoxChanged;
+ }
+
+ private IList AllCategories { get; set; }
+
+ private TextBoxElement TextBoxElement { get; set; }
+
+ private IList SelectedCategories
+ {
+ get
+ {
+ var selectedItems = new List();
+ foreach (var item in checkedListBoxCategory.CheckedItems)
+ {
+ selectedItems.Add(item.ToString());
+ }
+
+ return selectedItems;
+ }
+ }
+
+ internal void Init(IEnumerable allCategories, IEnumerable selectedCategories)
+ {
+ AllCategories = allCategories.ToList();
+
+ checkedListBoxCategory.SuspendLayout();
+ foreach (string item in allCategories)
+ {
+ int index = checkedListBoxCategory.Items.Add(item);
+ if (selectedCategories.Contains(item))
+ checkedListBoxCategory.SetItemChecked(index, true);
+ }
+ checkedListBoxCategory.ResumeLayout();
+ }
+
+ private void OnApplyAndCloseButtonClicked(object sender, EventArgs e)
+ {
+ ApplyButtonClicked?.Invoke(SelectedCategories);
+ Close();
+ }
+
+ private void OnApplyButtonClicked(object sender, EventArgs e)
+ {
+ ApplyButtonClicked?.Invoke(SelectedCategories);
+ }
+
+ private void OnSelectAllButtonClicked(object sender, EventArgs e)
+ {
+ for (int i = 0; i < checkedListBoxCategory.Items.Count; i++)
+ {
+ checkedListBoxCategory.SetItemChecked(i, true);
+ }
+ }
+
+ private void OnClearButtonClicked(object sender, EventArgs e)
+ {
+ for (int i = 0; i < checkedListBoxCategory.Items.Count; i++)
+ {
+ checkedListBoxCategory.SetItemChecked(i, false);
+ }
+ }
+
+ private void OnTextBoxChanged()
+ {
+ string searchText = searchTextBox.Text;
+ IList selectedCategories = SelectedCategories;
+ checkedListBoxCategory.SuspendLayout();
+
+ checkedListBoxCategory.Items.Clear();
+ foreach (string item in AllCategories)
+ {
+ if (string.IsNullOrEmpty(searchText) || item.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) > -1)
+ {
+ int index = checkedListBoxCategory.Items.Add(item);
+ if (selectedCategories.Contains(item))
+ checkedListBoxCategory.SetItemChecked(index, true);
+ }
+ }
+
+ checkedListBoxCategory.ResumeLayout();
+ }
+ }
+}
diff --git a/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.resx b/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.resx
new file mode 100644
index 00000000..37dfdf78
--- /dev/null
+++ b/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.resx
@@ -0,0 +1,816 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ AAABAAUAEBAAAAEAIABoBAAAVgAAABgYAAABACAAiAkAAL4EAAAgIAAAAQAgAKgQAABGDgAAMDAAAAEA
+ IACoJQAA7h4AAAAAAAABACAALF0AAJZEAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAADDDgAAww4AAAAA
+ AAAAAAAAAAAAAAAAAABFaSAAW28tCSthEEwaXAWoE1sC4BFbAvURWwL1FV0F3iFhDaM1aBtIbHs/B1Vy
+ LwAAAAAAAAAAALOMZgAdXggAOmUYHRpcBpohZxTwSIM//2maYv9unWj/XJFV/zp6Mf8YYwz/El0E7iJi
+ D5NIbygaKGQRAN2xqwAsYRAAOWQXHhldBrpPh0b/xNfC//b59v/1+PX/8fXw//T49P/y9vH/kbWM/w1c
+ Av8NWwH/HWELsklvKBk4ah4AZG4tCBlcBZtOh0X/5+/m/+rx6f+HroH/R4M+/zx7Mv9LhkL/gqt9/2aY
+ X/8LWgD/DFsA/w1bAf8iYg+SjIZVBihfDE4hZxTwwta///P38v9ckVT/CVkA/whYAP8KWgD/ClkA/wlZ
+ AP8NWwL/DFsA/wxbAP8MWwD/El0E7DVoG0YYWgKqTYdF//n7+f+qxab/D10F/wtbAP8JWQD/Qn85/1aN
+ Tv8KWQD/DFsA/wxbAP8MWwD/DFsA/w1bAf8iYg+fEloA43qmdf//////a5tl/whYAP8MWwD/CFgA/1yR
+ VP96pXT/CFkA/wxbAP8MWwD/DFsA/wxbAP8MWwD/GV8J2hJbAvqSto3//f79/1GJSf8IWAD/DFsA/whY
+ AP9ckVT/eqV0/whZAP8MWwD/DFsA/wxbAP8MWwD/DFsA/xVeBvISWwL6k7aO//39/f9PiEf/CFgA/wxb
+ AP8HWAD/W5BU/3qldP8HWAD/DFsA/wxbAP8MWwD/DFsA/wxbAP8VXgbyE1oB43yndv//////Z5lh/whY
+ AP8OXQL/GmQO/2maY/+FrYD/HGYR/xBeBf8MWwD/DFsA/wxbAP8MWwD/GF4I2hhaA6tOh0X/+fv5/6XC
+ of8NXAP/G2UQ/3+oef+gv5z/pcOh/4mwhP8qbyD/CloA/wxbAP8MWwD/DVsA/yBgDKApXwxQIGYT8MDV
+ vf/w9fD/VItM/wlZAP8SXwf/FGAI/xJfBv8TXwf/DlwD/wxbAP8MWwD/DFsA/xFcA+wvZBRHY20sCBpb
+ BZxMhUP/5+/m/+Tt4/91om//M3Yq/ydtHf86ejD/dKFt/02HRf8KWgD/DFsA/w1bAf8fXwqTeHc+Bi1h
+ DwA6YxYeGV0Gu1GJSP/M3cr/+vv5/+3z7P/k7eP/8PXv//j69/+FrYD/CloA/w1bAf8bXgizP2ccGjFk
+ FACwh2UAHl0HADpjFh4bXAWbJ2oZ8VmPUf+DrH7/jbKI/3ikcv9LhUL/G2UQ/xFcAu4fXwmUPWYaGiRf
+ CgDSopYAAAAAAAAAAABDZRsAV2omCSleC00ZWgKoFFoB4BJbAfYRWgH2E1oB3h1dB6QuYhFIW2wqB0hn
+ HwAAAAAAAAAAAOAHAADAAwAAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACAAQAAwAMAAOAHAAAoAAAAGAAAADAAAAABACAAAAAAAAAJAADDDgAAww4AAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAP/i/wBZbSkAfntECUZrIj0wZRWJJGIPxR1gC+YcYQvyHGEL8h5hDOQmYxHBNGgag09x
+ LDiVilwHc3pAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf3lDALaJZAJDaR86JGENphNb
+ A+sKWQD+CVkA/wpaAP8KWgD/CFkA/wdYAP8JWQD/DlsB/hdfB+cqZRSeT3EsM/+zqgGejmMAAAAAAAAA
+ AAAAAAAAAAAAAAAAAABbbisAcnM5CTFjFHIUXAToEF0F/zV3K/9pmmL/jbKI/5u7l/+YuZP/ha2A/2WX
+ Xv88ezL/F2IM/wtbAP8NWwH/GV8J4jpqHmiUilwHdH5FAAAAAAAAAAAAAAAAAFpsKABxcTUJKmEPiA9b
+ AvgxdSj/nr6a/+jw5//+/v7///////////////////////7+/v/v9O7/tc2y/ylvH/8KWgD/C1sA/xNd
+ BfU0aRp8nI1iB3Z/RwAAAAAAenQ5AP+lqwEvYhJzD1oB+EaCPv/V49T////////////s8uv/xtjD/67J
+ qv+uyKr/vdO6/9zn2v/7/Pv/2ubY/yZsG/8KWgD/DFsA/wtbAP8TXgX0OmofZ////wCejmQAKGANAD5l
+ GTwUWwPoMHQn/9Ti0v//////+fv4/6XCof8+fTX/F2IM/w5dA/8OXQL/E2AI/yZsG/9ckVX/appj/w9d
+ BP8MWwD/DFsA/wxbAP8LWwD/GWAJ4E9xLDI3aRwAiXZBCSJfC6gPXQT/nL2Y///////9/v3/kbWM/xRg
+ Cv8JWQD/C1sA/wxbAP8LWgD/CloA/wpaAP8JWQD/C1oA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DVsB/ypl
+ FJrZn4cFQGUaQRJbAew3eC7/6O/n///////H2cX/H2gW/wpaAP8MWwD/DFsA/wtbAP8dZhL/JWwa/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/C1sA/xdfCORRcS01LGEQjgpZAP90oW7/////////
+ //9xn2v/CFgA/wxbAP8MWwD/DFsA/whZAP9wn2r/oL+c/w5cA/8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/w9cAv01aBt+IV8Kyg1cAf+lwqH//////+3z7f86ejH/CVkA/wxbAP8MWwD/DFsA/whY
+ AP97pnX/sMqt/w5dA/8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8mYxG6Gl0G6xRh
+ Cf/B1b7//////9jl1v8iahf/C1oA/wxbAP8MWwD/DFsA/whYAP97pnX/sMqt/w5dA/8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtbAP8fYQzeGF0F+hpkD//N3cv//////8vcyf8ZZA7/C1oA/wxb
+ AP8MWwD/DFsA/whYAP97pnX/sMqt/w5dA/8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtb
+ AP8bYAnuGF0F+xplEP/O3sz//////8nbx/8YYw3/C1oA/wxbAP8MWwD/DFsA/whYAP97pnX/sMqt/w5d
+ A/8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtbAP8bXwnuG10H7BVhCv/D1sD//////9Xi
+ 0/8faBX/C1oA/wxbAP8MWwD/C1sA/wdYAP97pnX/sMqt/w5cA/8LWgD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8eYAvfIV8Kyw1cAv+nxKT//////+rx6f81dyz/CVkA/wxbAP8NXAH/FmIL/xRg
+ Cf+Bqnz/tMyx/xpkD/8XYwz/D10E/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8kYg+7LGEQjwtZ
+ AP91om////////7+/v9rm2X/CFgA/wtaAP8gaBX/pcKh/7zSuf/V49P/4evg/7zSuf+3z7T/P302/wlZ
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/w9cAv4xZRZ/QGUaQhJbAew2dy3/5u7l///////B1b7/G2US/wpa
+ AP8TXwf/P301/0eDPv9FgTz/RIE7/0aCPf9FgTz/HWYS/wtaAP8MWwD/DFsA/wxbAP8MWwD/C1sA/xZe
+ BuZIayQ2hHU+CSNfC6kPXAP/mLmT///////8/fv/ha1//w9dBf8JWQD/CVkA/wlZAP8JWQD/CVkA/whY
+ AP8GVwD/CVkA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DVsB/yZhDpy+i2oFKV4MAD9lGT0VWwPpLXEk/9Hg
+ z///////9fj0/5C0i/8qcCD/DVwC/wlZAP8IWQD/C1sB/xplD/9OiEb/SIRA/wtaAP8MWwD/DFsA/wxb
+ AP8LWwD/GF4G4kVpHzIxYxMAdHE2AP+WjwEwYRF1D1oB+USBPP/X5NX///////3+/f/c59r/pcKh/4Ss
+ f/+Cq3z/nLyY/8rbx//3+vf/udC2/xRhCf8LWwD/DFsA/wtbAP8SXAP1MmQVaAAAAACJfkwAAAAAAFpr
+ JwBwbzMKLGAPiRBaAfk1dyz/q8an//L28f/////////////////////////////////5+/n/ts6z/x5n
+ E/8LWgD/C1sA/xJcA/YuYxJ9iH1JBmZzNAAAAAAAAAAAAAAAAABYayYAbG4xCjFiEnMVWwPpFGAJ/0aD
+ Pv+Ir4L/ssuv/8PXwf/C1b//sMms/4qwhf9Ti0r/HWcS/wtbAP8NWwD/GF0G4zJjE2h6dDoHYG0rAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAeXI5AKt+VAJBZRo6JF8LpxJaAuwMWgD+EF4E/xVhCv8UYQn/Dl0D/wlZ
+ AP8JWQD/DVsB/hZdBeglYA2fQ2ccM+eNdQGGdkEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+u
+ /wBUaCAAdnI3CUNlGz0uYRGJI18LxRxdB+YaXgf0Gl4H8x1eCOQjXwvBLmERg0RmHDh+dD0HYmwqAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA/AA/APAADwDgAAcAwAADAIAAAwCAAAEAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAABAIAAAwDAAAMA4AAHAPAADwD8AD8AKAAAACAA
+ AABAAAAAAQAgAAAAAAAAEAAAww4AAMMOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAlIBPALKOaQVldDUrRWsiajRmGKYpYxLPI2IO5yNjEO8jYxDuJGIP5SxlFMs4aR2gTW8qZHN8
+ QybRoIYEspFsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAgXlDAKCGWgZRbSdAL2QUnR1fCuASXQT6DVsB/wtbAP8LWgD/C1oA/wtbAP8LWwD/DFsA/w5c
+ Af8TXQX4IGEN2jZpHJNgdjc4xJp8BKGMYQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAzZN1AAA5AABgcC8kMmQVmBheB+8MWgD/B1gA/wlZAP8PXQT/FGAJ/xVhC/8TYAj/Dl0D/wpa
+ AP8IWAD/CVkA/wtaAP8LWwD/DlwB/xtgCug7ax+Ld39HHQBMAADwurkAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJ6AVQD/y/wBTGojRiJgDNANWwH/CVkA/yJqF/9XjU//i7GG/67Iq//A1L7/w9fB/73T
+ u/+sx6n/kLSL/2iZYv87ezL/FmIL/wpaAP8MWwD/C1sA/w9cA/4pZRPEXnY2OwAAAADIpIoAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACZgFAA////AERmHFQbXgjlCVkA/xxmE/91om//0eDP//n7+f//////////////
+ /////////////////////////f79/+3z7P+907v/TYdF/wtaAP8MWwD/DFsA/wxbAP8hYg7aV3QxRwAA
+ AADCnYEAAAAAAAAAAAAAAAAAwY5vAABKAABJaCBHG14H5QlZAP80div/udC2//z9/P//////////////
+ /////////P37//n7+f/6/Pr//f79//////////////////////9zoW3/CVkA/wxbAP8MWwD/DFsA/wxb
+ AP8hYg7aX3c3OhJdBADpsZ4AAAAAAAAAAABKZx8AXGwpJSFfC9AJWQD/M3Uq/8zcyf//////////////
+ ///y9vH/uM+1/3yndv9bkFP/UIlH/1SLS/9kllz/hax//7jPtv/r8uv/6/Lq/zt6Mv8JWQD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAf8pZRPBen9IHGV4OQAAAAAAgXdAALuEXwYvYhGaDVsA/xtlEf+2zrP/////////
+ ////////y9zJ/1KKSv8UYAn/CFkA/whYAP8IWAD/CFgA/whYAP8JWQD/E2AI/zx7M/9ll13/F2IM/wtb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/xBcA/47ax+H/83cA6mSaQAvYBAASmgfQhddBe8JWQD/c6Ft//z9
+ /P///////////8TXwf8uciT/CFgA/wtbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/CVkA/wlZ
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/C1sA/xxgC+Vgdzc0Sm8oAOGLcAUsYRCgC1oA/yJq
+ GP/Q387////////////l7uT/QH44/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wpZAP8JWQD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DlwC/zdpHY7///8CWmsoLxte
+ B+IIWAD/XZJW//r8+v///////////46ziv8LWwH/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/RoI+/2KV
+ W/8VYQn/C1sA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/IWIO1nd9
+ RSM+ZRlwEVwC/AxbAP+cvJj////////////v9O7/QH44/wlZAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wpa
+ AP+YupT/2+fa/yFpFv8LWgD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8UXgX2TXAqXC5hEK0MWwD/GWQO/8jaxv///////////8rbyP8aZA//C1oA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/CloA/5i5lP/b59r/IWkW/wtaAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/w5cAf84aR2XJV8M1wpaAP8qbyH/4evg////////////pMKg/w1cAf8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8KWgD/mLmU/9vn2v8haRb/C1oA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/yxlFcMgXwrvCFkA/zl5MP/t8+3///////////+JsIT/CVkA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wpaAP+YuZT/2+fa/yFpFv8LWgD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/JWIP3h1eCPoIWQD/Qn85//L28v///////////3ym
+ dv8IWAD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/CloA/5i5lP/b59r/IWkW/wtaAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtbAP8hYg7oHV4I+whZAP9DgDr/8/fy////
+ ////////eqV0/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8KWgD/mLmU/9vn2v8haRb/C1oA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/C1sA/yFhDeggXwrvCFkA/zt7
+ Mv/v9O7///////////+ErH//CVkA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wpaAP+YuZT/2+fa/yFp
+ Fv8LWgD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/JGEO3iVf
+ DNgKWgD/LHEj/+Ps4v///////////529mf8LWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/CloA/5i5
+ k//b59r/IGkW/wpaAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8qZBPEL2ERrgxbAP8aZRD/y9zJ////////////w9bA/xZiDP8LWwD/DFsA/wxbAP8NWwH/El8G/xNf
+ B/8RXgb/m7uX/9zn2/8nbR3/EV8G/xJfB/8OXQP/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DlsB/zVmGZk+ZBhyEVwC/AxbAf+evZr////////////r8er/OXox/wlZAP8MWwD/C1oA/yBo
+ Ff+oxaX/wtbA/8DVvv/l7eT/9vn2/8bYxP/A1b7/wNS9/02HRP8JWQD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8TXQT3R2sjXVlqJzEcXgfjCFgA/1yRVf/5+/n///////////+FrYD/CloA/wxb
+ AP8LWgD/G2UQ/4Orff+WuJL/lbiQ/5O2jv+StY3/lbeQ/5W4kP+Vt5D/PXw0/wpZAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/C1sA/x5gC9hrdTgjzYZmBi1hEKIMWgD/IGkW/83dyv///////////9/p
+ 3f82eC7/CVkA/wxbAP8MWwD/CloA/wpaAP8KWgD/CloA/wpaAP8KWgD/CloA/wpaAP8LWgD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8OWwH/MmUWkP///wEyYBAASmcfRBhdBvAJWQD/bZxm//r8
+ +v///////////7bOs/8iahj/CVkA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/CloA/wpZ
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/C1sA/xpeCOdUbSg1QmcdAHp1OwCsf1UGMWERnA5b
+ AP8YYw7/sMqt/////////////v7+/7fOtP85eTD/C1oB/whYAP8KWQD/CloA/wpaAP8JWQD/CFgA/w1c
+ A/8wcyb/QH43/wxbAf8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8PXAL/NGQWiv+wtAKTgVAA////AEtm
+ HQBbaygnI18L0gpZAP8wcyf/ytvH/////////////////+Ps4f+Tto7/UIlI/zBzJv8lbBv/KG4e/zp6
+ Mf9hlFn/n76b/+Lr4f/D1sD/GWQO/wtaAP8MWwD/DFsA/wxbAP8MWwD/DFsA/yVgDcVocjQcV2woAAAA
+ AAAAAAAAt4pkAABIAABJZh1JHF0H5glZAP80div/vtO7//3+/f/////////////////3+vf/5u7l/9zo
+ 2//f6t7/7fPt//z9+/////////////H28f9Ggj3/CVkA/wxbAP8MWwD/DFsA/wxbAP8eXwrcUGslOhhc
+ BADXlXoAAAAAAAAAAAAAAAAAlYBPAP///wBFZRtVHV0H5glZAP8gaRf/ha2A/+Lr4P/+/v7/////////
+ ///////////////////////////////////5+/n/zNzJ/0KAOf8JWQD/DFsA/wxbAP8MWwD/Hl4J3Uxr
+ I0cAAAAAr5JvAAAAAAAAAAAAAAAAAAAAAAAAAAAAjHZCAP+mrwFLZx9HI18L0Q1aAf8LWwL/MXQn/3ej
+ cf+0zbH/1+TW/+fv5v/r8uv/6O/n/9zn2v/C1sD/lriR/1mPUf8gaBX/C1sA/wxbAP8LWwD/D1sC/iRg
+ DMZPaiM7AAAAAKd9VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvY5qAAA2AABcaykkMmISmRld
+ Bu8LWgD/CFkA/xFfBv8iahj/MHMn/zV3LP8xdCj/JWwb/xZiC/8LWgH/CFgA/wpaAP8LWwD/DlsB/xpd
+ B+ozYxSMZG8uHAtPAADjq6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHZx
+ NgCSfUsGTmghQC9hEZ4dXgjgElwD+wxaAP8KWQD/CVkA/wlZAP8KWgD/C1oA/wxbAP8OWwH/E1wD+R1e
+ CNswYhKUUWkjN6uEXgSJeUUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACEczwAon9UBV1sKStCZRpqMmITpihgDtAiXgrnIWAM8iFgC/EiXgrlKWAOzDNi
+ E6BDZRtjYm0sJbeFYAOae0wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/gAH//gAAf/wA
+ AD/wAAAf8AAAD+AAAAfAAAADgAAAAYAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABwAAAA+AAAAfwAAAP8AAAH/wAAD/+AAB//4AB/ygA
+ AAAwAAAAYAAAAAEAIAAAAAAAACQAAMMOAADDDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3BuwD///8AvJBtD4F9RzVhczRnTG0ml0Br
+ Ibs0ZRfWM2kc3zJpGuYyaRvlNGoc3jZmGdNEbSW1U3EtkGt5PWCQhVQv0pyCDP///wD/ytIAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wCyjmcA1JmBBXt6Qi5Rbih3NmYYuyNh
+ DuUXXgf5EFwD/g1bAf8MWwD/C1sA/wtbAP8LWwD/C1sA/wxbAP8NWwH/EV0E/RlfCfUnZBLfPWsgsF51
+ NWuRhlYn9bOtBNSfhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsItkANKchAVxdjs7QmgenSRh
+ DeUTXAT+DFsA/wtbAP8LWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtb
+ AP8LWwD/DFsB/xVeBvsqZRTbT3EsjYmDUDH/tKkD1aCGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOaplAAAAAAAgnpEI0dp
+ IJEiYAzqD1sC/wtbAP8MWwD/DFsA/wtaAP8KWgD/CVkA/whZAP8IWQD/CFkA/wlZAP8KWQD/C1oA/wtb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/EF0D/illE95XdDF/oI1iGwAwAAD20dkAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArotkAOGe
+ igRhcC9TLWIR0hFcA/8LWwD/DFsA/wpaAP8IWQD/DVsC/xpkEP8scSP/Pnw2/0iDQf9LhUT/SINC/0B+
+ Of8ydSn/I2oZ/xVhCv8MWwH/CFgA/wlZAP8LWwD/DFsA/wxbAP8MWwD/DFsA/wtbAP8UXgb7OWoewHt/
+ SEP/vcAC0J6EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACOgE0AroliDE5qJHsfXwrvDFsA/wxbAP8KWgD/C1sC/yluH/9jllz/n76b/8nbx//i7OH/7/Tu//X4
+ 9f/3+fb/9fn1//D18P/n7+b/2OXW/77TvP+au5b/a5tk/zp6MP8WYgv/CVkA/wtaAP8MWwD/DFsA/wxb
+ AP8LWwD/DVsB/ydkEuJkeDlm4KWPB7SSbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAH5yOgCbe0sPRWYckhhdBvkLWwD/C1oA/wpaAf8vcyb/i7CG/9rm2f/7/Pv/////////
+ /////////////////////////////////////////////////////////f79/+vy6v+70bj/appk/x1m
+ Ev8LWgD/DFsA/wxbAP8MWwD/DFsA/wtbAP8eYQzwXHY1e8+bgQqpjWQAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAinhDAKqAVgtDZhuRFVwE+wtbAP8KWgD/FGAK/22cZv/b5tn//v/+////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////9/n2/1iOUf8IWQD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/G2AK81l1M3ntqpgHtpRwAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACph1wA/6KVBExoIX0XXQX6C1sA/wpaAP8eZxT/mbqV//f6
+ 9///////////////////////////////////////////////////////////////////////////////
+ ////////////////////////5e3k/zJ1Kf8KWQD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/C1sA/x5i
+ De9nejxl/+r/As6bgAAAAAAAAAAAAAAAAAAAAAAAAAAAANWRdAAAOwAAXGwpVR5eCe8LWwD/CloA/x1m
+ FP+nxKP//f79/////////////////////////////f39/+Ps4v+2zrL/jbKI/3OhbP9omWD/aJlg/3Cf
+ af+Bqnv/nLyX/8DUvf/m7uT//P38////////////tc2y/xNgCP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wtbAP8nZBPge39IQRheBADusKoAAAAAAAAAAAAAAAAA////AGhtLgB6dDolK2EP0wxb
+ AP8LWwD/E18J/5a4kv/9/v3///////////////////////7//v/X5Nb/eaV0/zBzJ/8SXwf/ClkA/whY
+ AP8IWAD/CFgA/whYAP8JWQD/DFsB/xVhCv8ydSn/bJxm/7TNsf/u8+3/eKRx/wlZAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8NWwH/OmoevKmOZRmSh1YAAAAAAAAAAAAAAAAAo4ZaAP+i
+ lwRCZhuUEVwC/wxbAP8KWgD/aJli//b59v//////////////////////+vv5/6PBn/8uciT/CVkA/wpZ
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtbAP8KWQD/CFkA/xNgCf9Afjf/J20d/wta
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/FV4G+1h0MXn///8B056DAAAA
+ AAAAAAAATmYfAGVuLj4gXgnsC1sA/wpaAP8tcST/1+TW///////////////////////6/Pr/j7OK/xZi
+ DP8JWQD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtb
+ AP8JWQD/C1oA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/C1sA/ypl
+ FNuNhVQsd31FAAAAAACmhVoA/JqIBT1kGKEOWwH/DFsA/wtbAP+Ir4P/////////////////////////
+ //+mw6L/F2IN/wpaAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/xFdBP5RcS2G////AcqbfQBhaykAb3AzMyFfCugLWwD/CloA/ypvIP/a5tj/////////
+ /////////////9jl1/8wcyj/CVkA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wpa
+ AP8JWQD/C1oA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtbAP8sZRbVmIhaI4uDUQAAEwAASWcefRFcA/8MWwD/CVkA/2qb
+ ZP/9/fz//////////////////v79/3ikcv8JWQD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/D10D/zBzJ/86ejH/HmcU/wtaAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtbAP8WXgf6YXY3YwBRAACmfVARMGERwQxb
+ AP8MWwD/EV4G/67Iq///////////////////////2+fa/ypvIf8KWgD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8LWgD/GmUQ/73Tu//v9O//Zphg/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8NWwH/QGwiqP+s
+ oQltbzE7IF4J6wtbAP8KWgD/KW8g/93o3P//////////////////////nr6a/w1cAf8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWgD/G2UR/83dyv//////bp1o/whYAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8LWwD/KWQT2ZWGVyhSaSNwFVwE/AtbAP8IWQD/TIZF//X49f/////////////////9/fz/Y5Zb/whY
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWgD/G2UR/8zdyv//////bp1o/whY
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8LWwD/GmAK8mx5PFRCZRqiD1sB/wxbAP8IWAD/cJ5q////////////////////
+ ///s8uv/OXow/wlZAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWgD/G2UR/8zd
+ yv//////bp1o/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/El0E/VZzL4I2YxTJDVsA/wxbAP8KWQD/jrKJ////
+ ///////////////////X5NX/ImoX/wtaAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8LWgD/G2UR/8zdyv//////bp1o/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DlwB/0VsJKguYRDgC1sA/wxb
+ AP8MWwH/o8Gg///////////////////////C1r//FmIL/wtbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8LWgD/G2UR/8zdyv//////bp1o/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/zxq
+ HsQrYhDyC1sA/wxbAP8QXgX/scqt//////////////////////+yy6//EF0E/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWgD/G2UR/8zdyv//////bp1o/whYAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/C1sA/zFkFNgnYA35C1sA/wxbAP8SXwf/uM+1//////////////////////+qxqf/DlwD/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWgD/G2UR/8zdyv//////bp1o/whY
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/C1sA/zFoGdsnYA35C1sA/wxbAP8SXwj/udC2////////////////////
+ //+nxKT/DVwC/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWgD/G2UR/8zd
+ yv//////bp1o/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/C1sA/zFoGdssYhDyC1sA/wxbAP8RXgb/tMyx////
+ //////////////////+tyKr/Dl0D/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8LWgD/G2UR/8zdyv//////bp1o/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/C1sA/zBjE9kvYRDhC1sA/wxb
+ AP8NXAL/qMSk//////////////////////+60bf/E18H/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8LWgD/G2UR/8zdyv//////bp1o/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/ztp
+ HcU3YxTKDVsA/wxbAP8KWgD/k7aP///////////////////////P383/HGYS/wtaAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWgD/G2UR/8zdyv//////bp1o/whYAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DlsB/0JqIKlCZRqkD1sB/wxbAP8IWAD/daJw///////////////////////m7uX/MXQn/wpZ
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWgD/G2UR/8zdyv//////bp1o/whY
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/ElwD/lFvKoNTaSNyFlwE/AtbAP8IWQD/UIlJ//f69///////////////
+ ///5+/n/Vo1P/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwH/DFsB/wxbAf8LWwD/HGUS/83d
+ yv//////bp1o/whYAP8MWwH/DFsB/wxbAf8MWwH/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/GV4I9GZ0NVVqbjA9IF4J7AtbAP8KWgD/K3Ai/9/p
+ 3v//////////////////////krWN/wtaAP8MWwD/DFsA/wxbAP8MWwD/C1oA/xxmEf+RtYz/qMSk/6bD
+ o/+mw6L/rMep/+3z7P//////ytvI/6XCof+mw6P/psOj/6jEpf9akFP/CloA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/J2IQ3It/Syebe0sSMmERxAxb
+ AP8MWwD/EV4G/6/JrP//////////////////////0+HR/yNqGf8KWgD/DFsA/wxbAP8MWwD/CloA/yZs
+ G//d6Nv///////////////////////3+/f/9/f3//v7+//////////////////////+HroL/CVkA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8NWwH/Omcbq/+l
+ mAgABwAASWYegBJcA/8MWwD/CVkA/2iZYv/8/fz/////////////////+/z7/2maY/8JWQD/DFsA/wxb
+ AP8MWwD/C1sA/xVhCv9XjU//ZJZd/2OWXP9jllz/Y5Zc/2OWXP9jllz/Y5Zc/2OWXP9jllz/Y5Zc/2SW
+ Xf84eS//C1oA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtb
+ AP8VXQX8WG8sZQBSAABhaigAbG8xNSNeC+kLWwD/CloA/ydtHf/W49T//////////////////////8zd
+ yv8lbBz/CloA/wxbAP8MWwD/DFsA/wxbAP8JWQD/CFgA/whYAP8IWAD/CFgA/whYAP8IWAD/CFgA/whY
+ AP8IWAD/CFgA/whYAP8KWgD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wtbAP8pYhDaiH1JIn55QgCRgE8A1JBzBj5kGKQPWwH/DFsA/wpaAP+AqXr/////////
+ //////////////7+/v+StY7/EF4G/wtaAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/xFcA/9IaSGJ////AcKUcgD///8AT2UdAGRtLUAhXgrtC1sA/wpa
+ AP8nbR3/0N/O///////////////////////1+PT/c6Ft/w1cBP8LWgD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8KWgD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/C1sA/yZhDt95eD8saHEyAAAAAAAAAAAAlYJTAOSY
+ gQVEZRqYElwC/wxbAP8JWQD/X5NY//P38v//////////////////////8fbw/3+pef8YYw7/CVkA/wtb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWgD/CVkA/w9dBf8lbBz/D10E/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8LWwD/FFwE/U1rI3z///8AyZl7AAAA
+ AAAAAAAA////AGRqKQB1cjYoLmAP1gxbAP8LWwD/EF4G/46zif/8/fz///////////////////////n7
+ +f+yy6//SIRB/xNgCf8IWQD/CVkA/wpaAP8KWgD/C1oA/wpaAP8JWQD/CFgA/wpaAf8bZRH/S4ZD/5y8
+ mf/F2ML/Km8g/wpaAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8NWwH/M2QVwZN/
+ Thh/eEAAAAAAAAAAAAAAAAAAAAAAALaRbQAAMwAAW2onWSBeCfELWwD/C1oA/xplEf+jwZ///f79////
+ ////////////////////////7/Tu/7bOsv90oW3/RoI+/y5yJf8jaxn/ImoY/ypvIP88ezP/XZJV/4+z
+ iv/J28b/8/fy///////7/Pv/YZVa/whYAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtb
+ AP8kYAzlaXIzQSlaBwDhuqcAAAAAAAAAAAAAAAAAAAAAAAAAAACUgVAA05R3BUtmHoAZXAX6C1sA/wpa
+ AP8dZxT/nLyY//n7+f/////////////////////////////////+/v7/8/fz/+Tt4//a5tj/2eXX/+Dq
+ 3v/u8+3/+/z7////////////////////////////p8Oj/w9dBP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxb
+ AP8MWwD/C1sA/xxeCPNVaydl////AbmScAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAg3Y/AJ19
+ TgxHZRyTF1wF/AtbAP8KWgD/FmIM/3mkc//m7uX/////////////////////////////////////////
+ ////////////////////////////////////////////////////////3Ojb/ypvIP8KWgD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8LWwD/Gl4H9k9sJXrknYUFpoleAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAHpwNQCSeEUPRWQZlBpdBvoLWwD/C1oA/wxbAv8/fjf/qcWl/+/07///////////////
+ //////////////////////////////////////////////////////////////v8+//W49T/eaV0/xlj
+ Dv8LWgD/DFsA/wxbAP8MWwD/DFsA/wtbAP8cXQf0Tmkie8WWdgichlgAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAeUIAmX9QDU5oIH0hXgnwDFsA/wtbAP8JWQD/El8I/0aC
+ Pf+Tto7/0N/O//H28f/9/v3//////////////////////////////////f39//H18P/W5NX/p8Sj/2WX
+ Xf8mbRz/CloB/wtaAP8MWwD/DFsA/wxbAP8LWwD/DVsB/yNfC+ZVayZnwIJdBpZ3RQAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAm4JUAMSPcAVdaylUL2EQ0xJc
+ A/8LWwD/C1sA/wlZAP8MWwL/H2gV/0OAO/9pmWP/hq6C/5q7l/+hv57/n76c/5S3kP+AqXv/ZJZe/0J/
+ Ov8jahn/D10E/whZAP8KWgD/DFsA/wxbAP8MWwD/DFsA/wtbAP8UXAP9MmITxGdvMEH/srsCtolmAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALqV
+ cwAAAAAAd3M4JEZmHJIjXgvrEFsC/wtbAP8LWwD/C1oA/wlZAP8IWAD/CVkA/wtaAP8MWwD/C1oA/wpa
+ AP8JWQD/CFgA/wlZAP8LWgD/DFsA/wxbAP8MWwD/DFsA/wtbAP8LWwD/EVwC/yVfDOJLaCCAhnhCGTBR
+ AADiwrEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAm4BSALqOawVpbjA7QmUZniZfC+cUXAP+DFsA/wtbAP8LWwD/DFsA/wxb
+ AP8MWwD/DFsA/wxbAP8MWwD/DFsA/wxbAP8MWwD/DFsA/wtbAP8LWwD/DVsA/xVcBP0nYA3fRWYcjnRy
+ Ny74pJUCwI5sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wCbfU4Av4llBXBwMy5NZyB3NmITuyRf
+ C+YYXQX6EVwC/w5bAf8MWwD/C1sA/wtbAP8LWwD/C1sA/wxbAP8OWwH/EVwC/xldBvglXwzhN2MVslFp
+ Imp7dDok6ZmGA8GJZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOq1
+ owD///8ApYFVDnNxNTRaaidmSWYdlj5lGbwzYBDVMWIS4jBkFOwwZBTrMGER4DRhEtM+ZRm2Smcfj11r
+ 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
+ AABJRU5ErkJggg==
+
+
+
\ No newline at end of file
diff --git a/src/TestCentric/testcentric.gui/Elements/ControlElements/TextBoxElement.cs b/src/TestCentric/testcentric.gui/Elements/ControlElements/TextBoxElement.cs
new file mode 100644
index 00000000..70d20843
--- /dev/null
+++ b/src/TestCentric/testcentric.gui/Elements/ControlElements/TextBoxElement.cs
@@ -0,0 +1,95 @@
+// ***********************************************************************
+// Copyright (c) Charlie Poole and TestCentric contributors.
+// Licensed under the MIT License. See LICENSE file in root directory.
+// ***********************************************************************
+
+using System.Windows.Forms;
+using System;
+
+namespace TestCentric.Gui.Elements
+{
+ ///
+ /// This class implements the IChanged interface for a TextBox control. It provides this additional functionality:
+ /// - show a PlaceHoder text if there's no text input
+ /// - Invoke the Changed event as soon as no further input is made within a short period of time.
+ ///
+ internal class TextBoxElement : ControlElement, IChanged
+ {
+ private Timer _typingTimer;
+
+ public event CommandHandler Changed;
+
+ public TextBoxElement(TextBox textBox, string placeHolderText)
+ : base(textBox)
+ {
+ TextBox = textBox;
+ PlaceHolderText = placeHolderText;
+ TextBox.TextChanged += OnTextChanged;
+
+ TextBox.LostFocus += OnTextBoxLostFocus;
+ TextBox.GotFocus += OnTextBoxGotFocus;
+
+ // Call LostFocus to set initial text and color
+ OnTextBoxLostFocus(null, EventArgs.Empty);
+ }
+
+ private string PlaceHolderText { get; set; }
+
+ private TextBox TextBox { get; }
+
+ private bool IsPlaceHolderTextShown { get; set; }
+
+ private void OnTextBoxGotFocus(object sender, EventArgs e)
+ {
+ // If the PlaceHolderText is shown, replace it with an empty text
+ if (IsPlaceHolderTextShown)
+ {
+ TextBox.Text = "";
+ TextBox.ForeColor = System.Drawing.Color.Black;
+ IsPlaceHolderTextShown = false;
+ }
+ }
+
+ private void OnTextBoxLostFocus(object sender, EventArgs e)
+ {
+ // If there's no text input, show the PlaceHolderText instead
+ string searchText = TextBox.Text;
+ if (string.IsNullOrEmpty(searchText) && !string.IsNullOrEmpty(PlaceHolderText))
+ {
+ IsPlaceHolderTextShown = true;
+ TextBox.Text = PlaceHolderText;
+ TextBox.ForeColor = System.Drawing.Color.LightGray;
+ }
+ }
+
+ private void OnTextChanged(object sender, EventArgs e)
+ {
+ if (IsPlaceHolderTextShown)
+ return;
+
+ if (_typingTimer == null)
+ {
+ _typingTimer = new Timer();
+ _typingTimer.Interval = 600;
+ _typingTimer.Tick += TypingTimerTimeout;
+ }
+
+ _typingTimer.Stop();
+ _typingTimer.Start();
+ }
+
+ private void TypingTimerTimeout(object sender, EventArgs e)
+ {
+ var timer = sender as Timer;
+ if (timer == null)
+ return;
+
+ // The timer must be stopped!
+ timer.Stop();
+ if (Changed != null)
+ Changed();
+
+ TextBox.Focus();
+ }
+ }
+}
diff --git a/src/TestCentric/testcentric.gui/Elements/ICategoryFilterSelection.cs b/src/TestCentric/testcentric.gui/Elements/ICategoryFilterSelection.cs
new file mode 100644
index 00000000..8a5459f5
--- /dev/null
+++ b/src/TestCentric/testcentric.gui/Elements/ICategoryFilterSelection.cs
@@ -0,0 +1,25 @@
+// ***********************************************************************
+// Copyright (c) Charlie Poole and TestCentric contributors.
+// Licensed under the MIT License. See LICENSE file in root directory.
+// ***********************************************************************
+
+using TestCentric.Gui.Model;
+
+namespace TestCentric.Gui.Elements
+{
+ ///
+ /// This interface is specialized for the selection of multiple test categories
+ ///
+ public interface ICategoryFilterSelection : IMultiSelection
+ {
+ ///
+ /// Init the filter selection
+ ///
+ void Init(ITestModel testModel);
+
+ ///
+ /// Close the filter selection dialog
+ ///
+ void Close();
+ }
+}
diff --git a/src/TestCentric/testcentric.gui/Elements/README.md b/src/TestCentric/testcentric.gui/Elements/README.md
index bfced766..89473f36 100644
--- a/src/TestCentric/testcentric.gui/Elements/README.md
+++ b/src/TestCentric/testcentric.gui/Elements/README.md
@@ -56,6 +56,10 @@ In the current implementation, there are two separate hierarchies of UI Elements
`IToolTip` is an optional interface, which may be implemented by any element able to get and set its own tooltip text. It provides a single property, `ToolTipText`. It is implemented by our `ToolTipElement` class, making it available to all our tooltip elements.
+### ICategoryFilterSelection
+
+`ICategoryFilterSelection` extends `IMultiSelection` to add specific methods for the test category selection.
+
## Control Elements
### ControlElement
@@ -78,6 +82,10 @@ A `ListBoxElement` wraps a Windows `ListBox` control and implements `IListBox`.
A `TabSelector` element wraps a Windows `TabControl` and implements `ISelection`.
+### TextBoxElement
+
+A `TextBoxElement` element wraps a Windows `TextBox` and implements `IChanged`. It shows a placeholder text as long as no text is entered and invokes the Changed event as soon as no further input is made within a short period of time.
+
## ToolStripItem Elements
### ToolStripElement
@@ -112,6 +120,10 @@ A `ToolStripElement` wraps any Windows `ToolStripItem` and implements `IViewElem
`ToolStripButtonElement` wraps a Windows `ToolStripButton` and implements both `IChecked` and `IChanged`.
+### ToolStripCategoryFilterButton
+
+`ToolStripCategoryFilterButton` wraps a Windows `ToolStripDropDownButton` and implements `ICategoryFilterSelection` for dedicated test category selection.
+
### ToolStripMenuElement
`ToolStripMenuElement` wraps a Windows `ToolStripMenuItem`, extending the base class to provide a collection of subordinate Windows menu items.
diff --git a/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripCategoryFilterButton.cs b/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripCategoryFilterButton.cs
new file mode 100644
index 00000000..49aaf385
--- /dev/null
+++ b/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripCategoryFilterButton.cs
@@ -0,0 +1,125 @@
+// ***********************************************************************
+// Copyright (c) Charlie Poole and TestCentric contributors.
+// Licensed under the MIT License. See LICENSE file in root directory.
+// ***********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using TestCentric.Gui.Dialogs;
+using TestCentric.Gui.Model;
+
+namespace TestCentric.Gui.Elements
+{
+ ///
+ /// This class is responsible to open the CategoryFilter dialog when the ToolStripDropDownButton is clicked
+ /// - it will open the dialog as a non-modal dialog which is displayed on top of the main form
+ /// - it will place the dialog below the ToolStripDropDownButton when opened for the first time
+ /// or restore the last position/size when opened for the second time
+ ///
+ internal class ToolStripCategoryFilterButton : ToolStripElement, ICategoryFilterSelection
+ {
+ public event CommandHandler SelectionChanged;
+
+ private ToolStripDropDownButton _button;
+ private ITestModel _model;
+ private CategoryFilterDialog _dialog;
+ private Point _dialogLocation;
+ private Size _dialogSize;
+ IEnumerable _selectedItems;
+
+ public ToolStripCategoryFilterButton(ToolStripDropDownButton button)
+ : base(button)
+ {
+ _button = button;
+ _button.Click += OnButtonClicked;
+ }
+
+ public IEnumerable SelectedItems
+ {
+ get => _selectedItems;
+ set
+ {
+ _selectedItems = value;
+ UpdateFont();
+ }
+ }
+
+ public void Init(ITestModel model)
+ {
+ _model = model;
+ SelectedItems = _model.TestCentricTestFilter.CategoryFilter.ToList();
+ }
+
+
+ public void Close()
+ {
+ _dialog?.Close();
+ }
+
+ protected void OnButtonClicked(object sender, EventArgs e)
+ {
+ // Dialog is already opened => just set the focus
+ if (_dialog != null)
+ {
+ _dialog.Focus();
+ return;
+ }
+
+ // Create dialog and set Owner property to place it on top of main form
+ _dialog = new CategoryFilterDialog();
+ _dialog.Owner = Form.ActiveForm;
+ SetDialogSizeAndPosition();
+
+ // Init dialog with available test categories and currently selected categories
+ var allCategories = _model.TestCentricTestFilter.AllCategories;
+ _dialog.Init(allCategories, _model.TestCentricTestFilter.CategoryFilter);
+
+ _dialog.ApplyButtonClicked += (selectedItems) =>
+ {
+ SelectedItems = selectedItems;
+ SelectionChanged?.Invoke();
+ };
+
+ // Dialog closing: save dialog position and size for next usage
+ _dialog.FormClosing += (s, args) =>
+ {
+ _dialogLocation = _dialog.Location;
+ _dialogSize = _dialog.Size;
+ _dialog = null;
+ };
+
+ // Show dialog non-modal
+ _dialog.Show();
+ }
+
+ private void SetDialogSizeAndPosition()
+ {
+ _dialog.StartPosition = FormStartPosition.Manual;
+
+ if (_dialogSize != default(Size))
+ {
+ // Restore previous position and size of dialog
+ _dialog.Size = _dialogSize;
+ _dialogLocation = _dialog.Location;
+ }
+ else
+ {
+ // Determine position of button on screen and place dialog below
+ var bounds = _button.AccessibilityObject.Bounds;
+ _dialog.Location = new Point(bounds.Left, bounds.Bottom);
+ }
+ }
+
+ private void UpdateFont()
+ {
+ var allCategories = _model.TestCentricTestFilter.AllCategories;
+
+ var style = allCategories.Except(SelectedItems).Any() ? FontStyle.Bold : FontStyle.Regular;
+ _button.Font = new Font(_button.Font, style);
+ }
+
+ }
+}
diff --git a/src/TestCentric/testcentric.gui/Presenters/TreeViewPresenter.cs b/src/TestCentric/testcentric.gui/Presenters/TreeViewPresenter.cs
index bb08aecc..4c55667b 100644
--- a/src/TestCentric/testcentric.gui/Presenters/TreeViewPresenter.cs
+++ b/src/TestCentric/testcentric.gui/Presenters/TreeViewPresenter.cs
@@ -65,6 +65,7 @@ private void WireUpEvents()
Strategy = _treeDisplayStrategyFactory.Create(_treeSettings.DisplayFormat, _view, _model);
_view.ShowCheckBoxes.Checked = visualStateLoaded ? visualState.ShowCheckBoxes : _treeSettings.ShowCheckBoxes;
+ _view.CategoryFilter.Init(_model);
Strategy.OnTestLoaded(ea.Test, visualState);
CheckPropertiesDisplay();
CheckXmlDisplay();
@@ -81,6 +82,7 @@ private void WireUpEvents()
_model.Events.TestUnloaded += (ea) =>
{
Strategy.OnTestUnloaded();
+ _view.CategoryFilter.Close();
};
_model.Events.TestsUnloading += ea =>
@@ -263,6 +265,11 @@ private void WireUpEvents()
_model.TestCentricTestFilter.TextFilter = text;
};
+ _view.CategoryFilter.SelectionChanged += () =>
+ {
+ _model.TestCentricTestFilter.CategoryFilter = _view.CategoryFilter.SelectedItems;
+ };
+
// Node selected in tree
//_treeView.SelectedNodesChanged += (nodes) =>
//{
diff --git a/src/TestCentric/testcentric.gui/Views/ITestTreeView.cs b/src/TestCentric/testcentric.gui/Views/ITestTreeView.cs
index cf181fc2..4aadadae 100644
--- a/src/TestCentric/testcentric.gui/Views/ITestTreeView.cs
+++ b/src/TestCentric/testcentric.gui/Views/ITestTreeView.cs
@@ -55,6 +55,8 @@ public interface ITestTreeView : IView
IChanged TextFilter { get; }
+ ICategoryFilterSelection CategoryFilter { get; }
+
void SetTestFilterVisibility(bool visible);
void EnableTestFilter(bool enable);
diff --git a/src/TestCentric/testcentric.gui/Views/TestTreeView.Designer.cs b/src/TestCentric/testcentric.gui/Views/TestTreeView.Designer.cs
index ab902a21..b974cb6f 100644
--- a/src/TestCentric/testcentric.gui/Views/TestTreeView.Designer.cs
+++ b/src/TestCentric/testcentric.gui/Views/TestTreeView.Designer.cs
@@ -41,6 +41,8 @@ private void InitializeComponent()
this.filterOutcomeNotRunButton = new System.Windows.Forms.ToolStripButton();
this.filterTextToolStrip = new System.Windows.Forms.ToolStrip();
this.filterTextBox = new StretchToolStripTextBox();
+ this.filterSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ this.filterByCategory = new System.Windows.Forms.ToolStripDropDownButton();
this.testTreeContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
this.runMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.debugMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -117,6 +119,13 @@ private void InitializeComponent()
this.filterOutcomeNotRunButton.ToolTipText = "Show all tests not run yet";
this.filterOutcomeNotRunButton.CheckOnClick = true;
//
+ // filterByCategory
+ //
+ this.filterByCategory.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
+ this.filterByCategory.Name = "filterByCategory";
+ this.filterByCategory.Text = "Filter by category";
+ this.filterByCategory.ToolTipText = "Filter tests by category";
+ //
// filterToolStrip
//
this.filterToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -125,6 +134,8 @@ private void InitializeComponent()
this.filterOutcomeFailedButton,
this.filterOutcomeWarningButton,
this.filterOutcomeNotRunButton,
+ this.filterSeparator1,
+ this.filterByCategory,
});
this.filterToolStrip.Location = new System.Drawing.Point(0, 0);
this.filterToolStrip.Name = "filterToolStrip";
@@ -267,6 +278,8 @@ private void InitializeComponent()
private System.Windows.Forms.ToolStripButton filterOutcomeFailedButton;
private System.Windows.Forms.ToolStripButton filterOutcomeWarningButton;
private System.Windows.Forms.ToolStripButton filterOutcomeNotRunButton;
+ private System.Windows.Forms.ToolStripSeparator filterSeparator1;
+ private System.Windows.Forms.ToolStripDropDownButton filterByCategory;
private System.Windows.Forms.ToolStrip filterTextToolStrip;
private System.Windows.Forms.ToolStripTextBox filterTextBox;
private System.Windows.Forms.ToolStripMenuItem runMenuItem;
diff --git a/src/TestCentric/testcentric.gui/Views/TestTreeView.cs b/src/TestCentric/testcentric.gui/Views/TestTreeView.cs
index 3167d029..0f136587 100644
--- a/src/TestCentric/testcentric.gui/Views/TestTreeView.cs
+++ b/src/TestCentric/testcentric.gui/Views/TestTreeView.cs
@@ -50,6 +50,7 @@ public TestTreeView()
ViewAsXmlCommand = new CommandMenuElement(viewAsXmlMenuItem);
OutcomeFilter = new MultiCheckedToolStripButtonGroup(new[] { filterOutcomePassedButton, filterOutcomeFailedButton, filterOutcomeWarningButton, filterOutcomeNotRunButton });
TextFilter = new ToolStripTextBoxElement(filterTextBox, "Filter...");
+ CategoryFilter = new ToolStripCategoryFilterButton(filterByCategory);
TreeView = treeView;
// NOTE: We use MouseDown here rather than MouseUp because
@@ -127,6 +128,7 @@ public bool CheckBoxes
public TreeView TreeView { get; private set; }
public IMultiSelection OutcomeFilter { get; private set; }
+ public ICategoryFilterSelection CategoryFilter { get; private set; }
public IChanged TextFilter { get; private set; }
diff --git a/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreLoaded.cs b/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreLoaded.cs
index be95fd6e..c7d47c5b 100644
--- a/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreLoaded.cs
+++ b/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreLoaded.cs
@@ -244,6 +244,18 @@ public void TestLoaded_WithVisualState_TestListGroupBySetting_IsUpdatedFromVisua
Assert.That(_model.Settings.Gui.TestTree.FixtureList.GroupBy, Is.EqualTo("DURATION")); // Assert that fixtureList groupBy was not changed accidently
}
+ [Test]
+ public void TestLoaded_CategoryFilter_IsInitialized()
+ {
+ // Act: load tests
+ TestNode testNode = new TestNode("");
+ _model.LoadedTests.Returns(testNode);
+ FireTestLoadedEvent(testNode);
+
+ // Assert
+ _view.CategoryFilter.Received().Init(_model);
+ }
+
// TODO: Version 1 Test - Make it work if needed.
//[Test]
//[Platform(Exclude = "Linux", Reason = "Display issues")]
diff --git a/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreUnloaded.cs b/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreUnloaded.cs
index 580a81d9..aeedd62b 100644
--- a/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreUnloaded.cs
+++ b/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreUnloaded.cs
@@ -5,6 +5,7 @@
using NUnit.Framework;
using NSubstitute;
+using TestCentric.Gui.Model;
namespace TestCentric.Gui.Presenters.TestTree
{
@@ -13,6 +14,8 @@ public class WhenTestsAreUnloaded : TreeViewPresenterTestBase
[SetUp]
public void SimulateTestUnload()
{
+ _settings.Gui.TestTree.DisplayFormat = "NUNIT_TREE";
+
ClearAllReceivedCalls();
_model.HasTests.Returns(false);
@@ -20,6 +23,16 @@ public void SimulateTestUnload()
FireTestUnloadedEvent();
}
+ [Test]
+ public void TestUnloaded_CategoryFilter_IsClosed()
+ {
+ // Act: unload tests
+ FireTestUnloadedEvent();
+
+ // Assert
+ _view.CategoryFilter.Received().Close();
+ }
+
#if NYI // Add after implementation of project or package saving
[TestCase("NewProjectCommand", true)]
[TestCase("OpenProjectCommand", true)]