Made modifiers immutable to prevent mistakes

This commit is contained in:
Yousef Khadadeh 2025-11-09 15:01:57 +03:00
parent 45da7939eb
commit fabccaf553
4 changed files with 85 additions and 91 deletions

View file

@ -16,17 +16,9 @@ DrawTextBox::DrawTextBox():
skia::textlayout::TextStyle tStyle;
textBox->set_initial_text_style(tStyle);
auto colorMod = std::make_shared<ColorTextStyleModifier>();
colorMod->color = {1.0f, 1.0f, 1.0f, 1.0f};
textBox->set_initial_text_style_modifier(colorMod);
auto textSizeMod = std::make_shared<SizeTextStyleModifier>();
textSizeMod->size = 18.0f;
textBox->set_initial_text_style_modifier(textSizeMod);
auto fontFamilyMod = std::make_shared<FontFamiliesTextStyleModifier>();
fontFamilyMod->families = {SkString{"Roboto"}};
textBox->set_initial_text_style_modifier(fontFamilyMod);
textBox->set_initial_text_style_modifier(std::make_shared<ColorTextStyleModifier>(Vector4f{1.0f, 1.0f, 1.0f, 1.0f}));
textBox->set_initial_text_style_modifier(std::make_shared<SizeTextStyleModifier>(18.0f));
textBox->set_initial_text_style_modifier(std::make_shared<FontFamiliesTextStyleModifier>(std::vector<SkString>{SkString{"Roboto"}}));
}
DrawComponentType DrawTextBox::get_type() const {

View file

@ -24,62 +24,41 @@ 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])->families.back().c_str();
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)) {
auto fontFamilyMod = std::make_shared<FontFamiliesTextStyleModifier>();
fontFamilyMod->families.clear();
fontFamilyMod->families.emplace_back(newFontName);
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, fontFamilyMod);
}
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()}}));
});
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)) {
auto boldMod = std::make_shared<WeightTextStyleModifier>();
boldMod->set_weight(isBold ? SkFontStyle::Weight::kNormal_Weight : SkFontStyle::Weight::kBold_Weight);
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, boldMod);
}
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));
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)) {
auto italicMod = std::make_shared<SlantTextStyleModifier>();
italicMod->set_slant(isItalic ? SkFontStyle::Slant::kUpright_Slant : SkFontStyle::Slant::kItalic_Slant);
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, italicMod);
}
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));
uint8_t currentDecorationValue = std::static_pointer_cast<DecorationTextStyleModifier>(modsAtStartOfSelection[TextStyleModifier::ModifierType::DECORATION])->decorationValue;
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)) {
auto decorationMod = std::make_shared<DecorationTextStyleModifier>();
decorationMod->decorationValue = isUnderlined ? (currentDecorationValue & ~static_cast<uint8_t>(skia::textlayout::TextDecoration::kUnderline)) : currentDecorationValue | static_cast<uint8_t>(skia::textlayout::TextDecoration::kUnderline);
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, decorationMod);
}
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)) {
auto decorationMod = std::make_shared<DecorationTextStyleModifier>();
decorationMod->decorationValue = isLinethrough ? (currentDecorationValue & ~static_cast<uint8_t>(skia::textlayout::TextDecoration::kLineThrough)) : currentDecorationValue | static_cast<uint8_t>(skia::textlayout::TextDecoration::kLineThrough);
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, decorationMod);
}
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)) {
auto decorationMod = std::make_shared<DecorationTextStyleModifier>();
decorationMod->decorationValue = isOverline ? (currentDecorationValue & ~static_cast<uint8_t>(skia::textlayout::TextDecoration::kOverline)) : currentDecorationValue | static_cast<uint8_t>(skia::textlayout::TextDecoration::kOverline);
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, decorationMod);
}
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)));
});
newFontSize = std::static_pointer_cast<SizeTextStyleModifier>(modsAtStartOfSelection[TextStyleModifier::ModifierType::SIZE])->size;
if(t.gui.slider_scalar_field<uint32_t>("Font Size Slider", "Font Size", &newFontSize, 3, 100)) {
auto sizeMod = std::make_shared<SizeTextStyleModifier>();
sizeMod->size = newFontSize;
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, sizeMod);
}
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));
t.gui.left_to_right_line_layout([&]() {
CLAY({.layout = {.sizing = {.width = CLAY_SIZING_FIXED(40), .height = CLAY_SIZING_FIXED(40)}}}) {
if(t.gui.color_button("Text Color", &newTextColor, &newTextColor == t.colorRight)) {
@ -88,12 +67,9 @@ bool TextBoxEditTool::edit_gui(const std::shared_ptr<DrawComponent>& comp) {
}
t.gui.text_label("Text Color");
});
if((&newTextColor == t.colorRight) && t.isUpdatingColorRight) {
auto colorMod = std::make_shared<ColorTextStyleModifier>();
colorMod->color = newTextColor;
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, colorMod);
}
newTextColor = std::static_pointer_cast<ColorTextStyleModifier>(modsAtStartOfSelection[TextStyleModifier::ModifierType::COLOR])->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();
t.gui.pop_id();

View file

@ -38,17 +38,9 @@ std::shared_ptr<TextStyleModifier> TextStyleModifier::get_default_modifier(Modif
const TextStyleModifier::ModifierMap& TextStyleModifier::get_default_modifiers() {
if(defaultMods.empty()) {
auto weightMod = std::make_shared<WeightTextStyleModifier>();
weightMod->set_weight(SkFontStyle::kNormal_Weight);
defaultMods[ModifierType::WEIGHT] = weightMod;
auto slantMod = std::make_shared<SlantTextStyleModifier>();
slantMod->set_slant(SkFontStyle::kUpright_Slant);
defaultMods[ModifierType::SLANT] = slantMod;
auto decorationMod = std::make_shared<DecorationTextStyleModifier>();
decorationMod->decorationValue = skia::textlayout::TextDecoration::kNoDecoration;
defaultMods[ModifierType::DECORATION] = decorationMod;
defaultMods[ModifierType::WEIGHT] = std::make_shared<WeightTextStyleModifier>(SkFontStyle::kNormal_Weight);
defaultMods[ModifierType::SLANT] = std::make_shared<SlantTextStyleModifier>(SkFontStyle::kUpright_Slant);
defaultMods[ModifierType::DECORATION] = std::make_shared<DecorationTextStyleModifier>(skia::textlayout::TextDecoration::kNoDecoration);
}
return defaultMods;
}
@ -63,10 +55,16 @@ TextStyleModifier::~TextStyleModifier() {}
WeightTextStyleModifier::WeightTextStyleModifier(SkFontStyle::Weight initWeight): weightValue(initWeight / WEIGHT_VALUE_MODIFIER) {}
TextStyleModifier::ModifierType WeightTextStyleModifier::get_type() const {
return ModifierType::WEIGHT;
}
SkFontStyle::Weight WeightTextStyleModifier::get_weight() const {
return static_cast<SkFontStyle::Weight>(static_cast<int>(weightValue) * WEIGHT_VALUE_MODIFIER);
}
void WeightTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
a(weightValue);
}
@ -75,14 +73,6 @@ void WeightTextStyleModifier::load(cereal::PortableBinaryInputArchive& a) {
a(weightValue);
}
void WeightTextStyleModifier::set_weight(SkFontStyle::Weight newWeight) {
weightValue = newWeight / WEIGHT_VALUE_MODIFIER;
}
SkFontStyle::Weight WeightTextStyleModifier::get_weight() {
return static_cast<SkFontStyle::Weight>(static_cast<int>(weightValue) * WEIGHT_VALUE_MODIFIER);
}
void WeightTextStyleModifier::modify_text_style(skia::textlayout::TextStyle& style) const {
style.setFontStyle(SkFontStyle(static_cast<int>(weightValue) * WEIGHT_VALUE_MODIFIER, style.getFontStyle().width(), style.getFontStyle().slant()));
}
@ -93,10 +83,16 @@ bool WeightTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const
SlantTextStyleModifier::SlantTextStyleModifier(uint8_t initSlantValue): slantValue(initSlantValue) {}
TextStyleModifier::ModifierType SlantTextStyleModifier::get_type() const {
return ModifierType::SLANT;
}
SkFontStyle::Slant SlantTextStyleModifier::get_slant() const {
return static_cast<SkFontStyle::Slant>(slantValue);
}
void SlantTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
a(slantValue);
}
@ -105,14 +101,6 @@ void SlantTextStyleModifier::load(cereal::PortableBinaryInputArchive& a) {
a(slantValue);
}
void SlantTextStyleModifier::set_slant(SkFontStyle::Slant newSlant) {
slantValue = newSlant;
}
SkFontStyle::Slant SlantTextStyleModifier::get_slant() {
return static_cast<SkFontStyle::Slant>(slantValue);
}
void SlantTextStyleModifier::modify_text_style(skia::textlayout::TextStyle& style) const {
style.setFontStyle(SkFontStyle(style.getFontStyle().weight(), style.getFontStyle().width(), static_cast<SkFontStyle::Slant>(slantValue)));
}
@ -123,10 +111,16 @@ bool SlantTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const
ColorTextStyleModifier::ColorTextStyleModifier(const Vector4f& initColor): color(initColor) {}
TextStyleModifier::ModifierType ColorTextStyleModifier::get_type() const {
return ModifierType::COLOR;
}
const Vector4f& ColorTextStyleModifier::get_color() const {
return color;
}
void ColorTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
a(color);
}
@ -146,10 +140,16 @@ bool ColorTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const
SizeTextStyleModifier::SizeTextStyleModifier(float initSize): size(initSize) {}
TextStyleModifier::ModifierType SizeTextStyleModifier::get_type() const {
return ModifierType::SIZE;
}
float SizeTextStyleModifier::get_size() const {
return size;
}
void SizeTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
a(size);
}
@ -168,10 +168,16 @@ bool SizeTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const {
FontFamiliesTextStyleModifier::FontFamiliesTextStyleModifier(const std::vector<SkString>& initFamilies): families(initFamilies) {}
TextStyleModifier::ModifierType FontFamiliesTextStyleModifier::get_type() const {
return ModifierType::FONT_FAMILIES;
}
const std::vector<SkString>& FontFamiliesTextStyleModifier::get_families() const {
return families;
}
void FontFamiliesTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
a(families);
}
@ -192,10 +198,16 @@ bool FontFamiliesTextStyleModifier::equivalent_data(TextStyleModifier& modifier)
DecorationTextStyleModifier::DecorationTextStyleModifier(uint8_t initDecorationValue): decorationValue(initDecorationValue) {}
TextStyleModifier::ModifierType DecorationTextStyleModifier::get_type() const {
return ModifierType::DECORATION;
}
uint8_t DecorationTextStyleModifier::get_decoration_value() const {
return decorationValue;
}
void DecorationTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
a(decorationValue);
}

View file

@ -36,23 +36,27 @@ class TextStyleModifier {
class DecorationTextStyleModifier : public TextStyleModifier {
public:
DecorationTextStyleModifier() = default;
DecorationTextStyleModifier(uint8_t initDecorationValue);
virtual ModifierType get_type() const override;
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load(cereal::PortableBinaryInputArchive& a) override;
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
uint8_t decorationValue;
uint8_t get_decoration_value() const;
private:
uint8_t decorationValue;
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
};
class WeightTextStyleModifier : public TextStyleModifier {
public:
WeightTextStyleModifier() = default;
WeightTextStyleModifier(SkFontStyle::Weight initWeight);
virtual ModifierType get_type() const override;
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load(cereal::PortableBinaryInputArchive& a) override;
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
void set_weight(SkFontStyle::Weight newWeight);
SkFontStyle::Weight get_weight();
SkFontStyle::Weight get_weight() const;
private:
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
uint8_t weightValue;
@ -60,12 +64,13 @@ class WeightTextStyleModifier : public TextStyleModifier {
class SlantTextStyleModifier : public TextStyleModifier {
public:
SlantTextStyleModifier() = default;
SlantTextStyleModifier(uint8_t initSlantValue);
virtual ModifierType get_type() const override;
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load(cereal::PortableBinaryInputArchive& a) override;
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
void set_slant(SkFontStyle::Slant newSlant);
SkFontStyle::Slant get_slant();
SkFontStyle::Slant get_slant() const;
private:
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
uint8_t slantValue;
@ -73,33 +78,42 @@ class SlantTextStyleModifier : public TextStyleModifier {
class ColorTextStyleModifier : public TextStyleModifier {
public:
ColorTextStyleModifier() = default;
ColorTextStyleModifier(const Vector4f& initColor);
virtual ModifierType get_type() const override;
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load(cereal::PortableBinaryInputArchive& a) override;
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
Vector4f color;
const Vector4f& get_color() const;
private:
Vector4f color;
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
};
class SizeTextStyleModifier : public TextStyleModifier {
public:
SizeTextStyleModifier() = default;
SizeTextStyleModifier(float initSize);
virtual ModifierType get_type() const override;
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load(cereal::PortableBinaryInputArchive& a) override;
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
float size;
float get_size() const;
private:
float size;
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
};
class FontFamiliesTextStyleModifier : public TextStyleModifier {
public:
FontFamiliesTextStyleModifier() = default;
FontFamiliesTextStyleModifier(const std::vector<SkString>& initFamilies);
virtual ModifierType get_type() const override;
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load(cereal::PortableBinaryInputArchive& a) override;
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
std::vector<SkString> families;
const std::vector<SkString>& get_families() const;
private:
std::vector<SkString> families;
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
};