From 7f64090401cc9e34cb71198f7b7899e0615be890 Mon Sep 17 00:00:00 2001
From: robfram <robfram@gmail.com>
Date: Mon, 9 Apr 2018 22:08:53 +0200
Subject: [PATCH] LineEdit placeholder alignment, content margins, and overflow
 bugs

LineEdit doesn't correctly uses style margins nor use placeholders
width correctly, causing multiple rendering bugs.

(cherry picked from commit 53b51f68bf9b6dd38014b5ac022209b8433d7340)
---
 scene/gui/line_edit.cpp | 20 ++++++++++++++++----
 scene/gui/line_edit.h   |  1 +
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 03dc6686b8b..d9bcf5b3fda 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -600,6 +600,7 @@ void LineEdit::_notification(int p_what) {
 			}
 
 			int x_ofs = 0;
+			int cached_text_width = text.empty() ? cached_placeholder_width : cached_width;
 
 			switch (align) {
 
@@ -613,15 +614,15 @@ void LineEdit::_notification(int p_what) {
 					if (window_pos != 0)
 						x_ofs = style->get_offset().x;
 					else
-						x_ofs = int(size.width - (cached_width)) / 2;
+						x_ofs = MAX(style->get_margin(MARGIN_LEFT), int(size.width - (cached_text_width)) / 2);
 				} break;
 				case ALIGN_RIGHT: {
 
-					x_ofs = int(size.width - style->get_offset().x - (cached_width));
+					x_ofs = MAX(style->get_margin(MARGIN_LEFT), int(size.width - style->get_margin(MARGIN_RIGHT) - (cached_text_width)));
 				} break;
 			}
 
-			int ofs_max = width - style->get_minimum_size().width;
+			int ofs_max = width - style->get_margin(MARGIN_RIGHT);
 			int char_ofs = window_pos;
 
 			int y_area = height - style->get_minimum_size().height;
@@ -879,7 +880,7 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) {
 		} break;
 		case ALIGN_RIGHT: {
 
-			pixel_ofs = int(size.width - style->get_offset().x - (cached_width));
+			pixel_ofs = int(size.width - style->get_margin(MARGIN_RIGHT) - (cached_width));
 		} break;
 	}
 
@@ -1012,6 +1013,15 @@ String LineEdit::get_text() const {
 void LineEdit::set_placeholder(String p_text) {
 
 	placeholder = tr(p_text);
+	if ((max_length <= 0) || (placeholder.length() <= max_length)) {
+		Ref<Font> font = get_font("font");
+		cached_placeholder_width = 0;
+		if (font != NULL) {
+			for (int i = 0; i < placeholder.length(); i++) {
+				cached_placeholder_width += font->get_char_size(placeholder[i]).width;
+			}
+		}
+	}
 	update();
 }
 
@@ -1125,6 +1135,7 @@ void LineEdit::clear_internal() {
 
 	_clear_undo_stack();
 	cached_width = 0;
+	cached_placeholder_width = 0;
 	cursor_pos = 0;
 	window_pos = 0;
 	undo_text = "";
@@ -1466,6 +1477,7 @@ LineEdit::LineEdit() {
 	_create_undo_state();
 	align = ALIGN_LEFT;
 	cached_width = 0;
+	cached_placeholder_width = 0;
 	cursor_pos = 0;
 	window_pos = 0;
 	window_has_focus = true;
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index e3ad3b17f1b..c60ea36cc1a 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -84,6 +84,7 @@ private:
 	int max_length; // 0 for no maximum
 
 	int cached_width;
+	int cached_placeholder_width;
 
 	struct Selection {