Text modifiers now apply to text that will be inserted later
This commit is contained in:
parent
fabccaf553
commit
e0143f49f0
6 changed files with 106 additions and 58 deletions
|
|
@ -8,6 +8,7 @@
|
|||
#include <include/core/SkFontStyle.h>
|
||||
#include <modules/skparagraph/include/DartTypes.h>
|
||||
#include <modules/skparagraph/include/ParagraphStyle.h>
|
||||
#include <modules/skparagraph/include/TextStyle.h>
|
||||
#include <modules/skparagraph/src/ParagraphBuilderImpl.h>
|
||||
#include <modules/skunicode/include/SkUnicode_icu.h>
|
||||
#include <memory>
|
||||
|
|
@ -24,40 +25,50 @@ bool TextBoxEditTool::edit_gui(const std::shared_ptr<DrawComponent>& comp) {
|
|||
t.gui.push_id("edit tool text");
|
||||
t.gui.text_label_centered("Edit Text");
|
||||
|
||||
newFontName = std::static_pointer_cast<FontFamiliesTextStyleModifier>(modsAtStartOfSelection[TextStyleModifier::ModifierType::FONT_FAMILIES])->get_families().back().c_str();
|
||||
|
||||
t.gui.left_to_right_line_layout([&]() {
|
||||
t.gui.text_label("Font");
|
||||
if(t.gui.font_picker("font picker", &newFontName))
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, std::make_shared<FontFamiliesTextStyleModifier>(std::vector<SkString>{SkString{newFontName.c_str(), newFontName.size()}}));
|
||||
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()}});
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES]);
|
||||
}
|
||||
});
|
||||
|
||||
t.gui.left_to_right_line_centered_layout([&]() {
|
||||
bool isBold = std::static_pointer_cast<WeightTextStyleModifier>(modsAtStartOfSelection[TextStyleModifier::ModifierType::WEIGHT])->get_weight() == SkFontStyle::Weight::kBold_Weight;
|
||||
if(t.gui.svg_icon_button("Bold button", "data/icons/RemixIcon/bold.svg", isBold))
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, std::make_shared<WeightTextStyleModifier>(isBold ? SkFontStyle::Weight::kNormal_Weight : SkFontStyle::Weight::kBold_Weight));
|
||||
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);
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::WEIGHT]);
|
||||
}
|
||||
|
||||
bool isItalic = std::static_pointer_cast<SlantTextStyleModifier>(modsAtStartOfSelection[TextStyleModifier::ModifierType::SLANT])->get_slant() == SkFontStyle::Slant::kItalic_Slant;
|
||||
if(t.gui.svg_icon_button("Italic button", "data/icons/RemixIcon/italic.svg", isItalic))
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, std::make_shared<SlantTextStyleModifier>(isItalic ? SkFontStyle::Slant::kUpright_Slant : SkFontStyle::Slant::kItalic_Slant));
|
||||
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);
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SLANT]);
|
||||
}
|
||||
|
||||
uint8_t currentDecorationValue = std::static_pointer_cast<DecorationTextStyleModifier>(modsAtStartOfSelection[TextStyleModifier::ModifierType::DECORATION])->get_decoration_value();
|
||||
bool isUnderlined = currentDecorationValue & skia::textlayout::TextDecoration::kUnderline;
|
||||
if(t.gui.svg_icon_button("Underline button", "data/icons/RemixIcon/underline.svg", isUnderlined))
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, std::make_shared<DecorationTextStyleModifier>(isUnderlined ? (currentDecorationValue & ~static_cast<uint8_t>(skia::textlayout::TextDecoration::kUnderline)) : currentDecorationValue | static_cast<uint8_t>(skia::textlayout::TextDecoration::kUnderline)));
|
||||
|
||||
bool isLinethrough = currentDecorationValue & skia::textlayout::TextDecoration::kLineThrough;
|
||||
if(t.gui.svg_icon_button("Strikethrough button", "data/icons/RemixIcon/strikethrough.svg", isLinethrough))
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, std::make_shared<DecorationTextStyleModifier>(isLinethrough ? (currentDecorationValue & ~static_cast<uint8_t>(skia::textlayout::TextDecoration::kLineThrough)) : currentDecorationValue | static_cast<uint8_t>(skia::textlayout::TextDecoration::kLineThrough)));
|
||||
|
||||
bool isOverline = currentDecorationValue & skia::textlayout::TextDecoration::kOverline;
|
||||
if(t.gui.svg_icon_button("Overline button", "data/icons/RemixIcon/overline.svg", isOverline))
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, std::make_shared<DecorationTextStyleModifier>(isOverline ? (currentDecorationValue & ~static_cast<uint8_t>(skia::textlayout::TextDecoration::kOverline)) : currentDecorationValue | static_cast<uint8_t>(skia::textlayout::TextDecoration::kOverline)));
|
||||
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());
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::DECORATION]);
|
||||
}
|
||||
});
|
||||
|
||||
newFontSize = std::static_pointer_cast<SizeTextStyleModifier>(modsAtStartOfSelection[TextStyleModifier::ModifierType::SIZE])->get_size();
|
||||
if(t.gui.slider_scalar_field<uint32_t>("Font Size Slider", "Font Size", &newFontSize, 3, 100))
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, std::make_shared<SizeTextStyleModifier>(newFontSize));
|
||||
if(t.gui.slider_scalar_field<uint32_t>("Font Size Slider", "Font Size", &newFontSize, 3, 100)) {
|
||||
currentMods[TextStyleModifier::ModifierType::SIZE] = std::make_shared<SizeTextStyleModifier>(newFontSize);
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SIZE]);
|
||||
}
|
||||
|
||||
t.gui.left_to_right_line_layout([&]() {
|
||||
CLAY({.layout = {.sizing = {.width = CLAY_SIZING_FIXED(40), .height = CLAY_SIZING_FIXED(40)}}}) {
|
||||
|
|
@ -67,15 +78,26 @@ bool TextBoxEditTool::edit_gui(const std::shared_ptr<DrawComponent>& comp) {
|
|||
}
|
||||
t.gui.text_label("Text Color");
|
||||
});
|
||||
if((&newTextColor == t.colorRight) && t.isUpdatingColorRight)
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, std::make_shared<ColorTextStyleModifier>(newTextColor));
|
||||
newTextColor = std::static_pointer_cast<ColorTextStyleModifier>(modsAtStartOfSelection[TextStyleModifier::ModifierType::COLOR])->get_color();
|
||||
if((&newTextColor == t.colorRight) && t.isUpdatingColorRight) {
|
||||
currentMods[TextStyleModifier::ModifierType::COLOR] = std::make_shared<ColorTextStyleModifier>(newTextColor);
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::COLOR]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
t.gui.pop_id();
|
||||
|
||||
if(a->textBox->inputChangedTextBox)
|
||||
if(a->textBox->inputChangedTextBox) {
|
||||
set_mods_at_selection(a);
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
||||
// NOTE: There should be a system that periodically sends updates even if no changes are made, since unreliable channels can drop update data
|
||||
bool oldInputChangedTextBox = a->textBox->inputChangedTextBox;
|
||||
|
|
@ -83,13 +105,24 @@ bool TextBoxEditTool::edit_gui(const std::shared_ptr<DrawComponent>& comp) {
|
|||
return oldInputChangedTextBox;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void TextBoxEditTool::set_mods_at_selection(const std::shared_ptr<DrawTextBox>& a) {
|
||||
RichTextBox::TextPosition start = std::min(a->cursor->selectionBeginPos, a->cursor->selectionEndPos);
|
||||
RichTextBox::TextPosition end = std::max(a->cursor->selectionBeginPos, a->cursor->selectionEndPos);
|
||||
if(start == end)
|
||||
modsAtStartOfSelection = a->textBox->get_mods_used_at_pos(a->textBox->move(RichTextBox::Movement::LEFT, start));
|
||||
currentMods = a->textBox->get_mods_used_at_pos(a->textBox->move(RichTextBox::Movement::LEFT, start));
|
||||
else
|
||||
modsAtStartOfSelection = a->textBox->get_mods_used_at_pos(start);
|
||||
currentMods = a->textBox->get_mods_used_at_pos(start);
|
||||
}
|
||||
|
||||
void TextBoxEditTool::commit_edit_updates(const std::shared_ptr<DrawComponent>& comp, std::any& prevData) {
|
||||
|
|
@ -159,7 +192,7 @@ bool TextBoxEditTool::edit_update(const std::shared_ptr<DrawComponent>& comp) {
|
|||
|
||||
bool collidesWithBox = a->collides_with_cam_coords(drawP.world.drawData.cam.c, mousePointCollection);
|
||||
|
||||
input.text.set_rich_text_box_input(a->textBox, a->cursor);
|
||||
input.text.set_rich_text_box_input(a->textBox, a->cursor, currentMods);
|
||||
a->textBox->process_mouse_left_button(*a->cursor, a->get_mouse_pos(drawP), drawP.controls.leftClick && collidesWithBox, drawP.controls.leftClickHeld, input.key(InputManager::KEY_GENERIC_LSHIFT).held);
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -22,10 +22,16 @@ class TextBoxEditTool : public DrawingProgramEditToolBase {
|
|||
|
||||
uint32_t newFontSize = 15;
|
||||
Vector4f newTextColor{1.0f, 1.0f, 1.0f, 1.0f};
|
||||
bool newIsBold = false;
|
||||
bool newIsItalic = false;
|
||||
bool newIsUnderlined = false;
|
||||
bool newIsLinethrough = false;
|
||||
bool newIsOverline = false;
|
||||
std::string newFontName;
|
||||
|
||||
uint8_t get_new_decoration_value();
|
||||
void set_mods_at_selection(const std::shared_ptr<DrawTextBox>& a);
|
||||
TextStyleModifier::ModifierMap modsAtStartOfSelection;
|
||||
TextStyleModifier::ModifierMap currentMods;
|
||||
|
||||
std::vector<std::string> sortedFontList;
|
||||
|
||||
|
|
|
|||
|
|
@ -77,15 +77,16 @@ void InputManager::text_input_silence_everything() {
|
|||
text.newInput.clear();
|
||||
}
|
||||
|
||||
void InputManager::Text::set_rich_text_box_input(const std::shared_ptr<RichTextBox>& nTextBox, const std::shared_ptr<RichTextBox::Cursor>& nCursor) {
|
||||
void InputManager::Text::set_rich_text_box_input(const std::shared_ptr<RichTextBox>& nTextBox, const std::shared_ptr<RichTextBox::Cursor>& nCursor, const std::optional<TextStyleModifier::ModifierMap>& nModMap) {
|
||||
set_accepting_input();
|
||||
newTextBox = nTextBox;
|
||||
newCursor = nCursor;
|
||||
newModMap = nModMap;
|
||||
}
|
||||
|
||||
void InputManager::Text::add_text_to_textbox(const std::string& inputText) {
|
||||
if(textBox)
|
||||
textBox->process_text_input(*cursor, inputText);
|
||||
textBox->process_text_input(*cursor, inputText, modMap);
|
||||
}
|
||||
|
||||
void InputManager::Text::set_accepting_input() {
|
||||
|
|
@ -218,42 +219,42 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) {
|
|||
case SDLK_UP:
|
||||
set_key_down(e, KEY_TEXT_UP);
|
||||
if(text.textBox && key(KEY_TEXT_UP).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::UP, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::UP, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
set_key_down(e, KEY_TEXT_DOWN);
|
||||
if(text.textBox && key(KEY_TEXT_DOWN).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::DOWN, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::DOWN, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
set_key_down(e, KEY_TEXT_LEFT);
|
||||
if(text.textBox && key(KEY_TEXT_LEFT).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::LEFT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::LEFT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
set_key_down(e, KEY_TEXT_RIGHT);
|
||||
if(text.textBox && key(KEY_TEXT_RIGHT).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::RIGHT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::RIGHT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
case SDLK_BACKSPACE:
|
||||
set_key_down(e, KEY_TEXT_BACKSPACE);
|
||||
if(text.textBox && key(KEY_TEXT_BACKSPACE).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::BACKSPACE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::BACKSPACE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
case SDLK_DELETE:
|
||||
set_key_down(e, KEY_TEXT_DELETE);
|
||||
if(text.textBox && key(KEY_TEXT_DELETE).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::DELETE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::DELETE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
case SDLK_HOME:
|
||||
set_key_down(e, KEY_TEXT_HOME);
|
||||
if(text.textBox && key(KEY_TEXT_HOME).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::HOME, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::HOME, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
case SDLK_END:
|
||||
set_key_down(e, KEY_TEXT_END);
|
||||
if(text.textBox && key(KEY_TEXT_END).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::END, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::END, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
case SDLK_LSHIFT:
|
||||
set_key_down(e, KEY_TEXT_SHIFT);
|
||||
|
|
@ -287,24 +288,24 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) {
|
|||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_PASTE);
|
||||
if(text.textBox && key(KEY_TEXT_PASTE).repeat)
|
||||
text.textBox->process_text_input(*text.cursor, get_clipboard_str());
|
||||
text.textBox->process_text_input(*text.cursor, get_clipboard_str(), text.modMap);
|
||||
break;
|
||||
case SDLK_A:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_SELECTALL);
|
||||
if(text.textBox && key(KEY_TEXT_SELECTALL).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::SELECT_ALL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::SELECT_ALL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
case SDLK_RETURN: {
|
||||
set_key_down(e, KEY_TEXT_ENTER);
|
||||
if(text.textBox && key(KEY_TEXT_ENTER).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::ENTER, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::ENTER, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
}
|
||||
case SDLK_TAB: {
|
||||
set_key_down(e, KEY_TEXT_TAB);
|
||||
if(text.textBox && key(KEY_TEXT_TAB).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::TAB, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held);
|
||||
text.textBox->process_key_input(*text.cursor, RichTextBox::InputKey::TAB, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
break;
|
||||
}
|
||||
case SDLK_ESCAPE:
|
||||
|
|
@ -417,6 +418,7 @@ void InputManager::frame_reset(const Vector2i& windowSize) {
|
|||
text.acceptingInputNew = false;
|
||||
text.cursor = text.newCursor;
|
||||
text.textBox = text.newTextBox;
|
||||
text.modMap = text.newModMap;
|
||||
text.newCursor = nullptr;
|
||||
text.newTextBox = nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <Eigen/Dense>
|
||||
#include <array>
|
||||
#include "RichTextBox/TextStyleModifier.hpp"
|
||||
#include "TimePoint.hpp"
|
||||
#include <Helpers/Hashes.hpp>
|
||||
#include <unordered_map>
|
||||
|
|
@ -87,15 +88,17 @@ struct InputManager {
|
|||
void set_accepting_input();
|
||||
bool get_accepting_input();
|
||||
|
||||
void set_rich_text_box_input(const std::shared_ptr<RichTextBox>& nTextBox, const std::shared_ptr<RichTextBox::Cursor>& nCursor);
|
||||
void set_rich_text_box_input(const std::shared_ptr<RichTextBox>& nTextBox, const std::shared_ptr<RichTextBox::Cursor>& nCursor, const std::optional<TextStyleModifier::ModifierMap>& nModMap = std::nullopt);
|
||||
void add_text_to_textbox(const std::string& inputText);
|
||||
|
||||
private:
|
||||
std::shared_ptr<RichTextBox> textBox;
|
||||
std::shared_ptr<RichTextBox::Cursor> cursor;
|
||||
std::optional<TextStyleModifier::ModifierMap> modMap;
|
||||
|
||||
std::shared_ptr<RichTextBox> newTextBox;
|
||||
std::shared_ptr<RichTextBox::Cursor> newCursor;
|
||||
std::optional<TextStyleModifier::ModifierMap> newModMap;
|
||||
|
||||
bool acceptingInput = false;
|
||||
bool acceptingInputNew = false;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ RichTextBox::RichTextBox() {
|
|||
paragraphs.emplace_back();
|
||||
}
|
||||
|
||||
void RichTextBox::process_key_input(Cursor& cur, InputKey in, bool ctrl, bool shift) {
|
||||
void RichTextBox::process_key_input(Cursor& cur, InputKey in, bool ctrl, bool shift, const std::optional<TextStyleModifier::ModifierMap>& inputModMap) {
|
||||
bool moved = false;
|
||||
|
||||
switch(in) {
|
||||
|
|
@ -102,10 +102,10 @@ void RichTextBox::process_key_input(Cursor& cur, InputKey in, bool ctrl, bool sh
|
|||
cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.pos, move(ctrl ? Movement::RIGHT_WORD : Movement::RIGHT, cur.pos));
|
||||
break;
|
||||
case InputKey::ENTER:
|
||||
process_text_input(cur, "\n");
|
||||
process_text_input(cur, "\n", inputModMap);
|
||||
break;
|
||||
case InputKey::TAB:
|
||||
process_text_input(cur, "\t");
|
||||
process_text_input(cur, "\t", inputModMap);
|
||||
break;
|
||||
case InputKey::SELECT_ALL:
|
||||
cur.selectionBeginPos = move(Movement::HOME, cur.pos);
|
||||
|
|
@ -152,11 +152,11 @@ std::string RichTextBox::process_cut(Cursor& cur) {
|
|||
return toRet;
|
||||
}
|
||||
|
||||
void RichTextBox::process_text_input(Cursor& cur, const std::string& in) {
|
||||
void RichTextBox::process_text_input(Cursor& cur, const std::string& in, const std::optional<TextStyleModifier::ModifierMap>& inputModMap) {
|
||||
if(!in.empty()) {
|
||||
if(cur.selectionBeginPos != cur.selectionEndPos)
|
||||
cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.selectionBeginPos, cur.selectionEndPos);
|
||||
cur.selectionEndPos = cur.selectionBeginPos = cur.pos = insert(cur.pos, in);
|
||||
cur.selectionEndPos = cur.selectionBeginPos = cur.pos = insert(cur.pos, in, inputModMap);
|
||||
cur.previousX = std::nullopt;
|
||||
inputChangedTextBox = true;
|
||||
}
|
||||
|
|
@ -704,8 +704,8 @@ void RichTextBox::set_tab_space_width(unsigned newTabWidth) {
|
|||
tabWidth = newTabWidth;
|
||||
}
|
||||
|
||||
RichTextBox::TextPosition RichTextBox::insert(TextPosition pos, std::string_view textToInsert) {
|
||||
pos = move(Movement::NOWHERE, pos);
|
||||
RichTextBox::TextPosition RichTextBox::insert(TextPosition pos, std::string_view textToInsert, const std::optional<TextStyleModifier::ModifierMap>& inputModMap) {
|
||||
TextPosition oldPos = pos = move(Movement::NOWHERE, pos);
|
||||
|
||||
for(char c : textToInsert) {
|
||||
if(c == '\n') {
|
||||
|
|
@ -745,6 +745,10 @@ RichTextBox::TextPosition RichTextBox::insert(TextPosition pos, std::string_view
|
|||
|
||||
if(!textToInsert.empty()) {
|
||||
remove_duplicate_text_style_mods();
|
||||
if(inputModMap.has_value()) {
|
||||
for(const auto& [modType, modifier] : inputModMap.value())
|
||||
set_text_style_modifier_between(oldPos, pos, modifier);
|
||||
}
|
||||
inputChangedTextBox = true;
|
||||
needsRebuild = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class RichTextBox {
|
|||
|
||||
TextPosition move(Movement movement, TextPosition pos, std::optional<float>* previousX = nullptr, bool flipDependingOnTextDirection = false);
|
||||
void set_width(float newWidth);
|
||||
TextPosition insert(TextPosition pos, std::string_view textToInsert);
|
||||
TextPosition insert(TextPosition pos, std::string_view textToInsert, const std::optional<TextStyleModifier::ModifierMap>& inputModMap = std::nullopt);
|
||||
TextPosition remove(TextPosition p1, TextPosition p2);
|
||||
void set_font_collection(const sk_sp<skia::textlayout::FontCollection>& fC);
|
||||
void paint(SkCanvas* canvas, const PaintOpts& paintOpts);
|
||||
|
|
@ -111,13 +111,13 @@ class RichTextBox {
|
|||
void set_string(const std::string& str);
|
||||
|
||||
void process_mouse_left_button(Cursor& cur, const Vector2f& pos, bool clicked, bool held, bool shift);
|
||||
void process_key_input(Cursor& cur, InputKey in, bool ctrl, bool shift);
|
||||
void process_key_input(Cursor& cur, InputKey in, bool ctrl, bool shift, const std::optional<TextStyleModifier::ModifierMap>& inputModMap = std::nullopt);
|
||||
std::string process_copy(Cursor& cur);
|
||||
std::string process_cut(Cursor& cur);
|
||||
std::string get_text_between(TextPosition p1, TextPosition p2);
|
||||
std::string get_string();
|
||||
void set_tab_space_width(unsigned newTabWidth);
|
||||
void process_text_input(Cursor& cur, const std::string& in);
|
||||
void process_text_input(Cursor& cur, const std::string& in, const std::optional<TextStyleModifier::ModifierMap>& inputModMap = std::nullopt);
|
||||
|
||||
private:
|
||||
static size_t count_grapheme(const std::string& text);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue