added new gadget prototype for adding color picker later
authorHolger Schemel <holger.schemel@virtion.de>
Fri, 20 Sep 2024 19:56:12 +0000 (21:56 +0200)
committerHolger Schemel <holger.schemel@virtion.de>
Fri, 20 Sep 2024 14:58:26 +0000 (16:58 +0200)
src/libgame/gadgets.c
src/libgame/gadgets.h

index 844f4f4e9c527fe8025cd3a38665298bb9da4a3c..00e4b97ca5b9178d8efd233b274f41b324f247fd 100644 (file)
@@ -166,6 +166,16 @@ static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my,
       return gi;
   }
 
+  // color pickers may overlap other active gadgets, so check them first
+  for (gi = gadget_list_first_entry; gi != NULL; gi = gi->next)
+  {
+    if (gi->mapped && gi->active &&
+       gi->type & GD_TYPE_COLOR_PICKER &&
+       mx >= gi->x && mx < gi->x + gi->width &&
+       my >= gi->y && my < gi->y + gi->height)
+      return gi;
+  }
+
   // check all other gadgets
   for (gi = gadget_list_first_entry; gi != NULL; gi = gi->next)
   {
@@ -828,6 +838,79 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
       }
       break;
 
+    case GD_TYPE_COLOR_PICKER:
+      {
+       int i;
+       int border_x = gi->border.xsize;
+       int border_y = gi->border.ysize;
+       int x = gi->x;
+       int y = gi->y;
+       int width  = gi->width;
+       int height = gi->height;
+       int xsize = (width  - 2 * border_x) / border_x + 1;
+       int ysize = (height - 2 * border_y) / border_y + 1;
+
+       // top left part of gadget border
+       BlitBitmapOnBackground(gd->bitmap, drawto, gd->x, gd->y,
+                              border_x, border_y, x, y);
+
+       // top middle part of gadget border
+       for (i = 0; i < xsize; i++)
+         BlitBitmapOnBackground(gd->bitmap, drawto, gd->x + border_x, gd->y,
+                                border_x, border_y,
+                                x + border_x + i * border_x, y);
+
+       // top right part of gadget border
+       BlitBitmapOnBackground(gd->bitmap, drawto,
+                              gd->x + gi->border.width - border_x, gd->y,
+                              border_x, border_y,
+                              x + width - border_x, y);
+
+       // left and right part of gadget border for each row
+       for (i = 0; i < ysize; i++)
+       {
+         BlitBitmapOnBackground(gd->bitmap, drawto, gd->x, gd->y + border_y,
+                                border_x, border_y,
+                                x, y + border_y + i * border_y);
+         BlitBitmapOnBackground(gd->bitmap, drawto,
+                                gd->x + gi->border.width - border_x,
+                                gd->y + border_y,
+                                border_x, border_y,
+                                x + width - border_x,
+                                y + border_y + i * border_y);
+       }
+
+       // bottom left part of gadget border
+       BlitBitmapOnBackground(gd->bitmap, drawto,
+                              gd->x, gd->y + gi->border.height - border_y,
+                              border_x, border_y,
+                              x, y + height - border_y);
+
+       // bottom middle part of gadget border
+       for (i = 0; i < xsize; i++)
+         BlitBitmapOnBackground(gd->bitmap, drawto,
+                                gd->x + border_x,
+                                gd->y + gi->border.height - border_y,
+                                border_x, border_y,
+                                x + border_x + i * border_x,
+                                y + height - border_y);
+
+       // bottom right part of gadget border
+       BlitBitmapOnBackground(gd->bitmap, drawto,
+                              gd->x + gi->border.width - border_x,
+                              gd->y + gi->border.height - border_y,
+                              border_x, border_y,
+                              x + width - border_x,
+                              y + height - border_y);
+
+       ClearRectangleOnBackground(drawto,
+                                  x + border_x,
+                                  y + border_y,
+                                  width - 2 * border_x,
+                                  height - 2 * border_y);
+      }
+      break;
+
     default:
       return;
   }
@@ -1191,6 +1274,10 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
        gi->border.width = va_arg(ap, int);
        break;
 
+      case GDI_DESIGN_HEIGHT:
+       gi->border.height = va_arg(ap, int);
+       break;
+
       case GDI_DECORATION_DESIGN:
        gi->deco.design.bitmap = va_arg(ap, Bitmap *);
        gi->deco.design.x = va_arg(ap, int);
@@ -1503,6 +1590,13 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
     // always start with unselected text area (which is potentially cropped)
     gi->textarea.full_open = FALSE;
   }
+
+
+  if (gi->type & GD_TYPE_COLOR_PICKER)
+  {
+    gi->width  = COLOR_PICKER_WIDTH;
+    gi->height = COLOR_PICKER_HEIGHT;
+  }
 }
 
 void ModifyGadget(struct GadgetInfo *gi, int first_tag, ...)
@@ -1620,6 +1714,10 @@ static void MapGadgetExt(struct GadgetInfo *gi, boolean redraw)
 
   if (redraw)
     DrawGadget(gi, DG_UNPRESSED, DG_BUFFERED);
+
+  // when mapping color picker gadget, automatically activate it
+  if (gi->type & GD_TYPE_COLOR_PICKER)
+    last_gi = gi;
 }
 
 void MapGadget(struct GadgetInfo *gi)
@@ -1714,6 +1812,11 @@ boolean anyScrollbarGadgetActive(void)
   return (last_gi && (last_gi->type & GD_TYPE_SCROLLBAR) && last_gi->mapped);
 }
 
+boolean anyColorPickerGadgetActive(void)
+{
+  return (last_gi && (last_gi->type & GD_TYPE_COLOR_PICKER) && last_gi->mapped);
+}
+
 boolean anyTextGadgetActive(void)
 {
   return (anyTextInputGadgetActive() ||
@@ -1835,13 +1938,14 @@ boolean HandleGadgets(int mx, int my, int button)
      new_gi->type & GD_TYPE_SELECTBOX && new_gi->selectbox.open &&
      insideSelectboxLine(new_gi, mx, my));
 
-  // if mouse button pressed outside text or selectbox gadget, deactivate it
-  if (anyTextGadgetActive() &&
+  // if mouse button pressed outside text, selectbox or color picker gadget, deactivate it
+  if ((anyTextGadgetActive() || anyColorPickerGadgetActive()) &&
       (gadget_pressed_off_borders ||
        (gadget_pressed_inside_select_line && !mouse_inside_select_area)))
   {
     struct GadgetInfo *gi = last_gi;
-    boolean gadget_changed = ((gi->event_mask & GD_EVENT_TEXT_LEAVING) != 0);
+    boolean gadget_changed = ((gi->event_mask & GD_EVENT_TEXT_LEAVING) != 0 ||
+                              (gi->event_mask & GD_EVENT_COLOR_PICKER_LEAVING) != 0);
 
     // check if text input gadget has changed its value
     if (gi->type & GD_TYPE_TEXT_INPUT)
@@ -1867,9 +1971,16 @@ boolean HandleGadgets(int mx, int my, int button)
     if (gi->type & GD_TYPE_SELECTBOX)
       gadget_changed = FALSE;
 
+    // color picker does not select color when closed by clicking outside
+    if (gi->type & GD_TYPE_COLOR_PICKER)
+      gadget_changed = FALSE;
+
     DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
 
-    gi->event.type = GD_EVENT_TEXT_LEAVING;
+    if (gi->type & GD_TYPE_COLOR_PICKER)
+      gi->event.type = GD_EVENT_COLOR_PICKER_LEAVING;
+    else
+      gi->event.type = GD_EVENT_TEXT_LEAVING;
 
     if (!(gi->type & GD_TYPE_SELECTBOX))
       DoGadgetCallbackAction(gi, gadget_changed);
@@ -1934,7 +2045,8 @@ boolean HandleGadgets(int mx, int my, int button)
       pressed_my = 0;
     }
     else if (!(gi->type & GD_TYPE_TEXT_INPUT ||
-              gi->type & GD_TYPE_TEXT_AREA))       // text input stays open
+              gi->type & GD_TYPE_TEXT_AREA ||
+              gi->type & GD_TYPE_COLOR_PICKER))    // text input and color picker stays open
       last_gi = NULL;
   }
 
@@ -2315,7 +2427,8 @@ boolean HandleGadgets(int mx, int my, int button)
 
     if (deactivate_gadget &&
        !(gi->type & GD_TYPE_TEXT_INPUT ||
-         gi->type & GD_TYPE_TEXT_AREA))            // text input stays open
+         gi->type & GD_TYPE_TEXT_AREA ||
+         gi->type & GD_TYPE_COLOR_PICKER))         // text input and color picker stays open
       DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
 
     gi->state = GD_BUTTON_UNPRESSED;
index 6a27f988f7c8f6b3101708ba0abdaf21d5a2475f..cc9620d5221ecf63675c60ec26f31a66537f2e44 100644 (file)
@@ -31,6 +31,7 @@
 #define GD_TYPE_SELECTBOX              (1 << 9)
 #define GD_TYPE_SCROLLBAR_VERTICAL     (1 << 10)
 #define GD_TYPE_SCROLLBAR_HORIZONTAL   (1 << 11)
+#define GD_TYPE_COLOR_PICKER           (1 << 12)
 
 #define GD_TYPE_BUTTON                 (GD_TYPE_NORMAL_BUTTON | \
                                         GD_TYPE_TEXT_BUTTON | \
@@ -53,6 +54,7 @@
 #define GD_EVENT_INFO_ENTERING         (1 << 7)
 #define GD_EVENT_INFO_LEAVING          (1 << 8)
 #define GD_EVENT_PIXEL_PRECISE         (1 << 9)
+#define GD_EVENT_COLOR_PICKER_LEAVING  (1 << 10)
 
 // gadget button states
 #define GD_BUTTON_UNPRESSED            0
@@ -61,6 +63,8 @@
 // gadget structure constants
 #define MAX_GADGET_TEXTSIZE            1024
 #define MAX_INFO_TEXTSIZE              1024
+#define COLOR_PICKER_WIDTH             256
+#define COLOR_PICKER_HEIGHT            300
 
 // gadget creation tags
 #define GDI_END                                0
 #define GDI_BORDER_SIZE                        27
 #define GDI_BORDER_SIZE_SELECTBUTTON   28
 #define GDI_DESIGN_WIDTH               29
-#define GDI_DECORATION_DESIGN          30
-#define GDI_DECORATION_POSITION                31
-#define GDI_DECORATION_SIZE            32
-#define GDI_DECORATION_SHIFTING                33
-#define GDI_DECORATION_MASKED          34
-#define GDI_EVENT_MASK                 35
-#define GDI_EVENT                      36
-#define GDI_CALLBACK_INFO              37
-#define GDI_CALLBACK_ACTION            38
-#define GDI_AREA_SIZE                  39
-#define GDI_ITEM_SIZE                  40
-#define GDI_SCROLLBAR_ITEMS_MAX                41
-#define GDI_SCROLLBAR_ITEMS_VISIBLE    42
-#define GDI_SCROLLBAR_ITEM_POSITION    43
-#define GDI_WHEEL_AREA_X               44
-#define GDI_WHEEL_AREA_Y               45
-#define GDI_WHEEL_AREA_WIDTH           46
-#define GDI_WHEEL_AREA_HEIGHT          47
-#define GDI_INFO_TEXT                  48
-#define GDI_ACTIVE                     49
-#define GDI_DIRECT_DRAW                        50
-#define GDI_OVERLAY_TOUCH_BUTTON       51
-#define GDI_CALLBACK_ACTION_ALWAYS     52
+#define GDI_DESIGN_HEIGHT              30
+#define GDI_DECORATION_DESIGN          31
+#define GDI_DECORATION_POSITION                32
+#define GDI_DECORATION_SIZE            33
+#define GDI_DECORATION_SHIFTING                34
+#define GDI_DECORATION_MASKED          35
+#define GDI_EVENT_MASK                 36
+#define GDI_EVENT                      37
+#define GDI_CALLBACK_INFO              38
+#define GDI_CALLBACK_ACTION            39
+#define GDI_AREA_SIZE                  40
+#define GDI_ITEM_SIZE                  41
+#define GDI_SCROLLBAR_ITEMS_MAX                42
+#define GDI_SCROLLBAR_ITEMS_VISIBLE    43
+#define GDI_SCROLLBAR_ITEM_POSITION    44
+#define GDI_WHEEL_AREA_X               45
+#define GDI_WHEEL_AREA_Y               46
+#define GDI_WHEEL_AREA_WIDTH           47
+#define GDI_WHEEL_AREA_HEIGHT          48
+#define GDI_INFO_TEXT                  49
+#define GDI_ACTIVE                     50
+#define GDI_DIRECT_DRAW                        51
+#define GDI_OVERLAY_TOUCH_BUTTON       52
+#define GDI_CALLBACK_ACTION_ALWAYS     53
 
 // gadget deactivation hack
 #define GDI_ACTIVE_POS(a)              ((a) < 0 ? POS_OFFSCREEN : (a))
@@ -127,7 +132,8 @@ struct GadgetBorder
 {
   int xsize, ysize;                    // size of gadget border
   int xsize_selectbutton;              // for selectbox gadgets
-  int width;                           // for selectbox/text input gadgets
+  int width;                           // for variable sized gadgets
+  int height;                          // for variable sized gadgets
 };
 
 struct GadgetDesign
@@ -307,6 +313,7 @@ boolean anyTextAreaGadgetActive(void);
 boolean anySelectboxGadgetActive(void);
 boolean anyScrollbarGadgetActive(void);
 boolean anyTextGadgetActive(void);
+boolean anyColorPickerGadgetActive(void);
 
 void ClickOnGadget(struct GadgetInfo *, int);