mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-26 04:31:34 +08:00
Add support for password for input element. (#158)
This fixes: https://github.com/ArthurSonzogni/FTXUI/issues/139 CC:@Creapermann
This commit is contained in:
parent
5ee4ec40de
commit
b3a333b417
@ -10,23 +10,31 @@
|
|||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
std::wstring first_name_;
|
std::wstring first_name;
|
||||||
std::wstring last_name_;
|
std::wstring last_name;
|
||||||
|
std::wstring password;
|
||||||
|
|
||||||
Component input_first_name_ = Input(&first_name_, "first name");
|
|
||||||
Component input_last_name_ = Input(&last_name_, "last name");
|
Component input_first_name = Input(&first_name, "first name");
|
||||||
|
Component input_last_name = Input(&last_name, "last name");
|
||||||
|
|
||||||
|
InputOption password_option;
|
||||||
|
password_option.password = true;
|
||||||
|
Component input_password = Input(&password, "password", password_option);
|
||||||
|
|
||||||
auto component = Container::Vertical({
|
auto component = Container::Vertical({
|
||||||
input_first_name_,
|
input_first_name,
|
||||||
input_last_name_,
|
input_last_name,
|
||||||
|
input_password,
|
||||||
});
|
});
|
||||||
|
|
||||||
auto renderer = Renderer(component, [&] {
|
auto renderer = Renderer(component, [&] {
|
||||||
return vbox({
|
return vbox({
|
||||||
text(L"Hello " + first_name_ + L" " + last_name_),
|
text(L"Hello " + first_name + L" " + last_name),
|
||||||
separator(),
|
separator(),
|
||||||
hbox({text(L" First name : "), input_first_name_->Render()}),
|
hbox(text(L" First name : "), input_first_name->Render()),
|
||||||
hbox({text(L" Last name : "), input_last_name_->Render()}),
|
hbox(text(L" Last name : "), input_last_name->Render()),
|
||||||
|
hbox(text(L" Password : "), input_password->Render()),
|
||||||
}) |
|
}) |
|
||||||
border;
|
border;
|
||||||
});
|
});
|
||||||
|
@ -50,6 +50,9 @@ struct InputOption {
|
|||||||
/// Called when the user presses enter.
|
/// Called when the user presses enter.
|
||||||
std::function<void()> on_enter = [] {};
|
std::function<void()> on_enter = [] {};
|
||||||
|
|
||||||
|
/// Obscure the input content using '*'.
|
||||||
|
bool password = false;
|
||||||
|
|
||||||
Ref<int> cursor_position = 0;
|
Ref<int> cursor_position = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,9 +45,7 @@ struct Pixel {
|
|||||||
/// @brief Define how the Screen's dimensions should look like.
|
/// @brief Define how the Screen's dimensions should look like.
|
||||||
/// @ingroup screen
|
/// @ingroup screen
|
||||||
struct Dimension {
|
struct Dimension {
|
||||||
/// coucou
|
|
||||||
static Dimension Fixed(int);
|
static Dimension Fixed(int);
|
||||||
/// @brief coucou
|
|
||||||
static Dimension Fit(Element&);
|
static Dimension Fit(Element&);
|
||||||
static Dimension Full();
|
static Dimension Full();
|
||||||
|
|
||||||
|
@ -30,13 +30,18 @@ class InputBase : public ComponentBase {
|
|||||||
|
|
||||||
// Component implementation:
|
// Component implementation:
|
||||||
Element Render() override {
|
Element Render() override {
|
||||||
|
std::wstring password_content;
|
||||||
|
if (option_->password)
|
||||||
|
password_content = std::wstring(content_->size(), U'•');
|
||||||
|
std::wstring& content = option_->password ? password_content : *content_;
|
||||||
|
|
||||||
cursor_position() =
|
cursor_position() =
|
||||||
std::max(0, std::min<int>(content_->size(), cursor_position()));
|
std::max(0, std::min<int>(content.size(), cursor_position()));
|
||||||
auto main_decorator = flex | size(HEIGHT, EQUAL, 1);
|
auto main_decorator = flex | size(HEIGHT, EQUAL, 1);
|
||||||
bool is_focused = Focused();
|
bool is_focused = Focused();
|
||||||
|
|
||||||
// placeholder.
|
// placeholder.
|
||||||
if (content_->size() == 0) {
|
if (content.size() == 0) {
|
||||||
if (is_focused)
|
if (is_focused)
|
||||||
return text(*placeholder_) | focus | dim | inverted | main_decorator |
|
return text(*placeholder_) | focus | dim | inverted | main_decorator |
|
||||||
reflect(input_box_);
|
reflect(input_box_);
|
||||||
@ -46,15 +51,15 @@ class InputBase : public ComponentBase {
|
|||||||
|
|
||||||
// Not focused.
|
// Not focused.
|
||||||
if (!is_focused)
|
if (!is_focused)
|
||||||
return text(*content_) | main_decorator | reflect(input_box_);
|
return text(content) | main_decorator | reflect(input_box_);
|
||||||
|
|
||||||
std::wstring part_before_cursor = content_->substr(0, cursor_position());
|
std::wstring part_before_cursor = content.substr(0, cursor_position());
|
||||||
std::wstring part_at_cursor = cursor_position() < (int)content_->size()
|
std::wstring part_at_cursor = cursor_position() < (int)content.size()
|
||||||
? content_->substr(cursor_position(), 1)
|
? content.substr(cursor_position(), 1)
|
||||||
: L" ";
|
: L" ";
|
||||||
std::wstring part_after_cursor =
|
std::wstring part_after_cursor =
|
||||||
cursor_position() < (int)content_->size() - 1
|
cursor_position() < (int)content.size() - 1
|
||||||
? content_->substr(cursor_position() + 1)
|
? content.substr(cursor_position() + 1)
|
||||||
: L"";
|
: L"";
|
||||||
auto focused = is_focused ? focus : select;
|
auto focused = is_focused ? focus : select;
|
||||||
|
|
||||||
|
@ -35,6 +35,34 @@ TEST(InputTest, Type) {
|
|||||||
input->OnEvent(Event::Character('b'));
|
input->OnEvent(Event::Character('b'));
|
||||||
EXPECT_EQ(content, L"ab");
|
EXPECT_EQ(content, L"ab");
|
||||||
EXPECT_EQ(option.cursor_position(), 2u);
|
EXPECT_EQ(option.cursor_position(), 2u);
|
||||||
|
|
||||||
|
auto document = input->Render();
|
||||||
|
auto screen = Screen::Create(Dimension::Fit(document));
|
||||||
|
Render(screen, document);
|
||||||
|
EXPECT_EQ(screen.PixelAt(0, 0).character, L"a");
|
||||||
|
EXPECT_EQ(screen.PixelAt(1, 0).character, L"b");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InputTest, TypePassword) {
|
||||||
|
std::wstring content;
|
||||||
|
std::wstring placeholder;
|
||||||
|
auto option = InputOption();
|
||||||
|
option.password = true;
|
||||||
|
Component input = Input(&content, &placeholder, &option);
|
||||||
|
|
||||||
|
input->OnEvent(Event::Character('a'));
|
||||||
|
EXPECT_EQ(content, L"a");
|
||||||
|
EXPECT_EQ(option.cursor_position(), 1u);
|
||||||
|
|
||||||
|
input->OnEvent(Event::Character('b'));
|
||||||
|
EXPECT_EQ(content, L"ab");
|
||||||
|
EXPECT_EQ(option.cursor_position(), 2u);
|
||||||
|
|
||||||
|
auto document = input->Render();
|
||||||
|
auto screen = Screen::Create(Dimension::Fit(document));
|
||||||
|
Render(screen, document);
|
||||||
|
EXPECT_EQ(screen.PixelAt(0, 0).character, L"•");
|
||||||
|
EXPECT_EQ(screen.PixelAt(1, 0).character, L"•");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InputTest, Arrow) {
|
TEST(InputTest, Arrow) {
|
||||||
|
Loading…
Reference in New Issue
Block a user