diff --git a/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonDataGridViewDomainUpDownCell.cs b/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonDataGridViewDomainUpDownCell.cs index b4258a9bb..7bfb055c3 100644 --- a/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonDataGridViewDomainUpDownCell.cs +++ b/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonDataGridViewDomainUpDownCell.cs @@ -5,7 +5,7 @@ * © Component Factory Pty Ltd, 2006 - 2016, (Version 4.5.0.0) All rights reserved. * * 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), et al. 2017 - 2023. All rights reserved. + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac & Ahmed Abdelhameed et al. 2017 - 2025. All rights reserved. * */ #endregion @@ -18,14 +18,10 @@ namespace Krypton.Toolkit public class KryptonDataGridViewDomainUpDownCell : DataGridViewTextBoxCell { #region Static Fields - [ThreadStatic] - private static KryptonDomainUpDown _paintingDomainUpDown; - private const DataGridViewContentAlignment ANY_RIGHT = DataGridViewContentAlignment.TopRight | DataGridViewContentAlignment.MiddleRight | DataGridViewContentAlignment.BottomRight; private const DataGridViewContentAlignment ANY_CENTER = DataGridViewContentAlignment.TopCenter | DataGridViewContentAlignment.MiddleCenter | DataGridViewContentAlignment.BottomCenter; private static readonly Type _defaultEditType = typeof(KryptonDataGridViewDomainUpDownEditingControl); private static readonly Type _defaultValueType = typeof(string); - private static readonly Size _sizeLarge = new Size(10000, 10000); #endregion #region Identity @@ -34,14 +30,6 @@ public class KryptonDataGridViewDomainUpDownCell : DataGridViewTextBoxCell /// public KryptonDataGridViewDomainUpDownCell() { - // Create a thread specific KryptonNumericUpDown control used for the painting of the non-edited cells - if (_paintingDomainUpDown == null) - { - _paintingDomainUpDown = new KryptonDomainUpDown(); - _paintingDomainUpDown.SetLayoutDisplayPadding(new Padding(0, 0, 0, -1)); - _paintingDomainUpDown.StateCommon.Border.Width = 0; - _paintingDomainUpDown.StateCommon.Border.Draw = InheritBool.False; - } } /// @@ -70,7 +58,7 @@ public override string ToString() => [EditorBrowsable(EditorBrowsableState.Advanced)] public override void DetachEditingControl() { - DataGridView dataGridView = DataGridView; + DataGridView? dataGridView = DataGridView; if (dataGridView?.EditingControl == null) { throw new InvalidOperationException(@"Cell is detached or its grid has no editing control."); @@ -78,14 +66,11 @@ public override void DetachEditingControl() if (dataGridView.EditingControl is KryptonDomainUpDown domainUpDown) { - if (OwningColumn is KryptonDataGridViewDomainUpDownColumn domainColumn) - { - domainUpDown.Items.Clear(); + domainUpDown.Items.Clear(); - if (domainUpDown.Controls[0].Controls[1] is TextBox textBox) - { - textBox.ClearUndo(); - } + if (domainUpDown.Controls[0].Controls[1] is TextBox textBox) + { + textBox.ClearUndo(); } } @@ -98,67 +83,94 @@ public override void DetachEditingControl() /// set according to the cell properties. /// public override void InitializeEditingControl(int rowIndex, - object initialFormattedValue, - DataGridViewCellStyle dataGridViewCellStyle) + object? initialFormattedValue, + DataGridViewCellStyle dataGridViewCellStyle) { base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle); - if (DataGridView.EditingControl is KryptonDomainUpDown domainUpDown) + if (DataGridView!.EditingControl is KryptonDomainUpDown domainUpDown) { domainUpDown.Items.Clear(); domainUpDown.ButtonSpecs.Clear(); + domainUpDown.ReadOnly = KryptonOwningColumn?.ReadOnlyItemsList ?? false; - if (OwningColumn is KryptonDataGridViewDomainUpDownColumn domainColumn) + if (KryptonOwningColumn is not null) { - domainUpDown.Items.InsertRange(0, domainColumn.Items); + domainUpDown.Items.AddRange(KryptonOwningColumn.Items); } - domainUpDown.Text = initialFormattedValue is string initialFormattedValueStr ? initialFormattedValueStr : string.Empty; + domainUpDown.Text = initialFormattedValue as string ?? string.Empty; } + Debug.Print("InitializeEditingControl 5"); } - /// - /// Custom implementation of the PositionEditingControl method called by the DataGridView control when it - /// needs to relocate and/or resize the editing control. - /// - public override void PositionEditingControl(bool setLocation, - bool setSize, - Rectangle cellBounds, - Rectangle cellClip, - DataGridViewCellStyle cellStyle, - bool singleVerticalBorderAdded, - bool singleHorizontalBorderAdded, - bool isFirstDisplayedColumn, - bool isFirstDisplayedRow) + #endregion + + #region Protected + 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) { - Rectangle editingControlBounds = PositionEditingPanel(cellBounds, cellClip, cellStyle, - singleVerticalBorderAdded, singleHorizontalBorderAdded, - isFirstDisplayedColumn, isFirstDisplayedRow); + if (DataGridView is not null + && KryptonOwningColumn?.CellIndicatorImage is Image image) + { + int pos; + Rectangle textArea; + var righToLeft = DataGridView.RightToLeft == RightToLeft.Yes; + + if (righToLeft) + { + pos = cellBounds.Left; + + // The WinForms cell content always receives padding of one by default, custom padding is added tot that. + textArea = new Rectangle( + 1 + cellBounds.Left + cellStyle.Padding.Left + image.Width, + 1 + cellBounds.Top + cellStyle.Padding.Top, + cellBounds.Width - cellStyle.Padding.Left - cellStyle.Padding.Right - image.Width - 3, + cellBounds.Height - cellStyle.Padding.Top - cellStyle.Padding.Bottom - 2); + } + else + { + pos = cellBounds.Right - image.Width; + + // The WinForms cell content always receives padding of one by default, custom padding is added tot that. + textArea = new Rectangle( + 1 + cellBounds.Left + cellStyle.Padding.Left, + 1 + cellBounds.Top + cellStyle.Padding.Top, + cellBounds.Width - cellStyle.Padding.Left - cellStyle.Padding.Right - image.Width - 3, + cellBounds.Height - cellStyle.Padding.Top - cellStyle.Padding.Bottom - 2); + } + + // When the Krypton column is part of a WinForms DataGridView let the default paint routine paint the cell. + // Afterwards we paint the text and drop down image. + if (DataGridView is DataGridView) + { + base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, null, string.Empty, errorText, cellStyle, advancedBorderStyle, paintParts); + } + + // Draw the drop down button, only if no ErrorText has been set. + // If the ErrorText is set, only the error icon is shown. Otherwise both are painted on the same spot. + if (ErrorText.Length == 0) + { + graphics.DrawImage(image, new Point(pos, textArea.Top)); + } + else + { + formattedValue = errorText; + } - editingControlBounds = GetAdjustedEditingControlBounds(editingControlBounds, cellStyle); - DataGridView.EditingControl.Location = new Point(editingControlBounds.X, editingControlBounds.Y); - DataGridView.EditingControl.Size = new Size(editingControlBounds.Width, editingControlBounds.Height); + TextRenderer.DrawText(graphics, formattedValue?.ToString() ?? string.Empty, cellStyle.Font, textArea, cellStyle.ForeColor, + KryptonDataGridViewUtilities.ComputeTextFormatFlagsForCellStyleAlignment(righToLeft, cellStyle.Alignment, cellStyle.WrapMode)); + } } - #endregion - #region Protected /// /// Customized implementation of the GetErrorIconBounds function in order to draw the potential /// error icon next to the up/down buttons and not on top of them. /// protected override Rectangle GetErrorIconBounds(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex) { - const int BUTTONS_WIDTH = 16; - Rectangle errorIconBounds = base.GetErrorIconBounds(graphics, cellStyle, rowIndex); - if (DataGridView.RightToLeft == RightToLeft.Yes) - { - errorIconBounds.X = errorIconBounds.Left + BUTTONS_WIDTH; - } - else - { - errorIconBounds.X = errorIconBounds.Left - BUTTONS_WIDTH; - } + errorIconBounds.X = errorIconBounds.Left; return errorIconBounds; } @@ -168,51 +180,15 @@ protected override Rectangle GetErrorIconBounds(Graphics graphics, DataGridViewC /// protected override Size GetPreferredSize(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize) { - if (DataGridView == null) - { - return new Size(-1, -1); - } - - Size preferredSize = base.GetPreferredSize(graphics, cellStyle, rowIndex, constraintSize); - if (constraintSize.Width == 0) - { - const int BUTTONS_WIDTH = 16; // Account for the width of the up/down buttons. - const int BUTTON_MARGIN = 8; // Account for some blank pixels between the text and buttons. - preferredSize.Width += BUTTONS_WIDTH + BUTTON_MARGIN; - } - - return preferredSize; + return DataGridView == null + ? new Size(-1, -1) + : base.GetPreferredSize(graphics, cellStyle, rowIndex, constraintSize); } #endregion #region Private - private KryptonDataGridViewDomainUpDownEditingControl EditingDomainUpDown => DataGridView.EditingControl as KryptonDataGridViewDomainUpDownEditingControl; - - private Rectangle GetAdjustedEditingControlBounds(Rectangle editingControlBounds, - DataGridViewCellStyle cellStyle) - { - // Adjust the vertical location of the editing control: - var preferredHeight = _paintingDomainUpDown.GetPreferredSize(_sizeLarge).Height + 2; - if (preferredHeight < editingControlBounds.Height) - { - switch (cellStyle.Alignment) - { - case DataGridViewContentAlignment.MiddleLeft: - case DataGridViewContentAlignment.MiddleCenter: - case DataGridViewContentAlignment.MiddleRight: - editingControlBounds.Y += (editingControlBounds.Height - preferredHeight) / 2; - break; - case DataGridViewContentAlignment.BottomLeft: - case DataGridViewContentAlignment.BottomCenter: - case DataGridViewContentAlignment.BottomRight: - editingControlBounds.Y += editingControlBounds.Height - preferredHeight; - break; - } - } - - return editingControlBounds; - } + private KryptonDataGridViewDomainUpDownEditingControl EditingDomainUpDown => DataGridView!.EditingControl as KryptonDataGridViewDomainUpDownEditingControl; private void OnCommonChange() { @@ -230,7 +206,7 @@ private void OnCommonChange() } private bool OwnsEditingDomainUpDown(int rowIndex) => - rowIndex != -1 && DataGridView is { EditingControl: KryptonDataGridViewDomainUpDownEditingControl control } + rowIndex != -1 && DataGridView is { EditingControl: KryptonDataGridViewDomainUpDownEditingControl control } && (rowIndex == ((IDataGridViewEditingControl)control).EditingControlRowIndex); private static bool PartPainted(DataGridViewPaintParts paintParts, DataGridViewPaintParts paintPart) => (paintParts & paintPart) != 0; @@ -249,6 +225,11 @@ internal static HorizontalAlignment TranslateAlignment(DataGridViewContentAlignm return (align & ANY_CENTER) != 0 ? HorizontalAlignment.Center : HorizontalAlignment.Left; } } + + /// + /// Type casted version of OwningColumn + /// + internal KryptonDataGridViewDomainUpDownColumn? KryptonOwningColumn => OwningColumn as KryptonDataGridViewDomainUpDownColumn; #endregion } } \ No newline at end of file diff --git a/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonDataGridViewDomainUpDownColumn.cs b/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonDataGridViewDomainUpDownColumn.cs index bcadf70d5..c77a28219 100644 --- a/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonDataGridViewDomainUpDownColumn.cs +++ b/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonDataGridViewDomainUpDownColumn.cs @@ -5,7 +5,7 @@ * © Component Factory Pty Ltd, 2006 - 2016, (Version 4.5.0.0) All rights reserved. * * 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), et al. 2017 - 2023. All rights reserved. + * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac & Ahmed Abdelhameed et al. 2017 - 2025. All rights reserved. * */ #endregion @@ -19,13 +19,23 @@ namespace Krypton.Toolkit [ToolboxBitmap(typeof(KryptonDataGridViewDomainUpDownColumn), "ToolboxBitmaps.KryptonDomainUpDown.bmp")] public class KryptonDataGridViewDomainUpDownColumn : KryptonDataGridViewIconColumn { + #region Fields + // Cell indicator image instance + private KryptonDataGridViewCellIndicatorImage _kryptonDataGridViewCellIndicatorImage; + #endregion + #region Identity /// /// Initialize a new instance of the KryptonDataGridViewDomainUpDownColumn class. /// public KryptonDataGridViewDomainUpDownColumn() - : base(new KryptonDataGridViewDomainUpDownCell()) => - Items = new StringCollection(); + : base(new KryptonDataGridViewDomainUpDownCell()) + { + Items = []; + _kryptonDataGridViewCellIndicatorImage = new(); + + ReadOnlyItemsList = false; + } /// /// Returns a standard compact string representation of the column. @@ -55,10 +65,11 @@ public override object Clone() var strings = new string[Items.Count]; for (var i = 0; i < strings.Length; i++) { - strings[i] = Items[i]; + strings[i] = Items[i]!; } cloned.Items.AddRange(strings); + cloned.ReadOnlyItemsList = ReadOnlyItemsList; return cloned; } @@ -70,7 +81,7 @@ public override object Clone() /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public override DataGridViewCell CellTemplate + public override DataGridViewCell? CellTemplate { get => base.CellTemplate; set @@ -93,15 +104,36 @@ public override DataGridViewCell CellTemplate [Editor(@"System.Windows.Forms.Design.StringCollectionEditor", typeof(UITypeEditor))] public StringCollection Items { get; } + [Category(@"Behavior")] + [Browsable(true)] + [Description(@"Forces the user to select a value from the domain list if enabled. If not the user can select a value from the list or enter text which will be saved tot the cell.")] + [DefaultValue(false)] + public bool ReadOnlyItemsList { get; set; } #endregion #region Private /// /// Small utility function that returns the template cell as a KryptonDataGridViewDomainUpDownCell /// - private KryptonDataGridViewDomainUpDownCell DomainUpDownCellTemplate => (KryptonDataGridViewDomainUpDownCell)CellTemplate; - + private KryptonDataGridViewDomainUpDownCell DomainUpDownCellTemplate => CellTemplate as KryptonDataGridViewDomainUpDownCell; #endregion + #region Internal + /// + /// Provides the cell indicator images to the cells from from this column instance.
+ /// For internal use only. + ///
+ internal Image? CellIndicatorImage => _kryptonDataGridViewCellIndicatorImage.Image; + #endregion Internal + + #region Protected + /// + protected override void OnDataGridViewChanged() + { + _kryptonDataGridViewCellIndicatorImage.DataGridView = DataGridView as KryptonDataGridView; + base.OnDataGridViewChanged(); + } + #endregion Protected + } } \ No newline at end of file