src/widget.cpp
branchnoai
changeset 9724 b39bc69bb2f2
parent 9723 eee46cb39750
child 9826 9707ad4c9b60
--- a/src/widget.cpp	Wed Jan 09 18:11:12 2008 +0000
+++ b/src/widget.cpp	Sun Feb 03 20:17:54 2008 +0000
@@ -4,13 +4,18 @@
 
 #include "stdafx.h"
 #include "openttd.h"
-#include "player.h"
-#include "table/sprites.h"
-#include "table/strings.h"
+#include "core/math_func.hpp"
+#include "player_func.h"
 #include "gfx_func.h"
 #include "window_gui.h"
 #include "window_func.h"
+#include "widgets/dropdown_func.h"
 
+#include "table/sprites.h"
+#include "table/strings.h"
+
+static const char *UPARROW   = "\xEE\x8A\xA0";
+static const char *DOWNARROW = "\xEE\x8A\xAA";
 
 static Point HandleScrollbarHittest(const Scrollbar *sb, int top, int bottom)
 {
@@ -208,13 +213,13 @@
 			/* show different image when clicked for WWT_IMGBTN_2 */
 			if ((wi->type & WWT_MASK) == WWT_IMGBTN_2 && clicked) img++;
 			DrawSprite(img, PAL_NONE, r.left + 1 + clicked, r.top + 1 + clicked);
-			goto draw_default;
+			break;
 		}
 
 		case WWT_PANEL: {
 			assert(wi->data == 0);
 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
-			goto draw_default;
+			break;
 		}
 
 		case WWT_TEXTBTN:
@@ -229,7 +234,7 @@
 			if ((wi->type & WWT_MASK) == WWT_TEXTBTN_2 && clicked) str++;
 
 			DrawStringCentered(((r.left + r.right + 1) >> 1) + clicked, ((r.top + r.bottom + 1) >> 1) - 5 + clicked, str, TC_FROMSTRING);
-			goto draw_default;
+			break;
 		}
 
 		case WWT_TEXT: {
@@ -244,7 +249,7 @@
 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, FR_LOWERED | FR_DARKENED);
 
 			if (str != STR_NULL) DrawStringTruncated(r.left + 2, r.top + 1, str, TC_FROMSTRING, r.right - r.left - 10);
-			goto draw_default;
+			break;
 		}
 
 		case WWT_MATRIX: {
@@ -288,7 +293,7 @@
 				GfxFillRect(r.left + 1, x, r.right - 1, x, color);
 			}
 
-			goto draw_default;
+			break;
 		}
 
 		/* vertical scrollbar */
@@ -424,7 +429,7 @@
 			GfxFillRect(r.left + 1, r.bottom - 1, r.right - 1, r.bottom - 1, c1);
 			GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2);
 
-			goto draw_default;
+			break;
 		}
 
 		case WWT_STICKYBOX: {
@@ -468,11 +473,34 @@
 			}
 
 			DrawStringCenteredTruncated(r.left + 2, r.right - 2, r.top + 2, wi->data, 0x84);
-draw_default:;
-			if (w->IsWidgetDisabled(i)) {
-				GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, _colour_gradient[wi->color & 0xF][2] | (1 << PALETTE_MODIFIER_GREYOUT));
-			}
+			break;
 		}
+
+		case WWT_DROPDOWN: {
+			assert(r.bottom - r.top == 11); // ensure consistent size
+
+			StringID str = wi->data;
+			DrawFrameRect(r.left, r.top, r.right - 12, r.bottom, wi->color, FR_NONE);
+			DrawFrameRect(r.right - 11, r.top, r.right, r.bottom, wi->color, clicked ? FR_LOWERED : FR_NONE);
+			DrawString(r.right - (clicked ? 8 : 9), r.top + (clicked ? 2 : 1), STR_0225, TC_BLACK);
+			if (str != STR_NULL) DrawStringTruncated(r.left + 2, r.top + 1, str, TC_BLACK, r.right - r.left - 12);
+			break;
+		}
+
+		case WWT_DROPDOWNIN: {
+			assert(r.bottom - r.top == 11); // ensure consistent size
+
+			StringID str = wi->data;
+			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, FR_LOWERED | FR_DARKENED);
+			DrawFrameRect(r.right - 11, r.top + 1, r.right - 1, r.bottom - 1, wi->color, clicked ? FR_LOWERED : FR_NONE);
+			DrawString(r.right - (clicked ? 8 : 9), r.top + (clicked ? 2 : 1), STR_0225, TC_BLACK);
+			if (str != STR_NULL) DrawStringTruncated(r.left + 2, r.top + 2, str, TC_BLACK, r.right - r.left - 12);
+			break;
+		}
+		}
+
+		if (w->IsWidgetDisabled(i)) {
+			GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, _colour_gradient[wi->color & 0xF][2] | (1 << PALETTE_MODIFIER_GREYOUT));
 		}
 	}
 
@@ -483,235 +511,6 @@
 
 }
 
-static const Widget _dropdown_menu_widgets[] = {
-{      WWT_PANEL,   RESIZE_NONE,     0,     0, 0,     0, 0, 0x0, STR_NULL},
-{  WWT_SCROLLBAR,   RESIZE_NONE,     0,     0, 0,     0, 0, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{   WIDGETS_END},
-};
-
-static int GetDropdownItem(const Window *w)
-{
-	byte item, counter;
-	int y;
-
-	if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) < 0)
-		return -1;
-
-	y = _cursor.pos.y - w->top - 2 + w->vscroll.pos * 10;
-
-	if (y < 0)
-		return - 1;
-
-	item = y / 10;
-	if (item >= WP(w, dropdown_d).num_items || (HasBit(WP(w,dropdown_d).disabled_state, item) && !HasBit(WP(w,dropdown_d).hidden_state, item)) || WP(w,dropdown_d).items[item] == 0)
-		return - 1;
-
-	/* Skip hidden items -- +1 for each hidden item before the clicked item. */
-	for (counter = 0; item >= counter; ++counter)
-		if (HasBit(WP(w, dropdown_d).hidden_state, counter)) item++;
-
-	return item;
-}
-
-static void DropdownMenuWndProc(Window *w, WindowEvent *e)
-{
-	int item;
-
-	switch (e->event) {
-		case WE_PAINT: {
-			int x,y,i,sel;
-			int width, height;
-
-			DrawWindowWidgets(w);
-
-			x = 1;
-			y = 2 - w->vscroll.pos * 10;
-
-			sel    = WP(w, dropdown_d).selected_index;
-			width  = w->widget[0].right - 3;
-			height = w->widget[0].bottom - 3;
-
-			for (i = 0; WP(w, dropdown_d).items[i] != INVALID_STRING_ID; i++, sel--) {
-				if (HasBit(WP(w, dropdown_d).hidden_state, i)) continue;
-
-				if (y >= 0 && y <= height) {
-					if (WP(w, dropdown_d).items[i] != STR_NULL) {
-						if (sel == 0) GfxFillRect(x + 1, y, x + width, y + 9, 0);
-						DrawStringTruncated(x + 2, y, WP(w, dropdown_d).items[i], sel == 0 ? TC_WHITE : TC_BLACK, x + width);
-
-						if (HasBit(WP(w, dropdown_d).disabled_state, i)) {
-							GfxFillRect(x, y, x + width, y + 9,
-								(1 << PALETTE_MODIFIER_GREYOUT) | _colour_gradient[_dropdown_menu_widgets[0].color][5]
-							);
-						}
-					} else {
-						int c1 = _colour_gradient[_dropdown_menu_widgets[0].color][3];
-						int c2 = _colour_gradient[_dropdown_menu_widgets[0].color][7];
-
-						GfxFillRect(x + 1, y + 3, x + w->width - 5, y + 3, c1);
-						GfxFillRect(x + 1, y + 4, x + w->width - 5, y + 4, c2);
-					}
-				}
-				y += 10;
-			}
-		} break;
-
-		case WE_CLICK: {
-			if (e->we.click.widget != 0) break;
-			item = GetDropdownItem(w);
-			if (item >= 0) {
-				WP(w, dropdown_d).click_delay = 4;
-				WP(w, dropdown_d).selected_index = item;
-				SetWindowDirty(w);
-			}
-		} break;
-
-		case WE_MOUSELOOP: {
-			Window *w2 = FindWindowById(WP(w, dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
-			if (w2 == NULL) {
-				DeleteWindow(w);
-				return;
-			}
-
-			if (WP(w, dropdown_d).click_delay != 0 && --WP(w,dropdown_d).click_delay == 0) {
-				WindowEvent e;
-				e.event = WE_DROPDOWN_SELECT;
-				e.we.dropdown.button = WP(w, dropdown_d).parent_button;
-				e.we.dropdown.index  = WP(w, dropdown_d).selected_index;
-				w2->wndproc(w2, &e);
-				DeleteWindow(w);
-				return;
-			}
-
-			if (WP(w, dropdown_d).drag_mode) {
-				item = GetDropdownItem(w);
-
-				if (!_left_button_clicked) {
-					WP(w, dropdown_d).drag_mode = false;
-					if (item < 0) return;
-					WP(w, dropdown_d).click_delay = 2;
-				} else {
-					if (item < 0) return;
-				}
-
-				WP(w, dropdown_d).selected_index = item;
-				SetWindowDirty(w);
-			}
-		} break;
-
-		case WE_DESTROY: {
-			Window *w2 = FindWindowById(WP(w, dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
-			if (w2 != NULL) {
-				w2->RaiseWidget(WP(w, dropdown_d).parent_button);
-				w2->InvalidateWidget(WP(w, dropdown_d).parent_button);
-			}
-		} break;
-	}
-}
-
-void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, uint32 hidden_mask)
-{
-	int i;
-	const Widget *wi;
-	Window *w2;
-	const Window *w3;
-	bool is_dropdown_menu_shown = w->IsWidgetLowered(button);
-	int top, height;
-	int screen_top, screen_bottom;
-	bool scroll = false;
-
-	DeleteWindowById(WC_DROPDOWN_MENU, 0);
-
-	if (is_dropdown_menu_shown) return;
-
-	w->LowerWidget(button);
-
-	w->InvalidateWidget(button);
-
-	for (i = 0; strings[i] != INVALID_STRING_ID; i++) {}
-	if (i == 0) return;
-
-	wi = &w->widget[button];
-
-	if (hidden_mask != 0) {
-		uint j;
-
-		for (j = 0; strings[j] != INVALID_STRING_ID; j++) {
-			if (HasBit(hidden_mask, j)) i--;
-		}
-	}
-
-	/* The preferred position is just below the dropdown calling widget */
-	top = w->top + wi->bottom + 2;
-	height = i * 10 + 4;
-
-	w3 = FindWindowById(WC_STATUS_BAR, 0);
-	screen_bottom = w3 == NULL ? _screen.height : w3->top;
-
-	/* Check if the dropdown will fully fit below the widget */
-	if (top + height >= screen_bottom) {
-		w3 = FindWindowById(WC_MAIN_TOOLBAR, 0);
-		screen_top = w3 == NULL ? 0 : w3->top + w3->height;
-
-		/* If not, check if it will fit above the widget */
-		if (w->top + wi->top - height - 1 > screen_top) {
-			top = w->top + wi->top - height - 1;
-		} else {
-			/* ... and lastly if it won't, enable the scroll bar and fit the
-			 * list in below the widget */
-			int rows = (screen_bottom - 4 - top) / 10;
-			height = rows * 10 + 4;
-			scroll = true;
-		}
-	}
-
-	w2 = AllocateWindow(
-		w->left + wi[-1].left + 1,
-		top,
-		wi->right - wi[-1].left + 1,
-		height,
-		DropdownMenuWndProc,
-		WC_DROPDOWN_MENU,
-		_dropdown_menu_widgets);
-
-	w2->widget[0].color = wi->color;
-	w2->widget[0].right = wi->right - wi[-1].left;
-	w2->widget[0].bottom = height - 1;
-
-	w2->SetWidgetHiddenState(1, !scroll);
-
-	if (scroll) {
-		/* We're scrolling, so enable the scroll bar and shrink the list by
-		 * the scrollbar's width */
-		w2->widget[1].color  = wi->color;
-		w2->widget[1].right  = w2->widget[0].right;
-		w2->widget[1].left   = w2->widget[1].right - 11;
-		w2->widget[1].bottom = height - 1;
-		w2->widget[0].right -= 12;
-
-		w2->vscroll.cap   = (height - 4) / 10;
-		w2->vscroll.count = i;
-	}
-
-	w2->desc_flags = WDF_DEF_WIDGET;
-	w2->flags4 &= ~WF_WHITE_BORDER_MASK;
-
-	WP(w2, dropdown_d).disabled_state = disabled_mask;
-	WP(w2, dropdown_d).hidden_state = hidden_mask;
-
-	WP(w2, dropdown_d).parent_wnd_class = w->window_class;
-	WP(w2, dropdown_d).parent_wnd_num = w->window_number;
-	WP(w2, dropdown_d).parent_button = button;
-
-	WP(w2, dropdown_d).num_items = i;
-	WP(w2, dropdown_d).selected_index = selected;
-	WP(w2, dropdown_d).items = strings;
-
-	WP(w2, dropdown_d).click_delay = 0;
-	WP(w2, dropdown_d).drag_mode = true;
-}
-
-
 static void ResizeWidgets(Window *w, byte a, byte b)
 {
 	int16 offset = w->widget[a].left;
@@ -783,3 +582,34 @@
 		}
 	}
 }
+
+void ResizeWindowForWidget(Window *w, int widget, int delta_x, int delta_y)
+{
+	int right  = w->widget[widget].right;
+	int bottom = w->widget[widget].bottom;
+
+	for (uint i = 0; i < w->widget_count; i++) {
+		if (w->widget[i].left >= right) w->widget[i].left += delta_x;
+		if (w->widget[i].right >= right) w->widget[i].right += delta_x;
+		if (w->widget[i].top >= bottom) w->widget[i].top += delta_y;
+		if (w->widget[i].bottom >= bottom) w->widget[i].bottom += delta_y;
+	}
+
+	w->width  += delta_x;
+	w->height += delta_y;
+	w->resize.width  += delta_x;
+	w->resize.height += delta_y;
+}
+
+/** Draw a sort button's up or down arrow symbol.
+ * @param w Window of widget
+ * @param widget Sort button widget
+ * @param state State of sort button
+ */
+void DrawSortButtonState(const Window *w, int widget, SortButtonState state)
+{
+	if (state == SBS_OFF) return;
+
+	int offset = w->IsWidgetLowered(widget) ? 1 : 0;
+	DoDrawString(state == SBS_DOWN ? DOWNARROW : UPARROW, w->widget[widget].right - 11 + offset, w->widget[widget].top + 1 + offset, TC_BLACK);
+}