mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-06-19 14:00:55 -04:00
207 lines
6.2 KiB
C++
207 lines
6.2 KiB
C++
#pragma once
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "Alignment.hpp"
|
|
#include "InputEvent.hpp"
|
|
#include "TextConstants.hpp"
|
|
#include "utf8/UTF8.hpp"
|
|
|
|
#include "BoxLayout.hpp"
|
|
#include "InputMode.hpp"
|
|
#include "Label.hpp"
|
|
#include "Rect.hpp"
|
|
#include "Style.hpp"
|
|
#include "TextCursor.hpp"
|
|
#include "TextDocument.hpp"
|
|
#include "TextLine.hpp"
|
|
#include "Translator.hpp"
|
|
|
|
namespace gui
|
|
{
|
|
|
|
/// @brief Widget that holds multiple lines of text.
|
|
///
|
|
/// Can expand horizontally to it's max size if it needs to fit more text in line
|
|
/// Can expand vertically if needed to hold lines of text.
|
|
/// Handles input
|
|
/// 1. Provides text navigation
|
|
/// 2. Provides new letter input with gui::KeyInputMappedTranslation
|
|
/// 3. handles deletion of character
|
|
///
|
|
/// This widget stores both: whole text provided to it, and text visible on the screen
|
|
/// screen visible on the screen is a set of labels
|
|
///
|
|
class Text : public Rect
|
|
{
|
|
friend TextCursor;
|
|
|
|
protected:
|
|
// holds list of labels for displaying currently visible text lines.
|
|
class Lines
|
|
{
|
|
Item *parent = nullptr;
|
|
std::list<TextLine> lines;
|
|
|
|
public:
|
|
void erase()
|
|
{
|
|
if (parent != nullptr) {
|
|
for (auto &line : lines) {
|
|
line.erase();
|
|
}
|
|
}
|
|
lines.clear();
|
|
}
|
|
|
|
void emplace(TextLine &&line)
|
|
{
|
|
lines.emplace_back(std::move(line));
|
|
}
|
|
|
|
Lines(Item *parent)
|
|
{
|
|
this->parent = parent;
|
|
}
|
|
|
|
const auto &get()
|
|
{
|
|
return lines;
|
|
}
|
|
|
|
auto &last()
|
|
{
|
|
return lines.back();
|
|
}
|
|
|
|
auto size()
|
|
{
|
|
return lines.size();
|
|
}
|
|
|
|
auto maxWidth()
|
|
{
|
|
unsigned int w = 0;
|
|
// could be std::max_element
|
|
for (auto &el : lines) {
|
|
w = el.width() > w ? el.width() : w;
|
|
}
|
|
return w;
|
|
}
|
|
|
|
auto linesHeight()
|
|
{
|
|
unsigned int h = 0;
|
|
for (auto &el : lines) {
|
|
h += el.height();
|
|
}
|
|
return h;
|
|
}
|
|
|
|
auto linesVAlign(Length parentSize)
|
|
{
|
|
for (auto &line : lines) {
|
|
line.alignV(parent->getAlignment(Axis::Y), parentSize, linesHeight());
|
|
}
|
|
}
|
|
|
|
} lines;
|
|
|
|
TextCursor *cursor = nullptr;
|
|
std::unique_ptr<TextDocument> document = std::make_unique<TextDocument>(std::list<TextBlock>());
|
|
InputMode *mode = nullptr;
|
|
|
|
void buildDocument(const UTF8 &text);
|
|
void buildDocument(std::unique_ptr<TextDocument> &&document);
|
|
void buildCursor();
|
|
/// show cursor if cursor should be visible
|
|
void showCursor(bool focus);
|
|
|
|
EditMode editMode = EditMode::EDIT;
|
|
[[nodiscard]] bool isMode(EditMode edit) const
|
|
{
|
|
return editMode == edit;
|
|
}
|
|
KeyCode key_signs_remove = KeyCode::KEY_PND;
|
|
|
|
public:
|
|
ExpandMode expandMode = ExpandMode::EXPAND_NONE;
|
|
|
|
protected:
|
|
TextType textType = TextType::MULTI_LINE;
|
|
/// points to default text font to use
|
|
RawFont *font = nullptr;
|
|
Color textColor;
|
|
bool underline = false;
|
|
|
|
bool moveCursor(const NavigationDirection &direction, std::unique_ptr<TextDocument> &document);
|
|
bool handleNavigation(const InputEvent &inputEvent);
|
|
bool handleEnter();
|
|
|
|
std::list<DrawCommand *> buildDrawList() override;
|
|
/// redrawing lines
|
|
/// it redraws visible lines on screen and if needed requests resize in parent
|
|
virtual void drawLines();
|
|
/// redrawing cursor
|
|
void drawCursor();
|
|
|
|
public:
|
|
Text();
|
|
Text(Item *parent,
|
|
const uint32_t &x,
|
|
const uint32_t &y,
|
|
const uint32_t &w,
|
|
const uint32_t &h,
|
|
const UTF8 &text = "",
|
|
ExpandMode expandMode = ExpandMode::EXPAND_NONE,
|
|
TextType textType = TextType::MULTI_LINE);
|
|
~Text() override;
|
|
|
|
void setEditMode(EditMode mode);
|
|
void setTextType(TextType type);
|
|
void setUnderline(const bool val);
|
|
virtual void setText(const UTF8 &text);
|
|
void setText(std::unique_ptr<TextDocument> &&document);
|
|
|
|
void addText(const UTF8 &text);
|
|
void addText(TextBlock text);
|
|
virtual void clear();
|
|
virtual UTF8 getText();
|
|
/// saves text from widget to file at specified path
|
|
virtual bool saveText(UTF8 path);
|
|
void setFont(const UTF8 &fontName);
|
|
void setFont(RawFont *font);
|
|
|
|
// virtual methods from Item
|
|
bool onInput(const InputEvent &inputEvent) override;
|
|
/// move ownership of mode ptr to Text
|
|
void setInputMode(InputMode *&&mode)
|
|
{
|
|
if (this->mode != nullptr) {
|
|
delete this->mode;
|
|
}
|
|
this->mode = mode;
|
|
};
|
|
bool onFocus(bool state) override;
|
|
bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
|
|
void setRadius(int value) override;
|
|
void setAlignment(const Alignment &value) override;
|
|
void setPadding(const Padding &value) override;
|
|
|
|
private:
|
|
gui::KeyInputMappedTranslation translator;
|
|
bool handleRotateInputMode(const InputEvent &inputEvent);
|
|
bool handleRestoreInputModeUI(const InputEvent &inputEvent);
|
|
bool handleSelectSpecialChar(const InputEvent &inputEvent);
|
|
bool handleActivation(const InputEvent &inputEvent);
|
|
bool handleBackspace(const InputEvent &inputEvent);
|
|
bool handleAddChar(const InputEvent &inputEvent);
|
|
bool handleDigitLongPress(const InputEvent &inputEvent);
|
|
|
|
bool addChar(uint32_t utf8);
|
|
bool removeChar();
|
|
};
|
|
|
|
} /* namespace gui */
|