@@ -851,6 +851,10 @@ static int ui_offset_y_canvas = 0; /* Vertical offset for canvas hide/show an
851851static int ui_offset_y_tux = 0; /* Vertical offset for tux area (positive = hidden below) */
852852static int colorbar_is_visible = 0; /* Flag to track color bar visibility state */
853853
854+ /* Color picker button dimensions (DRY - used in both drawing and click detection) */
855+ #define COLOR_PICKER_BUTTON_MIN_HEIGHT 150
856+ #define COLOR_PICKER_BUTTON_PREFERRED_HEIGHT 200
857+
854858static int colors_rows;
855859
856860static int buttons_tall; /* promoted to a global variable from setup_normal_screen_layout() */
@@ -1471,6 +1475,48 @@ static void slide_colorbar_in(void)
14711475#endif
14721476}
14731477
1478+ /**
1479+ * Calculate color picker button position (DRY - used in both drawing and click detection)
1480+ * @param is_child_mode: whether in child mode
1481+ * @param tool: current tool (to check if slider is shown)
1482+ * @param button_top: output - top Y position of button
1483+ * @param button_bottom: output - bottom Y position of button
1484+ */
1485+ static void get_color_picker_button_rect(int is_child_mode, int tool, int *button_top, int *button_bottom)
1486+ {
1487+ if (is_child_mode && (tool == TOOL_BRUSH || tool == TOOL_LINES))
1488+ {
1489+ /* In child mode with slider: calculate available space and split between slider and button */
1490+ int available_height = WINDOW_HEIGHT - r_ttoolopt.h - 10;
1491+
1492+ if (available_height >= COLOR_PICKER_BUTTON_MIN_HEIGHT + 200)
1493+ *button_top = WINDOW_HEIGHT - COLOR_PICKER_BUTTON_PREFERRED_HEIGHT;
1494+ else if (available_height >= COLOR_PICKER_BUTTON_MIN_HEIGHT + 100)
1495+ *button_top = WINDOW_HEIGHT - COLOR_PICKER_BUTTON_MIN_HEIGHT;
1496+ else
1497+ *button_top = r_ttoolopt.h + (available_height / 2);
1498+ }
1499+ else
1500+ {
1501+ /* In expert mode or child mode without slider: button has fixed preferred height at bottom */
1502+ *button_top = WINDOW_HEIGHT - COLOR_PICKER_BUTTON_PREFERRED_HEIGHT;
1503+ }
1504+
1505+ *button_bottom = WINDOW_HEIGHT - 5; /* 5px margin from bottom */
1506+ }
1507+
1508+ /**
1509+ * Check if a click hits the color picker button
1510+ */
1511+ static int hit_color_picker_button(int x, int y, int is_child_mode, int tool)
1512+ {
1513+ int button_top, button_bottom;
1514+ get_color_picker_button_rect(is_child_mode, tool, &button_top, &button_bottom);
1515+
1516+ return (x >= (WINDOW_WIDTH - r_ttoolopt.w) && x <= WINDOW_WIDTH &&
1517+ y >= button_top && y <= button_bottom);
1518+ }
1519+
14741520/**
14751521 * Slide color bar and tux area out of view with animation
14761522 */
@@ -4795,129 +4841,94 @@ static void mainloop(void)
47954841 }
47964842 }
47974843 }
4844+ /* Color picker button click (separate hit test, as button may be outside r_toolopt) */
4845+ else if (!colorbar_is_visible && valid_click(event.button.button) &&
4846+ hit_color_picker_button(event.button.x, event.button.y, child_mode, cur_tool))
4847+ {
4848+ #ifdef __ANDROID__
4849+ __android_log_print(ANDROID_LOG_INFO, "TuxPaint", "COLOR_PICKER: Button clicked! x=%d y=%d",
4850+ event.button.x, event.button.y);
4851+ #endif
4852+ slide_colorbar_in();
4853+ playsound(screen, 1, SND_CLICK, 1, SNDPOS_RIGHT, SNDDIST_NEAR);
4854+ /* Note: no continue here, let it fall through to update UI */
4855+ }
4856+ /* Right toolbar (r_toolopt) area clicked */
47984857 else if (HIT(r_toolopt) && valid_click(event.button.button))
47994858 {
4800- /* Check for color picker button click first (when colorbar is hidden) */
4801- int handle_as_color_picker = 0;
4802-
4803- if (!colorbar_is_visible)
4804- {
4805- /* Calculate color picker button area */
4806- int button_top, button_bottom;
4807- int button_min_height = 150;
4808- int button_preferred_height = 200;
4809-
4810- if (child_mode && (cur_tool == TOOL_BRUSH || cur_tool == TOOL_LINES))
4859+ /* Handle slider in child mode when colorbar is visible */
4860+ if (colorbar_is_visible && child_mode && (cur_tool == TOOL_BRUSH || cur_tool == TOOL_LINES))
48114861 {
4812- /* In child mode with slider */
4813- int available_height = WINDOW_HEIGHT - r_ttoolopt.h - 10;
4862+ /* Calculate slider position - MUST match draw_child_mode_brush_slider() */
4863+ int slider_x, slider_y, slider_w, slider_h;
4864+ int click_y;
4865+ float click_percentage;
48144866
4815- if (available_height >= button_min_height + 200)
4816- button_top = WINDOW_HEIGHT - button_preferred_height;
4817- else if (available_height >= button_min_height + 100)
4818- button_top = WINDOW_HEIGHT - button_min_height;
4819- else
4820- button_top = r_ttoolopt.h + (available_height / 2);
4821- }
4822- else
4823- {
4824- /* In expert mode or child mode without slider */
4825- button_top = WINDOW_HEIGHT - button_preferred_height;
4826- }
4827-
4828- button_bottom = WINDOW_HEIGHT - 5;
4829-
4830- /* Check if click is within color picker button area */
4831- if (event.button.y >= button_top && event.button.y <= button_bottom)
4832- {
4833- /* Color picker button clicked - slide colorbar in and skip normal toolopt handling */
4834- slide_colorbar_in();
4835- playsound(screen, 1, SND_CLICK, 1, SNDPOS_RIGHT, SNDDIST_NEAR);
4836- handle_as_color_picker = 1;
4837- }
4838- }
4839-
4840- /* Only do normal toolopt handling if not handled as color picker button */
4841- if (!handle_as_color_picker)
4842- {
4843- /* Slide color bar in when right side (toolopt) is clicked (not color picker) */
4844- if (!colorbar_is_visible)
4845- slide_colorbar_in();
4846-
4847- /* In child mode with brush tool, handle slider clicks and dragging */
4848- if (child_mode && (cur_tool == TOOL_BRUSH || cur_tool == TOOL_LINES))
4849- {
4850- /* Calculate slider position - MUST match draw_child_mode_brush_slider() */
4851- int slider_x, slider_y, slider_w, slider_h;
4852- int click_y;
4853- float click_percentage;
4854- int child_brush_min = 0; /* Brush index 0 */
4855- int child_brush_max = 4; /* Brush index 4 */
4856-
4857- slider_w = button_w - 20;
4858- /* Use r_colors.y + ui_offset_y_colors to get the visible (animated) colorbar position
4859- in child mode, accounting for slide animation */
4860- /* Compress by 5% to avoid overlapping neighboring elements */
4861- slider_h = (int)(((r_colors.y + ui_offset_y_colors) - r_ttoolopt.h - 40) * 0.95);
4862- slider_x = WINDOW_WIDTH - r_ttoolopt.w + (r_ttoolopt.w - slider_w) / 2;
4863- slider_y = r_ttoolopt.h + 30; /* Add extra margin at top */
4864-
4865- click_y = event.button.y;
4866-
4867- SDL_Log("SLIDER CLICK: click_y=%d, slider_y=%d, slider_h=%d, range=[%d,%d]",
4868- click_y, slider_y, slider_h, slider_y, slider_y + slider_h);
4869-
4870- /* Check if click is within slider area */
4871- if (click_y >= slider_y && click_y <= slider_y + slider_h)
4872- {
4873- /* Start slider dragging mode */
4874- slider_dragging = 1;
4875-
4876- /* Calculate position and brush based on click position */
4877- click_percentage = (float)(click_y - slider_y) / (float)slider_h;
4878-
4879- /* Clamp to 0.0-1.0 range */
4880- if (click_percentage < 0.0f) click_percentage = 0.0f;
4881- if (click_percentage > 1.0f) click_percentage = 1.0f;
4867+ slider_w = button_w - 20;
4868+ /* Use r_colors.y + ui_offset_y_colors to get the visible (animated) colorbar position
4869+ in child mode, accounting for slide animation */
4870+ /* Compress by 5% to avoid overlapping neighboring elements */
4871+ slider_h = (int)(((r_colors.y + ui_offset_y_colors) - r_ttoolopt.h - 40) * 0.95);
4872+ slider_x = WINDOW_WIDTH - r_ttoolopt.w + (r_ttoolopt.w - slider_w) / 2;
4873+ slider_y = r_ttoolopt.h + 30; /* Add extra margin at top */
48824874
4883- /* Set position instantly (no animation on initial click) */
4884- slider_current_pos = click_percentage;
4885- slider_target_pos = click_percentage;
4886- slider_anim_duration = 0; /* No animation - instant response */
4875+ click_y = event.button.y;
48874876
4888- /* Calculate brush index in category based on click position */
4889- int brush_idx = (int)(click_percentage * child_brush_count);
4890- if (brush_idx >= child_brush_count) brush_idx = child_brush_count - 1;
4891-
4892- /* Get actual brush from category indices */
4893- cur_brush = child_brush_indices[brush_idx];
4894-
4895- SDL_Log("SLIDER CLICK: percentage=%.2f, brush=%d, instant position update",
4896- click_percentage, cur_brush);
4877+ SDL_Log("SLIDER CLICK: click_y=%d, slider_y=%d, slider_h=%d, range=[%d,%d]",
4878+ click_y, slider_y, slider_h, slider_y, slider_y + slider_h);
48974879
4880+ /* Check if click is within slider area */
4881+ if (click_y >= slider_y && click_y <= slider_y + slider_h)
4882+ {
4883+ /* Start slider dragging mode */
4884+ slider_dragging = 1;
4885+
4886+ /* Calculate position and brush based on click position */
4887+ click_percentage = (float)(click_y - slider_y) / (float)slider_h;
4888+
4889+ /* Clamp to 0.0-1.0 range */
4890+ if (click_percentage < 0.0f) click_percentage = 0.0f;
4891+ if (click_percentage > 1.0f) click_percentage = 1.0f;
4892+
4893+ /* Set position instantly (no animation on initial click) */
4894+ slider_current_pos = click_percentage;
4895+ slider_target_pos = click_percentage;
4896+ slider_anim_duration = 0; /* No animation - instant response */
4897+
4898+ /* Calculate brush index in category based on click position */
4899+ int brush_idx = (int)(click_percentage * child_brush_count);
4900+ if (brush_idx >= child_brush_count) brush_idx = child_brush_count - 1;
4901+
4902+ /* Get actual brush from category indices */
4903+ cur_brush = child_brush_indices[brush_idx];
4904+
4905+ SDL_Log("SLIDER CLICK: percentage=%.2f, brush=%d, instant position update",
4906+ click_percentage, cur_brush);
4907+
48984908#ifdef __ANDROID__
4899- save_preferences();
4909+ save_preferences();
49004910#endif
4901-
4902- /* Update brush */
4903- render_brush();
4904- draw_child_mode_brush_slider();
4905- draw_color_picker_button();
4906- SDL_Flip(screen); /* Flip immediately to show new position */
4907-
4908- playsound(screen, 1, SND_CLICK, 1, SNDPOS_RIGHT, SNDDIST_NEAR);
4909- }
4910- else
4911- {
4912- SDL_Log("SLIDER: Click outside slider area, ignoring");
4911+
4912+ /* Update brush */
4913+ render_brush();
4914+ draw_child_mode_brush_slider();
4915+ draw_color_picker_button();
4916+ SDL_Flip(screen); /* Flip immediately to show new position */
4917+
4918+ playsound(screen, 1, SND_CLICK, 1, SNDPOS_RIGHT, SNDDIST_NEAR);
4919+ }
4920+ else
4921+ {
4922+ SDL_Log("SLIDER: Click outside slider area, ignoring");
4923+ }
4924+ /* In child mode with slider, don't process grid-based brush selection */
4925+ continue; /* Skip rest of event processing */
49134926 }
4914- /* In child mode, don't process grid-based brush selection - skip the else if below */
4915- }
4916- /* Options on the right
4927+
4928+ /* Options on the right (normal toolopt grid in expert mode, or child mode without slider)
49174929 WARNING: this must be kept in sync with the mouse-move
49184930 code (for cursor changes) and mouse-scroll code. */
4919-
4920- else if (!child_mode && (cur_tool == TOOL_BRUSH || cur_tool == TOOL_STAMP ||
4931+ if (!child_mode && (cur_tool == TOOL_BRUSH || cur_tool == TOOL_STAMP ||
49214932 cur_tool == TOOL_SHAPES || cur_tool == TOOL_LINES ||
49224933 cur_tool == TOOL_MAGIC || cur_tool == TOOL_TEXT ||
49234934 cur_tool == TOOL_ERASER || cur_tool == TOOL_LABEL || cur_tool == TOOL_FILL))
@@ -6013,8 +6024,7 @@ static void mainloop(void)
60136024 if (do_draw)
60146025 update_screen_rect(&r_toolopt);
60156026 }
6016- } /* end if (!handle_as_color_picker) */
6017- }
6027+ } /* Close else if (HIT(r_toolopt)) at line 4833 */
60186028 else if (HIT_OFFSET_Y_COLORS(r_colors) && colors_are_selectable)
60196029 {
60206030#ifdef __ANDROID__
@@ -12993,42 +13003,9 @@ static void draw_color_picker_button(void)
1299313003 /* Show button when colorbar is hidden, in both expert and child mode */
1299413004 if (!colorbar_is_visible)
1299513005 {
12996- /* Calculate button area: from title/content to where colorbar would start */
13006+ /* Calculate button area using DRY helper function */
1299713007 int button_top, button_bottom;
12998-
12999- /* Reserve space for the button (minimum 150px, preferred 200px) */
13000- int button_min_height = 150;
13001- int button_preferred_height = 200;
13002-
13003- if (child_mode && (cur_tool == TOOL_BRUSH || cur_tool == TOOL_LINES))
13004- {
13005- /* In child mode with slider: calculate available space and split between slider and button */
13006- int available_height = WINDOW_HEIGHT - r_ttoolopt.h - 10;
13007-
13008- if (available_height >= button_min_height + 200)
13009- {
13010- /* Enough space: give button its preferred height, rest to slider */
13011- button_top = WINDOW_HEIGHT - button_preferred_height;
13012- }
13013- else if (available_height >= button_min_height + 100)
13014- {
13015- /* Limited space: give button minimum height, rest to slider */
13016- button_top = WINDOW_HEIGHT - button_min_height;
13017- }
13018- else
13019- {
13020- /* Very limited space: split 50/50 */
13021- button_top = r_ttoolopt.h + (available_height / 2);
13022- }
13023- }
13024- else
13025- {
13026- /* In expert mode or child mode without slider: button has fixed preferred height at bottom */
13027- button_top = WINDOW_HEIGHT - button_preferred_height;
13028- }
13029-
13030- /* Button goes to bottom of window */
13031- button_bottom = WINDOW_HEIGHT - 5; /* 5px margin from bottom */
13008+ get_color_picker_button_rect(child_mode, cur_tool, &button_top, &button_bottom);
1303213009
1303313010 SDL_Log("COLOR_PICKER: button_top=%d, button_bottom=%d, space=%d, WINDOW_HEIGHT=%d, r_colors.y=%d, ui_offset_y_colors=%d",
1303413011 button_top, button_bottom, button_bottom - button_top, WINDOW_HEIGHT, r_colors.y, ui_offset_y_colors);
0 commit comments