Wrap up GIF export UI

GIF export button now jumps to a process that iterates through the
chosen saved images, loading each (but not yet saving as a GIF).
It then returns to the Open->Slideshow dialog, and displays a
pop-up dialog that shows a success/fail message.

Also, adding an icon for a regular static image "Export" option,
to be added to the main Open dialog.
This commit is contained in:
Bill Kendrick 2020-07-26 11:46:12 -07:00
parent 7aa91af319
commit 28b28d583e

View file

@ -22,7 +22,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
June 14, 2002 - July 25, 2020
June 14, 2002 - July 26, 2020
*/
@ -1436,7 +1436,7 @@ static SDL_Surface *img_dead40x40;
static SDL_Surface *img_black, *img_grey;
static SDL_Surface *img_yes, *img_no;
static SDL_Surface *img_sfx, *img_speak;
static SDL_Surface *img_open, *img_erase, *img_back, *img_trash;
static SDL_Surface *img_open, *img_erase, *img_back, *img_trash, *img_pict_export;
static SDL_Surface *img_slideshow, *img_play, *img_gif_export, *img_select_digits;
static SDL_Surface *img_printer, *img_printer_wait;
static SDL_Surface *img_save_over, *img_popup_arrow;
@ -1761,7 +1761,7 @@ static short *brushes_directional = NULL;
static SDL_Surface *img_shapes[NUM_SHAPES], *img_shape_names[NUM_SHAPES];
static SDL_Surface *img_openlabels_open, *img_openlabels_erase,
*img_openlabels_slideshow, *img_openlabels_back, *img_openlabels_play,
*img_openlabels_gif_export, *img_openlabels_next;
*img_openlabels_gif_export, *img_openlabels_pict_export, *img_openlabels_next;
static SDL_Surface *img_tux[NUM_TIP_TUX];
@ -1984,8 +1984,8 @@ static int do_slideshow(void);
static void play_slideshow(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed);
static void draw_selection_digits(int right, int bottom, int n);
void do_export_gif(void);
char * get_export_filepath(void);
static int export_gif(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed);
static char * get_export_filepath(const char * ext);
static void wait_for_sfx(void);
static void rgbtohsv(Uint8 r8, Uint8 g8, Uint8 b8, float *h, float *s, float *v);
@ -2177,6 +2177,19 @@ static void do_wait(int counter)
#define PROMPT_TIP_LEFTCLICK_TXT gettext_noop("Remember to use the left mouse button!")
#define PROMPT_TIP_LEFTCLICK_YES gettext_noop("OK")
/* Confirmation of successful (we hope) image export */
#define PROMPT_PICT_EXPORT_TXT gettext_noop("Your picture has been exported!")
#define PROMPT_GIF_EXPORT_TXT gettext_noop("Your slideshow GIF has been exported!")
#define PROMPT_EXPORT_YES gettext_noop("OK")
/* We got an error exporting */
#define PROMPT_PICT_EXPORT_FAILED_TXT gettext_noop("Sorry! Your picture could not be exported!")
#define PROMPT_GIF_EXPORT_FAILED_TXT gettext_noop("Sorry! Your slideshow GIF could not be exported!")
/* Slideshow instructions */
#define TUX_TIP_SLIDESHOW gettext("Choose the pictures you want, then click “Play”.")
enum
{
@ -7872,6 +7885,9 @@ static void create_button_labels(void)
/* Open dialog: 'Slides' button, to switch to slide show mode */
img_openlabels_slideshow = do_render_button_label(gettext_noop("Slides"));
/* Open dialog: 'Export' button, to copy an image to an easily-accessible location */
img_openlabels_pict_export = do_render_button_label(gettext_noop("Export"));
/* Open dialog: 'Back' button, to dismiss Open dialog without opening a picture */
img_openlabels_back = do_render_button_label(gettext_noop("Back"));
@ -11243,9 +11259,13 @@ static int SDLCALL NondefectiveBlit(SDL_Surface * src, SDL_Rect * srcrect, SDL_S
/**
* FIXME
* Copy an image, scaling and smearing, as needed, into a new surface.
* Free the original surface.
*
* @param SDL_Surface * src -- source surface (will be freed by this function!)
* @param SDL_Surface * dst -- destination surface
* @param int SDCALL(*blit) -- function for blitting; "NondefectiveBlit" or "SDL_BlitSurface"
*/
/* For the 3rd arg, pass either NondefectiveBlit or SDL_BlitSurface. */
static void autoscale_copy_smear_free(SDL_Surface * src, SDL_Surface * dst,
int SDLCALL(*blit) (SDL_Surface * src,
SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect))
@ -12418,9 +12438,11 @@ static void cleanup(void)
free_surface(&img_openlabels_open);
free_surface(&img_openlabels_slideshow);
free_surface(&img_openlabels_erase);
free_surface(&img_openlabels_pict_export);
free_surface(&img_openlabels_back);
free_surface(&img_openlabels_next);
free_surface(&img_openlabels_play);
free_surface(&img_openlabels_gif_export);
free_surface(&img_progress);
@ -12440,11 +12462,13 @@ static void cleanup(void)
free_surface(&img_open);
free_surface(&img_erase);
free_surface(&img_pict_export);
free_surface(&img_back);
free_surface(&img_trash);
free_surface(&img_slideshow);
free_surface(&img_play);
free_surface(&img_gif_export);
free_surface(&img_select_digits);
free_surface(&img_dead40x40);
@ -13860,9 +13884,12 @@ static int do_png_save(FILE * fi, const char *const fname, SDL_Surface * surf, i
}
/**
* FIXME
* Generate a new file ID. Used when saving a picture for
* the first time (i.e., very first save, or saving as a new
* file, rather than overwriting/replacing the existing version).
*
* Affects "file_id" string.
*/
/* Pick a new file ID: */
static void get_new_file_id(void)
{
time_t t;
@ -13871,9 +13898,6 @@ static void get_new_file_id(void)
strftime(file_id, sizeof(file_id), "%Y%m%d%H%M%S", localtime(&t));
debug(file_id);
/* FIXME: Show thumbnail and prompt for title: */
}
@ -15053,6 +15077,7 @@ static int do_slideshow(void)
SDL_Surface *btn, *blnk;
int val_x, val_y, motioner;
int valhat_x, valhat_y, hatmotioner;
int export_successful;
val_x = val_y = motioner = 0;
valhat_x = valhat_y = hatmotioner = 0;
@ -15294,8 +15319,8 @@ static int do_slideshow(void)
#endif
/* Let user choose images: */
/* Instructions for Slideshow file dialog (FIXME: Make a #define) */
instructions = textdir(gettext_noop("Choose the pictures you want, " "then click “Play”."));
/* Instructions for Slideshow file dialog */
instructions = textdir(TUX_TIP_SLIDESHOW);
draw_tux_text(TUX_BORED, instructions, 1);
/* NOTE: cur is now set above; if file_id'th file is found, it's
@ -15628,8 +15653,8 @@ static int do_slideshow(void)
draw_colors(COLORSEL_CLOBBER_WIPE);
draw_none();
/* Instructions for Slideshow file dialog (FIXME: Make a #define) */
freeme = textdir(gettext_noop("Choose the pictures you want, " "then click “Play”."));
/* Instructions for Slideshow file dialog */
freeme = textdir(TUX_TIP_SLIDESHOW);
draw_tux_text(TUX_BORED, freeme, 1);
free(freeme);
@ -15675,7 +15700,7 @@ static int do_slideshow(void)
if (num_selected < 2)
{
/* None selected? Too dangerous to select all.
/* None selected? Too dangerous to automatically select all (like we do for slideshow playback).
Only 1 selected? No point in saving as GIF.
*/
freeme = textdir(gettext_noop("Select 2 or more drawings to turn into an animated GIF."));
@ -15686,7 +15711,27 @@ static int do_slideshow(void)
}
else
{
do_export_gif();
export_successful = export_gif(selected, num_selected, dirname, d_names, d_exts, speed);
/* Redraw entire screen, after export: */
SDL_FillRect(screen, NULL, SDL_MapRGB(canvas->format, 255, 255, 255));
draw_toolbar();
draw_colors(COLORSEL_CLOBBER_WIPE);
draw_none();
/* Show a message depending on success */
if (export_successful)
do_prompt_snd(PROMPT_GIF_EXPORT_TXT, PROMPT_EXPORT_YES, "", SND_TUXOK, screen->w / 2, screen->h / 2);
else
do_prompt_snd(PROMPT_GIF_EXPORT_FAILED_TXT, PROMPT_EXPORT_YES, "", SND_YOUCANNOT, screen->w / 2, screen->h / 2);
freeme = textdir(TUX_TIP_SLIDESHOW);
draw_tux_text(TUX_BORED, freeme, 1);
free(freeme);
SDL_Flip(screen);
update_list = 1;
}
}
else if (event.button.x >= (WINDOW_WIDTH - 96 - 48) &&
@ -15839,7 +15884,16 @@ static int do_slideshow(void)
/**
* FIXME
* Play an animated slideshow within Tux Paint.
* Called by the Open->Slideshow dialog, once a set of images
* have been selected/chosen, and "Play" is clicked.
*
* @param int * selected -- array of selected images, in the order they should be played
* @param int num_selected -- count of how many images were selected
* @char * dirname -- path to the directory of saved images to be played
* @char ** d_names -- array of file basenames of the images to be played
* @char ** d_ext -- array of file exentions of the images to be played
* @int speed -- how fast to play the slideshow (0 = no automatic advance, 1 = slowest, 10 = as fast as possible)
*/
static void play_slideshow(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed)
{
@ -15858,9 +15912,9 @@ static void play_slideshow(int *selected, int num_selected, char *dirname, char
val_x = val_y = motioner = 0;
valhat_x = valhat_y = hatmotioner = 0;
/* Back up the current image's IDs, because they will get
clobbered below! */
tmp_starter_id = strdup(starter_id);
tmp_template_id = strdup(template_id);
tmp_file_id = strdup(file_id);
@ -16066,6 +16120,8 @@ static void play_slideshow(int *selected, int num_selected, char *dirname, char
}
while (!done);
/* Restore everything about the currently-active image
that got clobbered above */
strcpy(starter_id, tmp_starter_id);
free(tmp_starter_id);
@ -24071,6 +24127,7 @@ static void setup(void)
img_open = loadimage(DATA_PREFIX "images/ui/open.png");
img_erase = loadimage(DATA_PREFIX "images/ui/erase.png");
img_pict_export = loadimage(DATA_PREFIX "images/ui/pict_export.png");
img_back = loadimage(DATA_PREFIX "images/ui/back.png");
img_trash = loadimage(DATA_PREFIX "images/ui/trash.png");
@ -25250,21 +25307,148 @@ char * get_xdg_user_dir(const char * dir_type, const char * fallback) {
/**
* After 2+ images have been selected in the Open->Slideshow
* dialog, they can be exported as an animated GIF.
*
* Params the same as play_slideshow(), except...
*
* @param int speed -- how fast to play the slideshow (0 and 1 both = slowest, 10 = fasted)
* @return int -- 0 if export failed or was aborted, 1 if successful
*/
void do_export_gif(void) {
static int export_gif(int *selected, int num_selected, char *dirname, char **d_names, char **d_exts, int speed) {
char * gif_fname;
char fname[MAX_PATH];
int i, done, which;
SDL_Event event;
SDLKey key;
SDL_Surface *img;
char *tmp_starter_id, *tmp_template_id, *tmp_file_id;
int tmp_starter_mirrored, tmp_starter_flipped, tmp_starter_personal;
/* Back up the current image's IDs, because they will get
clobbered below! */
tmp_starter_id = strdup(starter_id);
tmp_template_id = strdup(template_id);
tmp_file_id = strdup(file_id);
tmp_starter_mirrored = starter_mirrored;
tmp_starter_flipped = starter_flipped;
tmp_starter_personal = starter_personal;
do_setcursor(cursor_watch);
show_progress_bar(screen);
gif_fname = get_export_filepath("gif");
/* FIXME: Open GIF */
done = 0;
for (i = 0; i < num_selected && !done; i++)
{
which = selected[i];
show_progress_bar(screen);
/* Figure out filename: */
snprintf(fname, sizeof(fname), "%s/%s%s", dirname, d_names[which], d_exts[which]);
img = myIMG_Load(fname);
if (img != NULL)
{
autoscale_copy_smear_free(img, screen, SDL_BlitSurface);
strcpy(file_id, d_names[which]);
/* See if this saved image was based on a 'starter' */
load_starter_id(d_names[which], NULL);
if (starter_id[0] != '\0')
{
load_starter(starter_id);
if (starter_mirrored)
mirror_starter();
if (starter_flipped)
flip_starter();
}
else
load_template(template_id);
} else {
/* Error loading !*/
fprintf(stderr, "Error loading %s!\n", fname);
/* FIXME */
}
SDL_Flip(screen);
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
done = 1;
}
else if (event.type == SDL_KEYDOWN)
{
key = event.key.keysym.sym;
if (key == SDLK_ESCAPE) {
done = 1;
}
}
}
SDL_Delay(10);
}
/* FIXME: Quantize */
/* FIXME: Export each frame */
/* FIXME: Close GIF */
/* Restore everything about the currently-active image
that got clobbered above */
strcpy(starter_id, tmp_starter_id);
free(tmp_starter_id);
strcpy(template_id, tmp_template_id);
free(tmp_template_id);
strcpy(file_id, tmp_file_id);
free(tmp_file_id);
starter_mirrored = tmp_starter_mirrored;
starter_flipped = tmp_starter_flipped;
starter_personal = tmp_starter_personal;
free(gif_fname);
/* Success if we didn't have an error, and user didn't abort */
return(!done);
}
/**
* Returns the user's chosen export directory
* for animated GIFs, via Open->Slideshow dialog,
* and static PNGs, via Open dialog */
char * get_export_filepath(void) {
* Returns the name of a new file, located in the user's chosen
* export directory (e.g., ~/Pictures, or whatever "--exportdir" says).
*
* Used when exporting animated GIFs (via "Export GIF" in the
* Open->Slideshow dialog) and static PNGs (via "Export" in the
* main Open dialog).
*
* @param const char * ext -- extnesion of the file (e.g., "png" or "gif")
* @return char * -- filepath for the new file to be created
* (e.g., /home/username/Pictures/2020072620110100.gif")
*/
static char * get_export_filepath(const char * ext) {
char *rname;
char fname[FILENAME_MAX];
char timestamp[16];
time_t t;
rname = NULL;
/*
snprintf(fname, sizeof(fname), "saved/%s.dat", saved_id);
rname = get_fname(fname, DIR_SAVE);
*/
t = time(NULL);
strftime(timestamp, sizeof(timestamp), "%Y%m%d%H%M%S", localtime(&t));
snprintf(fname, sizeof(fname), "%s.%s", timestamp, ext);
rname = get_fname(fname, DIR_EXPORT);
debug(rname);
return(rname);
}