changeset 9682:ed50c006a790 draft

(svn r13787) -Codechange: resize the red error message box if needed
author smatz <smatz@openttd.org>
date Tue, 22 Jul 2008 19:25:47 +0000
parents 434976ffd38e
children 17cf35beb54b
files src/gfx.cpp src/gfx_func.h src/misc_gui.cpp
diffstat 3 files changed, 77 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/gfx.cpp
+++ b/src/gfx.cpp
@@ -452,6 +452,52 @@
 	}
 }
 
+
+/** Calculates height of string (in pixels). Accepts multiline string with '\0' as separators.
+ * @param src string to check
+ * @param num number of extra lines (output of FormatStringLinebreaks())
+ * @note assumes text won't be truncated. FormatStringLinebreaks() is a good way to ensure that.
+ * @return height of pixels of string when it is drawn
+ */
+static int GetMultilineStringHeight(const char *src, int num)
+{
+	int maxy = 0;
+	int y = 0;
+	int fh = GetCharacterHeight(_cur_fontsize);
+
+	for (;;) {
+		WChar c = Utf8Consume(&src);
+
+		switch (c) {
+			case 0:            y += fh; if (--num < 0) return maxy; break;
+			case '\n':         y += fh;                             break;
+			case SCC_SETX:     src++;                               break;
+			case SCC_SETXY:    src++; y = (int)*src++;              break;
+			case SCC_TINYFONT: fh = GetCharacterHeight(FS_SMALL);   break;
+			case SCC_BIGFONT:  fh = GetCharacterHeight(FS_LARGE);   break;
+			default:           maxy = max<int>(maxy, y + fh);       break;
+		}
+	}
+}
+
+
+/** Calculates height of string (in pixels). The string is changed to a multiline string if needed.
+ * @param str string to check
+ * @param maxw maximum string width
+ * @return height of pixels of string when it is drawn
+ */
+int GetStringHeight(StringID str, int maxw)
+{
+	char buffer[512];
+
+	GetString(buffer, str, lastof(buffer));
+
+	uint32 tmp = FormatStringLinebreaks(buffer, maxw);
+
+	return GetMultilineStringHeight(buffer, GB(tmp, 0, 16));
+}
+
+
 /** Draw a given string with the centre around the given (x,y) coordinates
  * @param x Centre the string around this pixel width
  * @param y Centre the string around this pixel height
--- a/src/gfx_func.h
+++ b/src/gfx_func.h
@@ -105,6 +105,7 @@
 
 Dimension GetStringBoundingBox(const char *str);
 uint32 FormatStringLinebreaks(char *str, int maxw);
+int GetStringHeight(StringID str, int maxw);
 void LoadStringWidthTable();
 void DrawStringMultiCenter(int x, int y, StringID str, int maxw);
 uint DrawStringMultiLine(int x, int y, StringID str, int maxw, int maxh = -1);
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -378,14 +378,14 @@
 static const Widget _errmsg_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,     4,     0,    10,     0,    13, STR_00C5,         STR_018B_CLOSE_WINDOW},
 {    WWT_CAPTION,   RESIZE_NONE,     4,    11,   239,     0,    13, STR_00B2_MESSAGE, STR_NULL},
-{      WWT_PANEL,   RESIZE_NONE,     4,     0,   239,    14,    45, 0x0,              STR_NULL},
+{      WWT_PANEL,   RESIZE_BOTTOM,   4,     0,   239,    14,    45, 0x0,              STR_NULL},
 {    WIDGETS_END},
 };
 
 static const Widget _errmsg_face_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,     4,     0,    10,     0,    13, STR_00C5,              STR_018B_CLOSE_WINDOW},
 {    WWT_CAPTION,   RESIZE_NONE,     4,    11,   333,     0,    13, STR_00B3_MESSAGE_FROM, STR_NULL},
-{      WWT_PANEL,   RESIZE_NONE,     4,     0,   333,    14,   136, 0x0,                   STR_NULL},
+{      WWT_PANEL,   RESIZE_BOTTOM,   4,     0,   333,    14,   136, 0x0,                   STR_NULL},
 {   WIDGETS_END},
 };
 
@@ -397,6 +397,8 @@
 	StringID message_2;
 	bool show_player_face;
 
+	int y[2];
+
 public:
 	ErrmsgWindow(Point pt, int width, int height, StringID msg1, StringID msg2, const Widget *widget, bool show_player_face) :
 			Window(pt.x, pt.y, width, height, WC_ERRMSG, widget),
@@ -407,16 +409,35 @@
 		this->message_1 = msg1;
 		this->message_2 = msg2;
 		this->desc_flags = WDF_STD_BTN | WDF_DEF_WIDGET;
+
+		SwitchToErrorRefStack();
+		RewindTextRefStack();
+
+		assert(msg2 != INVALID_STRING_ID);
+
+		int h2 = 3 + GetStringHeight(msg2, width - 2); // msg2 is printed first
+		int h1 = (msg1 == INVALID_STRING_ID) ? 0 : 3 + GetStringHeight(msg1, width - 2);
+
+		SwitchToNormalRefStack();
+
+		int h = 15 + h1 + h2;
+		height = max<int>(height, h);
+
+		if (msg1 == INVALID_STRING_ID) {
+			// only 1 line will be printed
+			y[1] = (height - 15) / 2 + 15 - 5;
+		} else {
+			int over = (height - h) / 4;
+
+			y[1] = 15 + h2 / 2 + 1 - 5 + over;
+			y[0] = height - 3 - h1 / 2 - 5 - over;
+		}
+
 		this->FindWindowPlacementAndResize(width, height);
 	}
 
 	virtual void OnPaint()
 	{
-		static int y[][3] = {
-			{15, 25, 30}, // _errmsg_widgets
-			{45, 65, 90}, // _errmsg_face_widgets
-		};
-
 		CopyInDParam(0, this->decode_params, lengthof(this->decode_params));
 		this->DrawWidgets();
 		CopyInDParam(0, this->decode_params, lengthof(this->decode_params));
@@ -432,11 +453,8 @@
 			DrawPlayerFace(p->face, p->player_color, 2, 16);
 		}
 
-		byte j = (this->message_1 == INVALID_STRING_ID) ? 1 : 0;
-		DrawStringMultiCenter(this->width - 120, y[this->show_player_face][j], this->message_2, this->width - 2);
-		if (j == 0) {
-			DrawStringMultiCenter(this->width - 120, y[this->show_player_face][2], this->message_1, this->width - 2);
-		}
+		DrawStringMultiCenter(this->width - 120, y[1], this->message_2, this->width - 2);
+		if (this->message_1 != INVALID_STRING_ID) DrawStringMultiCenter(this->width - 120, y[0], this->message_1, this->width - 2);
 
 		/* Switch back to the normal text ref. stack for NewGRF texts */
 		SwitchToNormalRefStack();