widget.c
changeset 5041 6e292440425f
parent 5017 e085e1fca90b
child 5125 60b21cf18b50
equal deleted inserted replaced
5040:2998743e2416 5041:6e292440425f
   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 {
   483 	int y;
   484 	int y;
   484 
   485 
   485 	if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) < 0)
   486 	if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) < 0)
   486 		return -1;
   487 		return -1;
   487 
   488 
   488 	y = _cursor.pos.y - w->top - 2;
   489 	y = _cursor.pos.y - w->top - 2 + w->vscroll.pos;
   489 
   490 
   490 	if (y < 0)
   491 	if (y < 0)
   491 		return - 1;
   492 		return - 1;
   492 
   493 
   493 	item = y / 10;
   494 	item = y / 10;
   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