comparison src/widget.cpp @ 11999:b8e87660b9fc draft

(svn r16405) -Codechange: Move widget drawing code to functions to allow re-use.
author alberth <alberth@openttd.org>
date Sat, 23 May 2009 18:06:29 +0000
parents de771cbe234d
children d092f17a921d
comparison
equal deleted inserted replaced
11998:683ebb3d3eb6 11999:b8e87660b9fc
197 GfxFillRect(left + 1, top + 1, right - 1, bottom - 1, interior); 197 GfxFillRect(left + 1, top + 1, right - 1, bottom - 1, interior);
198 } 198 }
199 } 199 }
200 } 200 }
201 201
202 /**
203 * Draw an image button.
204 * @param r Rectangle of the button.
205 * @param type Widget type (#WWT_IMGBTN or #WWT_IMGBTN_2).
206 * @param colour Colour of the button.
207 * @param clicked Button is lowered.
208 * @param img Sprite to draw.
209 */
210 static inline void DrawImageButtons(const Rect &r, WidgetType type, Colours colour, bool clicked, SpriteID img)
211 {
212 assert(img != 0);
213 DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
214
215 /* show different image when clicked for WWT_IMGBTN_2 */
216 if ((type & WWT_MASK) == WWT_IMGBTN_2 && clicked) img++;
217 DrawSprite(img, PAL_NONE, r.left + 1 + clicked, r.top + 1 + clicked);
218 }
219
220 /**
221 * Draw the label-part of a widget.
222 * @param r Rectangle of the label background.
223 * @param type Widget type (#WWT_TEXTBTN, #WWT_TEXTBTN_2, or #WWT_LABEL).
224 * @param clicked Label is rendered lowered.
225 * @param str Text to draw.
226 */
227 static inline void DrawLabel(const Rect &r, WidgetType type, bool clicked, StringID str)
228 {
229 if ((type & WWT_MASK) == WWT_TEXTBTN_2 && clicked) str++;
230 DrawString(r.left + clicked, r.right + clicked, ((r.top + r.bottom + 1) >> 1) - 5 + clicked, str, TC_FROMSTRING, SA_CENTER);
231 }
232
233 /**
234 * Draw text.
235 * @param r Rectangle of the background.
236 * @param colour Colour of the text.
237 * @param str Text to draw.
238 */
239 static inline void DrawText(const Rect &r, TextColour colour, StringID str)
240 {
241 if (str != STR_NULL) DrawString(r.left, r.right, r.top, str, colour);
242 }
243
244 /**
245 * Draw an inset widget.
246 * @param r Rectangle of the background.
247 * @param colour Colour of the inset.
248 * @param str Text to draw.
249 */
250 static inline void DrawInset(const Rect &r, Colours colour, StringID str)
251 {
252 DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, FR_LOWERED | FR_DARKENED);
253 if (str != STR_NULL) DrawString(r.left + 2, r.right - 2, r.top + 1, str);
254 }
255
256 /**
257 * Draw a matrix widget.
258 * @param r Rectangle of the matrix background.
259 * @param colour Colour of the background.
260 * @param clicked Matrix is rendered lowered.
261 * @param data Data of the widget.
262 */
263 static inline void DrawMatrix(const Rect &r, Colours colour, bool clicked, uint16 data)
264 {
265 DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
266
267 int c = GB(data, 0, 8);
268 int amt1 = (r.right - r.left + 1) / c;
269
270 int d = GB(data, 8, 8);
271 int amt2 = (r.bottom - r.top + 1) / d;
272
273 int col = _colour_gradient[colour & 0xF][6];
274
275 int x = r.left;
276 for (int ctr = c; ctr > 1; ctr--) {
277 x += amt1;
278 GfxFillRect(x, r.top + 1, x, r.bottom - 1, col);
279 }
280
281 x = r.top;
282 for (int ctr = d; ctr > 1; ctr--) {
283 x += amt2;
284 GfxFillRect(r.left + 1, x, r.right - 1, x, col);
285 }
286
287 col = _colour_gradient[colour & 0xF][4];
288
289 x = r.left - 1;
290 for (int ctr = c; ctr > 1; ctr--) {
291 x += amt1;
292 GfxFillRect(x, r.top + 1, x, r.bottom - 1, col);
293 }
294
295 x = r.top - 1;
296 for (int ctr = d; ctr > 1; ctr--) {
297 x += amt2;
298 GfxFillRect(r.left + 1, x, r.right - 1, x, col);
299 }
300 }
301
302 /**
303 * Draw a vertical scrollbar.
304 * @param r Rectangle of the scrollbar widget.
305 * @param colour Colour of the scrollbar widget.
306 * @param up_clicked Up-arrow is clicked.
307 * @param bar_dragged Bar is dragged.
308 * @param down_clicked Down-arrow is clicked.
309 * @param scrollbar Scrollbar size, offset, and capacity information.
310 */
311 static inline void DrawVerticalScrollbar(const Rect &r, Colours colour, bool up_clicked, bool bar_dragged, bool down_clicked, const Scrollbar *scrollbar)
312 {
313 assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere!
314
315 /* draw up/down buttons */
316 DrawFrameRect(r.left, r.top, r.right, r.top + 9, colour, (up_clicked) ? FR_LOWERED : FR_NONE);
317 DrawString(r.left + up_clicked, r.right + up_clicked, r.top + up_clicked, UPARROW, TC_BLACK, SA_CENTER);
318
319 DrawFrameRect(r.left, r.bottom - 9, r.right, r.bottom, colour, (down_clicked) ? FR_LOWERED : FR_NONE);
320 DrawString(r.left + down_clicked, r.right + down_clicked, r.bottom - 9 + down_clicked, DOWNARROW, TC_BLACK, SA_CENTER);
321
322 int c1 = _colour_gradient[colour & 0xF][3];
323 int c2 = _colour_gradient[colour & 0xF][7];
324
325 /* draw "shaded" background */
326 GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c2);
327 GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c1, FILLRECT_CHECKER);
328
329 /* draw shaded lines */
330 GfxFillRect(r.left + 2, r.top + 10, r.left + 2, r.bottom - 10, c1);
331 GfxFillRect(r.left + 3, r.top + 10, r.left + 3, r.bottom - 10, c2);
332 GfxFillRect(r.left + 7, r.top + 10, r.left + 7, r.bottom - 10, c1);
333 GfxFillRect(r.left + 8, r.top + 10, r.left + 8, r.bottom - 10, c2);
334
335 Point pt = HandleScrollbarHittest(scrollbar, r.top, r.bottom);
336 DrawFrameRect(r.left, pt.x, r.right, pt.y, colour, bar_dragged ? FR_LOWERED : FR_NONE);
337 }
338
339 /**
340 * Draw a horizontal scrollbar.
341 * @param r Rectangle of the scrollbar widget.
342 * @param colour Colour of the scrollbar widget.
343 * @param left_clicked Left-arrow is clicked.
344 * @param bar_dragged Bar is dragged.
345 * @param right_clicked Right-arrow is clicked.
346 * @param scrollbar Scrollbar size, offset, and capacity information.
347 */
348 static inline void DrawHorizontalScrollbar(const Rect &r, Colours colour, bool left_clicked, bool bar_dragged, bool right_clicked, const Scrollbar *scrollbar)
349 {
350 assert(r.bottom - r.top == 11); // To ensure the same sizes are used everywhere!
351
352 DrawFrameRect(r.left, r.top, r.left + 9, r.bottom, colour, left_clicked ? FR_LOWERED : FR_NONE);
353 DrawSprite(SPR_ARROW_LEFT, PAL_NONE, r.left + 1 + left_clicked, r.top + 1 + left_clicked);
354
355 DrawFrameRect(r.right - 9, r.top, r.right, r.bottom, colour, right_clicked ? FR_LOWERED : FR_NONE);
356 DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - 8 + right_clicked, r.top + 1 + right_clicked);
357
358 int c1 = _colour_gradient[colour & 0xF][3];
359 int c2 = _colour_gradient[colour & 0xF][7];
360
361 /* draw "shaded" background */
362 GfxFillRect(r.left + 10, r.top, r.right - 10, r.bottom, c2);
363 GfxFillRect(r.left + 10, r.top, r.right - 10, r.bottom, c1, FILLRECT_CHECKER);
364
365 /* draw shaded lines */
366 GfxFillRect(r.left + 10, r.top + 2, r.right - 10, r.top + 2, c1);
367 GfxFillRect(r.left + 10, r.top + 3, r.right - 10, r.top + 3, c2);
368 GfxFillRect(r.left + 10, r.top + 7, r.right - 10, r.top + 7, c1);
369 GfxFillRect(r.left + 10, r.top + 8, r.right - 10, r.top + 8, c2);
370
371 /* draw actual scrollbar */
372 Point pt = HandleScrollbarHittest(scrollbar, r.left, r.right);
373 DrawFrameRect(pt.x, r.top, pt.y, r.bottom, colour, bar_dragged ? FR_LOWERED : FR_NONE);
374 }
375
376 /**
377 * Draw a frame widget.
378 * @param r Rectangle of the frame.
379 * @param colour Colour of the frame.
380 * @param str Text of the frame.
381 */
382 static inline void DrawFrame(const Rect &r, Colours colour, StringID str)
383 {
384 int x2 = r.left; // by default the left side is the left side of the widget
385
386 if (str != STR_NULL) x2 = DrawString(r.left + 6, r.right - 6, r.top, str);
387
388 int c1 = _colour_gradient[colour][3];
389 int c2 = _colour_gradient[colour][7];
390
391 if (_dynlang.text_dir == TD_LTR) {
392 /* Line from upper left corner to start of text */
393 GfxFillRect(r.left, r.top + 4, r.left + 4, r.top + 4, c1);
394 GfxFillRect(r.left + 1, r.top + 5, r.left + 4, r.top + 5, c2);
395
396 /* Line from end of text to upper right corner */
397 GfxFillRect(x2, r.top + 4, r.right - 1, r.top + 4, c1);
398 GfxFillRect(x2, r.top + 5, r.right - 2, r.top + 5, c2);
399 } else {
400 /* Line from upper left corner to start of text */
401 GfxFillRect(r.left, r.top + 4, x2 - 2, r.top + 4, c1);
402 GfxFillRect(r.left + 1, r.top + 5, x2 - 2, r.top + 5, c2);
403
404 /* Line from end of text to upper right corner */
405 GfxFillRect(r.right - 5, r.top + 4, r.right - 1, r.top + 4, c1);
406 GfxFillRect(r.right - 5, r.top + 5, r.right - 2, r.top + 5, c2);
407 }
408
409 /* Line from upper left corner to bottom left corner */
410 GfxFillRect(r.left, r.top + 5, r.left, r.bottom - 1, c1);
411 GfxFillRect(r.left + 1, r.top + 6, r.left + 1, r.bottom - 2, c2);
412
413 /* Line from upper right corner to bottom right corner */
414 GfxFillRect(r.right - 1, r.top + 5, r.right - 1, r.bottom - 2, c1);
415 GfxFillRect(r.right, r.top + 4, r.right, r.bottom - 1, c2);
416
417 GfxFillRect(r.left + 1, r.bottom - 1, r.right - 1, r.bottom - 1, c1);
418 GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2);
419 }
420
421 /**
422 * Draw a sticky box.
423 * @param r Rectangle of the box.
424 * @param colour Colour of the sticky box.
425 * @param clicked Box is lowered.
426 */
427 static inline void DrawStickyBox(const Rect &r, Colours colour, bool clicked)
428 {
429 assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere!
430 DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
431 DrawSprite((clicked) ? SPR_PIN_UP : SPR_PIN_DOWN, PAL_NONE, r.left + 2 + clicked, r.top + 3 + clicked);
432 }
433
434 /**
435 * Draw a resize box.
436 * @param r Rectangle of the box.
437 * @param colour Colour of the resize box.
438 * @param at_left Resize box is at left-side of the window,
439 * @param clicked Box is lowered.
440 */
441 static inline void DrawResizeBox(const Rect &r, Colours colour, bool at_left, bool clicked)
442 {
443 assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere!
444 DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
445 if (at_left) {
446 DrawSprite(SPR_WINDOW_RESIZE_LEFT, PAL_NONE, r.left + 2, r.top + 3 + clicked);
447 } else {
448 DrawSprite(SPR_WINDOW_RESIZE_RIGHT, PAL_NONE, r.left + 3 + clicked, r.top + 3 + clicked);
449 }
450 }
451
452 /**
453 * Draw a close box.
454 * @param r Rectangle of the box.
455 * @param colour Colour of the close box.
456 * @param str Cross to draw (#STR_BLACK_CROSS or #STR_SILVER_CROSS).
457 */
458 static inline void DrawCloseBox(const Rect &r, Colours colour, StringID str)
459 {
460 assert(str == STR_BLACK_CROSS || str == STR_SILVER_CROSS); // black or silver cross
461 assert(r.right - r.left == 10); // To ensure the same sizes are used everywhere
462
463 DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, FR_NONE);
464 DrawString(r.left, r.right, r.top + 2, str, TC_FROMSTRING, SA_CENTER);
465 }
466
467 /**
468 * Draw a caption bar.
469 * @param r Rectangle of the bar.
470 * @param colour Colour of the window.
471 * @param owner 'Owner' of the window.
472 * @param str Text to draw in the bar.
473 */
474 static inline void DrawCaption(const Rect &r, Colours colour, Owner owner, StringID str)
475 {
476 assert(r.bottom - r.top == 13); // To ensure the same sizes are used everywhere!
477 DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, FR_BORDERONLY);
478 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);
479
480 if (owner != INVALID_OWNER) {
481 GfxFillRect(r.left + 2, r.top + 2, r.right - 2, r.bottom - 2, _colour_gradient[_company_colours[owner]][4]);
482 }
483
484 DrawString(r.left + 2, r.right - 2, r.top + 2, str, TC_FROMSTRING, SA_CENTER);
485 }
486
487 static inline void DrawDropdown(const Rect &r, Colours colour, bool clicked, StringID str)
488 {
489 assert(r.bottom - r.top == 11); // ensure consistent size
490
491 if (_dynlang.text_dir == TD_LTR) {
492 DrawFrameRect(r.left, r.top, r.right - 12, r.bottom, colour, FR_NONE);
493 DrawFrameRect(r.right - 11, r.top, r.right, r.bottom, colour, clicked ? FR_LOWERED : FR_NONE);
494 DrawString(r.right - (clicked ? 10 : 11), r.right, r.top + (clicked ? 2 : 1), STR_ARROW_DOWN, TC_BLACK, SA_CENTER);
495 if (str != STR_NULL) DrawString(r.left + 2, r.right - 14, r.top + 1, str, TC_BLACK);
496 } else {
497 DrawFrameRect(r.left + 12, r.top, r.right, r.bottom, colour, FR_NONE);
498 DrawFrameRect(r.left, r.top, r.left + 11, r.bottom, colour, clicked ? FR_LOWERED : FR_NONE);
499 DrawString(r.left + clicked, r.left + 11, r.top + (clicked ? 2 : 1), STR_ARROW_DOWN, TC_BLACK, SA_CENTER);
500 if (str != STR_NULL) DrawString(r.left + 14, r.right - 2, r.top + 1, str, TC_BLACK);
501 }
502 }
202 503
203 /** 504 /**
204 * Paint all widgets of a window. 505 * Paint all widgets of a window.
205 */ 506 */
206 void Window::DrawWidgets() const 507 void Window::DrawWidgets() const
220 continue; 521 continue;
221 } 522 }
222 523
223 switch (wi->type & WWT_MASK) { 524 switch (wi->type & WWT_MASK) {
224 case WWT_IMGBTN: 525 case WWT_IMGBTN:
225 case WWT_IMGBTN_2: { 526 case WWT_IMGBTN_2:
226 SpriteID img = wi->data; 527 DrawImageButtons(r, wi->type,wi->colour, clicked, wi->data);
227 assert(img != 0); 528 break;
228 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
229
230 /* show different image when clicked for WWT_IMGBTN_2 */
231 if ((wi->type & WWT_MASK) == WWT_IMGBTN_2 && clicked) img++;
232 DrawSprite(img, PAL_NONE, r.left + 1 + clicked, r.top + 1 + clicked);
233 break;
234 }
235 529
236 case WWT_PANEL: 530 case WWT_PANEL:
237 assert(wi->data == 0); 531 assert(wi->data == 0);
238 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE); 532 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
239 break; 533 break;
245 case WWT_TEXTBTN: 539 case WWT_TEXTBTN:
246 case WWT_TEXTBTN_2: 540 case WWT_TEXTBTN_2:
247 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE); 541 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
248 /* FALL THROUGH */ 542 /* FALL THROUGH */
249 543
250 case WWT_LABEL: { 544 case WWT_LABEL:
251 StringID str = wi->data; 545 DrawLabel(r, wi->type, clicked, wi->data);
252 546 break;
253 if ((wi->type & WWT_MASK) == WWT_TEXTBTN_2 && clicked) str++; 547
254 548 case WWT_TEXT:
255 DrawString(r.left + clicked, r.right + clicked, ((r.top + r.bottom + 1) >> 1) - 5 + clicked, str, TC_FROMSTRING, SA_CENTER); 549 DrawText(r, (TextColour)wi->colour, wi->data);
256 break; 550 break;
257 } 551
258 552 case WWT_INSET:
259 case WWT_TEXT: { 553 DrawInset(r, wi->colour, wi->data);
260 const StringID str = wi->data; 554 break;
261 555
262 if (str != STR_NULL) DrawString(r.left, r.right, r.top, str, (TextColour)wi->colour); 556 case WWT_MATRIX:
263 break; 557 DrawMatrix(r, wi->colour, clicked, wi->data);
264 } 558 break;
265
266 case WWT_INSET: {
267 const StringID str = wi->data;
268 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, FR_LOWERED | FR_DARKENED);
269
270 if (str != STR_NULL) DrawString(r.left + 2, r.right - 2, r.top + 1, str);
271 break;
272 }
273
274 case WWT_MATRIX: {
275 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
276
277 int c = GB(wi->data, 0, 8);
278 int amt1 = (wi->right - wi->left + 1) / c;
279
280 int d = GB(wi->data, 8, 8);
281 int amt2 = (wi->bottom - wi->top + 1) / d;
282
283 int colour = _colour_gradient[wi->colour & 0xF][6];
284
285 int x = r.left;
286 for (int ctr = c; ctr > 1; ctr--) {
287 x += amt1;
288 GfxFillRect(x, r.top + 1, x, r.bottom - 1, colour);
289 }
290
291 x = r.top;
292 for (int ctr = d; ctr > 1; ctr--) {
293 x += amt2;
294 GfxFillRect(r.left + 1, x, r.right - 1, x, colour);
295 }
296
297 colour = _colour_gradient[wi->colour & 0xF][4];
298
299 x = r.left - 1;
300 for (int ctr = c; ctr > 1; ctr--) {
301 x += amt1;
302 GfxFillRect(x, r.top + 1, x, r.bottom - 1, colour);
303 }
304
305 x = r.top - 1;
306 for (int ctr = d; ctr > 1; ctr--) {
307 x += amt2;
308 GfxFillRect(r.left + 1, x, r.right - 1, x, colour);
309 }
310
311 break;
312 }
313 559
314 /* vertical scrollbar */ 560 /* vertical scrollbar */
315 case WWT_SCROLLBAR: { 561 case WWT_SCROLLBAR:
316 assert(wi->data == 0); 562 assert(wi->data == 0);
317 assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere! 563 DrawVerticalScrollbar(r, wi->colour, (this->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_UP,
318 564 (this->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_MIDDLE,
319 /* draw up/down buttons */ 565 (this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_DOWN, &this->vscroll);
320 clicked = ((this->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_UP); 566 break;
321 DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->colour, (clicked) ? FR_LOWERED : FR_NONE); 567
322 DrawString(r.left + clicked, r.right + clicked, r.top + clicked, UPARROW, TC_BLACK, SA_CENTER); 568 case WWT_SCROLL2BAR:
323
324 clicked = (((this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_DOWN));
325 DrawFrameRect(r.left, r.bottom - 9, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
326 DrawString(r.left + clicked, r.right + clicked, r.bottom - 9 + clicked, DOWNARROW, TC_BLACK, SA_CENTER);
327
328 int c1 = _colour_gradient[wi->colour & 0xF][3];
329 int c2 = _colour_gradient[wi->colour & 0xF][7];
330
331 /* draw "shaded" background */
332 GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c2);
333 GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c1, FILLRECT_CHECKER);
334
335 /* draw shaded lines */
336 GfxFillRect(r.left + 2, r.top + 10, r.left + 2, r.bottom - 10, c1);
337 GfxFillRect(r.left + 3, r.top + 10, r.left + 3, r.bottom - 10, c2);
338 GfxFillRect(r.left + 7, r.top + 10, r.left + 7, r.bottom - 10, c1);
339 GfxFillRect(r.left + 8, r.top + 10, r.left + 8, r.bottom - 10, c2);
340
341 Point pt = HandleScrollbarHittest(&this->vscroll, r.top, r.bottom);
342 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);
343 break;
344 }
345
346 case WWT_SCROLL2BAR: {
347 assert(wi->data == 0); 569 assert(wi->data == 0);
348 assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere! 570 DrawVerticalScrollbar(r, wi->colour, (this->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_UP | WF_SCROLL2),
349 571 (this->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_MIDDLE | WF_SCROLL2),
350 /* draw up/down buttons */ 572 (this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_DOWN | WF_SCROLL2), &this->vscroll2);
351 clicked = ((this->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_UP | WF_SCROLL2)); 573 break;
352 DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
353 DrawString(r.left + clicked, r.right + clicked, r.top + clicked, UPARROW, TC_BLACK, SA_CENTER);
354
355 clicked = ((this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_DOWN | WF_SCROLL2));
356 DrawFrameRect(r.left, r.bottom - 9, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
357 DrawString(r.left + clicked, r.right + clicked, r.bottom - 9 + clicked, DOWNARROW, TC_BLACK, SA_CENTER);
358
359 int c1 = _colour_gradient[wi->colour & 0xF][3];
360 int c2 = _colour_gradient[wi->colour & 0xF][7];
361
362 /* draw "shaded" background */
363 GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c2);
364 GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c1, FILLRECT_CHECKER);
365
366 /* draw shaded lines */
367 GfxFillRect(r.left + 2, r.top + 10, r.left + 2, r.bottom - 10, c1);
368 GfxFillRect(r.left + 3, r.top + 10, r.left + 3, r.bottom - 10, c2);
369 GfxFillRect(r.left + 7, r.top + 10, r.left + 7, r.bottom - 10, c1);
370 GfxFillRect(r.left + 8, r.top + 10, r.left + 8, r.bottom - 10, c2);
371
372 Point pt = HandleScrollbarHittest(&this->vscroll2, r.top, r.bottom);
373 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);
374 break;
375 }
376 574
377 /* horizontal scrollbar */ 575 /* horizontal scrollbar */
378 case WWT_HSCROLLBAR: { 576 case WWT_HSCROLLBAR:
379 assert(wi->data == 0); 577 assert(wi->data == 0);
380 assert(r.bottom - r.top == 11); // To ensure the same sizes are used everywhere! 578 DrawHorizontalScrollbar(r, wi->colour, (this->flags4 & (WF_SCROLL_UP | WF_HSCROLL)) == (WF_SCROLL_UP | WF_HSCROLL),
381 579 (this->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == (WF_SCROLL_MIDDLE | WF_HSCROLL),
382 clicked = ((this->flags4 & (WF_SCROLL_UP | WF_HSCROLL)) == (WF_SCROLL_UP | WF_HSCROLL)); 580 (this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL)) == (WF_SCROLL_DOWN | WF_HSCROLL), &this->hscroll);
383 DrawFrameRect(r.left, r.top, r.left + 9, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE); 581 break;
384 DrawSprite(SPR_ARROW_LEFT, PAL_NONE, r.left + 1 + clicked, r.top + 1 + clicked); 582
385 583 case WWT_FRAME:
386 clicked = ((this->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL)) == (WF_SCROLL_DOWN | WF_HSCROLL)); 584 DrawFrame(r, wi->colour, wi->data);
387 DrawFrameRect(r.right - 9, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE); 585 break;
388 DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - 8 + clicked, r.top + 1 + clicked);
389
390 int c1 = _colour_gradient[wi->colour & 0xF][3];
391 int c2 = _colour_gradient[wi->colour & 0xF][7];
392
393 /* draw "shaded" background */
394 GfxFillRect(r.left + 10, r.top, r.right - 10, r.bottom, c2);
395 GfxFillRect(r.left + 10, r.top, r.right - 10, r.bottom, c1, FILLRECT_CHECKER);
396
397 /* draw shaded lines */
398 GfxFillRect(r.left + 10, r.top + 2, r.right - 10, r.top + 2, c1);
399 GfxFillRect(r.left + 10, r.top + 3, r.right - 10, r.top + 3, c2);
400 GfxFillRect(r.left + 10, r.top + 7, r.right - 10, r.top + 7, c1);
401 GfxFillRect(r.left + 10, r.top + 8, r.right - 10, r.top + 8, c2);
402
403 /* draw actual scrollbar */
404 Point pt = HandleScrollbarHittest(&this->hscroll, r.left, r.right);
405 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);
406
407 break;
408 }
409
410 case WWT_FRAME: {
411 const StringID str = wi->data;
412 int x2 = r.left; // by default the left side is the left side of the widget
413
414 if (str != STR_NULL) x2 = DrawString(r.left + 6, r.right - 6, r.top, str);
415
416 int c1 = _colour_gradient[wi->colour][3];
417 int c2 = _colour_gradient[wi->colour][7];
418
419 if (_dynlang.text_dir == TD_LTR) {
420 /* Line from upper left corner to start of text */
421 GfxFillRect(r.left, r.top + 4, r.left + 4, r.top + 4, c1);
422 GfxFillRect(r.left + 1, r.top + 5, r.left + 4, r.top + 5, c2);
423
424 /* Line from end of text to upper right corner */
425 GfxFillRect(x2, r.top + 4, r.right - 1, r.top + 4, c1);
426 GfxFillRect(x2, r.top + 5, r.right - 2, r.top + 5, c2);
427 } else {
428 /* Line from upper left corner to start of text */
429 GfxFillRect(r.left, r.top + 4, x2 - 2, r.top + 4, c1);
430 GfxFillRect(r.left + 1, r.top + 5, x2 - 2, r.top + 5, c2);
431
432 /* Line from end of text to upper right corner */
433 GfxFillRect(r.right - 5, r.top + 4, r.right - 1, r.top + 4, c1);
434 GfxFillRect(r.right - 5, r.top + 5, r.right - 2, r.top + 5, c2);
435 }
436
437 /* Line from upper left corner to bottom left corner */
438 GfxFillRect(r.left, r.top + 5, r.left, r.bottom - 1, c1);
439 GfxFillRect(r.left + 1, r.top + 6, r.left + 1, r.bottom - 2, c2);
440
441 /* Line from upper right corner to bottom right corner */
442 GfxFillRect(r.right - 1, r.top + 5, r.right - 1, r.bottom - 2, c1);
443 GfxFillRect(r.right, r.top + 4, r.right, r.bottom - 1, c2);
444
445 GfxFillRect(r.left + 1, r.bottom - 1, r.right - 1, r.bottom - 1, c1);
446 GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2);
447
448 break;
449 }
450 586
451 case WWT_STICKYBOX: 587 case WWT_STICKYBOX:
452 assert(wi->data == 0); 588 assert(wi->data == 0);
453 assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere! 589 DrawStickyBox(r, wi->colour, !!(this->flags4 & WF_STICKY));
454
455 clicked = !!(this->flags4 & WF_STICKY);
456 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE);
457 DrawSprite((clicked) ? SPR_PIN_UP : SPR_PIN_DOWN, PAL_NONE, r.left + 2 + clicked, r.top + 3 + clicked);
458 break; 590 break;
459 591
460 case WWT_RESIZEBOX: 592 case WWT_RESIZEBOX:
461 assert(wi->data == 0); 593 assert(wi->data == 0);
462 assert(r.right - r.left == 11); // To ensure the same sizes are used everywhere! 594 DrawResizeBox(r, wi->colour, wi->left < (this->width / 2), !!(this->flags4 & WF_SIZING));
463 595 break;
464 clicked = !!(this->flags4 & WF_SIZING); 596
465 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, (clicked) ? FR_LOWERED : FR_NONE); 597 case WWT_CLOSEBOX:
466 if (wi->left < (this->width / 2)) { 598 DrawCloseBox(r, wi->colour, wi->data);
467 DrawSprite(SPR_WINDOW_RESIZE_LEFT, PAL_NONE, r.left + 2, r.top + 3 + clicked); 599 break;
468 } else {
469 DrawSprite(SPR_WINDOW_RESIZE_RIGHT, PAL_NONE, r.left + 3 + clicked, r.top + 3 + clicked);
470 }
471 break;
472
473 case WWT_CLOSEBOX: {
474 const StringID str = wi->data;
475
476 assert(str == STR_BLACK_CROSS || str == STR_SILVER_CROSS); // black or silver cross
477 assert(r.right - r.left == 10); // To ensure the same sizes are used everywhere
478
479 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, FR_NONE);
480 DrawString(r.left, r.right, r.top + 2, str, TC_FROMSTRING, SA_CENTER);
481 break;
482 }
483 600
484 case WWT_CAPTION: 601 case WWT_CAPTION:
485 assert(r.bottom - r.top == 13); // To ensure the same sizes are used everywhere! 602 DrawCaption(r, wi->colour, this->owner, wi->data);
486 DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->colour, FR_BORDERONLY); 603 break;
487 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); 604
488 605 case WWT_DROPDOWN:
489 if (this->owner != INVALID_OWNER) { 606 DrawDropdown(r, wi->colour, clicked, wi->data);
490 GfxFillRect(r.left + 2, r.top + 2, r.right - 2, r.bottom - 2, _colour_gradient[_company_colours[this->owner]][4]); 607 break;
491 }
492
493 DrawString(r.left + 2, r.right - 2, r.top + 2, wi->data, TC_FROMSTRING, SA_CENTER);
494 break;
495
496 case WWT_DROPDOWN: {
497 assert(r.bottom - r.top == 11); // ensure consistent size
498
499 StringID str = wi->data;
500 if (_dynlang.text_dir == TD_LTR) {
501 DrawFrameRect(r.left, r.top, r.right - 12, r.bottom, wi->colour, FR_NONE);
502 DrawFrameRect(r.right - 11, r.top, r.right, r.bottom, wi->colour, clicked ? FR_LOWERED : FR_NONE);
503 DrawString(r.right - (clicked ? 10 : 11), r.right, r.top + (clicked ? 2 : 1), STR_ARROW_DOWN, TC_BLACK, SA_CENTER);
504 if (str != STR_NULL) DrawString(r.left + 2, r.right - 14, r.top + 1, str, TC_BLACK);
505 } else {
506 DrawFrameRect(r.left + 12, r.top, r.right, r.bottom, wi->colour, FR_NONE);
507 DrawFrameRect(r.left, r.top, r.left + 11, r.bottom, wi->colour, clicked ? FR_LOWERED : FR_NONE);
508 DrawString(r.left + clicked, r.left + 11, r.top + (clicked ? 2 : 1), STR_ARROW_DOWN, TC_BLACK, SA_CENTER);
509 if (str != STR_NULL) DrawString(r.left + 14, r.right - 2, r.top + 1, str, TC_BLACK);
510 }
511 break;
512 }
513 } 608 }
514 609
515 if (this->IsWidgetDisabled(i)) { 610 if (this->IsWidgetDisabled(i)) {
516 GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, _colour_gradient[wi->colour & 0xF][2], FILLRECT_CHECKER); 611 GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, _colour_gradient[wi->colour & 0xF][2], FILLRECT_CHECKER);
517 } 612 }