src/window.cpp
branchnoai
changeset 9723 eee46cb39750
parent 9722 ebf0ece7d8f6
child 9724 b39bc69bb2f2
equal deleted inserted replaced
9722:ebf0ece7d8f6 9723:eee46cb39750
     4 
     4 
     5 #include "stdafx.h"
     5 #include "stdafx.h"
     6 #include <stdarg.h>
     6 #include <stdarg.h>
     7 #include "openttd.h"
     7 #include "openttd.h"
     8 #include "debug.h"
     8 #include "debug.h"
     9 #include "functions.h"
       
    10 #include "map.h"
       
    11 #include "player.h"
     9 #include "player.h"
    12 #include "window.h"
    10 #include "gfx_func.h"
    13 #include "gfx.h"
       
    14 #include "viewport.h"
       
    15 #include "console.h"
    11 #include "console.h"
       
    12 #include "viewport_func.h"
    16 #include "variables.h"
    13 #include "variables.h"
    17 #include "table/sprites.h"
    14 #include "table/sprites.h"
    18 #include "genworld.h"
    15 #include "genworld.h"
    19 #include "helpers.hpp"
       
    20 #include "blitter/factory.hpp"
    16 #include "blitter/factory.hpp"
       
    17 #include "window_gui.h"
       
    18 #include "zoom_func.h"
       
    19 #include "core/alloc_func.hpp"
       
    20 #include "map_func.h"
       
    21 #include "vehicle_base.h"
    21 
    22 
    22 /* delta between mouse cursor and upper left corner of dragged window */
    23 /* delta between mouse cursor and upper left corner of dragged window */
    23 static Point _drag_delta;
    24 static Point _drag_delta;
    24 
    25 
    25 static Window _windows[25];
    26 static Window _windows[MAX_NUMBER_OF_WINDOWS];
    26 Window *_z_windows[lengthof(_windows)];
    27 Window *_z_windows[lengthof(_windows)];
    27 Window **_last_z_window; ///< always points to the next free space in the z-array
    28 Window **_last_z_window; ///< always points to the next free space in the z-array
    28 
    29 
    29 void CDECL SetWindowWidgetsDisabledState(Window *w, bool disab_stat, int widgets, ...)
    30 void CDECL Window::SetWidgetsDisabledState(bool disab_stat, int widgets, ...)
    30 {
    31 {
    31 	va_list wdg_list;
    32 	va_list wdg_list;
    32 
    33 
    33 	va_start(wdg_list, widgets);
    34 	va_start(wdg_list, widgets);
    34 
    35 
    35 	while (widgets != WIDGET_LIST_END) {
    36 	while (widgets != WIDGET_LIST_END) {
    36 		SetWindowWidgetDisabledState(w, widgets, disab_stat);
    37 		SetWidgetDisabledState(widgets, disab_stat);
    37 		widgets = va_arg(wdg_list, int);
    38 		widgets = va_arg(wdg_list, int);
    38 	}
    39 	}
    39 
    40 
    40 	va_end(wdg_list);
    41 	va_end(wdg_list);
    41 }
    42 }
    42 
    43 
    43 void CDECL SetWindowWidgetsHiddenState(Window *w, bool hidden_stat, int widgets, ...)
    44 void CDECL Window::SetWidgetsHiddenState(bool hidden_stat, int widgets, ...)
    44 {
    45 {
    45 	va_list wdg_list;
    46 	va_list wdg_list;
    46 
    47 
    47 	va_start(wdg_list, widgets);
    48 	va_start(wdg_list, widgets);
    48 
    49 
    49 	while (widgets != WIDGET_LIST_END) {
    50 	while (widgets != WIDGET_LIST_END) {
    50 		SetWindowWidgetHiddenState(w, widgets, hidden_stat);
    51 		SetWidgetHiddenState(widgets, hidden_stat);
    51 		widgets = va_arg(wdg_list, int);
    52 		widgets = va_arg(wdg_list, int);
    52 	}
    53 	}
    53 
    54 
    54 	va_end(wdg_list);
    55 	va_end(wdg_list);
    55 }
    56 }
    56 
    57 
    57 void CDECL SetWindowWidgetsLoweredState(Window *w, bool lowered_stat, int widgets, ...)
    58 void CDECL Window::SetWidgetsLoweredState(bool lowered_stat, int widgets, ...)
    58 {
    59 {
    59 	va_list wdg_list;
    60 	va_list wdg_list;
    60 
    61 
    61 	va_start(wdg_list, widgets);
    62 	va_start(wdg_list, widgets);
    62 
    63 
    63 	while (widgets != WIDGET_LIST_END) {
    64 	while (widgets != WIDGET_LIST_END) {
    64 		SetWindowWidgetLoweredState(w, widgets, lowered_stat);
    65 		SetWidgetLoweredState(widgets, lowered_stat);
    65 		widgets = va_arg(wdg_list, int);
    66 		widgets = va_arg(wdg_list, int);
    66 	}
    67 	}
    67 
    68 
    68 	va_end(wdg_list);
    69 	va_end(wdg_list);
    69 }
    70 }
    70 
    71 
    71 void RaiseWindowButtons(Window *w)
    72 void Window::RaiseButtons()
    72 {
    73 {
    73 	uint i;
    74 	uint i;
    74 
    75 
    75 	for (i = 0; i < w->widget_count; i++) {
    76 	for (i = 0; i < this->widget_count; i++) {
    76 		if (IsWindowWidgetLowered(w, i)) {
    77 		if (this->IsWidgetLowered(i)) {
    77 			RaiseWindowWidget(w, i);
    78 			this->RaiseWidget(i);
    78 			InvalidateWidget(w, i);
    79 			this->InvalidateWidget(i);
    79 		}
    80 		}
    80 	}
    81 	}
    81 }
    82 }
    82 
    83 
    83 void HandleButtonClick(Window *w, byte widget)
    84 void Window::InvalidateWidget(byte widget_index) const
    84 {
    85 {
    85 	LowerWindowWidget(w, widget);
    86 	const Widget *wi = &this->widget[widget_index];
    86 	w->flags4 |= 5 << WF_TIMEOUT_SHL;
    87 
    87 	InvalidateWidget(w, widget);
    88 	/* Don't redraw the window if the widget is invisible or of no-type */
    88 }
    89 	if (wi->type == WWT_EMPTY || IsWidgetHidden(widget_index)) return;
    89 
    90 
       
    91 	SetDirtyBlocks(this->left + wi->left, this->top + wi->top, this->left + wi->right + 1, this->top + wi->bottom + 1);
       
    92 }
       
    93 
       
    94 void Window::HandleButtonClick(byte widget)
       
    95 {
       
    96 	this->LowerWidget(widget);
       
    97 	this->flags4 |= 5 << WF_TIMEOUT_SHL;
       
    98 	this->InvalidateWidget(widget);
       
    99 }
    90 
   100 
    91 static void StartWindowDrag(Window *w);
   101 static void StartWindowDrag(Window *w);
    92 static void StartWindowSizing(Window *w);
   102 static void StartWindowSizing(Window *w);
    93 
   103 
    94 static void DispatchLeftClickEvent(Window *w, int x, int y, bool double_click)
   104 static void DispatchLeftClickEvent(Window *w, int x, int y, bool double_click)
   103 	if (w->desc_flags & WDF_DEF_WIDGET) {
   113 	if (w->desc_flags & WDF_DEF_WIDGET) {
   104 		e.we.click.widget = GetWidgetFromPos(w, x, y);
   114 		e.we.click.widget = GetWidgetFromPos(w, x, y);
   105 		if (e.we.click.widget < 0) return; // exit if clicked outside of widgets
   115 		if (e.we.click.widget < 0) return; // exit if clicked outside of widgets
   106 
   116 
   107 		/* don't allow any interaction if the button has been disabled */
   117 		/* don't allow any interaction if the button has been disabled */
   108 		if (IsWindowWidgetDisabled(w, e.we.click.widget)) return;
   118 		if (w->IsWidgetDisabled(e.we.click.widget)) return;
   109 
   119 
   110 		wi = &w->widget[e.we.click.widget];
   120 		wi = &w->widget[e.we.click.widget];
   111 
   121 
   112 		if (wi->type & WWB_MASK) {
   122 		if (wi->type & WWB_MASK) {
   113 			/* special widget handling for buttons*/
   123 			/* special widget handling for buttons*/
   114 			switch (wi->type) {
   124 			switch (wi->type) {
   115 				case WWT_PANEL   | WWB_PUSHBUTTON: /* WWT_PUSHBTN */
   125 				case WWT_PANEL   | WWB_PUSHBUTTON: /* WWT_PUSHBTN */
   116 				case WWT_IMGBTN  | WWB_PUSHBUTTON: /* WWT_PUSHIMGBTN */
   126 				case WWT_IMGBTN  | WWB_PUSHBUTTON: /* WWT_PUSHIMGBTN */
   117 				case WWT_TEXTBTN | WWB_PUSHBUTTON: /* WWT_PUSHTXTBTN */
   127 				case WWT_TEXTBTN | WWB_PUSHBUTTON: /* WWT_PUSHTXTBTN */
   118 					HandleButtonClick(w, e.we.click.widget);
   128 					w->HandleButtonClick(e.we.click.widget);
   119 					break;
   129 					break;
   120 			}
   130 			}
   121 		} else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_SCROLL2BAR || wi->type == WWT_HSCROLLBAR) {
   131 		} else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_SCROLL2BAR || wi->type == WWT_HSCROLLBAR) {
   122 			ScrollbarClickHandler(w, wi, e.we.click.pt.x, e.we.click.pt.y);
   132 			ScrollbarClickHandler(w, wi, e.we.click.pt.x, e.we.click.pt.y);
   123 		}
   133 		}
   134 			}
   144 			}
   135 		}
   145 		}
   136 
   146 
   137 		if (w->desc_flags & WDF_RESIZABLE && wi->type == WWT_RESIZEBOX) {
   147 		if (w->desc_flags & WDF_RESIZABLE && wi->type == WWT_RESIZEBOX) {
   138 			StartWindowSizing(w);
   148 			StartWindowSizing(w);
   139 			InvalidateWidget(w, e.we.click.widget);
   149 			w->InvalidateWidget(e.we.click.widget);
   140 			return;
   150 			return;
   141 		}
   151 		}
   142 
   152 
   143 		if (w->desc_flags & WDF_STICKY_BUTTON && wi->type == WWT_STICKYBOX) {
   153 		if (w->desc_flags & WDF_STICKY_BUTTON && wi->type == WWT_STICKYBOX) {
   144 			w->flags4 ^= WF_STICKY;
   154 			w->flags4 ^= WF_STICKY;
   145 			InvalidateWidget(w, e.we.click.widget);
   155 			w->InvalidateWidget(e.we.click.widget);
   146 			return;
   156 			return;
   147 		}
   157 		}
   148 	}
   158 	}
   149 
   159 
   150 	w->wndproc(w, &e);
   160 	w->wndproc(w, &e);
   951 {
   961 {
   952 	Window* const *wz;
   962 	Window* const *wz;
   953 
   963 
   954 	for (wz = _last_z_window; wz != _z_windows;) {
   964 	for (wz = _last_z_window; wz != _z_windows;) {
   955 		Window *w = *--wz;
   965 		Window *w = *--wz;
   956 		if (IS_INSIDE_1D(x, w->left, w->width) && IS_INSIDE_1D(y, w->top, w->height)) {
   966 		if (IsInsideBS(x, w->left, w->width) && IsInsideBS(y, w->top, w->height)) {
   957 			return w;
   967 			return w;
   958 		}
   968 		}
   959 	}
   969 	}
   960 
   970 
   961 	return NULL;
   971 	return NULL;
  1017 	for (wz = _last_z_window; wz != _z_windows;) {
  1027 	for (wz = _last_z_window; wz != _z_windows;) {
  1018 		w = *--wz;
  1028 		w = *--wz;
  1019 
  1029 
  1020 		if (w->flags4&WF_TIMEOUT_MASK && !(--w->flags4&WF_TIMEOUT_MASK)) {
  1030 		if (w->flags4&WF_TIMEOUT_MASK && !(--w->flags4&WF_TIMEOUT_MASK)) {
  1021 			CallWindowEventNP(w, WE_TIMEOUT);
  1031 			CallWindowEventNP(w, WE_TIMEOUT);
  1022 			if (w->desc_flags & WDF_UNCLICK_BUTTONS) RaiseWindowButtons(w);
  1032 			if (w->desc_flags & WDF_UNCLICK_BUTTONS) w->RaiseButtons();
  1023 		}
  1033 		}
  1024 	}
  1034 	}
  1025 }
  1035 }
  1026 
  1036 
  1027 Window *GetCallbackWnd()
  1037 Window *GetCallbackWnd()
  1632 	e.event = WE_KEYPRESS;
  1642 	e.event = WE_KEYPRESS;
  1633 	e.we.keypress.key     = GB(key,  0, 16);
  1643 	e.we.keypress.key     = GB(key,  0, 16);
  1634 	e.we.keypress.keycode = GB(key, 16, 16);
  1644 	e.we.keypress.keycode = GB(key, 16, 16);
  1635 	e.we.keypress.cont = true;
  1645 	e.we.keypress.cont = true;
  1636 
  1646 
       
  1647 	/*
       
  1648 	 * The Unicode standard defines an area called the private use area. Code points in this
       
  1649 	 * area are reserved for private use and thus not portable between systems. For instance,
       
  1650 	 * Apple defines code points for the arrow keys in this area, but these are only printable
       
  1651 	 * on a system running OS X. We don't want these keys to show up in text fields and such,
       
  1652 	 * and thus we have to clear the unicode character when we encounter such a key.
       
  1653 	 */
       
  1654 	if (e.we.keypress.key >= 0xE000 && e.we.keypress.key <= 0xF8FF) e.we.keypress.key = 0;
       
  1655 
       
  1656 	/*
       
  1657 	 * If both key and keycode is zero, we don't bother to process the event.
       
  1658 	 */
       
  1659 	if (e.we.keypress.key == 0 && e.we.keypress.keycode == 0) return;
       
  1660 
  1637 	/* check if we have a query string window open before allowing hotkeys */
  1661 	/* check if we have a query string window open before allowing hotkeys */
  1638 	if (FindWindowById(WC_QUERY_STRING,       0) != NULL ||
  1662 	if (FindWindowById(WC_QUERY_STRING,            0) != NULL ||
  1639 			FindWindowById(WC_SEND_NETWORK_MSG,   0) != NULL ||
  1663 			FindWindowById(WC_SEND_NETWORK_MSG,        0) != NULL ||
  1640 			FindWindowById(WC_GENERATE_LANDSCAPE, 0) != NULL ||
  1664 			FindWindowById(WC_GENERATE_LANDSCAPE,      0) != NULL ||
  1641 			FindWindowById(WC_CONSOLE,            0) != NULL ||
  1665 			FindWindowById(WC_CONSOLE,                 0) != NULL ||
  1642 			FindWindowById(WC_SAVELOAD,           0) != NULL) {
  1666 			FindWindowById(WC_SAVELOAD,                0) != NULL ||
       
  1667 			FindWindowById(WC_COMPANY_PASSWORD_WINDOW, 0) != NULL) {
  1643 		query_open = true;
  1668 		query_open = true;
  1644 	}
  1669 	}
  1645 
  1670 
  1646 	/* Call the event, start with the uppermost window. */
  1671 	/* Call the event, start with the uppermost window. */
  1647 	for (wz = _last_z_window; wz != _z_windows;) {
  1672 	for (wz = _last_z_window; wz != _z_windows;) {
  1651 		if (query_open &&
  1676 		if (query_open &&
  1652 				w->window_class != WC_QUERY_STRING &&
  1677 				w->window_class != WC_QUERY_STRING &&
  1653 				w->window_class != WC_SEND_NETWORK_MSG &&
  1678 				w->window_class != WC_SEND_NETWORK_MSG &&
  1654 				w->window_class != WC_GENERATE_LANDSCAPE &&
  1679 				w->window_class != WC_GENERATE_LANDSCAPE &&
  1655 				w->window_class != WC_CONSOLE &&
  1680 				w->window_class != WC_CONSOLE &&
  1656 				w->window_class != WC_SAVELOAD) {
  1681 				w->window_class != WC_SAVELOAD &&
       
  1682 				w->window_class != WC_COMPANY_PASSWORD_WINDOW) {
  1657 			continue;
  1683 			continue;
  1658 		}
  1684 		}
  1659 		w->wndproc(w, &e);
  1685 		w->wndproc(w, &e);
  1660 		if (!e.we.keypress.cont) break;
  1686 		if (!e.we.keypress.cont) break;
  1661 	}
  1687 	}
  1923 		const Window *w = *wz;
  1949 		const Window *w = *wz;
  1924 		if (w->window_class == cls && w->window_number == number) SetWindowDirty(w);
  1950 		if (w->window_class == cls && w->window_number == number) SetWindowDirty(w);
  1925 	}
  1951 	}
  1926 }
  1952 }
  1927 
  1953 
  1928 void InvalidateWidget(const Window *w, byte widget_index)
       
  1929 {
       
  1930 	const Widget *wi = &w->widget[widget_index];
       
  1931 
       
  1932 	/* Don't redraw the window if the widget is invisible or of no-type */
       
  1933 	if (wi->type == WWT_EMPTY || IsWindowWidgetHidden(w, widget_index)) return;
       
  1934 
       
  1935 	SetDirtyBlocks(w->left + wi->left, w->top + wi->top, w->left + wi->right + 1, w->top + wi->bottom + 1);
       
  1936 }
       
  1937 
       
  1938 void InvalidateWindowWidget(WindowClass cls, WindowNumber number, byte widget_index)
  1954 void InvalidateWindowWidget(WindowClass cls, WindowNumber number, byte widget_index)
  1939 {
  1955 {
  1940 	Window* const *wz;
  1956 	Window* const *wz;
  1941 
  1957 
  1942 	FOR_ALL_WINDOWS(wz) {
  1958 	FOR_ALL_WINDOWS(wz) {
  1943 		const Window *w = *wz;
  1959 		const Window *w = *wz;
  1944 		if (w->window_class == cls && w->window_number == number) {
  1960 		if (w->window_class == cls && w->window_number == number) {
  1945 			InvalidateWidget(w, widget_index);
  1961 			w->InvalidateWidget(widget_index);
  1946 		}
  1962 		}
  1947 	}
  1963 	}
  1948 }
  1964 }
  1949 
  1965 
  1950 void InvalidateWindowClasses(WindowClass cls)
  1966 void InvalidateWindowClasses(WindowClass cls)
  2129 				continue;
  2145 				continue;
  2130 
  2146 
  2131 			default:
  2147 			default:
  2132 				left = w->left;
  2148 				left = w->left;
  2133 				if (left + (w->width >> 1) >= neww) left = neww - w->width;
  2149 				if (left + (w->width >> 1) >= neww) left = neww - w->width;
       
  2150 				if (left < 0) left = 0;
       
  2151 
  2134 				top = w->top;
  2152 				top = w->top;
  2135 				if (top + (w->height >> 1) >= newh) top = newh - w->height;
  2153 				if (top + (w->height >> 1) >= newh) top = newh - w->height;
       
  2154 				if (top < 0) top = 0;
  2136 				break;
  2155 				break;
  2137 		}
  2156 		}
  2138 
  2157 
  2139 		if (w->viewport != NULL) {
  2158 		if (w->viewport != NULL) {
  2140 			w->viewport->left += left - w->left;
  2159 			w->viewport->left += left - w->left;