mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
add obscured mode
This commit is contained in:
parent
993b4582ad
commit
f7f4af2e49
@ -226,6 +226,39 @@ get_cursor_keys_active() const {
|
||||
return _cursor_keys_active;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGEntry::set_obscure_mode
|
||||
// Access: Published
|
||||
// Description: Specifies whether obscure mode should be enabled. In
|
||||
// obscure mode, a string of asterisks is displayed
|
||||
// instead of the literal text, e.g. for entering
|
||||
// passwords.
|
||||
//
|
||||
// In obscure mode, the width of the text is computed
|
||||
// based on the width of the string of asterisks, not on
|
||||
// the width of the actual text. This has implications
|
||||
// on the maximum length of text that may be entered if
|
||||
// max_width is in effect.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PGEntry::
|
||||
set_obscure_mode(bool flag) {
|
||||
if (_obscure_mode != flag) {
|
||||
_obscure_mode = flag;
|
||||
_text_geom_stale = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGEntry::get_obscure_mode
|
||||
// Access: Published
|
||||
// Description: Specifies whether obscure mode is enabled. See
|
||||
// set_obscure_mode().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PGEntry::
|
||||
get_obscure_mode() const {
|
||||
return _obscure_mode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGEntry::get_accept_prefix
|
||||
// Access: Published, Static
|
||||
|
@ -59,6 +59,7 @@ PGEntry(const string &name) : PGItem(name)
|
||||
_cursor_visible = true;
|
||||
|
||||
_cursor_keys_active = true;
|
||||
_obscure_mode = false;
|
||||
|
||||
set_active(true);
|
||||
update_state();
|
||||
@ -82,12 +83,15 @@ PGEntry::
|
||||
PGEntry(const PGEntry ©) :
|
||||
PGItem(copy),
|
||||
_text(copy._text),
|
||||
_obscured_text(copy._obscured_text),
|
||||
_cursor_position(copy._cursor_position),
|
||||
_max_chars(copy._max_chars),
|
||||
_max_width(copy._max_width),
|
||||
_text_defs(copy._text_defs),
|
||||
_blink_start(copy._blink_start),
|
||||
_blink_rate(copy._blink_rate)
|
||||
_blink_rate(copy._blink_rate),
|
||||
_cursor_keys_active(copy._cursor_keys_active),
|
||||
_obscure_mode(copy._obscure_mode)
|
||||
{
|
||||
_cursor_stale = true;
|
||||
_last_text_def = (TextNode *)NULL;
|
||||
@ -103,6 +107,7 @@ void PGEntry::
|
||||
operator = (const PGEntry ©) {
|
||||
PGItem::operator = (copy);
|
||||
_text = copy._text;
|
||||
_obscured_text = copy._obscured_text;
|
||||
_cursor_position = copy._cursor_position;
|
||||
_max_chars = copy._max_chars;
|
||||
_max_width = copy._max_width;
|
||||
@ -110,6 +115,9 @@ operator = (const PGEntry ©) {
|
||||
_blink_start = copy._blink_start;
|
||||
_blink_rate = copy._blink_rate;
|
||||
|
||||
_cursor_keys_active = copy._cursor_keys_active;
|
||||
_obscure_mode = copy._obscure_mode;
|
||||
|
||||
_cursor_stale = true;
|
||||
_text_geom_stale = true;
|
||||
}
|
||||
@ -180,6 +188,9 @@ press(const MouseWatcherParameter ¶m, bool background) {
|
||||
} else if (button == KeyboardButton::backspace()) {
|
||||
// Backspace. Remove the character to the left of the cursor.
|
||||
if (_cursor_position > 0) {
|
||||
if (_obscure_mode && _obscured_text.length() == _text.length()) {
|
||||
_obscured_text.erase(_obscured_text.begin() + _obscured_text.length() - 1);
|
||||
}
|
||||
_text.erase(_text.begin() + _cursor_position - 1);
|
||||
_cursor_position--;
|
||||
_cursor_stale = true;
|
||||
@ -190,6 +201,9 @@ press(const MouseWatcherParameter ¶m, bool background) {
|
||||
} else if (button == KeyboardButton::del()) {
|
||||
// Delete. Remove the character to the right of the cursor.
|
||||
if (_cursor_position < (int)_text.length()) {
|
||||
if (_obscure_mode && _obscured_text.length() == _text.length()) {
|
||||
_obscured_text.erase(_obscured_text.begin() + _obscured_text.length() - 1);
|
||||
}
|
||||
_text.erase(_text.begin() + _cursor_position);
|
||||
_text_geom_stale = true;
|
||||
erase(param);
|
||||
@ -236,6 +250,16 @@ press(const MouseWatcherParameter ¶m, bool background) {
|
||||
_text.substr(0, _cursor_position) + key +
|
||||
_text.substr(_cursor_position);
|
||||
|
||||
// Get a string to measure its length. In normal mode,
|
||||
// we measure the text itself. In obscure mode, we
|
||||
// measure a string of n asterisks.
|
||||
string measure_text;
|
||||
if (_obscure_mode) {
|
||||
measure_text = get_display_text() + '*';
|
||||
} else {
|
||||
measure_text = new_text;
|
||||
}
|
||||
|
||||
// Check the length.
|
||||
bool too_long = false;
|
||||
if (_max_width > 0.0) {
|
||||
@ -243,13 +267,13 @@ press(const MouseWatcherParameter ¶m, bool background) {
|
||||
if (_num_lines <= 1) {
|
||||
// If we have only one line, we can check the length
|
||||
// by simply measuring the width of the text.
|
||||
too_long = (text_node->calc_width(new_text) > _max_width);
|
||||
too_long = (text_node->calc_width(measure_text) > _max_width);
|
||||
|
||||
} else {
|
||||
// If we have multiple lines, we have to check the
|
||||
// length by wordwrapping it and counting up the
|
||||
// number of lines.
|
||||
string ww_text = text_node->wordwrap_to(new_text, _max_width, true);
|
||||
string ww_text = text_node->wordwrap_to(measure_text, _max_width, true);
|
||||
int num_lines = 1;
|
||||
size_t last_line_start = 0;
|
||||
for (size_t p = 0;
|
||||
@ -298,6 +322,9 @@ press(const MouseWatcherParameter ¶m, bool background) {
|
||||
|
||||
} else {
|
||||
_text = new_text;
|
||||
if (_obscure_mode) {
|
||||
_obscured_text = measure_text;
|
||||
}
|
||||
|
||||
_cursor_position++;
|
||||
_cursor_stale = true;
|
||||
@ -458,7 +485,6 @@ setup(float width, int num_lines) {
|
||||
// new RenderRelation(get_cursor_def(), text_node->generate());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGEntry::set_text_def
|
||||
// Access: Published
|
||||
@ -530,6 +556,34 @@ set_focus(bool focus) {
|
||||
update_state();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGEntry::get_display_text
|
||||
// Access: Private
|
||||
// Description: Returns the string that should be displayed within
|
||||
// the entry. This is normally _text, but it may be
|
||||
// _obscured_text.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const string &PGEntry::
|
||||
get_display_text() {
|
||||
if (_obscure_mode) {
|
||||
// If obscure mode is enabled, we should just display a bunch of
|
||||
// asterisks.
|
||||
if (_obscured_text.length() != _text.length()) {
|
||||
_obscured_text = "";
|
||||
string::const_iterator ti;
|
||||
for (ti = _text.begin(); ti != _text.end(); ++ti) {
|
||||
_obscured_text += '*';
|
||||
}
|
||||
}
|
||||
|
||||
return _obscured_text;
|
||||
|
||||
} else {
|
||||
// In normal, non-obscure mode, we display the actual text.
|
||||
return _text;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGEntry::slot_text_def
|
||||
// Access: Private
|
||||
@ -555,12 +609,15 @@ update_text() {
|
||||
nassertv(node != (TextNode *)NULL);
|
||||
|
||||
if (_text_geom_stale || node != _last_text_def) {
|
||||
const string &display_text = get_display_text();
|
||||
|
||||
// We need to regenerate.
|
||||
_last_text_def = node;
|
||||
|
||||
if (_max_width > 0.0 && _num_lines > 1) {
|
||||
// Fold the text into multiple lines.
|
||||
string ww_text = _last_text_def->wordwrap_to(_text, _max_width, true);
|
||||
string ww_text =
|
||||
_last_text_def->wordwrap_to(display_text, _max_width, true);
|
||||
|
||||
// And chop the lines up into pieces.
|
||||
_ww_lines.clear();
|
||||
@ -599,9 +656,9 @@ update_text() {
|
||||
_ww_lines.clear();
|
||||
_ww_lines.push_back(WWLine());
|
||||
WWLine &line = _ww_lines.back();
|
||||
line._str = _text;
|
||||
line._str = display_text;
|
||||
|
||||
_last_text_def->set_text(_text);
|
||||
_last_text_def->set_text(display_text);
|
||||
line._left = _last_text_def->get_left();
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,9 @@ PUBLISHED:
|
||||
INLINE void set_cursor_keys_active(bool flag);
|
||||
INLINE bool get_cursor_keys_active() const;
|
||||
|
||||
INLINE void set_obscure_mode(bool flag);
|
||||
INLINE bool get_obscure_mode() const;
|
||||
|
||||
void set_text_def(int state, TextNode *node);
|
||||
TextNode *get_text_def(int state) const;
|
||||
|
||||
@ -103,6 +106,7 @@ PUBLISHED:
|
||||
INLINE string get_erase_event() const;
|
||||
|
||||
private:
|
||||
const string &get_display_text();
|
||||
void slot_text_def(int state);
|
||||
void update_text();
|
||||
void update_cursor();
|
||||
@ -110,6 +114,7 @@ private:
|
||||
void update_state();
|
||||
|
||||
string _text;
|
||||
string _obscured_text;
|
||||
int _cursor_position;
|
||||
bool _cursor_stale;
|
||||
bool _cursor_visible;
|
||||
@ -152,6 +157,7 @@ private:
|
||||
double _blink_rate;
|
||||
|
||||
bool _cursor_keys_active;
|
||||
bool _obscure_mode;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user