Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ChacaracterCasing in TextBox #11931

Open
cesarchefinho opened this issue Jun 28, 2023 · 10 comments · May be fixed by #16910
Open

Support ChacaracterCasing in TextBox #11931

cesarchefinho opened this issue Jun 28, 2023 · 10 comments · May be fixed by #16910
Labels
enhancement help-wanted A contribution from the community would be most welcome.

Comments

@cesarchefinho
Copy link

Is your feature request related to a problem? Please describe.
Fix character casing on TextBoxes.

ALL FRAMEWORKS have it. (WInUI / UWP / WPF / WinForms)

Describe the solution you'd like

control how characters are cased when they are manually entered into the text box.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context

basicaly:

Add an enum

**public enum CharacterCasing
{
    Normal = 0,
    Upper,
    Lower
}**

modify textbox.cs

        **public static readonly StyledProperty<CharacterCasing> CharacterCasingProperty =
            AvaloniaProperty.Register<TextBox, CharacterCasing>(nameof(CharacterCasing));**

        **private string? AdjustCasing(string? text)
        {
            return CharacterCasing switch
            {
                CharacterCasing.Lower => text?.ToLower(),
                CharacterCasing.Upper => text?.ToUpper(),
                CharacterCasing.Normal => text,
                _ => text
            };
        }**

        **public CharacterCasing CharacterCasing
        {
            get => GetValue(CharacterCasingProperty);
            set => SetValue(CharacterCasingProperty, value);
        }**

        /// <summary>
        /// Gets or sets the Text content of the TextBox
        /// </summary>
        **[Content]
        public string? Text
        {
            get => AdjustCasing(GetValue(TextProperty));
            set => SetValue(TextProperty, AdjustCasing (value));
        }**

        protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
        {
            base.OnPropertyChanged(change);

            if (change.Property == TextProperty)
            {
                CoerceValue(CaretIndexProperty);
                CoerceValue(SelectionStartProperty);
                CoerceValue(SelectionEndProperty);

                RaiseTextChangeEvents();

                UpdatePseudoclasses();
                UpdateCommandStates();
            }
            **else if (change.Property == CharacterCasingProperty)
            {
                Text = AdjustCasing(Text);
            }**
            else if (change.Property == CaretIndexProperty)
            {
                OnCaretIndexChanged(change);
            }
            else if (change.Property == SelectionStartProperty)
            {
                OnSelectionStartChanged(change);
            }
            else if (change.Property == SelectionEndProperty)
            {
                OnSelectionEndChanged(change);
            }
            else if (change.Property == MaxLinesProperty)
            {
                InvalidateMeasure();
            }
            else if (change.Property == UndoLimitProperty)
            {
                OnUndoLimitChanged(change.GetNewValue<int>());
            }
            else if (change.Property == IsUndoEnabledProperty && change.GetNewValue<bool>() == false)
            {
                // from docs at
                // https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.primitives.textboxbase.isundoenabled:
                // "Setting this property to false clears the undo stack.
                // Therefore, if you disable undo and then re-enable it, undo commands still do not work
                // because the undo stack was emptied when you disabled undo."
                _undoRedoHelper.Clear();
                _selectedTextChangesMadeSinceLastUndoSnapshot = 0;
                _hasDoneSnapshotOnce = false;
            }
        }

        private void HandleTextInput(string? input)
        {
            if (IsReadOnly)
            {
                return;
            }
        
            **input = AdjustCasing(RemoveInvalidCharacters(input));**

            if (string.IsNullOrEmpty(input))
            {
                return;
            }

            _selectedTextChangesMadeSinceLastUndoSnapshot++;
            SnapshotUndoRedo(ignoreChangeCount: false);

            var currentText = Text ?? string.Empty;
     
            var selectionLength = Math.Abs(SelectionStart - SelectionEnd);
            var newLength = input.Length + currentText.Length - selectionLength;

            if (MaxLength > 0 && newLength > MaxLength)
            {
                input = input.Remove(Math.Max(0, input.Length - (newLength - MaxLength)));
                newLength = MaxLength;
            }

            if (!string.IsNullOrEmpty(input))
            {
                var textBuilder = StringBuilderCache.Acquire(Math.Max(currentText.Length, newLength));
                textBuilder.Append(currentText);

                var caretIndex = CaretIndex;

                if (selectionLength != 0)
                {
                    var (start, _) = GetSelectionRange();

                    textBuilder.Remove(start, selectionLength);

                    caretIndex = start;
                }

                textBuilder.Insert(caretIndex, input);

                SetCurrentValue(TextProperty, StringBuilderCache.GetStringAndRelease(textBuilder));

                ClearSelection();

                if (IsUndoEnabled)
                {
                    _undoRedoHelper.DiscardRedo();
                }

                SetCurrentValue(CaretIndexProperty, caretIndex + input.Length);
            }
        }

TextBoxCs.txt

@cesarchefinho
Copy link
Author

Can someone make a PR using this code and submit it to avalonia?

I don't have knowledge of working with open source projects, if someone can help I will be glad.

Thank you

@timunie
Copy link
Contributor

timunie commented Jun 29, 2023

@cesarchefinho communtiy PR will be opened up again after v11 dropped. Then you are welcome to learn how to contribute ;-) You can also chat on telegram with us if you need assistence to get started

@cesarchefinho
Copy link
Author

@timunie can you comment about this proposal and code changes marked with ** ** ?

thanks

@timunie
Copy link
Contributor

timunie commented Jun 29, 2023

I'll leave commenting on the impl details to @Gillibald . He is strong in this area.

@Gillibald
Copy link
Contributor

The part that handles OnPropertyChanged should be left out because it changes the casing of existing text. CharacterCasing is only meant to adjust input. I would accept such a change for the next version of Avalonia.

@cesarchefinho
Copy link
Author

thanks a lot.

Avalonia is the only framework tht haven't CharacterCasing and it is impirtant to a lot of people.

@cesarchefinho
Copy link
Author

@Gillibald , now avalinia is released, pease use my code to imorove texbox.

In future i will make other contributions by Pull Request, but now i dont have the knolowge to make it.

Thank you very much

@timunie
Copy link
Contributor

timunie commented Jul 6, 2023

@cesarchefinho we can guide you through the process I think. So your PR would be appreciated. Join us on telegram for chat support helping you to provide your very first PR. You'd benefit from learning new things as well.

@FraserElectronics
Copy link

What is the status with this ?
Is there still no option to limit the case in a TextBox?

Andy

@Gillibald
Copy link
Contributor

Contributions by the community are welcome.

The only acceptable solution is to add needed character properties to our Unicode data.

https://www.unicode.org/versions/Unicode15.1.0/ch05.pdf
Section 5.18 Case Mappings
https://www.[unicode.org/Public/UNIDATA/CaseFolding.txt](https://www.unicode.org/Public/UNIDATA/CaseFolding.txt)

@Gillibald Gillibald added the help-wanted A contribution from the community would be most welcome. label Apr 23, 2024
@Authfix Authfix linked a pull request Sep 3, 2024 that will close this issue
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement help-wanted A contribution from the community would be most welcome.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants