472 |
472 |
473 } |
473 } |
474 |
474 |
475 static const Widget _dropdown_menu_widgets[] = { |
475 static const Widget _dropdown_menu_widgets[] = { |
476 { WWT_PANEL, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL}, |
476 { WWT_PANEL, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL}, |
|
477 { WWT_SCROLLBAR, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, |
477 { WIDGETS_END}, |
478 { WIDGETS_END}, |
478 }; |
479 }; |
479 |
480 |
480 static int GetDropdownItem(const Window *w) |
481 static int GetDropdownItem(const Window *w) |
481 { |
482 { |
506 int item; |
507 int item; |
507 |
508 |
508 switch (e->event) { |
509 switch (e->event) { |
509 case WE_PAINT: { |
510 case WE_PAINT: { |
510 int x,y,i,sel; |
511 int x,y,i,sel; |
|
512 int width; |
|
513 bool scroll = w->vscroll.count > 0; |
|
514 DrawPixelInfo tmp_dpi, *old_dpi = NULL; |
511 |
515 |
512 DrawWindowWidgets(w); |
516 DrawWindowWidgets(w); |
513 |
517 |
514 x = 1; |
518 x = 1; |
515 y = 2; |
519 y = 2 - w->vscroll.pos; |
516 sel = WP(w,dropdown_d).selected_index; |
520 |
|
521 if (scroll) { |
|
522 /* Set up the bounding box for drawing the list content */ |
|
523 if (!FillDrawPixelInfo(&tmp_dpi, w->widget[0].left + 1, w->widget[0].top + 1, w->widget[0].right - 1, w->widget[0].bottom - 1)) return; |
|
524 old_dpi = _cur_dpi; |
|
525 _cur_dpi = &tmp_dpi; |
|
526 |
|
527 /* Adjust x and y for the 1 pixel offset of the bounding box */ |
|
528 x--; |
|
529 y--; |
|
530 } |
|
531 |
|
532 sel = WP(w,dropdown_d).selected_index; |
|
533 width = w->widget[0].right - 3; |
517 |
534 |
518 for (i = 0; WP(w,dropdown_d).items[i] != INVALID_STRING_ID; i++) { |
535 for (i = 0; WP(w,dropdown_d).items[i] != INVALID_STRING_ID; i++) { |
519 if (HASBIT(WP(w,dropdown_d).hidden_state, i)) { |
536 if (HASBIT(WP(w,dropdown_d).hidden_state, i)) { |
520 sel--; |
537 sel--; |
521 continue; |
538 continue; |
522 } |
539 } |
523 if (WP(w,dropdown_d).items[i] != STR_NULL) { |
540 if (WP(w,dropdown_d).items[i] != STR_NULL) { |
524 if (sel == 0) GfxFillRect(x + 1, y, x + w->width - 4, y + 9, 0); |
541 if (sel == 0) GfxFillRect(x + 1, y, x + width, y + 9, 0); |
525 DrawStringTruncated(x + 2, y, WP(w,dropdown_d).items[i], sel == 0 ? 12 : 16, w->width - 4); |
542 DrawStringTruncated(x + 2, y, WP(w,dropdown_d).items[i], sel == 0 ? 12 : 16, x + width); |
526 |
543 |
527 if (HASBIT(WP(w,dropdown_d).disabled_state, i)) { |
544 if (HASBIT(WP(w,dropdown_d).disabled_state, i)) { |
528 GfxFillRect(x, y, x + w->width - 3, y + 9, |
545 GfxFillRect(x, y, x + width, y + 9, |
529 PALETTE_MODIFIER_GREYOUT | _colour_gradient[_dropdown_menu_widgets[0].color][5] |
546 PALETTE_MODIFIER_GREYOUT | _colour_gradient[_dropdown_menu_widgets[0].color][5] |
530 ); |
547 ); |
531 } |
548 } |
532 } else { |
549 } else { |
533 int c1 = _colour_gradient[_dropdown_menu_widgets[0].color][3]; |
550 int c1 = _colour_gradient[_dropdown_menu_widgets[0].color][3]; |
537 GfxFillRect(x + 1, y + 4, x + w->width - 5, y + 4, c2); |
554 GfxFillRect(x + 1, y + 4, x + w->width - 5, y + 4, c2); |
538 } |
555 } |
539 y += 10; |
556 y += 10; |
540 sel--; |
557 sel--; |
541 } |
558 } |
|
559 |
|
560 /* Reset the bounding box if we had set it up */ |
|
561 if (scroll) _cur_dpi = old_dpi; |
542 } break; |
562 } break; |
543 |
563 |
544 case WE_CLICK: { |
564 case WE_CLICK: { |
|
565 if (e->we.click.widget != 0) break; |
545 item = GetDropdownItem(w); |
566 item = GetDropdownItem(w); |
546 if (item >= 0) { |
567 if (item >= 0) { |
547 WP(w,dropdown_d).click_delay = 4; |
568 WP(w,dropdown_d).click_delay = 4; |
548 WP(w,dropdown_d).selected_index = item; |
569 WP(w,dropdown_d).selected_index = item; |
549 SetWindowDirty(w); |
570 SetWindowDirty(w); |
598 WindowNumber num; |
619 WindowNumber num; |
599 WindowClass cls; |
620 WindowClass cls; |
600 int i; |
621 int i; |
601 const Widget *wi; |
622 const Widget *wi; |
602 Window *w2; |
623 Window *w2; |
|
624 const Window *w3; |
603 bool is_dropdown_menu_shown = IsWindowWidgetLowered(w, button); |
625 bool is_dropdown_menu_shown = IsWindowWidgetLowered(w, button); |
|
626 int top, height; |
|
627 int screen_top, screen_bottom; |
|
628 bool scroll = false; |
604 |
629 |
605 cls = w->window_class; |
630 cls = w->window_class; |
606 num = w->window_number; |
631 num = w->window_number; |
607 DeleteWindowById(WC_DROPDOWN_MENU, 0); |
632 DeleteWindowById(WC_DROPDOWN_MENU, 0); |
608 w = FindWindowById(cls, num); |
633 w = FindWindowById(cls, num); |
624 for (j = 0; strings[j] != INVALID_STRING_ID; j++) { |
649 for (j = 0; strings[j] != INVALID_STRING_ID; j++) { |
625 if (HASBIT(hidden_mask, j)) i--; |
650 if (HASBIT(hidden_mask, j)) i--; |
626 } |
651 } |
627 } |
652 } |
628 |
653 |
|
654 /* The preferred position is just below the dropdown calling widget */ |
|
655 top = w->top + wi->bottom + 2; |
|
656 height = i * 10 + 4; |
|
657 |
|
658 w3 = FindWindowById(WC_STATUS_BAR, 0); |
|
659 screen_bottom = w3 == NULL ? _screen.height : w3->top; |
|
660 |
|
661 /* Check if the dropdown will fully fit below the widget */ |
|
662 if (top + height >= screen_bottom) { |
|
663 w3 = FindWindowById(WC_MAIN_TOOLBAR, 0); |
|
664 screen_top = w3 == NULL ? 0 : w3->top + w3->height; |
|
665 |
|
666 /* If not, check if it will fit above the widget */ |
|
667 if (w->top + wi->top - height - 1 > screen_top) { |
|
668 top = w->top + wi->top - height - 1; |
|
669 } else { |
|
670 /* ... and lastly if it won't, enable the scroll bar and fit the |
|
671 * list in below the widget */ |
|
672 height = screen_bottom - top; |
|
673 scroll = true; |
|
674 } |
|
675 } |
|
676 |
629 w2 = AllocateWindow( |
677 w2 = AllocateWindow( |
630 w->left + wi[-1].left + 1, |
678 w->left + wi[-1].left + 1, |
631 w->top + wi->bottom + 2, |
679 top, |
632 wi->right - wi[-1].left + 1, |
680 wi->right - wi[-1].left + 1, |
633 i * 10 + 4, |
681 height, |
634 DropdownMenuWndProc, |
682 DropdownMenuWndProc, |
635 WC_DROPDOWN_MENU, |
683 WC_DROPDOWN_MENU, |
636 _dropdown_menu_widgets); |
684 _dropdown_menu_widgets); |
637 |
685 |
638 w2->widget[0].color = wi->color; |
686 w2->widget[0].color = wi->color; |
639 w2->widget[0].right = wi->right - wi[-1].left; |
687 w2->widget[0].right = wi->right - wi[-1].left; |
640 w2->widget[0].bottom = i * 10 + 3; |
688 w2->widget[0].bottom = height - 1; |
641 |
689 |
|
690 SetWindowWidgetHiddenState(w2, 1, !scroll); |
|
691 |
|
692 if (scroll) { |
|
693 /* We're scrolling, so enable the scroll bar and shrink the list by |
|
694 * the scrollbar's width */ |
|
695 w2->widget[1].color = wi->color; |
|
696 w2->widget[1].right = w2->widget[0].right; |
|
697 w2->widget[1].left = w2->widget[1].right - 11; |
|
698 w2->widget[1].bottom = height - 1; |
|
699 w2->widget[0].right -= 12; |
|
700 |
|
701 w2->vscroll.cap = height - 1; |
|
702 w2->vscroll.count = i * 10 + 3; |
|
703 } |
|
704 |
|
705 w2->desc_flags = WDF_DEF_WIDGET; |
642 w2->flags4 &= ~WF_WHITE_BORDER_MASK; |
706 w2->flags4 &= ~WF_WHITE_BORDER_MASK; |
643 |
707 |
644 WP(w2,dropdown_d).disabled_state = disabled_mask; |
708 WP(w2,dropdown_d).disabled_state = disabled_mask; |
645 WP(w2,dropdown_d).hidden_state = hidden_mask; |
709 WP(w2,dropdown_d).hidden_state = hidden_mask; |
646 |
710 |