فهرست منبع

Merge pull request #18491 from Calinou/custom-lineedit-secret-character

Make the LineEdit "secret" character customizable
Max Hilbrunner 7 سال پیش
والد
کامیت
79f9c3c2ab
3فایلهای تغییر یافته به همراه35 افزوده شده و 7 حذف شده
  1. 4 1
      doc/classes/LineEdit.xml
  2. 27 6
      scene/gui/line_edit.cpp
  3. 4 0
      scene/gui/line_edit.h

+ 4 - 1
doc/classes/LineEdit.xml

@@ -110,7 +110,10 @@
 			Text shown when the [LineEdit] is empty. It is [b]not[/b] the [LineEdit]'s default value (see [member text]).
 		</member>
 		<member name="secret" type="bool" setter="set_secret" getter="is_secret">
-			If [code]true[/code] every character is shown as "*".
+			If [code]true[/code], every character is replaced with the secret character (see [member secret_character]).
+		</member>
+		<member name="secret_character" type="string" setter="set_secret_character" getter="get_secret_character">
+			The character to use to mask secret input (defaults to "*"). Only a single character can be used as the secret character.
 		</member>
 		<member name="text" type="String" setter="set_text" getter="get_text">
 			String value of the [LineEdit].

+ 27 - 6
scene/gui/line_edit.cpp

@@ -663,8 +663,8 @@ void LineEdit::_notification(int p_what) {
 							if (ofs >= ime_text.length())
 								break;
 
-							CharType cchar = (pass && !text.empty()) ? '*' : ime_text[ofs];
-							CharType next = (pass && !text.empty()) ? '*' : ime_text[ofs + 1];
+							CharType cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs];
+							CharType next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1];
 							int im_char_width = font->get_char_size(cchar, next).width;
 
 							if ((x_ofs + im_char_width) > ofs_max)
@@ -685,8 +685,8 @@ void LineEdit::_notification(int p_what) {
 					}
 				}
 
-				CharType cchar = (pass && !text.empty()) ? '*' : t[char_ofs];
-				CharType next = (pass && !text.empty()) ? '*' : t[char_ofs + 1];
+				CharType cchar = (pass && !text.empty()) ? secret_character[0] : t[char_ofs];
+				CharType next = (pass && !text.empty()) ? secret_character[0] : t[char_ofs + 1];
 				int char_width = font->get_char_size(cchar, next).width;
 
 				// end of widget, break!
@@ -717,8 +717,8 @@ void LineEdit::_notification(int p_what) {
 						if (ofs >= ime_text.length())
 							break;
 
-						CharType cchar = (pass && !text.empty()) ? '*' : ime_text[ofs];
-						CharType next = (pass && !text.empty()) ? '*' : ime_text[ofs + 1];
+						CharType cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs];
+						CharType next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1];
 						int im_char_width = font->get_char_size(cchar, next).width;
 
 						if ((x_ofs + im_char_width) > ofs_max)
@@ -1225,6 +1225,7 @@ void LineEdit::select_all() {
 	selection.enabled = true;
 	update();
 }
+
 void LineEdit::set_editable(bool p_editable) {
 
 	editable = p_editable;
@@ -1241,11 +1242,27 @@ void LineEdit::set_secret(bool p_secret) {
 	pass = p_secret;
 	update();
 }
+
 bool LineEdit::is_secret() const {
 
 	return pass;
 }
 
+void LineEdit::set_secret_character(const String &p_string) {
+
+	// An empty string as the secret character would crash the engine
+	// It also wouldn't make sense to use multiple characters as the secret character
+	ERR_EXPLAIN("Secret character must be exactly one character long (" + itos(p_string.length()) + " characters given)");
+	ERR_FAIL_COND(p_string.length() != 1);
+
+	secret_character = p_string;
+	update();
+}
+
+String LineEdit::get_secret_character() const {
+	return secret_character;
+}
+
 void LineEdit::select(int p_from, int p_to) {
 
 	if (p_from == 0 && p_to == 0) {
@@ -1434,6 +1451,8 @@ void LineEdit::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("is_editable"), &LineEdit::is_editable);
 	ClassDB::bind_method(D_METHOD("set_secret", "enabled"), &LineEdit::set_secret);
 	ClassDB::bind_method(D_METHOD("is_secret"), &LineEdit::is_secret);
+	ClassDB::bind_method(D_METHOD("set_secret_character", "character"), &LineEdit::set_secret_character);
+	ClassDB::bind_method(D_METHOD("get_secret_character"), &LineEdit::get_secret_character);
 	ClassDB::bind_method(D_METHOD("menu_option", "option"), &LineEdit::menu_option);
 	ClassDB::bind_method(D_METHOD("get_menu"), &LineEdit::get_menu);
 	ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enable"), &LineEdit::set_context_menu_enabled);
@@ -1461,6 +1480,7 @@ void LineEdit::_bind_methods() {
 	ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "max_length"), "set_max_length", "get_max_length");
 	ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
 	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "secret"), "set_secret", "is_secret");
+	ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "secret_character"), "set_secret_character", "get_secret_character");
 	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand_to_text_length"), "set_expand_to_text_length", "get_expand_to_text_length");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
@@ -1485,6 +1505,7 @@ LineEdit::LineEdit() {
 	window_has_focus = true;
 	max_length = 0;
 	pass = false;
+	secret_character = "*";
 	text_changed_dirty = false;
 	placeholder_alpha = 0.6;
 

+ 4 - 0
scene/gui/line_edit.h

@@ -72,6 +72,7 @@ private:
 	String undo_text;
 	String text;
 	String placeholder;
+	String secret_character;
 	float placeholder_alpha;
 	String ime_text;
 	Point2 ime_selection;
@@ -194,6 +195,9 @@ public:
 	void set_secret(bool p_secret);
 	bool is_secret() const;
 
+	void set_secret_character(const String &p_string);
+	String get_secret_character() const;
+
 	virtual Size2 get_minimum_size() const;
 
 	void set_expand_to_text_length(bool p_enabled);