// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "Misc/Attribute.h" #include "Layout/Geometry.h" #include "Input/Reply.h" #include "Widgets/SWidget.h" #include "Layout/Margin.h" #include "Styling/SlateTypes.h" #include "Framework/Application/IMenu.h" #include "Widgets/Input/IVirtualKeyboardEntry.h" #include "Widgets/Text/ISlateEditableTextWidget.h" #include "Framework/Text/ITextLayoutMarshaller.h" #include "Framework/Text/TextLineHighlight.h" #include "Framework/Text/IRun.h" #include "Framework/Text/TextLayout.h" #include "Widgets/Text/SlateEditableTextTypes.h" #include "Framework/Text/SlateTextLayoutFactory.h" #include "GenericPlatform/ITextInputMethodSystem.h" class FArrangedChildren; class FExtender; class FPaintArgs; class FSlateWindowElementList; class FSlateTextBlockLayout; class FUICommandList; class IBreakIterator; class ISlateEditableTextWidget; class SWindow; enum class ETextShapingMethod : uint8; /** Class to handle the cached layout of SEditableText/SMultiLineEditableText by proxying around a FTextLayout */ class FSlateEditableTextLayout { public: SLATE_API FSlateEditableTextLayout(ISlateEditableTextWidget& InOwnerWidget, const TAttribute& InInitialText, FTextBlockStyle InTextStyle, const TOptional InTextShapingMethod, const TOptional InTextFlowDirection, const FCreateSlateTextLayout& InCreateSlateTextLayout, TSharedRef InTextMarshaller, TSharedRef InHintTextMarshaller); SLATE_API ~FSlateEditableTextLayout(); SLATE_API void SetText(const TAttribute& InText); SLATE_API FText GetText() const; SLATE_API void SetHintText(const TAttribute& InHintText); SLATE_API FText GetHintText() const; SLATE_API void SetSearchText(const TAttribute& InSearchText); SLATE_API FText GetSearchText() const; /** Get the index of the search result (0 if none) */ SLATE_API int32 GetSearchResultIndex() const; /** Get the total number of search results (0 if none) */ SLATE_API int32 GetNumSearchResults() const; SLATE_API void SetTextStyle(const FTextBlockStyle& InTextStyle); SLATE_API const FTextBlockStyle& GetTextStyle() const; /** Get the number of Text Lines */ SLATE_API int32 GetTextLineCount(); /** Set the brush to use when drawing the cursor */ SLATE_API void SetCursorBrush(const TAttribute& InCursorBrush); /** Set the brush to use when drawing the composition highlight */ SLATE_API void SetCompositionBrush(const TAttribute& InCompositionBrush); /** Get the plain text string without rich-text formatting */ SLATE_API FText GetPlainText() const; /** * Sets the current editable text for this text block * Note: Doesn't update the value of BoundText, nor does it call OnTextChanged * * @param TextToSet The new text to set in the internal TextLayout * @param bForce True to force the update, even if the text currently matches what's in the TextLayout * * @return true if the text was updated, false if the text wasn't update (because it was already up-to-date) */ SLATE_API bool SetEditableText(const FText& TextToSet, const bool bForce = false); /** * Gets the current editable text for this text block * Note: We don't store text in this form (it's stored as lines in the text layout) so every call to this function has to reconstruct it */ SLATE_API FText GetEditableText() const; /** Get the currently selected text */ SLATE_API FText GetSelectedText() const; /** Get the current selection*/ SLATE_API FTextSelection GetSelection() const; /** Set the text shaping method that the internal text layout should use */ SLATE_API void SetTextShapingMethod(const TOptional& InTextShapingMethod); /** Set the text flow direction that the internal text layout should use */ SLATE_API void SetTextFlowDirection(const TOptional& InTextFlowDirection); /** Set the wrapping to use for this document */ SLATE_API void SetTextWrapping(const TAttribute& InWrapTextAt, const TAttribute& InAutoWrapText, const TAttribute& InWrappingPolicy); /** Set whether text wraps onto a new line when it's length exceeds this width; if this value is zero or negative, no wrapping occurs */ SLATE_API void SetWrapTextAt(const TAttribute& InWrapTextAt); /** Set whether to wrap text automatically based on the widget's computed horizontal space */ SLATE_API void SetAutoWrapText(const TAttribute& InAutoWrapText); /** Set the wrapping policy to use */ SLATE_API void SetWrappingPolicy(const TAttribute& InWrappingPolicy); /** Set the amount of blank space left around the edges of text area */ SLATE_API void SetMargin(const TAttribute& InMargin); /** Set how the text should be aligned with the margin */ SLATE_API void SetJustification(const TAttribute& InJustification); /** Set the amount to scale each lines height by */ SLATE_API void SetLineHeightPercentage(const TAttribute& InLineHeightPercentage); /** Set whether to leave extra space below the last line due to line height */ SLATE_API void SetApplyLineHeightToBottomLine(const TAttribute& InApplyLineHeightToBottomLine); /** Set the text overflow policy that should be used to determine what happens to clipped text */ SLATE_API void SetOverflowPolicy(TOptional InOverflowPolicy); /** Set the information used to help identify who owns this text layout in the case of an error */ SLATE_API void SetDebugSourceInfo(const TAttribute& InDebugSourceInfo); /** Get the virtual keyboard handler for this text layout */ SLATE_API TSharedRef GetVirtualKeyboardEntry() const; /** Get the IME context for this text layout */ SLATE_API TSharedRef GetTextInputMethodContext() const; /** Register and activate the IME context for this text layout */ SLATE_API void EnableTextInputMethodContext(); /** Refresh this editable text immediately, rather than wait for the usual caching mechanisms to take affect on the text Tick */ SLATE_API bool Refresh(); /** Force the text layout to be updated from the marshaller */ SLATE_API void ForceRefreshTextLayout(const FText& CurrentText); /** Begin a new text search (this is called automatically when BoundSearchText changes) */ SLATE_API void BeginSearch(const FText& InSearchText, const ESearchCase::Type InSearchCase = ESearchCase::IgnoreCase, const bool InReverse = false); /** Advance the current search to the next match (does nothing if not currently searching) */ SLATE_API void AdvanceSearch(const bool InReverse = false); /** Update the horizontal scroll amount from the given fraction */ SLATE_API UE::Slate::FDeprecateVector2DResult SetHorizontalScrollFraction(const float InScrollOffsetFraction); /** Update the vertical scroll amount from the given fraction */ SLATE_API UE::Slate::FDeprecateVector2DResult SetVerticalScrollFraction(const float InScrollOffsetFraction); /** Set the absolute scroll offset value */ SLATE_API UE::Slate::FDeprecateVector2DResult SetScrollOffset(const UE::Slate::FDeprecateVector2DParameter& InScrollOffset, const FGeometry& InGeometry); /** Get the absolute scroll offset value */ SLATE_API UE::Slate::FDeprecateVector2DResult GetScrollOffset() const; /** Returns the computed wrap location for this layout */ SLATE_API float GetComputedWrappingWidth() const; /** Returns whether or not we are auto wrapping text */ SLATE_API bool GetAutoWrapText() const; /** Called when our parent widget receives focus */ SLATE_API bool HandleFocusReceived(const FFocusEvent& InFocusEvent); /** Called when our parent widget loses focus */ SLATE_API bool HandleFocusLost(const FFocusEvent& InFocusEvent); /** Called to handle an OnKeyChar event from our parent widget */ SLATE_API FReply HandleKeyChar(const FCharacterEvent& InCharacterEvent); /** Called to handle an OnKeyDown event from our parent widget */ SLATE_API FReply HandleKeyDown(const FKeyEvent& InKeyEvent); /** Called to handle an OnKeyUp event from our parent widget */ SLATE_API FReply HandleKeyUp(const FKeyEvent& InKeyEvent); /** Called to handle an OnMouseButtonDown event from our parent widget */ SLATE_API FReply HandleMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& InMouseEvent); /** Called to handle an OnMouseButtonUp event from our parent widget */ SLATE_API FReply HandleMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& InMouseEvent); /** Called to handle an OnMouseMove event from our parent widget */ SLATE_API FReply HandleMouseMove(const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent); /** Called to handle an OnMouseButtonDoubleClick event from our parent widget */ SLATE_API FReply HandleMouseButtonDoubleClick(const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent); /** Called to handle an escape action acting on the current selection */ SLATE_API bool HandleEscape(); /** Called to handle a backspace action acting on the current selection or at the cursor position */ SLATE_API bool HandleBackspace(); /** Called to handle a delete action acting on the current selection or at the cursor position */ SLATE_API bool HandleDelete(); /** Called to handle a typing a character on the current selection or at the cursor position */ SLATE_API bool HandleTypeChar(const TCHAR InChar); /** Called to handle a carriage return action acting on the current selection or at the cursor position */ SLATE_API bool HandleCarriageReturn(bool isRepeat); /** Are we able to delete the currently selected text? */ SLATE_API bool CanExecuteDelete() const; /** Delete any currently selected text */ SLATE_API void DeleteSelectedText(); /** Query to see if any text is selected within the document */ SLATE_API bool AnyTextSelected() const; /** Query to see if the text under the given position is currently selected */ SLATE_API bool IsTextSelectedAt(const FGeometry& MyGeometry, const UE::Slate::FDeprecateVector2DParameter& ScreenSpacePosition) const; /** Query to see if the text under the given position is currently selected (the position is local to the text layout space) */ SLATE_API bool IsTextSelectedAt(const UE::Slate::FDeprecateVector2DParameter& InLocalPosition) const; /** Are we able to execute the "Select All" command? */ SLATE_API bool CanExecuteSelectAll() const; /** Select all the text in the document */ SLATE_API void SelectAllText(); /** Select the word under the given position */ SLATE_API void SelectWordAt(const FGeometry& MyGeometry, const UE::Slate::FDeprecateVector2DParameter& ScreenSpacePosition); /** Select the word under the given position (the position is local to the text layout space) */ SLATE_API void SelectWordAt(const UE::Slate::FDeprecateVector2DParameter& InLocalPosition); /** Select a block of text */ SLATE_API void SelectText(const FTextLocation& InSelectionStart, const FTextLocation& InCursorLocation); /** Clear the active text selection */ SLATE_API void ClearSelection(); /** Are we able to cut the currently selected text? */ SLATE_API bool CanExecuteCut() const; /** Cut the currently selected text and place it on the clipboard */ SLATE_API void CutSelectedTextToClipboard(); /** Are we able to copy the currently selected text? */ SLATE_API bool CanExecuteCopy() const; /** Copy the currently selected text and place it on the clipboard */ SLATE_API void CopySelectedTextToClipboard(); /** Are we able to paste the text from the clipboard into this document? */ SLATE_API bool CanExecutePaste() const; /** Paste the text from the clipboard into this document */ SLATE_API void PasteTextFromClipboard(); /** Insert the given text at the current cursor position, correctly taking into account new line characters */ SLATE_API void InsertTextAtCursor(const FString& InString); /** Insert the given run at the current cursor position */ SLATE_API void InsertRunAtCursor(TSharedRef InRun); /** Move the cursor in the document using the specified move method */ SLATE_API bool MoveCursor(const FMoveCursor& InArgs); /** Move the cursor to the given location in the document (will also scroll to this point) */ SLATE_API void GoTo(const FTextLocation& NewLocation); /** Move the cursor specified location */ SLATE_API void GoTo(const ETextLocation NewLocation); /** Jump the cursor to the given location in the document */ SLATE_API void JumpTo(ETextLocation JumpLocation, ECursorAction Action); /** Scroll to the given location in the document (without moving the cursor) */ SLATE_API void ScrollTo(const FTextLocation& NewLocation); /** Scroll to the given location in the document (without moving the cursor) */ SLATE_API void ScrollTo(const ETextLocation NewLocation); /** Update the active cursor highlight based on the state of the text layout */ SLATE_API void UpdateCursorHighlight(); /** Remove any active cursor highlights */ SLATE_API void RemoveCursorHighlight(); /** Update the preferred offset of the cursor, based on the current state of the text layout */ SLATE_API void UpdatePreferredCursorScreenOffsetInLine(); /** Apply the given style to the currently selected text (or insert a new run at the current cursor position if no text is selected) */ SLATE_API void ApplyToSelection(const FRunInfo& InRunInfo, const FTextBlockStyle& InStyle); /** Get the run currently under the cursor, or null if there is no run currently under the cursor */ SLATE_API TSharedPtr GetRunUnderCursor() const; /** Get the runs currently that are current selected, some of which may be only partially selected */ SLATE_API TArray> GetSelectedRuns() const; /** Get the interaction position of the cursor (where to insert, delete, etc, text from/to) */ SLATE_API FTextLocation GetCursorLocation() const; /** * Given a location and a Direction to offset, return a new location. * * @param Location Cursor location from which to offset * @param Direction Positive means right, negative means left. */ SLATE_API FTextLocation TranslatedLocation(const FTextLocation& CurrentLocation, int8 Direction) const; /** * Given a location and a Direction to offset, return a new location. * * @param Location Cursor location from which to offset * @param NumLinesToMove Number of lines to move in a given direction. Positive means down, negative means up. * @param GeometryScale Geometry DPI scale at which the widget is being rendered * @param OutCursorPosition Fill with the updated cursor position. * @param OutCursorAlignment Optionally fill with a new cursor alignment (will be auto-calculated if not set). */ SLATE_API void TranslateLocationVertical(const FTextLocation& Location, int32 NumLinesToMove, float GeometryScale, FTextLocation& OutCursorPosition, TOptional& OutCursorAlignment) const; /** Find the closest word boundary */ SLATE_API FTextLocation ScanForWordBoundary(const FTextLocation& Location, int8 Direction) const; /** Get the character at Location */ SLATE_API TCHAR GetCharacterAt(const FTextLocation& Location) const; /** Are we at the beginning of all the text. */ SLATE_API bool IsAtBeginningOfDocument(const FTextLocation& Location) const; /** Are we at the end of all the text. */ SLATE_API bool IsAtEndOfDocument(const FTextLocation& Location) const; /** Is this location the beginning of a line */ SLATE_API bool IsAtBeginningOfLine(const FTextLocation& Location) const; /** Is this location the end of a line. */ SLATE_API bool IsAtEndOfLine(const FTextLocation& Location) const; /** Are we currently at the beginning of a word */ SLATE_API bool IsAtWordStart(const FTextLocation& Location) const; /** Restores the text to the original state */ SLATE_API void RestoreOriginalText(); /** Returns whether the current text varies from the original */ SLATE_API bool HasTextChangedFromOriginal() const; /** Called to begin an undoable editable text transaction */ SLATE_API void BeginEditTransation(); /** Called to end an undoable editable text transaction */ SLATE_API void EndEditTransaction(); /** Push the given undo state onto the undo stack */ SLATE_API void PushUndoState(const SlateEditableTextTypes::FUndoState& InUndoState); /** Clear the current undo stack */ SLATE_API void ClearUndoStates(); /** Create an undo state that reflects the current state of the document */ SLATE_API void MakeUndoState(SlateEditableTextTypes::FUndoState& OutUndoState); /** Are we currently able to execute an undo action? */ SLATE_API bool CanExecuteUndo() const; /** Execute an undo action */ SLATE_API void Undo(); /** Are we currently able to execute a redo action? */ SLATE_API bool CanExecuteRedo() const; /** Execute a redo action */ SLATE_API void Redo(); SLATE_API void SaveText(const FText& TextToSave); SLATE_API void LoadText(); SLATE_API bool ComputeVolatility() const; SLATE_API void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime); SLATE_API int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled); SLATE_API void CacheDesiredSize(float LayoutScaleMultiplier); SLATE_API FVector2D ComputeDesiredSize(float LayoutScaleMultiplier) const; SLATE_API FChildren* GetChildren(); SLATE_API void OnArrangeChildren(const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren) const; SLATE_API UE::Slate::FDeprecateVector2DResult GetSize() const; SLATE_API TSharedRef BuildDefaultContextMenu(const TSharedPtr& InMenuExtender) const; SLATE_API bool HasActiveContextMenu() const; /** * Fill OutTextLine with the text line where the current cursor location is at * * @param OutTextLine FString of the line */ SLATE_API void GetCurrentTextLine(FString& OutTextLine) const; /** * Fill OutTextLine with the text line at the specified index * * @param InLineIndex Index of the line * @param OutTextLine FString of the line */ SLATE_API void GetTextLine(const int32 InLineIndex, FString& OutTextLine) const; private: /** Insert the given text at the current cursor position, correctly taking into account new line characters */ SLATE_API void InsertTextAtCursorImpl(const FString& InString); /** Insert a new-line at the current cursor position */ SLATE_API void InsertNewLineAtCursorImpl(); /** Implementation of Refresh that actually updates the layout. Optionally takes text to set, or will use the current editable text if none if provided */ SLATE_API bool RefreshImpl(const FText* InTextToSet, const bool bForce = false); /** Create a text or password run using the given text and style */ SLATE_API TSharedRef CreateTextOrPasswordRun(const FRunInfo& InRunInfo, const TSharedRef& InText, const FTextBlockStyle& InStyle); /** Called when the active context menu is closed */ SLATE_API void OnContextMenuClosed(TSharedRef Menu); void UpdateTextChangedByVirtualKeyboard(); private: /** Virtual keyboard handler for an editable text layout */ friend class FVirtualKeyboardEntry; class FVirtualKeyboardEntry : public IVirtualKeyboardEntry { public: static TSharedRef Create(FSlateEditableTextLayout& InOwnerLayout); virtual void SetTextFromVirtualKeyboard(const FText& InNewText, ETextEntryType TextEntryType) override; virtual void SetSelectionFromVirtualKeyboard(int InSelStart, int InSelEnd) override; virtual bool GetSelection(int& OutSelStart, int& OutSelEnd) override; virtual FText GetText() const override; virtual FText GetHintText() const override; virtual EKeyboardType GetVirtualKeyboardType() const override; virtual FVirtualKeyboardOptions GetVirtualKeyboardOptions() const override; virtual bool IsMultilineEntry() const override; virtual bool IsIntegratedKeyboardEnabled() const override; private: FVirtualKeyboardEntry(FSlateEditableTextLayout& InOwnerLayout); FSlateEditableTextLayout* OwnerLayout; }; private: /** * Note: The IME interface for the multiline editable text uses the pre-flowed version of the string since the IME APIs are designed to work with flat strings * This means we have to do a bit of juggling to convert between the two */ friend class FTextInputMethodContext; class FTextInputMethodContext : public ITextInputMethodContext { public: static TSharedRef Create(FSlateEditableTextLayout& InOwnerLayout); void CacheWindow(); FORCEINLINE void KillContext() { OwnerLayout = nullptr; bIsComposing = false; } FORCEINLINE FTextRange GetCompositionRange() const { return FTextRange(CompositionBeginIndex, CompositionBeginIndex + CompositionLength); } bool UpdateCachedGeometry(const FGeometry& InAllottedGeometry) { if (CachedGeometry != InAllottedGeometry) { CachedGeometry = InAllottedGeometry; return true; } return false; } virtual bool IsComposing() override; virtual bool IsReadOnly() override; virtual uint32 GetTextLength() override; virtual void GetSelectionRange(uint32& BeginIndex, uint32& Length, ECaretPosition& CaretPosition) override; virtual void SetSelectionRange(const uint32 BeginIndex, const uint32 Length, const ECaretPosition CaretPosition) override; virtual void GetTextInRange(const uint32 BeginIndex, const uint32 Length, FString& OutString) override; virtual void SetTextInRange(const uint32 BeginIndex, const uint32 Length, const FString& InString) override; virtual int32 GetCharacterIndexFromPoint(const FVector2D& Point) override; virtual bool GetTextBounds(const uint32 BeginIndex, const uint32 Length, FVector2D& Position, FVector2D& Size) override; virtual void GetScreenBounds(FVector2D& Position, FVector2D& Size) override; virtual TSharedPtr GetWindow() override; virtual void BeginComposition() override; virtual void UpdateCompositionRange(const int32 InBeginIndex, const uint32 InLength) override; virtual void EndComposition() override; private: FTextInputMethodContext(FSlateEditableTextLayout& InOwnerLayout); FSlateEditableTextLayout* OwnerLayout; TWeakPtr CachedParentWindow; FGeometry CachedGeometry; bool bIsComposing; int32 CompositionBeginIndex; uint32 CompositionLength; }; private: /** Pointer to the interface for our owner widget */ ISlateEditableTextWidget* OwnerWidget; /** The iterator to use to detect grapheme cluster boundaries */ TSharedPtr GraphemeBreakIterator; /** The marshaller used to get/set the BoundText text to/from the text layout. */ TSharedPtr Marshaller; /** The marshaller used to get/set the HintText text to/from the text layout. */ TSharedPtr HintMarshaller; /** Delegate used to create internal text layouts. */ FCreateSlateTextLayout CreateSlateTextLayout; /** In control of the layout and wrapping of the BoundText */ TSharedPtr TextLayout; /** In control of the layout and wrapping of the HintText */ TUniquePtr HintTextLayout; /** Default style used by the TextLayout */ FTextBlockStyle TextStyle; /** Style used to draw the hint text (only valid when HintTextLayout is set) */ FTextBlockStyle HintTextStyle; /** The text displayed in this text block */ TAttribute BoundText; /** The state of BoundText last Tick() (used to allow updates when the text is changed) */ FTextSnapshot BoundTextLastTick; /** Was the editable text showing a password last Tick() (allows a forcible text layout update when changing state) */ bool bWasPasswordLastTick; /** The text that appears when there is no text in the text box */ TAttribute HintText; /** The text to be searched for */ TAttribute BoundSearchText; /** The state of BoundSearchText last Tick() (used to allow updates when the text is changed) */ FTextSnapshot BoundSearchTextLastTick; /** The active search text (set from BeginSearch) */ FText SearchText; /** The case-sensitivity of the active search (set from BeginSearch) */ ESearchCase::Type SearchCase; /** The map to look up the index of each search result (key is the starting location of each matched string)*/ TMap SearchResultToIndexMap; /** The active search result index */ int32 CurrentSearchResultIndex; /** Whether text wraps onto a new line when it's length exceeds this width; if this value is zero or negative, no wrapping occurs. */ TAttribute WrapTextAt; /** True if we're wrapping text automatically based on the computed horizontal space for this widget */ TAttribute AutoWrapText; /** The wrapping policy we're using */ TAttribute WrappingPolicy; /** The amount of blank space left around the edges of text area */ TAttribute Margin; /** How the text should be aligned with the margin */ TAttribute Justification; /** The amount to scale each lines height by */ TAttribute LineHeightPercentage; /** Whether to leave extra space below the last line due to line height */ TAttribute ApplyLineHeightToBottomLine; /** The information used to help identify who owns this text layout in the case of an error */ TAttribute DebugSourceInfo; /** Virtual keyboard handler for this text layout */ TSharedPtr VirtualKeyboardEntry; /** True if the IME context for this text layout has been registered with the input method manager */ bool bHasRegisteredTextInputMethodContext; /** IME context for this text layout */ TSharedPtr TextInputMethodContext; /** Notification interface object for IMEs */ TSharedPtr TextInputMethodChangeNotifier; /** Layout highlighter used to draw the cursor */ TSharedPtr CursorLineHighlighter; /** Layout highlighter used to draw an active text composition */ TSharedPtr TextCompositionHighlighter; /** Layout highlighter used to draw the active text selection */ TSharedPtr TextSelectionHighlighter; /** Layout highlighter used to draw the active search selection */ TSharedPtr SearchSelectionHighlighter; /** Line highlights that have been added from this editable text layout (used for cleanup without removing) */ TArray ActiveLineHighlights; /** The scroll offset (in unscaled Slate units) for this text */ FVector2f ScrollOffset; /** If set, the pending data containing a position that should be scrolled into view */ TOptional PositionToScrollIntoView; /** That start of the selection when there is a selection. The end is implicitly wherever the cursor happens to be. */ TOptional SelectionStart; /** The user probably wants the cursor where they last explicitly positioned it horizontally. */ float PreferredCursorScreenOffsetInLine; /** Current cursor data */ SlateEditableTextTypes::FCursorInfo CursorInfo; /** Undo states */ TArray UndoStates; /** Current undo state level that we've rolled back to, or INDEX_NONE if we haven't undone. Used for 'Redo'. */ int32 CurrentUndoLevel; /** Undo state that will be pushed if text is actually changed between calls to BeginEditTransation() and EndEditTransaction() */ TOptional StateBeforeChangingText; /** Track the number transactions that are opened */ int32 NumTransactionsOpened; /** Original text undo state */ SlateEditableTextTypes::FUndoState OriginalText; /** True if we're currently selecting text by dragging the mouse cursor with the left button held down */ bool bIsDragSelecting; /** True if the last mouse down caused us to receive keyboard focus */ bool bWasFocusedByLastMouseDown; /** True if characters were selected by dragging since the last keyboard focus. Used for text selection. */ bool bHasDragSelectedSinceFocused; /** Whether the text has been changed by a virtual keyboard */ bool bTextChangedByVirtualKeyboard; /** Whether the text has been committed by a virtual keyboard */ bool bTextCommittedByVirtualKeyboard; /** What text was submitted by a virtual keyboard */ FText VirtualKeyboardText; /** How the text was committed by the virtual keyboard */ ETextCommit::Type VirtualKeyboardTextCommitType; /** Override for the overflow policy. If this is not set the text style setting is used */ TOptional OverflowPolicyOverride; /** The last known size of the widget from the previous OnPaint, used to recalculate wrapping */ FVector2f CachedSize; /** A list commands to execute if a user presses the corresponding key-binding in the text box */ TSharedPtr UICommandList; /** Information about any active context menu widgets */ FActiveTextEditContextMenu ActiveContextMenu; /** Whether the cursor position has been changed externally*/ bool bSelectionChangedExternally; /** The boundaries of the external selection */ int ExternalSelectionStart; int ExternalSelectionEnd; };