26std::string PasswordField(
int size) {
28 out.reserve(2 *
size);
35class InputBase :
public ComponentBase {
37 InputBase(StringRef content,
38 ConstStringRef placeholder,
39 Ref<InputOption> option)
40 : content_(content), placeholder_(placeholder), option_(option) {}
42 int cursor_position_internal_ = 0;
43 int& cursor_position() {
44 int& opt = option_->cursor_position();
47 return cursor_position_internal_;
52 std::string password_content;
53 if (option_->password())
54 password_content = PasswordField(content_->size());
55 std::string& content = option_->password() ? password_content : *content_;
59 cursor_position() = std::max(0, std::min<int>(
size, cursor_position()));
61 bool is_focused = Focused();
65 bool hovered = hovered_;
69 if (hovered || is_focused)
71 return text(*placeholder_) | decorator |
reflect(box_);
79 return text(content) | main_decorator |
reflect(box_);
82 int index_before_cursor =
GlyphPosition(content, cursor_position());
83 int index_after_cursor =
GlyphPosition(content, 1, index_before_cursor);
84 std::string part_before_cursor = content.substr(0, index_before_cursor);
85 std::string part_at_cursor =
" ";
86 if (cursor_position() <
size) {
87 part_at_cursor = content.substr(index_before_cursor,
88 index_after_cursor - index_before_cursor);
90 std::string part_after_cursor = content.substr(index_after_cursor);
91 auto focused = (is_focused || hovered_) ?
focus :
select;
93 text(part_before_cursor),
95 text(part_after_cursor),
100 bool OnEvent(Event event)
override {
102 std::max(0, std::min<int>(content_->size(), cursor_position()));
104 if (event.is_mouse())
105 return OnMouseEvent(event);
111 if (cursor_position() == 0)
113 size_t start =
GlyphPosition(*content_, cursor_position() - 1);
115 content_->erase(start, end - start);
117 option_->on_change();
123 if (cursor_position() ==
int(content_->size()))
126 size_t end =
GlyphPosition(*content_, cursor_position() + 1);
127 content_->erase(start, end - start);
128 option_->on_change();
148 cursor_position() < (
int)content_->size()) {
154 cursor_position() = 0;
164 if (event.is_character()) {
166 content_->insert(start, event.character());
168 option_->on_change();
175 bool OnMouseEvent(Event event) {
177 box_.Contain(event.mouse().x, event.mouse().y) && CaptureMouse(event);
187 if (content_->size() == 0)
191 int original_glyph = cursor_position();
192 original_glyph = std::clamp(original_glyph, 0,
int(mapping.size()));
193 int original_cell = 0;
194 for (
size_t i = 0; i < mapping.size(); i++) {
195 if (mapping[i] == original_glyph) {
200 if (mapping[original_cell] != original_glyph)
201 original_cell = mapping.size();
202 int target_cell = original_cell +
event.mouse().x - cursor_box_.x_min;
203 int target_glyph = target_cell < (int)mapping.size() ? mapping[target_cell]
204 : (int)mapping.size();
205 target_glyph = std::clamp(target_glyph, 0,
GlyphCount(*content_));
206 if (cursor_position() != target_glyph) {
207 cursor_position() = target_glyph;
208 option_->on_change();
213 bool Focusable() const final {
return true; }
215 bool hovered_ =
false;
217 ConstStringRef placeholder_;
221 Ref<InputOption> option_;
227class WideInputBase :
public InputBase {
229 WideInputBase(WideStringRef content,
230 ConstStringRef placeholder,
231 Ref<InputOption> option)
232 : InputBase(&wrapped_content_, std::move(placeholder), std::move(option)),
233 content_(std::move(content)),
234 wrapped_content_(
to_string(*content_)) {}
238 return InputBase::Render();
241 bool OnEvent(Event event)
override {
243 if (InputBase::OnEvent(event)) {
250 WideStringRef content_;
251 std::string wrapped_content_;
An adapter. Own or reference a constant string. For convenience, this class convert multiple immutabl...
An adapter. Own or reference an mutable object.
An adapter. Own or reference a constant string. For convenience, this class convert multiple mutable ...
An adapter. Own or reference a constant string. For convenience, this class convert multiple mutable ...
std::function< Element(Element)> Decorator
Element flex(Element)
Make a child element to expand proportionnally to the space left in a container.
std::shared_ptr< T > Make(Args &&... args)
std::shared_ptr< Node > Element
Component Input(StringRef content, ConstStringRef placeholder, Ref< InputOption > option={})
An input box for editing text.
Element bold(Element)
Use a bold font, for elements with more emphasis.
Element hbox(Elements)
A container displaying elements horizontally one by one.
std::wstring to_wstring(const std::string &s)
Convert a std::wstring into a UTF8 std::string.
Element inverted(Element)
Add a filter that will invert the foreground and the background colors.
std::string to_string(const std::wstring &s)
Convert a UTF8 std::string into a std::wstring.
Element text(std::wstring text)
Display a piece of unicode text.
int GlyphPosition(const std::string &input, size_t glyph_index, size_t start=0)
std::vector< int > CellToGlyphIndex(const std::string &input)
int GlyphCount(const std::string &input)
Decorator reflect(Box &box)
Element dim(Element)
Use a light font, for elements with less emphasis.
Element frame(Element)
Allow an element to be displayed inside a 'virtual' area. It size can be larger than its container....
void Render(Screen &screen, const Element &node)
Display an element on a ftxui::Screen.
Decorator size(Direction, Constraint, int value)
Apply a constraint on the size of an element.
std::shared_ptr< ComponentBase > Component
static const Event Backspace
static const Event Return
static const Event ArrowLeft
static const Event Delete
static const Event ArrowRight