2025-08-02 20:10:33 +03:00
# include "TextBoxEditTool.hpp"
# include "DrawingProgram.hpp"
# include "../MainProgram.hpp"
# include "../DrawData.hpp"
2025-11-08 20:50:23 +03:00
# include "Helpers/ConvertVec.hpp"
2025-08-02 20:10:33 +03:00
# include "Helpers/SCollision.hpp"
# include <cereal/types/vector.hpp>
2025-11-04 17:31:23 +03:00
# include <include/core/SkFontStyle.h>
2025-11-08 20:50:23 +03:00
# include <modules/skparagraph/include/DartTypes.h>
# include <modules/skparagraph/include/ParagraphStyle.h>
2025-11-09 16:24:40 +03:00
# include <modules/skparagraph/include/TextStyle.h>
2025-11-08 20:50:23 +03:00
# include <modules/skparagraph/src/ParagraphBuilderImpl.h>
# include <modules/skunicode/include/SkUnicode_icu.h>
2025-08-02 20:10:33 +03:00
# include <memory>
# include "EditTool.hpp"
2025-11-10 14:45:51 +03:00
using namespace RichText ;
2025-08-02 20:10:33 +03:00
TextBoxEditTool : : TextBoxEditTool ( DrawingProgram & initDrawP ) :
DrawingProgramEditToolBase ( initDrawP )
{ }
2025-12-15 15:36:42 +03:00
bool TextBoxEditTool : : edit_gui ( const CanvasComponentContainer : : ObjInfoSharedPtr & comp ) {
auto & a = static_cast < TextBoxCanvasComponent & > ( comp - > obj - > get_comp ( ) ) ;
2025-08-02 20:10:33 +03:00
Toolbar & t = drawP . world . main . toolbar ;
2025-11-05 12:29:31 +03:00
2025-08-02 20:10:33 +03:00
t . gui . push_id ( " edit tool text " ) ;
t . gui . text_label_centered ( " Edit Text " ) ;
2025-11-08 20:50:23 +03:00
t . gui . left_to_right_line_layout ( [ & ] ( ) {
t . gui . text_label ( " Font " ) ;
2025-11-09 16:24:40 +03:00
if ( t . gui . font_picker ( " font picker " , & newFontName ) ) {
currentMods [ TextStyleModifier : : ModifierType : : FONT_FAMILIES ] = std : : make_shared < FontFamiliesTextStyleModifier > ( std : : vector < SkString > { SkString { newFontName . c_str ( ) , newFontName . size ( ) } } ) ;
2025-12-15 15:36:42 +03:00
add_undo_if_selecting_area ( a , [ & ] ( ) { a . textBox - > set_text_style_modifier_between ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos , currentMods [ TextStyleModifier : : ModifierType : : FONT_FAMILIES ] ) ; } ) ;
2025-11-09 16:24:40 +03:00
}
2025-11-08 20:50:23 +03:00
} ) ;
2025-11-05 12:29:31 +03:00
2025-11-05 18:21:49 +03:00
t . gui . left_to_right_line_centered_layout ( [ & ] ( ) {
2025-11-09 16:24:40 +03:00
if ( t . gui . svg_icon_button ( " Bold button " , " data/icons/RemixIcon/bold.svg " , newIsBold ) ) {
newIsBold = ! newIsBold ;
currentMods [ TextStyleModifier : : ModifierType : : WEIGHT ] = std : : make_shared < WeightTextStyleModifier > ( newIsBold ? SkFontStyle : : Weight : : kBold_Weight : SkFontStyle : : Weight : : kNormal_Weight ) ;
2025-12-15 15:36:42 +03:00
add_undo_if_selecting_area ( a , [ & ] ( ) { a . textBox - > set_text_style_modifier_between ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos , currentMods [ TextStyleModifier : : ModifierType : : WEIGHT ] ) ; } ) ;
2025-11-09 16:24:40 +03:00
}
if ( t . gui . svg_icon_button ( " Italic button " , " data/icons/RemixIcon/italic.svg " , newIsItalic ) ) {
newIsItalic = ! newIsItalic ;
currentMods [ TextStyleModifier : : ModifierType : : SLANT ] = std : : make_shared < SlantTextStyleModifier > ( newIsItalic ? SkFontStyle : : Slant : : kItalic_Slant : SkFontStyle : : Slant : : kUpright_Slant ) ;
2025-12-15 15:36:42 +03:00
add_undo_if_selecting_area ( a , [ & ] ( ) { a . textBox - > set_text_style_modifier_between ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos , currentMods [ TextStyleModifier : : ModifierType : : SLANT ] ) ; } ) ;
2025-11-09 16:24:40 +03:00
}
bool decorationEdited = false ;
if ( t . gui . svg_icon_button ( " Underline button " , " data/icons/RemixIcon/underline.svg " , newIsUnderlined ) ) {
newIsUnderlined = ! newIsUnderlined ;
decorationEdited = true ;
}
if ( t . gui . svg_icon_button ( " Strikethrough button " , " data/icons/RemixIcon/strikethrough.svg " , newIsLinethrough ) ) {
newIsLinethrough = ! newIsLinethrough ;
decorationEdited = true ;
}
if ( t . gui . svg_icon_button ( " Overline button " , " data/icons/RemixIcon/overline.svg " , newIsOverline ) ) {
newIsOverline = ! newIsOverline ;
decorationEdited = true ;
}
if ( decorationEdited ) {
currentMods [ TextStyleModifier : : ModifierType : : DECORATION ] = std : : make_shared < DecorationTextStyleModifier > ( get_new_decoration_value ( ) ) ;
2025-12-15 15:36:42 +03:00
add_undo_if_selecting_area ( a , [ & ] ( ) { a . textBox - > set_text_style_modifier_between ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos , currentMods [ TextStyleModifier : : ModifierType : : DECORATION ] ) ; } ) ;
2025-11-09 16:24:40 +03:00
}
2025-11-05 18:21:49 +03:00
} ) ;
2025-11-10 16:49:02 +03:00
t . gui . left_to_right_line_centered_layout ( [ & ] ( ) {
if ( t . gui . svg_icon_button ( " Align left button " , " data/icons/RemixIcon/align-left.svg " , currentPStyle . textAlignment = = skia : : textlayout : : TextAlign : : kLeft ) )
2025-12-15 15:36:42 +03:00
add_undo ( [ & ] ( ) { a . textBox - > set_text_alignment_between ( a . cursor - > selectionBeginPos . fParagraphIndex , a . cursor - > selectionEndPos . fParagraphIndex , skia : : textlayout : : TextAlign : : kLeft ) ; } ) ;
2025-11-10 16:49:02 +03:00
if ( t . gui . svg_icon_button ( " Align center button " , " data/icons/RemixIcon/align-center.svg " , currentPStyle . textAlignment = = skia : : textlayout : : TextAlign : : kCenter ) )
2025-12-15 15:36:42 +03:00
add_undo ( [ & ] ( ) { a . textBox - > set_text_alignment_between ( a . cursor - > selectionBeginPos . fParagraphIndex , a . cursor - > selectionEndPos . fParagraphIndex , skia : : textlayout : : TextAlign : : kCenter ) ; } ) ;
2025-11-10 16:49:02 +03:00
if ( t . gui . svg_icon_button ( " Align right button " , " data/icons/RemixIcon/align-right.svg " , currentPStyle . textAlignment = = skia : : textlayout : : TextAlign : : kRight ) )
2025-12-15 15:36:42 +03:00
add_undo ( [ & ] ( ) { a . textBox - > set_text_alignment_between ( a . cursor - > selectionBeginPos . fParagraphIndex , a . cursor - > selectionEndPos . fParagraphIndex , skia : : textlayout : : TextAlign : : kRight ) ; } ) ;
2025-11-10 16:49:02 +03:00
if ( t . gui . svg_icon_button ( " Align justify button " , " data/icons/RemixIcon/align-justify.svg " , currentPStyle . textAlignment = = skia : : textlayout : : TextAlign : : kJustify ) )
2025-12-15 15:36:42 +03:00
add_undo ( [ & ] ( ) { a . textBox - > set_text_alignment_between ( a . cursor - > selectionBeginPos . fParagraphIndex , a . cursor - > selectionEndPos . fParagraphIndex , skia : : textlayout : : TextAlign : : kJustify ) ; } ) ;
2025-11-10 16:49:02 +03:00
if ( t . gui . svg_icon_button ( " Text direction left " , " data/icons/RemixIcon/text-direction-l.svg " , currentPStyle . textDirection = = skia : : textlayout : : TextDirection : : kLtr ) )
2025-12-15 15:36:42 +03:00
add_undo ( [ & ] ( ) { a . textBox - > set_text_direction_between ( a . cursor - > selectionBeginPos . fParagraphIndex , a . cursor - > selectionEndPos . fParagraphIndex , skia : : textlayout : : TextDirection : : kLtr ) ; } ) ;
2025-11-10 16:49:02 +03:00
if ( t . gui . svg_icon_button ( " Text direction right " , " data/icons/RemixIcon/text-direction-r.svg " , currentPStyle . textDirection = = skia : : textlayout : : TextDirection : : kRtl ) )
2025-12-15 15:36:42 +03:00
add_undo ( [ & ] ( ) { a . textBox - > set_text_direction_between ( a . cursor - > selectionBeginPos . fParagraphIndex , a . cursor - > selectionEndPos . fParagraphIndex , skia : : textlayout : : TextDirection : : kRtl ) ; } ) ;
2025-11-10 16:49:02 +03:00
} ) ;
2025-11-09 16:24:40 +03:00
if ( t . gui . slider_scalar_field < uint32_t > ( " Font Size Slider " , " Font Size " , & newFontSize , 3 , 100 ) ) {
2025-11-12 14:54:46 +03:00
hold_undo_data ( " Font Size " , a ) ;
2025-11-09 16:24:40 +03:00
currentMods [ TextStyleModifier : : ModifierType : : SIZE ] = std : : make_shared < SizeTextStyleModifier > ( newFontSize ) ;
2025-12-15 15:36:42 +03:00
a . textBox - > set_text_style_modifier_between ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos , currentMods [ TextStyleModifier : : ModifierType : : SIZE ] ) ;
2025-11-09 16:24:40 +03:00
}
2025-11-12 14:54:46 +03:00
else
release_undo_data ( " Font Size " ) ;
2025-11-09 15:01:57 +03:00
2025-11-24 17:45:21 +03:00
// Text color
2025-11-05 18:21:49 +03:00
t . gui . left_to_right_line_layout ( [ & ] ( ) {
2025-11-24 18:23:53 +03:00
if ( t . gui . color_button_big ( " Text Color " , & newTextColor , & newTextColor = = t . colorRight ) )
t . color_selector_right ( & newTextColor = = t . colorRight ? nullptr : & newTextColor ) ;
2025-11-05 18:21:49 +03:00
t . gui . text_label ( " Text Color " ) ;
} ) ;
2025-11-12 14:54:46 +03:00
if ( & newTextColor = = t . colorRight )
hold_undo_data ( " Text Color " , a ) ;
else
release_undo_data ( " Text Color " ) ;
2025-11-09 16:24:40 +03:00
if ( ( & newTextColor = = t . colorRight ) & & t . isUpdatingColorRight ) {
currentMods [ TextStyleModifier : : ModifierType : : COLOR ] = std : : make_shared < ColorTextStyleModifier > ( newTextColor ) ;
2025-12-15 15:36:42 +03:00
a . textBox - > set_text_style_modifier_between ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos , currentMods [ TextStyleModifier : : ModifierType : : COLOR ] ) ;
2025-11-09 16:24:40 +03:00
}
2025-11-24 17:45:21 +03:00
// Highlight color
t . gui . left_to_right_line_layout ( [ & ] ( ) {
2025-11-24 18:23:53 +03:00
if ( t . gui . color_button_big ( " Highlight Color " , & newHighlightColor , & newHighlightColor = = t . colorRight ) ) {
if ( newHighlightColor . w ( ) = = 0.0f ) { // Make highlight appear when the button is pressed
newHighlightColor . w ( ) = 1.0f ;
currentMods [ TextStyleModifier : : ModifierType : : HIGHLIGHT_COLOR ] = std : : make_shared < HighlightColorTextStyleModifier > ( newHighlightColor ) ;
2025-12-15 15:36:42 +03:00
add_undo_if_selecting_area ( a , [ & ] ( ) { a . textBox - > set_text_style_modifier_between ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos , currentMods [ TextStyleModifier : : ModifierType : : HIGHLIGHT_COLOR ] ) ; } ) ;
2025-11-24 17:45:21 +03:00
}
2025-11-24 18:23:53 +03:00
t . color_selector_right ( & newHighlightColor = = t . colorRight ? nullptr : & newHighlightColor ) ;
2025-11-24 17:45:21 +03:00
}
2025-11-24 17:57:46 +03:00
if ( newHighlightColor . w ( ) ! = 0.0f ) {
if ( t . gui . svg_icon_button ( " Remove Highlight Color " , " data/icons/close.svg " ) ) {
2025-11-24 18:23:53 +03:00
newHighlightColor = { 0.0f , 0.0f , 0.0f , 0.0f } ;
2025-11-24 17:57:46 +03:00
currentMods [ TextStyleModifier : : ModifierType : : HIGHLIGHT_COLOR ] = std : : make_shared < HighlightColorTextStyleModifier > ( newHighlightColor ) ;
2025-12-15 15:36:42 +03:00
add_undo_if_selecting_area ( a , [ & ] ( ) { a . textBox - > set_text_style_modifier_between ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos , currentMods [ TextStyleModifier : : ModifierType : : HIGHLIGHT_COLOR ] ) ; } ) ;
2025-11-24 17:57:46 +03:00
}
}
2025-11-24 18:23:53 +03:00
t . gui . text_label ( " Highlight Color " ) ;
2025-11-24 17:45:21 +03:00
} ) ;
if ( & newHighlightColor = = t . colorRight )
hold_undo_data ( " Highlight Color " , a ) ;
else
release_undo_data ( " Highlight Color " ) ;
if ( ( & newHighlightColor = = t . colorRight ) & & t . isUpdatingColorRight ) {
currentMods [ TextStyleModifier : : ModifierType : : HIGHLIGHT_COLOR ] = std : : make_shared < HighlightColorTextStyleModifier > ( newHighlightColor ) ;
2025-12-15 15:36:42 +03:00
a . textBox - > set_text_style_modifier_between ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos , currentMods [ TextStyleModifier : : ModifierType : : HIGHLIGHT_COLOR ] ) ;
2025-11-24 17:45:21 +03:00
}
2025-08-02 20:10:33 +03:00
t . gui . pop_id ( ) ;
2025-10-25 17:31:55 +03:00
2025-12-15 15:36:42 +03:00
if ( a . textBox - > inputChangedTextBox )
2025-11-10 16:49:02 +03:00
set_styles_at_selection ( a ) ;
2025-11-05 12:29:31 +03:00
// NOTE: There should be a system that periodically sends updates even if no changes are made, since unreliable channels can drop update data
2025-12-15 15:36:42 +03:00
bool oldInputChangedTextBox = a . textBox - > inputChangedTextBox ;
a . textBox - > inputChangedTextBox = false ;
2025-11-05 12:29:31 +03:00
return oldInputChangedTextBox ;
2025-08-02 20:10:33 +03:00
}
2025-12-15 15:36:42 +03:00
bool TextBoxEditTool : : right_click_popup_gui ( const CanvasComponentContainer : : ObjInfoSharedPtr & comp , Vector2f popupPos ) {
2025-12-02 09:53:03 +03:00
Toolbar & t = drawP . world . main . toolbar ;
bool shouldClose = false ;
2025-12-15 15:36:42 +03:00
auto & a = static_cast < TextBoxCanvasComponent & > ( comp - > obj - > get_comp ( ) ) ;
2025-12-02 09:53:03 +03:00
t . gui . list_popup_menu ( " Text popup menu " , popupPos , [ & ] ( ) {
t . gui . text_label_light ( " Text menu " ) ;
InputManager & input = drawP . world . main . input ;
if ( t . gui . text_button_left_transparent ( " Paste " , " Paste " ) ) {
input . call_text_paste ( true ) ;
shouldClose = true ;
}
if ( t . gui . text_button_left_transparent ( " Paste without formatting " , " Paste without formatting " ) ) {
input . call_text_paste ( false ) ;
shouldClose = true ;
}
2025-12-15 15:36:42 +03:00
if ( a . cursor - > selectionBeginPos ! = a . cursor - > selectionEndPos ) {
2025-12-02 09:53:03 +03:00
if ( t . gui . text_button_left_transparent ( " Copy " , " Copy " ) ) {
2025-12-15 15:36:42 +03:00
input . set_clipboard_plain_and_richtext_pair ( a . textBox - > process_copy ( * a . cursor ) ) ;
2025-12-02 09:53:03 +03:00
shouldClose = true ;
}
if ( t . gui . text_button_left_transparent ( " Cut " , " Cut " ) ) {
input . text . do_textbox_operation_with_undo ( [ & ] ( ) {
2025-12-15 15:36:42 +03:00
input . set_clipboard_plain_and_richtext_pair ( a . textBox - > process_cut ( * a . cursor ) ) ;
2025-12-02 09:53:03 +03:00
} ) ;
shouldClose = true ;
}
}
} ) ;
return ! shouldClose ;
}
2025-12-15 15:36:42 +03:00
void TextBoxEditTool : : hold_undo_data ( const std : : string & undoName , TextBoxCanvasComponent & a ) {
2025-11-12 14:54:46 +03:00
auto it = undoHeldData . find ( undoName ) ;
if ( it ! = undoHeldData . end ( ) ) {
std : : pair < RichText : : TextBox : : Cursor , RichText : : TextData > & undoData = it - > second ;
2025-12-15 15:36:42 +03:00
if ( undoData . first ! = * a . cursor )
2025-11-12 14:54:46 +03:00
undoHeldData . erase ( it ) ;
}
2025-12-15 15:36:42 +03:00
else if ( a . cursor - > selectionBeginPos ! = a . cursor - > selectionEndPos )
undoHeldData . emplace ( undoName , std : : pair < RichText : : TextBox : : Cursor , RichText : : TextData > { * a . cursor , a . textBox - > get_rich_text_data ( ) } ) ;
2025-11-12 14:54:46 +03:00
}
void TextBoxEditTool : : release_undo_data ( const std : : string & undoName ) {
auto it = undoHeldData . find ( undoName ) ;
if ( it ! = undoHeldData . end ( ) ) {
std : : pair < RichText : : TextBox : : Cursor , RichText : : TextData > & undoData = it - > second ;
InputManager & input = drawP . world . main . input ;
input . text . add_textbox_undo ( undoData . first , undoData . second ) ;
undoHeldData . erase ( it ) ;
}
}
2025-12-15 15:36:42 +03:00
void TextBoxEditTool : : add_undo_if_selecting_area ( TextBoxCanvasComponent & a , const std : : function < void ( ) > & func ) {
if ( a . cursor - > selectionBeginPos = = a . cursor - > selectionEndPos )
2025-11-12 14:54:46 +03:00
func ( ) ;
else {
InputManager & input = drawP . world . main . input ;
input . text . do_textbox_operation_with_undo ( func ) ;
}
}
void TextBoxEditTool : : add_undo ( const std : : function < void ( ) > & func ) {
InputManager & input = drawP . world . main . input ;
input . text . do_textbox_operation_with_undo ( func ) ;
}
2025-11-09 16:24:40 +03:00
uint8_t TextBoxEditTool : : get_new_decoration_value ( ) {
uint8_t toRet = skia : : textlayout : : TextDecoration : : kNoDecoration ;
if ( newIsUnderlined )
toRet | = skia : : textlayout : : TextDecoration : : kUnderline ;
if ( newIsLinethrough )
toRet | = skia : : textlayout : : TextDecoration : : kLineThrough ;
if ( newIsOverline )
toRet | = skia : : textlayout : : TextDecoration : : kOverline ;
return toRet ;
}
2025-12-15 15:36:42 +03:00
void TextBoxEditTool : : set_styles_at_selection ( TextBoxCanvasComponent & a ) {
TextPosition start = std : : min ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos ) ;
TextPosition end = std : : max ( a . cursor - > selectionBeginPos , a . cursor - > selectionEndPos ) ;
2025-11-05 14:55:22 +03:00
if ( start = = end )
2025-12-15 15:36:42 +03:00
currentMods = a . textBox - > get_mods_used_at_pos ( a . textBox - > move ( TextBox : : Movement : : LEFT , start ) ) ;
2025-11-05 14:55:22 +03:00
else
2025-12-15 15:36:42 +03:00
currentMods = a . textBox - > get_mods_used_at_pos ( start ) ;
2025-11-10 16:49:02 +03:00
newFontName = std : : static_pointer_cast < FontFamiliesTextStyleModifier > ( currentMods [ TextStyleModifier : : ModifierType : : FONT_FAMILIES ] ) - > get_families ( ) . back ( ) . c_str ( ) ;
newFontSize = std : : static_pointer_cast < SizeTextStyleModifier > ( currentMods [ TextStyleModifier : : ModifierType : : SIZE ] ) - > get_size ( ) ;
newTextColor = std : : static_pointer_cast < ColorTextStyleModifier > ( currentMods [ TextStyleModifier : : ModifierType : : COLOR ] ) - > get_color ( ) ;
2025-11-24 17:45:21 +03:00
newHighlightColor = std : : static_pointer_cast < HighlightColorTextStyleModifier > ( currentMods [ TextStyleModifier : : ModifierType : : HIGHLIGHT_COLOR ] ) - > get_color ( ) ;
2025-11-10 16:49:02 +03:00
newIsBold = std : : static_pointer_cast < WeightTextStyleModifier > ( currentMods [ TextStyleModifier : : ModifierType : : WEIGHT ] ) - > get_weight ( ) = = SkFontStyle : : Weight : : kBold_Weight ;
newIsItalic = std : : static_pointer_cast < SlantTextStyleModifier > ( currentMods [ TextStyleModifier : : ModifierType : : SLANT ] ) - > get_slant ( ) = = SkFontStyle : : Slant : : kItalic_Slant ;
newIsUnderlined = std : : static_pointer_cast < DecorationTextStyleModifier > ( currentMods [ TextStyleModifier : : ModifierType : : DECORATION ] ) - > get_decoration_value ( ) & skia : : textlayout : : TextDecoration : : kUnderline ;
newIsLinethrough = std : : static_pointer_cast < DecorationTextStyleModifier > ( currentMods [ TextStyleModifier : : ModifierType : : DECORATION ] ) - > get_decoration_value ( ) & skia : : textlayout : : TextDecoration : : kLineThrough ;
newIsOverline = std : : static_pointer_cast < DecorationTextStyleModifier > ( currentMods [ TextStyleModifier : : ModifierType : : DECORATION ] ) - > get_decoration_value ( ) & skia : : textlayout : : TextDecoration : : kOverline ;
2025-12-15 15:36:42 +03:00
currentPStyle = a . textBox - > get_paragraph_style_data_at ( start . fParagraphIndex ) ;
2025-11-05 14:55:22 +03:00
}
2025-12-15 15:36:42 +03:00
void TextBoxEditTool : : commit_edit_updates ( const CanvasComponentContainer : : ObjInfoSharedPtr & comp , std : : any & prevData ) {
auto & a = static_cast < TextBoxCanvasComponent & > ( comp - > obj - > get_comp ( ) ) ;
a . d . editing = false ;
comp - > obj - > commit_update ( drawP ) ;
2025-08-02 20:10:33 +03:00
}
2025-12-15 15:36:42 +03:00
TextBoxEditTool : : TextBoxEditToolAllData TextBoxEditTool : : get_all_data ( const TextBoxCanvasComponent & a ) {
2025-10-25 17:31:55 +03:00
return {
2025-12-15 15:36:42 +03:00
. textboxData = a . d ,
. richText = a . textBox - > get_rich_text_data ( )
2025-10-25 17:31:55 +03:00
} ;
}
2025-12-15 15:36:42 +03:00
void TextBoxEditTool : : edit_start ( EditTool & editTool , const CanvasComponentContainer : : ObjInfoSharedPtr & comp , std : : any & prevData ) {
auto & a = static_cast < TextBoxCanvasComponent & > ( comp - > obj - > get_comp ( ) ) ;
auto & cur = a . cursor ;
auto & textbox = a . textBox ;
2025-11-10 14:45:51 +03:00
cur = std : : make_shared < TextBox : : Cursor > ( ) ;
2025-12-15 15:36:42 +03:00
Vector2f textSelectPos = a . get_mouse_pos ( drawP ) ;
2025-11-27 16:12:32 +03:00
textbox - > process_mouse_left_button ( * cur , textSelectPos , 1 , false , false ) ;
2025-11-04 10:58:26 +03:00
prevData = get_all_data ( a ) ;
2025-12-15 15:36:42 +03:00
a . d . editing = true ;
a . textBox - > inputChangedTextBox = true ;
2025-11-05 12:29:31 +03:00
2025-11-10 16:49:02 +03:00
set_styles_at_selection ( a ) ;
2025-11-05 12:29:31 +03:00
2025-12-15 15:36:42 +03:00
editTool . add_point_handle ( { & a . d . p1 , nullptr , & a . d . p2 } ) ;
editTool . add_point_handle ( { & a . d . p2 , & a . d . p1 , nullptr } ) ;
2025-08-02 20:10:33 +03:00
}
2025-12-15 15:36:42 +03:00
bool TextBoxEditTool : : edit_update ( const CanvasComponentContainer : : ObjInfoSharedPtr & comp ) {
auto & a = static_cast < TextBoxCanvasComponent & > ( comp - > obj - > get_comp ( ) ) ;
2025-08-02 20:10:33 +03:00
SCollision : : ColliderCollection < float > mousePointCollection ;
mousePointCollection . circle . emplace_back ( drawP . world . main . input . mouse . pos , 1.0f ) ;
mousePointCollection . recalculate_bounds ( ) ;
2025-12-15 15:36:42 +03:00
a . init_text_box ( drawP ) ;
2025-08-02 20:10:33 +03:00
InputManager & input = drawP . world . main . input ;
2025-12-15 15:36:42 +03:00
bool collidesWithBox = comp - > obj - > collides_with_cam_coords ( drawP . world . drawData . cam . c , mousePointCollection ) ;
2025-08-02 20:10:33 +03:00
2025-12-15 15:36:42 +03:00
input . text . set_rich_text_box_input ( a . textBox , a . cursor , true , currentMods ) ;
a . textBox - > process_mouse_left_button ( * a . cursor , a . get_mouse_pos ( drawP ) , ( drawP . controls . leftClick & & collidesWithBox ) ? drawP . world . main . input . mouse . leftClicks : 0 , drawP . controls . leftClickHeld , input . key ( InputManager : : KEY_GENERIC_LSHIFT ) . held ) ;
2025-08-02 20:10:33 +03:00
return true ;
}