#region Imports using DPumpHydr.WinFrmUI.RLT.Child.Material; using DPumpHydr.WinFrmUI.RLT.Helper; using DPumpHydr.WinFrmUI.RLT.Manager; using DPumpHydr.WinFrmUI.RLT.Util; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; using static DPumpHydr.WinFrmUI.RLT.Helper.MaterialDrawHelper; using static DPumpHydr.WinFrmUI.RLT.Util.MaterialAnimations; #endregion namespace DPumpHydr.WinFrmUI.RLT.Controls { #region MaterialTextBoxEdit public class MaterialTextBoxEdit : Control, MaterialControlI { MaterialContextMenuStrip cms = new MaterialBaseTextBoxContextMenuStrip(); ContextMenuStrip _lastContextMenuStrip = new(); //Properties for managing the material design properties [Browsable(false)] public int Depth { get; set; } [Browsable(false)] public MaterialSkinManager SkinManager => MaterialSkinManager.Instance; /// /// /// /// public new bool Focus() { return baseTextBox.Focus(); } [Browsable(false)] public MaterialMouseState MouseState { get; set; } //Unused properties [Browsable(false)] public override Image BackgroundImage { get; set; } [Browsable(false)] public override ImageLayout BackgroundImageLayout { get; set; } [Browsable(false)] public string SelectedText { get => baseTextBox.SelectedText; set => baseTextBox.SelectedText = value; } [Browsable(false)] public int SelectionStart { get => baseTextBox.SelectionStart; set => baseTextBox.SelectionStart = value; } [Browsable(false)] public int SelectionLength { get => baseTextBox.SelectionLength; set => baseTextBox.SelectionLength = value; } [Browsable(false)] public int TextLength => baseTextBox.TextLength; [Browsable(false)] public override Color ForeColor { get; set; } //Material properties private bool _UseTallSize; [Category("Material"), DefaultValue(true), Description("Using a larger size enables the hint to always be visible")] public bool UseTallSize { get => _UseTallSize; set { _UseTallSize = value; UpdateHeight(); UpdateRects(); Invalidate(); } } private bool _showAssistiveText; [Category("Material"), DefaultValue(false), Description("Assistive elements provide additional detail about text entered into text fields. Could be Helper text or Error message.")] public bool ShowAssistiveText { get => _showAssistiveText; set { _showAssistiveText = value; if (_showAssistiveText) { _helperTextHeight = HELPER_TEXT_HEIGHT; } else { _helperTextHeight = 0; } UpdateHeight(); //UpdateRects(); Invalidate(); } } private string _helperText; [Category("Material"), DefaultValue(""), Localizable(true), Description("Helper text conveys additional guidance about the input field, such as how it will be used.")] public string HelperText { get => _helperText; set { _helperText = value; Invalidate(); } } [Category("Material"), DefaultValue(""), Localizable(true), Description("Helper text conveys additional guidance about the input field, such as how it will be used.")] public string NullValuePromptText { get => _nullValuePromptText; set { _nullValuePromptText = value; Invalidate(); } } private string _nullValuePromptText; private string _errorMessage; [Category("Material"), DefaultValue(""), Localizable(true), Description("When text input isn't accepted, an error message can display instructions on how to fix it. Error messages are displayed below the input line, replacing helper text until fixed.")] public string ErrorMessage { get => _errorMessage; set { _errorMessage = value; Invalidate(); } } [Category("Material"), DefaultValue(""), Localizable(true)] public string Hint { get => baseTextBox.Hint; set { baseTextBox.Hint = value; hasHint = !string.IsNullOrEmpty(baseTextBox.Hint); UpdateRects(); Invalidate(); } } [Category("Material"), DefaultValue(true)] public bool UseAccent { get; set; } private Image _leadingIcon; [Category("Material"), Browsable(true), Localizable(false)] /// /// Gets or sets the leading Icon /// public Image LeadingIcon { get => _leadingIcon; set { _leadingIcon = value; UpdateRects(); preProcessIcons(); Invalidate(); } } private Image _trailingIcon; [Category("Material"), Browsable(true), Localizable(false)] /// /// Gets or sets the trailing Icon /// public Image TrailingIcon { get => _trailingIcon; set { _trailingIcon = value; UpdateRects(); preProcessIcons(); Invalidate(); } } public enum PrefixSuffixTypes { None, Prefix, Suffix, } private PrefixSuffixTypes _prefixsuffix; [Category("Material"), DefaultValue(PrefixSuffixTypes.None), Description("Set Prefix/Suffix/None")] public PrefixSuffixTypes PrefixSuffix { get => _prefixsuffix; set { _prefixsuffix = value; UpdateRects(); //Génére une nullref exception if (_prefixsuffix == PrefixSuffixTypes.Suffix) { RightToLeft = RightToLeft.Yes; } else { RightToLeft = RightToLeft.No; } Invalidate(); } } private string _prefixsuffixText; [Category("Material"), DefaultValue(""), Localizable(true), Description("Set Prefix or Suffix text")] public string PrefixSuffixText { get => _prefixsuffixText; set { //if (_prefixsuffixText != value) //{ _prefixsuffixText = value; UpdateRects(); Invalidate(); //} } } //TextBox properties public override ContextMenuStrip ContextMenuStrip { get => baseTextBox.ContextMenuStrip; set { if (value != null) { //ContextMenuStrip = value; baseTextBox.ContextMenuStrip = value; base.ContextMenuStrip = value; } else { //ContextMenuStrip = cms; baseTextBox.ContextMenuStrip = cms; base.ContextMenuStrip = cms; } _lastContextMenuStrip = base.ContextMenuStrip; } } [Browsable(false)] public override Color BackColor => Parent == null ? SkinManager.BackgroundColor : Parent.BackColor; public override string Text { get => baseTextBox.Text; set { baseTextBox.Text = value; UpdateRects(); } } [Category("Appearance")] public HorizontalAlignment TextAlign { get => baseTextBox.TextAlign; set => baseTextBox.TextAlign = value; } [Category("Behavior")] public CharacterCasing CharacterCasing { get => baseTextBox.CharacterCasing; set => baseTextBox.CharacterCasing = value; } [Category("Behavior")] public bool HideSelection { get => baseTextBox.HideSelection; set => baseTextBox.HideSelection = value; } [Category("Behavior")] public int MaxLength { get => baseTextBox.MaxLength; set => baseTextBox.MaxLength = value; } [Category("Behavior")] public char PasswordChar { get => baseTextBox.PasswordChar; set => baseTextBox.PasswordChar = value; } [Category("Behavior")] public bool ShortcutsEnabled { get => baseTextBox.ShortcutsEnabled; set { baseTextBox.ShortcutsEnabled = value; if (value == false) { baseTextBox.ContextMenuStrip = null; base.ContextMenuStrip = null; } else { baseTextBox.ContextMenuStrip = _lastContextMenuStrip; base.ContextMenuStrip = _lastContextMenuStrip; } } } [Category("Behavior")] public bool UseSystemPasswordChar { get => baseTextBox.UseSystemPasswordChar; set => baseTextBox.UseSystemPasswordChar = value; } public new object Tag { get => baseTextBox.Tag; set => baseTextBox.Tag = value; } private bool _readonly; [Category("Behavior")] public bool ReadOnly { get => _readonly; set { _readonly = value; if (Enabled == true) { baseTextBox.ReadOnly = _readonly; } this.Invalidate(); } } private bool _animateReadOnly; [Category("Material")] [Browsable(true)] public bool AnimateReadOnly { get => _animateReadOnly; set { _animateReadOnly = value; Invalidate(); } } private bool _leaveOnEnterKey; [Category("Material"), DefaultValue(false), Description("Select next control which have TabStop property set to True when enter key is pressed.")] public bool LeaveOnEnterKey { get => _leaveOnEnterKey; set { _leaveOnEnterKey = value; if (value) { baseTextBox.KeyDown += new KeyEventHandler(LeaveOnEnterKey_KeyDown); } else { baseTextBox.KeyDown -= LeaveOnEnterKey_KeyDown; } Invalidate(); } } public AutoCompleteStringCollection AutoCompleteCustomSource { get => baseTextBox.AutoCompleteCustomSource; set => baseTextBox.AutoCompleteCustomSource = value; } public AutoCompleteSource AutoCompleteSource { get => baseTextBox.AutoCompleteSource; set => baseTextBox.AutoCompleteSource = value; } public AutoCompleteMode AutoCompleteMode { get => baseTextBox.AutoCompleteMode; set => baseTextBox.AutoCompleteMode = value; } public void SelectAll() { baseTextBox.SelectAll(); } public void Clear() { baseTextBox.Clear(); } public void Copy() { baseTextBox.Copy(); } public void Cut() { baseTextBox.Cut(); } public void Undo() { baseTextBox.Undo(); } public void Paste() { baseTextBox.Paste(); } #region "Events" [Category("Action")] [Description("Fires when Leading Icon is clicked")] public event EventHandler LeadingIconClick; [Category("Action")] [Description("Fires when Trailing Icon is clicked")] public event EventHandler TrailingIconClick; #endregion # region Forwarding events to baseTextBox public event EventHandler AcceptsTabChanged { add => baseTextBox.AcceptsTabChanged += value; remove => baseTextBox.AcceptsTabChanged -= value; } public new event EventHandler AutoSizeChanged { add => baseTextBox.AutoSizeChanged += value; remove => baseTextBox.AutoSizeChanged -= value; } public new event EventHandler BackgroundImageChanged { add => baseTextBox.BackgroundImageChanged += value; remove => baseTextBox.BackgroundImageChanged -= value; } public new event EventHandler BackgroundImageLayoutChanged { add => baseTextBox.BackgroundImageLayoutChanged += value; remove => baseTextBox.BackgroundImageLayoutChanged -= value; } public new event EventHandler BindingContextChanged { add => baseTextBox.BindingContextChanged += value; remove => baseTextBox.BindingContextChanged -= value; } public event EventHandler BorderStyleChanged { add => baseTextBox.BorderStyleChanged += value; remove => baseTextBox.BorderStyleChanged -= value; } public new event EventHandler CausesValidationChanged { add => baseTextBox.CausesValidationChanged += value; remove => baseTextBox.CausesValidationChanged -= value; } public new event UICuesEventHandler ChangeUICues { add => baseTextBox.ChangeUICues += value; remove => baseTextBox.ChangeUICues -= value; } public new event EventHandler Click { add => baseTextBox.Click += value; remove => baseTextBox.Click -= value; } public new event EventHandler ClientSizeChanged { add => baseTextBox.ClientSizeChanged += value; remove => baseTextBox.ClientSizeChanged -= value; } #if NETFRAMEWORK public new event EventHandler ContextMenuChanged { add => baseTextBox.ContextMenuChanged += value; remove => baseTextBox.ContextMenuChanged -= value; } #endif public new event EventHandler ContextMenuStripChanged { add => baseTextBox.ContextMenuStripChanged += value; remove => baseTextBox.ContextMenuStripChanged -= value; } public new event ControlEventHandler ControlAdded { add => baseTextBox.ControlAdded += value; remove => baseTextBox.ControlAdded -= value; } public new event ControlEventHandler ControlRemoved { add => baseTextBox.ControlRemoved += value; remove => baseTextBox.ControlRemoved -= value; } public new event EventHandler CursorChanged { add => baseTextBox.CursorChanged += value; remove => baseTextBox.CursorChanged -= value; } public new event EventHandler Disposed { add => baseTextBox.Disposed += value; remove => baseTextBox.Disposed -= value; } public new event EventHandler DockChanged { add => baseTextBox.DockChanged += value; remove => baseTextBox.DockChanged -= value; } public new event EventHandler DoubleClick { add => baseTextBox.DoubleClick += value; remove => baseTextBox.DoubleClick -= value; } public new event DragEventHandler DragDrop { add => baseTextBox.DragDrop += value; remove => baseTextBox.DragDrop -= value; } public new event DragEventHandler DragEnter { add => baseTextBox.DragEnter += value; remove => baseTextBox.DragEnter -= value; } public new event EventHandler DragLeave { add => baseTextBox.DragLeave += value; remove => baseTextBox.DragLeave -= value; } public new event DragEventHandler DragOver { add => baseTextBox.DragOver += value; remove => baseTextBox.DragOver -= value; } public new event EventHandler EnabledChanged { add => baseTextBox.EnabledChanged += value; remove => baseTextBox.EnabledChanged -= value; } public new event EventHandler Enter { add => baseTextBox.Enter += value; remove => baseTextBox.Enter -= value; } public new event EventHandler FontChanged { add => baseTextBox.FontChanged += value; remove => baseTextBox.FontChanged -= value; } public new event EventHandler ForeColorChanged { add => baseTextBox.ForeColorChanged += value; remove => baseTextBox.ForeColorChanged -= value; } public new event GiveFeedbackEventHandler GiveFeedback { add => baseTextBox.GiveFeedback += value; remove => baseTextBox.GiveFeedback -= value; } public new event EventHandler GotFocus { add => baseTextBox.GotFocus += value; remove => baseTextBox.GotFocus -= value; } public new event EventHandler HandleCreated { add => baseTextBox.HandleCreated += value; remove => baseTextBox.HandleCreated -= value; } public new event EventHandler HandleDestroyed { add => baseTextBox.HandleDestroyed += value; remove => baseTextBox.HandleDestroyed -= value; } public new event HelpEventHandler HelpRequested { add => baseTextBox.HelpRequested += value; remove => baseTextBox.HelpRequested -= value; } public event EventHandler HideSelectionChanged { add => baseTextBox.HideSelectionChanged += value; remove => baseTextBox.HideSelectionChanged -= value; } public new event EventHandler ImeModeChanged { add => baseTextBox.ImeModeChanged += value; remove => baseTextBox.ImeModeChanged -= value; } public new event InvalidateEventHandler Invalidated { add => baseTextBox.Invalidated += value; remove => baseTextBox.Invalidated -= value; } public new event KeyEventHandler KeyDown { add => baseTextBox.KeyDown += value; remove => baseTextBox.KeyDown -= value; } public new event KeyPressEventHandler KeyPress { add => baseTextBox.KeyPress += value; remove => baseTextBox.KeyPress -= value; } public new event KeyEventHandler KeyUp { add => baseTextBox.KeyUp += value; remove => baseTextBox.KeyUp -= value; } public new event LayoutEventHandler Layout { add => baseTextBox.Layout += value; remove => baseTextBox.Layout -= value; } public new event EventHandler Leave { add => baseTextBox.Leave += value; remove => baseTextBox.Leave -= value; } public new event EventHandler LocationChanged { add => baseTextBox.LocationChanged += value; remove => baseTextBox.LocationChanged -= value; } public new event EventHandler LostFocus { add => baseTextBox.LostFocus += value; remove => baseTextBox.LostFocus -= value; } public new event EventHandler MarginChanged { add => baseTextBox.MarginChanged += value; remove => baseTextBox.MarginChanged -= value; } public event EventHandler ModifiedChanged { add => baseTextBox.ModifiedChanged += value; remove => baseTextBox.ModifiedChanged -= value; } public new event EventHandler MouseCaptureChanged { add => baseTextBox.MouseCaptureChanged += value; remove => baseTextBox.MouseCaptureChanged -= value; } public new event MouseEventHandler MouseClick { add => baseTextBox.MouseClick += value; remove => baseTextBox.MouseClick -= value; } public new event MouseEventHandler MouseDoubleClick { add => baseTextBox.MouseDoubleClick += value; remove => baseTextBox.MouseDoubleClick -= value; } public new event MouseEventHandler MouseDown { add => baseTextBox.MouseDown += value; remove => baseTextBox.MouseDown -= value; } public new event EventHandler MouseEnter { add => baseTextBox.MouseEnter += value; remove => baseTextBox.MouseEnter -= value; } public new event EventHandler MouseHover { add => baseTextBox.MouseHover += value; remove => baseTextBox.MouseHover -= value; } public new event EventHandler MouseLeave { add => baseTextBox.MouseLeave += value; remove => baseTextBox.MouseLeave -= value; } public new event MouseEventHandler MouseMove { add => baseTextBox.MouseMove += value; remove => baseTextBox.MouseMove -= value; } public new event MouseEventHandler MouseUp { add => baseTextBox.MouseUp += value; remove => baseTextBox.MouseUp -= value; } public new event MouseEventHandler MouseWheel { add => baseTextBox.MouseWheel += value; remove => baseTextBox.MouseWheel -= value; } public new event EventHandler Move { add => baseTextBox.Move += value; remove => baseTextBox.Move -= value; } public event EventHandler MultilineChanged { add => baseTextBox.MultilineChanged += value; remove => baseTextBox.MultilineChanged -= value; } public new event EventHandler PaddingChanged { add => baseTextBox.PaddingChanged += value; remove => baseTextBox.PaddingChanged -= value; } public new event PaintEventHandler Paint { add => baseTextBox.Paint += value; remove => baseTextBox.Paint -= value; } public new event EventHandler ParentChanged { add => baseTextBox.ParentChanged += value; remove => baseTextBox.ParentChanged -= value; } public new event PreviewKeyDownEventHandler PreviewKeyDown { add => baseTextBox.PreviewKeyDown += value; remove => baseTextBox.PreviewKeyDown -= value; } public new event QueryAccessibilityHelpEventHandler QueryAccessibilityHelp { add => baseTextBox.QueryAccessibilityHelp += value; remove => baseTextBox.QueryAccessibilityHelp -= value; } public new event QueryContinueDragEventHandler QueryContinueDrag { add => baseTextBox.QueryContinueDrag += value; remove => baseTextBox.QueryContinueDrag -= value; } public event EventHandler ReadOnlyChanged { add => baseTextBox.ReadOnlyChanged += value; remove => baseTextBox.ReadOnlyChanged -= value; } public new event EventHandler RegionChanged { add => baseTextBox.RegionChanged += value; remove => baseTextBox.RegionChanged -= value; } public new event EventHandler Resize { add => baseTextBox.Resize += value; remove => baseTextBox.Resize -= value; } public new event EventHandler RightToLeftChanged { add => baseTextBox.RightToLeftChanged += value; remove => baseTextBox.RightToLeftChanged -= value; } public new event EventHandler SizeChanged { add => baseTextBox.SizeChanged += value; remove => baseTextBox.SizeChanged -= value; } public new event EventHandler StyleChanged { add => baseTextBox.StyleChanged += value; remove => baseTextBox.StyleChanged -= value; } public new event EventHandler SystemColorsChanged { add => baseTextBox.SystemColorsChanged += value; remove => baseTextBox.SystemColorsChanged -= value; } public new event EventHandler TabIndexChanged { add => baseTextBox.TabIndexChanged += value; remove => baseTextBox.TabIndexChanged -= value; } public new event EventHandler TabStopChanged { add => baseTextBox.TabStopChanged += value; remove => baseTextBox.TabStopChanged -= value; } public event EventHandler TextAlignChanged { add => baseTextBox.TextAlignChanged += value; remove => baseTextBox.TextAlignChanged -= value; } public new event EventHandler TextChanged { add => baseTextBox.TextChanged += value; remove => baseTextBox.TextChanged -= value; } public new event EventHandler Validated { add => baseTextBox.Validated += value; remove => baseTextBox.Validated -= value; } public new event CancelEventHandler Validating { add => baseTextBox.Validating += value; remove => baseTextBox.Validating -= value; } public new event EventHandler VisibleChanged { add => baseTextBox.VisibleChanged += value; remove => baseTextBox.VisibleChanged -= value; } # endregion private readonly AnimationManager _animationManager; public bool isFocused = false; private const int PREFIX_SUFFIX_PADDING = 4; private const int ICON_SIZE = 24; private const int HINT_TEXT_SMALL_SIZE = 18; private const int HINT_TEXT_SMALL_Y = 4; private const int LEFT_PADDING = 16; private const int RIGHT_PADDING = 12; private const int ACTIVATION_INDICATOR_HEIGHT = 2; private const int HELPER_TEXT_HEIGHT = 16; private const int FONT_HEIGHT = 20; private int HEIGHT = 48; private int LINE_Y; private bool hasHint; private bool _errorState = false; private int _left_padding; private int _right_padding; private int _prefix_padding; private int _suffix_padding; private int _helperTextHeight; private Rectangle _leadingIconBounds; private Rectangle _trailingIconBounds; private Dictionary iconsBrushes; private Dictionary iconsErrorBrushes; protected readonly MaterialBaseTextBox baseTextBox; public MaterialTextBoxEdit() { // Material Properties UseAccent = true; MouseState = MaterialMouseState.OUT; SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.DoubleBuffer, true); // Animations _animationManager = new AnimationManager { Increment = 0.06, AnimationType = AnimationType.EaseInOut, InterruptAnimation = false }; _animationManager.OnAnimationProgress += sender => Invalidate(); SkinManager.ColorSchemeChanged += sender => { preProcessIcons(); }; SkinManager.ThemeChanged += sender => { preProcessIcons(); }; Font = SkinManager.GetFontByType(MaterialSkinManager.FontType.Subtitle1); baseTextBox = new MaterialBaseTextBox { BorderStyle = BorderStyle.None, Font = base.Font, ForeColor = SkinManager.TextHighEmphasisColor, Multiline = false, Location = new Point(LEFT_PADDING, (HEIGHT / 2) - (FONT_HEIGHT / 2)), Width = Width - (LEFT_PADDING + RIGHT_PADDING), Height = FONT_HEIGHT }; Enabled = true; ReadOnly = false; Size = new Size(250, HEIGHT); UseTallSize = true; PrefixSuffix = PrefixSuffixTypes.None; ShowAssistiveText = false; HelperText = string.Empty; ErrorMessage = string.Empty; if (!Controls.Contains(baseTextBox) && !DesignMode) { Controls.Add(baseTextBox); } baseTextBox.GotFocus += (sender, args) => { if (Enabled) { isFocused = true; _animationManager.StartNewAnimation(AnimationDirection.In); } else { base.Focus(); } UpdateRects(); }; baseTextBox.LostFocus += (sender, args) => { isFocused = false; _animationManager.StartNewAnimation(AnimationDirection.Out); UpdateRects(); }; baseTextBox.TextChanged += new EventHandler(Redraw); baseTextBox.BackColorChanged += new EventHandler(Redraw); baseTextBox.TabStop = true; this.TabStop = false; cms.Opening += ContextMenuStripOnOpening; cms.OnItemClickStart += ContextMenuStripOnItemClickStart; ContextMenuStrip = cms; } private void Redraw(object sencer, EventArgs e) { SuspendLayout(); Invalidate(); ResumeLayout(false); } protected override void OnPaint(PaintEventArgs pevent) { Graphics g = pevent.Graphics; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; g.Clear(Parent.BackColor == Color.Transparent ? ((Parent.Parent == null || (Parent.Parent != null && Parent.Parent.BackColor == Color.Transparent)) ? SkinManager.BackgroundColor : Parent.Parent.BackColor) : Parent.BackColor); SolidBrush backBrush = new(BlendColor(Parent.BackColor, SkinManager.BackgroundAlternativeColor, SkinManager.BackgroundAlternativeColor.A)); //backColor g.FillRectangle( !Enabled ? SkinManager.BackgroundDisabledBrush : // Disabled isFocused ? SkinManager.BackgroundFocusBrush : // Focused MouseState == MaterialMouseState.HOVER && (!ReadOnly || (ReadOnly && !AnimateReadOnly)) ? SkinManager.BackgroundHoverBrush : // Hover backBrush, // Normal ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, LINE_Y); baseTextBox.BackColor = !Enabled ? MaterialColorHelper.RemoveAlpha(SkinManager.BackgroundDisabledColor, BackColor) : //Disabled isFocused ? BlendColor(BackColor, SkinManager.BackgroundFocusColor, SkinManager.BackgroundFocusColor.A) : //Focused MouseState == MaterialMouseState.HOVER && (!ReadOnly || (ReadOnly && !AnimateReadOnly)) ? BlendColor(BackColor, SkinManager.BackgroundHoverColor, SkinManager.BackgroundHoverColor.A) : // Hover BlendColor(BackColor, SkinManager.BackgroundAlternativeColor, SkinManager.BackgroundAlternativeColor.A); // Normal //Leading Icon if (LeadingIcon != null) { if (_errorState) { g.FillRectangle(iconsErrorBrushes["_leadingIcon"], _leadingIconBounds); } else { g.FillRectangle(iconsBrushes["_leadingIcon"], _leadingIconBounds); } } //Trailing Icon if (TrailingIcon != null) { if (_errorState) { g.FillRectangle(iconsErrorBrushes["_trailingIcon"], _trailingIconBounds); } else { g.FillRectangle(iconsBrushes["_trailingIcon"], _trailingIconBounds); } } // HintText bool userTextPresent = !string.IsNullOrEmpty(Text); Rectangle helperTextRect = new(LEFT_PADDING - _prefix_padding, LINE_Y + ACTIVATION_INDICATOR_HEIGHT, Width - (LEFT_PADDING - _prefix_padding) - _right_padding, HELPER_TEXT_HEIGHT); Rectangle hintRect = new(_left_padding - _prefix_padding, HINT_TEXT_SMALL_Y, Width - (_left_padding - _prefix_padding) - _right_padding, HINT_TEXT_SMALL_SIZE); int hintTextSize = 12; // bottom line base g.FillRectangle(SkinManager.DividersAlternativeBrush, 0, LINE_Y, Width, 1); if (ReadOnly == false || (ReadOnly && AnimateReadOnly)) { if (!_animationManager.IsAnimating()) { // No animation // bottom line if (isFocused) { g.FillRectangle(_errorState ? SkinManager.BackgroundHoverRedBrush : isFocused ? UseAccent ? SkinManager.ColorScheme.AccentBrush : SkinManager.ColorScheme.PrimaryBrush : SkinManager.DividersBrush, 0, LINE_Y, Width, isFocused ? 2 : 1); } } else { // Animate - Focus got/lost double animationProgress = _animationManager.GetProgress(); // Line Animation int LineAnimationWidth = (int)(Width * animationProgress); int LineAnimationX = (Width / 2) - (LineAnimationWidth / 2); g.FillRectangle(UseAccent ? SkinManager.ColorScheme.AccentBrush : SkinManager.ColorScheme.PrimaryBrush, LineAnimationX, LINE_Y, LineAnimationWidth, 2); } } // Prefix: if (_prefixsuffix == PrefixSuffixTypes.Prefix && _prefixsuffixText != null && _prefixsuffixText.Length > 0 && (isFocused || userTextPresent || !hasHint)) { using MaterialNativeTextRenderer NativeText = new(g); Rectangle prefixRect = new( _left_padding - _prefix_padding, hasHint && UseTallSize ? hintRect.Y + hintRect.Height - 2 : ClientRectangle.Y, // NativeText.MeasureLogString(_prefixsuffixText, SkinManager.getLogFontByType(MaterialSkinManager.fontType.Subtitle1)).Width, _prefix_padding, hasHint && UseTallSize ? LINE_Y - (hintRect.Y + hintRect.Height) : LINE_Y); // Draw Prefix text NativeText.DrawTransparentText( _prefixsuffixText, SkinManager.GetLogFontByType(MaterialSkinManager.FontType.Subtitle1), Enabled ? SkinManager.TextMediumEmphasisColor : SkinManager.TextDisabledOrHintColor, prefixRect.Location, prefixRect.Size, MaterialNativeTextRenderer.TextAlignFlags.Left | MaterialNativeTextRenderer.TextAlignFlags.Middle); } // Suffix: if (_prefixsuffix == PrefixSuffixTypes.Suffix && _prefixsuffixText != null && _prefixsuffixText.Length > 0 && (isFocused || userTextPresent || !hasHint)) { using MaterialNativeTextRenderer NativeText = new(g); Rectangle suffixRect = new( Width - _right_padding, hasHint && UseTallSize ? hintRect.Y + hintRect.Height - 2 : ClientRectangle.Y, //NativeText.MeasureLogString(_prefixsuffixText, SkinManager.getLogFontByType(MaterialSkinManager.fontType.Subtitle1)).Width + PREFIX_SUFFIX_PADDING, _suffix_padding, hasHint && UseTallSize ? LINE_Y - (hintRect.Y + hintRect.Height) : LINE_Y); // Draw Suffix text NativeText.DrawTransparentText( _prefixsuffixText, SkinManager.GetLogFontByType(MaterialSkinManager.FontType.Subtitle1), Enabled ? SkinManager.TextMediumEmphasisColor : SkinManager.TextDisabledOrHintColor, suffixRect.Location, suffixRect.Size, MaterialNativeTextRenderer.TextAlignFlags.Right | MaterialNativeTextRenderer.TextAlignFlags.Middle); } // Draw hint text if (hasHint && UseTallSize && (isFocused || userTextPresent)) { using MaterialNativeTextRenderer NativeText = new(g); NativeText.DrawTransparentText( Hint, SkinManager.GetTextBoxFontBySize(hintTextSize), Enabled ? !_errorState || (!userTextPresent && !isFocused) ? isFocused ? UseAccent ? SkinManager.ColorScheme.AccentColor : // Focus Accent SkinManager.ColorScheme.PrimaryColor : // Focus Primary SkinManager.TextMediumEmphasisColor : // not focused SkinManager.BackgroundHoverRedColor : // error state SkinManager.TextDisabledOrHintColor, // Disabled hintRect.Location, hintRect.Size, MaterialNativeTextRenderer.TextAlignFlags.Left | MaterialNativeTextRenderer.TextAlignFlags.Middle); } // Draw helper text if (_showAssistiveText && isFocused && !_errorState) { using MaterialNativeTextRenderer NativeText = new(g); NativeText.DrawTransparentText( HelperText, SkinManager.GetTextBoxFontBySize(hintTextSize), Enabled ? !_errorState || (!userTextPresent && !isFocused) ? isFocused ? UseAccent ? SkinManager.ColorScheme.AccentColor : // Focus Accent SkinManager.ColorScheme.PrimaryColor : // Focus Primary SkinManager.TextMediumEmphasisColor : // not focused SkinManager.BackgroundHoverRedColor : // error state SkinManager.TextDisabledOrHintColor, // Disabled helperTextRect.Location, helperTextRect.Size, MaterialNativeTextRenderer.TextAlignFlags.Left | MaterialNativeTextRenderer.TextAlignFlags.Middle); } // Draw error message if (_showAssistiveText && _errorState && ErrorMessage != null) { using MaterialNativeTextRenderer NativeText = new(g); NativeText.DrawTransparentText( ErrorMessage, SkinManager.GetTextBoxFontBySize(hintTextSize), Enabled ? SkinManager.BackgroundHoverRedColor : // error state SkinManager.TextDisabledOrHintColor, // Disabled helperTextRect.Location, helperTextRect.Size, MaterialNativeTextRenderer.TextAlignFlags.Left | MaterialNativeTextRenderer.TextAlignFlags.Middle); } } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (DesignMode) { return; } if (LeadingIcon != null && _leadingIconBounds.Contains(e.Location) && LeadingIconClick != null) { Cursor = Cursors.Hand; } else if (TrailingIcon != null && _trailingIconBounds.Contains(e.Location) && TrailingIconClick != null) { Cursor = Cursors.Hand; } else { Cursor = Cursors.IBeam; } } protected override void OnMouseDown(MouseEventArgs e) { if (DesignMode) { return; } if (LeadingIcon != null && _leadingIconBounds.Contains(e.Location)) { LeadingIconClick?.Invoke(this, new EventArgs()); } else if (TrailingIcon != null && _trailingIconBounds.Contains(e.Location)) { TrailingIconClick?.Invoke(this, new EventArgs()); } else { baseTextBox?.Focus(); } base.OnMouseDown(e); } protected override void OnMouseEnter(EventArgs e) { if (DesignMode) { return; } base.OnMouseEnter(e); MouseState = MaterialMouseState.HOVER; Invalidate(); } protected override void OnMouseLeave(EventArgs e) { if (DesignMode) { return; } if (this.ClientRectangle.Contains(this.PointToClient(Control.MousePosition))) { return; } else { base.OnMouseLeave(e); MouseState = MaterialMouseState.OUT; Invalidate(); } } protected override void OnResize(EventArgs e) { base.OnResize(e); UpdateRects(); preProcessIcons(); Size = new Size(Width, HEIGHT); LINE_Y = HEIGHT - ACTIVATION_INDICATOR_HEIGHT - _helperTextHeight; } protected override void OnCreateControl() { base.OnCreateControl(); // events MouseState = MaterialMouseState.OUT; } #region Icon private static Size ResizeIcon(Image Icon) { int newWidth, newHeight; //Resize icon if greater than ICON_SIZE if (Icon.Width > ICON_SIZE || Icon.Height > ICON_SIZE) { //calculate aspect ratio float aspect = Icon.Width / (float)Icon.Height; //calculate new dimensions based on aspect ratio newWidth = (int)(ICON_SIZE * aspect); newHeight = (int)(newWidth / aspect); //if one of the two dimensions exceed the box dimensions if (newWidth > ICON_SIZE || newHeight > ICON_SIZE) { //depending on which of the two exceeds the box dimensions set it as the box dimension and calculate the other one based on the aspect ratio if (newWidth > newHeight) { newWidth = ICON_SIZE; newHeight = (int)(newWidth / aspect); } else { newHeight = ICON_SIZE; newWidth = (int)(newHeight * aspect); } } } else { newWidth = Icon.Width; newHeight = Icon.Height; } return new Size() { Height = newHeight, Width = newWidth }; } private void preProcessIcons() { if (_trailingIcon == null && _leadingIcon == null) { return; } // Calculate lightness and color float l = (SkinManager.Theme == MaterialSkinManager.Themes.LIGHT) ? 0f : 1f; // Create matrices float[][] matrixGray = { new float[] { 0, 0, 0, 0, 0}, // Red scale factor new float[] { 0, 0, 0, 0, 0}, // Green scale factor new float[] { 0, 0, 0, 0, 0}, // Blue scale factor new float[] { 0, 0, 0, Enabled ? .7f : .3f, 0}, // alpha scale factor new float[] { l, l, l, 0, 1}};// offset float[][] matrixRed = { new float[] { 0, 0, 0, 0, 0}, // Red scale factor new float[] { 0, 0, 0, 0, 0}, // Green scale factor new float[] { 0, 0, 0, 0, 0}, // Blue scale factor new float[] { 0, 0, 0, 1, 0}, // alpha scale factor new float[] { 1, 0, 0, 0, 1}};// offset ColorMatrix colorMatrixGray = new(matrixGray); ColorMatrix colorMatrixRed = new(matrixRed); ImageAttributes grayImageAttributes = new(); ImageAttributes redImageAttributes = new(); // Set color matrices grayImageAttributes.SetColorMatrix(colorMatrixGray, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); redImageAttributes.SetColorMatrix(colorMatrixRed, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); // Create brushes iconsBrushes = new Dictionary(2); iconsErrorBrushes = new Dictionary(2); // Image Rect Rectangle destRect = new(0, 0, ICON_SIZE, ICON_SIZE); if (_leadingIcon != null) { // ******************** // *** _leadingIcon *** // ******************** //Resize icon if greater than ICON_SIZE Size newSize_leadingIcon = ResizeIcon(_leadingIcon); Bitmap _leadingIconIconResized = new(_leadingIcon, newSize_leadingIcon.Width, newSize_leadingIcon.Height); // Create a pre-processed copy of the image (GRAY) Bitmap bgray = new(destRect.Width, destRect.Height); using (Graphics gGray = Graphics.FromImage(bgray)) { gGray.DrawImage(_leadingIconIconResized, new Point[] { new(0, 0), new(destRect.Width, 0), new(0, destRect.Height), }, destRect, GraphicsUnit.Pixel, grayImageAttributes); } //Create a pre - processed copy of the image(RED) Bitmap bred = new(destRect.Width, destRect.Height); using (Graphics gred = Graphics.FromImage(bred)) { gred.DrawImage(_leadingIconIconResized, new Point[] { new(0, 0), new(destRect.Width, 0), new(0, destRect.Height), }, destRect, GraphicsUnit.Pixel, redImageAttributes); } // added processed image to brush for drawing TextureBrush textureBrushGray = new(bgray); TextureBrush textureBrushRed = new(bred); textureBrushGray.WrapMode = System.Drawing.Drawing2D.WrapMode.Clamp; textureBrushRed.WrapMode = System.Drawing.Drawing2D.WrapMode.Clamp; Rectangle iconRect = _leadingIconBounds; textureBrushGray.TranslateTransform(iconRect.X + (iconRect.Width / 2) - (_leadingIconIconResized.Width / 2), iconRect.Y + (iconRect.Height / 2) - (_leadingIconIconResized.Height / 2)); textureBrushRed.TranslateTransform(iconRect.X + (iconRect.Width / 2) - (_leadingIconIconResized.Width / 2), iconRect.Y + (iconRect.Height / 2) - (_leadingIconIconResized.Height / 2)); // add to dictionary iconsBrushes.Add("_leadingIcon", textureBrushGray); iconsErrorBrushes.Add("_leadingIcon", textureBrushRed); } if (_trailingIcon != null) { // ********************* // *** _trailingIcon *** // ********************* //Resize icon if greater than ICON_SIZE Size newSize_trailingIcon = ResizeIcon(_trailingIcon); Bitmap _trailingIconResized = new(_trailingIcon, newSize_trailingIcon.Width, newSize_trailingIcon.Height); // Create a pre-processed copy of the image (GRAY) Bitmap bgray = new(destRect.Width, destRect.Height); using (Graphics gGray = Graphics.FromImage(bgray)) { gGray.DrawImage(_trailingIconResized, new Point[] { new(0, 0), new(destRect.Width, 0), new(0, destRect.Height), }, destRect, GraphicsUnit.Pixel, grayImageAttributes); } //Create a pre - processed copy of the image(RED) Bitmap bred = new(destRect.Width, destRect.Height); using (Graphics gred = Graphics.FromImage(bred)) { gred.DrawImage(_trailingIconResized, new Point[] { new(0, 0), new(destRect.Width, 0), new(0, destRect.Height), }, destRect, GraphicsUnit.Pixel, redImageAttributes); } // added processed image to brush for drawing TextureBrush textureBrushGray = new(bgray); TextureBrush textureBrushRed = new(bred); textureBrushGray.WrapMode = System.Drawing.Drawing2D.WrapMode.Clamp; textureBrushRed.WrapMode = System.Drawing.Drawing2D.WrapMode.Clamp; Rectangle iconRect = _trailingIconBounds; textureBrushGray.TranslateTransform(iconRect.X + (iconRect.Width / 2) - (_trailingIconResized.Width / 2), iconRect.Y + (iconRect.Height / 2) - (_trailingIconResized.Height / 2)); textureBrushRed.TranslateTransform(iconRect.X + (iconRect.Width / 2) - (_trailingIconResized.Width / 2), iconRect.Y + (iconRect.Height / 2) - (_trailingIconResized.Height / 2)); // add to dictionary iconsBrushes.Add("_trailingIcon", textureBrushGray); //iconsSelectedBrushes.Add(0, textureBrushColor); iconsErrorBrushes.Add("_trailingIcon", textureBrushRed); } } #endregion private void UpdateHeight() { HEIGHT = _UseTallSize ? 48 : 36; HEIGHT += _helperTextHeight; Size = new Size(Size.Width, HEIGHT); } private void UpdateRects() { if (LeadingIcon != null) { _left_padding = LEFT_PADDING + ICON_SIZE; } else { _left_padding = LEFT_PADDING; } if (_trailingIcon != null) { _right_padding = RIGHT_PADDING + ICON_SIZE; } else { _right_padding = RIGHT_PADDING; } if (_prefixsuffix == PrefixSuffixTypes.Prefix && _prefixsuffixText != null && _prefixsuffixText.Length > 0) { using MaterialNativeTextRenderer NativeText = new(CreateGraphics()); _prefix_padding = NativeText.MeasureLogString(_prefixsuffixText, SkinManager.GetLogFontByType(MaterialSkinManager.FontType.Subtitle1)).Width + PREFIX_SUFFIX_PADDING; _left_padding += _prefix_padding; } else { _prefix_padding = 0; } if (_prefixsuffix == PrefixSuffixTypes.Suffix && _prefixsuffixText != null && _prefixsuffixText.Length > 0) { using MaterialNativeTextRenderer NativeText = new(CreateGraphics()); _suffix_padding = NativeText.MeasureLogString(_prefixsuffixText, SkinManager.GetLogFontByType(MaterialSkinManager.FontType.Subtitle1)).Width + PREFIX_SUFFIX_PADDING; _right_padding += _suffix_padding; } else { _suffix_padding = 0; } if (hasHint && UseTallSize && (isFocused || !string.IsNullOrEmpty(Text))) { baseTextBox.Location = new Point(_left_padding, 22); baseTextBox.Width = Width - (_left_padding + _right_padding); baseTextBox.Height = FONT_HEIGHT; } else { baseTextBox.Location = new Point(_left_padding, ((LINE_Y + ACTIVATION_INDICATOR_HEIGHT) / 2) - (FONT_HEIGHT / 2)); baseTextBox.Width = Width - (_left_padding + _right_padding); baseTextBox.Height = FONT_HEIGHT; } _leadingIconBounds = new Rectangle(8, ((LINE_Y + ACTIVATION_INDICATOR_HEIGHT) / 2) - (ICON_SIZE / 2), ICON_SIZE, ICON_SIZE); _trailingIconBounds = new Rectangle(Width - (ICON_SIZE + 8), ((LINE_Y + ACTIVATION_INDICATOR_HEIGHT) / 2) - (ICON_SIZE / 2), ICON_SIZE, ICON_SIZE); } public void SetErrorState(bool ErrorState) { _errorState = ErrorState; if (_errorState) { baseTextBox.ForeColor = SkinManager.BackgroundHoverRedColor; } else { baseTextBox.ForeColor = SkinManager.TextHighEmphasisColor; } baseTextBox.Invalidate(); Invalidate(); } public bool GetErrorState() { return _errorState; } private void ContextMenuStripOnItemClickStart(object sender, ToolStripItemClickedEventArgs toolStripItemClickedEventArgs) { switch (toolStripItemClickedEventArgs.ClickedItem.Text) { case "Undo": Undo(); break; case "Cut": Cut(); break; case "Copy": Copy(); break; case "Paste": Paste(); break; case "Delete": SelectedText = string.Empty; break; case "Select All": SelectAll(); break; } } private void ContextMenuStripOnOpening(object sender, CancelEventArgs cancelEventArgs) { if (sender is MaterialBaseTextBoxContextMenuStrip strip) { strip.undo.Enabled = baseTextBox.CanUndo && !ReadOnly; strip.cut.Enabled = !string.IsNullOrEmpty(SelectedText) && !ReadOnly; strip.copy.Enabled = !string.IsNullOrEmpty(SelectedText); strip.paste.Enabled = Clipboard.ContainsText() && !ReadOnly; strip.delete.Enabled = !string.IsNullOrEmpty(SelectedText) && !ReadOnly; strip.selectAll.Enabled = !string.IsNullOrEmpty(Text); } } private void LeaveOnEnterKey_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { e.Handled = true; e.SuppressKeyPress = true; SendKeys.Send("{TAB}"); } } } #endregion }