24 #include "table/strings.h" 41 int rev_base = top + bottom;
44 button_size = NWidgetScrollbar::GetHorizontalDimension().width;
46 button_size = NWidgetScrollbar::GetVerticalDimension().height;
49 bottom -= button_size;
51 int height = (bottom - top);
56 if (count != 0) top += height * pos / count;
58 if (cap > count) cap = count;
59 if (count != 0) bottom -= (count - pos - cap) * height / count;
63 pt.x = rev_base - bottom;
64 pt.y = rev_base - top;
90 button_size = NWidgetScrollbar::GetHorizontalDimension().width;
93 button_size = NWidgetScrollbar::GetVerticalDimension().height;
95 if (pos < mi + button_size) {
98 if (_scroller_click_timeout <= 1) {
99 _scroller_click_timeout = 3;
103 }
else if (pos >= ma - button_size) {
107 if (_scroller_click_timeout <= 1) {
108 _scroller_click_timeout = 3;
117 }
else if (pos > pt.y) {
120 _scrollbar_start_pos = pt.x - mi - button_size;
121 _scrollbar_size = ma - mi - button_size * 2;
123 _cursorpos_drag_start = _cursor.
pos;
150 assert(scrollbar != NULL);
165 return (nw != NULL) ? nw->
index : -1;
179 assert(colour < COLOUR_END);
196 interior = (flags &
FR_DARKENED ? medium_dark : medium_light);
202 interior = medium_dark;
223 if ((type & WWT_MASK) ==
WWT_IMGBTN_2 && clicked) img++;
237 if (str == STR_NULL)
return;
240 int offset =
max(0, ((
int)(r.bottom - r.top + 1) - (
int)d.height) / 2);
253 int offset =
max(0, ((
int)(r.bottom - r.top + 1) - (
int)d.height) / 2);
254 if (str != STR_NULL)
DrawString(r.left, r.right, r.top + offset, str, colour);
278 static inline void DrawMatrix(
const Rect &r, Colours colour,
bool clicked, uint16 data, uint resize_x, uint resize_y)
284 if (num_columns == 0) {
285 column_width = resize_x;
286 num_columns = (r.right - r.left + 1) / column_width;
288 column_width = (r.right - r.left + 1) / num_columns;
294 row_height = resize_y;
295 num_rows = (r.bottom - r.top + 1) / row_height;
297 row_height = (r.bottom - r.top + 1) / num_rows;
303 for (
int ctr = num_columns; ctr > 1; ctr--) {
309 for (
int ctr = num_rows; ctr > 1; ctr--) {
317 for (
int ctr = num_columns; ctr > 1; ctr--) {
323 for (
int ctr = num_rows; ctr > 1; ctr--) {
340 int centre = (r.right - r.left) / 2;
341 int height = NWidgetScrollbar::GetVerticalDimension().height;
345 DrawSprite(SPR_ARROW_UP, PAL_NONE, r.left + 1 + up_clicked, r.top + 1 + up_clicked);
347 DrawFrameRect(r.left, r.bottom - (height - 1), r.right, r.bottom, colour, (down_clicked) ?
FR_LOWERED : FR_NONE);
348 DrawSprite(SPR_ARROW_DOWN, PAL_NONE, r.left + 1 + down_clicked, r.bottom - (height - 2) + down_clicked);
354 GfxFillRect(r.left, r.top + height, r.right, r.bottom - height, c2);
358 GfxFillRect(r.left + centre - 3, r.top + height, r.left + centre - 3, r.bottom - height, c1);
359 GfxFillRect(r.left + centre - 2, r.top + height, r.left + centre - 2, r.bottom - height, c2);
360 GfxFillRect(r.left + centre + 2, r.top + height, r.left + centre + 2, r.bottom - height, c1);
361 GfxFillRect(r.left + centre + 3, r.top + height, r.left + centre + 3, r.bottom - height, c2);
378 int centre = (r.bottom - r.top) / 2;
379 int width = NWidgetScrollbar::GetHorizontalDimension().width;
382 DrawSprite(SPR_ARROW_LEFT, PAL_NONE, r.left + 1 + left_clicked, r.top + 1 + left_clicked);
385 DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - (width - 2) + right_clicked, r.top + 1 + right_clicked);
391 GfxFillRect(r.left + width, r.top, r.right - width, r.bottom, c2);
395 GfxFillRect(r.left + width, r.top + centre - 3, r.right - width, r.top + centre - 3, c1);
396 GfxFillRect(r.left + width, r.top + centre - 2, r.right - width, r.top + centre - 2, c2);
397 GfxFillRect(r.left + width, r.top + centre + 2, r.right - width, r.top + centre + 2, c1);
398 GfxFillRect(r.left + width, r.top + centre + 3, r.right - width, r.top + centre + 3, c2);
427 GfxFillRect(r.left, r.top + dy1, r.left + 4, r.top + dy1, c1);
428 GfxFillRect(r.left + 1, r.top + dy2, r.left + 4, r.top + dy2, c2);
431 GfxFillRect(x2, r.top + dy1, r.right - 1, r.top + dy1, c1);
432 GfxFillRect(x2, r.top + dy2, r.right - 2, r.top + dy2, c2);
435 GfxFillRect(r.left, r.top + dy1, x2 - 2, r.top + dy1, c1);
436 GfxFillRect(r.left + 1, r.top + dy2, x2 - 2, r.top + dy2, c2);
439 GfxFillRect(r.right - 5, r.top + dy1, r.right - 1, r.top + dy1, c1);
440 GfxFillRect(r.right - 5, r.top + dy2, r.right - 2, r.top + dy2, c2);
444 GfxFillRect(r.left, r.top + dy2, r.left, r.bottom - 1, c1);
445 GfxFillRect(r.left + 1, r.top + dy2 + 1, r.left + 1, r.bottom - 2, c2);
448 GfxFillRect(r.right - 1, r.top + dy2, r.right - 1, r.bottom - 2, c1);
449 GfxFillRect(r.right, r.top + dy1, r.right, r.bottom - 1, c2);
451 GfxFillRect(r.left + 1, r.bottom - 1, r.right - 1, r.bottom - 1, c1);
452 GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2);
527 if (colour != COLOUR_WHITE)
DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, FR_NONE);
551 if (str != STR_NULL) {
553 int offset =
max(0, ((
int)(r.bottom - r.top + 1) - (
int)d.height) / 2);
574 int image_offset =
max(0, ((
int)(r.bottom - r.top + 1) - dd_height) / 2);
578 DrawFrameRect(r.right + 1 - dd_width, r.top, r.right, r.bottom, colour, clicked_dropdown ?
FR_LOWERED : FR_NONE);
579 DrawSprite(SPR_ARROW_DOWN, PAL_NONE, r.right - (dd_width - 2) + clicked_dropdown, r.top + image_offset + clicked_dropdown);
583 DrawFrameRect(r.left, r.top, r.left + dd_width - 1, r.bottom, colour, clicked_dropdown ?
FR_LOWERED : FR_NONE);
584 DrawSprite(SPR_ARROW_DOWN, PAL_NONE, r.left + 1 + clicked_dropdown, r.top + image_offset + clicked_dropdown);
615 const NWidgetBase *widget = this->GetWidget<NWidgetBase>(i);
616 if (widget == NULL || !widget->IsHighlighted())
continue;
620 int right = left + widget->
current_x - 1;
621 int bottom = top + widget->
current_y - 1;
623 int colour =
_string_colourmap[_window_highlight_colour ? widget->GetHighlightColour() : TC_WHITE];
643 const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(widget);
646 Dimension dim = NWidgetScrollbar::GetVerticalDimension();
649 int y = offset + nwid->
pos_y + (nwid->
current_y - dim.height) / 2;
660 return NWidgetScrollbar::GetVerticalDimension().width + 1;
797 return (this->
type == tp) ? this : NULL;
819 this->min_x =
max(this->min_x, min_x);
820 this->min_y =
max(this->min_y, min_y);
900 void NWidgetCore::FillNestedArray(
NWidgetBase **array, uint length)
902 if (this->
index >= 0 && (uint)(this->
index) < length) array[this->
index] =
this;
920 NWidgetContainer::~NWidgetContainer()
922 while (this->
head != NULL) {
932 if (this->
type == tp)
return this;
933 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
935 if (nwid != NULL)
return nwid;
946 assert(wid->
next == NULL && wid->
prev == NULL);
948 if (this->
head == NULL) {
952 assert(this->
tail != NULL);
961 void NWidgetContainer::FillNestedArray(
NWidgetBase **array, uint length)
963 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
964 child_wid->FillNestedArray(array, length);
976 void NWidgetStacked::SetIndex(
int index)
983 if (this->
index >= 0 && init_array) {
999 this->
fill_x = fill.width;
1000 this->
fill_y = fill.height;
1013 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1014 child_wid->SetupSmallestSize(w, init_array);
1016 this->
smallest_x =
max(this->
smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
1017 this->
smallest_y =
max(this->
smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
1032 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1033 uint hor_step = (sizing ==
ST_SMALLEST) ? 1 : child_wid->GetHorizontalStepSize(sizing);
1034 uint child_width =
ComputeMaxSize(child_wid->smallest_x, given_width - child_wid->padding_left - child_wid->padding_right, hor_step);
1035 uint child_pos_x = (rtl ? child_wid->padding_right : child_wid->padding_left);
1037 uint vert_step = (sizing ==
ST_SMALLEST) ? 1 : child_wid->GetVerticalStepSize(sizing);
1038 uint child_height =
ComputeMaxSize(child_wid->smallest_y, given_height - child_wid->padding_top - child_wid->padding_bottom, vert_step);
1039 uint child_pos_y = child_wid->padding_top;
1041 child_wid->AssignSizePosition(sizing, x + child_pos_x, y + child_pos_y, child_width, child_height, rtl);
1045 void NWidgetStacked::FillNestedArray(
NWidgetBase **array, uint length)
1047 if (this->
index >= 0 && (uint)(this->
index) < length) array[this->
index] =
this;
1048 NWidgetContainer::FillNestedArray(array, length);
1056 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; plane++, child_wid = child_wid->
next) {
1072 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; plane++, child_wid = child_wid->
next) {
1091 this->flags = flags;
1105 this->pip_pre = pip_pre;
1106 this->pip_inter = pip_inter;
1107 this->pip_post = pip_post;
1112 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1121 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1123 if (nwid != NULL)
return nwid;
1144 uint max_vert_fill = 0;
1145 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1146 child_wid->SetupSmallestSize(w, init_array);
1147 longest =
max(longest, child_wid->smallest_x);
1148 max_vert_fill =
max(max_vert_fill, child_wid->GetVerticalStepSize(
ST_SMALLEST));
1149 this->
smallest_y =
max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
1152 uint max_smallest = this->
smallest_y + 3 * max_vert_fill;
1155 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1156 uint step_size = child_wid->GetVerticalStepSize(
ST_SMALLEST);
1157 uint child_height = child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom;
1158 if (step_size > 1 && child_height < cur_height) {
1159 uint remainder = (cur_height - child_height) % step_size;
1160 if (remainder > 0) {
1161 cur_height += step_size - remainder;
1162 assert(cur_height < max_smallest);
1172 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1173 if (child_wid->fill_x == 1) child_wid->smallest_x = longest;
1178 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1179 if (child_wid->next != NULL) {
1180 child_wid->padding_right += this->
pip_inter;
1182 child_wid->padding_right += this->
pip_post;
1185 this->
smallest_x += child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right;
1186 if (child_wid->fill_x > 0) {
1187 if (this->
fill_x == 0 || this->
fill_x > child_wid->fill_x) this->
fill_x = child_wid->fill_x;
1191 if (child_wid->resize_x > 0) {
1205 uint additional_length = given_width;
1208 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1209 additional_length -= child_wid->smallest_x + child_wid->padding_right + child_wid->padding_left;
1231 int num_changing_childs = 0;
1232 uint biggest_stepsize = 0;
1233 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1234 uint hor_step = child_wid->GetHorizontalStepSize(sizing);
1236 num_changing_childs++;
1237 biggest_stepsize =
max(biggest_stepsize, hor_step);
1239 child_wid->current_x = child_wid->smallest_x;
1242 uint vert_step = (sizing ==
ST_SMALLEST) ? 1 : child_wid->GetVerticalStepSize(sizing);
1243 child_wid->current_y =
ComputeMaxSize(child_wid->smallest_y, given_height - child_wid->padding_top - child_wid->padding_bottom, vert_step);
1247 while (biggest_stepsize > 0) {
1248 uint next_biggest_stepsize = 0;
1249 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1250 uint hor_step = child_wid->GetHorizontalStepSize(sizing);
1251 if (hor_step > biggest_stepsize)
continue;
1252 if (hor_step == biggest_stepsize) {
1253 uint increment = additional_length / num_changing_childs;
1254 num_changing_childs--;
1255 if (hor_step > 1) increment -= increment % hor_step;
1256 child_wid->current_x = child_wid->smallest_x + increment;
1257 additional_length -= increment;
1260 next_biggest_stepsize =
max(next_biggest_stepsize, hor_step);
1262 biggest_stepsize = next_biggest_stepsize;
1264 assert(num_changing_childs == 0);
1267 uint position = rtl ? this->
current_x : 0;
1269 while (child_wid != NULL) {
1270 uint child_width = child_wid->
current_x;
1276 position = rtl ? position - padded_child_width : position + padded_child_width;
1278 child_wid = child_wid->
next;
1309 uint max_hor_fill = 0;
1310 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1311 child_wid->SetupSmallestSize(w, init_array);
1312 highest =
max(highest, child_wid->smallest_y);
1313 max_hor_fill =
max(max_hor_fill, child_wid->GetHorizontalStepSize(
ST_SMALLEST));
1314 this->
smallest_x =
max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
1317 uint max_smallest = this->
smallest_x + 3 * max_hor_fill;
1320 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1321 uint step_size = child_wid->GetHorizontalStepSize(
ST_SMALLEST);
1322 uint child_width = child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right;
1323 if (step_size > 1 && child_width < cur_width) {
1324 uint remainder = (cur_width - child_width) % step_size;
1325 if (remainder > 0) {
1326 cur_width += step_size - remainder;
1327 assert(cur_width < max_smallest);
1337 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1338 if (child_wid->fill_y == 1) child_wid->smallest_y = highest;
1343 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1344 if (child_wid->next != NULL) {
1345 child_wid->padding_bottom += this->
pip_inter;
1347 child_wid->padding_bottom += this->
pip_post;
1350 this->
smallest_y += child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom;
1351 if (child_wid->fill_y > 0) {
1352 if (this->
fill_y == 0 || this->
fill_y > child_wid->fill_y) this->
fill_y = child_wid->fill_y;
1356 if (child_wid->resize_y > 0) {
1370 uint additional_length = given_height;
1373 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1374 additional_length -= child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom;
1387 int num_changing_childs = 0;
1388 uint biggest_stepsize = 0;
1389 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1390 uint vert_step = child_wid->GetVerticalStepSize(sizing);
1391 if (vert_step > 0) {
1392 num_changing_childs++;
1393 biggest_stepsize =
max(biggest_stepsize, vert_step);
1395 child_wid->current_y = child_wid->smallest_y;
1398 uint hor_step = (sizing ==
ST_SMALLEST) ? 1 : child_wid->GetHorizontalStepSize(sizing);
1399 child_wid->current_x =
ComputeMaxSize(child_wid->smallest_x, given_width - child_wid->padding_left - child_wid->padding_right, hor_step);
1403 while (biggest_stepsize > 0) {
1404 uint next_biggest_stepsize = 0;
1405 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1406 uint vert_step = child_wid->GetVerticalStepSize(sizing);
1407 if (vert_step > biggest_stepsize)
continue;
1408 if (vert_step == biggest_stepsize) {
1409 uint increment = additional_length / num_changing_childs;
1410 num_changing_childs--;
1411 if (vert_step > 1) increment -= increment % vert_step;
1412 child_wid->current_y = child_wid->smallest_y + increment;
1413 additional_length -= increment;
1416 next_biggest_stepsize =
max(next_biggest_stepsize, vert_step);
1418 biggest_stepsize = next_biggest_stepsize;
1420 assert(num_changing_childs == 0);
1424 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1425 uint child_x = x + (rtl ? child_wid->padding_right : child_wid->padding_left);
1426 uint child_height = child_wid->current_y;
1428 child_wid->AssignSizePosition(sizing, child_x, y + position + child_wid->padding_top, child_wid->current_x, child_height, rtl);
1429 position += child_height + child_wid->padding_top + child_wid->padding_bottom;
1450 void NWidgetSpacer::FillNestedArray(
NWidgetBase **array, uint length)
1473 void NWidgetMatrix::SetIndex(
int index)
1475 this->index = index;
1478 void NWidgetMatrix::SetColour(Colours colour)
1480 this->colour = colour;
1489 this->clicked = clicked;
1490 if (this->clicked >= 0 && this->sb != NULL && this->widgets_x != 0) {
1491 int vpos = (this->clicked / this->widgets_x) * this->widget_h;
1494 if (this->sb->GetPosition() < vpos) vpos += this->widget_h - this->pip_inter - 1;
1495 this->sb->ScrollTowards(vpos);
1506 this->count = count;
1508 if (this->sb == NULL || this->widgets_x == 0)
return;
1515 count =
CeilDiv(count, this->sb->IsVertical() ? this->widgets_x : this->widgets_y);
1516 count *= (this->sb->IsVertical() ? this->head->smallest_y : this->head->smallest_x) + this->pip_inter;
1517 if (count > 0) count -= this->pip_inter;
1518 count += this->pip_pre + this->pip_post;
1519 this->sb->SetCount(count);
1521 this->sb->SetStepSize(this->sb->IsVertical() ? this->widget_h : this->widget_w);
1535 assert(this->head != NULL);
1536 assert(this->head->next == NULL);
1538 if (this->index >= 0 && init_array) {
1547 this->head->SetupSmallestSize(w, init_array);
1549 Dimension padding = { (uint)this->pip_pre + this->pip_post, (uint)this->pip_pre + this->pip_post};
1550 Dimension size = {this->head->smallest_x + padding.width, this->head->smallest_y + padding.height};
1552 Dimension resize = {this->pip_inter + this->head->smallest_x, this->pip_inter + this->head->smallest_y};
1554 if (this->index >= 0) w->
UpdateWidgetSize(this->index, &size, padding, &fill, &resize);
1558 this->
fill_x = fill.width;
1559 this->
fill_y = fill.height;
1574 this->widget_w = this->head->smallest_x + this->pip_inter;
1575 this->widget_h = this->head->smallest_y + this->pip_inter;
1579 this->widgets_x =
CeilDiv(this->
current_x - this->pip_pre - this->pip_post + this->pip_inter, this->widget_w);
1580 this->widgets_y =
CeilDiv(this->
current_y - this->pip_pre - this->pip_post + this->pip_inter, this->widget_h);
1585 this->SetCount(this->count);
1588 void NWidgetMatrix::FillNestedArray(
NWidgetBase **array, uint length)
1590 if (this->index >= 0 && (uint)(this->index) < length) array[this->index] =
this;
1591 NWidgetContainer::FillNestedArray(array, length);
1599 int start_x, start_y, base_offs_x, base_offs_y;
1600 this->GetScrollOffsets(start_x, start_y, base_offs_x, base_offs_y);
1604 int widget_col = (rtl ?
1605 -x + (int)this->pip_post + (
int)this->
pos_x + base_offs_x + (int)this->widget_w - 1 - (
int)this->pip_inter :
1606 x - (int)this->pip_pre - (
int)this->
pos_x - base_offs_x
1609 int widget_row = (y - base_offs_y - (int)this->pip_pre - (
int)this->
pos_y) / this->widget_h;
1611 int sub_wid = (widget_row + start_y) * this->widgets_x + start_x + widget_col;
1612 if (sub_wid >= this->count)
return NULL;
1615 assert(child != NULL);
1617 this->
pos_x + (rtl ? this->pip_post - widget_col * this->widget_w : this->pip_pre + widget_col * this->widget_w) + base_offs_x,
1618 this->
pos_y + this->pip_pre + widget_row * this->widget_h + base_offs_y,
1621 SB(child->
index, 16, 16, sub_wid);
1634 if (!
FillDrawPixelInfo(&tmp_dpi, this->
pos_x + (rtl ? this->pip_post : this->pip_pre), this->
pos_y + this->pip_pre, this->
current_x - this->pip_pre - this->pip_post, this->
current_y - this->pip_pre - this->pip_post))
return;
1636 _cur_dpi = &tmp_dpi;
1640 assert(child != NULL);
1641 int start_x, start_y, base_offs_x, base_offs_y;
1642 this->GetScrollOffsets(start_x, start_y, base_offs_x, base_offs_y);
1644 int offs_y = base_offs_y;
1645 for (
int y = start_y; y < start_y + this->widgets_y + 1; y++, offs_y += this->widget_h) {
1647 if (offs_y + child->
smallest_y <= 0)
continue;
1648 if (offs_y >= (
int)this->
current_y)
break;
1651 if (y * this->widgets_x >= this->count)
break;
1653 int offs_x = base_offs_x;
1654 for (
int x = start_x; x < start_x + this->widgets_x + 1; x++, offs_x += rtl ? -this->widget_w : this->widget_w) {
1656 if (offs_x + child->
smallest_x <= 0)
continue;
1657 if (offs_x >= (
int)this->
current_x)
continue;
1660 int sub_wid = y * this->widgets_x + x;
1661 if (sub_wid >= this->count)
break;
1665 SB(child->
index, 16, 16, sub_wid);
1687 if (this->sb != NULL) {
1688 if (this->sb->IsVertical()) {
1689 start_y = this->sb->GetPosition() / this->widget_h;
1690 base_offs_y += -this->sb->GetPosition() + start_y * this->widget_h;
1692 start_x = this->sb->GetPosition() / this->widget_w;
1693 int sub_x = this->sb->GetPosition() - start_x * this->widget_w;
1695 base_offs_x += sub_x;
1697 base_offs_x -= sub_x;
1715 if (index >= 0) this->
SetIndex(index);
1716 this->child =
child;
1719 NWidgetBackground::~NWidgetBackground()
1733 if (this->
child == NULL) {
1751 if (this->
child == NULL) {
1754 this->
child->
SetPIP(pip_pre, pip_inter, pip_post);
1759 if (init_array && this->
index >= 0) {
1763 if (this->
child != NULL) {
1795 d =
maxdim(d, background);
1797 if (this->
index >= 0) {
1798 static const Dimension padding = {0, 0};
1804 this->
fill_x = fill.width;
1805 this->fill_y = fill.height;
1807 this->resize_y = resize.height;
1815 if (this->
child != NULL) {
1823 void NWidgetBackground::FillNestedArray(
NWidgetBase **array, uint length)
1825 if (this->
index >= 0 && (uint)(this->
index) < length) array[this->
index] =
this;
1826 if (this->
child != NULL) this->
child->FillNestedArray(array, length);
1834 r.left = this->
pos_x;
1836 r.top = this->
pos_y;
1840 if (dpi->left > r.right || dpi->left + dpi->width <= r.left || dpi->top > r.bottom || dpi->top + dpi->height <= r.top)
return;
1842 switch (this->
type) {
1875 if (nwid == NULL) nwid =
this;
1884 if (nwid == NULL && this->
type == tp) nwid =
this;
1895 if (init_array && this->
index >= 0) {
1962 if (pos != INT_MAX) pos += this->GetPosition();
1963 return (pos >= this->GetCount()) ? INT_MAX : pos;
1976 if (this->IsVertical()) {
1997 if (init_array && this->
index >= 0) {
2004 switch (this->
type) {
2006 this->
SetMinimalSize(NWidgetScrollbar::GetHorizontalDimension().width * 3, NWidgetScrollbar::GetHorizontalDimension().height);
2009 this->
SetDataTip(0x0, STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST);
2013 this->
SetMinimalSize(NWidgetScrollbar::GetVerticalDimension().width, NWidgetScrollbar::GetVerticalDimension().height * 3);
2016 this->
SetDataTip(0x0, STR_TOOLTIP_VSCROLL_BAR_SCROLLS_LIST);
2019 default: NOT_REACHED();
2031 r.left = this->
pos_x;
2033 r.top = this->
pos_y;
2037 if (dpi->left > r.right || dpi->left + dpi->width <= r.left || dpi->top > r.bottom || dpi->top + dpi->height <= r.top)
return;
2054 void NWidgetScrollbar::InvalidateDimensionCache()
2060 Dimension NWidgetScrollbar::GetVerticalDimension()
2071 Dimension NWidgetScrollbar::GetHorizontalDimension()
2088 shadebox_dimension.width = shadebox_dimension.height = 0;
2089 debugbox_dimension.width = debugbox_dimension.height = 0;
2090 defsizebox_dimension.width = defsizebox_dimension.height = 0;
2091 stickybox_dimension.width = stickybox_dimension.height = 0;
2092 resizebox_dimension.width = resizebox_dimension.height = 0;
2093 closebox_dimension.width = closebox_dimension.height = 0;
2094 dropdown_dimension.width = dropdown_dimension.height = 0;
2116 if (index >= 0) this->
SetIndex(index);
2136 case NWID_PUSHBUTTON_DROPDOWN:
2150 this->
SetDataTip(data, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS);
2156 this->
SetDataTip(STR_NULL, STR_TOOLTIP_STICKY);
2162 this->
SetDataTip(STR_NULL, STR_TOOLTIP_SHADE);
2168 this->
SetDataTip(STR_NULL, STR_TOOLTIP_DEBUG);
2174 this->
SetDataTip(STR_NULL, STR_TOOLTIP_DEFSIZE);
2180 this->
SetDataTip(STR_NULL, STR_TOOLTIP_RESIZE);
2186 this->
SetDataTip(STR_NULL, STR_TOOLTIP_CLOSE_WINDOW);
2201 if (this->
index >= 0 && init_array) {
2211 switch (this->
type) {
2225 if (NWidgetLeaf::shadebox_dimension.width == 0) {
2227 NWidgetLeaf::shadebox_dimension.width += extra.width;
2228 NWidgetLeaf::shadebox_dimension.height += extra.height;
2230 size =
maxdim(size, NWidgetLeaf::shadebox_dimension);
2237 if (NWidgetLeaf::debugbox_dimension.width == 0) {
2238 NWidgetLeaf::debugbox_dimension =
GetSpriteSize(SPR_WINDOW_DEBUG);
2239 NWidgetLeaf::debugbox_dimension.width += extra.width;
2240 NWidgetLeaf::debugbox_dimension.height += extra.height;
2242 size =
maxdim(size, NWidgetLeaf::debugbox_dimension);
2254 if (NWidgetLeaf::stickybox_dimension.width == 0) {
2256 NWidgetLeaf::stickybox_dimension.width += extra.width;
2257 NWidgetLeaf::stickybox_dimension.height += extra.height;
2259 size =
maxdim(size, NWidgetLeaf::stickybox_dimension);
2266 if (NWidgetLeaf::defsizebox_dimension.width == 0) {
2267 NWidgetLeaf::defsizebox_dimension =
GetSpriteSize(SPR_WINDOW_DEFSIZE);
2268 NWidgetLeaf::defsizebox_dimension.width += extra.width;
2269 NWidgetLeaf::defsizebox_dimension.height += extra.height;
2271 size =
maxdim(size, NWidgetLeaf::defsizebox_dimension);
2278 if (NWidgetLeaf::resizebox_dimension.width == 0) {
2280 NWidgetLeaf::resizebox_dimension.width += extra.width;
2281 NWidgetLeaf::resizebox_dimension.height += extra.height;
2283 size =
maxdim(size, NWidgetLeaf::resizebox_dimension);
2288 size.width =
max(size.width, 30 + sprite_size.width);
2304 d2.width += extra.width;
2305 d2.height += extra.height;
2314 d2.width += extra.width;
2315 d2.height += extra.height;
2323 if (NWidgetLeaf::closebox_dimension.width == 0) {
2324 NWidgetLeaf::closebox_dimension =
GetSpriteSize(SPR_CLOSEBOX);
2325 NWidgetLeaf::closebox_dimension.width += extra.width;
2326 NWidgetLeaf::closebox_dimension.height += extra.height;
2328 size =
maxdim(size, NWidgetLeaf::closebox_dimension);
2338 d2.width += extra.width;
2339 d2.height += extra.height;
2356 d2.width += extra.width;
2357 d2.height += extra.height;
2363 case NWID_PUSHBUTTON_DROPDOWN: {
2366 if (NWidgetLeaf::dropdown_dimension.width == 0) {
2367 NWidgetLeaf::dropdown_dimension =
GetSpriteSize(SPR_ARROW_DOWN);
2370 extra.width =
WD_DROPDOWNTEXT_LEFT + WD_DROPDOWNTEXT_RIGHT + NWidgetLeaf::dropdown_dimension.width;
2374 d2.width += extra.width;
2375 d2.height =
max(d2.height, NWidgetLeaf::dropdown_dimension.height) + extra.height;
2387 this->
fill_x = fill.width;
2388 this->fill_y = fill.height;
2390 this->resize_y = resize.height;
2401 new_dpi.left += this->
pos_x;
2402 new_dpi.top += this->
pos_y;
2405 _cur_dpi = &new_dpi;
2408 r.left = this->
pos_x;
2410 r.top = this->
pos_y;
2414 switch (this->
type) {
2443 case AWV_LEFT: sprite = SPR_ARROW_LEFT;
break;
2444 case AWV_RIGHT: sprite = SPR_ARROW_RIGHT;
break;
2445 default: NOT_REACHED();
2467 if (query != NULL) query->DrawEditBox(w, this->
index);
2510 case NWID_PUSHBUTTON_DROPDOWN:
2537 int button_width = this->
pos_x + this->
current_x - NWidgetLeaf::dropdown_dimension.width;
2538 return pt.x < button_width;
2540 int button_left = this->
pos_x + NWidgetLeaf::dropdown_dimension.width;
2541 return pt.x >= button_left;
2569 while (count > num_used) {
2570 switch (parts->
type) {
2572 if (*dest != NULL)
return num_used;
2577 if (*dest != NULL)
return num_used;
2583 if (*dest != NULL)
return num_used;
2591 if (*dest != NULL)
return num_used;
2593 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2598 if (*dest != NULL)
return num_used;
2604 if (*dest != NULL)
return num_used;
2610 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2615 if (*dest != NULL)
return num_used;
2618 *dest = parts->u.
func_ptr(&biggest);
2619 *biggest_index =
max(*biggest_index, biggest);
2627 assert(parts->u.
xy.x >= 0 && parts->u.
xy.y >= 0);
2636 assert(parts->u.
xy.x >= 0 && parts->u.
xy.y >= 0);
2653 if (nwrb != NULL) nwrb->
SetFill(parts->u.
xy.x, parts->u.
xy.y);
2691 if (*dest != NULL)
return num_used;
2693 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2698 if (*dest != NULL)
return num_used;
2700 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2704 if (*dest != NULL)
return num_used;
2709 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2714 if (*dest != NULL)
return num_used;
2717 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2742 assert(*parent == NULL || (nwid_cont != NULL && nwid_parent == NULL) || (nwid_cont == NULL && nwid_parent != NULL));
2747 bool fill_sub =
false;
2748 int num_used =
MakeNWidget(parts, count - total_used, &sub_widget, &fill_sub, biggest_index);
2750 total_used += num_used;
2753 if (sub_widget == NULL)
break;
2760 int num_used =
MakeWidgetTree(parts, count - total_used, &sub_ptr, biggest_index);
2762 total_used += num_used;
2766 if (nwid_cont != NULL) nwid_cont->
Add(sub_widget);
2767 if (nwid_parent != NULL) nwid_parent->
Add(sub_widget);
2768 if (nwid_cont == NULL && nwid_parent == NULL) {
2769 *parent = sub_widget;
2774 if (count == total_used)
return total_used;
2776 assert(total_used < count);
2778 return total_used + 1;
2794 *biggest_index = -1;
2816 *biggest_index = -1;
2820 int num_used =
MakeWidgetTree(parts, count, &nwid, biggest_index);
2821 assert(nwid != NULL);
2828 *shade_select = NULL;
2838 root->
Add(*shade_select);
2840 (*shade_select)->
Add(body);
2842 *shade_select = NULL;
2850 *biggest_index =
max(*biggest_index, biggest2);
2866 assert(max_length >= 1);
2875 for (
int widnum = widget_first; widnum <= widget_last; widnum++) {
2877 if (hor_length == max_length) {
2896 *biggest_index = widget_last;
2897 if (vert == NULL)
return hor;
2899 if (hor_length > 0 && hor_length < max_length) {
2906 if (hor != NULL) vert->
Add(hor);
Functions related to OTTD's strings.
Left offset of sticky sprite.
static const PaletteID PALETTE_TO_TRANSPARENT
This sets the sprite to transparent.
void InitializeWindowViewport(Window *w, int x, int y, int width, int height, uint32 follow_flags, ZoomLevel zoom)
Initialize viewport of the window for use.
Data about how and where to blit pixels.
Horizontally center the text.
const QueryString * GetQueryString(uint widnum) const
Return the querystring associated to a editbox.
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen...
Offset at right of a matrix cell.
Point pos
logical mouse position
static int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Right offset of closebox string.
WindowFlags flags
Window flags.
int left
x position of left edge of the window
int height
Screen height of the viewport.
void DrawWidgets() const
Paint all widgets of a window.
Width of left bevel border.
Left offset of scrollbar.
Right offset of debug sprite.
Height of a drop down widget.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Offset at top to draw the frame rectangular area.
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
byte _colour_gradient[COLOUR_END][8]
All 16 colour gradients 8 colours per gradient from darkest (0) to lightest (7)
Bottom offset of shade sprite.
Left offset of shade sprite.
int virtual_height
height << zoom
If set the background is darker, allows for lowered frames with normal background colour when used wi...
int top
y position of top edge of the window
static bool IsInsideBS(const T x, const uint base, const uint size)
Checks if a value is between a window started at some base point.
int LeastCommonMultiple(int a, int b)
Compute least common multiple (lcm) of arguments a and b, the smallest integer value that is a multip...
static int ScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift left (when zoom > ZOOM_LVL_NORMAL) When shifting right...
Width of right bevel border.
Offset at top of a matrix cell.
Bottom offset of defsize sprite.
Top offset of debug sprite.
Left offset of debug sprite.
static T max(const T a, const T b)
Returns the maximum of two values.
Window is made sticky by user.
static T SB(T &x, const uint8 s, const uint8 n, const U d)
Set n bits in x starting at bit s to d.
Functions, definitions and such used only by the GUI.
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
Set up a clipping area for only drawing into a certain area.
virtual bool IsNewGRFInspectable() const
Is the data related to this window NewGRF inspectable?
FrameFlags
Flags to describe the look of the frame.
Width of a close box widget.
Functions related to (drawing on) viewports.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Base for the GUIs that have an edit box in them.
Data structure for an opened window.
Bottom offset of image in the button.
Bottom offset of the text of the frame.
NWidgetBase ** nested_array
Array of pointers into the tree. Do not access directly, use Window::GetWidget() instead.
Right offset of resize sprite.
Offset at bottom of a matrix cell.
Right offset of defsize sprite.
bool IsWidgetLowered(byte widget_index) const
Gets the lowered state of a widget.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Data stored about a string that can be modified in the GUI.
ClientSettings _settings_client
The current settings for this game.
Apply a recolour sprite to the screen content.
Types related to global configuration settings.
Bottom offset of resize sprite.
Definition of base types and functions in a cross-platform compatible way.
Height of bottom bevel border.
A number of safeguards to prevent using unsafe methods.
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
static uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
Left offset of defsize sprite.
uint nested_array_size
Size of the nested array.
void DrawSortButtonState(int widget, SortButtonState state) const
Draw a sort button's up or down arrow symbol.
static const PaletteID PALETTE_NEWSPAPER
Recolour sprite for newspaper-greying.
Offset at left of a matrix cell.
Top offset of resize sprite.
int GetRowFromWidget(int clickpos, int widget, int padding, int line_height=-1) const
Compute the row of a widget that a user clicked in.
int virtual_width
width << zoom
SortButtonState
State of a sort direction button.
Right offset of sticky sprite.
Offset at bottom to draw the frame rectangular area.
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
TransparencyOptionBits _transparency_opt
The bits that should be transparent.
Offset of the caption text at the left.
void SetDirtyBlocks(int left, int top, int right, int bottom)
This function extends the internal _invalid_rect rectangle as it now contains the rectangle defined b...
Right offset of the text of the frame.
Right offset of the image in the button.
Top offset of the text of the frame.
Left offset of the text of the frame.
Top offset of defsize sprite.
Window has a widget that has a highlight.
Base class that provides memory initialization on dynamically created objects.
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Text is written left-to-right by default.
Left offset of resize sprite.
Bottom offset of closebox string.
Maximum number of companies.
Draw border only, no background.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Offset of the caption text at the top.
bool newgrf_developer_tools
activate NewGRF developer tools and allow modifying NewGRFs in an existing game
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
int scrolling_scrollbar
Widgetindex of just being dragged scrollbar. -1 if none is active.
int left
Screen coordinate left egde of the viewport.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
void DrawViewport() const
Draw the viewport of this window.
Draw only every second pixel, used for greying-out.
static int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Top offset of shade sprite.
Width of a standard sticky box widget.
Bottom offset of scrollbar.
ZoomLevel
All zoom levels we know.
Functions related to companies.
Height of top bevel border.
GUISettings gui
settings related to the GUI
Data structure for viewport, display of a part of the world.
uint32 SpriteID
The number of a sprite, without mapping bits and colourtables.
If set the frame is lowered and the background colour brighter (ie. buttons when pressed) ...
Bottom offset of sticky sprite.
Offset of the caption text at the bottom.
Bottom offset of debug sprite.
static const byte _string_colourmap[17]
Colour mapping for TextColour.
bool _window_highlight_colour
If false, highlight is white, otherwise the by the widget defined colour.
TextDirection _current_text_dir
Text direction of the currently selected language.
uint8 spacing
Extra spacing around lines.
Functions related to transparency.
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
uint TransparencyOptionBits
transparency option bits
Top offset of image in the button.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
Functions related to zooming.
FontSize
Available font sizes.
Set if palette is actually a magic text recolour.
Top offset of sticky sprite.
Bottom offset of the dropdown widget string.
Right offset of scrollbar.
Coordinates of a point in 2D.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Colours _company_colours[MAX_COMPANIES]
NOSAVE: can be determined from company structs.
The colour translation of GRF's strings.
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable...
Right offset of shade sprite.
Width of a resize box widget.
Offset at right to draw the frame rectangular area.
ZoomLevel zoom
The zoom level of the viewport.
int width
width of the window (number of pixels to the right in x direction)
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Specification of a rectangle with absolute coordinates of all edges.
bool IsShaded() const
Is window shaded currently?
Text is written right-to-left by default.
Left offset of the dropdown widget string.
Owner
Enum for all companies/owners.
int top
Screen coordinate top edge of the viewport.
Makes the background transparent if set.
ViewportData * viewport
Pointer to viewport data, if present.
uint8 lines
Number of text lines.
FontSize size
Font size of text lines.
const NWID * GetWidget(uint widnum) const
Get the nested widget with number widnum from the nested widget tree.
Do not sort (with this button).
Window white border counter bit mask.
Left offset of the image in the button.
Left offset of closebox string.
NWidgetBase * nested_root
Root of the nested tree.
Dimensions (a width and height) of a rectangle in 2D.
Offset at left to draw the frame rectangular area.
This file contains all sprite-related enums and defines.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Right offset of the dropdown widget string.
Top offset of the dropdown widget string.
Offset of the caption text at the right.
Top offset of closebox string.
int height
Height of the window (number of pixels down in y direction)
int width
Screen width of the viewport.