22 #include "table/strings.h" 39 int rev_base = top + bottom;
42 button_size = NWidgetScrollbar::GetHorizontalDimension().width;
44 button_size = NWidgetScrollbar::GetVerticalDimension().height;
47 bottom -= button_size;
49 int height = (bottom - top);
54 if (count != 0) top += height * pos / count;
56 if (cap > count) cap = count;
57 if (count != 0) bottom -= (count - pos - cap) * height / count;
61 pt.x = rev_base - bottom;
62 pt.y = rev_base - top;
88 button_size = NWidgetScrollbar::GetHorizontalDimension().width;
91 button_size = NWidgetScrollbar::GetVerticalDimension().height;
93 if (pos < mi + button_size) {
96 if (_scroller_click_timeout <= 1) {
97 _scroller_click_timeout = 3;
101 }
else if (pos >= ma - button_size) {
105 if (_scroller_click_timeout <= 1) {
106 _scroller_click_timeout = 3;
115 }
else if (pos > pt.y) {
118 _scrollbar_start_pos = pt.x - mi - button_size;
119 _scrollbar_size = ma - mi - button_size * 2;
121 _cursorpos_drag_start = _cursor.
pos;
148 assert(scrollbar !=
nullptr);
163 return (nw !=
nullptr) ? nw->
index : -1;
177 assert(colour < COLOUR_END);
194 interior = (flags &
FR_DARKENED ? medium_dark : medium_light);
200 interior = medium_dark;
221 if ((type & WWT_MASK) ==
WWT_IMGBTN_2 && clicked) img++;
235 if (str == STR_NULL)
return;
238 int offset =
max(0, ((
int)(r.bottom - r.top + 1) - (
int)d.height) / 2);
251 int offset =
max(0, ((
int)(r.bottom - r.top + 1) - (
int)d.height) / 2);
252 if (str != STR_NULL)
DrawString(r.left, r.right, r.top + offset, str, colour);
276 static inline void DrawMatrix(
const Rect &r, Colours colour,
bool clicked, uint16 data, uint resize_x, uint resize_y)
282 if (num_columns == 0) {
283 column_width = resize_x;
284 num_columns = (r.right - r.left + 1) / column_width;
286 column_width = (r.right - r.left + 1) / num_columns;
292 row_height = resize_y;
293 num_rows = (r.bottom - r.top + 1) / row_height;
295 row_height = (r.bottom - r.top + 1) / num_rows;
301 for (
int ctr = num_columns; ctr > 1; ctr--) {
307 for (
int ctr = num_rows; ctr > 1; ctr--) {
315 for (
int ctr = num_columns; ctr > 1; ctr--) {
321 for (
int ctr = num_rows; ctr > 1; ctr--) {
338 int centre = (r.right - r.left) / 2;
339 int height = NWidgetScrollbar::GetVerticalDimension().height;
343 DrawSprite(SPR_ARROW_UP, PAL_NONE, r.left + 1 + up_clicked, r.top + 1 + up_clicked);
345 DrawFrameRect(r.left, r.bottom - (height - 1), r.right, r.bottom, colour, (down_clicked) ?
FR_LOWERED : FR_NONE);
346 DrawSprite(SPR_ARROW_DOWN, PAL_NONE, r.left + 1 + down_clicked, r.bottom - (height - 2) + down_clicked);
352 GfxFillRect(r.left, r.top + height, r.right, r.bottom - height, c2);
356 GfxFillRect(r.left + centre - 3, r.top + height, r.left + centre - 3, r.bottom - height, c1);
357 GfxFillRect(r.left + centre - 2, r.top + height, r.left + centre - 2, r.bottom - height, c2);
358 GfxFillRect(r.left + centre + 2, r.top + height, r.left + centre + 2, r.bottom - height, c1);
359 GfxFillRect(r.left + centre + 3, r.top + height, r.left + centre + 3, r.bottom - height, c2);
376 int centre = (r.bottom - r.top) / 2;
377 int width = NWidgetScrollbar::GetHorizontalDimension().width;
380 DrawSprite(SPR_ARROW_LEFT, PAL_NONE, r.left + 1 + left_clicked, r.top + 1 + left_clicked);
383 DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - (width - 2) + right_clicked, r.top + 1 + right_clicked);
389 GfxFillRect(r.left + width, r.top, r.right - width, r.bottom, c2);
393 GfxFillRect(r.left + width, r.top + centre - 3, r.right - width, r.top + centre - 3, c1);
394 GfxFillRect(r.left + width, r.top + centre - 2, r.right - width, r.top + centre - 2, c2);
395 GfxFillRect(r.left + width, r.top + centre + 2, r.right - width, r.top + centre + 2, c1);
396 GfxFillRect(r.left + width, r.top + centre + 3, r.right - width, r.top + centre + 3, c2);
425 GfxFillRect(r.left, r.top + dy1, r.left + 4, r.top + dy1, c1);
426 GfxFillRect(r.left + 1, r.top + dy2, r.left + 4, r.top + dy2, c2);
429 GfxFillRect(x2, r.top + dy1, r.right - 1, r.top + dy1, c1);
430 GfxFillRect(x2, r.top + dy2, r.right - 2, r.top + dy2, c2);
433 GfxFillRect(r.left, r.top + dy1, x2 - 2, r.top + dy1, c1);
434 GfxFillRect(r.left + 1, r.top + dy2, x2 - 2, r.top + dy2, c2);
437 GfxFillRect(r.right - 5, r.top + dy1, r.right - 1, r.top + dy1, c1);
438 GfxFillRect(r.right - 5, r.top + dy2, r.right - 2, r.top + dy2, c2);
442 GfxFillRect(r.left, r.top + dy2, r.left, r.bottom - 1, c1);
443 GfxFillRect(r.left + 1, r.top + dy2 + 1, r.left + 1, r.bottom - 2, c2);
446 GfxFillRect(r.right - 1, r.top + dy2, r.right - 1, r.bottom - 2, c1);
447 GfxFillRect(r.right, r.top + dy1, r.right, r.bottom - 1, c2);
449 GfxFillRect(r.left + 1, r.bottom - 1, r.right - 1, r.bottom - 1, c1);
450 GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2);
525 if (colour != COLOUR_WHITE)
DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, FR_NONE);
549 if (str != STR_NULL) {
551 int offset =
max(0, ((
int)(r.bottom - r.top + 1) - (
int)d.height) / 2);
572 int image_offset =
max(0, ((
int)(r.bottom - r.top + 1) - dd_height) / 2);
576 DrawFrameRect(r.right + 1 - dd_width, r.top, r.right, r.bottom, colour, clicked_dropdown ?
FR_LOWERED : FR_NONE);
577 DrawSprite(SPR_ARROW_DOWN, PAL_NONE, r.right - (dd_width - 2) + clicked_dropdown, r.top + image_offset + clicked_dropdown);
581 DrawFrameRect(r.left, r.top, r.left + dd_width - 1, r.bottom, colour, clicked_dropdown ?
FR_LOWERED : FR_NONE);
582 DrawSprite(SPR_ARROW_DOWN, PAL_NONE, r.left + 1 + clicked_dropdown, r.top + image_offset + clicked_dropdown);
613 const NWidgetBase *widget = this->GetWidget<NWidgetBase>(i);
614 if (widget ==
nullptr || !widget->IsHighlighted())
continue;
618 int right = left + widget->
current_x - 1;
619 int bottom = top + widget->
current_y - 1;
621 int colour =
_string_colourmap[_window_highlight_colour ? widget->GetHighlightColour() : TC_WHITE];
641 const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(widget);
644 Dimension dim = NWidgetScrollbar::GetVerticalDimension();
647 int y = offset + nwid->
pos_y + (nwid->
current_y - dim.height) / 2;
658 return NWidgetScrollbar::GetVerticalDimension().width + 1;
795 return (this->
type == tp) ? this :
nullptr;
817 this->min_x =
max(this->min_x, min_x);
818 this->min_y =
max(this->min_y, min_y);
900 if (this->
index >= 0 && (uint)(this->
index) < length) array[this->
index] =
this;
914 this->
head =
nullptr;
915 this->
tail =
nullptr;
918 NWidgetContainer::~NWidgetContainer()
920 while (this->
head !=
nullptr) {
925 this->
tail =
nullptr;
930 if (this->
type == tp)
return this;
931 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
933 if (nwid !=
nullptr)
return nwid;
944 assert(wid->
next ==
nullptr && wid->
prev ==
nullptr);
946 if (this->
head ==
nullptr) {
950 assert(this->
tail !=
nullptr);
951 assert(this->
tail->
next ==
nullptr);
961 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
962 child_wid->FillNestedArray(array, length);
974 void NWidgetStacked::SetIndex(
int index)
981 if (this->
index >= 0 && init_array) {
997 this->
fill_x = fill.width;
998 this->
fill_y = fill.height;
1007 this->
fill_x = (this->
head !=
nullptr) ? 1 : 0;
1008 this->
fill_y = (this->
head !=
nullptr) ? 1 : 0;
1011 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1012 child_wid->SetupSmallestSize(w, init_array);
1014 this->
smallest_x =
max(this->
smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
1015 this->
smallest_y =
max(this->
smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
1030 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1031 uint hor_step = (sizing ==
ST_SMALLEST) ? 1 : child_wid->GetHorizontalStepSize(sizing);
1032 uint child_width =
ComputeMaxSize(child_wid->smallest_x, given_width - child_wid->padding_left - child_wid->padding_right, hor_step);
1033 uint child_pos_x = (rtl ? child_wid->padding_right : child_wid->padding_left);
1035 uint vert_step = (sizing ==
ST_SMALLEST) ? 1 : child_wid->GetVerticalStepSize(sizing);
1036 uint child_height =
ComputeMaxSize(child_wid->smallest_y, given_height - child_wid->padding_top - child_wid->padding_bottom, vert_step);
1037 uint child_pos_y = child_wid->padding_top;
1039 child_wid->AssignSizePosition(sizing, x + child_pos_x, y + child_pos_y, child_width, child_height, rtl);
1045 if (this->
index >= 0 && (uint)(this->
index) < length) array[this->
index] =
this;
1054 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; plane++, child_wid = child_wid->
next) {
1070 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; plane++, child_wid = child_wid->
next) {
1089 this->flags = flags;
1103 this->pip_pre = pip_pre;
1104 this->pip_inter = pip_inter;
1105 this->pip_post = pip_post;
1110 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1119 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1121 if (nwid !=
nullptr)
return nwid;
1142 uint max_vert_fill = 0;
1143 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1144 child_wid->SetupSmallestSize(w, init_array);
1145 longest =
max(longest, child_wid->smallest_x);
1146 max_vert_fill =
max(max_vert_fill, child_wid->GetVerticalStepSize(
ST_SMALLEST));
1147 this->
smallest_y =
max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
1150 uint max_smallest = this->
smallest_y + 3 * max_vert_fill;
1153 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1154 uint step_size = child_wid->GetVerticalStepSize(
ST_SMALLEST);
1155 uint child_height = child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom;
1156 if (step_size > 1 && child_height < cur_height) {
1157 uint remainder = (cur_height - child_height) % step_size;
1158 if (remainder > 0) {
1159 cur_height += step_size - remainder;
1160 assert(cur_height < max_smallest);
1170 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1171 if (child_wid->fill_x == 1) child_wid->smallest_x = longest;
1176 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1177 if (child_wid->next !=
nullptr) {
1178 child_wid->padding_right += this->
pip_inter;
1180 child_wid->padding_right += this->
pip_post;
1183 this->
smallest_x += child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right;
1184 if (child_wid->fill_x > 0) {
1185 if (this->
fill_x == 0 || this->
fill_x > child_wid->fill_x) this->
fill_x = child_wid->fill_x;
1189 if (child_wid->resize_x > 0) {
1203 uint additional_length = given_width;
1206 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1207 additional_length -= child_wid->smallest_x + child_wid->padding_right + child_wid->padding_left;
1229 int num_changing_childs = 0;
1230 uint biggest_stepsize = 0;
1231 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1232 uint hor_step = child_wid->GetHorizontalStepSize(sizing);
1234 num_changing_childs++;
1235 biggest_stepsize =
max(biggest_stepsize, hor_step);
1237 child_wid->current_x = child_wid->smallest_x;
1240 uint vert_step = (sizing ==
ST_SMALLEST) ? 1 : child_wid->GetVerticalStepSize(sizing);
1241 child_wid->current_y =
ComputeMaxSize(child_wid->smallest_y, given_height - child_wid->padding_top - child_wid->padding_bottom, vert_step);
1245 while (biggest_stepsize > 0) {
1246 uint next_biggest_stepsize = 0;
1247 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1248 uint hor_step = child_wid->GetHorizontalStepSize(sizing);
1249 if (hor_step > biggest_stepsize)
continue;
1250 if (hor_step == biggest_stepsize) {
1251 uint increment = additional_length / num_changing_childs;
1252 num_changing_childs--;
1253 if (hor_step > 1) increment -= increment % hor_step;
1254 child_wid->current_x = child_wid->smallest_x + increment;
1255 additional_length -= increment;
1258 next_biggest_stepsize =
max(next_biggest_stepsize, hor_step);
1260 biggest_stepsize = next_biggest_stepsize;
1262 assert(num_changing_childs == 0);
1265 uint position = rtl ? this->
current_x : 0;
1267 while (child_wid !=
nullptr) {
1268 uint child_width = child_wid->
current_x;
1274 position = rtl ? position - padded_child_width : position + padded_child_width;
1276 child_wid = child_wid->
next;
1307 uint max_hor_fill = 0;
1308 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1309 child_wid->SetupSmallestSize(w, init_array);
1310 highest =
max(highest, child_wid->smallest_y);
1311 max_hor_fill =
max(max_hor_fill, child_wid->GetHorizontalStepSize(
ST_SMALLEST));
1312 this->
smallest_x =
max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
1315 uint max_smallest = this->
smallest_x + 3 * max_hor_fill;
1318 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1319 uint step_size = child_wid->GetHorizontalStepSize(
ST_SMALLEST);
1320 uint child_width = child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right;
1321 if (step_size > 1 && child_width < cur_width) {
1322 uint remainder = (cur_width - child_width) % step_size;
1323 if (remainder > 0) {
1324 cur_width += step_size - remainder;
1325 assert(cur_width < max_smallest);
1335 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1336 if (child_wid->fill_y == 1) child_wid->smallest_y = highest;
1341 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1342 if (child_wid->next !=
nullptr) {
1343 child_wid->padding_bottom += this->
pip_inter;
1345 child_wid->padding_bottom += this->
pip_post;
1348 this->
smallest_y += child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom;
1349 if (child_wid->fill_y > 0) {
1350 if (this->
fill_y == 0 || this->
fill_y > child_wid->fill_y) this->
fill_y = child_wid->fill_y;
1354 if (child_wid->resize_y > 0) {
1368 uint additional_length = given_height;
1371 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1372 additional_length -= child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom;
1385 int num_changing_childs = 0;
1386 uint biggest_stepsize = 0;
1387 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1388 uint vert_step = child_wid->GetVerticalStepSize(sizing);
1389 if (vert_step > 0) {
1390 num_changing_childs++;
1391 biggest_stepsize =
max(biggest_stepsize, vert_step);
1393 child_wid->current_y = child_wid->smallest_y;
1396 uint hor_step = (sizing ==
ST_SMALLEST) ? 1 : child_wid->GetHorizontalStepSize(sizing);
1397 child_wid->current_x =
ComputeMaxSize(child_wid->smallest_x, given_width - child_wid->padding_left - child_wid->padding_right, hor_step);
1401 while (biggest_stepsize > 0) {
1402 uint next_biggest_stepsize = 0;
1403 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1404 uint vert_step = child_wid->GetVerticalStepSize(sizing);
1405 if (vert_step > biggest_stepsize)
continue;
1406 if (vert_step == biggest_stepsize) {
1407 uint increment = additional_length / num_changing_childs;
1408 num_changing_childs--;
1409 if (vert_step > 1) increment -= increment % vert_step;
1410 child_wid->current_y = child_wid->smallest_y + increment;
1411 additional_length -= increment;
1414 next_biggest_stepsize =
max(next_biggest_stepsize, vert_step);
1416 biggest_stepsize = next_biggest_stepsize;
1418 assert(num_changing_childs == 0);
1422 for (
NWidgetBase *child_wid = this->
head; child_wid !=
nullptr; child_wid = child_wid->
next) {
1423 uint child_x = x + (rtl ? child_wid->padding_right : child_wid->padding_left);
1424 uint child_height = child_wid->current_y;
1426 child_wid->AssignSizePosition(sizing, child_x, y + position + child_wid->padding_top, child_wid->current_x, child_height, rtl);
1427 position += child_height + child_wid->padding_top + child_wid->padding_bottom;
1471 void NWidgetMatrix::SetIndex(
int index)
1473 this->index = index;
1476 void NWidgetMatrix::SetColour(Colours colour)
1478 this->colour = colour;
1487 this->clicked = clicked;
1488 if (this->clicked >= 0 && this->sb !=
nullptr && this->widgets_x != 0) {
1489 int vpos = (this->clicked / this->widgets_x) * this->widget_h;
1492 if (this->sb->GetPosition() < vpos) vpos += this->widget_h - this->pip_inter - 1;
1493 this->sb->ScrollTowards(vpos);
1504 this->count = count;
1506 if (this->sb ==
nullptr || this->widgets_x == 0)
return;
1513 count =
CeilDiv(count, this->sb->IsVertical() ? this->widgets_x : this->widgets_y);
1514 count *= (this->sb->IsVertical() ? this->head->smallest_y : this->head->smallest_x) + this->pip_inter;
1515 if (count > 0) count -= this->pip_inter;
1516 count += this->pip_pre + this->pip_post;
1517 this->sb->SetCount(count);
1519 this->sb->SetStepSize(this->sb->IsVertical() ? this->widget_h : this->widget_w);
1533 assert(this->head !=
nullptr);
1534 assert(this->head->next ==
nullptr);
1536 if (this->index >= 0 && init_array) {
1543 assert(nw !=
nullptr);
1545 this->head->SetupSmallestSize(w, init_array);
1547 Dimension padding = { (uint)this->pip_pre + this->pip_post, (uint)this->pip_pre + this->pip_post};
1548 Dimension size = {this->head->smallest_x + padding.width, this->head->smallest_y + padding.height};
1550 Dimension resize = {this->pip_inter + this->head->smallest_x, this->pip_inter + this->head->smallest_y};
1552 if (this->index >= 0) w->
UpdateWidgetSize(this->index, &size, padding, &fill, &resize);
1556 this->
fill_x = fill.width;
1557 this->
fill_y = fill.height;
1572 this->widget_w = this->head->smallest_x + this->pip_inter;
1573 this->widget_h = this->head->smallest_y + this->pip_inter;
1577 this->widgets_x =
CeilDiv(this->
current_x - this->pip_pre - this->pip_post + this->pip_inter, this->widget_w);
1578 this->widgets_y =
CeilDiv(this->
current_y - this->pip_pre - this->pip_post + this->pip_inter, this->widget_h);
1583 this->SetCount(this->count);
1588 if (this->index >= 0 && (uint)(this->index) < length) array[this->index] =
this;
1597 int start_x, start_y, base_offs_x, base_offs_y;
1598 this->GetScrollOffsets(start_x, start_y, base_offs_x, base_offs_y);
1602 int widget_col = (rtl ?
1603 -x + (int)this->pip_post + (
int)this->
pos_x + base_offs_x + (int)this->widget_w - 1 - (
int)this->pip_inter :
1604 x - (int)this->pip_pre - (
int)this->
pos_x - base_offs_x
1607 int widget_row = (y - base_offs_y - (int)this->pip_pre - (
int)this->
pos_y) / this->widget_h;
1609 int sub_wid = (widget_row + start_y) * this->widgets_x + start_x + widget_col;
1610 if (sub_wid >= this->count)
return nullptr;
1613 assert(child !=
nullptr);
1615 this->
pos_x + (rtl ? this->pip_post - widget_col * this->widget_w : this->pip_pre + widget_col * this->widget_w) + base_offs_x,
1616 this->
pos_y + this->pip_pre + widget_row * this->widget_h + base_offs_y,
1619 SB(child->
index, 16, 16, sub_wid);
1632 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;
1634 _cur_dpi = &tmp_dpi;
1638 assert(child !=
nullptr);
1639 int start_x, start_y, base_offs_x, base_offs_y;
1640 this->GetScrollOffsets(start_x, start_y, base_offs_x, base_offs_y);
1642 int offs_y = base_offs_y;
1643 for (
int y = start_y; y < start_y + this->widgets_y + 1; y++, offs_y += this->widget_h) {
1645 if (offs_y + child->
smallest_y <= 0)
continue;
1646 if (offs_y >= (
int)this->
current_y)
break;
1649 if (y * this->widgets_x >= this->count)
break;
1651 int offs_x = base_offs_x;
1652 for (
int x = start_x; x < start_x + this->widgets_x + 1; x++, offs_x += rtl ? -this->widget_w : this->widget_w) {
1654 if (offs_x + child->
smallest_x <= 0)
continue;
1655 if (offs_x >= (
int)this->
current_x)
continue;
1658 int sub_wid = y * this->widgets_x + x;
1659 if (sub_wid >= this->count)
break;
1663 SB(child->
index, 16, 16, sub_wid);
1685 if (this->sb !=
nullptr) {
1686 if (this->sb->IsVertical()) {
1687 start_y = this->sb->GetPosition() / this->widget_h;
1688 base_offs_y += -this->sb->GetPosition() + start_y * this->widget_h;
1690 start_x = this->sb->GetPosition() / this->widget_w;
1691 int sub_x = this->sb->GetPosition() - start_x * this->widget_w;
1693 base_offs_x += sub_x;
1695 base_offs_x -= sub_x;
1713 if (index >= 0) this->
SetIndex(index);
1714 this->child =
child;
1717 NWidgetBackground::~NWidgetBackground()
1719 if (this->
child !=
nullptr)
delete this->
child;
1731 if (this->
child ==
nullptr) {
1749 if (this->
child ==
nullptr) {
1752 this->
child->
SetPIP(pip_pre, pip_inter, pip_post);
1757 if (init_array && this->
index >= 0) {
1761 if (this->
child !=
nullptr) {
1793 d =
maxdim(d, background);
1795 if (this->
index >= 0) {
1796 static const Dimension padding = {0, 0};
1802 this->
fill_x = fill.width;
1803 this->fill_y = fill.height;
1805 this->resize_y = resize.height;
1813 if (this->
child !=
nullptr) {
1823 if (this->
index >= 0 && (uint)(this->
index) < length) array[this->
index] =
this;
1832 r.left = this->
pos_x;
1834 r.top = this->
pos_y;
1838 if (dpi->left > r.right || dpi->left + dpi->width <= r.left || dpi->top > r.bottom || dpi->top + dpi->height <= r.top)
return;
1840 switch (this->
type) {
1873 if (nwid ==
nullptr) nwid =
this;
1882 if (nwid ==
nullptr && this->
type == tp) nwid =
this;
1893 if (init_array && this->
index >= 0) {
1937 if (vp !=
nullptr) {
1960 if (pos != INT_MAX) pos += this->GetPosition();
1961 return (pos >= this->GetCount()) ? INT_MAX : pos;
1974 if (this->IsVertical()) {
1995 if (init_array && this->
index >= 0) {
2002 switch (this->
type) {
2004 this->
SetMinimalSize(NWidgetScrollbar::GetHorizontalDimension().width * 3, NWidgetScrollbar::GetHorizontalDimension().height);
2007 this->
SetDataTip(0x0, STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST);
2011 this->
SetMinimalSize(NWidgetScrollbar::GetVerticalDimension().width, NWidgetScrollbar::GetVerticalDimension().height * 3);
2014 this->
SetDataTip(0x0, STR_TOOLTIP_VSCROLL_BAR_SCROLLS_LIST);
2017 default: NOT_REACHED();
2029 r.left = this->
pos_x;
2031 r.top = this->
pos_y;
2035 if (dpi->left > r.right || dpi->left + dpi->width <= r.left || dpi->top > r.bottom || dpi->top + dpi->height <= r.top)
return;
2052 void NWidgetScrollbar::InvalidateDimensionCache()
2058 Dimension NWidgetScrollbar::GetVerticalDimension()
2069 Dimension NWidgetScrollbar::GetHorizontalDimension()
2086 shadebox_dimension.width = shadebox_dimension.height = 0;
2087 debugbox_dimension.width = debugbox_dimension.height = 0;
2088 defsizebox_dimension.width = defsizebox_dimension.height = 0;
2089 stickybox_dimension.width = stickybox_dimension.height = 0;
2090 resizebox_dimension.width = resizebox_dimension.height = 0;
2091 closebox_dimension.width = closebox_dimension.height = 0;
2092 dropdown_dimension.width = dropdown_dimension.height = 0;
2114 if (index >= 0) this->
SetIndex(index);
2134 case NWID_PUSHBUTTON_DROPDOWN:
2148 this->
SetDataTip(data, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS);
2154 this->
SetDataTip(STR_NULL, STR_TOOLTIP_STICKY);
2160 this->
SetDataTip(STR_NULL, STR_TOOLTIP_SHADE);
2166 this->
SetDataTip(STR_NULL, STR_TOOLTIP_DEBUG);
2172 this->
SetDataTip(STR_NULL, STR_TOOLTIP_DEFSIZE);
2178 this->
SetDataTip(STR_NULL, STR_TOOLTIP_RESIZE);
2184 this->
SetDataTip(STR_NULL, STR_TOOLTIP_CLOSE_WINDOW);
2199 if (this->
index >= 0 && init_array) {
2209 switch (this->
type) {
2223 if (NWidgetLeaf::shadebox_dimension.width == 0) {
2225 NWidgetLeaf::shadebox_dimension.width += extra.width;
2226 NWidgetLeaf::shadebox_dimension.height += extra.height;
2228 size =
maxdim(size, NWidgetLeaf::shadebox_dimension);
2235 if (NWidgetLeaf::debugbox_dimension.width == 0) {
2236 NWidgetLeaf::debugbox_dimension =
GetSpriteSize(SPR_WINDOW_DEBUG);
2237 NWidgetLeaf::debugbox_dimension.width += extra.width;
2238 NWidgetLeaf::debugbox_dimension.height += extra.height;
2240 size =
maxdim(size, NWidgetLeaf::debugbox_dimension);
2252 if (NWidgetLeaf::stickybox_dimension.width == 0) {
2254 NWidgetLeaf::stickybox_dimension.width += extra.width;
2255 NWidgetLeaf::stickybox_dimension.height += extra.height;
2257 size =
maxdim(size, NWidgetLeaf::stickybox_dimension);
2264 if (NWidgetLeaf::defsizebox_dimension.width == 0) {
2265 NWidgetLeaf::defsizebox_dimension =
GetSpriteSize(SPR_WINDOW_DEFSIZE);
2266 NWidgetLeaf::defsizebox_dimension.width += extra.width;
2267 NWidgetLeaf::defsizebox_dimension.height += extra.height;
2269 size =
maxdim(size, NWidgetLeaf::defsizebox_dimension);
2276 if (NWidgetLeaf::resizebox_dimension.width == 0) {
2278 NWidgetLeaf::resizebox_dimension.width += extra.width;
2279 NWidgetLeaf::resizebox_dimension.height += extra.height;
2281 size =
maxdim(size, NWidgetLeaf::resizebox_dimension);
2286 size.width =
max(size.width, 30 + sprite_size.width);
2302 d2.width += extra.width;
2303 d2.height += extra.height;
2312 d2.width += extra.width;
2313 d2.height += extra.height;
2321 if (NWidgetLeaf::closebox_dimension.width == 0) {
2322 NWidgetLeaf::closebox_dimension =
GetSpriteSize(SPR_CLOSEBOX);
2323 NWidgetLeaf::closebox_dimension.width += extra.width;
2324 NWidgetLeaf::closebox_dimension.height += extra.height;
2326 size =
maxdim(size, NWidgetLeaf::closebox_dimension);
2336 d2.width += extra.width;
2337 d2.height += extra.height;
2354 d2.width += extra.width;
2355 d2.height += extra.height;
2361 case NWID_PUSHBUTTON_DROPDOWN: {
2364 if (NWidgetLeaf::dropdown_dimension.width == 0) {
2365 NWidgetLeaf::dropdown_dimension =
GetSpriteSize(SPR_ARROW_DOWN);
2368 extra.width =
WD_DROPDOWNTEXT_LEFT + WD_DROPDOWNTEXT_RIGHT + NWidgetLeaf::dropdown_dimension.width;
2372 d2.width += extra.width;
2373 d2.height =
max(d2.height, NWidgetLeaf::dropdown_dimension.height) + extra.height;
2385 this->
fill_x = fill.width;
2386 this->fill_y = fill.height;
2388 this->resize_y = resize.height;
2399 new_dpi.left += this->
pos_x;
2400 new_dpi.top += this->
pos_y;
2403 _cur_dpi = &new_dpi;
2406 r.left = this->
pos_x;
2408 r.top = this->
pos_y;
2412 switch (this->
type) {
2441 case AWV_LEFT: sprite = SPR_ARROW_LEFT;
break;
2442 case AWV_RIGHT: sprite = SPR_ARROW_RIGHT;
break;
2443 default: NOT_REACHED();
2465 if (query !=
nullptr) query->DrawEditBox(w, this->
index);
2508 case NWID_PUSHBUTTON_DROPDOWN:
2535 int button_width = this->
pos_x + this->
current_x - NWidgetLeaf::dropdown_dimension.width;
2536 return pt.x < button_width;
2538 int button_left = this->
pos_x + NWidgetLeaf::dropdown_dimension.width;
2539 return pt.x >= button_left;
2567 while (count > num_used) {
2568 switch (parts->
type) {
2570 if (*dest !=
nullptr)
return num_used;
2575 if (*dest !=
nullptr)
return num_used;
2581 if (*dest !=
nullptr)
return num_used;
2589 if (*dest !=
nullptr)
return num_used;
2591 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2596 if (*dest !=
nullptr)
return num_used;
2602 if (*dest !=
nullptr)
return num_used;
2608 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2613 if (*dest !=
nullptr)
return num_used;
2616 *dest = parts->u.
func_ptr(&biggest);
2617 *biggest_index =
max(*biggest_index, biggest);
2624 if (nwrb !=
nullptr) {
2625 assert(parts->u.
xy.x >= 0 && parts->u.
xy.y >= 0);
2633 if (nwrb !=
nullptr) {
2634 assert(parts->u.
xy.x >= 0 && parts->u.
xy.y >= 0);
2642 if (nwrb !=
nullptr) {
2651 if (nwrb !=
nullptr) nwrb->
SetFill(parts->u.
xy.x, parts->u.
xy.y);
2657 if (nwc !=
nullptr) {
2679 if (nwc !=
nullptr) {
2689 if (*dest !=
nullptr)
return num_used;
2691 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2696 if (*dest !=
nullptr)
return num_used;
2698 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2702 if (*dest !=
nullptr)
return num_used;
2707 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2712 if (*dest !=
nullptr)
return num_used;
2715 *biggest_index =
max(*biggest_index, (
int)parts->u.
widget.
index);
2740 assert(*parent ==
nullptr || (nwid_cont !=
nullptr && nwid_parent ==
nullptr) || (nwid_cont ==
nullptr && nwid_parent !=
nullptr));
2745 bool fill_sub =
false;
2746 int num_used =
MakeNWidget(parts, count - total_used, &sub_widget, &fill_sub, biggest_index);
2748 total_used += num_used;
2751 if (sub_widget ==
nullptr)
break;
2758 int num_used =
MakeWidgetTree(parts, count - total_used, &sub_ptr, biggest_index);
2760 total_used += num_used;
2764 if (nwid_cont !=
nullptr) nwid_cont->
Add(sub_widget);
2765 if (nwid_parent !=
nullptr) nwid_parent->
Add(sub_widget);
2766 if (nwid_cont ==
nullptr && nwid_parent ==
nullptr) {
2767 *parent = sub_widget;
2772 if (count == total_used)
return total_used;
2774 assert(total_used < count);
2776 return total_used + 1;
2792 *biggest_index = -1;
2814 *biggest_index = -1;
2818 int num_used =
MakeWidgetTree(parts, count, &nwid, biggest_index);
2819 assert(nwid !=
nullptr);
2826 *shade_select =
nullptr;
2836 root->
Add(*shade_select);
2838 (*shade_select)->
Add(body);
2840 *shade_select =
nullptr;
2848 *biggest_index =
max(*biggest_index, biggest2);
2864 assert(max_length >= 1);
2873 for (
int widnum = widget_first; widnum <= widget_last; widnum++) {
2875 if (hor_length == max_length) {
2881 if (hor ==
nullptr) {
2894 *biggest_index = widget_last;
2895 if (vert ==
nullptr)
return hor;
2897 if (hor_length > 0 && hor_length < max_length) {
2904 if (hor !=
nullptr) vert->
Add(hor);
Functions related to OTTD's strings.
Owner
Enum for all companies/owners.
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)
static int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
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
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?
static bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
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.
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 left
Screen coordinate left edge 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.
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.
Maximum number of companies.
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.
ZoomLevel
All zoom levels we know.
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.
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.
int mouse_capture_widget
Widgetindex of current mouse capture widget (e.g. dragged scrollbar). -1 if no widget has mouse captu...
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.