X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Flibgame%2Fgadgets.c;h=daa045eb4892dd4ea28b98d9def164ad143bf12d;hp=9c974b872ed91f485820fe4378e17478f19b9fd0;hb=3b6f0ed7443f58031823df29c1a7bd89d7d63a8d;hpb=3ff2e8a0b5c27b99a9920bdf5ed82bc41bf40181 diff --git a/src/libgame/gadgets.c b/src/libgame/gadgets.c index 9c974b87..daa045eb 100644 --- a/src/libgame/gadgets.c +++ b/src/libgame/gadgets.c @@ -26,6 +26,13 @@ #define GADGET_DEACTIVATED(g) ((g)->x < 0 || (g)->y < 0) +#define OPTION_TEXT_SELECTABLE(g, t) \ + (t[0] != g->selectbox.char_unselectable && \ + t[0] != '\0' && \ + !strEqual(t, " ")) +#define CURRENT_OPTION_SELECTABLE(g) \ + OPTION_TEXT_SELECTABLE(g, g->selectbox.options[g->selectbox.current_index].text) + static struct GadgetInfo *gadget_list_first_entry = NULL; static struct GadgetInfo *gadget_list_last_entry = NULL; @@ -89,6 +96,16 @@ static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my, boolean check_horizontal = (IS_WHEEL_BUTTON_HORIZONTAL(button) || GetKeyModState() & KMOD_Shift); + /* check for the first active scrollbar directly under the mouse pointer */ + for (gi = gadget_list_first_entry; gi != NULL; gi = gi->next) + { + if (gi->mapped && gi->active && + (gi->type & GD_TYPE_SCROLLBAR) && + mx >= gi->x && mx < gi->x + gi->width && + my >= gi->y && my < gi->y + gi->height) + return gi; + } + /* check for the first active scrollbar with matching mouse wheel area */ for (gi = gadget_list_first_entry; gi != NULL; gi = gi->next) { @@ -214,15 +231,31 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) case GD_TYPE_NORMAL_BUTTON: case GD_TYPE_CHECK_BUTTON: case GD_TYPE_RADIO_BUTTON: + BlitBitmapOnBackground(gd->bitmap, drawto, gd->x, gd->y, gi->width, gi->height, gi->x, gi->y); + if (gi->deco.design.bitmap) - BlitBitmap(gi->deco.design.bitmap, drawto, - gi->deco.design.x, gi->deco.design.y, - gi->deco.width, gi->deco.height, - gi->x + gi->deco.x + (pressed ? gi->deco.xshift : 0), - gi->y + gi->deco.y + (pressed ? gi->deco.yshift : 0)); + { + // make sure that decoration does not overlap gadget border + int deco_x = gi->deco.x + (pressed ? gi->deco.xshift : 0); + int deco_y = gi->deco.y + (pressed ? gi->deco.yshift : 0); + int deco_width = MIN(gi->deco.width, gi->width - deco_x); + int deco_height = MIN(gi->deco.height, gi->height - deco_y); + + if (gi->deco.masked) + BlitBitmapMasked(gi->deco.design.bitmap, drawto, + gi->deco.design.x, gi->deco.design.y, + deco_width, deco_height, + gi->x + deco_x, gi->y + deco_y); + else + BlitBitmap(gi->deco.design.bitmap, drawto, + gi->deco.design.x, gi->deco.design.y, + deco_width, deco_height, + gi->x + deco_x, gi->y + deco_y); + } + break; case GD_TYPE_TEXT_BUTTON: @@ -404,7 +437,8 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) { int i; char text[MAX_GADGET_TEXTSIZE + 1]; - int font_nr = (pressed ? gi->font_active : gi->font); + int font_nr_default = (pressed ? gi->font_active : gi->font); + int font_nr = font_nr_default; int font_width = getFontWidth(font_nr); int font_height = getFontHeight(font_nr); int border_x = gi->border.xsize; @@ -441,6 +475,10 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) gi->selectbox.size); text[gi->selectbox.size] = '\0'; + /* set font value */ + font_nr = (OPTION_TEXT_SELECTABLE(gi, text) ? font_nr_default : + gi->font_unselectable); + /* gadget text value */ DrawTextExt(drawto, gi->x + border_x, gi->y + border_y, text, font_nr, BLIT_MASKED); @@ -549,7 +587,11 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) strncpy(text, gi->selectbox.options[i].text, gi->selectbox.size); text[gi->selectbox.size] = '\0'; - if (i == gi->selectbox.current_index) + font_nr = (OPTION_TEXT_SELECTABLE(gi, text) ? font_nr_default : + gi->font_unselectable); + + if (i == gi->selectbox.current_index && + OPTION_TEXT_SELECTABLE(gi, text)) { FillRectangle(drawto, gi->selectbox.x + border_x, @@ -688,6 +730,10 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) return; } + // do not use direct gadget drawing anymore; this worked as a speed-up once, + // but would slow things down a lot now the screen is always fully redrawn + direct = FALSE; + if (direct) { BlitBitmap(drawto, window, @@ -873,12 +919,18 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) gi->font = va_arg(ap, int); if (gi->font_active == 0) gi->font_active = gi->font; + if (gi->font_unselectable == 0) + gi->font_unselectable = gi->font; break; case GDI_TEXT_FONT_ACTIVE: gi->font_active = va_arg(ap, int); break; + case GDI_TEXT_FONT_UNSELECTABLE: + gi->font_unselectable = va_arg(ap, int); + break; + case GDI_SELECTBOX_OPTIONS: gi->selectbox.options = va_arg(ap, struct ValueTextInfo *); break; @@ -887,6 +939,10 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) gi->selectbox.index = va_arg(ap, int); break; + case GDI_SELECTBOX_CHAR_UNSELECTABLE: + gi->selectbox.char_unselectable = (char)va_arg(ap, int); + break; + case GDI_DESIGN_UNPRESSED: gi->design[GD_BUTTON_UNPRESSED].bitmap = va_arg(ap, Bitmap *); gi->design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int); @@ -945,6 +1001,10 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) gi->deco.yshift = va_arg(ap, int); break; + case GDI_DECORATION_MASKED: + gi->deco.masked = (boolean)va_arg(ap, int); + break; + case GDI_EVENT_MASK: gi->event_mask = va_arg(ap, unsigned int); break; @@ -954,14 +1014,12 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) gi->drawing.area_ysize = va_arg(ap, int); /* determine dependent values for drawing area gadget, if needed */ - if (gi->width == 0 && gi->height == 0 && - gi->drawing.item_xsize !=0 && gi->drawing.item_ysize !=0) + if (gi->drawing.item_xsize != 0 && gi->drawing.item_ysize != 0) { gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize; gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize; } - else if (gi->drawing.item_xsize == 0 && gi->drawing.item_ysize == 0 && - gi->width != 0 && gi->height != 0) + else if (gi->width != 0 && gi->height != 0) { gi->drawing.item_xsize = gi->width / gi->drawing.area_xsize; gi->drawing.item_ysize = gi->height / gi->drawing.area_ysize; @@ -984,14 +1042,12 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) gi->drawing.item_ysize = va_arg(ap, int); /* determine dependent values for drawing area gadget, if needed */ - if (gi->width == 0 && gi->height == 0 && - gi->drawing.area_xsize !=0 && gi->drawing.area_ysize !=0) + if (gi->drawing.area_xsize != 0 && gi->drawing.area_ysize != 0) { gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize; gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize; } - else if (gi->drawing.area_xsize == 0 && gi->drawing.area_ysize == 0 && - gi->width != 0 && gi->height != 0) + else if (gi->width != 0 && gi->height != 0) { gi->drawing.area_xsize = gi->width / gi->drawing.item_xsize; gi->drawing.area_ysize = gi->height / gi->drawing.item_ysize; @@ -1591,7 +1647,8 @@ boolean HandleGadgets(int mx, int my, int button) if (gi->type & GD_TYPE_SELECTBOX && (keep_selectbox_open || mouse_released_where_pressed || - !gadget_released_inside_select_area)) /* selectbox stays open */ + !gadget_released_inside_select_area || + !CURRENT_OPTION_SELECTABLE(gi))) /* selectbox stays open */ { gi->selectbox.stay_open = TRUE; pressed_mx = 0; @@ -1752,7 +1809,7 @@ boolean HandleGadgets(int mx, int my, int button) { boolean scroll_single_step = ((GetKeyModState() & KMOD_Alt) != 0); - item_steps = (scroll_single_step ? 1 : DEFAULT_WHEEL_STEPS); + item_steps = (scroll_single_step ? 1 : wheel_steps); item_direction = (button == MB_WHEEL_UP || button == MB_WHEEL_LEFT ? -1 : +1); } @@ -1949,7 +2006,8 @@ boolean HandleGadgets(int mx, int my, int button) { if (keep_selectbox_open || mouse_released_where_pressed || - !gadget_released_inside_select_area) /* selectbox stays open */ + !gadget_released_inside_select_area || + !CURRENT_OPTION_SELECTABLE(gi)) /* selectbox stays open */ { deactivate_gadget = FALSE; gadget_changed = FALSE;