// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Containers/Array.h" #include "CoreMinimal.h" #include "Framework/SlateDelegates.h" #include "Misc/Attribute.h" #include "NamingTokensEngineSubsystem.h" #include "Templates/SharedPointer.h" #include "Widgets/DeclarativeSyntaxSupport.h" #include "Widgets/Input/SMultiLineEditableTextBox.h" class ITextLayoutMarshaller; class FNamingTokensStringSyntaxHighlighterMarshaller; class FString; class FText; class SMenuAnchor; struct FNamingTokenDataTreeItem; /** * An editable text box for displaying tokenized strings in either their unevaluated or resolved form. */ class SNamingTokensEditableTextBox : public SCompoundWidget { public: SLATE_BEGIN_ARGS(SNamingTokensEditableTextBox) : _Style(nullptr) , _ArgumentStyle(nullptr) , _AllowMultiLine(false) , _IsReadOnly(false) , _CanDisplayResolvedText(true) , _DisplayTokenIcon(true) , _DisplayErrorMessage(true) , _DisplayBorderImage(true) , _EnableSuggestionDropdown(true) , _FullyQualifyGlobalTokenSuggestions(false) {} /** The styling of the textbox. */ SLATE_STYLE_ARGUMENT(FEditableTextBoxStyle, Style) /** The styling of our arguments. */ SLATE_STYLE_ARGUMENT(FTextBlockStyle, ArgumentStyle) /** The initial text that will appear in the widget. */ SLATE_ATTRIBUTE(FText, Text) /** The (optional) resolved text, displayed when the text box is not focused. If not provided, the templated text is shown. */ SLATE_ATTRIBUTE(FText, ResolvedText) /** The list of available arguments to use in this template string. If Empty, any argument name is valid. */ SLATE_ATTRIBUTE(TConstArrayView, ValidArguments) /** The marshaller used to get/set the raw text to/from the text layout. */ SLATE_ARGUMENT(TSharedPtr, Marshaller) /** Whether to allow multi-line text. */ SLATE_ATTRIBUTE(bool, AllowMultiLine) /** Sets whether this text box can actually be modified interactively by the user */ SLATE_ATTRIBUTE(bool, IsReadOnly) /** If we're allowed to display the resolved text. */ SLATE_ATTRIBUTE(bool, CanDisplayResolvedText) /** If we can display the default token icon. */ SLATE_ATTRIBUTE(bool, DisplayTokenIcon) /** If we display error messages. */ SLATE_ATTRIBUTE(bool, DisplayErrorMessage) /** If we should use the border image. */ SLATE_ATTRIBUTE(bool, DisplayBorderImage) /** Allows custom validation. */ SLATE_EVENT(FOnVerifyTextChanged, OnValidateTokenizedText) /** Called whenever the (tokenized) text is changed interactively by the user. */ SLATE_EVENT(FOnTextChanged, OnTextChanged) /** Called whenever the (tokenized) text is committed by the user. */ SLATE_EVENT(FOnTextCommitted, OnTextCommitted) /** Called prior to Naming Token evaluation. Only fires if this widget is handling evaluations. */ SLATE_EVENT(FSimpleDelegate, OnPreEvaluateNamingTokens) /** Filter args to apply during evaluation. */ SLATE_ARGUMENT(FNamingTokenFilterArgs, FilterArgs) /** Contexts to provide to evaluation. */ SLATE_ARGUMENT(TArray>, Contexts) /** If drop down suggestions should be enabled. */ SLATE_ARGUMENT(bool, EnableSuggestionDropdown) /** If the namespace should be inserted when selecting a global suggestion. */ SLATE_ARGUMENT(bool, FullyQualifyGlobalTokenSuggestions) SLATE_END_ARGS() /** Constructs this widget with InArgs */ NAMINGTOKENSUI_API void Construct(const FArguments& InArgs); /** Retrieve the editable text widget. */ TSharedPtr GetEditableText() const { return EditableText; } /** Set the current tokenized text. */ NAMINGTOKENSUI_API void SetTokenizedText(const FText& InText); /** Return the bound text attribute. */ const TAttribute& GetBoundText() const { return BoundText; } /** Retrieve the resolved text. */ NAMINGTOKENSUI_API const FText& GetResolvedText() const; /** Retrieve the raw tokenized text. */ NAMINGTOKENSUI_API const FText& GetTokenizedText() const; /** Sets the style to use. */ NAMINGTOKENSUI_API void SetNormalStyle(const FEditableTextBoxStyle* InNormalStyle); /** Sets the argument style to use. */ NAMINGTOKENSUI_API void SetArgumentStyle(const FTextBlockStyle* InArgumentStyle); /** If the suggestion box should be enabled. */ NAMINGTOKENSUI_API void SetEnableSuggestionDropdown(bool bInEnableSuggestionDropdown); /** Provide filter args to use during evaluation. */ NAMINGTOKENSUI_API void SetFilterArgs(const FNamingTokenFilterArgs& InFilterArgs); /** Provide contexts to naming token evaluation. */ NAMINGTOKENSUI_API void SetContexts(const TArray& InContexts); /** Evaluate the token text and update the resolved text. */ NAMINGTOKENSUI_API void EvaluateNamingTokens(); private: /** @return Text contents based on current state */ FText GetText() const; const FSlateBrush* GetBorderImage() const; /** The background color for the border. */ NAMINGTOKENSUI_API virtual FSlateColor GetBorderBackgroundColor() const; NAMINGTOKENSUI_API virtual FSlateColor GetForegroundColor() const override; void SetError(const FText& InError) const; NAMINGTOKENSUI_API virtual bool HasKeyboardFocus() const override; NAMINGTOKENSUI_API virtual FReply OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& InFocusEvent) override; NAMINGTOKENSUI_API virtual void OnFocusChanging(const FWeakWidgetPath& PreviousFocusPath, const FWidgetPath& NewWidgetPath, const FFocusEvent& InFocusEvent) override; NAMINGTOKENSUI_API virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override; bool ValidateTokenizedText(const FText& InTokenizedText); bool ValidateTokenBraces(const FText& InTokenizedText, FText& OutError); bool ValidateTokenArgs(const FText& InTokenizedText, FText& OutError); bool ParseArgs(const FString& InTokenizedTextString, TArray& OutArgs); void OnEditableTextChanged(const FText& InTokenizedText); void OnEditableTextCommitted(const FText& InTokenizedText, ETextCommit::Type InCommitType); /** Check for type text and update filters if needed. */ void UpdateFilters() const; struct FCursorTokenData { /** Start '{' location of token. */ FTextLocation StartLocation; /** End '}' location of token. */ FTextLocation EndLocation; /** Length of EndLocation-StartLocation offset. */ int32 Length; /** Word entered between brackets. */ FString EnteredWord; }; /** Opens or closes the dropdown based on cursor status. */ void OpenOrCloseSuggestionDropdown() const; /** Opens or closes the suggestion drop down on the next tick, providing a request hasn't already been made. */ void OpenOrCloseSuggestionDropdownNextTick() const; /** Trigger the suggestion process. */ void OpenSuggestionDropdown() const; /** Close the suggestion window. */ void CloseSuggestionDropdown() const; /** Retrieve information about the current token where the cursor is. */ TSharedPtr GetCurrentCursorTokenData() const; /** Create the dropdown content for filtering naming tokens. */ TSharedRef OnGetDropdownContent(); /** When our editable text has a character typed. */ FReply OnEditableTextKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& InCharacterEvent) const; /** When editable text has a key pressed. */ FReply OnEditableTextKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) const; /** User has moved the text cursor. */ void OnEditableTextCursorMoved(const FTextLocation& NewCursorPosition); /** When a dropdown suggestion has been selected. */ void OnSuggestionSelected(TSharedPtr SelectedItem) const; /** Called when the suggestion box has been double clicked. */ void OnSuggestionDoubleClicked(TSharedPtr SelectedItem); /** Called if the suggestion box has received focus. */ void OnSuggestionDropdownReceivedFocus() const; private: /** Filter args to use during evaluation. */ FNamingTokenFilterArgs NamingTokenFilterArgs; /** Contexts to provide to evaluation. */ TArray> NamingTokenContexts; /** Editable text widget. */ TSharedPtr EditableText; /** The dropdown filter UI anchor. */ TSharedPtr DropdownAnchor; /** The Dropdown widget. */ TSharedPtr FilterWidget; /** Cursor token data of the last token data. */ mutable TSharedPtr LastCursorTokenData; /** Style shared between Editable and NonEditable text widgets. */ const FEditableTextBoxStyle* TextBoxStyle = nullptr; /** The style to use for our argument formatting. */ const FTextBlockStyle* ArgumentStyle = nullptr; TSharedPtr Box; TSharedPtr HScrollBarBox; TSharedPtr HScrollBar; TSharedPtr VScrollBarBox; TSharedPtr VScrollBar; /** The marshaller we use. */ TSharedPtr Marshaller; TSharedPtr ErrorReporting; /** The bound text which could return either tokenized or resolved text. */ TAttribute BoundText; TAttribute TokenizedText; TAttribute ResolvedText; /** If we are displaying the token icon. */ TAttribute DisplayTokenIcon; /** If error messages are displayed. */ TAttribute DisplayErrorMessage; /** If the border image is used. */ TAttribute DisplayBorderImage; /** Attribute checking if we can display the resolved text. */ TAttribute CanDisplayResolvedText; TAttribute> ValidArguments; /** Callback to verify tokenized text when changed. Will return an error message to denote problems. */ FOnVerifyTextChanged OnValidateTokenizedText; /** Callback when tokenized text is changed. */ FOnTextChanged OnTokenizedTextChanged; /** Callback when tokenized text is committed. */ FOnTextCommitted OnTokenizedTextCommitted; /** Callback before we evaluate tokens. */ FSimpleDelegate OnPreEvaluateTokens; /** If this widget is handling all token evaluation. */ bool bHandlingEvaluation = false; /** If global tokens should have their namespace inserted too from suggestions. */ bool bFullyQualifyGlobalTokenSuggestions = false; /** If suggestions are enabled by default. */ bool bEnableSuggestionDropdown = true; /** Suggesting box in the process of opening or closing. */ mutable bool bModifyingSuggestionDropdown = false; };