2
0
David Rose 24 жил өмнө
parent
commit
f7f4af2e49

+ 33 - 0
panda/src/pgui/pgEntry.I

@@ -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

+ 64 - 7
panda/src/pgui/pgEntry.cxx

@@ -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 &copy) :
   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 &copy) {
   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 &copy) {
   _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 &param, 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 &param, 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);
@@ -235,6 +249,16 @@ press(const MouseWatcherParameter &param, bool background) {
               string new_text = 
                 _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;
@@ -243,13 +267,13 @@ press(const MouseWatcherParameter &param, 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 &param, 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();
     }
 

+ 6 - 0
panda/src/pgui/pgEntry.h

@@ -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() {