30std::vector<std::string>
Split(
const std::string& input) {
31 std::vector<std::string>
output;
32 std::stringstream
ss(input);
34 while (std::getline(
ss, line)) {
37 if (input.back() ==
'\n') {
92class InputBase :
public ComponentBase,
public InputOption {
109 if (content->empty()) {
120 const std::vector<std::string> lines =
Split(*content);
122 cursor_position() =
util::clamp(cursor_position(), 0, (
int)content->size());
127 for (
const auto& line : lines) {
141 for (
size_t i = 0; i < lines.size(); ++i) {
142 const std::string& line = lines[i];
167 auto element =
hbox({
184 Element Text(
const std::string& input) {
190 out.reserve(10 + input.size() * 3 / 2);
191 for (
size_t i = 0; i < input.size(); ++i) {
198 if (cursor_position() == 0) {
202 const size_t end = cursor_position();
204 cursor_position() =
static_cast<int>(
start);
210 if (cursor_position() == (
int)content->size()) {
213 const size_t start = cursor_position();
214 const size_t end =
GlyphNext(content(), cursor_position());
228 if (cursor_position() == 0) {
233 static_cast<int>(
GlyphPrevious(content(), cursor_position()));
238 if (cursor_position() == (
int)content->size()) {
243 static_cast<int>(
GlyphNext(content(), cursor_position()));
248 size_t iter = cursor_position();
255 if (content()[
iter] ==
'\n') {
266 if (cursor_position() == (
int)content().
size() ||
267 content()[cursor_position()] ==
'\n') {
273 static_cast<int>(
GlyphNext(content(), cursor_position()));
278 if (cursor_position() == 0) {
286 if (cursor_position() == 0) {
293 cursor_position() =
static_cast<int>(
previous);
296 static_cast<int>(
GlyphPrevious(content(), cursor_position()));
298 if (cursor_position() == 0) {
305 cursor_position() =
static_cast<int>(
previous);
313 if (cursor_position() == (
int)content->size()) {
321 if (content()[cursor_position()] ==
'\n') {
325 static_cast<int>(
GlyphNext(content(), cursor_position()));
326 if (cursor_position() == (
int)content().size()) {
331 static_cast<int>(
GlyphNext(content(), cursor_position()));
338 cursor_position() = 0;
343 cursor_position() =
static_cast<int>(content->size());
356 if (!insert() && cursor_position() < (
int)content->size() &&
357 content()[cursor_position()] !=
'\n') {
360 content->insert(cursor_position(), character);
361 cursor_position() +=
static_cast<int>(character.size());
366 bool OnEvent(Event
event)
override {
367 cursor_position() =
util::clamp(cursor_position(), 0, (
int)content->size());
372 if (
event.is_character()) {
375 if (
event.is_mouse()) {
415 if (cursor_position() == 0) {
420 while (cursor_position()) {
425 cursor_position() =
static_cast<int>(
previous);
428 while (cursor_position()) {
433 cursor_position() =
static_cast<int>(
previous);
439 if (cursor_position() == (
int)content().
size()) {
444 while (cursor_position() < (
int)content().
size()) {
446 static_cast<int>(
GlyphNext(content(), cursor_position()));
452 while (cursor_position() < (
int)content().size()) {
457 cursor_position() =
static_cast<int>(
next);
464 hovered_ = box_.Contain(
event.mouse().x,
480 if (content->empty()) {
481 cursor_position() = 0;
486 std::vector<std::string> lines =
Split(*content);
489 for (
const auto& line : lines) {
518 cursor_position() = 0;
520 cursor_position() +=
static_cast<int>(lines[i].size() + 1);
524 static_cast<int>(
GlyphWidth(content(), cursor_position()));
526 static_cast<int>(
GlyphNext(content(), cursor_position()));
534 insert() = !insert();
540 bool hovered_ =
false;
600 option.content = std::move(content);
626 option.content = std::move(content);
627 option.placeholder = std::move(placeholder);
An adapter. Own or reference a constant string. For convenience, this class convert multiple mutable ...
constexpr const T & clamp(const T &v, const T &lo, const T &hi)
size_t GlyphNext(const std::string &input, size_t start)
Element focusCursorBarBlinking(Element)
Same as focus, but set the cursor shape to be a blinking bar.
Element xflex(Element)
Expand/Minimize if possible/needed on the X axis.
WordBreakProperty CodepointToWordBreakProperty(uint32_t codepoint)
Element nothing(Element element)
A decoration doing absolutely nothing.
Decorator size(WidthOrHeight, Constraint, int value)
Apply a constraint on the size of an element.
std::shared_ptr< Node > Element
std::shared_ptr< T > Make(Args &&... args)
std::shared_ptr< ComponentBase > Component
int string_width(const std::string &)
Element hbox(Elements)
A container displaying elements horizontally one by one.
Element text(std::wstring text)
Display a piece of unicode text.
std::vector< Element > Elements
Component Input(InputOption options={})
An input box for editing text.
bool EatCodePoint(const std::string &input, size_t start, size_t *end, uint32_t *ucs)
Element focus(Element)
Set the child to be the one focused among its siblings.
Decorator reflect(Box &box)
bool IsFullWidth(uint32_t ucs)
Element frame(Element)
Allow an element to be displayed inside a 'virtual' area. It size can be larger than its container....
Element focusCursorBlockBlinking(Element)
Same as focus, but set the cursor shape to be a blinking block.
size_t GlyphPrevious(const std::string &input, size_t start)
Element vbox(Elements)
A container displaying elements vertically one by one.
static const Event ArrowLeftCtrl
static const Event Backspace
static const Event ArrowUp
static const Event ArrowDown
static const Event Return
static const Event ArrowLeft
static const Event Delete
static const Event Insert
static const Event ArrowRightCtrl
static const Event ArrowRight