From 82995543058c4e905a8a6bd11a549540ef3597f1 Mon Sep 17 00:00:00 2001 From: Peter Wagner Date: Sat, 4 Apr 2026 10:15:35 +0100 Subject: [PATCH] * Is it time to bring over `AdvancedDataGridView` * Implements #3301 --- Documents/Changelog/Changelog.md | 2 + .../KryptonAdvancedDataGridView.cs | 1520 ++++++++++ ...ryptonAdvancedDataGridViewSearchToolBar.cs | 653 +++++ .../Controls Toolkit/MenuStrip.cs | 2537 +++++++++++++++++ .../Controls Toolkit/TreeNodeItemSelector.cs | 191 ++ .../VisualCustomFilterForm.Designer.cs | 176 ++ .../VisualCustomFilterForm.cs | 527 ++++ .../VisualCustomFilterForm.resx | 120 + ...ataGridViewSearchToolBarSearchEventArgs.cs | 64 + .../EventArgs/ColumnHeaderCellEventArgs.cs | 33 + ...GridViewSearchToolBarSearchEventHandler.cs | 17 + .../General/ColumnHeaderCellEventHandler.cs | 17 + .../General/Definitions.cs | 283 ++ .../General/KryptonColumnHeaderCell.cs | 715 +++++ .../Krypton.Utilities/Global/Globals.cs | 5 + .../Krypton.Utilities/GlobalUsings.cs | 7 - .../Properties/Resources.Designer.cs | 190 ++ .../Properties/Resources.resx | 57 + .../Resources/ColumnHeader_Filtered.png | Bin 0 -> 351 bytes .../ColumnHeader_FilteredAndOrderedASC.png | Bin 0 -> 352 bytes .../ColumnHeader_FilteredAndOrderedDESC.png | Bin 0 -> 371 bytes .../Resources/ColumnHeader_OrderedASC.png | Bin 0 -> 268 bytes .../Resources/ColumnHeader_OrderedDESC.png | Bin 0 -> 279 bytes .../Resources/ColumnHeader_SavedFilters.png | Bin 0 -> 285 bytes .../Resources/ColumnHeader_UnFiltered.png | Bin 0 -> 242 bytes .../Resources/MenuStrip_OrderASCbool.png | Bin 0 -> 364 bytes .../Resources/MenuStrip_OrderASCnum.png | Bin 0 -> 390 bytes .../Resources/MenuStrip_OrderASCtxt.png | Bin 0 -> 303 bytes .../Resources/MenuStrip_OrderDESCbool.png | Bin 0 -> 369 bytes .../Resources/MenuStrip_OrderDESCnum.png | Bin 0 -> 374 bytes .../Resources/MenuStrip_OrderDESCtxt.png | Bin 0 -> 300 bytes .../Resources/MenuStrip_ResizeGrip.png | Bin 0 -> 181 bytes .../SearchToolBar_ButtonCaseSensitive.png | Bin 0 -> 452 bytes .../Resources/SearchToolBar_ButtonClose.png | Bin 0 -> 225 bytes .../SearchToolBar_ButtonFromBegin.png | Bin 0 -> 469 bytes .../Resources/SearchToolBar_ButtonSearch.png | Bin 0 -> 632 bytes .../SearchToolBar_ButtonWholeWord.png | Bin 0 -> 575 bytes .../AdvancedDataGridViewTest.Designer.cs | 401 +++ .../TestForm/AdvancedDataGridViewTest.cs | 483 ++++ .../TestForm/AdvancedDataGridViewTest.resx | 120 + .../TestForm/StartScreen.cs | 1 + .../TestForm/flag-green_24.png | Bin 0 -> 978 bytes .../TestForm/flag-red_24.png | Bin 0 -> 942 bytes 43 files changed, 8112 insertions(+), 7 deletions(-) create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridView.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridViewSearchToolBar.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/MenuStrip.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/TreeNodeItemSelector.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.Designer.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.resx create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/AdvancedDataGridViewSearchToolBarSearchEventArgs.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/ColumnHeaderCellEventArgs.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/AdvancedDataGridViewSearchToolBarSearchEventHandler.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/ColumnHeaderCellEventHandler.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/Definitions.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/KryptonColumnHeaderCell.cs delete mode 100644 Source/Krypton Components/Krypton.Utilities/GlobalUsings.cs create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_Filtered.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_FilteredAndOrderedASC.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_FilteredAndOrderedDESC.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedASC.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedDESC.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_SavedFilters.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_UnFiltered.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCbool.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCnum.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCtxt.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCbool.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCnum.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCtxt.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_ResizeGrip.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonCaseSensitive.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonClose.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonFromBegin.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonSearch.png create mode 100644 Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonWholeWord.png create mode 100644 Source/Krypton Components/TestForm/AdvancedDataGridViewTest.Designer.cs create mode 100644 Source/Krypton Components/TestForm/AdvancedDataGridViewTest.cs create mode 100644 Source/Krypton Components/TestForm/AdvancedDataGridViewTest.resx create mode 100644 Source/Krypton Components/TestForm/flag-green_24.png create mode 100644 Source/Krypton Components/TestForm/flag-red_24.png diff --git a/Documents/Changelog/Changelog.md b/Documents/Changelog/Changelog.md index 84a39233a1..673ddfc69f 100644 --- a/Documents/Changelog/Changelog.md +++ b/Documents/Changelog/Changelog.md @@ -45,6 +45,8 @@ ## 2026-11-xx - Build 2611 (V110 Nightly) - November 2026 +* Implemented [#3301](https://github.com/Krypton-Suite/Standard-Toolkit/issues/3301), Is it time to bring over `AdvancedDataGridView` + * To use, you will need to download the `Krypton.Standard.Toolkit` NuGet package, as this control is part of the `Krypton.Utilities` assembly. * Resolved [#3227](https://github.com/Krypton-Suite/Standard-Toolkit/issues/3227), `KryptonDockingManager.LoadConfigFromArray` throws exception * Resolved [#3225](https://github.com/Krypton-Suite/Standard-Toolkit/issues/3225), Ribbon large button image-to-text separator not DPI-scaled * Resolved [#3256](https://github.com/Krypton-Suite/Standard-Toolkit/issues/3256), Tree View Event is Crashing diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridView.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridView.cs new file mode 100644 index 0000000000..821f516592 --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridView.cs @@ -0,0 +1,1520 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +// Control specific using statements + +#if NETFRAMEWORK +using System.Web.Script.Serialization; +#else +using System.Text.Json; +#endif + +namespace Krypton.Utilities; + +/// +/// Extends with Excel-style column filtering, multi-column sort composition, +/// and optional integration with for in-grid search. +/// +/// +/// +/// Filter and sort are applied by composing expressions and assigning them to the data source: +/// / when is a ; +/// / when it is a ; +/// or row filter and sort when it is a (non-null default view). +/// +/// +/// Use and to observe changes; set or to skip updating the bound source. +/// +/// +/// +/// +/// KryptonAdvancedDataGridView developer guide +[DesignerCategory("code")] +public class KryptonAdvancedDataGridView : KryptonDataGridView +{ + #region Instance Fields + + private readonly List _sortOrderList = []; + private readonly List _filterOrderList = []; + private readonly List _filteredColumns = []; + private List _menuStripToDispose = []; + + private bool _loadedFilter; + private string? _sortString; + private string? _filterString; + + private bool _sortStringChangedInvokeBeforeDatasourceUpdate = true; + private bool _filterStringChangedInvokeBeforeDatasourceUpdate = true; + + #endregion + + #region Events + + /// + /// Provides data for . + /// + public class SortEventArgs : EventArgs + { + /// + /// Gets or sets the composed ADO.NET-style sort expression for the bound list (e.g. ). + /// + public string? SortString { get; set; } + + /// + /// When , the control does not assign the sort to the data source. + /// + public bool Cancel { get; set; } + + /// Initializes a new instance of the class. + public SortEventArgs() + { + SortString = null; + Cancel = false; + } + } + + /// + /// Provides data for . + /// + public class FilterEventArgs : EventArgs + { + /// + /// Gets or sets the composed row filter expression (e.g. or ). + /// + public string? FilterString { get; set; } + + /// + /// When , the control does not assign the filter to the data source. + /// + public bool Cancel { get; set; } + + /// Initializes a new instance of the class. + public FilterEventArgs() + { + FilterString = null; + Cancel = false; + } + } + + /// + /// Occurs when the aggregate sort expression changes, before or after the data source is updated depending on . + /// + public event EventHandler? SortStringChanged; + + /// + /// Occurs when the aggregate filter expression changes, before or after the data source is updated depending on . + /// + public event EventHandler? FilterStringChanged; + + #endregion + + #region Identity + + /// Initializes a new instance of the class. + public KryptonAdvancedDataGridView() + { + //System.Windows.Forms.RightToLeft = System.Windows.Forms.RightToLeft.No; + } + + #endregion + + #region Implementation + + /// + /// Default UI strings for column header menus and the custom filter dialog. Keys are the string names of members (for example nameof(TranslationKey.KryptonAdvancedDataGridViewSortTextAscending)). + /// Merge overrides with or . + /// + public static Dictionary Translations = new() + { + { nameof(TranslationKey.KryptonAdvancedDataGridViewSortDateTimeAscending), "Sort Oldest to Newest" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewSortDateTimeDescending), "Sort Newest to Oldest" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewSortBoolAscending), "Sort by False/True" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewSortBoolDescending), "Sort by True/False" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewSortNumAscending), "Sort Smallest to Largest" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewSortNumDescending), "Sort Largest to Smallest" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewSortTextAscending), "Sort А to Z" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewSortTextDescending), "Sort Z to A" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewAddCustomFilter), "Add a Custom Filter" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewCustomFilter), "Custom Filter" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewClearFilter), "Clear Filter" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewClearSort), "Clear Sort" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewButtonFilter), "Filter" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewButtonUndoFilter), "Cancel" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectAll), "(Select All)" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectEmpty), "(Blanks)" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectTrue), "True" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectFalse), "False" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewFilterChecklistDisable), "Filter list is disabled" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewEquals), "equals" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual), "does not equal" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThan), "earlier than" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThanOrEqualTo), "earlier than or equal to" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThan), "later than"}, + { nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThanOrEqualTo), "later than or equal to" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewBetween), "between" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThan), "greater than" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThanOrEqualTo), "greater than or equal to" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewLessThan), "less than" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewLessThanOrEqualTo), "less than or equal to" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewBeginsWith), "begins with" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotBeginWith), "does not begin with" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewEndsWith), "ends with" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEndWith), "does not end with" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewContains), "contains" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotContain), "does not contain" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewInvalidValue), "Invalid Value" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewFilterStringDescription), "Show rows where value {0} \"{1}\"" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewFormTitle), "Custom Filter" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewLabelColumnNameText), "Show rows where value" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewLabelAnd), "And" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewButtonOk), "OK" }, + { nameof(TranslationKey.KryptonAdvancedDataGridViewButtonCancel), "Cancel" } + }; + + #endregion + + #region Implemntation + + #region translations methods + + /// + /// Merges entries into for keys that already exist; unknown keys are ignored. + /// + /// Localized strings, keyed by the same names as . + public static void SetTranslations(IDictionary? translations) + { + //set localization strings + if (translations != null) + { + foreach (KeyValuePair translation in translations) + { + if (Translations.ContainsKey(translation.Key)) + { + Translations[translation.Key] = translation.Value; + } + } + } + } + + /// Returns the live dictionary. + /// The static translation map used by filter and sort UI. + public static IDictionary GetTranslations() + { + return Translations; + } + + /// + /// Loads a JSON object of string keys and string values, merges recognized keys, and fills any missing keys from . + /// + /// Path to the JSON file. + /// A new dictionary suitable for passing to . + public static IDictionary LoadTranslationsFromFile(string filename) + { + IDictionary ret = new Dictionary(); + + if (!String.IsNullOrEmpty(filename)) + { + //deserialize the file + try + { + string jsonText = File.ReadAllText(filename); +#if NETFRAMEWORK + Dictionary translations = + new JavaScriptSerializer().Deserialize>(jsonText); +#else + Dictionary? translations = + JsonSerializer.Deserialize>(jsonText); +#endif + foreach (KeyValuePair translation in translations!) + { + if (!ret.ContainsKey(translation.Key) && Translations.ContainsKey(translation.Key)) + { + ret.Add(translation.Key, translation.Value); + } + } + } + catch (Exception e) + { + KryptonExceptionHandler.CaptureException(e); + } + } + + //add default translations if not in files + foreach (KeyValuePair translation in GetTranslations()) + { + if (!ret.ContainsKey(translation.Key)) + { + ret.Add(translation.Key, translation.Value); + } + } + + return ret; + } + + #endregion + + + #region public Helper methods + + /// Sets to to reduce flicker. + public void SetDoubleBuffered() + { + DoubleBuffered = true; + } + + #endregion + + + #region public Filter and Sort methods + + /// + /// Gets or sets whether is raised before (default) or after the sort is applied to the data source. + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool SortStringChangedInvokeBeforeDatasourceUpdate + { + get => _sortStringChangedInvokeBeforeDatasourceUpdate; + set => _sortStringChangedInvokeBeforeDatasourceUpdate = value; + } + + /// + /// Gets or sets whether is raised before (default) or after the filter is applied to the data source. + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool FilterStringChangedInvokeBeforeDatasourceUpdate + { + get => _filterStringChangedInvokeBeforeDatasourceUpdate; + set => _filterStringChangedInvokeBeforeDatasourceUpdate = value; + } + + /// + /// Disable a Filter and Sort on a DataGridViewColumn + /// + /// + public void DisableFilterAndSort(DataGridViewColumn column) + { + if (Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + if (cell.FilterAndSortEnabled && (cell.SortString!.Length > 0 || cell.FilterString!.Length > 0)) + { + CleanFilter(true); + cell.FilterAndSortEnabled = false; + } + else + { + cell.FilterAndSortEnabled = false; + } + + _filterOrderList.Remove(column.Name); + _sortOrderList.Remove(column.Name); + _filteredColumns.Remove(column.Name); + } + } + } + + /// + /// Enable a Filter and Sort on a DataGridViewColumn + /// + /// + public void EnableFilterAndSort(DataGridViewColumn column) + { + if (Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + if (!cell.FilterAndSortEnabled && (cell.FilterString!.Length > 0 || cell.SortString!.Length > 0)) + { + CleanFilter(true); + } + + cell.FilterAndSortEnabled = true; + _filteredColumns.Remove(column.Name); + + SetFilterDateAndTimeEnabled(column, cell.IsFilterDateAndTimeEnabled); + SetSortEnabled(column, cell.IsSortEnabled); + SetFilterEnabled(column, cell.IsFilterEnabled); + } + else + { + column.SortMode = DataGridViewColumnSortMode.Programmatic; + cell = new KryptonColumnHeaderCell(column.HeaderCell, true); + cell.SortChanged += Cell_SortChanged; + cell.FilterChanged += Cell_FilterChanged; + cell.FilterPopup += Cell_FilterPopup; + column.MinimumWidth = cell.MinimumSize.Width; + if (ColumnHeadersHeight < cell.MinimumSize.Height) + { + ColumnHeadersHeight = cell.MinimumSize.Height; + } + + column.HeaderCell = cell; + } + } + } + + /// + /// Enabled or disable Filter and Sort capabilities on a DataGridViewColumn + /// + /// + /// + public void SetFilterAndSortEnabled(DataGridViewColumn column, bool enabled) + { + if (enabled) + { + EnableFilterAndSort(column); + } + else + { + DisableFilterAndSort(column); + } + } + + /// + /// Disable a Filter checklist on a DataGridViewColumn + /// + /// + public void DisableFilterChecklist(DataGridViewColumn? column) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SetFilterChecklistEnabled(false); + } + } + } + + /// + /// Enable a Filter checklist on a DataGridViewColumn + /// + /// + public void EnableFilterChecklist(DataGridViewColumn? column) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SetFilterChecklistEnabled(true); + } + } + } + + /// + /// Enabled or disable Filter checklist capabilities on a DataGridViewColumn + /// + /// + /// + public void SetFilterChecklistEnabled(DataGridViewColumn? column, bool enabled) + { + if (enabled) + { + EnableFilterChecklist(column); + } + else + { + DisableFilterChecklist(column); + } + } + + /// + /// Set Filter checklist nodes max on a DataGridViewColumn + /// + /// + /// + public void SetFilterChecklistNodesMax(DataGridViewColumn column, int maxNodes) + { + if (Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SetFilterChecklistNodesMax(maxNodes); + } + } + } + + /// + /// Set Filter checklist nodes max + /// + /// + public void SetFilterChecklistNodesMax(int maxNodes) + { + foreach (KryptonColumnHeaderCell c in FilterableCells) + { + c.SetFilterChecklistNodesMax(maxNodes); + } + } + + /// + /// Enable or disable Filter checklist nodes max on a DataGridViewColumn + /// + /// + /// + public void EnabledFilterChecklistNodesMax(DataGridViewColumn column, bool enabled) + { + if (Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.EnabledFilterChecklistNodesMax(enabled); + } + } + } + + /// + /// Enable or disable Filter checklist nodes max + /// + /// + public void EnabledFilterChecklistNodesMax(bool enabled) + { + foreach (KryptonColumnHeaderCell c in FilterableCells) + { + c.EnabledFilterChecklistNodesMax(enabled); + } + } + + /// + /// Disable a Filter custom on a DataGridViewColumn + /// + /// + public void DisableFilterCustom(DataGridViewColumn? column) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SetFilterCustomEnabled(false); + } + } + } + + /// + /// Enable a Filter custom on a DataGridViewColumn + /// + /// + public void EnableFilterCustom(DataGridViewColumn? column) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SetFilterCustomEnabled(true); + } + } + } + + /// + /// Enabled or disable Filter custom capabilities on a DataGridViewColumn + /// + /// + /// + public void SetFilterCustomEnabled(DataGridViewColumn? column, bool enabled) + { + if (enabled) + { + EnableFilterCustom(column); + } + else + { + DisableFilterCustom(column); + } + } + + /// + /// Set nodes to enable TextChanged delay on filter checklist on a DataGridViewColumn + /// + /// + /// + public void SetFilterChecklistTextFilterTextChangedDelayNodes(DataGridViewColumn? column, int numNodes) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.TextFilterTextChangedDelayNodes = numNodes; + } + } + } + + /// + /// Set nodes to enable TextChanged delay on filter checklist + /// + /// + public void SetFilterChecklistTextFilterTextChangedDelayNodes(int numNodes) + { + foreach (KryptonColumnHeaderCell c in FilterableCells) + { + c.TextFilterTextChangedDelayNodes = numNodes; + } + } + + /// + /// Disable TextChanged delay on filter checklist on a DataGridViewColumn + /// + /// + public void SetFilterChecklistTextFilterTextChangedDelayDisabled(DataGridViewColumn column) + { + if (Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SetTextFilterTextChangedDelayNodesDisabled(); + } + } + } + + /// + /// Disable TextChanged delay on filter checklist + /// + public void SetFilterChecklistTextFilterTextChangedDelayDisabled() + { + foreach (KryptonColumnHeaderCell c in FilterableCells) + { + c.SetTextFilterTextChangedDelayNodesDisabled(); + } + } + + /// + /// Set TextChanged delay milliseconds on filter checklist on a DataGridViewColumn + /// + /// + /// + public void SetFilterChecklistTextFilterTextChangedDelayMs(DataGridViewColumn? column, int milliseconds) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SetTextFilterTextChangedDelayMs(milliseconds); + } + } + } + + /// + /// Set TextChanged delay milliseconds on filter checklist + /// + public void SetFilterChecklistTextFilterTextChangedDelayMs(int milliseconds) + { + foreach (KryptonColumnHeaderCell c in FilterableCells) + { + c.SetTextFilterTextChangedDelayMs(milliseconds); + } + } + + /// + /// Applies saved filter and sort expressions and marks header cells as loaded until the user changes filter state. + /// + /// Aggregate filter string, or to skip. + /// Aggregate sort string, or to skip. + public void LoadFilterAndSort(string? filter, string? sorting) + { + foreach (KryptonColumnHeaderCell c in FilterableCells) + { + c.SetLoadedMode(true); + } + + _filteredColumns.Clear(); + + _filterOrderList.Clear(); + _sortOrderList.Clear(); + + if (filter != null) + { + FilterString = filter; + } + + if (sorting != null) + { + SortString = sorting; + } + + _loadedFilter = true; + } + + /// Clears loaded mode, internal order lists, and all column filter and sort state. + public void CleanFilterAndSort() + { + foreach (KryptonColumnHeaderCell c in FilterableCells) + { + c.SetLoadedMode(false); + } + + _filteredColumns.Clear(); + _filterOrderList.Clear(); + _sortOrderList.Clear(); + + _loadedFilter = false; + + CleanFilter(); + CleanSort(); + } + + /// + /// Enables or disables NOT IN-style semantics for checklist filters on all filterable columns. + /// + /// to use NOT IN logic; otherwise . + public void SetMenuStripFilterNotInLogic(bool enabled) + { + foreach (KryptonColumnHeaderCell c in FilterableCells) + { + c.IsMenuStripFilterNOTINLogicEnabled = enabled; + } + } + + /// + /// Gets or sets whether new columns receive filter and sort UI. Also used when replacing header cells in . + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool FilterAndSortEnabled + { + get => _filterAndSortEnabled; + set => _filterAndSortEnabled = value; + } + private bool _filterAndSortEnabled = true; + + private bool _filterAndSortOnBitmapColumns; + + /// + /// Gets or sets whether filter and sort UI is shown on columns whose is . + /// Default is (image columns have no header drop-down). + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool FilterAndSortOnBitmapColumns + { + get => _filterAndSortOnBitmapColumns; + set + { + if (_filterAndSortOnBitmapColumns == value) + { + return; + } + + _filterAndSortOnBitmapColumns = value; + for (int i = 0; i < Columns.Count; i++) + { + InvalidateCell(i, -1); + } + } + } + + #endregion + + + #region public Sort methods + + /// + /// Gets the composed multi-column sort expression. Applied to , + /// , or when the data source matches. + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string? SortString + { + get => !string.IsNullOrEmpty(_sortString) ? _sortString : string.Empty; + private set + { + string? old = value; + if (old != _sortString) + { + _sortString = value; + + TriggerSortStringChanged(); + } + } + } + + /// + /// Raises (subject to ) and applies the current sort to the data source when not canceled. + /// + public void TriggerSortStringChanged() + { + //call event handler if one is attached + SortEventArgs sortEventArgs = new SortEventArgs + { + SortString = _sortString, + Cancel = false + }; + //invoke SortStringChanged + if (_sortStringChangedInvokeBeforeDatasourceUpdate) + { + if (SortStringChanged != null) + { + SortStringChanged.Invoke(this, sortEventArgs); + } + } + //sort datasource + if (sortEventArgs.Cancel == false) + { + if (DataSource is BindingSource datasource) + { + datasource.Sort = sortEventArgs.SortString; + } + else if (DataSource is DataView dataView) + { + dataView.Sort = sortEventArgs.SortString ?? string.Empty; + } + else if (DataSource is DataTable { DefaultView: not null } dataTable) + { + dataTable.DefaultView.Sort = sortEventArgs.SortString ?? string.Empty; + } + } + //invoke SortStringChanged + if (!_sortStringChangedInvokeBeforeDatasourceUpdate) + { + if (SortStringChanged != null) + { + SortStringChanged.Invoke(this, sortEventArgs); + } + } + } + + /// + /// Enabled or disable Sort capabilities for a DataGridViewColumn + /// + /// + /// + public void SetSortEnabled(DataGridViewColumn? column, bool enabled) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SetSortEnabled(enabled); + } + } + } + + /// + /// Applies ascending sort for the column via the header menu logic. + /// + /// The column to sort, or to no-op. + public void SortAscending(DataGridViewColumn? column) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SortASC(); + } + } + } + + /// + /// Applies descending sort for the column via the header menu logic. + /// + /// The column to sort, or to no-op. + public void SortDescending(DataGridViewColumn? column) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SortDESC(); + } + } + } + + /// + /// Clean all Sort on specific column + /// + /// + /// + public void CleanSort(DataGridViewColumn? column, bool fireEvent) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell && FilterableCells.Contains(cell)) + { + cell.CleanSort(); + //remove column from sorted list + _sortOrderList.Remove(column.Name); + } + } + + if (fireEvent) + { + SortString = BuildSortString(); + } + else + { + _sortString = BuildSortString(); + } + } + + /// + /// Clean all Sort on specific column + /// + /// + public void CleanSort(DataGridViewColumn? column) + { + CleanSort(column, true); + } + + /// + /// Clean all Sort on all columns + /// + /// + public void CleanSort(bool fireEvent) + { + foreach (KryptonColumnHeaderCell c in FilterableCells) + { + c.CleanSort(); + } + + _sortOrderList.Clear(); + + if (fireEvent) + { + SortString = null; + } + else + { + _sortString = null; + } + } + + /// + /// Clean all Sort on all columns + /// + public void CleanSort() + { + CleanSort(true); + } + + #endregion + + + #region public Filter methods + + /// + /// Gets the composed row filter (multi-column conditions combined with AND). Applied to , , or the table default view when supported. + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string? FilterString + { + get => !String.IsNullOrEmpty(_filterString) ? _filterString : ""; + private set + { + string? old = value; + if (old != _filterString) + { + _filterString = value; + + TriggerFilterStringChanged(); + } + } + } + + /// + /// Raises (subject to ) and applies the current filter to the data source when not canceled. + /// + public void TriggerFilterStringChanged() + { + //call event handler if one is attached + FilterEventArgs filterEventArgs = new FilterEventArgs + { + FilterString = _filterString, + Cancel = false + }; + //invoke FilterStringChanged + if (_filterStringChangedInvokeBeforeDatasourceUpdate) + { + if (FilterStringChanged != null) + { + FilterStringChanged.Invoke(this, filterEventArgs); + } + } + //filter datasource + if (filterEventArgs.Cancel == false) + { + if (DataSource is BindingSource bindingsource) + { + bindingsource.Filter = filterEventArgs.FilterString; + } + else if (DataSource is DataView dataview) + { + dataview.RowFilter = filterEventArgs.FilterString; + } + else if (DataSource is DataTable { DefaultView: not null } datatable) + { + datatable.DefaultView.RowFilter = filterEventArgs.FilterString; + } + } + //invoke FilterStringChanged + if (!_filterStringChangedInvokeBeforeDatasourceUpdate) + { + if (FilterStringChanged != null) + { + FilterStringChanged.Invoke(this, filterEventArgs); + } + } + } + + /// + /// Set FilterDateAndTime status for a DataGridViewColumn + /// + /// + /// + public void SetFilterDateAndTimeEnabled(DataGridViewColumn? column, bool enabled) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.IsFilterDateAndTimeEnabled = enabled; + } + } + } + + /// + /// Enable or disable Filter capabilities for a DataGridViewColumn + /// + /// + /// + public void SetFilterEnabled(DataGridViewColumn column, bool enabled) + { + if (Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SetFilterEnabled(enabled); + } + } + } + + /// + /// Enable or disable Text filter on checklist remove node mode for a DataGridViewColumn + /// + /// + /// + public void SetChecklistTextFilterRemoveNodesOnSearchMode(DataGridViewColumn? column, bool enabled) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SetChecklistTextFilterRemoveNodesOnSearchMode(enabled); + } + } + } + + /// + /// Clean Filter on specific column + /// + /// + /// + public void CleanFilter(DataGridViewColumn column, bool fireEvent) + { + if (Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.CleanFilter(); + //remove column from filtered list + _filterOrderList.Remove(column.Name); + } + } + + if (fireEvent) + { + FilterString = BuildFilterString(); + } + else + { + _filterString = BuildFilterString(); + } + } + + /// + /// Clean Filter on specific column + /// + /// + public void CleanFilter(DataGridViewColumn column) + { + CleanFilter(column, true); + } + + /// + /// Clean Filter on all columns + /// + /// + public void CleanFilter(bool fireEvent) + { + foreach (KryptonColumnHeaderCell c in FilterableCells) + { + c.CleanFilter(); + } + _filterOrderList.Clear(); + + if (fireEvent) + { + FilterString = null; + } + else + { + _filterString = null; + } + } + + /// Clears filters on all columns and raises the aggregate filter change. + public void CleanFilter() + { + CleanFilter(true); + } + + /// + /// Set the text filter search nodes behaviour + /// + public void SetTextFilterRemoveNodesOnSearch(DataGridViewColumn? column, bool enabled) + { + if (column != null && Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.DoesTextFilterRemoveNodesOnSearch = enabled; + } + } + } + + /// + /// Get the text filter search nodes behaviour + /// + public bool? GetTextFilterRemoveNodesOnSearch(DataGridViewColumn column) + { + bool? ret = null; + if (Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + ret = cell.DoesTextFilterRemoveNodesOnSearch; + } + } + return ret; + } + + #endregion + + + #region public Find methods + + /// + /// Searches displayed cell text from a start position; typically used with for find-next behavior. + /// + /// Text to match against . + /// Bound column to search, or to search all visible columns. + /// Starting row index (clamped to zero or greater). + /// Starting column index when searching all columns. + /// When , requires an exact match of the formatted string. + /// When , comparison is case-sensitive. + /// The first matching cell, or if none. + public DataGridViewCell? FindCell(string? valueToFind, string? columnName, int rowIndex, int columnIndex, bool isWholeWordSearch, bool isCaseSensitive) + { + if (valueToFind != null && RowCount > 0 && ColumnCount > 0 && (columnName == null || (Columns.Contains(columnName) && Columns[columnName]!.Visible))) + { + rowIndex = Math.Max(0, rowIndex); + + if (!isCaseSensitive) + { + valueToFind = valueToFind.ToLower(); + } + + if (columnName != null) + { + int c = Columns[columnName]!.Index; + if (columnIndex > c) + { + rowIndex++; + } + + for (int r = rowIndex; r < RowCount; r++) + { + string value = Rows[r].Cells[c].FormattedValue?.ToString() ?? string.Empty; + if (!isCaseSensitive) + { + value = value.ToLower(); + } + + if ((!isWholeWordSearch && value.Contains(valueToFind)) || value.Equals(valueToFind)) + { + return Rows[r].Cells[c]; + } + } + } + else + { + columnIndex = Math.Max(0, columnIndex); + + for (int r = rowIndex; r < RowCount; r++) + { + for (int c = columnIndex; c < ColumnCount; c++) + { + if (!Rows[r].Cells[c].Visible) + { + continue; + } + + string value = Rows[r].Cells[c].FormattedValue?.ToString() ?? string.Empty; + if (!isCaseSensitive) + { + value = value.ToLower(); + } + + if ((!isWholeWordSearch && value.Contains(valueToFind)) || value.Equals(valueToFind)) + { + return Rows[r].Cells[c]; + } + } + + columnIndex = 0; + } + } + } + + return null; + } + + #endregion + + + #region public Cell methods + + /// Opens the filter and sort drop-down for the specified column programmatically. + /// The column whose header menu should open. + public void ShowMenuStrip(DataGridViewColumn column) + { + if (Columns.Contains(column)) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + Cell_FilterPopup(cell, new ColumnHeaderCellEventArgs(cell.MenuStrip, column)); + } + } + } + + #endregion + + + #region cells methods + + /// + /// Get all columns + /// + private IEnumerable FilterableCells => + from DataGridViewColumn c in Columns + where c.HeaderCell is KryptonColumnHeaderCell + select c.HeaderCell as KryptonColumnHeaderCell; + + #endregion + + + #region column events + + /// + /// Overriden OnColumnAdded event + /// + /// + protected override void OnColumnAdded(DataGridViewColumnEventArgs e) + { + e.Column.SortMode = DataGridViewColumnSortMode.Programmatic; + KryptonColumnHeaderCell cell = new KryptonColumnHeaderCell(e.Column.HeaderCell, FilterAndSortEnabled); + cell.SortChanged += Cell_SortChanged; + cell.FilterChanged += Cell_FilterChanged; + cell.FilterPopup += Cell_FilterPopup; + e.Column.MinimumWidth = cell.MinimumSize.Width; + if (ColumnHeadersHeight < cell.MinimumSize.Height) + { + ColumnHeadersHeight = cell.MinimumSize.Height; + } + + e.Column.HeaderCell = cell; + + base.OnColumnAdded(e); + } + + /// + /// Overridden OnColumnRemoved event + /// + /// + protected override void OnColumnRemoved(DataGridViewColumnEventArgs e) + { + _filteredColumns.Remove(e.Column.Name); + _filterOrderList.Remove(e.Column.Name); + _sortOrderList.Remove(e.Column.Name); + + if (e.Column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SortChanged -= Cell_SortChanged; + cell.FilterChanged -= Cell_FilterChanged; + cell.FilterPopup -= Cell_FilterPopup; + + cell.CleanEvents(); + if (!e.Column.IsDataBound) + { + cell.MenuStrip?.Dispose(); + } + else if (cell.MenuStrip is { } menuStrip) + { + _menuStripToDispose.Add(menuStrip); + } + } + base.OnColumnRemoved(e); + } + + #endregion + + + #region rows events + + /// + /// Overridden OnRowsAdded event + /// + /// + protected override void OnRowsAdded(DataGridViewRowsAddedEventArgs e) + { + if (e.RowIndex >= 0) + { + _filteredColumns.Clear(); + } + + base.OnRowsAdded(e); + } + + /// + /// Overridden OnRowsRemoved event + /// + /// + protected override void OnRowsRemoved(DataGridViewRowsRemovedEventArgs e) + { + if (e.RowIndex >= 0) + { + _filteredColumns.Clear(); + } + + base.OnRowsRemoved(e); + } + + #endregion + + + #region cell events + + /// + /// Overridden OnCellValueChanged event + /// + /// + protected override void OnCellValueChanged(DataGridViewCellEventArgs e) + { + if (e is { RowIndex: >= 0, ColumnIndex: >= 0 }) + { + _filteredColumns.Remove(Columns[e.ColumnIndex].Name); + } + + base.OnCellValueChanged(e); + } + + #endregion + + + #region filter events + + /// + /// Build the complete Filter string + /// + /// + private string BuildFilterString() + { + StringBuilder sb = new StringBuilder(""); + string appx = ""; + + foreach (string filterOrder in _filterOrderList) + { + DataGridViewColumn? column = Columns[filterOrder]; + + if (column?.HeaderCell is KryptonColumnHeaderCell cell) + { + if (cell.FilterAndSortEnabled && cell.ActiveFilterType != MenuStrip.FilterType.None) + { + sb.AppendFormat(appx + "(" + cell.FilterString + ")", column.DataPropertyName); + appx = " AND "; + } + } + } + return sb.ToString(); + } + + /// + /// FilterPopup event + /// + /// + /// + private void Cell_FilterPopup(object sender, ColumnHeaderCellEventArgs e) + { + if (!Columns.Contains(e.Column) || e.FilterMenu is not { } filterMenu) + { + return; + } + + DataGridViewColumn column = e.Column; + + Rectangle rect = GetCellDisplayRectangle(column.Index, -1, true); + + if (_filteredColumns.Contains(column.Name)) + { + filterMenu.Show(this, rect.Left, rect.Bottom, false); + } + else + { + _filteredColumns.Add(column.Name); + if (_filterOrderList.Any() && _filterOrderList.Last() == column.Name) + { + filterMenu.Show(this, rect.Left, rect.Bottom, true); + } + else + { + filterMenu.Show(this, rect.Left, rect.Bottom, MenuStrip.GetValuesForFilter(this, column.Name)); + } + } + } + + /// + /// FilterChanged event + /// + /// + /// + private void Cell_FilterChanged(object sender, ColumnHeaderCellEventArgs e) + { + if (!Columns.Contains(e.Column) || e.FilterMenu is not { } filterMenu) + { + return; + } + + DataGridViewColumn column = e.Column; + + _filterOrderList.Remove(column.Name); + if (filterMenu.ActiveFilterType != MenuStrip.FilterType.None) + { + _filterOrderList.Add(column.Name); + } + + FilterString = BuildFilterString(); + + if (_loadedFilter) + { + _loadedFilter = false; + foreach (KryptonColumnHeaderCell c in FilterableCells.Where(f => f.MenuStrip != filterMenu)) + { + c.SetLoadedMode(false); + } + } + } + + #endregion + + + #region sort events + + /// + /// Build the complete Sort string + /// + /// + private string BuildSortString() + { + StringBuilder sb = new StringBuilder(""); + string appx = ""; + + foreach (string sortOrder in _sortOrderList) + { + DataGridViewColumn? column = Columns[sortOrder]; + + if (column?.HeaderCell is KryptonColumnHeaderCell cell) + { + if (cell.FilterAndSortEnabled && cell.ActiveSortType != MenuStrip.SortType.None) + { + sb.AppendFormat(appx + cell.SortString, column.DataPropertyName); + appx = ", "; + } + } + } + + return sb.ToString(); + } + + /// + /// SortChanged event + /// + /// + /// + private void Cell_SortChanged(object sender, ColumnHeaderCellEventArgs e) + { + if (!Columns.Contains(e.Column) || e.FilterMenu is not MenuStrip filterMenu) + { + return; + } + + DataGridViewColumn column = e.Column; + + _sortOrderList.Remove(column.Name); + if (filterMenu.ActiveSortType != MenuStrip.SortType.None) + { + _sortOrderList.Add(column.Name); + } + + SortString = BuildSortString(); + } + + #endregion + + #endregion + + #region Protected + + /// + protected override void OnHandleDestroyed(EventArgs e) + { + foreach (DataGridViewColumn column in Columns) + { + if (column.HeaderCell is KryptonColumnHeaderCell cell) + { + cell.SortChanged -= Cell_SortChanged; + cell.FilterChanged -= Cell_FilterChanged; + cell.FilterPopup -= Cell_FilterPopup; + } + } + + foreach (MenuStrip menuStrip in _menuStripToDispose) + { + menuStrip.Dispose(); + } + + _menuStripToDispose.Clear(); + + base.OnHandleDestroyed(e); + } + + /// + protected override void OnDataSourceChanged(EventArgs e) + { + foreach (DataGridViewColumn column in Columns) + { + KryptonColumnHeaderCell? cell = column.HeaderCell as KryptonColumnHeaderCell; + + _menuStripToDispose = _menuStripToDispose.Where(f => f != cell!.MenuStrip).ToList(); + } + + foreach (MenuStrip menuStrip in _menuStripToDispose) + { + menuStrip.Dispose(); + } + + _menuStripToDispose.Clear(); + base.OnDataSourceChanged(e); + } + + #endregion +} diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridViewSearchToolBar.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridViewSearchToolBar.cs new file mode 100644 index 0000000000..0164dcf231 --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridViewSearchToolBar.cs @@ -0,0 +1,653 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +// Control specific using statements + +#if NETFRAMEWORK +using System.Web.Script.Serialization; +#else +using System.Text.Json; +#endif + +namespace Krypton.Utilities; + +[DesignerCategory("code")] +public partial class KryptonAdvancedDataGridViewSearchToolBar : ToolStrip +{ + #region Design Code + + /// + /// Required designer variable. + /// + private IContainer? components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract + 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() + { + this.tsbtnClose = new System.Windows.Forms.ToolStripButton(); + this.tslblSearch = new System.Windows.Forms.ToolStripLabel(); + this.tscmbColumns = new System.Windows.Forms.ToolStripComboBox(); + this.tstxtSearch = new System.Windows.Forms.ToolStripTextBox(); + this.tsbtnFromBegin = new System.Windows.Forms.ToolStripButton(); + this.tsbtnCaseSensitive = new System.Windows.Forms.ToolStripButton(); + this.tsbtnSearch = new System.Windows.Forms.ToolStripButton(); + this.tsbtnWholeWord = new System.Windows.Forms.ToolStripButton(); + this.tssepSearch = new System.Windows.Forms.ToolStripSeparator(); + this.SuspendLayout(); + // + // button_close + // + this.tsbtnClose.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.tsbtnClose.Image = global::Krypton.Utilities.Properties.Resources.SearchToolBar_ButtonCaseSensitive; + this.tsbtnClose.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.tsbtnClose.ImageTransparentColor = System.Drawing.Color.Magenta; + this.tsbtnClose.Name = "tsbtnClose"; + this.tsbtnClose.Overflow = System.Windows.Forms.ToolStripItemOverflow.Never; + this.tsbtnClose.Size = new System.Drawing.Size(23, 24); + this.tsbtnClose.Click += new System.EventHandler(this.button_close_Click); + // + // label_search + // + this.tslblSearch.Name = "tslblSearch"; + this.tslblSearch.Size = new System.Drawing.Size(45, 15); + + // + // comboBox_columns + // + this.tscmbColumns.AutoSize = false; + this.tscmbColumns.AutoToolTip = true; + this.tscmbColumns.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.tscmbColumns.FlatStyle = System.Windows.Forms.FlatStyle.Standard; + this.tscmbColumns.IntegralHeight = false; + this.tscmbColumns.Margin = new System.Windows.Forms.Padding(0, 2, 8, 2); + this.tscmbColumns.MaxDropDownItems = 12; + this.tscmbColumns.Name = "tscmbColumns"; + this.tscmbColumns.Size = new System.Drawing.Size(150, 23); + // + // textBox_search + // + this.tstxtSearch.AutoSize = false; + this.tstxtSearch.ForeColor = System.Drawing.Color.LightGray; + this.tstxtSearch.Margin = new System.Windows.Forms.Padding(0, 2, 8, 2); + this.tstxtSearch.Name = "tstxtSearch"; + this.tstxtSearch.Overflow = System.Windows.Forms.ToolStripItemOverflow.Never; + this.tstxtSearch.Size = new System.Drawing.Size(100, 23); + this.tstxtSearch.Enter += new System.EventHandler(this.textBox_search_Enter); + this.tstxtSearch.Leave += new System.EventHandler(this.textBox_search_Leave); + this.tstxtSearch.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox_search_KeyDown); + this.tstxtSearch.TextChanged += new System.EventHandler(this.textBox_search_TextChanged); + // + // button_frombegin + // + this.tsbtnFromBegin.CheckOnClick = true; + this.tsbtnFromBegin.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.tsbtnFromBegin.Image = global::Krypton.Utilities.Properties.Resources.SearchToolBar_ButtonFromBegin; + this.tsbtnFromBegin.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.tsbtnFromBegin.ImageTransparentColor = System.Drawing.Color.Magenta; + this.tsbtnFromBegin.Name = "tsbtnFromBegin"; + this.tsbtnFromBegin.Size = new System.Drawing.Size(23, 20); + // + // button_casesensitive + // + this.tsbtnCaseSensitive.CheckOnClick = true; + this.tsbtnCaseSensitive.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.tsbtnCaseSensitive.Image = global::Krypton.Utilities.Properties.Resources.SearchToolBar_ButtonCaseSensitive; + this.tsbtnCaseSensitive.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.tsbtnCaseSensitive.ImageTransparentColor = System.Drawing.Color.Magenta; + this.tsbtnCaseSensitive.Name = "tsbtnCaseSensitive"; + this.tsbtnCaseSensitive.Size = new System.Drawing.Size(23, 20); + // + // button_search + // + this.tsbtnSearch.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.tsbtnSearch.Image = global::Krypton.Utilities.Properties.Resources.SearchToolBar_ButtonSearch; + this.tsbtnSearch.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.tsbtnSearch.ImageTransparentColor = System.Drawing.Color.Magenta; + this.tsbtnSearch.Name = "tsbtnSearch"; + this.tsbtnSearch.Overflow = System.Windows.Forms.ToolStripItemOverflow.Never; + this.tsbtnSearch.Size = new System.Drawing.Size(23, 24); + this.tsbtnSearch.Click += new System.EventHandler(this.button_search_Click); + // + // button_wholeword + // + this.tsbtnWholeWord.CheckOnClick = true; + this.tsbtnWholeWord.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.tsbtnWholeWord.Image = global::Krypton.Utilities.Properties.Resources.SearchToolBar_ButtonWholeWord; + this.tsbtnWholeWord.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.tsbtnWholeWord.ImageTransparentColor = System.Drawing.Color.Magenta; + this.tsbtnWholeWord.Margin = new System.Windows.Forms.Padding(1, 1, 1, 2); + this.tsbtnWholeWord.Name = "tsbtnWholeWord"; + this.tsbtnWholeWord.Size = new System.Drawing.Size(23, 20); + // + // separator_search + // + this.tssepSearch.AutoSize = false; + this.tssepSearch.Name = "tssepSearch"; + this.tssepSearch.Size = new System.Drawing.Size(10, 25); + // + // AdvancedDataGridViewSearchToolBar + // + this.AllowMerge = false; + this.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.tsbtnClose, + this.tslblSearch, + this.tscmbColumns, + this.tstxtSearch, + this.tsbtnFromBegin, + this.tsbtnWholeWord, + this.tsbtnCaseSensitive, + this.tssepSearch, + this.tsbtnSearch}); + this.MaximumSize = new System.Drawing.Size(0, 27); + this.MinimumSize = new System.Drawing.Size(0, 27); + this.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional; + this.Size = new System.Drawing.Size(0, 27); + this.Resize += new System.EventHandler(this.ResizeMe); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private ToolStripButton tsbtnClose; + private ToolStripLabel tslblSearch; + private ToolStripComboBox tscmbColumns; + private ToolStripTextBox tstxtSearch; + private ToolStripButton tsbtnFromBegin; + private ToolStripButton tsbtnCaseSensitive; + private ToolStripButton tsbtnSearch; + private ToolStripButton tsbtnWholeWord; + private ToolStripSeparator tssepSearch; + + #endregion + + #region public events + + public event AdvancedDataGridViewSearchToolBarSearchEventHandler? Search; + + #endregion + + + #region class properties + + private DataGridViewColumnCollection? _columnsList; + + private const bool BUTTON_CLOSE_ENABLED = false; + + #endregion + + + #region translations + + /// + /// Internationalization strings + /// + public static Dictionary Translations = new Dictionary() + { + { nameof(TranslationKey.ADGVSTBLabelSearch), "Search:" }, + { nameof(TranslationKey.ADGVSTBButtonFromBegin), "From Begin" }, + { nameof(TranslationKey.ADGVSTBButtonCaseSensitiveToolTip), "Case Sensitivity" }, + { nameof(TranslationKey.ADGVSTBButtonSearchToolTip), "Find Next" }, + { nameof(TranslationKey.ADGVSTBButtonCloseToolTip), "Hide" }, + { nameof(TranslationKey.ADGVSTBButtonWholeWordToolTip), "Search only Whole Word" }, + { nameof(TranslationKey.ADGVSTBComboBoxColumnsAll), "(All Columns)" }, + { nameof(TranslationKey.ADGVSTBTextBoxSearchToolTip), "Value for Search" } + }; + + /// + /// Used to check if components translations has to be updated + /// + private Dictionary _translationsRefreshComponentTranslationsCheck = new Dictionary() { }; + + #endregion + + #region Identity + + /// Initializes a new instance of the class. + public KryptonAdvancedDataGridViewSearchToolBar() + { + //initialize components + InitializeComponent(); + + RefreshComponentTranslations(); + + //set default values + if (!BUTTON_CLOSE_ENABLED) + { + Items.RemoveAt(0); + } + + tscmbColumns!.SelectedIndex = 0; + + // Use Krypton + RenderMode = ToolStripRenderMode.ManagerRenderMode; + } + + #endregion + + #region Translations Methods + + /// + /// Set translation dictionary + /// + /// + public static void SetTranslations(IDictionary? translations) + { + //set localization strings + if (translations != null) + { + foreach (KeyValuePair translation in translations) + { + if (Translations.ContainsKey(translation.Key)) + { + Translations[translation.Key] = translation.Value; + } + } + } + } + + /// + /// Get translation dictionary + /// + /// + public static IDictionary GetTranslations() + { + return Translations; + } + + /// + /// Load translations from file + /// + /// + /// + public static IDictionary LoadTranslationsFromFile(string filename) + { + IDictionary ret = new Dictionary(); + + if (!String.IsNullOrEmpty(filename)) + { + //deserialize the file + try + { + string jsonText = File.ReadAllText(filename); +#if NETFRAMEWORK + Dictionary translations = + new JavaScriptSerializer().Deserialize>(jsonText); +#else + Dictionary? translations = + JsonSerializer.Deserialize>(jsonText); +#endif + foreach (KeyValuePair translation in translations!) + { + if (!ret.ContainsKey(translation.Key) && Translations.ContainsKey(translation.Key)) + { + ret.Add(translation.Key, translation.Value); + } + } + } + catch + { + // Nothing to do + } + } + + //add default translations if not in files + foreach (KeyValuePair translation in GetTranslations()) + { + if (!ret.ContainsKey(translation.Key)) + { + ret.Add(translation.Key, translation.Value); + } + } + + return ret; + } + + /// + /// Update components translations + /// + private void RefreshComponentTranslations() + { + tscmbColumns.BeginUpdate(); + tscmbColumns.Items.Clear(); + tscmbColumns.Items.AddRange([Translations[nameof(TranslationKey.ADGVSTBComboBoxColumnsAll)]]); + if (_columnsList != null) + { + foreach (DataGridViewColumn c in _columnsList) + { + if (c.Visible) + { + tscmbColumns.Items.Add(c.HeaderText); + } + } + } + + tscmbColumns.SelectedIndex = 0; + tscmbColumns.EndUpdate(); + tsbtnClose.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBButtonCloseToolTip)]; + tslblSearch.Text = Translations[nameof(TranslationKey.ADGVSTBLabelSearch)]; + tstxtSearch.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBTextBoxSearchToolTip)]; + tsbtnFromBegin.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBButtonFromBegin)]; + tsbtnCaseSensitive.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBButtonCaseSensitiveToolTip)]; + tsbtnSearch.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBButtonSearchToolTip)]; + tsbtnWholeWord.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBButtonWholeWordToolTip)]; + tstxtSearch.Text = tstxtSearch.ToolTipText; + } + + #endregion + + #region Button Events + + /// + /// button Search Click event + /// + /// + /// + void button_search_Click(object? sender, EventArgs e) + { + if (tstxtSearch.TextLength > 0 && tstxtSearch.Text != tstxtSearch.ToolTipText && Search != null) + { + DataGridViewColumn? c = null; + if (tscmbColumns.SelectedIndex > 0 && _columnsList != null && _columnsList.GetColumnCount(DataGridViewElementStates.Visible) > 0) + { + DataGridViewColumn?[] cols = _columnsList.Cast().Where(col => col.Visible).ToArray(); + + if (cols.Length == tscmbColumns.Items.Count - 1) + { + if (cols[tscmbColumns.SelectedIndex - 1]!.HeaderText == tscmbColumns.SelectedItem?.ToString()) + { + c = cols[tscmbColumns.SelectedIndex - 1]; + } + } + } + + AdvancedDataGridViewSearchToolBarSearchEventArgs args = new AdvancedDataGridViewSearchToolBarSearchEventArgs( + tstxtSearch.Text, + c, + tsbtnCaseSensitive.Checked, + tsbtnWholeWord.Checked, + tsbtnFromBegin.Checked + ); + Search(this, args); + } + } + + /// + /// button Close Click event + /// + /// + /// + void button_close_Click(object? sender, EventArgs e) + { + Hide(); + } + + #endregion + + #region Textbox Search Events + + /// + /// textBox Search TextChanged event + /// + /// + /// + void textBox_search_TextChanged(object? sender, EventArgs e) + { + tsbtnSearch.Enabled = tstxtSearch.TextLength > 0 && tstxtSearch.Text != tstxtSearch.ToolTipText; + } + + + /// + /// textBox Search Enter event + /// + /// + /// + void textBox_search_Enter(object? sender, EventArgs e) + { + if (tstxtSearch.Text == tstxtSearch.ToolTipText && tstxtSearch.ForeColor == Color.LightGray) + { + tstxtSearch.Text = ""; + } + else + { + tstxtSearch.SelectAll(); + } + + tstxtSearch.ForeColor = SystemColors.WindowText; + } + + /// + /// textBox Search Leave event + /// + /// + /// + void textBox_search_Leave(object? sender, EventArgs e) + { + if (tstxtSearch.Text.Trim() == "") + { + tstxtSearch.Text = tstxtSearch.ToolTipText; + tstxtSearch.ForeColor = Color.LightGray; + } + } + + + /// + /// textBox Search KeyDown event + /// + /// + /// + void textBox_search_KeyDown(object? sender, KeyEventArgs e) + { + if (tstxtSearch.TextLength > 0 && tstxtSearch.Text != tstxtSearch.ToolTipText && e.KeyData == Keys.Enter) + { + button_search_Click(tsbtnSearch, EventArgs.Empty); + e.SuppressKeyPress = true; + e.Handled = true; + } + } + + #endregion + + #region Public Methods + + /// + /// Set Columns to search in + /// + /// + public void SetColumns(DataGridViewColumnCollection columns) + { + _columnsList = columns; + tscmbColumns.BeginUpdate(); + tscmbColumns.Items.Clear(); + tscmbColumns.Items.AddRange([Translations[nameof(TranslationKey.ADGVSTBComboBoxColumnsAll)]]); + if (_columnsList != null) + { + foreach (DataGridViewColumn c in _columnsList) + { + if (c.Visible) + { + tscmbColumns.Items.Add(c.HeaderText); + } + } + } + + tscmbColumns.SelectedIndex = 0; + tscmbColumns.EndUpdate(); + } + + #endregion + + #region Resize Events + + /// + /// Resize event + /// + /// + /// + private void ResizeMe(object? sender, EventArgs e) + { + SuspendLayout(); + int w1 = 150; + int w2 = 150; + int oldW = tscmbColumns.Width + tstxtSearch.Width; + foreach (ToolStripItem c in Items) + { + c.Overflow = ToolStripItemOverflow.Never; + c.Visible = true; + } + + int width = PreferredSize.Width - oldW + w1 + w2; + if (Width < width) + { + tslblSearch.Visible = false; + GetResizeBoxSize(PreferredSize.Width - oldW + w1 + w2, ref w1, ref w2); + width = PreferredSize.Width - oldW + w1 + w2; + + if (Width < width) + { + tsbtnCaseSensitive.Overflow = ToolStripItemOverflow.Always; + GetResizeBoxSize(PreferredSize.Width - oldW + w1 + w2, ref w1, ref w2); + width = PreferredSize.Width - oldW + w1 + w2; + } + + if (Width < width) + { + tsbtnWholeWord.Overflow = ToolStripItemOverflow.Always; + GetResizeBoxSize(PreferredSize.Width - oldW + w1 + w2, ref w1, ref w2); + width = PreferredSize.Width - oldW + w1 + w2; + } + + if (Width < width) + { + tsbtnFromBegin.Overflow = ToolStripItemOverflow.Always; + tssepSearch.Visible = false; + GetResizeBoxSize(PreferredSize.Width - oldW + w1 + w2, ref w1, ref w2); + width = PreferredSize.Width - oldW + w1 + w2; + } + + if (Width < width) + { + tscmbColumns.Overflow = ToolStripItemOverflow.Always; + tstxtSearch.Overflow = ToolStripItemOverflow.Always; + w1 = 150; + w2 = Math.Max(Width - PreferredSize.Width - tstxtSearch.Margin.Left - tstxtSearch.Margin.Right, 75); + tstxtSearch.Overflow = ToolStripItemOverflow.Never; + width = PreferredSize.Width - tstxtSearch.Width + w2; + } + if (Width < width) + { + tsbtnSearch.Overflow = ToolStripItemOverflow.Always; + w2 = Math.Max(Width - PreferredSize.Width + tstxtSearch.Width, 75); + width = PreferredSize.Width - tstxtSearch.Width + w2; + } + if (Width < width) + { + tsbtnClose.Overflow = ToolStripItemOverflow.Always; + tstxtSearch.Margin = new Padding(8, 2, 8, 2); + w2 = Math.Max(Width - PreferredSize.Width + tstxtSearch.Width, 75); + width = PreferredSize.Width - tstxtSearch.Width + w2; + } + + if (Width < width) + { + w2 = Math.Max(Width - PreferredSize.Width + tstxtSearch.Width, 20); + width = PreferredSize.Width - tstxtSearch.Width + w2; + } + if (width > Width) + { + tstxtSearch.Overflow = ToolStripItemOverflow.Always; + tstxtSearch.Margin = new Padding(0, 2, 8, 2); + w2 = 150; + } + } + else + { + GetResizeBoxSize(width, ref w1, ref w2); + } + + if (tscmbColumns.Width != w1) + { + tscmbColumns.Width = w1; + } + + if (tstxtSearch.Width != w2) + { + tstxtSearch.Width = w2; + } + + ResumeLayout(); + } + + /// + /// Get a Resize Size for a box + /// + /// + /// + /// + private void GetResizeBoxSize(int width, ref int w1, ref int w2) + { + int dif = (int)Math.Round((width - Width) / 2.0, 0, MidpointRounding.AwayFromZero); + + int oldW1 = w1; + int oldW2 = w2; + if (Width < width) + { + w1 = Math.Max(w1 - dif, 75); + w2 = Math.Max(w2 - dif, 75); + } + else + { + w1 = Math.Min(w1 - dif, 150); + w2 += Width - width + oldW1 - w1; + } + } + + #endregion + + #region Paint Events + + /// + /// On Paint event + /// + /// + protected override void OnPaint(PaintEventArgs e) + { + //check if translations are changed and update components + if (!(_translationsRefreshComponentTranslationsCheck == Translations || (_translationsRefreshComponentTranslationsCheck.Count == Translations.Count && !_translationsRefreshComponentTranslationsCheck.Except(Translations).Any()))) + { + _translationsRefreshComponentTranslationsCheck = Translations; + RefreshComponentTranslations(); + } + + base.OnPaint(e); + } + + #endregion +} diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/MenuStrip.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/MenuStrip.cs new file mode 100644 index 0000000000..e6afe620e1 --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/MenuStrip.cs @@ -0,0 +1,2537 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +using Timer = System.Windows.Forms.Timer; + +using static Krypton.Utilities.KryptonAdvancedDataGridViewSearchToolBar; + +namespace Krypton.Utilities; + +[DesignerCategory("code")] +internal partial class MenuStrip : ContextMenuStrip +{ + #region Designer Code + + /// + /// Required designer variable. + /// + private IContainer? components; + + /// + /// 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() + { + this.components = new System.ComponentModel.Container(); + this._sortAscMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._sortDescMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._cancelSortMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._toolStripSeparator1MenuItem = new System.Windows.Forms.ToolStripSeparator(); + this._cancelFilterMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._customFilterLastFiltersListMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._customFilterMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._toolStripSeparator2MenuItem = new System.Windows.Forms.ToolStripSeparator(); + this._customFilterLastFilter1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._customFilterLastFilter2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._customFilterLastFilter3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._customFilterLastFilter4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._customFilterLastFilter5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this._toolStripSeparator3MenuItem = new System.Windows.Forms.ToolStripSeparator(); + this._checkList = new System.Windows.Forms.TreeView(); + this._buttonFilter = new System.Windows.Forms.Button(); + this._buttonUndofilter = new System.Windows.Forms.Button(); + this._checkFilterListPanel = new System.Windows.Forms.Panel(); + this._checkFilterListButtonsPanel = new System.Windows.Forms.Panel(); + this._checkFilterListButtonsControlHost = new System.Windows.Forms.ToolStripControlHost(_checkFilterListButtonsPanel); + this._checkFilterListControlHost = new System.Windows.Forms.ToolStripControlHost(_checkFilterListPanel); + this._checkTextFilter = new System.Windows.Forms.TextBox(); + this._checkTextFilterControlHost = new System.Windows.Forms.ToolStripControlHost(_checkTextFilter); + this._resizeBoxControlHost = new System.Windows.Forms.ToolStripControlHost(new System.Windows.Forms.Control()); + this.SuspendLayout(); + // + // MenuStrip + // + this.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.AutoSize = false; + this.Padding = new System.Windows.Forms.Padding(0); + this.Margin = new System.Windows.Forms.Padding(0); + this.Size = new System.Drawing.Size(287, 370); + this.Closed += new System.Windows.Forms.ToolStripDropDownClosedEventHandler(MenuStrip_Closed); + this.LostFocus += new System.EventHandler(MenuStrip_LostFocus); + this.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + _sortAscMenuItem, + _sortDescMenuItem, + _cancelSortMenuItem, + _toolStripSeparator1MenuItem, + _cancelFilterMenuItem, + _customFilterLastFiltersListMenuItem, + _toolStripSeparator3MenuItem, + _checkTextFilterControlHost, + _checkFilterListControlHost, + _checkFilterListButtonsControlHost, + _resizeBoxControlHost}); + // + // sortASCMenuItem + // + this._sortAscMenuItem.Name = "_sortAscMenuItem"; + this._sortAscMenuItem.AutoSize = false; + this._sortAscMenuItem.Size = new System.Drawing.Size(Width - 1, 22); + this._sortAscMenuItem.Click += new System.EventHandler(SortASCMenuItem_Click); + this._sortAscMenuItem.MouseEnter += new System.EventHandler(SortASCMenuItem_MouseEnter); + this._sortAscMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + // + // sortDESCMenuItem + // + this._sortDescMenuItem.Name = "_sortDescMenuItem"; + this._sortDescMenuItem.AutoSize = false; + this._sortDescMenuItem.Size = new System.Drawing.Size(Width - 1, 22); + this._sortDescMenuItem.Click += new System.EventHandler(SortDESCMenuItem_Click); + this._sortDescMenuItem.MouseEnter += new System.EventHandler(SortDESCMenuItem_MouseEnter); + this._sortDescMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + // + // cancelSortMenuItem + // + this._cancelSortMenuItem.Name = "_cancelSortMenuItem"; + this._cancelSortMenuItem.Enabled = false; + this._cancelSortMenuItem.AutoSize = false; + this._cancelSortMenuItem.Size = new System.Drawing.Size(Width - 1, 22); + this._cancelSortMenuItem.Text = "Clear Sort"; + this._cancelSortMenuItem.Click += new System.EventHandler(CancelSortMenuItem_Click); + this._cancelSortMenuItem.MouseEnter += new System.EventHandler(CancelSortMenuItem_MouseEnter); + // + // toolStripSeparator1MenuItem + // + this._toolStripSeparator1MenuItem.Name = "_toolStripSeparator1MenuItem"; + this._toolStripSeparator1MenuItem.Size = new System.Drawing.Size(Width - 4, 6); + // + // cancelFilterMenuItem + // + this._cancelFilterMenuItem.Name = "_cancelFilterMenuItem"; + this._cancelFilterMenuItem.Enabled = false; + this._cancelFilterMenuItem.AutoSize = false; + this._cancelFilterMenuItem.Size = new System.Drawing.Size(Width - 1, 22); + this._cancelFilterMenuItem.Text = "Clear Filter"; + this._cancelFilterMenuItem.Click += new System.EventHandler(CancelFilterMenuItem_Click); + this._cancelFilterMenuItem.MouseEnter += new System.EventHandler(CancelFilterMenuItem_MouseEnter); + // + // toolStripMenuItem2 + // + this._toolStripSeparator2MenuItem.Name = "_toolStripSeparator2MenuItem"; + this._toolStripSeparator2MenuItem.Size = new System.Drawing.Size(149, 6); + this._toolStripSeparator2MenuItem.Visible = false; + // + // customFilterMenuItem + // + this._customFilterMenuItem.Name = "_customFilterMenuItem"; + this._customFilterMenuItem.Size = new System.Drawing.Size(152, 22); + this._customFilterMenuItem.Text = "Add a Custom Filter"; + this._customFilterMenuItem.Click += new System.EventHandler(CustomFilterMenuItem_Click); + // + // customFilterLastFilter1MenuItem + // + this._customFilterLastFilter1MenuItem.Name = "_customFilterLastFilter1MenuItem"; + this._customFilterLastFilter1MenuItem.Size = new System.Drawing.Size(152, 22); + this._customFilterLastFilter1MenuItem.Tag = "0"; + this._customFilterLastFilter1MenuItem.Text = null; + this._customFilterLastFilter1MenuItem.Visible = false; + this._customFilterLastFilter1MenuItem.VisibleChanged += new System.EventHandler(CustomFilterLastFilter1MenuItem_VisibleChanged); + this._customFilterLastFilter1MenuItem.Click += new System.EventHandler(CustomFilterLastFilterMenuItem_Click); + this._customFilterLastFilter1MenuItem.TextChanged += new System.EventHandler(CustomFilterLastFilterMenuItem_TextChanged); + // + // customFilterLastFilter2MenuItem + // + this._customFilterLastFilter2MenuItem.Name = "_customFilterLastFilter2MenuItem"; + this._customFilterLastFilter2MenuItem.Size = new System.Drawing.Size(152, 22); + this._customFilterLastFilter2MenuItem.Tag = "1"; + this._customFilterLastFilter2MenuItem.Text = null; + this._customFilterLastFilter2MenuItem.Visible = false; + this._customFilterLastFilter2MenuItem.Click += new System.EventHandler(CustomFilterLastFilterMenuItem_Click); + this._customFilterLastFilter2MenuItem.TextChanged += new System.EventHandler(CustomFilterLastFilterMenuItem_TextChanged); + // + // customFilterLastFilter3MenuItem + // + this._customFilterLastFilter3MenuItem.Name = "_customFilterLastFilter3MenuItem"; + this._customFilterLastFilter3MenuItem.Size = new System.Drawing.Size(152, 22); + this._customFilterLastFilter3MenuItem.Tag = "2"; + this._customFilterLastFilter3MenuItem.Text = null; + this._customFilterLastFilter3MenuItem.Visible = false; + this._customFilterLastFilter3MenuItem.Click += new System.EventHandler(CustomFilterLastFilterMenuItem_Click); + this._customFilterLastFilter3MenuItem.TextChanged += new System.EventHandler(CustomFilterLastFilterMenuItem_TextChanged); + // + // customFilterLastFilter3MenuItem + // + this._customFilterLastFilter4MenuItem.Name = "lastfilter4MenuItem"; + this._customFilterLastFilter4MenuItem.Size = new System.Drawing.Size(152, 22); + this._customFilterLastFilter4MenuItem.Tag = "3"; + this._customFilterLastFilter4MenuItem.Text = null; + this._customFilterLastFilter4MenuItem.Visible = false; + this._customFilterLastFilter4MenuItem.Click += new System.EventHandler(CustomFilterLastFilterMenuItem_Click); + this._customFilterLastFilter4MenuItem.TextChanged += new System.EventHandler(CustomFilterLastFilterMenuItem_TextChanged); + // + // customFilterLastFilter5MenuItem + // + this._customFilterLastFilter5MenuItem.Name = "_customFilterLastFilter5MenuItem"; + this._customFilterLastFilter5MenuItem.Size = new System.Drawing.Size(152, 22); + this._customFilterLastFilter5MenuItem.Tag = "4"; + this._customFilterLastFilter5MenuItem.Text = null; + this._customFilterLastFilter5MenuItem.Visible = false; + this._customFilterLastFilter5MenuItem.Click += new System.EventHandler(CustomFilterLastFilterMenuItem_Click); + this._customFilterLastFilter5MenuItem.TextChanged += new System.EventHandler(CustomFilterLastFilterMenuItem_TextChanged); + // + // customFilterLastFiltersListMenuItem + // + this._customFilterLastFiltersListMenuItem.Name = "_customFilterLastFiltersListMenuItem"; + this._customFilterLastFiltersListMenuItem.AutoSize = false; + this._customFilterLastFiltersListMenuItem.Size = new System.Drawing.Size(Width - 1, 22); + this._customFilterLastFiltersListMenuItem.Image = Properties.Resources.ColumnHeader_Filtered; + this._customFilterLastFiltersListMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this._customFilterLastFiltersListMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + _customFilterMenuItem, + _toolStripSeparator2MenuItem, + _customFilterLastFilter1MenuItem, + _customFilterLastFilter2MenuItem, + _customFilterLastFilter3MenuItem, + _customFilterLastFilter4MenuItem, + _customFilterLastFilter5MenuItem}); + this._customFilterLastFiltersListMenuItem.MouseEnter += new System.EventHandler(CustomFilterLastFiltersListMenuItem_MouseEnter); + this._customFilterLastFiltersListMenuItem.Paint += new System.Windows.Forms.PaintEventHandler(CustomFilterLastFiltersListMenuItem_Paint); + // + // toolStripMenuItem3 + // + this._toolStripSeparator3MenuItem.Name = "_toolStripSeparator3MenuItem"; + this._toolStripSeparator3MenuItem.Size = new System.Drawing.Size(Width - 4, 6); + // + // button_filter + // + this._buttonFilter.Name = "_buttonFilter"; + this._buttonFilter.BackColor = System.Windows.Forms.Button.DefaultBackColor; + this._buttonFilter.UseVisualStyleBackColor = true; + this._buttonFilter.Margin = new System.Windows.Forms.Padding(0); + this._buttonFilter.Size = new System.Drawing.Size(75, 23); + this._buttonFilter.Text = "Filter"; + this._buttonFilter.Click += new System.EventHandler(Button_ok_Click); + this._buttonFilter.Location = new System.Drawing.Point(this._checkFilterListButtonsPanel.Width - 164, 0); + // + // button_undofilter + // + this._buttonUndofilter.Name = "_buttonUndofilter"; + this._buttonUndofilter.BackColor = System.Windows.Forms.Button.DefaultBackColor; + this._buttonUndofilter.UseVisualStyleBackColor = true; + this._buttonUndofilter.Margin = new System.Windows.Forms.Padding(0); + this._buttonUndofilter.Size = new System.Drawing.Size(75, 23); + this._buttonUndofilter.Text = "Cancel"; + this._buttonUndofilter.Click += new System.EventHandler(Button_cancel_Click); + this._buttonUndofilter.Location = new System.Drawing.Point(this._checkFilterListButtonsPanel.Width - 79, 0); + // + // resizeBoxControlHost + // + this._resizeBoxControlHost.Name = "_resizeBoxControlHost"; + this._resizeBoxControlHost.Control.Cursor = System.Windows.Forms.Cursors.SizeNWSE; + this._resizeBoxControlHost.AutoSize = false; + this._resizeBoxControlHost.Padding = new System.Windows.Forms.Padding(0); + this._resizeBoxControlHost.Margin = new System.Windows.Forms.Padding(Width - 45, 0, 0, 0); + this._resizeBoxControlHost.Size = new System.Drawing.Size(10, 10); + this._resizeBoxControlHost.Paint += new System.Windows.Forms.PaintEventHandler(ResizeBoxControlHost_Paint); + this._resizeBoxControlHost.MouseDown += new System.Windows.Forms.MouseEventHandler(ResizeBoxControlHost_MouseDown); + this._resizeBoxControlHost.MouseUp += new System.Windows.Forms.MouseEventHandler(ResizeBoxControlHost_MouseUp); + this._resizeBoxControlHost.MouseMove += new System.Windows.Forms.MouseEventHandler(ResizeBoxControlHost_MouseMove); + // + // checkFilterListControlHost + // + this._checkFilterListControlHost.Name = "_checkFilterListControlHost"; + this._checkFilterListControlHost.AutoSize = false; + this._checkFilterListControlHost.Size = new System.Drawing.Size(Width - 35, 194); + this._checkFilterListControlHost.Padding = new System.Windows.Forms.Padding(0); + this._checkFilterListControlHost.Margin = new System.Windows.Forms.Padding(0); + // + // checkTextFilterControlHost + // + this._checkTextFilterControlHost.Name = "_checkTextFilterControlHost"; + this._checkTextFilterControlHost.AutoSize = false; + this._checkTextFilterControlHost.Size = new System.Drawing.Size(Width - 35, 20); + this._checkTextFilterControlHost.Padding = new System.Windows.Forms.Padding(4, 0, 4, 0); + this._checkTextFilterControlHost.Margin = new System.Windows.Forms.Padding(0); + // + // checkFilterListButtonsControlHost + // + this._checkFilterListButtonsControlHost.Name = "_checkFilterListButtonsControlHost"; + this._checkFilterListButtonsControlHost.AutoSize = false; + this._checkFilterListButtonsControlHost.Size = new System.Drawing.Size(Width - 35, 24); + this._checkFilterListButtonsControlHost.Padding = new System.Windows.Forms.Padding(0); + this._checkFilterListButtonsControlHost.Margin = new System.Windows.Forms.Padding(0); + // + // checkFilterListPanel + // + this._checkFilterListPanel.Name = "_checkFilterListPanel"; + this._checkFilterListPanel.AutoSize = false; + this._checkFilterListPanel.Size = _checkFilterListControlHost.Size; + this._checkFilterListPanel.Padding = new System.Windows.Forms.Padding(0); + this._checkFilterListPanel.Margin = new System.Windows.Forms.Padding(0); + this._checkFilterListPanel.BackColor = BackColor; + this._checkFilterListPanel.BorderStyle = System.Windows.Forms.BorderStyle.None; + this._checkFilterListPanel.Controls.Add(_checkList); + // + // checkList + // + this._checkList.Name = "_checkList"; + this._checkList.AutoSize = false; + this._checkList.Padding = new System.Windows.Forms.Padding(0); + this._checkList.Margin = new System.Windows.Forms.Padding(0); + this._checkList.Bounds = new System.Drawing.Rectangle(4, 4, this._checkFilterListPanel.Width - 8, this._checkFilterListPanel.Height - 8); + this._checkList.StateImageList = GetCheckListStateImages(); + this._checkList.CheckBoxes = false; + this._checkList.MouseLeave += new System.EventHandler(CheckList_MouseLeave); + this._checkList.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(CheckList_NodeMouseClick); + this._checkList.KeyDown += new System.Windows.Forms.KeyEventHandler(CheckList_KeyDown); + this._checkList.MouseEnter += CheckList_MouseEnter; + this._checkList.NodeMouseDoubleClick += CheckList_NodeMouseDoubleClick; + // + // checkTextFilter + // + this._checkTextFilter.Name = "_checkTextFilter"; + this._checkTextFilter.Padding = new System.Windows.Forms.Padding(0); + this._checkTextFilter.Margin = new System.Windows.Forms.Padding(0); + this._checkTextFilter.Size = _checkTextFilterControlHost.Size; + this._checkTextFilter.Dock = System.Windows.Forms.DockStyle.Fill; + this._checkTextFilter.TextChanged += new System.EventHandler(CheckTextFilter_TextChanged); + // + // checkFilterListButtonsPanel + // + this._checkFilterListButtonsPanel.Name = "_checkFilterListButtonsPanel"; + this._checkFilterListButtonsPanel.AutoSize = false; + this._checkFilterListButtonsPanel.Size = _checkFilterListButtonsControlHost.Size; + this._checkFilterListButtonsPanel.Padding = new System.Windows.Forms.Padding(0); + this._checkFilterListButtonsPanel.Margin = new System.Windows.Forms.Padding(0); + this._checkFilterListButtonsPanel.BackColor = BackColor; + this._checkFilterListButtonsPanel.BorderStyle = System.Windows.Forms.BorderStyle.None; + this._checkFilterListButtonsPanel.Controls.AddRange(new System.Windows.Forms.Control[] { + _buttonFilter, + _buttonUndofilter + }); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private ToolStripMenuItem _sortAscMenuItem; + private ToolStripMenuItem _sortDescMenuItem; + private ToolStripMenuItem _cancelSortMenuItem; + private ToolStripSeparator _toolStripSeparator1MenuItem; + private ToolStripSeparator _toolStripSeparator2MenuItem; + private ToolStripSeparator _toolStripSeparator3MenuItem; + private ToolStripMenuItem _cancelFilterMenuItem; + private ToolStripMenuItem _customFilterLastFiltersListMenuItem; + private ToolStripMenuItem _customFilterMenuItem; + private ToolStripMenuItem _customFilterLastFilter1MenuItem; + private ToolStripMenuItem _customFilterLastFilter2MenuItem; + private ToolStripMenuItem _customFilterLastFilter3MenuItem; + private ToolStripMenuItem _customFilterLastFilter4MenuItem; + private ToolStripMenuItem _customFilterLastFilter5MenuItem; + private TreeView _checkList; + private Button _buttonFilter; + private Button _buttonUndofilter; + private ToolStripControlHost _checkFilterListControlHost; + private ToolStripControlHost _checkFilterListButtonsControlHost; + private ToolStripControlHost _resizeBoxControlHost; + private Panel _checkFilterListPanel; + private Panel _checkFilterListButtonsPanel; + private TextBox _checkTextFilter; + private ToolStripControlHost _checkTextFilterControlHost; + + #endregion + + #region public enum + + /// + /// MenuStrip Filter type + /// + public enum FilterType : byte + { + None = 0, + Custom = 1, + CheckList = 2, + Loaded = 3 + } + + + /// + /// MenuStrip Sort type + /// + public enum SortType : byte + { + None = 0, + Asc = 1, + Desc = 2 + } + + #endregion + + + #region public constants + + /// + /// Default checklist filter node behaviour + /// + public const bool DefaultCheckTextFilterRemoveNodesOnSearch = true; + + /// + /// Default max filter checklist max nodes + /// + public const int DefaultMaxChecklistNodes = 10000; + + /// + /// Default number of nodes to enable the TextChanged delay on text filter + /// + public const int DefaultTextFilterTextChangedDelayNodes = 1000; + + /// + /// Number of nodes to disable the text filter TextChanged delay + /// + public const int TextFilterTextChangedDelayNodesDisabled = -1; + + /// + /// Default delay milliseconds for TextChanged delay on text filter + /// + public const int DefaultTextFilterTextChangedDelayMs = 300; + + #endregion + + + #region class properties + + private FilterType _activeFilterType = FilterType.None; + private SortType _activeSortType = SortType.None; + private TreeNodeItemSelector?[] _loadedNodes = []; + private TreeNodeItemSelector?[] _startingNodes = []; + private TreeNodeItemSelector?[] _removedNodes = []; + private TreeNodeItemSelector?[] _removedSessionNodes = []; + private string? _sortString; + private string? _filterString; + private static readonly Point _resizeStartPoint = new Point(1, 1); + private Point _resizeEndPoint = new Point(-1, -1); + private bool _checkTextFilterChangedEnabled = true; + private bool _checkTextFilterRemoveNodesOnSearch = DefaultCheckTextFilterRemoveNodesOnSearch; + private int _maxChecklistNodes = DefaultMaxChecklistNodes; + private bool _filterClick; + private Timer? _textFilterTextChangedTimer; + private int _textFilterTextChangedDelayNodes = DefaultTextFilterTextChangedDelayNodes; + private int _textFilterTextChangedDelayMs = DefaultTextFilterTextChangedDelayMs; + + #endregion + + + #region Identity + + /// + /// MenuStrip constructor + /// + /// + public MenuStrip(Type dataType) + : base() + { + //initialize components + InitializeComponent(); + + //set component translations + _cancelSortMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewClearSort)]; + _cancelFilterMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewClearFilter)]; + _customFilterMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewAddCustomFilter)]; + _buttonFilter!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewButtonFilter)]; + _buttonUndofilter!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewButtonUndoFilter)]; + + //set type + DataType = dataType; + + //set components values + if (DataType == typeof(DateTime) || DataType == typeof(TimeSpan)) + { + _customFilterLastFiltersListMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewCustomFilter)]; + _sortAscMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortDateTimeAscending)]; + _sortDescMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortDateTimeDescending)]; + _sortAscMenuItem.Image = Properties.Resources.MenuStrip_OrderASCnum; + _sortDescMenuItem.Image = Properties.Resources.MenuStrip_OrderDESCnum; + } + else if (DataType == typeof(bool)) + { + _customFilterLastFiltersListMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewCustomFilter)]; + _sortAscMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortBoolAscending)]; + _sortDescMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortBoolDescending)]; + _sortAscMenuItem.Image = Properties.Resources.MenuStrip_OrderASCbool; + _sortDescMenuItem.Image = Properties.Resources.MenuStrip_OrderDESCbool; + } + else if (DataType == typeof(Int32) || DataType == typeof(Int64) || DataType == typeof(Int16) || + DataType == typeof(UInt32) || DataType == typeof(UInt64) || DataType == typeof(UInt16) || + DataType == typeof(Byte) || DataType == typeof(SByte) || DataType == typeof(Decimal) || + DataType == typeof(Single) || DataType == typeof(Double)) + { + _customFilterLastFiltersListMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewCustomFilter)]; + _sortAscMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortNumAscending)]; + _sortDescMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortNumDescending)]; + _sortAscMenuItem.Image = Properties.Resources.MenuStrip_OrderASCnum; + _sortDescMenuItem.Image = Properties.Resources.MenuStrip_OrderDESCnum; + } + else + { + _customFilterLastFiltersListMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewCustomFilter)]; + _sortAscMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortTextAscending)]; + _sortDescMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortTextDescending)]; + _sortAscMenuItem.Image = Properties.Resources.MenuStrip_OrderASCtxt; + _sortDescMenuItem.Image = Properties.Resources.MenuStrip_OrderDESCtxt; + } + + //set check filter textbox + if (DataType == typeof(DateTime) || DataType == typeof(TimeSpan) || DataType == typeof(bool)) + { + _checkTextFilter!.Enabled = false; + } + + //set default NOT IN logic + IsFilterNotinLogicEnabled = false; + + //sent enablers default + IsSortEnabled = true; + IsFilterEnabled = true; + IsFilterChecklistEnabled = true; + IsFilterDateAndTimeEnabled = true; + + //set default components + _customFilterLastFiltersListMenuItem.Enabled = DataType != typeof(bool); + _customFilterLastFiltersListMenuItem.Checked = ActiveFilterType == FilterType.Custom; + + //resize before hitting ResizeBox so the grip works correctly + float scalingFactor = GetScalingFactor(); + MinimumSize = new Size(Scale(PreferredSize.Width, scalingFactor), Scale(PreferredSize.Height, scalingFactor)); + //once the size is set resize the ones that won't change + _resizeBoxControlHost!.Height = Scale(_resizeBoxControlHost.Height, scalingFactor); + _resizeBoxControlHost.Width = Scale(_resizeBoxControlHost.Width, scalingFactor); + _toolStripSeparator1MenuItem!.Height = Scale(_toolStripSeparator1MenuItem.Height, scalingFactor); + _toolStripSeparator2MenuItem!.Height = Scale(_toolStripSeparator2MenuItem.Height, scalingFactor); + _toolStripSeparator3MenuItem!.Height = Scale(_toolStripSeparator3MenuItem.Height, scalingFactor); + _sortAscMenuItem.Height = Scale(_sortAscMenuItem.Height, scalingFactor); + _sortDescMenuItem.Height = Scale(_sortDescMenuItem.Height, scalingFactor); + _cancelSortMenuItem.Height = Scale(_cancelSortMenuItem.Height, scalingFactor); + _cancelFilterMenuItem.Height = Scale(_cancelFilterMenuItem.Height, scalingFactor); + _customFilterMenuItem.Height = Scale(_customFilterMenuItem.Height, scalingFactor); + _customFilterLastFiltersListMenuItem.Height = Scale(_customFilterLastFiltersListMenuItem.Height, scalingFactor); + _checkTextFilterControlHost!.Height = Scale(_checkTextFilterControlHost.Height, scalingFactor); + _buttonFilter.Width = Scale(_buttonFilter.Width, scalingFactor); + _buttonFilter.Height = Scale(_buttonFilter.Height, scalingFactor); + _buttonUndofilter.Width = Scale(_buttonUndofilter.Width, scalingFactor); + _buttonUndofilter.Height = Scale(_buttonUndofilter.Height, scalingFactor); + //resize + ResizeBox(MinimumSize.Width, MinimumSize.Height); + + _textFilterTextChangedTimer = new Timer(); + _textFilterTextChangedTimer.Interval = _textFilterTextChangedDelayMs; + _textFilterTextChangedTimer.Tick += new EventHandler(CheckTextFilterTextChangedTimer_Tick); + + RenderMode = ToolStripRenderMode.ManagerRenderMode; + } + + /// + /// Closed event + /// + /// + /// + private void MenuStrip_Closed(object? sender, EventArgs e) + { + ResizeClean(); + + if (_checkTextFilterRemoveNodesOnSearch && !_filterClick) + { + _loadedNodes = DuplicateNodes(_startingNodes); + } + + _startingNodes = []; + + _checkTextFilterChangedEnabled = false; + _checkTextFilter.Text = ""; + _checkTextFilterChangedEnabled = true; + } + + /// + /// LostFocus event + /// + /// + /// + private void MenuStrip_LostFocus(object? sender, EventArgs e) + { + if (!ContainsFocus) + { + Close(); + } + } + + /// + /// Control removed event + /// + /// + protected override void OnControlRemoved(ControlEventArgs e) + { + _loadedNodes = []; + _startingNodes = []; + _removedNodes = []; + _removedSessionNodes = []; + _textFilterTextChangedTimer?.Stop(); + + base.OnControlRemoved(e); + } + + /// + /// Get all images for checkList + /// + /// + private static ImageList GetCheckListStateImages() + { + ImageList images = new ImageList(); + Bitmap unCheckImg = new Bitmap(16, 16); + Bitmap checkImg = new Bitmap(16, 16); + Bitmap mixedImg = new Bitmap(16, 16); + + using (Bitmap img = new Bitmap(16, 16)) + { + using (Graphics g = Graphics.FromImage(img)) + { + CheckBoxRenderer.DrawCheckBox(g, new Point(0, 1), CheckBoxState.UncheckedNormal); + unCheckImg = (Bitmap)img.Clone(); + CheckBoxRenderer.DrawCheckBox(g, new Point(0, 1), CheckBoxState.CheckedNormal); + checkImg = (Bitmap)img.Clone(); + CheckBoxRenderer.DrawCheckBox(g, new Point(0, 1), CheckBoxState.MixedNormal); + mixedImg = (Bitmap)img.Clone(); + } + } + + images.Images.Add("uncheck", unCheckImg); + images.Images.Add("check", checkImg); + images.Images.Add("mixed", mixedImg); + + return images; + } + + #endregion + + + #region public events + + /// + /// The current Sorting in changed + /// + public event EventHandler? SortChanged; + + /// + /// The current Filter is changed + /// + public event EventHandler? FilterChanged; + + #endregion + + + #region public getter and setters + + /// + /// Set the max checklist nodes + /// + [DefaultValue(DefaultMaxChecklistNodes)] + public int MaxChecklistNodes + { + get => _maxChecklistNodes; + set => _maxChecklistNodes = value; + } + + /// + /// Get the current MenuStripSortType type + /// + public SortType ActiveSortType => _activeSortType; + + /// + /// Get the current MenuStripFilterType type + /// + public FilterType ActiveFilterType => _activeFilterType; + + /// + /// Get the DataType for the MenuStrip Filter + /// + public Type DataType { get; private set; } + + /// + /// Get or Set the Filter Sort enabled + /// + [DefaultValue(false)] + public bool IsSortEnabled { get; set; } + + /// + /// Get or Set the Filter enabled + /// + [DefaultValue(false)] + public bool IsFilterEnabled { get; set; } + + /// + /// Get or Set the Filter Checklist enabled + /// + [DefaultValue(false)] + public bool IsFilterChecklistEnabled { get; set; } + + /// + /// Get or Set the Filter Custom enabled + /// + [DefaultValue(false)] + public bool IsFilterCustomEnabled { get; set; } + + /// + /// Get or Set the Filter DateAndTime enabled + /// + [DefaultValue(false)] + public bool IsFilterDateAndTimeEnabled { get; set; } + + /// + /// Get or Set the NOT IN logic for Filter + /// + [DefaultValue(false)] + public bool IsFilterNotinLogicEnabled { get; set; } + + /// + /// Set the text filter search nodes behaviour + /// + [DefaultValue(DefaultCheckTextFilterRemoveNodesOnSearch)] + public bool DoesTextFilterRemoveNodesOnSearch + { + get => _checkTextFilterRemoveNodesOnSearch; + set => _checkTextFilterRemoveNodesOnSearch = value; + } + + /// + /// Number of nodes to enable the TextChanged delay on text filter + /// + [DefaultValue(DefaultTextFilterTextChangedDelayNodes)] + public int TextFilterTextChangedDelayNodes + { + get => _textFilterTextChangedDelayNodes; + set => _textFilterTextChangedDelayNodes = value; + } + + /// + /// Delay milliseconds for TextChanged delay on text filter + /// + [DefaultValue(DefaultTextFilterTextChangedDelayMs)] + public int TextFilterTextChangedDelayMs + { + get => _textFilterTextChangedDelayMs; + set => _textFilterTextChangedDelayMs = value; + } + + #endregion + + + #region public enablers + + /// + /// Enabled or disable Sorting capabilities + /// + /// + public void SetSortEnabled(bool enabled) + { + IsSortEnabled = enabled; + + _sortAscMenuItem.Enabled = enabled; + _sortDescMenuItem.Enabled = enabled; + _cancelSortMenuItem.Enabled = enabled; + } + + /// + /// Enable or disable Filter capabilities + /// + /// + public void SetFilterEnabled(bool enabled) + { + IsFilterEnabled = enabled; + + _cancelFilterMenuItem.Enabled = enabled; + _customFilterLastFiltersListMenuItem.Enabled = enabled && DataType != typeof(bool); + _buttonFilter.Enabled = enabled; + _buttonUndofilter.Enabled = enabled; + _checkList.Enabled = enabled; + _checkTextFilter.Enabled = enabled; + } + + /// + /// Enable or disable Filter checklist capabilities + /// + /// + public void SetFilterChecklistEnabled(bool enabled) + { + if (!IsFilterEnabled) + { + enabled = false; + } + + IsFilterChecklistEnabled = enabled; + _checkList.Enabled = enabled; + _checkTextFilter.ReadOnly = !enabled; + + if (!IsFilterChecklistEnabled) + { + ChecklistClearNodes(); + TreeNodeItemSelector disabledNode = TreeNodeItemSelector.CreateNode( + $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewFilterChecklistDisable)]} ", null, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.SelectAll); + disabledNode.NodeFont = new Font(_checkList.Font, FontStyle.Bold); + ChecklistAddNode(disabledNode); + ChecklistReloadNodes(); + } + } + + /// + /// Enable or disable Filter custom capabilities + /// + /// + public void SetFilterCustomEnabled(bool enabled) + { + if (!IsFilterEnabled) + { + enabled = false; + } + + IsFilterCustomEnabled = enabled; + _customFilterMenuItem.Enabled = enabled; + _customFilterLastFiltersListMenuItem.Enabled = enabled; + + if (!IsFilterCustomEnabled) + { + UnCheckCustomFilters(); + } + } + + /// + /// Disable text filter TextChanged delay + /// + public void SetTextFilterTextChangedDelayNodesDisabled() + { + _textFilterTextChangedDelayNodes = TextFilterTextChangedDelayNodesDisabled; + } + + #endregion + + + #region preset loader + + public void SetLoadedMode(bool enabled) + { + _customFilterMenuItem.Enabled = !enabled; + _cancelFilterMenuItem.Enabled = enabled; + if (enabled) + { + _activeFilterType = FilterType.Loaded; + _sortString = null; + _filterString = null; + _customFilterLastFiltersListMenuItem.Checked = false; + for (int i = 2; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count - 1; i++) + { + ((_customFilterLastFiltersListMenuItem.DropDownItems[i] as ToolStripMenuItem)!).Checked = false; + } + + ChecklistClearNodes(); + TreeNodeItemSelector allNode = TreeNodeItemSelector.CreateNode( + $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectAll)]} ", null, CheckState.Indeterminate, TreeNodeItemSelector.CustomNodeType.SelectAll); + allNode.NodeFont = new Font(_checkList.Font, FontStyle.Bold); + ChecklistAddNode(allNode); + ChecklistReloadNodes(); + + SetSortEnabled(false); + SetFilterEnabled(false); + } + else + { + _activeFilterType = FilterType.None; + + SetSortEnabled(true); + SetFilterEnabled(true); + } + } + + #endregion + + + #region public show methods + + /// + /// Show the menuStrip + /// + /// + /// + /// + /// + public void Show(Control control, int x, int y, IEnumerable vals) + { + _removedNodes = []; + _removedSessionNodes = []; + + //add nodes + BuildNodes(vals); + //set the starting nodes + _startingNodes = DuplicateNodes(_loadedNodes); + + if (_activeFilterType == FilterType.Custom) + { + SetNodesCheckState(_loadedNodes, false); + } + + base.Show(control, x, y); + + _filterClick = false; + + _checkTextFilterChangedEnabled = false; + _checkTextFilter.Text = ""; + _checkTextFilterChangedEnabled = true; + } + + /// + /// Show the menuStrip + /// + /// + /// + /// + /// + public void Show(Control control, int x, int y, bool restoreFilter) + { + _checkTextFilterChangedEnabled = false; + _checkTextFilter.Text = ""; + _checkTextFilterChangedEnabled = true; + if (restoreFilter || _checkTextFilterRemoveNodesOnSearch) + { + //reset the starting nodes + _startingNodes = DuplicateNodes(_loadedNodes); + } + //reset removed nodes + if (_checkTextFilterRemoveNodesOnSearch) + { + _removedNodes = _loadedNodes.Where(n => n!.CheckState == CheckState.Unchecked && n.NodeType == TreeNodeItemSelector.CustomNodeType.Default).ToArray(); + _removedSessionNodes = _removedNodes; + } + + ChecklistReloadNodes(); + + base.Show(control, x, y); + + _filterClick = false; + } + + /// + /// Get values used for Show method + /// + /// + /// + /// + public static IEnumerable GetValuesForFilter(DataGridView grid, string columnName) + { + var vals = + from DataGridViewRow nulls in grid.Rows + select nulls.Cells[columnName]; + + return vals; + } + + #endregion + + + #region public sort methods + + /// + /// Sort ASC + /// + public void SortAsc() + { + SortASCMenuItem_Click(this, null); + } + + /// + /// Sort DESC + /// + public void SortDesc() + { + SortDESCMenuItem_Click(this, null); + } + + /// + /// Get the Sorting String + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string? SortString + { + get => !String.IsNullOrEmpty(_sortString) ? _sortString : ""; + private set + { + _cancelSortMenuItem.Enabled = value is { Length: > 0 }; + _sortString = value; + } + } + + /// + /// Clean the Sorting + /// + public void CleanSort() + { + _sortAscMenuItem.Checked = false; + _sortDescMenuItem.Checked = false; + _activeSortType = SortType.None; + SortString = null; + } + + #endregion + + + #region public filter methods + + /// + /// Get the Filter string + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string? FilterString + { + get => !String.IsNullOrEmpty(_filterString) ? _filterString : ""; + private set + { + _cancelFilterMenuItem.Enabled = value is { Length: > 0 }; + _filterString = value; + } + } + + /// + /// Clean the Filter + /// + public void CleanFilter() + { + if (_checkTextFilterRemoveNodesOnSearch) + { + _removedNodes = []; + _removedSessionNodes = []; + } + + for (int i = 2; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count - 1; i++) + { + ((_customFilterLastFiltersListMenuItem.DropDownItems[i] as ToolStripMenuItem)!).Checked = false; + } + _activeFilterType = FilterType.None; + SetNodesCheckState(_loadedNodes, true); + FilterString = null; + _customFilterLastFiltersListMenuItem.Checked = false; + _buttonFilter.Enabled = true; + } + + /// + /// Set the text filter on checklist remove node mode + /// + /// + public void SetChecklistTextFilterRemoveNodesOnSearchMode(bool enabled) + { + if (_checkTextFilterRemoveNodesOnSearch != enabled) + { + _checkTextFilterRemoveNodesOnSearch = enabled; + CleanFilter(); + } + } + + #endregion + + + #region checklist filter methods + + /// + /// Clear checklist loaded nodes + /// + private void ChecklistClearNodes() + { + _loadedNodes = []; + } + + /// + /// Add a node to checklist nodes + /// + /// + private void ChecklistAddNode(TreeNodeItemSelector node) + { + _loadedNodes = _loadedNodes.Concat([node]).ToArray(); + } + + /// + /// Load checklist nodes + /// + private void ChecklistReloadNodes() + { + _checkList.BeginUpdate(); + _checkList.Nodes.Clear(); + int nodeCount = 0; + foreach (TreeNodeItemSelector? node in _loadedNodes) + { + if (node!.NodeType == TreeNodeItemSelector.CustomNodeType.Default) + { + if (_maxChecklistNodes == 0) + { + if (!_removedNodes.Contains(node)) + { + _checkList.Nodes.Add(node); + } + } + else + { + if (nodeCount < _maxChecklistNodes && !_removedNodes.Contains(node)) + { + _checkList.Nodes.Add(node); + } + else if (nodeCount == _maxChecklistNodes) + { + _checkList.Nodes.Add("..."); + } + + if (!_removedNodes.Contains(node) || nodeCount == _maxChecklistNodes) + { + nodeCount++; + } + } + } + else + { + _checkList.Nodes.Add(node); + } + + } + _checkList.EndUpdate(); + } + + /// + /// Get checklist nodes + /// + /// + private TreeNodeCollection ChecklistNodes() => _checkList.Nodes; + + /// + /// Set the Filter String using checkList selected Nodes + /// + private void SetCheckListFilter() + { + UnCheckCustomFilters(); + + TreeNodeItemSelector? selectAllNode = GetSelectAllNode(); + _customFilterLastFiltersListMenuItem.Checked = false; + + if (selectAllNode is { Checked: true } && string.IsNullOrEmpty(_checkTextFilter.Text)) + { + CancelFilterMenuItem_Click(null, EventArgs.Empty); + } + else + { + string? oldFilter = FilterString; + FilterString = ""; + _activeFilterType = FilterType.CheckList; + + if (_loadedNodes.Length > 1) + { + selectAllNode = GetSelectEmptyNode(); + if (selectAllNode is { Checked: true }) + { + FilterString = "[{0}] IS NULL"; + } + + if (_loadedNodes.Length > 2 || selectAllNode == null) + { + string filter = BuildNodesFilterString( + IsFilterNotinLogicEnabled && DataType != typeof(DateTime) && DataType != typeof(TimeSpan) && DataType != typeof(bool) ? + _loadedNodes.AsParallel().Cast().Where( + n => n.NodeType != TreeNodeItemSelector.CustomNodeType.SelectAll + && n.NodeType != TreeNodeItemSelector.CustomNodeType.SelectEmpty + && n.CheckState == CheckState.Unchecked + ) : + _loadedNodes.AsParallel().Cast().Where( + n => n.NodeType != TreeNodeItemSelector.CustomNodeType.SelectAll + && n.NodeType != TreeNodeItemSelector.CustomNodeType.SelectEmpty + && n.CheckState != CheckState.Unchecked + ) + ); + + if (filter.Length > 0) + { + if (FilterString.Length > 0) + { + FilterString += " OR "; + } + + if (DataType == typeof(bool)) + { + FilterString += $"[{{0}}] ={filter}"; + } + else if (DataType == typeof(int) || DataType == typeof(long) || DataType == typeof(short) || + DataType == typeof(uint) || DataType == typeof(ulong) || DataType == typeof(ushort) || + DataType == typeof(decimal) || + DataType == typeof(byte) || DataType == typeof(sbyte) || DataType == typeof(string)) + { + if (IsFilterNotinLogicEnabled) + { + FilterString += $"[{{0}}] NOT IN ({filter})"; + } + else + { + FilterString += $"[{{0}}] IN ({filter})"; + } + } + else if (DataType == typeof(Bitmap)) + { } + else + { + if (IsFilterNotinLogicEnabled) + { + FilterString += $"Convert([{{0}}],System.String) NOT IN ({filter})"; + } + else + { + FilterString += $"Convert([{{0}}],System.String) IN ({filter})"; + } + } + } + } + } + + if (oldFilter != FilterString && FilterChanged != null) + { + FilterChanged(this, EventArgs.Empty); + } + } + } + + /// + /// Build a Filter string based on selected Nodes + /// + /// + /// + private string BuildNodesFilterString(IEnumerable? nodes) + { + StringBuilder sb = new StringBuilder(""); + + string appx = ", "; + + var treeNodeItemSelectors = nodes as TreeNodeItemSelector[] ?? nodes?.ToArray(); + if (nodes != null && treeNodeItemSelectors!.Any()) + { + if (DataType == typeof(DateTime)) + { + if (treeNodeItemSelectors != null) + { + foreach (TreeNodeItemSelector n in treeNodeItemSelectors) + { + if (n.Checked && !n.Nodes.AsParallel().Cast() + .Any(sn => sn.CheckState != CheckState.Unchecked)) + { + DateTime dt = (DateTime)n.Value!; + sb.Append( + $"'{Convert.ToString(IsFilterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'{appx}"); + } + else if (n.CheckState != CheckState.Unchecked && n.Nodes.Count > 0) + { + string subnode = BuildNodesFilterString(n.Nodes.AsParallel().Cast() + .Where(sn => sn.CheckState != CheckState.Unchecked)); + if (subnode.Length > 0) + { + sb.Append(subnode + appx); + } + } + } + } + } + else if (DataType == typeof(TimeSpan)) + { + if (treeNodeItemSelectors != null) + { + foreach (TreeNodeItemSelector n in treeNodeItemSelectors) + { + if (n.Checked && !n.Nodes.AsParallel().Cast() + .Any(sn => sn.CheckState != CheckState.Unchecked)) + { + TimeSpan ts = (TimeSpan)n.Value!; + sb.Append( + $"'P{(ts.Days > 0 ? $"{ts.Days}D" : "")}{(ts.TotalHours > 0 ? "T" : "")}{(ts.Hours > 0 ? $"{ts.Hours}H" : "")}{(ts.Minutes > 0 ? $"{ts.Minutes}M" : "")}{(ts.Seconds > 0 ? $"{ts.Seconds}S" : "")}'{appx}"); + } + else if (n.CheckState != CheckState.Unchecked && n.Nodes.Count > 0) + { + string subnode = BuildNodesFilterString(n.Nodes.AsParallel().Cast() + .Where(sn => sn.CheckState != CheckState.Unchecked)); + if (subnode.Length > 0) + { + sb.Append(subnode + appx); + } + } + } + } + } + else if (DataType == typeof(bool)) + { + if (treeNodeItemSelectors != null) + { + foreach (TreeNodeItemSelector n in treeNodeItemSelectors) + { + sb.Append(n.Value); + break; + } + } + } + else if (DataType == typeof(int) || DataType == typeof(long) || DataType == typeof(short) || + DataType == typeof(uint) || DataType == typeof(ulong) || DataType == typeof(ushort) || + DataType == typeof(byte) || DataType == typeof(sbyte)) + { + if (treeNodeItemSelectors != null) + { + foreach (TreeNodeItemSelector n in treeNodeItemSelectors) + { + sb.Append(n.Value + appx); + } + } + } + else if (DataType == typeof(float) || DataType == typeof(double) || DataType == typeof(decimal)) + { + if (treeNodeItemSelectors != null) + { + foreach (TreeNodeItemSelector n in treeNodeItemSelectors) + { + sb.Append((n.Value?.ToString() ?? string.Empty).Replace(",", ".") + appx); + } + } + } + else if (DataType == typeof(Bitmap)) + { } + else + { + if (treeNodeItemSelectors != null) + { + foreach (TreeNodeItemSelector n in treeNodeItemSelectors) + { + sb.Append($"'{FormatFilterString(n.Value?.ToString()!)}'{appx}"); + } + } + } + } + + if (sb.Length > appx.Length && DataType != typeof(bool)) + { + sb.Remove(sb.Length - appx.Length, appx.Length); + } + + return sb.ToString(); + } + + /// + /// Format a text Filter string + /// + /// + /// + private static string FormatFilterString(string text) + { + return text.Replace("'", "''"); + } + + /// + /// Add nodes to checkList + /// + /// + private void BuildNodes(IEnumerable? vals) + { + if (!IsFilterChecklistEnabled) + { + return; + } + + ChecklistClearNodes(); + + if (vals != null) + { + //add select all node + TreeNodeItemSelector allNode = TreeNodeItemSelector.CreateNode( + $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectAll)]} ", null, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.SelectAll); + allNode.NodeFont = new Font(_checkList.Font, FontStyle.Bold); + ChecklistAddNode(allNode); + + if (vals.Any()) + { + var noNulls = vals.Where(c => c.Value != null && c.Value != DBNull.Value); + + //add select empty node + IEnumerable dataGridViewCells = noNulls as DataGridViewCell[] ?? noNulls.ToArray(); + if (vals.Count() != dataGridViewCells.Count()) + { + TreeNodeItemSelector nullNode = TreeNodeItemSelector.CreateNode( + $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectEmpty)]} ", null, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.SelectEmpty); + nullNode.NodeFont = new Font(_checkList.Font, FontStyle.Bold); + ChecklistAddNode(nullNode); + } + + //add datetime nodes + if (DataType == typeof(DateTime)) + { + var years = + from year in dataGridViewCells + group year by ((DateTime)year.Value!).Year into cy + orderby cy.Key ascending + select cy; + + foreach (var year in years) + { + TreeNodeItemSelector yearNode = TreeNodeItemSelector.CreateNode(year.Key.ToString(), year.Key, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.DateTimeNode); + ChecklistAddNode(yearNode); + + var months = + from month in year + group month by ((DateTime)month.Value!).Month into cm + orderby cm.Key ascending + select cm; + + foreach (var month in months) + { + TreeNodeItemSelector? monthNode = yearNode.CreateChildNode(CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(month.Key), month.Key); + + var days = + from day in month + group day by ((DateTime)day.Value!).Day into cd + orderby cd.Key ascending + select cd; + + foreach (var day in days) + { + TreeNodeItemSelector? daysNode; + + if (!IsFilterDateAndTimeEnabled) + { + daysNode = monthNode?.CreateChildNode(day.Key.ToString("D2"), day.First().Value); + } + else + { + daysNode = monthNode?.CreateChildNode(day.Key.ToString("D2"), day.Key); + + var hours = + from hour in day + group hour by ((DateTime)hour.Value!).Hour into ch + orderby ch.Key ascending + select ch; + + foreach (var hour in hours) + { + TreeNodeItemSelector? hoursNode = daysNode?.CreateChildNode( + $"{hour.Key:D2} h", hour.Key); + + var mins = + from min in hour + group min by ((DateTime)min.Value!).Minute into cmin + orderby cmin.Key ascending + select cmin; + + foreach (var min in mins) + { + TreeNodeItemSelector? minsNode = hoursNode?.CreateChildNode( + $"{min.Key:D2} m", min.Key); + + var secs = + from sec in min + group sec by ((DateTime)sec.Value!).Second into cs + orderby cs.Key ascending + select cs; + + foreach (var sec in secs) + { + TreeNodeItemSelector? secsNode = minsNode?.CreateChildNode( + $"{sec.Key:D2} s", sec.First().Value); + } + } + } + } + } + } + } + } + + //add timespan nodes + else if (DataType == typeof(TimeSpan)) + { + var days = + from day in dataGridViewCells + group day by ((TimeSpan)day.Value!).Days into cd + orderby cd.Key ascending + select cd; + + foreach (var day in days) + { + TreeNodeItemSelector daysNode = TreeNodeItemSelector.CreateNode(day.Key.ToString("D2"), day.Key, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.DateTimeNode); + ChecklistAddNode(daysNode); + + var hours = + from hour in day + group hour by ((TimeSpan)hour.Value!).Hours into ch + orderby ch.Key ascending + select ch; + + foreach (var hour in hours) + { + TreeNodeItemSelector? hoursNode = daysNode.CreateChildNode($"{hour.Key:D2} h", hour.Key); + + var mins = + from min in hour + group min by ((TimeSpan)min.Value!).Minutes into cmin + orderby cmin.Key ascending + select cmin; + + foreach (var min in mins) + { + TreeNodeItemSelector? minsNode = hoursNode?.CreateChildNode($"{min.Key:D2} m", min.Key); + + var secs = + from sec in min + group sec by ((TimeSpan)sec.Value!).Seconds into cs + orderby cs.Key ascending + select cs; + + foreach (var sec in secs) + { + TreeNodeItemSelector? secsNode = minsNode?.CreateChildNode($"{sec.Key:D2} s", sec.First().Value); + } + } + } + } + } + + //add boolean nodes + else if (DataType == typeof(bool)) + { + var values = dataGridViewCells.Where(c => c.Value is true); + + var gridViewCells = values as DataGridViewCell[] ?? values.ToArray(); + if (gridViewCells.Count() != dataGridViewCells.Count()) + { + TreeNodeItemSelector node = TreeNodeItemSelector.CreateNode(KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectFalse)], false, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.Default); + ChecklistAddNode(node); + } + + if (gridViewCells.Any()) + { + TreeNodeItemSelector node = TreeNodeItemSelector.CreateNode(KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectTrue)], true, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.Default); + ChecklistAddNode(node); + } + } + + //ignore image nodes + else if (DataType == typeof(Bitmap)) + { } + + //add string nodes + else + { + foreach (var v in dataGridViewCells.GroupBy(c => c.Value).OrderBy(g => g.Key)) + { + TreeNodeItemSelector node = TreeNodeItemSelector.CreateNode(v.First().FormattedValue?.ToString(), v.Key, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.Default); + ChecklistAddNode(node); + } + } + } + } + + ChecklistReloadNodes(); + } + + /// + /// Check if filter buttons needs to be enabled + /// + private void CheckFilterButtonEnabled() + { + _buttonFilter.Enabled = HasNodesChecked(_loadedNodes); + } + + /// + /// Check if selected nodes exists + /// + /// + /// + private bool HasNodesChecked(TreeNodeItemSelector?[] nodes) + { + bool state = false; + state = !string.IsNullOrEmpty(_checkTextFilter.Text) ? nodes.Any(n => n!.CheckState == CheckState.Checked && n.Text.ToLower().Contains(_checkTextFilter.Text.ToLower())) : nodes.Any(n => n!.CheckState == CheckState.Checked); + + if (state) + { + return state; + } + + foreach (TreeNodeItemSelector? node in nodes) + { + foreach (TreeNodeItemSelector nodesel in node!.Nodes) + { + state = HasNodesChecked([nodesel]); + if (state) + { + break; + } + } + if (state) + { + break; + } + } + + return state; + } + + /// + /// Check + /// + /// + private void NodeCheckChange(TreeNodeItemSelector? node) + { + if (node != null) + { + node.CheckState = node.CheckState == CheckState.Checked ? CheckState.Unchecked : CheckState.Checked; + + if (node.NodeType == TreeNodeItemSelector.CustomNodeType.SelectAll) + { + SetNodesCheckState(_loadedNodes, node.Checked); + } + else + { + if (node.Nodes.Count > 0) + { + foreach (TreeNodeItemSelector subnode in node.Nodes) + { + SetNodesCheckState([subnode], node.Checked); + } + } + + //refresh nodes + CheckState state = UpdateNodesCheckState(ChecklistNodes()); + GetSelectAllNode()!.CheckState = state; + } + } + } + + /// + /// Set Nodes CheckState + /// + /// + /// + private void SetNodesCheckState(TreeNodeItemSelector?[] nodes, bool isChecked) + { + foreach (TreeNodeItemSelector? node in nodes) + { + node!.Checked = isChecked; + if (node.Nodes is { Count: > 0 }) + { + foreach (TreeNodeItemSelector subnode in node.Nodes) + { + SetNodesCheckState([subnode], isChecked); + } + } + + } + } + + /// + /// Update Nodes CheckState recursively + /// + /// + /// + private CheckState UpdateNodesCheckState(TreeNodeCollection nodes) + { + CheckState result = CheckState.Unchecked; + bool isFirstNode = true; + bool isAllNodesSomeCheckState = true; + + foreach (TreeNodeItemSelector n in nodes.OfType()) + { + if (n.NodeType == TreeNodeItemSelector.CustomNodeType.SelectAll) + { + continue; + } + + if (n.Nodes.Count > 0) + { + n.CheckState = UpdateNodesCheckState(n.Nodes); + } + + if (isFirstNode) + { + result = n.CheckState; + isFirstNode = false; + } + else + { + if (result != n.CheckState) + { + isAllNodesSomeCheckState = false; + } + } + } + + return isAllNodesSomeCheckState ? result : CheckState.Indeterminate; + } + + /// + /// Get the SelectAll Node + /// + /// + private TreeNodeItemSelector? GetSelectAllNode() + { + TreeNodeItemSelector? result = null; + int i = 0; + foreach (TreeNodeItemSelector? n in ChecklistNodes().OfType()) + { + if (n.NodeType == TreeNodeItemSelector.CustomNodeType.SelectAll) + { + result = n; + break; + } + else if (i > 2) + { + break; + } + else + { + i++; + } + } + + return result; + } + + /// + /// Get the SelectEmpty Node + /// + /// + private TreeNodeItemSelector? GetSelectEmptyNode() + { + TreeNodeItemSelector? result = null; + int i = 0; + foreach (TreeNodeItemSelector? n in ChecklistNodes().OfType()) + { + if (n.NodeType == TreeNodeItemSelector.CustomNodeType.SelectEmpty) + { + result = n; + break; + } + else if (i > 2) + { + break; + } + else + { + i++; + } + } + + return result; + } + + /// + /// Duplicate Nodes + /// + private static TreeNodeItemSelector?[] DuplicateNodes(TreeNodeItemSelector?[] nodes) + { + TreeNodeItemSelector?[] ret = new TreeNodeItemSelector[nodes.Length]; + int i = 0; + foreach (TreeNodeItemSelector? n in nodes) + { + ret[i] = n?.Clone(); + i++; + } + return ret; + } + + #endregion + + + #region checklist filter events + + /// + /// CheckList NodeMouseClick event + /// + /// + /// + private void CheckList_NodeMouseClick(object? sender, TreeNodeMouseClickEventArgs e) + { + TreeViewHitTestInfo hitTestInfo = _checkList.HitTest(e.X, e.Y); + if (hitTestInfo is { Location: TreeViewHitTestLocations.StateImage }) + { + //check the node check status + NodeCheckChange(e.Node as TreeNodeItemSelector); + //set filter button enabled + CheckFilterButtonEnabled(); + } + } + + /// + /// CheckList KeyDown event + /// + /// + /// + private void CheckList_KeyDown(object? sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Space) + { + //check the node check status + NodeCheckChange(_checkList.SelectedNode as TreeNodeItemSelector); + //set filter button enabled + CheckFilterButtonEnabled(); + } + } + + /// + /// CheckList NodeMouseDoubleClick event + /// + /// + /// + private void CheckList_NodeMouseDoubleClick(object? sender, TreeNodeMouseClickEventArgs e) + { + TreeNodeItemSelector? n = e.Node as TreeNodeItemSelector; + //set the new node check status + SetNodesCheckState(_loadedNodes, false); + n!.CheckState = CheckState.Unchecked; + NodeCheckChange(n); + //set filter button enabled + CheckFilterButtonEnabled(); + //do Filter by checkList + Button_ok_Click(this, EventArgs.Empty); + } + + /// + /// CheckList MouseEnter event + /// + /// + /// + private void CheckList_MouseEnter(object? sender, EventArgs e) + { + _checkList.Focus(); + } + + /// + /// CheckList MouseLeave event + /// + /// + /// + private void CheckList_MouseLeave(object? sender, EventArgs e) + { + Focus(); + } + + /// + /// Set the Filter by checkList + /// + /// + /// + private void Button_ok_Click(object? sender, EventArgs e) + { + _filterClick = true; + + SetCheckListFilter(); + Close(); + } + + /// + /// Undo changed by checkList + /// + /// + /// + private void Button_cancel_Click(object? sender, EventArgs e) + { + _loadedNodes = DuplicateNodes(_startingNodes); + Close(); + } + + #endregion + + + #region filter methods + + /// + /// UnCheck all Custom Filter presets + /// + private void UnCheckCustomFilters() + { + for (int i = 2; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count; i++) + { + ((_customFilterLastFiltersListMenuItem.DropDownItems[i] as ToolStripMenuItem)!).Checked = false; + } + } + + /// + /// Set a Custom Filter + /// + /// + private void SetCustomFilter(int filtersMenuItemIndex) + { + if (_activeFilterType == FilterType.CheckList) + { + SetNodesCheckState(_loadedNodes, false); + } + + ToolStripItem presetItem = _customFilterLastFiltersListMenuItem.DropDownItems[filtersMenuItemIndex]; + string filterString = presetItem.Tag?.ToString() ?? string.Empty; + string viewFilterString = presetItem.Text ?? string.Empty; + + //do preset jobs + if (filtersMenuItemIndex != 2) + { + for (var i = filtersMenuItemIndex; i > 2; i--) + { + _customFilterLastFiltersListMenuItem.DropDownItems[i].Text = _customFilterLastFiltersListMenuItem.DropDownItems[i - 1].Text; + _customFilterLastFiltersListMenuItem.DropDownItems[i].Tag = _customFilterLastFiltersListMenuItem.DropDownItems[i - 1].Tag; + } + + _customFilterLastFiltersListMenuItem.DropDownItems[2].Text = viewFilterString; + _customFilterLastFiltersListMenuItem.DropDownItems[2].Tag = filterString; + } + + // uncheck other preset + for (var i = 3; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count; i++) + { + ((_customFilterLastFiltersListMenuItem.DropDownItems[i] as ToolStripMenuItem)!).Checked = false; + } + + ((_customFilterLastFiltersListMenuItem.DropDownItems[2] as ToolStripMenuItem)!).Checked = true; + _activeFilterType = FilterType.Custom; + + //get Filter string + string? oldFilter = FilterString; + FilterString = filterString; + + //set CheckList nodes + SetNodesCheckState(_loadedNodes, false); + + _customFilterLastFiltersListMenuItem.Checked = true; + _buttonFilter.Enabled = false; + + //fire Filter changed + if (oldFilter != FilterString && FilterChanged != null) + { + FilterChanged(this, EventArgs.Empty); + } + } + + #endregion + + + #region filter events + + /// + /// Cancel Filter Click event + /// + /// + /// + private void CancelFilterMenuItem_Click(object? sender, EventArgs e) + { + string? oldFilter = FilterString; + + //clean Filter + CleanFilter(); + + //fire Filter changed + if (oldFilter != FilterString && FilterChanged != null) + { + FilterChanged(this, EventArgs.Empty); + } + } + + /// + /// Cancel Filter MouseEnter event + /// + /// + /// + private void CancelFilterMenuItem_MouseEnter(object? sender, EventArgs e) + { + if (((sender as ToolStripMenuItem)!).Enabled) + { + ((sender as ToolStripMenuItem)!).Select(); + } + } + + /// + /// Custom Filter Click event + /// + /// + /// + private void CustomFilterMenuItem_Click(object? sender, EventArgs e) + { + //ignore image nodes + if (DataType == typeof(Bitmap)) + { + return; + } + + //open a new Custom filter window + VisualCustomFilterForm flt = new VisualCustomFilterForm(DataType, IsFilterDateAndTimeEnabled); + + if (flt.ShowDialog() == DialogResult.OK) + { + //add the new Filter presets + + string? filterString = flt.FilterString; + string? viewFilterString = flt.FilterStringDescription; + + int index = -1; + + for (int i = 2; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count; i++) + { + if (_customFilterLastFiltersListMenuItem.DropDown.Items[i].Available) + { + ToolStripItem presetRow = _customFilterLastFiltersListMenuItem.DropDownItems[i]; + if (string.Equals(presetRow.Text, viewFilterString, StringComparison.Ordinal) + && string.Equals(presetRow.Tag?.ToString(), filterString, StringComparison.Ordinal)) + { + index = i; + break; + } + } + else + { + break; + } + } + + if (index < 2) + { + for (int i = _customFilterLastFiltersListMenuItem.DropDownItems.Count - 2; i > 1; i--) + { + if (_customFilterLastFiltersListMenuItem.DropDownItems[i].Available) + { + _customFilterLastFiltersListMenuItem.DropDownItems[i + 1].Text = _customFilterLastFiltersListMenuItem.DropDownItems[i].Text; + _customFilterLastFiltersListMenuItem.DropDownItems[i + 1].Tag = _customFilterLastFiltersListMenuItem.DropDownItems[i].Tag; + } + } + index = 2; + + _customFilterLastFiltersListMenuItem.DropDownItems[2].Text = viewFilterString; + _customFilterLastFiltersListMenuItem.DropDownItems[2].Tag = filterString; + } + + //set the Custom Filter + SetCustomFilter(index); + } + } + + /// + /// Custom Filter preset MouseEnter event + /// + /// + /// + private void CustomFilterLastFiltersListMenuItem_MouseEnter(object? sender, EventArgs e) + { + if (((sender as ToolStripMenuItem)!).Enabled) + { + ((sender as ToolStripMenuItem)!).Select(); + } + } + + /// + /// Custom Filter preset MouseEnter event + /// + /// + /// + private void CustomFilterLastFiltersListMenuItem_Paint(object? sender, PaintEventArgs e) + { + Rectangle rect = new Rectangle(_customFilterLastFiltersListMenuItem.Width - 12, 7, 10, 10); + ControlPaint.DrawMenuGlyph(e.Graphics, rect, MenuGlyph.Arrow, Color.Black, Color.Transparent); + } + + /// + /// Custom Filter preset 1 Visibility changed + /// + /// + /// + private void CustomFilterLastFilter1MenuItem_VisibleChanged(object? sender, EventArgs e) + { + _toolStripSeparator2MenuItem.Visible = !_customFilterLastFilter1MenuItem.Visible; + ((sender as ToolStripMenuItem)!).VisibleChanged -= CustomFilterLastFilter1MenuItem_VisibleChanged; + } + + /// + /// Custom Filter preset Click event + /// + /// + /// + private void CustomFilterLastFilterMenuItem_Click(object? sender, EventArgs e) + { + if (sender is not ToolStripMenuItem menuitem) + { + return; + } + + for (int i = 2; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count; i++) + { + ToolStripItem presetRow = _customFilterLastFiltersListMenuItem.DropDownItems[i]; + if (string.Equals(presetRow.Text, menuitem.Text, StringComparison.Ordinal) + && string.Equals(presetRow.Tag?.ToString(), menuitem.Tag?.ToString(), StringComparison.Ordinal)) + { + //set current filter preset as active + SetCustomFilter(i); + break; + } + } + } + + /// + /// Custom Filter preset TextChanged event + /// + /// + /// + private void CustomFilterLastFilterMenuItem_TextChanged(object? sender, EventArgs e) + { + ((sender as ToolStripMenuItem)!).Available = true; + ((sender as ToolStripMenuItem)!).TextChanged -= CustomFilterLastFilterMenuItem_TextChanged; + } + + /// + /// Text changed timer + /// + /// + /// + private void CheckTextFilterTextChangedTimer_Tick(object? sender, EventArgs e) + { + if (sender is not Timer timer) + { + return; + } + + CheckTextFilterHandleTextChanged(timer.Tag?.ToString() ?? string.Empty); + + timer.Stop(); + } + + /// + /// Check list filter changer + /// + /// + /// + private void CheckTextFilter_TextChanged(object? sender, EventArgs e) + { + if (!_checkTextFilterChangedEnabled) + { + return; + } + + if (_textFilterTextChangedDelayNodes != TextFilterTextChangedDelayNodesDisabled && _loadedNodes.Length > _textFilterTextChangedDelayNodes) + { + if (_textFilterTextChangedTimer == null) + { + _textFilterTextChangedTimer = new Timer(); + _textFilterTextChangedTimer.Tick += new EventHandler(CheckTextFilterTextChangedTimer_Tick); + } + _textFilterTextChangedTimer.Stop(); + _textFilterTextChangedTimer.Interval = _textFilterTextChangedDelayMs; + _textFilterTextChangedTimer.Tag = _checkTextFilter.Text.ToLower(); + _textFilterTextChangedTimer.Start(); + } + else + { + CheckTextFilterHandleTextChanged(_checkTextFilter.Text.ToLower()); + } + } + + /// + /// Handle check filter text changed + /// + /// + private void CheckTextFilterHandleTextChanged(string text) + { + TreeNodeItemSelector allNode = TreeNodeItemSelector.CreateNode( + $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectAll)]} ", null, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.SelectAll); + TreeNodeItemSelector nullNode = TreeNodeItemSelector.CreateNode( + $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectEmpty)]} ", null, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.SelectEmpty); + string?[] removedNodesText = []; + if (_checkTextFilterRemoveNodesOnSearch) + { + removedNodesText = _removedSessionNodes.Where(r => !string.IsNullOrEmpty(r?.Text)).Select(r => r?.Text.ToLower()).Distinct().ToArray(); + } + for (int i = _loadedNodes.Length - 1; i >= 0; i--) + { + TreeNodeItemSelector? node = _loadedNodes[i]; + if (node?.Text == allNode.Text) + { + node.CheckState = CheckState.Indeterminate; + } + else if (node?.Text == nullNode.Text) + { + node.CheckState = CheckState.Unchecked; + } + else + { + if (node != null) + { + node.CheckState = node.Text.ToLower().Contains(text) + ? CheckState.Unchecked + : CheckState.Checked; + + if (removedNodesText.Contains(node.Text.ToLower())) + { + node.CheckState = CheckState.Checked; + } + + NodeCheckChange(node); + } + } + } + //set filter button enabled + CheckFilterButtonEnabled(); + _removedNodes = _removedSessionNodes; + if (_checkTextFilterRemoveNodesOnSearch) + { + for (int i = _loadedNodes.Length - 1; i >= 0; i--) + { + TreeNodeItemSelector? node = _loadedNodes[i]; + if (!(node?.Text == allNode.Text || node?.Text == nullNode.Text)) + { + if (!node!.Text.ToLower().Contains(text)) + { + _removedNodes = _removedNodes.Concat([node]).ToArray(); + } + } + } + ChecklistReloadNodes(); + } + } + + #endregion + + + #region sort events + + /// + /// Sort ASC Click event + /// + /// + /// + private void SortASCMenuItem_Click(object? sender, EventArgs? e) + { + //ignore image nodes + if (DataType == typeof(Bitmap)) + { + return; + } + + _sortAscMenuItem.Checked = true; + _sortDescMenuItem.Checked = false; + _activeSortType = SortType.Asc; + + //get Sort String + string? oldSort = SortString; + SortString = "[{0}] ASC"; + + //fire Sort Changed + if (oldSort != SortString && SortChanged != null) + { + SortChanged(this, EventArgs.Empty); + } + } + + /// + /// Sort ASC MouseEnter event + /// + /// + /// + private void SortASCMenuItem_MouseEnter(object? sender, EventArgs e) + { + if (((sender as ToolStripMenuItem)!).Enabled) + { + ((ToolStripMenuItem)sender).Select(); + } + } + + /// + /// Sort DESC Click event + /// + /// + /// + private void SortDESCMenuItem_Click(object? sender, EventArgs? e) + { + //ignore image nodes + if (DataType == typeof(Bitmap)) + { + return; + } + + _sortAscMenuItem.Checked = false; + _sortDescMenuItem.Checked = true; + _activeSortType = SortType.Desc; + + //get Sort String + string? oldSort = SortString; + SortString = "[{0}] DESC"; + + //fire Sort Changed + if (oldSort != SortString && SortChanged != null) + { + SortChanged(this, EventArgs.Empty); + } + } + + /// + /// Sort DESC MouseEnter event + /// + /// + /// + private void SortDESCMenuItem_MouseEnter(object? sender, EventArgs e) + { + if (((sender as ToolStripMenuItem)!).Enabled) + { + ((ToolStripMenuItem)sender).Select(); + } + } + + /// + /// Cancel Sort Click event + /// + /// + /// + private void CancelSortMenuItem_Click(object? sender, EventArgs e) + { + string? oldSort = SortString; + //clean Sort + CleanSort(); + //fire Sort changed + if (oldSort != SortString && SortChanged != null) + { + SortChanged(this, EventArgs.Empty); + } + } + + /// + /// Cancel Sort MouseEnter event + /// + /// + /// + private void CancelSortMenuItem_MouseEnter(object? sender, EventArgs e) + { + if (sender is ToolStripMenuItem menuItem && menuItem.Enabled) + { + menuItem.Select(); + } + } + + #endregion + + + #region resize methods + + /// + /// Get the scaling factor + /// + /// + private float GetScalingFactor() + { + float ret = 1; + using (Graphics gScale = CreateGraphics()) + { + try + { + ret = gScale.DpiX / 96.0F; + } + catch (Exception e) + { + KryptonExceptionHandler.CaptureException(e); + } + } + return ret; + } + + /// + /// Scale an item + /// + /// + /// + /// + private static int Scale(int dimension, float factor) + { + return (int)Math.Floor(dimension * factor); + } + + /// + /// Resize the box + /// + /// + /// + /// + private void ResizeBox(int w, int h) + { + _sortAscMenuItem.Width = w - 1; + _sortDescMenuItem.Width = w - 1; + _cancelSortMenuItem.Width = w - 1; + _cancelFilterMenuItem.Width = w - 1; + _customFilterMenuItem.Width = w - 1; + _customFilterLastFiltersListMenuItem.Width = w - 1; + _checkTextFilterControlHost.Width = w - 35; + + //scale objects using original width and height + float scalingFactor = GetScalingFactor(); + int w2 = (int)Math.Round(w / scalingFactor, 0); + int h2 = (int)Math.Round(h / scalingFactor, 0); + _checkFilterListControlHost.Size = new Size(Scale(w2 - 35, scalingFactor), Scale(h2 - 160 - 25, scalingFactor)); + _checkFilterListPanel.Size = _checkFilterListControlHost.Size; + _checkList.Bounds = new Rectangle(Scale(4, scalingFactor), Scale(4, scalingFactor), Scale(w2 - 35 - 8, scalingFactor), Scale(h2 - 160 - 25 - 8, scalingFactor)); + _checkFilterListButtonsControlHost.Size = new Size(Scale(w2 - 35, scalingFactor), Scale(24, scalingFactor)); + _buttonFilter.Location = new Point(Scale(w2 - 35 - 164, scalingFactor), 0); + _buttonUndofilter.Location = new Point(Scale(w2 - 35 - 79, scalingFactor), 0); + _resizeBoxControlHost.Margin = new Padding(Scale(w2 - 46, scalingFactor), 0, 0, 0); + + //get all objects height to make sure we have room for the grip + int finalHeight = + _sortAscMenuItem.Height + + _sortDescMenuItem.Height + + _cancelSortMenuItem.Height + + _cancelFilterMenuItem.Height + + _toolStripSeparator1MenuItem.Height + + _toolStripSeparator2MenuItem.Height + + _customFilterLastFiltersListMenuItem.Height + + _toolStripSeparator3MenuItem.Height + + _checkFilterListControlHost.Height + + _checkTextFilterControlHost.Height + + _checkFilterListButtonsControlHost.Height + + _resizeBoxControlHost.Height; + + // apply the needed height only when scaled + Size = Math.Abs(scalingFactor - 1) < 1 ? new Size(w, h) : new Size(w, h + (finalHeight - h < 0 ? 0 : finalHeight - h)); + } + + /// + /// Clean box for Resize + /// + private void ResizeClean() + { + if (_resizeEndPoint.X != -1) + { + Point startPoint = PointToScreen(_resizeStartPoint); + + Rectangle rc = new Rectangle(startPoint.X, startPoint.Y, _resizeEndPoint.X, _resizeEndPoint.Y) + { + X = Math.Min(startPoint.X, _resizeEndPoint.X), + Width = Math.Abs(startPoint.X - _resizeEndPoint.X), + + Y = Math.Min(startPoint.Y, _resizeEndPoint.Y), + Height = Math.Abs(startPoint.Y - _resizeEndPoint.Y) + }; + + ControlPaint.DrawReversibleFrame(rc, Color.Black, FrameStyle.Dashed); + + _resizeEndPoint.X = -1; + } + } + + #endregion + + + #region resize events + + /// + /// Resize MouseDown event + /// + /// + /// + private void ResizeBoxControlHost_MouseDown(object? sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + ResizeClean(); + } + } + + /// + /// Resize MouseMove event + /// + /// + /// + private void ResizeBoxControlHost_MouseMove(object? sender, MouseEventArgs e) + { + if (Visible) + { + if (e.Button == MouseButtons.Left) + { + int x = e.X; + int y = e.Y; + + ResizeClean(); + + x += Width - _resizeBoxControlHost.Width; + y += Height - _resizeBoxControlHost.Height; + + x = Math.Max(x, MinimumSize.Width - 1); + y = Math.Max(y, MinimumSize.Height - 1); + + Point startPoint = PointToScreen(_resizeStartPoint); + Point endPoint = PointToScreen(new Point(x, y)); + + Rectangle rc = new Rectangle + { + X = Math.Min(startPoint.X, endPoint.X), + Width = Math.Abs(startPoint.X - endPoint.X), + + Y = Math.Min(startPoint.Y, endPoint.Y), + Height = Math.Abs(startPoint.Y - endPoint.Y) + }; + + ControlPaint.DrawReversibleFrame(rc, Color.Black, FrameStyle.Dashed); + + _resizeEndPoint.X = endPoint.X; + _resizeEndPoint.Y = endPoint.Y; + } + } + } + + /// + /// Resize MouseUp event + /// + /// + /// + private void ResizeBoxControlHost_MouseUp(object? sender, MouseEventArgs e) + { + if (_resizeEndPoint.X != -1) + { + ResizeClean(); + + if (Visible) + { + if (e.Button == MouseButtons.Left) + { + int newWidth = e.X + Width - _resizeBoxControlHost.Width; + int newHeight = e.Y + Height - _resizeBoxControlHost.Height; + + newWidth = Math.Max(newWidth, MinimumSize.Width); + newHeight = Math.Max(newHeight, MinimumSize.Height); + + ResizeBox(newWidth, newHeight); + } + } + } + } + + /// + /// Resize Paint event + /// + /// + /// + private void ResizeBoxControlHost_Paint(object? sender, PaintEventArgs e) + { + e.Graphics.DrawImage(Properties.Resources.MenuStrip_ResizeGrip, 0, 0); + } + + #endregion + +} diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/TreeNodeItemSelector.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/TreeNodeItemSelector.cs new file mode 100644 index 0000000000..04dd178dac --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/TreeNodeItemSelector.cs @@ -0,0 +1,191 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +namespace Krypton.Utilities; + +internal class TreeNodeItemSelector : TreeNode +{ + #region public enum + + public enum CustomNodeType : byte + { + Default, + SelectAll, + SelectEmpty, + DateTimeNode + } + + #endregion + + + #region class properties + + private CheckState _checkState = CheckState.Unchecked; + private TreeNodeItemSelector? _parent; + + #endregion + + + #region constructor + + /// + /// TreeNodeItemSelector constructor + /// + /// + /// + /// + /// + private TreeNodeItemSelector(string? text, object? value, CheckState state, CustomNodeType nodeType) + : base(text) + { + CheckState = state; + NodeType = nodeType; + Value = value; + } + + #endregion + + + #region public clone method + + /// + /// Clone a Node + /// + /// + public new TreeNodeItemSelector Clone() + { + TreeNodeItemSelector n = new TreeNodeItemSelector(Text, Value, _checkState, NodeType) + { + NodeFont = NodeFont + }; + + if (GetNodeCount(false) > 0) + { + foreach (TreeNodeItemSelector? child in Nodes) + { + if (child != null) + { + n.AddChild(child.Clone()); + } + } + } + + return n; + } + + #endregion + + + #region public getters / setters + + /// + /// Get Node NodeType + /// + public CustomNodeType NodeType { get; private set; } + + /// + /// Get Node value + /// + public object? Value { get; private set; } + + /// + /// Get Node parent + /// + public new TreeNodeItemSelector? Parent + { + get => _parent; + set => _parent = value; + } + + /// + /// Node is Checked + /// + public new bool Checked + { + get => _checkState == CheckState.Checked; + set => CheckState = value ? CheckState.Checked : CheckState.Unchecked; + } + + /// + /// Get or Set the current Node CheckState + /// + public CheckState CheckState + { + get => _checkState; + set + { + _checkState = value; + StateImageIndex = _checkState switch + { + CheckState.Checked => 1, + CheckState.Indeterminate => 2, + _ => 0 + }; + } + } + + #endregion + + + #region public create nodes methods + + /// + /// Create a Node + /// + /// + /// + /// + /// + /// + public static TreeNodeItemSelector CreateNode(string? text, object? value, CheckState state, CustomNodeType type) + { + return new TreeNodeItemSelector(text, value, state, type); + } + + /// + /// Create a child Node + /// + /// + /// + /// + /// + public TreeNodeItemSelector? CreateChildNode(string? text, object? value, CheckState state) + { + TreeNodeItemSelector? n = null; + + //specific method for datetimenode + if (NodeType == CustomNodeType.DateTimeNode) + { + n = new TreeNodeItemSelector(text, value, state, CustomNodeType.DateTimeNode); + } + + if (n != null) + { + AddChild(n); + } + + return n; + } + public TreeNodeItemSelector? CreateChildNode(string? text, object? value) + { + return CreateChildNode(text, value, _checkState); + } + + /// + /// Add a child Node to this Node + /// + /// + protected void AddChild(TreeNodeItemSelector? child) + { + child!.Parent = this; + Nodes.Add(child); + } + + #endregion +} diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.Designer.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.Designer.cs new file mode 100644 index 0000000000..8e6773eeee --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.Designer.cs @@ -0,0 +1,176 @@ +namespace Krypton.Utilities +{ + partial class VisualCustomFilterForm + { + /// + /// 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() + { + this.components = new System.ComponentModel.Container(); + this.kryptonPanel1 = new Krypton.Toolkit.KryptonPanel(); + this.button_cancel = new Krypton.Toolkit.KryptonButton(); + this.button_ok = new Krypton.Toolkit.KryptonButton(); + this.kryptonBorderEdge1 = new Krypton.Toolkit.KryptonBorderEdge(); + this.kryptonPanel2 = new Krypton.Toolkit.KryptonPanel(); + this.label_columnName = new Krypton.Toolkit.KryptonLabel(); + this.comboBox_filterType = new Krypton.Toolkit.KryptonComboBox(); + this.label_and = new Krypton.Toolkit.KryptonLabel(); + this.ep = new Krypton.Toolkit.KryptonErrorProvider(this.components); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel1)).BeginInit(); + this.kryptonPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel2)).BeginInit(); + this.kryptonPanel2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBox_filterType)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ep)).BeginInit(); + this.SuspendLayout(); + // + // kryptonPanel1 + // + this.kryptonPanel1.Controls.Add(this.button_cancel); + this.kryptonPanel1.Controls.Add(this.button_ok); + this.kryptonPanel1.Controls.Add(this.kryptonBorderEdge1); + this.kryptonPanel1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.kryptonPanel1.Location = new System.Drawing.Point(0, 126); + this.kryptonPanel1.Name = "kryptonPanel1"; + this.kryptonPanel1.PanelBackStyle = Krypton.Toolkit.PaletteBackStyle.PanelAlternate; + this.kryptonPanel1.Size = new System.Drawing.Size(205, 50); + this.kryptonPanel1.TabIndex = 1; + // + // button_cancel + // + this.button_cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button_cancel.Location = new System.Drawing.Point(118, 15); + this.button_cancel.Name = "button_cancel"; + this.button_cancel.Size = new System.Drawing.Size(75, 23); + this.button_cancel.TabIndex = 3; + this.button_cancel.Values.Text = "Cancel"; + this.button_cancel.Click += new System.EventHandler(this.button_cancel_Click); + // + // button_ok + // + this.button_ok.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button_ok.Location = new System.Drawing.Point(37, 15); + this.button_ok.Name = "button_ok"; + this.button_ok.Size = new System.Drawing.Size(75, 23); + this.button_ok.TabIndex = 2; + this.button_ok.Values.Text = "OK"; + this.button_ok.Click += new System.EventHandler(this.button_ok_Click); + // + // kryptonBorderEdge1 + // + this.kryptonBorderEdge1.BorderStyle = Krypton.Toolkit.PaletteBorderStyle.HeaderSecondary; + this.kryptonBorderEdge1.Dock = System.Windows.Forms.DockStyle.Top; + this.kryptonBorderEdge1.Location = new System.Drawing.Point(0, 0); + this.kryptonBorderEdge1.Name = "kryptonBorderEdge1"; + this.kryptonBorderEdge1.Size = new System.Drawing.Size(205, 1); + this.kryptonBorderEdge1.Text = "kryptonBorderEdge1"; + // + // kryptonPanel2 + // + this.kryptonPanel2.Controls.Add(this.label_columnName); + this.kryptonPanel2.Controls.Add(this.comboBox_filterType); + this.kryptonPanel2.Controls.Add(this.label_and); + this.kryptonPanel2.Dock = System.Windows.Forms.DockStyle.Fill; + this.kryptonPanel2.Location = new System.Drawing.Point(0, 0); + this.kryptonPanel2.Name = "kryptonPanel2"; + this.kryptonPanel2.Size = new System.Drawing.Size(205, 126); + this.kryptonPanel2.TabIndex = 2; + // + // label_columnName + // + this.label_columnName.LabelStyle = Krypton.Toolkit.LabelStyle.NormalPanel; + this.label_columnName.Location = new System.Drawing.Point(6, 13); + this.label_columnName.Name = "label_columnName"; + this.label_columnName.Size = new System.Drawing.Size(138, 20); + this.label_columnName.TabIndex = 7; + this.label_columnName.Values.Text = "Show rows where value"; + // + // comboBox_filterType + // + this.comboBox_filterType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_filterType.DropDownWidth = 189; + this.comboBox_filterType.FormattingEnabled = true; + this.comboBox_filterType.IntegralHeight = false; + this.comboBox_filterType.Location = new System.Drawing.Point(9, 39); + this.comboBox_filterType.Name = "comboBox_filterType"; + this.comboBox_filterType.Size = new System.Drawing.Size(189, 21); + this.comboBox_filterType.TabIndex = 8; + this.comboBox_filterType.SelectedIndexChanged += new System.EventHandler(this.comboBox_filterType_SelectedIndexChanged); + // + // label_and + // + this.label_and.LabelStyle = Krypton.Toolkit.LabelStyle.NormalPanel; + this.label_and.Location = new System.Drawing.Point(9, 93); + this.label_and.Name = "label_and"; + this.label_and.Size = new System.Drawing.Size(33, 20); + this.label_and.TabIndex = 9; + this.label_and.Values.Text = "And"; + this.label_and.Visible = false; + // + // ep + // + this.ep.ContainerControl = this; + // + // FormCustomFilter + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(205, 176); + this.Controls.Add(this.kryptonPanel2); + this.Controls.Add(this.kryptonPanel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "FormCustomFilter"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Custom Filter"; + this.Controls.SetChildIndex(this.kryptonPanel1, 0); + this.Controls.SetChildIndex(this.kryptonPanel2, 0); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel1)).EndInit(); + this.kryptonPanel1.ResumeLayout(false); + this.kryptonPanel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel2)).EndInit(); + this.kryptonPanel2.ResumeLayout(false); + this.kryptonPanel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBox_filterType)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ep)).EndInit(); + this.ResumeLayout(false); + } + + #endregion + + private KryptonPanel kryptonPanel1; + private KryptonBorderEdge kryptonBorderEdge1; + private KryptonButton button_cancel; + private KryptonButton button_ok; + private KryptonPanel kryptonPanel2; + private KryptonLabel label_columnName; + private KryptonComboBox comboBox_filterType; + private KryptonLabel label_and; + private KryptonErrorProvider ep; + } +} \ No newline at end of file diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.cs new file mode 100644 index 0000000000..98e8f4ec89 --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.cs @@ -0,0 +1,527 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +namespace Krypton.Utilities; + +public partial class VisualCustomFilterForm : KryptonForm +{ + #region Instance Fields + + private readonly FilterType _filterType; + private Control? _valControl1; + private Control? _valControl2; + + private readonly bool _filterDateAndTimeEnabled; + + private string? _filterString; + + private string? _filterStringDescription; + + #endregion + + #region Public + + /// + /// Get the Filter string + /// + public string? FilterString => _filterString; + + /// + /// Get the Filter string description + /// + public string? FilterStringDescription => _filterStringDescription; + + #endregion + + #region Identity + + /// + /// Initializes a new instance of the class. + /// + /// Type of the data. + /// if set to true [filter date and time enabled]. + public VisualCustomFilterForm(Type dataType, bool filterDateAndTimeEnabled) + { + InitializeComponent(); + + //set component translations + Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewFormTitle)]; + label_columnName.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLabelColumnNameText)]; + label_and.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLabelAnd)]; + button_ok.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewButtonOk)]; + button_cancel.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewButtonCancel)]; + + _filterType = dataType switch + { + _ when dataType == typeof(DateTime) => FilterType.DateTime, + _ when dataType == typeof(TimeSpan) => FilterType.TimeSpan, + _ when dataType == typeof(int) || dataType == typeof(long) || dataType == typeof(short) || + dataType == typeof(uint) || dataType == typeof(ulong) || dataType == typeof(ushort) || + dataType == typeof(byte) || dataType == typeof(sbyte) => FilterType.Integer, + _ when dataType == typeof(float) || dataType == typeof(double) || dataType == typeof(decimal) => FilterType.Float, + _ when dataType == typeof(string) => FilterType.String, + _ => FilterType.Unknown + }; + + _filterDateAndTimeEnabled = filterDateAndTimeEnabled; + + switch (_filterType) + { + case FilterType.DateTime: + _valControl1 = new DateTimePicker(); + _valControl2 = new DateTimePicker(); + if (_filterDateAndTimeEnabled) + { + DateTimeFormatInfo dt = Thread.CurrentThread.CurrentCulture.DateTimeFormat; + + (_valControl1 as DateTimePicker)!.CustomFormat = $@"{dt.ShortDatePattern} HH:mm"; + (_valControl2 as DateTimePicker)!.CustomFormat = $@"{dt.ShortDatePattern} HH:mm"; + (_valControl1 as DateTimePicker)!.Format = DateTimePickerFormat.Custom; + (_valControl2 as DateTimePicker)!.Format = DateTimePickerFormat.Custom; + } + else + { + (_valControl1 as DateTimePicker)!.Format = DateTimePickerFormat.Short; + (_valControl2 as DateTimePicker)!.Format = DateTimePickerFormat.Short; + } + + comboBox_filterType.Items.AddRange([ + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThan)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThanOrEqualTo)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThan)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThanOrEqualTo)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBetween)] + ]); + break; + + case FilterType.TimeSpan: + _valControl1 = new TextBox(); + _valControl2 = new TextBox(); + comboBox_filterType.Items.AddRange([ + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewContains)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotContain)] + ]); + break; + + case FilterType.Integer: + case FilterType.Float: + _valControl1 = new TextBox(); + _valControl2 = new TextBox(); + _valControl1.TextChanged += valControl_TextChanged; + _valControl2.TextChanged += valControl_TextChanged; + comboBox_filterType.Items.AddRange([ + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThan)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThanOrEqualTo)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLessThan)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLessThanOrEqualTo)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBetween)] + ]); + _valControl1.Tag = true; + _valControl2.Tag = true; + button_ok.Enabled = false; + break; + + default: + _valControl1 = new TextBox(); + _valControl2 = new TextBox(); + comboBox_filterType.Items.AddRange([ + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBeginsWith)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotBeginWith)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEndsWith)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEndWith)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewContains)], + KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotContain)] + ]); + break; + } + comboBox_filterType.SelectedIndex = 0; + + _valControl1.Name = "valControl1"; + _valControl1.Location = new(20, 66); + _valControl1.Size = new(166, 20); + _valControl1.Width = comboBox_filterType.Width - 20; + _valControl1.TabIndex = 4; + _valControl1.Visible = true; + _valControl1.KeyDown += valControl_KeyDown; + + _valControl2.Name = "valControl2"; + _valControl2.Location = new(20, 108); + _valControl2.Size = new(166, 20); + _valControl2.Width = comboBox_filterType.Width - 20; + _valControl2.TabIndex = 5; + _valControl2.Visible = false; + _valControl2.VisibleChanged += valControl2_VisibleChanged; + _valControl2.KeyDown += valControl_KeyDown; + + Controls.Add(_valControl1); + Controls.Add(_valControl2); + + ep.SetIconAlignment(_valControl1, KryptonErrorIconAlignment.MiddleRight); + ep.SetIconPadding(_valControl1, -18); + ep.SetIconAlignment(_valControl2, KryptonErrorIconAlignment.MiddleRight); + ep.SetIconPadding(_valControl2, -18); + } + + #endregion + + #region Implementation + + /// + /// Build a Filter string + /// + /// + /// + /// + /// + /// + /// + private string? BuildCustomFilter(FilterType filterType, bool filterDateAndTimeEnabled, string filterTypeConditionText, Control control1, Control control2) + { + string? filterString; + + string? column = @"[{0}] "; + + if (filterType == FilterType.Unknown) + { + column = $"Convert([{{0}}], 'System.String') "; + } + + filterString = column; + + switch (filterType) + { + case FilterType.DateTime: + DateTime dt = ((DateTimePicker)control1).Value; + dt = new(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0); + + if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)]) + { + filterString = + $"Convert([{{0}}], 'System.String') LIKE '%{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}%'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThan)]) + { + filterString += + $"< '{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThanOrEqualTo)]) + { + filterString += + $"<= '{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThan)]) + { + filterString += + $"> '{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThanOrEqualTo)]) + { + filterString += + $">= '{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBetween)]) + { + DateTime dt1 = ((DateTimePicker)control2).Value; + dt1 = new(dt1.Year, dt1.Month, dt1.Day, dt1.Hour, dt1.Minute, 0); + filterString += + $">= '{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'"; + filterString += + $" AND {column}<= '{Convert.ToString(filterDateAndTimeEnabled ? dt1 : dt1.Date, CultureInfo.CurrentCulture)}'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)]) + { + filterString = + $"Convert([{{0}}], 'System.String') NOT LIKE '%{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}%'"; + } + + break; + + case FilterType.TimeSpan: + try + { + TimeSpan ts = TimeSpan.Parse(control1.Text); + + if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewContains)]) + { + filterString = + $"(Convert([{{0}}], 'System.String') LIKE '%P{(ts.Days > 0 ? $"{ts.Days}D" : "")}{(ts.TotalHours > 0 ? "T" : "")}{(ts.Hours > 0 ? $"{ts.Hours}H" : "")}{(ts.Minutes > 0 ? $"{ts.Minutes}M" : "")}{(ts.Seconds > 0 ? $"{ts.Seconds}S" : "")}%')"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotContain)]) + { + filterString = + $"(Convert([{{0}}], 'System.String') NOT LIKE '%P{(ts.Days > 0 ? $"{ts.Days}D" : "")}{(ts.TotalHours > 0 ? "T" : "")}{(ts.Hours > 0 ? $"{ts.Hours}H" : "")}{(ts.Minutes > 0 ? $"{ts.Minutes}M" : "")}{(ts.Seconds > 0 ? $"{ts.Seconds}S" : "")}%')"; + } + } + catch (FormatException) + { + filterString = null; + } + break; + + case FilterType.Integer: + case FilterType.Float: + + string num = control1.Text; + + if (filterType == FilterType.Float) + { + num = num.Replace(",", "."); + } + + if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)]) + { + filterString += $"= {num}"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBetween)]) + { + filterString += + $">= {num} AND {column}<= {(filterType == FilterType.Float ? control2.Text.Replace(",", ".") : control2.Text)}"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)]) + { + filterString += $"<> {num}"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThan)]) + { + filterString += $"> {num}"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThanOrEqualTo)]) + { + filterString += $">= {num}"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLessThan)]) + { + filterString += $"< {num}"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLessThanOrEqualTo)]) + { + filterString += $"<= {num}"; + } + + break; + + default: + string txt = FormatFilterString(control1.Text); + if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)]) + { + filterString += $"LIKE '{txt}'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)]) + { + filterString += $"NOT LIKE '{txt}'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBeginsWith)]) + { + filterString += $"LIKE '{txt}%'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEndsWith)]) + { + filterString += $"LIKE '%{txt}'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotBeginWith)]) + { + filterString += $"NOT LIKE '{txt}%'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEndWith)]) + { + filterString += $"NOT LIKE '%{txt}'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewContains)]) + { + filterString += $"LIKE '%{txt}%'"; + } + else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotContain)]) + { + filterString += $"NOT LIKE '%{txt}%'"; + } + + break; + } + + return filterString; + } + + /// + /// Format a text Filter string + /// + /// + /// + private string FormatFilterString(string text) + { + string result = ""; + string s; + string[] replace = ["%", "[", "]", "*", "\"", "\\"]; + + for (int i = 0; i < text.Length; i++) + { + s = text[i].ToString(); + if (replace.Contains(s)) + { + result += $"[{s}]"; + } + else + { + result += s; + } + } + + return result.Replace("'", "''"); + } + + private void button_cancel_Click(object sender, EventArgs e) + { + _filterStringDescription = null; + _filterString = null; + DialogResult = DialogResult.Cancel; + } + + private void button_ok_Click(object sender, EventArgs e) + { + if (_valControl1 != null && _valControl2 != null && ((_valControl1.Visible && _valControl1.Tag != null && (bool)_valControl1.Tag) || + (_valControl2.Visible && _valControl2.Tag != null && (bool)_valControl2.Tag))) + { + button_ok.Enabled = false; + return; + } + + if (_valControl1 != null) + { + if (_valControl2 != null) + { + string? filterString = BuildCustomFilter(_filterType, _filterDateAndTimeEnabled, comboBox_filterType.Text, _valControl1, _valControl2); + + if (!String.IsNullOrEmpty(filterString)) + { + _filterString = filterString; + _filterStringDescription = string.Format(KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewFilterStringDescription)], comboBox_filterType.Text, _valControl1.Text); + if (_valControl2.Visible) + { + _filterStringDescription += $" {label_and.Text} \"{_valControl2.Text}\""; + } + + DialogResult = DialogResult.OK; + } + else + { + _filterString = null; + _filterStringDescription = null; + DialogResult = DialogResult.Cancel; + } + } + } + + Close(); + } + + private void comboBox_filterType_SelectedIndexChanged(object sender, EventArgs e) + { + if (_valControl2 != null) + { + _valControl2.Visible = comboBox_filterType.Text == + KryptonAdvancedDataGridView.Translations[ + nameof(TranslationKey.KryptonAdvancedDataGridViewBetween)]; + if (_valControl1 != null) + { + button_ok.Enabled = + !(_valControl1.Visible && _valControl1.Tag != null && (bool)_valControl1.Tag) || + (_valControl2.Visible && _valControl2.Tag != null && (bool)_valControl2.Tag); + } + } + } + + /// + /// Changed control2 visibility + /// + /// + /// + private void valControl2_VisibleChanged(object? sender, EventArgs e) + { + if (_valControl2 != null) + { + label_and.Visible = _valControl2.Visible; + } + } + + /// + /// Changed a control Text + /// + /// + /// + private void valControl_TextChanged(object? sender, EventArgs e) + { + bool hasErrors = false; + switch (_filterType) + { + case FilterType.Integer: + long val; + hasErrors = !long.TryParse((sender as TextBox)!.Text, out val); + break; + + case FilterType.Float: + double val1; + hasErrors = !double.TryParse((sender as TextBox)!.Text, out val1); + break; + } + + (sender as Control)!.Tag = hasErrors || (sender as TextBox)!.Text.Length == 0; + + if (hasErrors && (sender as TextBox)!.Text.Length > 0) + { + ep.SetError((sender as Control)!, KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewInvalidValue)]); + } + else + { + ep.SetError((sender as Control)!, ""); + } + + if (_valControl1 != null && _valControl2 != null) + { + button_ok.Enabled = !(_valControl1.Visible && _valControl1.Tag != null && (bool)_valControl1.Tag) || + (_valControl2.Visible && _valControl2.Tag != null && (bool)_valControl2.Tag); + } + } + + /// + /// KeyDown on a control + /// + /// + /// + private void valControl_KeyDown(object? sender, KeyEventArgs e) + { + if (e.KeyData == Keys.Enter) + { + if (sender == _valControl1) + { + if (_valControl2 is { Visible: true }) + { + _valControl2.Focus(); + } + else + { + button_ok_Click(button_ok, EventArgs.Empty); + } + } + else + { + button_ok_Click(button_ok, EventArgs.Empty); + } + + e.SuppressKeyPress = false; + e.Handled = true; + } + } + + #endregion +} \ No newline at end of file diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.resx b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + \ No newline at end of file diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/AdvancedDataGridViewSearchToolBarSearchEventArgs.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/AdvancedDataGridViewSearchToolBarSearchEventArgs.cs new file mode 100644 index 0000000000..8fa85b60a7 --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/AdvancedDataGridViewSearchToolBarSearchEventArgs.cs @@ -0,0 +1,64 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +namespace Krypton.Utilities; + +public class AdvancedDataGridViewSearchToolBarSearchEventArgs : EventArgs +{ + /// Gets the value to search. + /// The value to search. + public string ValueToSearch { get; private set; } + + /// + /// Gets the column to search. + /// + /// + /// The column to search. + /// + public DataGridViewColumn? ColumnToSearch { get; private set; } + + /// + /// Gets a value indicating whether [case sensitive]. + /// + /// + /// true if [case sensitive]; otherwise, false. + /// + public bool CaseSensitive { get; private set; } + + /// + /// Gets a value indicating whether [whole word]. + /// + /// + /// true if [whole word]; otherwise, false. + /// + public bool WholeWord { get; private set; } + + /// + /// Gets a value indicating whether [from begin]. + /// + /// + /// true if [from begin]; otherwise, false. + /// + public bool FromBegin { get; private set; } + + /// Initializes a new instance of the class. + /// The value. + /// The column. + /// if set to true [case]. + /// if set to true [whole]. + /// if set to true [from begin]. + public AdvancedDataGridViewSearchToolBarSearchEventArgs(string value, DataGridViewColumn? column, bool @case, bool whole, bool fromBegin) + { + ValueToSearch = value; + ColumnToSearch = column; + CaseSensitive = @case; + WholeWord = whole; + FromBegin = fromBegin; + } +} \ No newline at end of file diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/ColumnHeaderCellEventArgs.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/ColumnHeaderCellEventArgs.cs new file mode 100644 index 0000000000..30014c4331 --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/ColumnHeaderCellEventArgs.cs @@ -0,0 +1,33 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +namespace Krypton.Utilities; + +internal class ColumnHeaderCellEventArgs : EventArgs +{ + public MenuStrip? FilterMenu { get; private set; } + + public DataGridViewColumn Column { get; private set; } + + #region Identity + + /// + /// Initializes a new instance of the class. + /// + /// The filter menu. + /// The column. + public ColumnHeaderCellEventArgs(MenuStrip? filterMenu, DataGridViewColumn column) + { + FilterMenu = filterMenu; + + Column = column; + } + + #endregion +} \ No newline at end of file diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/AdvancedDataGridViewSearchToolBarSearchEventHandler.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/AdvancedDataGridViewSearchToolBarSearchEventHandler.cs new file mode 100644 index 0000000000..7d137a386d --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/AdvancedDataGridViewSearchToolBarSearchEventHandler.cs @@ -0,0 +1,17 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +namespace Krypton.Utilities; + +/// +/// +/// +/// The sender. +/// The instance containing the event data. +public delegate void AdvancedDataGridViewSearchToolBarSearchEventHandler(object sender, AdvancedDataGridViewSearchToolBarSearchEventArgs e); diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/ColumnHeaderCellEventHandler.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/ColumnHeaderCellEventHandler.cs new file mode 100644 index 0000000000..1be3acd159 --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/ColumnHeaderCellEventHandler.cs @@ -0,0 +1,17 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +namespace Krypton.Utilities; + +/// +/// +/// +/// The sender. +/// The instance containing the event data. +internal delegate void ColumnHeaderCellEventHandler(object sender, ColumnHeaderCellEventArgs e); diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/Definitions.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/Definitions.cs new file mode 100644 index 0000000000..de058980b4 --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/Definitions.cs @@ -0,0 +1,283 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +namespace Krypton.Utilities; + +#region Enum FilterType + +/// +/// Specifies the category of filtering to apply for a column or value. +/// +public enum FilterType +{ + /// + /// The filter type is unknown or not specified. + /// + Unknown, + + /// + /// Filter applies to values. + /// + DateTime, + + /// + /// Filter applies to values. + /// + TimeSpan, + + /// + /// Filter applies to textual/string values. + /// + String, + + /// + /// Filter applies to floating point numeric values. + /// + Float, + + /// + /// Filter applies to integer numeric values. + /// + Integer +} + +#endregion + +#region Enum TranslationKey + +/// +/// Available translation keys for KryptonAdvancedDataGridView UI strings. +/// +public enum TranslationKey +{ + /// + /// Sort by date/time ascending. + /// + KryptonAdvancedDataGridViewSortDateTimeAscending, + + /// + /// Sort by date/time descending. + /// + KryptonAdvancedDataGridViewSortDateTimeDescending, + + /// + /// Sort boolean values with false then true. + /// + KryptonAdvancedDataGridViewSortBoolAscending, + + /// + /// Sort boolean values with true then false. + /// + KryptonAdvancedDataGridViewSortBoolDescending, + + /// + /// Sort numeric values ascending. + /// + KryptonAdvancedDataGridViewSortNumAscending, + + /// + /// Sort numeric values descending. + /// + KryptonAdvancedDataGridViewSortNumDescending, + + /// + /// Sort text values ascending (A-Z). + /// + KryptonAdvancedDataGridViewSortTextAscending, + + /// + /// Sort text values descending (Z-A). + /// + KryptonAdvancedDataGridViewSortTextDescending, + + /// + /// Add a custom filter. + /// + KryptonAdvancedDataGridViewAddCustomFilter, + + /// + /// Label for a custom filter. + /// + KryptonAdvancedDataGridViewCustomFilter, + + /// + /// Clear the active filter. + /// + KryptonAdvancedDataGridViewClearFilter, + + /// + /// Clear the active sort. + /// + KryptonAdvancedDataGridViewClearSort, + + /// + /// Text for the filter button. + /// + KryptonAdvancedDataGridViewButtonFilter, + + /// + /// Text for the undo filter button. + /// + KryptonAdvancedDataGridViewButtonUndoFilter, + + /// + /// Select all nodes in checklist filter. + /// + KryptonAdvancedDataGridViewNodeSelectAll, + + /// + /// Select empty/null nodes in checklist filter. + /// + KryptonAdvancedDataGridViewNodeSelectEmpty, + + /// + /// Select nodes with true values in checklist filter. + /// + KryptonAdvancedDataGridViewNodeSelectTrue, + + /// + /// Select nodes with false values in checklist filter. + /// + KryptonAdvancedDataGridViewNodeSelectFalse, + + /// + /// Disable checklist filter. + /// + KryptonAdvancedDataGridViewFilterChecklistDisable, + + /// + /// Equality operator label. + /// + KryptonAdvancedDataGridViewEquals, + + /// + /// Inequality operator label. + /// + KryptonAdvancedDataGridViewDoesNotEqual, + + /// + /// Earlier than operator label. + /// + KryptonAdvancedDataGridViewEarlierThan, + + /// + /// Earlier than or equal to operator label. + /// + KryptonAdvancedDataGridViewEarlierThanOrEqualTo, + + /// + /// Later than operator label. + /// + KryptonAdvancedDataGridViewLaterThan, + + /// + /// Later than or equal to operator label. + /// + KryptonAdvancedDataGridViewLaterThanOrEqualTo, + + /// + /// Between operator label. + /// + KryptonAdvancedDataGridViewBetween, + + /// + /// Greater than operator label. + /// + KryptonAdvancedDataGridViewGreaterThan, + + /// + /// Greater than or equal to operator label. + /// + KryptonAdvancedDataGridViewGreaterThanOrEqualTo, + + /// + /// Less than operator label. + /// + KryptonAdvancedDataGridViewLessThan, + + /// + /// Less than or equal to operator label. + /// + KryptonAdvancedDataGridViewLessThanOrEqualTo, + + /// + /// Begins with operator label. + /// + KryptonAdvancedDataGridViewBeginsWith, + + /// + /// Does not begin with operator label. + /// + KryptonAdvancedDataGridViewDoesNotBeginWith, + + /// + /// Ends with operator label. + /// + KryptonAdvancedDataGridViewEndsWith, + + /// + /// Does not end with operator label. + /// + KryptonAdvancedDataGridViewDoesNotEndWith, + + /// + /// Contains operator label. + /// + KryptonAdvancedDataGridViewContains, + + /// + /// Does not contain operator label. + /// + KryptonAdvancedDataGridViewDoesNotContain, + + /// + /// Invalid value message. + /// + KryptonAdvancedDataGridViewInvalidValue, + + /// + /// Description for string filter UI. + /// + KryptonAdvancedDataGridViewFilterStringDescription, + + /// + /// Title for the filter form. + /// + KryptonAdvancedDataGridViewFormTitle, + + /// + /// Label for column name text. + /// + KryptonAdvancedDataGridViewLabelColumnNameText, + + /// + /// Label for logical AND between conditions. + /// + KryptonAdvancedDataGridViewLabelAnd, + + /// + /// Text for the "OK" button in the advanced data grid view filter form. + /// + KryptonAdvancedDataGridViewButtonOk, + + /// + /// Text for the "Cancel" button in the advanced data grid view filter form. + /// + KryptonAdvancedDataGridViewButtonCancel, + ADGVSTBLabelSearch, + ADGVSTBButtonFromBegin, + ADGVSTBButtonCaseSensitiveToolTip, + ADGVSTBButtonSearchToolTip, + ADGVSTBButtonCloseToolTip, + ADGVSTBButtonWholeWordToolTip, + ADGVSTBComboBoxColumnsAll, + ADGVSTBTextBoxSearchToolTip +} + +#endregion \ No newline at end of file diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/KryptonColumnHeaderCell.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/KryptonColumnHeaderCell.cs new file mode 100644 index 0000000000..8183a61ccc --- /dev/null +++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/KryptonColumnHeaderCell.cs @@ -0,0 +1,715 @@ +#region BSD License +/* + * + * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE) + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved. + * + */ +#endregion + +namespace Krypton.Utilities; + +internal class KryptonColumnHeaderCell : DataGridViewColumnHeaderCell +{ + #region Instance Fields + + private Image _filterImage = Properties.Resources.ColumnHeader_UnFiltered; + private Size _filterButtonImageSize = new Size(16, 16); + private bool _filterButtonPressed = false; + private bool _filterButtonOver = false; + private Rectangle _filterButtonOffsetBounds = Rectangle.Empty; + private Rectangle _filterButtonImageBounds = Rectangle.Empty; + private Padding _filterButtonMargin = new Padding(3, 4, 3, 4); + private bool _filterEnabled = false; + + /// + /// Get the MenuStrip for this ColumnHeaderCell + /// + public MenuStrip? MenuStrip { get; private set; } + + + #endregion + + #region Constants + + /// + /// Default behaviour for Date and Time filter + /// + private const bool FILTER_DATE_AND_TIME_DEFAULT_ENABLED = false; + + #endregion + + #region Events + + public event ColumnHeaderCellEventHandler? FilterPopup; + public event ColumnHeaderCellEventHandler? SortChanged; + public event ColumnHeaderCellEventHandler? FilterChanged; + + #endregion + + #region Identity + + /// + /// Initializes a new instance of the class. + /// + /// The old cell. + /// if set to true [filter enabled]. + public KryptonColumnHeaderCell(DataGridViewColumnHeaderCell oldCell, bool filterEnabled) : base() + { + Tag = oldCell.Tag; + + ErrorText = oldCell.ErrorText; + + ToolTipText = oldCell.ToolTipText; + + Value = oldCell.Value; + + ValueType = oldCell.ValueType; + + ContextMenuStrip = oldCell.ContextMenuStrip; + + Style = oldCell.Style; + + _filterEnabled = filterEnabled; + + if (oldCell is KryptonColumnHeaderCell { MenuStrip: not null } oldCellt) + { + MenuStrip = oldCellt.MenuStrip; + _filterImage = oldCellt._filterImage; + _filterButtonPressed = oldCellt._filterButtonPressed; + _filterButtonOver = oldCellt._filterButtonOver; + _filterButtonOffsetBounds = oldCellt._filterButtonOffsetBounds; + _filterButtonImageBounds = oldCellt._filterButtonImageBounds; + MenuStrip.FilterChanged += new EventHandler(MenuStrip_FilterChanged); + MenuStrip.SortChanged += new EventHandler(MenuStrip_SortChanged); + } + else + { + Type dataType = oldCell.OwningColumn?.ValueType ?? typeof(object); + MenuStrip = new MenuStrip(dataType); + MenuStrip.FilterChanged += new EventHandler(MenuStrip_FilterChanged); + MenuStrip.SortChanged += new EventHandler(MenuStrip_SortChanged); + } + + IsFilterDateAndTimeEnabled = FILTER_DATE_AND_TIME_DEFAULT_ENABLED; + IsSortEnabled = true; + IsFilterEnabled = true; + IsFilterChecklistEnabled = true; + } + + ~KryptonColumnHeaderCell() + { + if (MenuStrip != null) + { + MenuStrip.FilterChanged -= MenuStrip_FilterChanged; + MenuStrip.SortChanged -= MenuStrip_SortChanged; + } + } + + #endregion + + #region Implementation + + /// + /// Get or Set the Filter and Sort enabled status + /// + public bool FilterAndSortEnabled + { + get => _filterEnabled; + set + { + if (!value) + { + _filterButtonPressed = false; + _filterButtonOver = false; + } + + if (value != _filterEnabled) + { + _filterEnabled = value; + bool refreshed = false; + if (MenuStrip?.FilterString!.Length > 0) + { + MenuStrip_FilterChanged(this, EventArgs.Empty); + refreshed = true; + } + if (MenuStrip?.SortString!.Length > 0) + { + MenuStrip_SortChanged(this, EventArgs.Empty); + refreshed = true; + } + if (!refreshed) + { + RepaintCell(); + } + } + } + } + + /// + /// Set or Unset the Filter and Sort to Loaded mode + /// + /// + public void SetLoadedMode(bool enabled) + { + MenuStrip?.SetLoadedMode(enabled); + RefreshImage(); + RepaintCell(); + } + + /// + /// Clean Sort + /// + public void CleanSort() + { + if (MenuStrip != null && FilterAndSortEnabled) + { + MenuStrip.CleanSort(); + RefreshImage(); + RepaintCell(); + } + } + + /// + /// Clean Filter + /// + public void CleanFilter() + { + if (MenuStrip != null && FilterAndSortEnabled) + { + MenuStrip.CleanFilter(); + RefreshImage(); + RepaintCell(); + } + } + + /// + /// Sort ASC + /// + public void SortASC() + { + if (MenuStrip != null && FilterAndSortEnabled) + { + MenuStrip.SortAsc(); + } + } + + /// + /// Sort DESC + /// + public void SortDESC() + { + if (MenuStrip != null && FilterAndSortEnabled) + { + MenuStrip.SortDesc(); + } + } + + /// + /// Clone the ColumnHeaderCell + /// + /// + public override object Clone() + { + return new KryptonColumnHeaderCell(this, FilterAndSortEnabled); + } + + /// + /// Get the MenuStrip SortType + /// + public MenuStrip.SortType ActiveSortType + { + get + { + if (MenuStrip != null && FilterAndSortEnabled) + { + return MenuStrip.ActiveSortType; + } + else + { + return MenuStrip.SortType.None; + } + } + } + + /// + /// Get the MenuStrip FilterType + /// + public MenuStrip.FilterType ActiveFilterType + { + get + { + if (MenuStrip != null && FilterAndSortEnabled) + { + return MenuStrip.ActiveFilterType; + } + else + { + return MenuStrip.FilterType.None; + } + } + } + + /// + /// Get the Sort string + /// + public string? SortString + { + get + { + if (MenuStrip != null && FilterAndSortEnabled) + { + return MenuStrip.SortString; + } + else + { + return ""; + } + } + } + + /// + /// Get the Filter string + /// + public string? FilterString + { + get + { + if (MenuStrip != null && FilterAndSortEnabled) + { + return MenuStrip.FilterString; + } + else + { + return ""; + } + } + } + + /// + /// Get the Minimum size + /// + public Size MinimumSize => + new(_filterButtonImageSize.Width + _filterButtonMargin.Left + _filterButtonMargin.Right, + _filterButtonImageSize.Height + _filterButtonMargin.Bottom + _filterButtonMargin.Top); + + /// + /// Get or Set the Sort enabled status + /// + public bool IsSortEnabled + { + get => MenuStrip is { IsSortEnabled: true }; + set => MenuStrip?.IsSortEnabled = value; + } + + /// + /// Get or Set the Filter enabled status + /// + public bool IsFilterEnabled + { + get => MenuStrip is { IsFilterEnabled: true }; + set => MenuStrip?.IsFilterEnabled = value; + } + + /// + /// Get or Set the Filter enabled status + /// + public bool IsFilterChecklistEnabled + { + get => MenuStrip is { IsFilterChecklistEnabled: true }; + set => MenuStrip?.IsFilterChecklistEnabled = value; + } + + /// + /// Get or Set the FilterDateAndTime enabled status + /// + public bool IsFilterDateAndTimeEnabled + { + get => MenuStrip is { IsFilterDateAndTimeEnabled: true }; + set => MenuStrip?.IsFilterDateAndTimeEnabled = value; + } + + /// + /// Get or Set the NOT IN logic for Filter + /// + public bool IsMenuStripFilterNOTINLogicEnabled + { + get => MenuStrip is { IsFilterNotinLogicEnabled: true }; + set => MenuStrip?.IsFilterNotinLogicEnabled = value; + } + + /// + /// Set the text filter search nodes behaviour + /// + public bool DoesTextFilterRemoveNodesOnSearch + { + get => MenuStrip is { DoesTextFilterRemoveNodesOnSearch: true }; + set => MenuStrip?.DoesTextFilterRemoveNodesOnSearch = value; + } + + /// + /// Number of nodes to enable the TextChanged delay on text filter + /// + public int TextFilterTextChangedDelayNodes + { + get => MenuStrip!.TextFilterTextChangedDelayNodes; + set => MenuStrip?.TextFilterTextChangedDelayNodes = value; + } + + /// + /// Enabled or disable Sort capabilities + /// + /// + public void SetSortEnabled(bool enabled) + { + if (MenuStrip != null) + { + MenuStrip.IsSortEnabled = enabled; + MenuStrip.SetSortEnabled(enabled); + } + } + + /// + /// Enable or disable Filter capabilities + /// + /// + public void SetFilterEnabled(bool enabled) + { + if (MenuStrip != null) + { + MenuStrip.IsFilterEnabled = enabled; + MenuStrip.SetFilterEnabled(enabled); + } + } + + /// + /// Enable or disable Filter checklist capabilities + /// + /// + public void SetFilterChecklistEnabled(bool enabled) + { + if (MenuStrip != null) + { + MenuStrip.IsFilterChecklistEnabled = enabled; + MenuStrip.SetFilterChecklistEnabled(enabled); + } + } + + /// + /// Set Filter checklist nodes max + /// + /// + public void SetFilterChecklistNodesMax(int maxNodes) + { + if (maxNodes >= 0) + { + MenuStrip?.MaxChecklistNodes = maxNodes; + } + } + + /// + /// Enable or disable Filter checklist nodes max + /// + /// + public void EnabledFilterChecklistNodesMax(bool enabled) + { + if (MenuStrip is { MaxChecklistNodes: 0 } && enabled) + { + MenuStrip.MaxChecklistNodes = MenuStrip.DefaultMaxChecklistNodes; + } + else if (MenuStrip is not { MaxChecklistNodes: 0 } && !enabled) + { + MenuStrip?.MaxChecklistNodes = 0; + } + } + + /// + /// Enable or disable Filter custom capabilities + /// + /// + public void SetFilterCustomEnabled(bool enabled) + { + if (MenuStrip != null) + { + MenuStrip.IsFilterCustomEnabled = enabled; + MenuStrip.SetFilterCustomEnabled(enabled); + } + } + + /// + /// Enable or disable Text filter on checklist remove node mode + /// + /// + public void SetChecklistTextFilterRemoveNodesOnSearchMode(bool enabled) => MenuStrip?.SetChecklistTextFilterRemoveNodesOnSearchMode(enabled); + + /// + /// Disable text filter TextChanged delay + /// + public void SetTextFilterTextChangedDelayNodesDisabled() => MenuStrip?.SetTextFilterTextChangedDelayNodesDisabled(); + + /// + /// Set text filter TextChanged delay milliseconds + /// + public void SetTextFilterTextChangedDelayMs(int milliseconds) => MenuStrip?.TextFilterTextChangedDelayMs = milliseconds; + + #endregion + + #region MenuStrip Events + + /// + /// OnFilterChanged event + /// + /// + /// + private void MenuStrip_FilterChanged(object? sender, EventArgs e) + { + RefreshImage(); + RepaintCell(); + if (FilterAndSortEnabled && FilterChanged != null && OwningColumn != null) + { + FilterChanged(this, new ColumnHeaderCellEventArgs(MenuStrip, OwningColumn)); + } + } + + /// + /// OnSortChanged event + /// + /// + /// + private void MenuStrip_SortChanged(object? sender, EventArgs e) + { + RefreshImage(); + RepaintCell(); + if (FilterAndSortEnabled && SortChanged != null && OwningColumn != null) + { + SortChanged(this, new ColumnHeaderCellEventArgs(MenuStrip, OwningColumn)); + } + } + + /// + /// Clean attached events + /// + public void CleanEvents() + { + MenuStrip?.FilterChanged -= MenuStrip_FilterChanged; + MenuStrip?.SortChanged -= MenuStrip_SortChanged; + } + + + #endregion + + #region Paint Methods + + /// + /// Repaint the Cell + /// + private void RepaintCell() + { + if (Displayed && DataGridView != null) + { + DataGridView.InvalidateCell(this); + } + } + + /// + /// Refresh the Cell image + /// + private void RefreshImage() + { + if (ActiveFilterType == MenuStrip.FilterType.Loaded) + { + _filterImage = Properties.Resources.ColumnHeader_SavedFilters; + } + else + { + if (ActiveFilterType == MenuStrip.FilterType.None) + { + if (ActiveSortType == MenuStrip.SortType.None) + { + _filterImage = Properties.Resources.ColumnHeader_UnFiltered; + } + else if (ActiveSortType == MenuStrip.SortType.Asc) + { + _filterImage = Properties.Resources.ColumnHeader_OrderedASC; + } + else + { + _filterImage = Properties.Resources.ColumnHeader_OrderedDESC; + } + } + else + { + if (ActiveSortType == MenuStrip.SortType.None) + { + _filterImage = Properties.Resources.ColumnHeader_Filtered; + } + else if (ActiveSortType == MenuStrip.SortType.Asc) + { + _filterImage = Properties.Resources.ColumnHeader_FilteredAndOrderedASC; + } + else + { + _filterImage = Properties.Resources.ColumnHeader_FilteredAndOrderedDESC; + } + } + } + } + + /// + /// Pain method + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + protected override void Paint( + Graphics graphics, + Rectangle clipBounds, + Rectangle cellBounds, + int rowIndex, + DataGridViewElementStates cellState, + object? value, + object? formattedValue, + string? errorText, + DataGridViewCellStyle cellStyle, + DataGridViewAdvancedBorderStyle advancedBorderStyle, + DataGridViewPaintParts paintParts) + { + if (SortGlyphDirection != SortOrder.None) + { + SortGlyphDirection = SortOrder.None; + } + + base.Paint(graphics, clipBounds, cellBounds, rowIndex, + cellState, value, formattedValue, + errorText, cellStyle, advancedBorderStyle, paintParts); + + // By default, skip Bitmap columns unless KryptonAdvancedDataGridView.FilterAndSortOnBitmapColumns is true + if (OwningColumn?.ValueType == typeof(Bitmap) && + (DataGridView is not KryptonAdvancedDataGridView advancedGrid || !advancedGrid.FilterAndSortOnBitmapColumns)) + { + return; + } + + if (FilterAndSortEnabled && paintParts.HasFlag(DataGridViewPaintParts.ContentBackground)) + { + _filterButtonOffsetBounds = GetFilterBounds(true); + _filterButtonImageBounds = GetFilterBounds(false); + Rectangle buttonBounds = _filterButtonOffsetBounds; + if (clipBounds.IntersectsWith(buttonBounds)) + { + ControlPaint.DrawBorder(graphics, buttonBounds, Color.Gray, ButtonBorderStyle.Solid); + buttonBounds.Inflate(-1, -1); + using (Brush b = new SolidBrush(_filterButtonOver ? Color.WhiteSmoke : Color.White)) + graphics.FillRectangle(b, buttonBounds); + graphics.DrawImage(_filterImage, buttonBounds); + } + } + } + + /// + /// Get the ColumnHeaderCell Bounds + /// + /// + /// + private Rectangle GetFilterBounds(bool withOffset = true) + { + Rectangle cell = DataGridView!.GetCellDisplayRectangle(ColumnIndex, -1, false); + + Point p = new Point( + (withOffset ? cell.Right : cell.Width) - _filterButtonImageSize.Width - _filterButtonMargin.Right, + (withOffset ? cell.Bottom : cell.Height) - _filterButtonImageSize.Height - _filterButtonMargin.Bottom); + + return new Rectangle(p, _filterButtonImageSize); + } + + #endregion + + #region Mouse Events + + /// + /// OnMouseMove event + /// + /// + protected override void OnMouseMove(DataGridViewCellMouseEventArgs e) + { + if (FilterAndSortEnabled) + { + if (_filterButtonImageBounds.Contains(e.X, e.Y) && !_filterButtonOver) + { + _filterButtonOver = true; + RepaintCell(); + } + else if (!_filterButtonImageBounds.Contains(e.X, e.Y) && _filterButtonOver) + { + _filterButtonOver = false; + RepaintCell(); + } + } + base.OnMouseMove(e); + } + + /// + /// OnMouseDown event + /// + /// + protected override void OnMouseDown(DataGridViewCellMouseEventArgs e) + { + if (FilterAndSortEnabled && _filterButtonImageBounds.Contains(e.X, e.Y)) + { + if (e.Button == MouseButtons.Left && !_filterButtonPressed) + { + _filterButtonPressed = true; + _filterButtonOver = true; + RepaintCell(); + } + } + else + { + base.OnMouseDown(e); + } + } + + /// + /// OnMouseUp event + /// + /// + protected override void OnMouseUp(DataGridViewCellMouseEventArgs e) + { + if (FilterAndSortEnabled && e.Button == MouseButtons.Left && _filterButtonPressed) + { + _filterButtonPressed = false; + _filterButtonOver = false; + RepaintCell(); + if (_filterButtonImageBounds.Contains(e.X, e.Y) && FilterPopup != null && OwningColumn != null) + { + FilterPopup(this, new ColumnHeaderCellEventArgs(MenuStrip, OwningColumn)); + } + } + base.OnMouseUp(e); + } + + /// + /// OnMouseLeave event + /// + /// + protected override void OnMouseLeave(int rowIndex) + { + if (FilterAndSortEnabled && _filterButtonOver) + { + _filterButtonOver = false; + RepaintCell(); + } + + base.OnMouseLeave(rowIndex); + } + + #endregion +} diff --git a/Source/Krypton Components/Krypton.Utilities/Global/Globals.cs b/Source/Krypton Components/Krypton.Utilities/Global/Globals.cs index 547799c493..18bab5378f 100644 --- a/Source/Krypton Components/Krypton.Utilities/Global/Globals.cs +++ b/Source/Krypton Components/Krypton.Utilities/Global/Globals.cs @@ -10,12 +10,17 @@ global using System; global using System.Collections.Concurrent; global using System.ComponentModel; +global using System.Data; global using System.Diagnostics; global using System.Diagnostics.CodeAnalysis; global using System.Drawing; +global using System.Net; +global using System.Net.Http; global using System.Security.Cryptography; +global using System.Text; global using System.Windows.Forms; global using System.Windows.Forms.Design; +global using System.Xml.Serialization; global using Krypton.Navigator; global using Krypton.Ribbon; diff --git a/Source/Krypton Components/Krypton.Utilities/GlobalUsings.cs b/Source/Krypton Components/Krypton.Utilities/GlobalUsings.cs deleted file mode 100644 index fcb44bd76b..0000000000 --- a/Source/Krypton Components/Krypton.Utilities/GlobalUsings.cs +++ /dev/null @@ -1,7 +0,0 @@ -// Global using directives - -global using System; -global using System.Net.Http; -global using System.Net; -global using System.Text; -global using System.Xml.Serialization; \ No newline at end of file diff --git a/Source/Krypton Components/Krypton.Utilities/Properties/Resources.Designer.cs b/Source/Krypton Components/Krypton.Utilities/Properties/Resources.Designer.cs index d5e41d1dba..9951530dd5 100644 --- a/Source/Krypton Components/Krypton.Utilities/Properties/Resources.Designer.cs +++ b/Source/Krypton Components/Krypton.Utilities/Properties/Resources.Designer.cs @@ -90,6 +90,76 @@ internal static System.Drawing.Bitmap Cancel_Windows_11 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ColumnHeader_Filtered { + get { + object obj = ResourceManager.GetObject("ColumnHeader_Filtered", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ColumnHeader_FilteredAndOrderedASC { + get { + object obj = ResourceManager.GetObject("ColumnHeader_FilteredAndOrderedASC", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ColumnHeader_FilteredAndOrderedDESC { + get { + object obj = ResourceManager.GetObject("ColumnHeader_FilteredAndOrderedDESC", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ColumnHeader_OrderedASC { + get { + object obj = ResourceManager.GetObject("ColumnHeader_OrderedASC", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ColumnHeader_OrderedDESC { + get { + object obj = ResourceManager.GetObject("ColumnHeader_OrderedDESC", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ColumnHeader_SavedFilters { + get { + object obj = ResourceManager.GetObject("ColumnHeader_SavedFilters", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ColumnHeader_UnFiltered { + get { + object obj = ResourceManager.GetObject("ColumnHeader_UnFiltered", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -220,6 +290,76 @@ internal static System.Drawing.Bitmap Krypton_Stable { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap MenuStrip_OrderASCbool { + get { + object obj = ResourceManager.GetObject("MenuStrip_OrderASCbool", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap MenuStrip_OrderASCnum { + get { + object obj = ResourceManager.GetObject("MenuStrip_OrderASCnum", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap MenuStrip_OrderASCtxt { + get { + object obj = ResourceManager.GetObject("MenuStrip_OrderASCtxt", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap MenuStrip_OrderDESCbool { + get { + object obj = ResourceManager.GetObject("MenuStrip_OrderDESCbool", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap MenuStrip_OrderDESCnum { + get { + object obj = ResourceManager.GetObject("MenuStrip_OrderDESCnum", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap MenuStrip_OrderDESCtxt { + get { + object obj = ResourceManager.GetObject("MenuStrip_OrderDESCtxt", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap MenuStrip_ResizeGrip { + get { + object obj = ResourceManager.GetObject("MenuStrip_ResizeGrip", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -280,6 +420,56 @@ internal static System.Drawing.Bitmap Restart_Dark { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SearchToolBar_ButtonCaseSensitive { + get { + object obj = ResourceManager.GetObject("SearchToolBar_ButtonCaseSensitive", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SearchToolBar_ButtonClose { + get { + object obj = ResourceManager.GetObject("SearchToolBar_ButtonClose", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SearchToolBar_ButtonFromBegin { + get { + object obj = ResourceManager.GetObject("SearchToolBar_ButtonFromBegin", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SearchToolBar_ButtonSearch { + get { + object obj = ResourceManager.GetObject("SearchToolBar_ButtonSearch", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SearchToolBar_ButtonWholeWord { + get { + object obj = ResourceManager.GetObject("SearchToolBar_ButtonWholeWord", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/Source/Krypton Components/Krypton.Utilities/Properties/Resources.resx b/Source/Krypton Components/Krypton.Utilities/Properties/Resources.resx index e83225b85c..ba60dd6208 100644 --- a/Source/Krypton Components/Krypton.Utilities/Properties/Resources.resx +++ b/Source/Krypton Components/Krypton.Utilities/Properties/Resources.resx @@ -127,6 +127,27 @@ ..\Resources\Cancel_Windows_11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\ColumnHeader_Filtered.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ColumnHeader_FilteredAndOrderedASC.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ColumnHeader_FilteredAndOrderedDESC.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ColumnHeader_OrderedASC.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ColumnHeader_OrderedDESC.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ColumnHeader_SavedFilters.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ColumnHeader_UnFiltered.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\Copy.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -166,6 +187,27 @@ ..\Resources\Krypton Stable.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\MenuStrip_OrderASCbool.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\MenuStrip_OrderASCnum.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\MenuStrip_OrderASCtxt.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\MenuStrip_OrderDESCbool.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\MenuStrip_OrderDESCnum.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\MenuStrip_OrderDESCtxt.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\MenuStrip_ResizeGrip.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\Ok.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -184,6 +226,21 @@ ..\Resources\Restart_Dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\SearchToolBar_ButtonCaseSensitive.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\SearchToolBar_ButtonClose.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\SearchToolBar_ButtonFromBegin.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\SearchToolBar_ButtonSearch.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\SearchToolBar_ButtonWholeWord.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\Stop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_Filtered.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_Filtered.png new file mode 100644 index 0000000000000000000000000000000000000000..30031fce7aa7af073b911025708916e9afde381a GIT binary patch literal 351 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3oVGw3ym^DWND5#L^ z5#-Cj&@Rou(EXo*k;hqs_qZQiXxR2~VQpH{cC9m6$UZ#5O3|UgJIPyKu<$h6y+j|pt z-ZPHRdtvLJVSnfE#8>87qGI!-`3jrL{H14D96ZALup&?KzYGt<{3dYHk})z4*}Q$iB}h~A2T literal 0 HcmV?d00001 diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_FilteredAndOrderedASC.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_FilteredAndOrderedASC.png new file mode 100644 index 0000000000000000000000000000000000000000..9b89940fcb5376dba96de421fce4c2ccdde51cbb GIT binary patch literal 352 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3oArNM~bhqvgP*5S+ zBgmJ5p~~nPlsC z*g>FmKj#z?lM`jGo)ho1miZs_E#mciU{}g@>Vq;DN2bBdj6dGakoN6;i^@$ojso-Z7M6C8cI#B0 znzm=1*&fmNKIz5B#Gi-u+r5dDojcd<$!g!ww+RlBU9a1p>zXieRAxlnXmfV>&b@y2 zai7PhI~o2yo9H6qIw{0(Evp36u3fPv3-%xQ7Lv{&KR>?L+F{ZWt!u1>LaTGP>g_Ae uvV6{R!cyHcVtTBpv8T}j=^d-*GcuS>Y2*5>^#v% zi58kd4N+o5ys?NE?=D7?3@p0?Gs`glZzQn@8uN&aF`C<$B#Fv5l4d$S^lGj)6^34t zW;aU0`;kc!K|T94NHS#}6p!mp7q`B~SDtg%?eW|n@bdc3S=QmSeFQ)hMH8*YyIY>8 z{$TXmQiD7fm$#3FDF(1DJ7LU#cxThmdmFN{9B^^-z{&ApVafokvz6@S=zD<9ukHot zhmUn>nvTn<&oKiSetcGV0q5NRn{%+g{b#ezZB$#W#WmALVr}bJwCIw54*>8NpD?5a R8;Jk_002ovPDHLkV1j_qm+Alj literal 0 HcmV?d00001 diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedASC.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedASC.png new file mode 100644 index 0000000000000000000000000000000000000000..d6625f04b32477dadf73a9bc7fab6be6bc513078 GIT binary patch literal 268 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1G>pWc?Ln>}1{rUgjp4qaYQ{-s$ww#~-(~gF`1SSm zC$9dORn)6aXLP?3~O^E>SBjZVv!WtPlE*;@0wvOzSQ8>V`Y(Y+2(wf&M QK$kOky85}Sb4q9e0DJsv*#H0l literal 0 HcmV?d00001 diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedDESC.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedDESC.png new file mode 100644 index 0000000000000000000000000000000000000000..c4b15dc7484dfbf7ef1cc5916d004b836436ecfb GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GJ3U<-Ln>}1{rUgjp4qaYQ{-q*PtSkPYZ8)@KjmkpF<4HO z&{0(UH@|!K>-`oJ*sA*@dKGl^_%5;>^5IEg5=-fuK3)9A*98R*!Qbm|Z_DlJ>gt-Y zkc-FAc7+<7iqttasbBFf5iG%r8ygQUeS3R*_JYg?X@)761qDS9%Jt8iH_yD0D`bPK zqJhIYpw35r3=U_@8)u15Fg+-7Lh4~-@xMQnDS!DlvIqn$mZ}1{rUgjp4loPCFO{S3$xD-m3cOmO-_rujSVMo za%4@JIPsv?xh8+%UB-qcN!&aovoG*A-mduk(3>rgQLb(O|9^%yRX-aa-d�^WMHb z-JI6gss)OrVe@g`o$kMGP+I3OIWdJhg_uGS?d*2 hnUjhN7#kRv849N69?#hzZ42}YgQu&X%Q~loCICV|av=Z! literal 0 HcmV?d00001 diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_UnFiltered.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_UnFiltered.png new file mode 100644 index 0000000000000000000000000000000000000000..16b306fb3c11d93a8891b34391b75c153cc60f8a GIT binary patch literal 242 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3oVGw3ym^DWND5#L^ z5#-Cj&@Rou(EXo*k;hqs_qZQiXxR0Rve{|TPBpqO7cJ*e-=i3z$c-MJHTRL-0^B6z1jAY9gTe~DWM4fbH7m@ literal 0 HcmV?d00001 diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCbool.png b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCbool.png new file mode 100644 index 0000000000000000000000000000000000000000..75c518b58940349e53557bb1f9acb30985d4922f GIT binary patch literal 364 zcmV-y0h9iTP)f?)x3?tsRa zXuI7Vx~_}dnee)DpT!3fV^viI;txP4!IQ?Oz|-VhJiB~vQp(AlfPG+t)XABcn`sUx zEBPq(elfn`CIj-bI*&P;;nd|BTido@o6TBj{U2c-3L!3G6khf}`&HmS$LQXsvn&Ut zRM<2Pr@LbNFFb0R{k*bI=>F(zloZ0000< KMNUMnLSTZrg_+#| literal 0 HcmV?d00001 diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCnum.png b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCnum.png new file mode 100644 index 0000000000000000000000000000000000000000..ebc3a3ec8121db7975bc115f349b34eb6e2e2689 GIT binary patch literal 390 zcmV;10eSw3P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0UJp~K~y+Tl~P-7 zgD?=Z4dNlCRX;dGa|XBt95=a1^INGOg&_Dy-N?q7^#cffsUwZNyX@@P*xVSy{(|oj z;KVtn*d{Yj`*zASP3hrqeAQZ~zO)E`5)sI;ZCesKJ75;#+g#kj3E#t(E$+7Z8@jIh zztC^hXAV|K=L=_C#{nel+N~oJqjZD?SL2D?)~~3G(D? zHW1h>*srm_G5*QIKPy)>UM?u-Uy|q)#A!HvP2Y4*)rX#?b&ikTYk#&8PyfqbIOW_= z*OR;QOqCf0COHTRN%t7mWj&CcZg@=W@xt!N__;SkZz%6R?RJ;>TyjkI0+y~{ErR_8pYUz@$Dd%?2 uQPecs!|1@VP$Iwb%bKFv)~5h z5^xJRZhMnt+z;D5yH32EKwB_o~nx=UL zE|OP3uGGbudOpjQ$V%nFrd}$lm&W`t>@51Vz4|?vk;o!fRERLk_MO&0(J&05QtA;# z;p2Qde{OgZcRJ7W!nSQ2_I)pLE%IU>0#~#C|WlxfSd)CgWEav)bkc2M1>X?g**Eyhz{{%a2Y93le1+)X!zzXA*Z7+u~LsD|61 P00000NkvXXu0mjfW5AZs literal 0 HcmV?d00001 diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCnum.png b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCnum.png new file mode 100644 index 0000000000000000000000000000000000000000..cd03b10615311c0716f4dea795c343e013c122be GIT binary patch literal 374 zcmV-+0g3*JP)tX_y5J0* zGr%q2xYL_-ww1alOazNI9g(r zBuQ>*mfkL}mnXRfGAIPJOP+XD)u@z8$8iL!lvI6;>1s;*b3=G^tAk28_ZrvZC;5tti#}Etuxsx1)4l8iDZe5;{H~G$?=Bnjs zU6D6!Sp|hXZn@s$VNBUqFCi>wc<158eTI)TWh~Q+)tru4I90oAMz3cP)Ou5*n8a{z zuTa@Tc|m4|y+Yq)O|vc5weGraD8uTto@H~gil@H+l(SrCtv5}GdTi$F|NDwbY<#v% zpVp^!pZByxWv`IuI>r66S3j3^P6UCs86! ze>%5ElfsIfUuV|bUoTLh_~=`8<-GLy=hGEpuJ5(IYT3W%`p1er^Ze8k79D;VQ26&I zf9TXQ@#9W2M5jo%6{gPrxaP-;dj%Fg zrLpX8ceGsFZNEl6*yk2wCc(qSGDH5Jw#&RC-^)^W0=!QAH@!b`)vE1v`}uctJ@-zW sR(!9j(7kIBL*vp~f4Q!AwybrGy2YK>>^HvK2n=}!Pgg&ebxsLQ068SU*#H0l literal 0 HcmV?d00001 diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonClose.png b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonClose.png new file mode 100644 index 0000000000000000000000000000000000000000..17c03870f915a65fa11b140da3a91d27cb6f196e GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4F%}28J29*~C-V}>VM%xNb!1@J z*w6hZkrl}2EbxddW?B`cTA*N=r;B5VMsR7LBUgg~56fpx#}EJQH7Y*6 z@)Tfk{9w2%SgKP{eA=?v3u7m{RZgPx#1ZP1_K>z@;j|==^1poj532;bRa{vGiy#N3Xy#Yu2kgWg!0cuG^K~y+TV;E+j zck|!>Fx-mCv5v!DMjnEv>G>8!{9p~^8q*M?vJH=X?Uf90Vs z{}=4}^#AgMpZ|N;zWd+2^bOdMyy-9g>xQnvZ2-vD6$iikpSSDN|65Of{Re@DC2#(h z&VBhmXX^9+NxjehtNJa%Z2-v0b9Q|C|M2Axux1b_nf>yA)|BV}6MCQi4{Lq=U(Rh7 zZUaF6z4_=fR4XbtcKOYJuiA(I#q1{GHUQ+$=4EgGpStoAs_p;(=*}nq1DhU!*$$=m z|MQ!5<2C>k(&a!ya;821zw^jlu%>{9NB`Zb9)Q_qd3XPF8nogz02EExK>sEJ{Ttr) z`2U=B7yi3e-2ZP=d=G4ZUdFBetU8Uj4FJV)T+h@0p)HU8`_w)B?^J&Ozjfig|0daY zzy_!%5n+I3(l#(Qj@j^ED|q>T1&_Jlfa5jk{LiM_gx`Rn2pAXui6ba&BNFZ>00000 LNkvXXu0mjfOo;G9 literal 0 HcmV?d00001 diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonSearch.png b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonSearch.png new file mode 100644 index 0000000000000000000000000000000000000000..03d9e50f0dda5b4f7842d68a3e3fdaba2f8f3357 GIT binary patch literal 632 zcmV-;0*C#HP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGiy#N3Xy#Yu2kgWg!0u4z-K~y+TW1tE6 z_U)VH_wU~mfH)0^9sd9S&jgji559i=Y7W%UwCe7gv-Rhn-l;tO`2M2Xug`z|_H7$b z+y$x(JNWhMm+|9wUv@?Byz|Oz`IZ03ICRVP_g7zj+z&Lw391|u{P^*sE^YPo7nW1b z{tsGs_S4Mck1sDi{q#cgva9dFVso#&1GxmNcYr1Wcg*$H!0KHHQ#QBe2e%$Smf8e`i>F)o#&pka3G*B0+4HbZFowWMO zHOt&B|FsIX{mGeh;z`MjqmLZp7ypKdoxJw^FtYbh05EjffQDpET6O-KR>s;t7OAWM z!*F2P+K(XGDQEq!lb0S7G$iHut9LuMAHIHK{l06b?mc?5=j+#R+fo|WKQ|7a`QO%O z-mjzQ?&CHD1pfW|#|`wWJ}7Yk4HX2jL53uhEqt!++4SGkr~cQ`v$qZdEmMMOAq-%K zL}vFsSF+0ZU*EIr22d;%Doq>!8S?4V*KJc~&N~MRFOW;2Qp5vLQbwdk1_l6YZjwO6 S!th`K0000J%=P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGiy#N3Xy#Yu2kgWg!0n|xEK~y+Tm6A(q zQ&AL!w~&e;sGx|JQi}crb>?qSQtH4)lX#mKi3Sl7je@;-6*Y>FXgYGL15v7WB(|hh ztsn$NVq!w96Y;I3xx@s`=ef7VQ6RkwHhXan-`eLKjud}xqt@!9*6ia$dn=ydB=diJ zDc1)mFAh*`^jl?m>7=m>8lL?rF6V}M&w8|jajTb`o2*Ko*KiG;qgdb4IiS>DLlp-; zcY+E%1PU*(qP#LTpt({MTWcvSZ0sCx<>p?3nr>AQA>d6=Qr+)K@<#QM18EAs zSM%c6y8i*W8R14=7@w7$ayWFx0z)G@1uG!Q>*Zc(s~~rZmrdc>LXQ=Yof1ry8oRml zP>^`WMKls4>>p+BkC47LL?m#Q)4HE0i$ZKPNWh(DM)~Zt@TGo-is7W(@Q}H$0vry< zE)~3^TjgejZ^i`rZQ=2EA@e}NOMBgwdn$Z3Zc#P%G4(^ZXdZo~a8^AQeBxbwkVju_ zP9C2#;g9N5Ik{W22?u;f6 + /// 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() + { + this.components = new System.ComponentModel.Container(); + this.kryptonPanel1 = new Krypton.Toolkit.KryptonPanel(); + this.kbtnApplySavedFilters = new Krypton.Toolkit.KryptonButton(); + this.kbtnClearFilters = new Krypton.Toolkit.KryptonButton(); + this.kbtnSaveFilters = new Krypton.Toolkit.KryptonButton(); + this.kryptonLabel6 = new Krypton.Toolkit.KryptonLabel(); + this.kryptonLabel5 = new Krypton.Toolkit.KryptonLabel(); + this.kcmbSortSaved = new Krypton.Toolkit.KryptonComboBox(); + this.kcmbSavedFilters = new Krypton.Toolkit.KryptonComboBox(); + this.ktxtStringFilter = new Krypton.Toolkit.KryptonTextBox(); + this.kryptonLabel4 = new Krypton.Toolkit.KryptonLabel(); + this.ktxtSortString = new Krypton.Toolkit.KryptonTextBox(); + this.kryptonLabel2 = new Krypton.Toolkit.KryptonLabel(); + this.ktxtFilterString = new Krypton.Toolkit.KryptonTextBox(); + this.kryptonLabel1 = new Krypton.Toolkit.KryptonLabel(); + this.kcmbMemoryTest = new Krypton.Toolkit.KryptonComboBox(); + this.kbtnMemoryTest = new Krypton.Toolkit.KryptonButton(); + this.kbtnLoadRandomData = new Krypton.Toolkit.KryptonButton(); + this.kryptonPanel2 = new Krypton.Toolkit.KryptonPanel(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.tsslMemoryUsage = new System.Windows.Forms.ToolStripStatusLabel(); + this.kryptonPanel3 = new Krypton.Toolkit.KryptonPanel(); + this.ktxtTotalRows = new Krypton.Toolkit.KryptonTextBox(); + this.kryptonLabel3 = new Krypton.Toolkit.KryptonLabel(); + this.kryptonPanel4 = new Krypton.Toolkit.KryptonPanel(); + this.kadgvMain = new Krypton.Utilities.KryptonAdvancedDataGridView(); + this.kryptonAdvancedDataGridViewSearchToolBar1 = new Krypton.Utilities.KryptonAdvancedDataGridViewSearchToolBar(); + this.bsData = new System.Windows.Forms.BindingSource(this.components); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel1)).BeginInit(); + this.kryptonPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.kcmbSortSaved)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.kcmbSavedFilters)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.kcmbMemoryTest)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel2)).BeginInit(); + this.kryptonPanel2.SuspendLayout(); + this.statusStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel3)).BeginInit(); + this.kryptonPanel3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel4)).BeginInit(); + this.kryptonPanel4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.kadgvMain)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.bsData)).BeginInit(); + this.SuspendLayout(); + // + // kryptonPanel1 + // + this.kryptonPanel1.Controls.Add(this.kbtnApplySavedFilters); + this.kryptonPanel1.Controls.Add(this.kbtnClearFilters); + this.kryptonPanel1.Controls.Add(this.kbtnSaveFilters); + this.kryptonPanel1.Controls.Add(this.kryptonLabel6); + this.kryptonPanel1.Controls.Add(this.kryptonLabel5); + this.kryptonPanel1.Controls.Add(this.kcmbSortSaved); + this.kryptonPanel1.Controls.Add(this.kcmbSavedFilters); + this.kryptonPanel1.Controls.Add(this.ktxtStringFilter); + this.kryptonPanel1.Controls.Add(this.kryptonLabel4); + this.kryptonPanel1.Controls.Add(this.ktxtSortString); + this.kryptonPanel1.Controls.Add(this.kryptonLabel2); + this.kryptonPanel1.Controls.Add(this.ktxtFilterString); + this.kryptonPanel1.Controls.Add(this.kryptonLabel1); + this.kryptonPanel1.Controls.Add(this.kcmbMemoryTest); + this.kryptonPanel1.Controls.Add(this.kbtnMemoryTest); + this.kryptonPanel1.Controls.Add(this.kbtnLoadRandomData); + this.kryptonPanel1.Dock = System.Windows.Forms.DockStyle.Top; + this.kryptonPanel1.Location = new System.Drawing.Point(0, 0); + this.kryptonPanel1.Name = "kryptonPanel1"; + this.kryptonPanel1.Size = new System.Drawing.Size(1108, 189); + this.kryptonPanel1.TabIndex = 0; + // + // kbtnApplySavedFilters + // + this.kbtnApplySavedFilters.Location = new System.Drawing.Point(1005, 72); + this.kbtnApplySavedFilters.Name = "kbtnApplySavedFilters"; + this.kbtnApplySavedFilters.Size = new System.Drawing.Size(90, 25); + this.kbtnApplySavedFilters.TabIndex = 15; + this.kbtnApplySavedFilters.Values.Text = "Apply"; + this.kbtnApplySavedFilters.Click += new System.EventHandler(this.kbtnApplySavedFilters_Click); + // + // kbtnClearFilters + // + this.kbtnClearFilters.Location = new System.Drawing.Point(669, 45); + this.kbtnClearFilters.Name = "kbtnClearFilters"; + this.kbtnClearFilters.Size = new System.Drawing.Size(179, 25); + this.kbtnClearFilters.TabIndex = 14; + this.kbtnClearFilters.Values.Text = "Clean Filter And Sort"; + this.kbtnClearFilters.Click += new System.EventHandler(this.kbtnClearFilters_Click); + // + // kbtnSaveFilters + // + this.kbtnSaveFilters.Location = new System.Drawing.Point(669, 13); + this.kbtnSaveFilters.Name = "kbtnSaveFilters"; + this.kbtnSaveFilters.Size = new System.Drawing.Size(180, 25); + this.kbtnSaveFilters.TabIndex = 13; + this.kbtnSaveFilters.Values.Text = "Save Current Filter And Sort"; + this.kbtnSaveFilters.Click += new System.EventHandler(this.kbtnSaveFilters_Click); + // + // kryptonLabel6 + // + this.kryptonLabel6.Location = new System.Drawing.Point(860, 40); + this.kryptonLabel6.Name = "kryptonLabel6"; + this.kryptonLabel6.Size = new System.Drawing.Size(71, 20); + this.kryptonLabel6.TabIndex = 12; + this.kryptonLabel6.Values.Text = "Sort Saved:"; + // + // kryptonLabel5 + // + this.kryptonLabel5.Location = new System.Drawing.Point(855, 12); + this.kryptonLabel5.Name = "kryptonLabel5"; + this.kryptonLabel5.Size = new System.Drawing.Size(76, 20); + this.kryptonLabel5.TabIndex = 11; + this.kryptonLabel5.Values.Text = "Filter Saved:"; + // + // kcmbSortSaved + // + this.kcmbSortSaved.DropDownWidth = 159; + this.kcmbSortSaved.IntegralHeight = false; + this.kcmbSortSaved.Location = new System.Drawing.Point(937, 39); + this.kcmbSortSaved.Name = "kcmbSortSaved"; + this.kcmbSortSaved.Size = new System.Drawing.Size(159, 21); + this.kcmbSortSaved.StateCommon.ComboBox.Content.TextH = Krypton.Toolkit.PaletteRelativeAlign.Near; + this.kcmbSortSaved.TabIndex = 10; + // + // kcmbSavedFilters + // + this.kcmbSavedFilters.DropDownWidth = 159; + this.kcmbSavedFilters.IntegralHeight = false; + this.kcmbSavedFilters.Location = new System.Drawing.Point(937, 12); + this.kcmbSavedFilters.Name = "kcmbSavedFilters"; + this.kcmbSavedFilters.Size = new System.Drawing.Size(159, 21); + this.kcmbSavedFilters.StateCommon.ComboBox.Content.TextH = Krypton.Toolkit.PaletteRelativeAlign.Near; + this.kcmbSavedFilters.TabIndex = 9; + // + // ktxtStringFilter + // + this.ktxtStringFilter.Location = new System.Drawing.Point(147, 159); + this.ktxtStringFilter.Name = "ktxtStringFilter"; + this.ktxtStringFilter.Size = new System.Drawing.Size(100, 23); + this.ktxtStringFilter.TabIndex = 8; + this.ktxtStringFilter.TextChanged += new System.EventHandler(this.ktxtStringFilter_TextChanged); + // + // kryptonLabel4 + // + this.kryptonLabel4.Location = new System.Drawing.Point(13, 159); + this.kryptonLabel4.Name = "kryptonLabel4"; + this.kryptonLabel4.Size = new System.Drawing.Size(128, 20); + this.kryptonLabel4.TabIndex = 7; + this.kryptonLabel4.Values.Text = "Filter column \"string\":"; + // + // ktxtSortString + // + this.ktxtSortString.Location = new System.Drawing.Point(207, 72); + this.ktxtSortString.Multiline = true; + this.ktxtSortString.Name = "ktxtSortString"; + this.ktxtSortString.ReadOnly = true; + this.ktxtSortString.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.ktxtSortString.Size = new System.Drawing.Size(180, 80); + this.ktxtSortString.TabIndex = 6; + // + // kryptonLabel2 + // + this.kryptonLabel2.Location = new System.Drawing.Point(207, 45); + this.kryptonLabel2.Name = "kryptonLabel2"; + this.kryptonLabel2.Size = new System.Drawing.Size(71, 20); + this.kryptonLabel2.TabIndex = 5; + this.kryptonLabel2.Values.Text = "Sort String:"; + // + // ktxtFilterString + // + this.ktxtFilterString.Location = new System.Drawing.Point(13, 72); + this.ktxtFilterString.Multiline = true; + this.ktxtFilterString.Name = "ktxtFilterString"; + this.ktxtFilterString.ReadOnly = true; + this.ktxtFilterString.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.ktxtFilterString.Size = new System.Drawing.Size(180, 80); + this.ktxtFilterString.TabIndex = 4; + // + // kryptonLabel1 + // + this.kryptonLabel1.Location = new System.Drawing.Point(13, 45); + this.kryptonLabel1.Name = "kryptonLabel1"; + this.kryptonLabel1.Size = new System.Drawing.Size(76, 20); + this.kryptonLabel1.TabIndex = 3; + this.kryptonLabel1.Values.Text = "Filter String:"; + // + // kcmbMemoryTest + // + this.kcmbMemoryTest.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.kcmbMemoryTest.DropDownWidth = 121; + this.kcmbMemoryTest.IntegralHeight = false; + this.kcmbMemoryTest.Location = new System.Drawing.Point(393, 13); + this.kcmbMemoryTest.Name = "kcmbMemoryTest"; + this.kcmbMemoryTest.Size = new System.Drawing.Size(121, 21); + this.kcmbMemoryTest.StateCommon.ComboBox.Content.TextH = Krypton.Toolkit.PaletteRelativeAlign.Near; + this.kcmbMemoryTest.TabIndex = 2; + // + // kbtnMemoryTest + // + this.kbtnMemoryTest.Location = new System.Drawing.Point(207, 12); + this.kbtnMemoryTest.Name = "kbtnMemoryTest"; + this.kbtnMemoryTest.Size = new System.Drawing.Size(180, 25); + this.kbtnMemoryTest.TabIndex = 1; + this.kbtnMemoryTest.Values.Text = "Memory Test"; + this.kbtnMemoryTest.Click += new System.EventHandler(this.kbtnMemoryTest_Click); + // + // kbtnLoadRandomData + // + this.kbtnLoadRandomData.Location = new System.Drawing.Point(13, 13); + this.kbtnLoadRandomData.Name = "kbtnLoadRandomData"; + this.kbtnLoadRandomData.Size = new System.Drawing.Size(167, 25); + this.kbtnLoadRandomData.TabIndex = 0; + this.kbtnLoadRandomData.Values.Text = "Load &Random Data"; + this.kbtnLoadRandomData.Click += new System.EventHandler(this.kbtnLoadRandomData_Click); + // + // kryptonPanel2 + // + this.kryptonPanel2.Controls.Add(this.statusStrip1); + this.kryptonPanel2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.kryptonPanel2.Location = new System.Drawing.Point(0, 622); + this.kryptonPanel2.Name = "kryptonPanel2"; + this.kryptonPanel2.Size = new System.Drawing.Size(1108, 22); + this.kryptonPanel2.TabIndex = 1; + // + // statusStrip1 + // + this.statusStrip1.Font = new System.Drawing.Font("Segoe UI", 9F); + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.tsslMemoryUsage}); + this.statusStrip1.Location = new System.Drawing.Point(0, 0); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.ManagerRenderMode; + this.statusStrip1.Size = new System.Drawing.Size(1108, 22); + this.statusStrip1.TabIndex = 0; + this.statusStrip1.Text = "statusStrip1"; + // + // tsslMemoryUsage + // + this.tsslMemoryUsage.Name = "tsslMemoryUsage"; + this.tsslMemoryUsage.Size = new System.Drawing.Size(116, 17); + this.tsslMemoryUsage.Text = "Memory Usage: /Mb"; + // + // kryptonPanel3 + // + this.kryptonPanel3.Controls.Add(this.ktxtTotalRows); + this.kryptonPanel3.Controls.Add(this.kryptonLabel3); + this.kryptonPanel3.Dock = System.Windows.Forms.DockStyle.Bottom; + this.kryptonPanel3.Location = new System.Drawing.Point(0, 593); + this.kryptonPanel3.Name = "kryptonPanel3"; + this.kryptonPanel3.Size = new System.Drawing.Size(1108, 29); + this.kryptonPanel3.TabIndex = 2; + // + // ktxtTotalRows + // + this.ktxtTotalRows.Location = new System.Drawing.Point(92, 3); + this.ktxtTotalRows.Name = "ktxtTotalRows"; + this.ktxtTotalRows.Size = new System.Drawing.Size(100, 23); + this.ktxtTotalRows.TabIndex = 1; + // + // kryptonLabel3 + // + this.kryptonLabel3.Location = new System.Drawing.Point(13, 6); + this.kryptonLabel3.Name = "kryptonLabel3"; + this.kryptonLabel3.Size = new System.Drawing.Size(73, 20); + this.kryptonLabel3.TabIndex = 0; + this.kryptonLabel3.Values.Text = "Total Rows:"; + // + // kryptonPanel4 + // + this.kryptonPanel4.Controls.Add(this.kadgvMain); + this.kryptonPanel4.Controls.Add(this.kryptonAdvancedDataGridViewSearchToolBar1); + this.kryptonPanel4.Dock = System.Windows.Forms.DockStyle.Fill; + this.kryptonPanel4.Location = new System.Drawing.Point(0, 189); + this.kryptonPanel4.Name = "kryptonPanel4"; + this.kryptonPanel4.Size = new System.Drawing.Size(1108, 404); + this.kryptonPanel4.TabIndex = 3; + // + // kadgvMain + // + this.kadgvMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.kadgvMain.FilterAndSortEnabled = true; + this.kadgvMain.FilterStringChangedInvokeBeforeDatasourceUpdate = true; + this.kadgvMain.Location = new System.Drawing.Point(0, 27); + this.kadgvMain.Name = "kadgvMain"; + this.kadgvMain.Size = new System.Drawing.Size(1108, 377); + this.kadgvMain.SortStringChangedInvokeBeforeDatasourceUpdate = true; + this.kadgvMain.TabIndex = 1; + this.kadgvMain.SortStringChanged += new System.EventHandler(this.kadgvMain_SortStringChanged); + this.kadgvMain.FilterStringChanged += new System.EventHandler(this.kadgvMain_FilterStringChanged); + // + // kryptonAdvancedDataGridViewSearchToolBar1 + // + this.kryptonAdvancedDataGridViewSearchToolBar1.AllowMerge = false; + this.kryptonAdvancedDataGridViewSearchToolBar1.Font = new System.Drawing.Font("Segoe UI", 9F); + this.kryptonAdvancedDataGridViewSearchToolBar1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.kryptonAdvancedDataGridViewSearchToolBar1.Location = new System.Drawing.Point(0, 0); + this.kryptonAdvancedDataGridViewSearchToolBar1.MaximumSize = new System.Drawing.Size(0, 27); + this.kryptonAdvancedDataGridViewSearchToolBar1.MinimumSize = new System.Drawing.Size(0, 27); + this.kryptonAdvancedDataGridViewSearchToolBar1.Name = "kryptonAdvancedDataGridViewSearchToolBar1"; + this.kryptonAdvancedDataGridViewSearchToolBar1.Size = new System.Drawing.Size(1108, 27); + this.kryptonAdvancedDataGridViewSearchToolBar1.TabIndex = 0; + this.kryptonAdvancedDataGridViewSearchToolBar1.Text = "kryptonAdvancedDataGridViewSearchToolBar1"; + this.kryptonAdvancedDataGridViewSearchToolBar1.Search += new Krypton.Utilities.AdvancedDataGridViewSearchToolBarSearchEventHandler(this.kryptonAdvancedDataGridViewSearchToolBar1_Search); + // + // bsData + // + this.bsData.ListChanged += new System.ComponentModel.ListChangedEventHandler(this.bsData_ListChanged); + // + // AdvancedDataGridView + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1108, 644); + this.Controls.Add(this.kryptonPanel4); + this.Controls.Add(this.kryptonPanel3); + this.Controls.Add(this.kryptonPanel2); + this.Controls.Add(this.kryptonPanel1); + this.Name = "AdvancedDataGridView"; + this.Text = "AdvancedDataGridView"; + this.Load += new System.EventHandler(this.AdvancedDataGridView_Load); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel1)).EndInit(); + this.kryptonPanel1.ResumeLayout(false); + this.kryptonPanel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.kcmbSortSaved)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.kcmbSavedFilters)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.kcmbMemoryTest)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel2)).EndInit(); + this.kryptonPanel2.ResumeLayout(false); + this.kryptonPanel2.PerformLayout(); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel3)).EndInit(); + this.kryptonPanel3.ResumeLayout(false); + this.kryptonPanel3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel4)).EndInit(); + this.kryptonPanel4.ResumeLayout(false); + this.kryptonPanel4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.kadgvMain)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.bsData)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private KryptonPanel kryptonPanel1; + private KryptonPanel kryptonPanel2; + private KryptonPanel kryptonPanel3; + private KryptonPanel kryptonPanel4; + private KryptonButton kbtnLoadRandomData; + private KryptonButton kbtnMemoryTest; + private KryptonComboBox kcmbMemoryTest; + private KryptonLabel kryptonLabel1; + private KryptonTextBox ktxtFilterString; + private KryptonTextBox ktxtSortString; + private KryptonLabel kryptonLabel2; + private Krypton.Utilities.KryptonAdvancedDataGridViewSearchToolBar kryptonAdvancedDataGridViewSearchToolBar1; + private Krypton.Utilities.KryptonAdvancedDataGridView kadgvMain; + private StatusStrip statusStrip1; + private ToolStripStatusLabel tsslMemoryUsage; + private KryptonLabel kryptonLabel3; + private KryptonTextBox ktxtTotalRows; + private KryptonLabel kryptonLabel4; + private KryptonTextBox ktxtStringFilter; + private KryptonLabel kryptonLabel5; + private KryptonComboBox kcmbSortSaved; + private KryptonComboBox kcmbSavedFilters; + private KryptonLabel kryptonLabel6; + private KryptonButton kbtnSaveFilters; + private KryptonButton kbtnClearFilters; + private KryptonButton kbtnApplySavedFilters; + private BindingSource bsData; + } +} \ No newline at end of file diff --git a/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.cs b/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.cs new file mode 100644 index 0000000000..d891365935 --- /dev/null +++ b/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.cs @@ -0,0 +1,483 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +using Krypton.Utilities; + +namespace TestForm +{ + public partial class AdvancedDataGridViewTest : KryptonForm + { + #region Instance Fields + + private DataTable? _dataTable = null; + private DataSet? _dataSet = null; + + private SortedDictionary _filtersaved = new SortedDictionary(); + private SortedDictionary _sortsaved = new SortedDictionary(); + + private bool _testtranslations = false; + private bool _testtranslationsFromFile = false; + + private static int DisplayItemsCounter = 100; + + private static bool MemoryTestEnabled = true; + private const int MEMORY_TEST_NUM = 100; + private bool _memorytest = false; + private object[][] _inrows = new object[][] { }; + + private Timer? _memorytestclosetimer = null; + private Timer? _timermemoryusage = null; + + private static bool CollectGarbageOnTimerMemoryUsageUpdate = true; + + #endregion + + #region Identity + + public AdvancedDataGridViewTest() + { + InitializeComponent(); + + //set timers + if (components != null) + { + _memorytestclosetimer = new Timer(components) + { + Interval = 10 + }; + _timermemoryusage = new Timer(components) + { + Interval = 2000 + }; + } + + //trigger the memory usage show + _timermemoryusage_Tick(null, null); + + //set localization strings + Dictionary translations = new Dictionary(); + foreach (KeyValuePair translation in KryptonAdvancedDataGridView.Translations) + { + if (!translations.ContainsKey(translation.Key)) + { + translations.Add(translation.Key, $".{translation.Value}"); + } + } + foreach (KeyValuePair translation in KryptonAdvancedDataGridViewSearchToolBar.Translations) + { + if (!translations.ContainsKey(translation.Key)) + { + translations.Add(translation.Key, $".{translation.Value}"); + } + } + if (_testtranslations) + { + KryptonAdvancedDataGridView.SetTranslations(translations); + KryptonAdvancedDataGridViewSearchToolBar.SetTranslations(translations); + } + if (_testtranslationsFromFile) + { + KryptonAdvancedDataGridView.SetTranslations(KryptonAdvancedDataGridView.LoadTranslationsFromFile("lang.json")); + KryptonAdvancedDataGridViewSearchToolBar.SetTranslations(KryptonAdvancedDataGridViewSearchToolBar.LoadTranslationsFromFile("lang.json")); + } + + //set filter and sort saved + _filtersaved.Add(0, ""); + _sortsaved.Add(0, ""); + kcmbSavedFilters.DataSource = new BindingSource(_filtersaved, null!); + kcmbSavedFilters.DisplayMember = "Key"; + kcmbSavedFilters.ValueMember = "Value"; + kcmbSavedFilters.SelectedIndex = -1; + kcmbSortSaved.DataSource = new BindingSource(_sortsaved, null!); + kcmbSortSaved.DisplayMember = "Key"; + kcmbSortSaved.ValueMember = "Value"; + kcmbSortSaved.SelectedIndex = -1; + + //set memory test button + kbtnMemoryTest.Enabled = MemoryTestEnabled; + + //initialize dataset + _dataTable = new DataTable(); + _dataSet = new DataSet(); + + //initialize bindingsource + bsData.DataSource = _dataSet; + + //initialize datagridview + kadgvMain.SetDoubleBuffered(); + kadgvMain.DataSource = bsData; + + //set bindingsource + SetTestData(); + } + + public AdvancedDataGridViewTest(bool memoryTest, object[][] inRows) : this() + { + _memorytest = memoryTest; + + _inrows = inRows; + } + + #endregion + + #region Implementation + + /// + /// Loads a sample flag PNG from the output directory when present; otherwise builds a small solid-color placeholder + /// so the Advanced DataGridView image column demo runs without shipping binary assets. + /// + private static Image LoadOrCreateSampleFlag(string fileName, Color fallbackColor) + { + string path = Path.Combine(Application.StartupPath, fileName); + if (File.Exists(path)) + { + return Image.FromFile(path); + } + + var bmp = new Bitmap(24, 24); + using (Graphics g = Graphics.FromImage(bmp)) + { + g.Clear(fallbackColor); + } + + return bmp; + } + + private void kbtnLoadRandomData_Click(object sender, EventArgs e) + { + //add test data to bindsource + AddTestData(); + } + + private void SetTestData() + { + _dataTable = _dataSet?.Tables.Add("TableTest"); + if (_dataTable != null) + { + _dataTable.Columns.Add("int", typeof(int)); + _dataTable.Columns.Add("decimal", typeof(decimal)); + _dataTable.Columns.Add("double", typeof(double)); + _dataTable.Columns.Add("date", typeof(DateTime)); + _dataTable.Columns.Add("datetime", typeof(DateTime)); + _dataTable.Columns.Add("string", typeof(string)); + _dataTable.Columns.Add("boolean", typeof(bool)); + _dataTable.Columns.Add("guid", typeof(Guid)); + _dataTable.Columns.Add("image", typeof(Bitmap)); + _dataTable.Columns.Add("timespan", typeof(TimeSpan)); + + bsData.DataMember = _dataTable.TableName; + } + + kryptonAdvancedDataGridViewSearchToolBar1.SetColumns(kadgvMain.Columns); + } + + private void AddTestData() + { + Random r = new Random(); + Image[] sampleImages = new Image[2]; + sampleImages[0] = LoadOrCreateSampleFlag("flag-green_24.png", Color.FromArgb(72, 170, 72)); + sampleImages[1] = LoadOrCreateSampleFlag("flag-red_24.png", Color.FromArgb(210, 72, 72)); + + int maxMinutes = (int)((TimeSpan.FromHours(20) - TimeSpan.FromHours(10)).TotalMinutes); + + if (_inrows.Length == 0) + { + for (int i = 0; i < DisplayItemsCounter; i++) + { + object[] newRow = + [ + i, + Math.Round((decimal)i*2/3, 6), + Math.Round(i % 2 == 0 ? (double)i*2/3 : (double)i/2, 6), + DateTime.Today.AddHours(i*2).AddHours(i%2 == 0 ?i*10+1:0).AddMinutes(i%2 == 0 ?i*10+1:0).AddSeconds(i%2 == 0 ?i*10+1:0).AddMilliseconds(i%2 == 0 ?i*10+1:0).Date, + DateTime.Today.AddHours(i*2).AddHours(i%2 == 0 ?i*10+1:0).AddMinutes(i%2 == 0 ?i*10+1:0).AddSeconds(i%2 == 0 ?i*10+1:0).AddMilliseconds(i%2 == 0 ?i*10+1:0), + (i*2 % 3 == 0 ? null : $"{i} str")!, + i % 2 == 0 ? true:false, + Guid.NewGuid(), + sampleImages[r.Next(0, 2)], + TimeSpan.FromHours(10).Add(TimeSpan.FromMinutes(r.Next(maxMinutes))) + ]; + + _dataTable?.Rows.Add(newRow); + } + } + else + { + for (int i = 0; i < _inrows.Length; i++) + { + _dataTable?.Rows.Add(_inrows[i]); + } + } + + } + + private void AdvancedDataGridView_Load(object sender, EventArgs e) + { + //add test data to bindsource + AddTestData(); + + //setup datagridview + kadgvMain.SetFilterDateAndTimeEnabled(kadgvMain.Columns["datetime"], true); + kadgvMain.SetSortEnabled(kadgvMain.Columns["guid"], false); + kadgvMain.SetFilterChecklistEnabled(kadgvMain.Columns["guid"], false); + kadgvMain.SortAscending(kadgvMain.Columns["datetime"]); + kadgvMain.SortDescending(kadgvMain.Columns["double"]); + kadgvMain.SetTextFilterRemoveNodesOnSearch(kadgvMain.Columns["double"], false); + kadgvMain.SetChecklistTextFilterRemoveNodesOnSearchMode(kadgvMain.Columns["decimal"], false); + kadgvMain.SetFilterChecklistEnabled(kadgvMain.Columns["double"], false); + kadgvMain.SetFilterCustomEnabled(kadgvMain.Columns["timespan"], false); + kadgvMain.CleanSort(kadgvMain.Columns["datetime"]); + kadgvMain.SetFilterChecklistTextFilterTextChangedDelayNodes(kadgvMain.Columns["string"], 10); + kadgvMain.SetFilterChecklistTextFilterTextChangedDelayMs(kadgvMain.Columns["string"], 500); + + //memory test + if (!_memorytest) + { + //set timer memory usage + _timermemoryusage?.Enabled = true; + _timermemoryusage?.Tick += _timermemoryusage_Tick; + } + else + { + kryptonPanel1.Visible = false; + + _memorytestclosetimer?.Enabled = true; + _memorytestclosetimer?.Tick += _memorytestclosetimer_Tick; + + foreach (DataGridViewColumn column in kadgvMain.Columns) + kadgvMain.ShowMenuStrip(column); + } + } + + private void kadgvMain_FilterStringChanged(object sender, KryptonAdvancedDataGridView.FilterEventArgs e) + { + //eventually set the FilterString here + //if e.Cancel is set to true one have to update the datasource here using + //bindingSource_main.Filter = kadgvMain.FilterString; + //otherwise it will be updated by the component + + //sample use of the override string filter + string stringColumnFilter = ktxtStringFilter.Text; + if (!string.IsNullOrEmpty(stringColumnFilter)) + { + e.FilterString += (!string.IsNullOrEmpty(e.FilterString) ? " AND " : "") + + $"string LIKE '%{stringColumnFilter.Replace("'", "''")}%'"; + } + + ktxtFilterString.Text = e.FilterString; + } + + private void kadgvMain_SortStringChanged(object sender, KryptonAdvancedDataGridView.SortEventArgs e) + { + //eventually set the SortString here + //if e.Cancel is set to true one have to update the datasource here + //bindingSource_main.Sort = kadgvMain.SortString; + //otherwise it will be updated by the component + + ktxtSortString.Text = e.SortString; + } + + private void ktxtStringFilter_TextChanged(object sender, EventArgs e) + { + //trigger the filter string changed function when text is changed + kadgvMain.TriggerFilterStringChanged(); + } + + private void bsData_ListChanged(object sender, ListChangedEventArgs e) + { + ktxtTotalRows.Text = bsData.List.Count.ToString(); + } + + private void kbtnSaveFilters_Click(object sender, EventArgs e) + { + _filtersaved.Add((kcmbSavedFilters.Items.Count - 1) + 1, kadgvMain.FilterString); + kcmbSavedFilters.DataSource = new BindingSource(_filtersaved, null!); + kcmbSavedFilters.SelectedIndex = kcmbSavedFilters.Items.Count - 1; + _sortsaved.Add((kcmbSortSaved.Items.Count - 1) + 1, kadgvMain.SortString); + kcmbSortSaved.DataSource = new BindingSource(_sortsaved, null!); + kcmbSortSaved.SelectedIndex = kcmbSortSaved.Items.Count - 1; + } + + private void kbtnApplySavedFilters_Click(object sender, EventArgs e) + { + if (kcmbSavedFilters.SelectedIndex != -1 && kcmbSortSaved.SelectedIndex != -1) + { + kadgvMain.LoadFilterAndSort(kcmbSavedFilters.SelectedValue?.ToString(), kcmbSortSaved.SelectedValue?.ToString()); + } + } + + private void kbtnClearFilters_Click(object sender, EventArgs e) + { + kadgvMain.CleanFilterAndSort(); + kcmbSavedFilters.SelectedIndex = -1; + kcmbSortSaved.SelectedIndex = -1; + } + + private void kryptonAdvancedDataGridViewSearchToolBar1_Search(object sender, AdvancedDataGridViewSearchToolBarSearchEventArgs e) + { + bool restartSearch = true; + int startColumn = 0; + int startRow = 0; + if (!e.FromBegin) + { + bool endColumn = kadgvMain.CurrentCell != null && kadgvMain.CurrentCell.ColumnIndex + 1 >= kadgvMain.ColumnCount; + bool endRow = kadgvMain.CurrentCell != null && kadgvMain.CurrentCell.RowIndex + 1 >= kadgvMain.RowCount; + + if (endColumn && endRow) + { + if (kadgvMain.CurrentCell != null) + { + startColumn = kadgvMain.CurrentCell.ColumnIndex; + startRow = kadgvMain.CurrentCell.RowIndex; + } + } + else + { + if (kadgvMain.CurrentCell != null) + { + startColumn = endColumn ? 0 : kadgvMain.CurrentCell.ColumnIndex + 1; + startRow = kadgvMain.CurrentCell.RowIndex + (endColumn ? 1 : 0); + } + } + } + DataGridViewCell? c = kadgvMain.FindCell( + e.ValueToSearch, + e.ColumnToSearch != null ? e.ColumnToSearch.Name : null, + startRow, + startColumn, + e.WholeWord, + e.CaseSensitive); + if (c == null && restartSearch) + { + c = kadgvMain.FindCell( + e.ValueToSearch, + e.ColumnToSearch != null ? e.ColumnToSearch.Name : null, + 0, + 0, + e.WholeWord, + e.CaseSensitive); + } + + if (c != null) + { + kadgvMain.CurrentCell = c; + } + } + + private void _timermemoryusage_Tick(object? sender, EventArgs? e) + { + if (CollectGarbageOnTimerMemoryUsageUpdate) + { + GC.Collect(); + } + + tsslMemoryUsage.Text = $@"Memory Usage: {GC.GetTotalMemory(false) / (1024 * 1024)}Mb"; + } + + private void kbtnMemoryTest_Click(object sender, EventArgs e) + { + if (kcmbMemoryTest.SelectedItem != null && kcmbMemoryTest.SelectedItem.ToString() == "FullForm") + { + //build random data + Random r = new Random(); + Image[] sampleimages = new Image[2]; + sampleimages[0] = LoadOrCreateSampleFlag("flag-green_24.png", Color.FromArgb(72, 170, 72)); + sampleimages[1] = LoadOrCreateSampleFlag("flag-red_24.png", Color.FromArgb(210, 72, 72)); + int maxMinutes = (int)((TimeSpan.FromHours(20) - TimeSpan.FromHours(10)).TotalMinutes); + object[][] testrows = new object[100][]; + for (int i = 0; i < 100; i++) + { + object[] newrow = new object[] { + i, + Math.Round((decimal)i*2/3, 6), + Math.Round(i % 2 == 0 ? (double)i*2/3 : (double)i/2, 6), + DateTime.Today.AddHours(i*2).AddHours(i%2 == 0 ?i*10+1:0).AddMinutes(i%2 == 0 ?i*10+1:0).AddSeconds(i%2 == 0 ?i*10+1:0).AddMilliseconds(i%2 == 0 ?i*10+1:0).Date, + DateTime.Today.AddHours(i*2).AddHours(i%2 == 0 ?i*10+1:0).AddMinutes(i%2 == 0 ?i*10+1:0).AddSeconds(i%2 == 0 ?i*10+1:0).AddMilliseconds(i%2 == 0 ?i*10+1:0), + (i*2 % 3 == 0 ? null : $"{i} str")!, + i % 2 == 0 ? true:false, + Guid.NewGuid(), + sampleimages[r.Next(0, 2)], + TimeSpan.FromHours(10).Add(TimeSpan.FromMinutes(r.Next(maxMinutes))) + }; + + testrows.SetValue(newrow, i); + } + + //show the forms + for (int i = 0; i < MEMORY_TEST_NUM; i++) + { + AdvancedDataGridViewTest formtest = new AdvancedDataGridViewTest(true, testrows); + formtest.Show(); + //wait for the form to be disposed + while (!formtest.IsDisposed) + { + Application.DoEvents(); + System.Threading.Thread.Sleep(100); + } + } + } + else if (kcmbMemoryTest.SelectedItem != null && kcmbMemoryTest.SelectedItem.ToString() == "DataSource") + { + object? datasourcePrev = kadgvMain.DataSource; + + //initialize dataset + DataTable dataTableTest = new DataTable(); + DataSet dataSetTest = new DataSet(); + dataTableTest = dataSetTest.Tables.Add("TableTest"); + dataTableTest.Columns.Add("int", typeof(int)); + dataTableTest.Columns.Add("decimal", typeof(decimal)); + dataTableTest.Columns.Add("double", typeof(double)); + //add data + for (int i = 0; i < 100; i++) + { + object[] newrow = new object[] { + i, + Math.Round((decimal)i*2/3, 6), + Math.Round(i % 2 == 0 ? (double)i*2/3 : (double)i/2, 6) + }; + dataTableTest.Rows.Add(newrow); + } + + //update the DataSource + for (int i = 0; i < MEMORY_TEST_NUM; i++) + { + using (BindingSource bindingSourceTest = new BindingSource()) + { + bindingSourceTest.DataSource = dataSetTest; + bindingSourceTest.DataMember = dataTableTest.TableName; + kadgvMain.DataSource = null; + kadgvMain.ColumnHeadersVisible = false; + kadgvMain.DataSource = bindingSourceTest; + kadgvMain.Refresh(); + kadgvMain.ColumnHeadersVisible = true; + Application.DoEvents(); + } + } + + //restore original datasource + kadgvMain.DataSource = datasourcePrev; + } + else + { + KryptonMessageBox.Show("Select a Memory Test", "Warning", KryptonMessageBoxButtons.OK, KryptonMessageBoxIcon.Warning); + } + } + + private void _memorytestclosetimer_Tick(object? sender, EventArgs e) + { + _dataTable?.Rows.Clear(); + + Close(); + } + + #endregion + } +} diff --git a/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.resx b/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + \ No newline at end of file diff --git a/Source/Krypton Components/TestForm/StartScreen.cs b/Source/Krypton Components/TestForm/StartScreen.cs index 75dc0b1599..d35fd5e8f1 100644 --- a/Source/Krypton Components/TestForm/StartScreen.cs +++ b/Source/Krypton Components/TestForm/StartScreen.cs @@ -57,6 +57,7 @@ public StartScreen() /// private void AddButtons() { + CreateButton("KryptonAdvancedDataGridView", "Need to manipulate some data?"); CreateButton("AboutBox", "Try this About Box for a change"); CreateButton("Accessibility Test (UIA Providers)", "Comprehensive demo and test for UIA Provider implementation (Issue #762). Tests all 10 controls with accessibility support, organized by category with detailed results."); CreateButton("Badge Test", "Comprehensive badge functionality demonstration for KryptonButton and KryptonCheckButton."); diff --git a/Source/Krypton Components/TestForm/flag-green_24.png b/Source/Krypton Components/TestForm/flag-green_24.png new file mode 100644 index 0000000000000000000000000000000000000000..31a4a705d04573d71df87d601cecb62a78cf6a44 GIT binary patch literal 978 zcmV;@11ZXCyE9AlEK{^9K}qK4s{OzmtFDQT9{k~nme;>| zG+efVp`oFlthJ3->$@}^`Begyr3%yrj#w*dts^#YFvd}995L2G2&)E_v!3C^-{Z;s zp<=-Y1_mBC#ysq~)0(;MH_#i?vn(s`y5=k3TMysZI%A!NuiqHcQWUj%o+qi;kJnU! zWhzQhR7@B2ODNKVzP`RqzVE+at<8th_co$Drs&{ehFYY8V!DUwR{#YRRa8{GI)acfT>_VoOWQnVbFIZT$0UW}dvNl|&I{=RfUd5tyL{hoHpVRE^ZDLeWC+0f z+pc^&KW(?DvLBdWaf(Fri`90^O?DjTm25T}5|QI=ZEbVq0026lo$!Fe`;On&T~lAx z3~cun?5Wi@0?^UXQ4x>F|L}dk-f^65?d|QO>j7AgH~`UT^!Z#aS8t3t`+o+9MT%7Q zRnPMfk&?~b5P<8t=R={;J&8o(yPlq&I-qLtJOa37Vpw45Cm;_Pzyr+Qy?d?n_VzXa zyH&M8MD74$su~lK5D->XS45WgjH)6csH%#H0#;RXB4U8Fs-{KcA7ETn`$F6pv7}ET5S}v2q+XO!9~F;WMgQx zr7lbyQRpHM6oO5fU8SK9a=A6;IP(|U+TQ*wld0LSE+Cak zy>5(Yu{Um@`FvHLb&0A+RFKl@YLm70VpAe<{qtz>i7*V0g<+_U89lS;)3REkzaP*tsTYpkkzB4U7& zs+L4#5%^72b8#w9>`Nd6Gy_dQ5=gVrz*?zoD+VaC@%~GI2dn`90L#GAzo7uJI^jrb Q3;+NC07*qoM6N<$f(#JJzyJUM literal 0 HcmV?d00001