summaryrefslogtreecommitdiff
path: root/src/widget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widget.cpp')
-rw-r--r--src/widget.cpp563
1 files changed, 329 insertions, 234 deletions
diff --git a/src/widget.cpp b/src/widget.cpp
index 9238f8174..3375a3a2a 100644
--- a/src/widget.cpp
+++ b/src/widget.cpp
@@ -199,318 +199,413 @@ void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, Fra
}
}
-
/**
- * Paint all widgets of a window.
+ * Draw an image button.
+ * @param r Rectangle of the button.
+ * @param type Widget type (#WWT_IMGBTN or #WWT_IMGBTN_2).
+ * @param colour Colour of the button.
+ * @param clicked Button is lowered.
+ * @param img Sprite to draw.
*/
-void Window::DrawWidgets() const
+static inline void DrawImageButtons(const Rect &r, WidgetType type, Colours colour, bool clicked, SpriteID img)
{
- const DrawPixelInfo *dpi = _cur_dpi;
+ assert(img != 0);
+ DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
- for (uint i = 0; i < this->widget_count; i++) {
- const Widget *wi = &this->widget[i];
- bool clicked = this->IsWidgetLowered(i);
- Rect r;
+ /* show different image when clicked for WWT_IMGBTN_2 */
+ if ((type & WWT_MASK) == WWT_IMGBTN_2 && clicked) img++;
+ DrawSprite(img, PAL_NONE, r.left + 1 + clicked, r.top + 1 + clicked);
+}
- if (dpi->left > (r.right = wi->right) ||
- dpi->left + dpi->width <= (r.left = wi->left) ||
- dpi->top > (r.bottom = wi->bottom) ||
- dpi->top + dpi->height <= (r.top = wi->top) ||
- this->IsWidgetHidden(i)) {
- continue;
- }
+/**
+ * Draw the label-part of a widget.
+ * @param r Rectangle of the label background.
+ * @param type Widget type (#WWT_TEXTBTN, #WWT_TEXTBTN_2, or #WWT_LABEL).
+ * @param clicked Label is rendered lowered.
+ * @param str Text to draw.
+ */
+static inline void DrawLabel(const Rect &r, WidgetType type, bool clicked, StringID str)
+{
+ if ((type & WWT_MASK) == WWT_TEXTBTN_2 && clicked) str++;
+ DrawString(r.left + clicked, r.right + clicked, ((r.top + r.bottom + 1) >> 1) - 5 + clicked, str, TC_FROMSTRING, SA_CENTER);
+}
- switch (wi->type & WWT_MASK) {
- case WWT_IMGBTN:
- case WWT_IMGBTN_2: {
- SpriteID img = wi->data;
- assert(img != 0);
- DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
+/**
+ * Draw text.
+ * @param r Rectangle of the background.
+ * @param colour Colour of the text.
+ * @param str Text to draw.
+ */
+static inline void DrawText(const Rect &r, TextColour colour, StringID str)
+{
+ if (str != STR_NULL) DrawString(r.left, r.right, r.top, str, colour);
+}
- /* show different image when clicked for WWT_IMGBTN_2 */
- if ((wi->type & WWT_MASK) == WWT_IMGBTN_2 && clicked) img++;
- DrawSprite(img, PAL_NONE, r.left + 1 + clicked, r.top + 1 + clicked);
- break;
- }
+/**
+ * Draw an inset widget.
+ * @param r Rectangle of the background.
+ * @param colour Colour of the inset.
+ * @param str Text to draw.
+ */
+static inline void DrawInset(const Rect &r, Colours colour, StringID str)
+{
+ DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, FR_LOWERED | FR_DARKENED);
+ if (str != STR_NULL) DrawString(r.left + 2, r.right - 2, r.top + 1, str);
+}
- case WWT_PANEL:
- assert(wi->data == 0);
- DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
- break;
+/**
+ * Draw a matrix widget.
+ * @param r Rectangle of the matrix background.
+ * @param colour Colour of the background.
+ * @param clicked Matrix is rendered lowered.
+ * @param data Data of the widget.
+ */
+static inline void DrawMatrix(const Rect &r, Colours colour, bool clicked, uint16 data)
+{
+ DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
- case WWT_EDITBOX:
- DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, FR_LOWERED | FR_DARKENED);
- break;
+ int c = GB(data, 0, 8);
+ int amt1 = (r.right - r.left + 1) / c;
- case WWT_TEXTBTN:
- case WWT_TEXTBTN_2:
- DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
- /* FALL THROUGH */
+ int d = GB(data, 8, 8);
+ int amt2 = (r.bottom - r.top + 1) / d;
- case WWT_LABEL: {
- StringID str = wi->data;
+ int col = _colour_gradient[colour & 0xF][6];
- if ((wi->type & WWT_MASK) == WWT_TEXTBTN_2 && clicked) str++;
+ int x = r.left;
+ for (int ctr = c; ctr > 1; ctr--) {
+ x += amt1;
+ GfxFillRect(x, r.top + 1, x, r.bottom - 1, col);
+ }
- DrawString(r.left + clicked, r.right + clicked, ((r.top + r.bottom + 1) >> 1) - 5 + clicked, str, TC_FROMSTRING, SA_CENTER);
- break;
- }
+ x = r.top;
+ for (int ctr = d; ctr > 1; ctr--) {
+ x += amt2;
+ GfxFillRect(r.left + 1, x, r.right - 1, x, col);
+ }
- case WWT_TEXT: {
- const StringID str = wi->data;
+ col = _colour_gradient[colour & 0xF][4];
- if (str != STR_NULL) DrawString(r.left, r.right, r.top, str, (TextColour)wi->colour);
- break;
- }
+ x = r.left - 1;
+ for (int ctr = c; ctr > 1; ctr--) {
+ x += amt1;
+ GfxFillRect(x, r.top + 1, x, r.bottom - 1, col);
+ }
- case WWT_INSET: {
- const StringID str = wi->data;
- DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, FR_LOWERED | FR_DARKENED);
+ x = r.top - 1;
+ for (int ctr = d; ctr > 1; ctr--) {
+ x += amt2;
+ GfxFillRect(r.left + 1, x, r.right - 1, x, col);
+ }
+}
- if (str != STR_NULL) DrawString(r.left + 2, r.right - 2, r.top + 1, str);
- break;
- }
+/**
+ * Draw a vertical scrollbar.
+ * @param r Rectangle of the scrollbar widget.
+ * @param colour Colour of the scrollbar widget.
+ * @param up_clicked Up-arrow is clicked.
+ * @param bar_dragged Bar is dragged.
+ * @param down_clicked Down-arrow is clicked.
+ * @param scrollbar Scrollbar size, offset, and capacity information.
+ */
+static inline void DrawVerticalScrollbar(const Rect &r, Colours colour, bool up_clicked, bool bar_dragged, bool down_clicked, const Scrollbar *scrollbar)
+{
+ assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere!
- case WWT_MATRIX: {
- DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
+ /* draw up/down buttons */
+ DrawFrameRect(r.left, r.top, r.right, r.top + 9, colour, (up_clicked) ? FR_LOWERED : FR_NONE);
+ DrawString(r.left + up_clicked, r.right + up_clicked, r.top + up_clicked, UPARROW, TC_BLACK, SA_CENTER);
- int c = GB(wi->data, 0, 8);
- int amt1 = (wi->right - wi->left + 1) / c;
+ DrawFrameRect(r.left, r.bottom - 9, r.right, r.bottom, colour, (down_clicked) ? FR_LOWERED : FR_NONE);
+ DrawString(r.left + down_clicked, r.right + down_clicked, r.bottom - 9 + down_clicked, DOWNARROW, TC_BLACK, SA_CENTER);
- int d = GB(wi->data, 8, 8);
- int amt2 = (wi->bottom - wi->top + 1) / d;
+ int c1 = _colour_gradient[colour & 0xF][3];
+ int c2 = _colour_gradient[colour & 0xF][7];
- int colour = _colour_gradient[wi->colour & 0xF][6];
+ /* draw "shaded" background */
+ GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c2);
+ GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c1, FILLRECT_CHECKER);
- int x = r.left;
- for (int ctr = c; ctr > 1; ctr--) {
- x += amt1;
- GfxFillRect(x, r.top + 1, x, r.bottom - 1, colour);
- }
+ /* draw shaded lines */
+ GfxFillRect(r.left + 2, r.top + 10, r.left + 2, r.bottom - 10, c1);
+ GfxFillRect(r.left + 3, r.top + 10, r.left + 3, r.bottom - 10, c2);
+ GfxFillRect(r.left + 7, r.top + 10, r.left + 7, r.bottom - 10, c1);
+ GfxFillRect(r.left + 8, r.top + 10, r.left + 8, r.bottom - 10, c2);
- x = r.top;
- for (int ctr = d; ctr > 1; ctr--) {
- x += amt2;
- GfxFillRect(r.left + 1, x, r.right - 1, x, colour);
- }
+ Point pt = HandleScrollbarHittest(scrollbar, r.top, r.bottom);
+ DrawFrameRect(r.left, pt.x, r.right, pt.y, colour, bar_dragged ? FR_LOWERED : FR_NONE);
+}
- colour = _colour_gradient[wi->colour & 0xF][4];
+/**
+ * Draw a horizontal scrollbar.
+ * @param r Rectangle of the scrollbar widget.
+ * @param colour Colour of the scrollbar widget.
+ * @param left_clicked Left-arrow is clicked.
+ * @param bar_dragged Bar is dragged.
+ * @param right_clicked Right-arrow is clicked.
+ * @param scrollbar Scrollbar size, offset, and capacity information.
+ */
+static inline void DrawHorizontalScrollbar(const Rect &r, Colours colour, bool left_clicked, bool bar_dragged, bool right_clicked, const Scrollbar *scrollbar)
+{
+ assert(r.bottom - r.top == 11); // To ensure the same sizes are used everywhere!
- x = r.left - 1;
- for (int ctr = c; ctr > 1; ctr--) {
- x += amt1;
- GfxFillRect(x, r.top + 1, x, r.bottom - 1, colour);
- }
+ DrawFrameRect(r.left, r.top, r.left + 9, r.bottom, colour, left_clicked ? FR_LOWERED : FR_NONE);
+ DrawSprite(SPR_ARROW_LEFT, PAL_NONE, r.left + 1 + left_clicked, r.top + 1 + left_clicked);
- x = r.top - 1;
- for (int ctr = d; ctr > 1; ctr--) {
- x += amt2;
- GfxFillRect(r.left + 1, x, r.right - 1, x, colour);
- }
+ DrawFrameRect(r.right - 9, r.top, r.right, r.bottom, colour, right_clicked ? FR_LOWERED : FR_NONE);
+ DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - 8 + right_clicked, r.top + 1 + right_clicked);
- break;
- }
+ int c1 = _colour_gradient[colour & 0xF][3];
+ int c2 = _colour_gradient[colour & 0xF][7];
- /* vertical scrollbar */
- case WWT_SCROLLBAR: {
- assert(wi->data == 0);
- assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere!
+ /* draw "shaded" background */
+ GfxFillRect(r.left + 10, r.top, r.right - 10, r.bottom, c2);
+ GfxFillRect(r.left + 10, r.top, r.right - 10, r.bottom, c1, FILLRECT_CHECKER);
- /* draw up/down buttons */
- clicked = ((this->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_UP);
- DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawString(r.left + clicked, r.right + clicked, r.top + clicked, UPARROW, TC_BLACK, SA_CENTER);
+ /* draw shaded lines */
+ GfxFillRect(r.left + 10, r.top + 2, r.right - 10, r.top + 2, c1);
+ GfxFillRect(r.left + 10, r.top + 3, r.right - 10, r.top + 3, c2);
+ GfxFillRect(r.left + 10, r.top + 7, r.right - 10, r.top + 7, c1);
+ GfxFillRect(r.left + 10, r.top + 8, r.right - 10, r.top + 8, c2);
- clicked = (((this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_DOWN));
- DrawFrameRect(r.left, r.bottom - 9, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawString(r.left + clicked, r.right + clicked, r.bottom - 9 + clicked, DOWNARROW, TC_BLACK, SA_CENTER);
+ /* draw actual scrollbar */
+ Point pt = HandleScrollbarHittest(scrollbar, r.left, r.right);
+ DrawFrameRect(pt.x, r.top, pt.y, r.bottom, colour, bar_dragged ? FR_LOWERED : FR_NONE);
+}
- int c1 = _colour_gradient[wi->colour & 0xF][3];
- int c2 = _colour_gradient[wi->colour & 0xF][7];
+/**
+ * Draw a frame widget.
+ * @param r Rectangle of the frame.
+ * @param colour Colour of the frame.
+ * @param str Text of the frame.
+ */
+static inline void DrawFrame(const Rect &r, Colours colour, StringID str)
+{
+ int x2 = r.left; // by default the left side is the left side of the widget
- /* draw "shaded" background */
- GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c2);
- GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c1, FILLRECT_CHECKER);
+ if (str != STR_NULL) x2 = DrawString(r.left + 6, r.right - 6, r.top, str);
- /* draw shaded lines */
- GfxFillRect(r.left + 2, r.top + 10, r.left + 2, r.bottom - 10, c1);
- GfxFillRect(r.left + 3, r.top + 10, r.left + 3, r.bottom - 10, c2);
- GfxFillRect(r.left + 7, r.top + 10, r.left + 7, r.bottom - 10, c1);
- GfxFillRect(r.left + 8, r.top + 10, r.left + 8, r.bottom - 10, c2);
+ int c1 = _colour_gradient[colour][3];
+ int c2 = _colour_gradient[colour][7];
- Point pt = HandleScrollbarHittest(&this->vscroll, r.top, r.bottom);
- DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->colour, (this->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_MIDDLE ? FR_LOWERED : FR_NONE);
- break;
- }
+ if (_dynlang.text_dir == TD_LTR) {
+ /* Line from upper left corner to start of text */
+ GfxFillRect(r.left, r.top + 4, r.left + 4, r.top + 4, c1);
+ GfxFillRect(r.left + 1, r.top + 5, r.left + 4, r.top + 5, c2);
- case WWT_SCROLL2BAR: {
- assert(wi->data == 0);
- assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere!
+ /* Line from end of text to upper right corner */
+ GfxFillRect(x2, r.top + 4, r.right - 1, r.top + 4, c1);
+ GfxFillRect(x2, r.top + 5, r.right - 2, r.top + 5, c2);
+ } else {
+ /* Line from upper left corner to start of text */
+ GfxFillRect(r.left, r.top + 4, x2 - 2, r.top + 4, c1);
+ GfxFillRect(r.left + 1, r.top + 5, x2 - 2, r.top + 5, c2);
- /* draw up/down buttons */
- clicked = ((this->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_UP | WF_SCROLL2));
- DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawString(r.left + clicked, r.right + clicked, r.top + clicked, UPARROW, TC_BLACK, SA_CENTER);
+ /* Line from end of text to upper right corner */
+ GfxFillRect(r.right - 5, r.top + 4, r.right - 1, r.top + 4, c1);
+ GfxFillRect(r.right - 5, r.top + 5, r.right - 2, r.top + 5, c2);
+ }
- clicked = ((this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_DOWN | WF_SCROLL2));
- DrawFrameRect(r.left, r.bottom - 9, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawString(r.left + clicked, r.right + clicked, r.bottom - 9 + clicked, DOWNARROW, TC_BLACK, SA_CENTER);
+ /* Line from upper left corner to bottom left corner */
+ GfxFillRect(r.left, r.top + 5, r.left, r.bottom - 1, c1);
+ GfxFillRect(r.left + 1, r.top + 6, r.left + 1, r.bottom - 2, c2);
- int c1 = _colour_gradient[wi->colour & 0xF][3];
- int c2 = _colour_gradient[wi->colour & 0xF][7];
+ /* Line from upper right corner to bottom right corner */
+ GfxFillRect(r.right - 1, r.top + 5, r.right - 1, r.bottom - 2, c1);
+ GfxFillRect(r.right, r.top + 4, r.right, r.bottom - 1, c2);
- /* draw "shaded" background */
- GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c2);
- GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c1, FILLRECT_CHECKER);
+ GfxFillRect(r.left + 1, r.bottom - 1, r.right - 1, r.bottom - 1, c1);
+ GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2);
+}
- /* draw shaded lines */
- GfxFillRect(r.left + 2, r.top + 10, r.left + 2, r.bottom - 10, c1);
- GfxFillRect(r.left + 3, r.top + 10, r.left + 3, r.bottom - 10, c2);
- GfxFillRect(r.left + 7, r.top + 10, r.left + 7, r.bottom - 10, c1);
- GfxFillRect(r.left + 8, r.top + 10, r.left + 8, r.bottom - 10, c2);
+/**
+ * Draw a sticky box.
+ * @param r Rectangle of the box.
+ * @param colour Colour of the sticky box.
+ * @param clicked Box is lowered.
+ */
+static inline void DrawStickyBox(const Rect &r, Colours colour, bool clicked)
+{
+ assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere!
+ DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
+ DrawSprite((clicked) ? SPR_PIN_UP : SPR_PIN_DOWN, PAL_NONE, r.left + 2 + clicked, r.top + 3 + clicked);
+}
- Point pt = HandleScrollbarHittest(&this->vscroll2, r.top, r.bottom);
- DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->colour, (this->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_MIDDLE | WF_SCROLL2) ? FR_LOWERED : FR_NONE);
- break;
- }
+/**
+ * Draw a resize box.
+ * @param r Rectangle of the box.
+ * @param colour Colour of the resize box.
+ * @param at_left Resize box is at left-side of the window,
+ * @param clicked Box is lowered.
+ */
+static inline void DrawResizeBox(const Rect &r, Colours colour, bool at_left, bool clicked)
+{
+ assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere!
+ DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
+ if (at_left) {
+ DrawSprite(SPR_WINDOW_RESIZE_LEFT, PAL_NONE, r.left + 2, r.top + 3 + clicked);
+ } else {
+ DrawSprite(SPR_WINDOW_RESIZE_RIGHT, PAL_NONE, r.left + 3 + clicked, r.top + 3 + clicked);
+ }
+}
- /* horizontal scrollbar */
- case WWT_HSCROLLBAR: {
- assert(wi->data == 0);
- assert(r.bottom - r.top == 11); // To ensure the same sizes are used everywhere!
+/**
+ * Draw a close box.
+ * @param r Rectangle of the box.
+ * @param colour Colour of the close box.
+ * @param str Cross to draw (#STR_BLACK_CROSS or #STR_SILVER_CROSS).
+ */
+static inline void DrawCloseBox(const Rect &r, Colours colour, StringID str)
+{
+ assert(str == STR_BLACK_CROSS || str == STR_SILVER_CROSS); // black or silver cross
+ assert(r.right - r.left == 10); // To ensure the same sizes are used everywhere
- clicked = ((this->flags4 & (WF_SCROLL_UP | WF_HSCROLL)) == (WF_SCROLL_UP | WF_HSCROLL));
- DrawFrameRect(r.left, r.top, r.left + 9, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawSprite(SPR_ARROW_LEFT, PAL_NONE, r.left + 1 + clicked, r.top + 1 + clicked);
+ DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, FR_NONE);
+ DrawString(r.left, r.right, r.top + 2, str, TC_FROMSTRING, SA_CENTER);
+}
- clicked = ((this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL)) == (WF_SCROLL_DOWN | WF_HSCROLL));
- DrawFrameRect(r.right - 9, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - 8 + clicked, r.top + 1 + clicked);
+/**
+ * Draw a caption bar.
+ * @param r Rectangle of the bar.
+ * @param colour Colour of the window.
+ * @param owner 'Owner' of the window.
+ * @param str Text to draw in the bar.
+ */
+static inline void DrawCaption(const Rect &r, Colours colour, Owner owner, StringID str)
+{
+ assert(r.bottom - r.top == 13); // To ensure the same sizes are used everywhere!
+ DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, FR_BORDERONLY);
+ DrawFrameRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, colour, (owner == INVALID_OWNER) ? FR_LOWERED | FR_DARKENED : FR_LOWERED | FR_DARKENED | FR_BORDERONLY);
- int c1 = _colour_gradient[wi->colour & 0xF][3];
- int c2 = _colour_gradient[wi->colour & 0xF][7];
+ if (owner != INVALID_OWNER) {
+ GfxFillRect(r.left + 2, r.top + 2, r.right - 2, r.bottom - 2, _colour_gradient[_company_colours[owner]][4]);
+ }
- /* draw "shaded" background */
- GfxFillRect(r.left + 10, r.top, r.right - 10, r.bottom, c2);
- GfxFillRect(r.left + 10, r.top, r.right - 10, r.bottom, c1, FILLRECT_CHECKER);
+ DrawString(r.left + 2, r.right - 2, r.top + 2, str, TC_FROMSTRING, SA_CENTER);
+}
- /* draw shaded lines */
- GfxFillRect(r.left + 10, r.top + 2, r.right - 10, r.top + 2, c1);
- GfxFillRect(r.left + 10, r.top + 3, r.right - 10, r.top + 3, c2);
- GfxFillRect(r.left + 10, r.top + 7, r.right - 10, r.top + 7, c1);
- GfxFillRect(r.left + 10, r.top + 8, r.right - 10, r.top + 8, c2);
+static inline void DrawDropdown(const Rect &r, Colours colour, bool clicked, StringID str)
+{
+ assert(r.bottom - r.top == 11); // ensure consistent size
- /* draw actual scrollbar */
- Point pt = HandleScrollbarHittest(&this->hscroll, r.left, r.right);
- DrawFrameRect(pt.x, r.top, pt.y, r.bottom, wi->colour, (this->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == (WF_SCROLL_MIDDLE | WF_HSCROLL) ? FR_LOWERED : FR_NONE);
+ if (_dynlang.text_dir == TD_LTR) {
+ DrawFrameRect(r.left, r.top, r.right - 12, r.bottom, colour, FR_NONE);
+ DrawFrameRect(r.right - 11, r.top, r.right, r.bottom, colour, clicked ? FR_LOWERED : FR_NONE);
+ DrawString(r.right - (clicked ? 10 : 11), r.right, r.top + (clicked ? 2 : 1), STR_ARROW_DOWN, TC_BLACK, SA_CENTER);
+ if (str != STR_NULL) DrawString(r.left + 2, r.right - 14, r.top + 1, str, TC_BLACK);
+ } else {
+ DrawFrameRect(r.left + 12, r.top, r.right, r.bottom, colour, FR_NONE);
+ DrawFrameRect(r.left, r.top, r.left + 11, r.bottom, colour, clicked ? FR_LOWERED : FR_NONE);
+ DrawString(r.left + clicked, r.left + 11, r.top + (clicked ? 2 : 1), STR_ARROW_DOWN, TC_BLACK, SA_CENTER);
+ if (str != STR_NULL) DrawString(r.left + 14, r.right - 2, r.top + 1, str, TC_BLACK);
+ }
+}
- break;
- }
+/**
+ * Paint all widgets of a window.
+ */
+void Window::DrawWidgets() const
+{
+ const DrawPixelInfo *dpi = _cur_dpi;
- case WWT_FRAME: {
- const StringID str = wi->data;
- int x2 = r.left; // by default the left side is the left side of the widget
+ for (uint i = 0; i < this->widget_count; i++) {
+ const Widget *wi = &this->widget[i];
+ bool clicked = this->IsWidgetLowered(i);
+ Rect r;
- if (str != STR_NULL) x2 = DrawString(r.left + 6, r.right - 6, r.top, str);
+ if (dpi->left > (r.right = wi->right) ||
+ dpi->left + dpi->width <= (r.left = wi->left) ||
+ dpi->top > (r.bottom = wi->bottom) ||
+ dpi->top + dpi->height <= (r.top = wi->top) ||
+ this->IsWidgetHidden(i)) {
+ continue;
+ }
- int c1 = _colour_gradient[wi->colour][3];
- int c2 = _colour_gradient[wi->colour][7];
+ switch (wi->type & WWT_MASK) {
+ case WWT_IMGBTN:
+ case WWT_IMGBTN_2:
+ DrawImageButtons(r, wi->type,wi->colour, clicked, wi->data);
+ break;
- if (_dynlang.text_dir == TD_LTR) {
- /* Line from upper left corner to start of text */
- GfxFillRect(r.left, r.top + 4, r.left + 4, r.top + 4, c1);
- GfxFillRect(r.left + 1, r.top + 5, r.left + 4, r.top + 5, c2);
+ case WWT_PANEL:
+ assert(wi->data == 0);
+ DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
+ break;
- /* Line from end of text to upper right corner */
- GfxFillRect(x2, r.top + 4, r.right - 1, r.top + 4, c1);
- GfxFillRect(x2, r.top + 5, r.right - 2, r.top + 5, c2);
- } else {
- /* Line from upper left corner to start of text */
- GfxFillRect(r.left, r.top + 4, x2 - 2, r.top + 4, c1);
- GfxFillRect(r.left + 1, r.top + 5, x2 - 2, r.top + 5, c2);
+ case WWT_EDITBOX:
+ DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, FR_LOWERED | FR_DARKENED);
+ break;
- /* Line from end of text to upper right corner */
- GfxFillRect(r.right - 5, r.top + 4, r.right - 1, r.top + 4, c1);
- GfxFillRect(r.right - 5, r.top + 5, r.right - 2, r.top + 5, c2);
- }
+ case WWT_TEXTBTN:
+ case WWT_TEXTBTN_2:
+ DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
+ /* FALL THROUGH */
- /* Line from upper left corner to bottom left corner */
- GfxFillRect(r.left, r.top + 5, r.left, r.bottom - 1, c1);
- GfxFillRect(r.left + 1, r.top + 6, r.left + 1, r.bottom - 2, c2);
+ case WWT_LABEL:
+ DrawLabel(r, wi->type, clicked, wi->data);
+ break;
- /* Line from upper right corner to bottom right corner */
- GfxFillRect(r.right - 1, r.top + 5, r.right - 1, r.bottom - 2, c1);
- GfxFillRect(r.right, r.top + 4, r.right, r.bottom - 1, c2);
+ case WWT_TEXT:
+ DrawText(r, (TextColour)wi->colour, wi->data);
+ break;
- GfxFillRect(r.left + 1, r.bottom - 1, r.right - 1, r.bottom - 1, c1);
- GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2);
+ case WWT_INSET:
+ DrawInset(r, wi->colour, wi->data);
+ break;
+ case WWT_MATRIX:
+ DrawMatrix(r, wi->colour, clicked, wi->data);
break;
- }
- case WWT_STICKYBOX:
+ /* vertical scrollbar */
+ case WWT_SCROLLBAR:
assert(wi->data == 0);
- assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere!
+ DrawVerticalScrollbar(r, wi->colour, (this->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_UP,
+ (this->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_MIDDLE,
+ (this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_DOWN, &this->vscroll);
+ break;
- clicked = !!(this->flags4 & WF_STICKY);
- DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawSprite((clicked) ? SPR_PIN_UP : SPR_PIN_DOWN, PAL_NONE, r.left + 2 + clicked, r.top + 3 + clicked);
+ case WWT_SCROLL2BAR:
+ assert(wi->data == 0);
+ DrawVerticalScrollbar(r, wi->colour, (this->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_UP | WF_SCROLL2),
+ (this->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_MIDDLE | WF_SCROLL2),
+ (this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_DOWN | WF_SCROLL2), &this->vscroll2);
break;
- case WWT_RESIZEBOX:
+ /* horizontal scrollbar */
+ case WWT_HSCROLLBAR:
assert(wi->data == 0);
- assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere!
+ DrawHorizontalScrollbar(r, wi->colour, (this->flags4 & (WF_SCROLL_UP | WF_HSCROLL)) == (WF_SCROLL_UP | WF_HSCROLL),
+ (this->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == (WF_SCROLL_MIDDLE | WF_HSCROLL),
+ (this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL)) == (WF_SCROLL_DOWN | WF_HSCROLL), &this->hscroll);
+ break;
- clicked = !!(this->flags4 & WF_SIZING);
- DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
- if (wi->left < (this->width / 2)) {
- DrawSprite(SPR_WINDOW_RESIZE_LEFT, PAL_NONE, r.left + 2, r.top + 3 + clicked);
- } else {
- DrawSprite(SPR_WINDOW_RESIZE_RIGHT, PAL_NONE, r.left + 3 + clicked, r.top + 3 + clicked);
- }
+ case WWT_FRAME:
+ DrawFrame(r, wi->colour, wi->data);
break;
- case WWT_CLOSEBOX: {
- const StringID str = wi->data;
+ case WWT_STICKYBOX:
+ assert(wi->data == 0);
+ DrawStickyBox(r, wi->colour, !!(this->flags4 & WF_STICKY));
+ break;
- assert(str == STR_BLACK_CROSS || str == STR_SILVER_CROSS); // black or silver cross
- assert(r.right - r.left == 10); // To ensure the same sizes are used everywhere
+ case WWT_RESIZEBOX:
+ assert(wi->data == 0);
+ DrawResizeBox(r, wi->colour, wi->left < (this->width / 2), !!(this->flags4 & WF_SIZING));
+ break;
- DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, FR_NONE);
- DrawString(r.left, r.right, r.top + 2, str, TC_FROMSTRING, SA_CENTER);
+ case WWT_CLOSEBOX:
+ DrawCloseBox(r, wi->colour, wi->data);
break;
- }
case WWT_CAPTION:
- assert(r.bottom - r.top == 13); // To ensure the same sizes are used everywhere!
- DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, FR_BORDERONLY);
- DrawFrameRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, wi->colour, (this->owner == INVALID_OWNER) ? FR_LOWERED | FR_DARKENED : FR_LOWERED | FR_DARKENED | FR_BORDERONLY);
-
- if (this->owner != INVALID_OWNER) {
- GfxFillRect(r.left + 2, r.top + 2, r.right - 2, r.bottom - 2, _colour_gradient[_company_colours[this->owner]][4]);
- }
-
- DrawString(r.left + 2, r.right - 2, r.top + 2, wi->data, TC_FROMSTRING, SA_CENTER);
+ DrawCaption(r, wi->colour, this->owner, wi->data);
break;
- case WWT_DROPDOWN: {
- assert(r.bottom - r.top == 11); // ensure consistent size
-
- StringID str = wi->data;
- if (_dynlang.text_dir == TD_LTR) {
- DrawFrameRect(r.left, r.top, r.right - 12, r.bottom, wi->colour, FR_NONE);
- DrawFrameRect(r.right - 11, r.top, r.right, r.bottom, wi->colour, clicked ? FR_LOWERED : FR_NONE);
- DrawString(r.right - (clicked ? 10 : 11), r.right, r.top + (clicked ? 2 : 1), STR_ARROW_DOWN, TC_BLACK, SA_CENTER);
- if (str != STR_NULL) DrawString(r.left + 2, r.right - 14, r.top + 1, str, TC_BLACK);
- } else {
- DrawFrameRect(r.left + 12, r.top, r.right, r.bottom, wi->colour, FR_NONE);
- DrawFrameRect(r.left, r.top, r.left + 11, r.bottom, wi->colour, clicked ? FR_LOWERED : FR_NONE);
- DrawString(r.left + clicked, r.left + 11, r.top + (clicked ? 2 : 1), STR_ARROW_DOWN, TC_BLACK, SA_CENTER);
- if (str != STR_NULL) DrawString(r.left + 14, r.right - 2, r.top + 1, str, TC_BLACK);
- }
+ case WWT_DROPDOWN:
+ DrawDropdown(r, wi->colour, clicked, wi->data);
break;
}
- }
if (this->IsWidgetDisabled(i)) {
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, _colour_gradient[wi->colour & 0xF][2], FILLRECT_CHECKER);