vkdoom_m/include/zwidget/widgets/textedit/textedit.h
Marcus Minhorst 87689ccb5f Squashed 'libraries/ZWidget/' changes from cecd34301d..924b8e0e78
924b8e0e78 Fix scroll size issue
f0344ed99b Add option to hide scrollbar when no scrolling is to be had
f7b01d6625 Remove stray sdl
214d098353 Theme role improvements
82d0431ca5 Textedit highlight now follows theme
373ab3f4ca Added hex Colorf alias
5ea6d5a62a Reduced duplicate code
a92e045b18 Simplified theme
d076c9991c Expanded example
e4556c97df Named colors
6d9300c742 Fix COM thread error
6499e5c523 Add null pointer checks
f9d5724210 Fix x11 backend locking up Implement raw mouse input support (XInput 2.0) Fix x11 DPI scaling
4a86fb5056 XInitThreads must be called when using vulkan
8095090774 Add DPI scale to X11 backend
02fb328172 Mute a bunch of warnings
f13c745a63 Fix typo
5689bf5edd Merge in changes from SurrealEngine Use C++20 Make SDL2 optional

git-subtree-dir: libraries/ZWidget
git-subtree-split: 924b8e0e786093708c0d73419a347f8e6ffe55d6
2025-08-26 22:05:52 -04:00

161 lines
4.2 KiB
C++

#pragma once
#include "../../core/widget.h"
#include "../../core/timer.h"
#include "../../core/span_layout.h"
#include "../../core/font.h"
#include <functional>
class Scrollbar;
class TextEdit : public Widget
{
public:
TextEdit(Widget* parent);
~TextEdit();
bool IsReadOnly() const;
bool IsLowercase() const;
bool IsUppercase() const;
int GetMaxLength() const;
std::string GetText() const;
int GetLineCount() const;
std::string GetLineText(int line) const;
std::string GetSelection() const;
int GetSelectionStart() const;
int GetSelectionLength() const;
int GetCursorPos() const;
int GetCursorLineNumber() const;
double GetTotalHeight();
void SetSelectAllOnFocusGain(bool enable);
void SelectAll();
void SetReadOnly(bool enable = true);
void SetLowercase(bool enable = true);
void SetUppercase(bool enable = true);
void SetMaxLength(int length);
void SetText(const std::string& text);
void AddText(const std::string& text);
void SetSelection(int pos, int length);
void ClearSelection();
void SetCursorPos(int pos);
void DeleteSelectedText();
void SetInputMask(const std::string& mask);
void SetCursorDrawingEnabled(bool enable);
std::function<std::string(std::string text)> FuncFilterKeyChar;
std::function<void()> FuncBeforeEditChanged;
std::function<void()> FuncAfterEditChanged;
std::function<void()> FuncSelectionChanged;
std::function<void()> FuncFocusGained;
std::function<void()> FuncFocusLost;
std::function<void()> FuncEnterPressed;
protected:
void OnPaint(Canvas* canvas) override;
void OnMouseMove(const Point& pos) override;
bool OnMouseDown(const Point& pos, InputKey key) override;
bool OnMouseDoubleclick(const Point& pos, InputKey key) override;
bool OnMouseUp(const Point& pos, InputKey key) override;
void OnKeyChar(std::string chars) override;
void OnKeyDown(InputKey key) override;
void OnKeyUp(InputKey key) override;
void OnGeometryChanged() override;
void OnEnableChanged() override;
void OnSetFocus() override;
void OnLostFocus() override;
private:
void LayoutLines(Canvas* canvas);
void OnTimerExpired();
void OnScrollTimerExpired();
void CreateComponents();
void OnVerticalScroll();
void UpdateVerticalScroll();
void MoveVerticalScroll();
double GetTotalLineHeight();
struct Line
{
std::string text;
SpanLayout layout;
Rect box;
bool invalidated = true;
Line(const TextEdit *self)
{
layout.SetSelectionColors(self->selectionFG, self->selectionBG);
}
};
struct ivec2
{
ivec2() = default;
ivec2(int x, int y) : x(x), y(y) { }
int x = 0;
int y = 0;
bool operator==(const ivec2& b) const { return x == b.x && y == b.y; }
bool operator!=(const ivec2& b) const { return x != b.x || y != b.y; }
};
Colorf selectionBG, selectionFG;
Scrollbar* vert_scrollbar;
Timer* timer = nullptr;
std::vector<Line> lines = { Line{this} };
ivec2 cursor_pos = { 0, 0 };
int max_length = -1;
bool mouse_selecting = false;
bool lowercase = false;
bool uppercase = false;
bool readonly = false;
ivec2 selection_start = { -1, 0 };
int selection_length = 0;
std::string input_mask;
static std::string break_characters;
void Move(int steps, bool shift, bool ctrl);
void InsertText(ivec2 pos, const std::string& str);
void Backspace();
void Del();
ivec2 GetCharacterIndex(Point mouse_wincoords);
ivec2 FindNextBreakCharacter(ivec2 pos);
ivec2 FindPreviousBreakCharacter(ivec2 pos);
bool InputMaskAcceptsInput(ivec2 cursor_pos, const std::string& str);
std::string::size_type ToOffset(ivec2 pos) const;
ivec2 FromOffset(std::string::size_type offset) const;
VerticalTextPosition vertical_text_align;
Timer* scroll_timer = nullptr;
bool mouse_moves_left = false;
bool cursor_blink_visible = true;
unsigned int blink_timer = 0;
int clip_start_offset = 0;
int clip_end_offset = 0;
bool ignore_mouse_events = false;
struct UndoInfo
{
/* set undo text when:
- added char after moving
- destructive block operation (del, cut etc)
- beginning erase
*/
std::string undo_text;
bool first_erase = false;
bool first_text_insert = false;
} undo_info;
bool select_all_on_focus_gain = false;
std::shared_ptr<Font> font = Font::Create("NotoSans", 12.0);
template<typename T>
static T clamp(T val, T minval, T maxval) { return std::max<T>(std::min<T>(val, maxval), minval); }
};