Skip to content

Commit

Permalink
Reimplement password box widget to avoid laying out text that will ne…
Browse files Browse the repository at this point in the history
…ver be rendered
  • Loading branch information
CelticMinstrel committed Aug 21, 2016
1 parent 149b477 commit 274dfca
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 115 deletions.
132 changes: 43 additions & 89 deletions src/gui/widgets/password_box.cpp
Expand Up @@ -24,6 +24,7 @@
#include "serialization/string_utils.hpp"
#include "serialization/unicode.hpp"

#include "desktop/clipboard.hpp"
#include "utils/functional.hpp"

#define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
Expand All @@ -36,111 +37,64 @@ namespace gui2

REGISTER_WIDGET3(ttext_box_definition, password_box, "text_box_definition")

namespace
{

size_t get_text_length(const std::string& str)
{
return utf8::size(str);
}

} // namespace

void tpassword_box::set_value(const std::string& text)
{
ttext_box::set_value(text);
real_value_ = get_value();
ttext_box::set_value(std::string(get_text_length(real_value_), '*'));
}

void tpassword_box::insert_char(const utf8::string& unicode)
{
pre_function();
ttext_box::insert_char(unicode);
post_function();
}

void tpassword_box::delete_char(const bool before_cursor)
{
pre_function();
ttext_box::delete_char(before_cursor);
post_function();
real_value_ = text;
size_t sz = utf8::size(text);
utf8::string passwd;
for(size_t i = 0; i < sz; i++) {
passwd.append("");
}
ttext_box::set_value(passwd);
}

void tpassword_box::handle_key_backspace(SDLMod /*modifier*/, bool& handled)
void tpassword_box::delete_selection()
{
pre_function();

// Copy & paste from ttext_::handle_key_backspace()
DBG_GUI_E << LOG_SCOPE_HEADER << '\n';

handled = true;
if(get_selection_length() != 0) {
delete_selection();
} else if(get_selection_start()) {
delete_char(true);
int len = get_selection_length();
if(len == 0) {
return;
}
unsigned start = get_selection_start();
if(len < 0) {
len = -len;
start -= len;
}

post_function();
utf8::erase(real_value_, start, len);
set_value(real_value_);
set_cursor(start, false);
}

void tpassword_box::handle_key_delete(SDLMod /*modifier*/, bool& handled)
void tpassword_box::insert_char(const utf8::string& unicode)
{
pre_function();

// Copy & paste from ttext_::handle_key_delete()
DBG_GUI_E << LOG_SCOPE_HEADER << '\n';

handled = true;
if(get_selection_length() != 0) {
delete_selection();
} else if(get_selection_start() < get_text_length(text())) {
delete_char(false);
int len = get_selection_length();
unsigned sel = get_selection_start();
if(len < 0) {
len = -len;
sel -= len;
}

post_function();
size_t sz = utf8::size(unicode);
if(sz == 1) {
ttext_box::insert_char("");
} else {
utf8::string passwd;
for(size_t i = 0; i < sz; i++) {
passwd.append("");
}
ttext_box::insert_char(passwd);
set_cursor(sel + sz, false);
}
utf8::insert(real_value_, sel, unicode);
}

void tpassword_box::paste_selection(const bool mouse)
{
pre_function();
ttext_box::paste_selection(mouse);
post_function();
}

void tpassword_box::pre_function()
{
// ttext_box::set_value() will reset the selection,
// we therefore have to remember it
size_t selection_start = get_selection_start();
size_t selection_length = get_selection_length();

// Tell ttext_box the actual input of this box
ttext_box::set_value(real_value_);

// Restore the selection
set_selection_start(selection_start);
set_selection_length(selection_length);
}

void tpassword_box::post_function()
{
// See above
size_t selection_start = get_selection_start();
size_t selection_length = get_selection_length();

// Get the input back and make ttext_box forget it
real_value_ = get_value();
ttext_box::set_value(std::string(get_text_length(real_value_), '*'));

// See above
set_selection_start(selection_start);
set_selection_length(selection_length);

// Why do the selection functions not update
// the canvas?
update_canvas();
set_is_dirty(true);
const std::string& text = desktop::clipboard::copy_from_clipboard(mouse);
if(text.empty()) {
return;
}
insert_char(text);
}

const std::string& tpassword_box::get_control_type() const
Expand Down
27 changes: 1 addition & 26 deletions src/gui/widgets/password_box.hpp
Expand Up @@ -34,25 +34,6 @@ namespace gui2

class tpassword_box : public ttext_box
{

// The hack works like this: we add the member real_value_
// that holds the actual user input.
// Overridden functions now simply
// - call set_value() from ttext_box with real_value_,
// which is done in prefunction()
// - call ttext_box::overridden_function()
// - set real_value_ to get_value() from ttext_box and
// call set_value() from ttext_box with real_value_
// turned into stars, which is done in post_function()
//
// and overridden function should therefore look like this:
//
// overridden_function(some parameter) {
// pre_function();
// ttext_box::overridden_function(some parameter);
// post_function();
// }

public:
tpassword_box() : ttext_box(), real_value_()
{
Expand All @@ -68,19 +49,13 @@ class tpassword_box : public ttext_box

protected:
void insert_char(const utf8::string& unicode);
void delete_char(const bool before_cursor);

void paste_selection(const bool mouse);
void delete_selection();

// We do not override copy_selection because we
// actually want it to copy just the stars

private:
void handle_key_backspace(SDLMod modifier, bool& handled);
void handle_key_delete(SDLMod modifier, bool& handled);

void pre_function();
void post_function();

std::string real_value_;

Expand Down

0 comments on commit 274dfca

Please sign in to comment.