From 076b15fd2019d16b717f3aae39d21e3bb33a5bf3 Mon Sep 17 00:00:00 2001 From: Bill Kendrick Date: Wed, 26 Jan 2022 00:20:14 -0800 Subject: [PATCH] Rigging up do_color_sel() to offer immediate mode The pick-a-color-from-the-canvas color selection feature (the option in the color palette showing a pipette icon) has been extended to support an immediate mode (return on "mouse-up" event, don't show a "Back" button, and don't animate the appearance of the color dialog at the bottom), which will be used by a forthcoming feature that will offer a keyboard shortcut to bring up this color selection option. --- docs/CHANGES.txt | 4 ++ src/tuxpaint.c | 169 ++++++++++++++++++++++++++++++----------------- 2 files changed, 112 insertions(+), 61 deletions(-) diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt index 3a71b9006..d471084a4 100644 --- a/docs/CHANGES.txt +++ b/docs/CHANGES.txt @@ -70,6 +70,10 @@ http://www.tuxpaint.org/ * Show a "pipette"-shaped mouse pointer when selecting a color from the color palette, or the picture. + * WIP Provide a keyboard shortcut for picking colors from + the canvas more quickly. + Closes https://sourceforge.net/p/tuxpaint/feature-requests/209/ + * Localization Updates: --------------------- * Albanian translation diff --git a/src/tuxpaint.c b/src/tuxpaint.c index 9aefa83b6..b3289685e 100644 --- a/src/tuxpaint.c +++ b/src/tuxpaint.c @@ -2179,7 +2179,7 @@ static int do_new_dialog(void); static int do_new_dialog_add_colors(SDL_Surface * *thumbs, int num_files, int *d_places, char * *d_names, char * *d_exts, int *white_in_palette); static int do_color_picker(void); -static int do_color_sel(void); +static int do_color_sel(int temp_mode); static int do_slideshow(void); static void play_slideshow(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed); @@ -4718,7 +4718,7 @@ static void mainloop(void) if (cur_color == (unsigned)(NUM_COLORS - 1)) do_color_picker(); else - do_color_sel(); + do_color_sel(0); if (cur_tool == TOOL_TEXT || cur_tool == TOOL_LABEL) { @@ -21885,9 +21885,17 @@ static Uint8 magic_touched(int x, int y) } /** - * FIXME + * Allow the user to select a color from one of the + * pixels within their picture. + * + * @param boolean temp_mode - whether to only appear + * while a shortcut key is being held + * (if not, the mouse will be positioned at the bottom + * center, the UI will show a "Back" button, and wait + * for a color to be clicked in the canvas, or the "Back" + * button to be clicked) */ -static int do_color_sel(void) +static int do_color_sel(int temp_mode) { #ifndef NO_PROMPT_SHADOWS SDL_Surface *alpha_surf; @@ -21903,9 +21911,18 @@ static int do_color_sel(void) int done, chose; int back_left, back_top; int color_sel_x = 0, color_sel_y = 0; - int want_animated_popups = 1; + int want_animated_popups; SDL_Surface *tmp_btn_up, *tmp_btn_down; + if (!temp_mode) + { + want_animated_popups = 1; + } + else + { + want_animated_popups = 0; + } + Uint32(*getpixel_tmp_btn_up) (SDL_Surface *, int, int); Uint32(*getpixel_tmp_btn_down) (SDL_Surface *, int, int); Uint32(*getpixel_img_paintwell) (SDL_Surface *, int, int); @@ -21922,8 +21939,6 @@ static int do_color_sel(void) val_x = val_y = motioner = 0; valhat_x = valhat_y = hatmotioner = 0; - /* FIXME this is the first step to make animated popups optional, - to be removed from here when implemented in a more general way */ hide_blinking_cursor(); @@ -22016,13 +22031,11 @@ static int do_color_sel(void) /* Determine spot for example color: */ - color_example_dest.x = r_color_sel.x + 2; color_example_dest.y = r_color_sel.y + 2; color_example_dest.w = r_color_sel.w - button_w - 8; color_example_dest.h = r_color_sel.h - 4; - SDL_FillRect(screen, &color_example_dest, SDL_MapRGB(screen->format, 0, 0, 0)); color_example_dest.x += 2; @@ -22039,29 +22052,38 @@ static int do_color_sel(void) - /* Draw current color picker color: */ + if (!temp_mode) + { + /* Draw current color picker color: */ + + SDL_FillRect(screen, &color_example_dest, + SDL_MapRGB(screen->format, + color_hexes[NUM_COLORS - 2][0], + color_hexes[NUM_COLORS - 2][1], color_hexes[NUM_COLORS - 2][2])); - SDL_FillRect(screen, &color_example_dest, - SDL_MapRGB(screen->format, - color_hexes[NUM_COLORS - 2][0], - color_hexes[NUM_COLORS - 2][1], color_hexes[NUM_COLORS - 2][2])); - - - - /* Show "Back" button */ - - back_left = r_color_sel.x + r_color_sel.w - button_w - 4; - back_top = r_color_sel.y; - - dest.x = back_left; - dest.y = back_top; - - SDL_BlitSurface(img_back, NULL, screen, &dest); - - dest.x = back_left + (img_back->w - img_openlabels_back->w) / 2; - dest.y = back_top + img_back->h - img_openlabels_back->h; - SDL_BlitSurface(img_openlabels_back, NULL, screen, &dest); + /* Show "Back" button */ + back_left = r_color_sel.x + r_color_sel.w - button_w - 4; + back_top = r_color_sel.y; + + dest.x = back_left; + dest.y = back_top; + + SDL_BlitSurface(img_back, NULL, screen, &dest); + + dest.x = back_left + (img_back->w - img_openlabels_back->w) / 2; + dest.y = back_top + img_back->h - img_openlabels_back->h; + SDL_BlitSurface(img_openlabels_back, NULL, screen, &dest); + } + else + { + int mx, my; + /* Temp mode: Grab color from canvas under the mouse immediately + (let the motion-handling code in the loop below do it for us!) */ + SDL_GetMouseState(&mx, &my); + SDL_WarpMouse(mx - 1, my); /* Need to move to a different spot, or no events occur */ + SDL_WarpMouse(mx, my); + } /* Blit canvas on screen */ @@ -22078,8 +22100,11 @@ static int do_color_sel(void) #ifndef __ANDROID__ /* FIXME: Strangely, this SDL_WarpMouse makes further event.button.x/y to be 0 on Android, thus making the selector unresponsive. Needs testing on other operating sistems with touchscreen. */ - SDL_WarpMouse(r_color_sel.x + r_color_sel.w / 2, r_color_sel.y + r_color_sel.h / 2); + + if (!temp_mode) + SDL_WarpMouse(r_color_sel.x + r_color_sel.w / 2, r_color_sel.y + r_color_sel.h / 2); #endif + do { while (SDL_PollEvent(&event)) @@ -22107,6 +22132,7 @@ static int do_color_sel(void) if (key == SDLK_ESCAPE) { + /* Hit [Escape]; abort (in either full UI or temporary mode) */ chose = 0; done = 1; } @@ -22117,7 +22143,7 @@ static int do_color_sel(void) event.button.x < r_canvas.x + r_canvas.w && event.button.y >= r_canvas.y && event.button.y < r_canvas.y + r_canvas.h) { - /* Picked a color! */ + /* Picked a color in the canvas, and released! */ chose = 1; done = 1; @@ -22128,14 +22154,26 @@ static int do_color_sel(void) color_sel_x = x; color_sel_y = y; } - else if (event.button.x >= back_left && - event.button.x < back_left + img_back->w && - event.button.y >= back_top && event.button.y < back_top + img_back->h) + else { - /* Decided to go Back */ - - chose = 0; - done = 1; + if (!temp_mode) + { + if (event.button.x >= back_left && + event.button.x < back_left + img_back->w && + event.button.y >= back_top && event.button.y < back_top + img_back->h) + { + /* Full UI mode: Decided to go Back; abort */ + + chose = 0; + done = 1; + } + } + else + { + /* Temp mode: Released outside of canvas; abort */ + chose = 0; + done = 1; + } } } else if (event.type == SDL_MOUSEMOTION) @@ -22144,7 +22182,7 @@ static int do_color_sel(void) event.button.x < r_canvas.x + r_canvas.w && event.button.y >= r_canvas.y && event.button.y < r_canvas.y + r_canvas.h) { - /* Hovering over the colors! */ + /* Hovering over the canvas! */ do_setcursor(cursor_pipette); @@ -22165,27 +22203,32 @@ static int do_color_sel(void) } else { - /* Revert to current color picker color, so we know what it was, - and what we'll get if we go Back: */ + /* Outside the canvas... */ - SDL_FillRect(screen, &color_example_dest, - SDL_MapRGB(screen->format, - color_hexes[NUM_COLORS - 2][0], - color_hexes[NUM_COLORS - 2][1], color_hexes[NUM_COLORS - 2][2])); - - SDL_UpdateRect(screen, - color_example_dest.x, - color_example_dest.y, color_example_dest.w, color_example_dest.h); - - - /* Change cursor to arrow (or hand, if over Back): */ - - if (event.button.x >= back_left && - event.button.x < back_left + img_back->w && - event.button.y >= back_top && event.button.y < back_top + img_back->h) - do_setcursor(cursor_hand); - else - do_setcursor(cursor_arrow); + if (!temp_mode) + { + /* Revert to current color picker color, so we know what it was, + and what we'll get if we go Back: */ + + SDL_FillRect(screen, &color_example_dest, + SDL_MapRGB(screen->format, + color_hexes[NUM_COLORS - 2][0], + color_hexes[NUM_COLORS - 2][1], color_hexes[NUM_COLORS - 2][2])); + + SDL_UpdateRect(screen, + color_example_dest.x, + color_example_dest.y, color_example_dest.w, color_example_dest.h); + + + /* Change cursor to arrow (or hand, if over Back): */ + + if (event.button.x >= back_left && + event.button.x < back_left + img_back->w && + event.button.y >= back_top && event.button.y < back_top + img_back->h) + do_setcursor(cursor_hand); + else + do_setcursor(cursor_arrow); + } } oldpos_x = event.motion.x; @@ -22299,7 +22342,11 @@ static int do_color_sel(void) } /** - * FIXME + * Display a large prompt, allowing the user to pick a + * color from a large palette. + * + * FIXME: Various options here would be helpful + * (RGB, HSV, color wheel, etc.) -bjk 2022.01.25 */ static int do_color_picker(void) {