home *** CD-ROM | disk | FTP | other *** search
- /* The GIMP -- an image manipulation program
- * Copyright (C) 1995 Spencer Kimball and Peter Mattis
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
- #include "config.h"
-
- #include <gtk/gtk.h>
-
- #include "apptypes.h"
-
- #include "appenv.h"
- #include "gdisplay.h"
- #include "gimpprogress.h"
- #include "gimpui.h"
-
- #include "libgimp/gimpintl.h"
-
-
- struct gimp_progress_pvt {
- GDisplay *gdisp; /* gdisp in use, or NULL*/
-
- /* next four fields are only valid if gdisp is NULL */
- GtkWidget *dialog; /* progress dialog, NULL if using gdisp */
- GtkWidget *dialog_label;
- GtkWidget *progressbar;
- GtkWidget *cancelbutton;
-
- GtkSignalFunc cancel_callback; /* callback to remove, or NULL */
- gpointer cancel_data;
- };
-
- /* prototypes */
- static void progress_signal_setup (gimp_progress *, GtkSignalFunc, gpointer);
-
-
- /* These progress bar routines are re-entrant, and so should be
- * thread-safe. */
-
-
- /* Start a progress bar on "gdisp" with reason "message". If "gdisp"
- * is NULL, the progress bar is presented in a new dialog box. If
- * "message" is NULL, then no message is used.
- *
- * If "cancel_callback" is not NULL, it is attached to the progress
- * bar cancel button's "clicked" signal, with data "cancel_data". The
- * cancel button is only made sensitive if the callback is set.
- *
- * It is an error to progress_start() a bar on a "gdisp" for which
- * there is already a progress bar active.
- *
- * Progress bars with "important" set to TRUE will be shown to the
- * user in any possible way. Unimportant progress bars will not be
- * shown to the user if it would mean creating a new window.
- */
- gimp_progress *
- progress_start (GDisplay *gdisp,
- const char *message,
- gboolean important,
- GtkSignalFunc cancel_callback,
- gpointer cancel_data)
- {
- gimp_progress *p;
- guint cid;
- GtkWidget *vbox;
-
- p = g_new (gimp_progress, 1);
-
- p->gdisp = gdisp;
- p->dialog = NULL;
- p->cancel_callback = NULL;
- p->cancel_data = NULL;
-
- /* do we have a useful gdisplay and statusarea? */
- if (gdisp && GTK_WIDGET_VISIBLE (gdisp->statusarea))
- {
- if (message)
- {
- cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar),
- "progress");
-
- gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), cid, message);
- }
-
- /* really need image locking to stop multiple people going at
- * the image */
- if (gdisp->progressid)
- g_warning("%d progress bars already active for display %p\n",
- gdisp->progressid, gdisp);
- gdisp->progressid++;
- }
- else
- {
- /* unimporant progress indications are occasionally failed */
- if (!important)
- {
- g_free (p);
- return NULL;
- }
-
- p->gdisp = NULL;
- p->dialog = gimp_dialog_new (_("Progress"), "plug_in_progress",
- NULL, NULL,
- GTK_WIN_POS_NONE,
- FALSE, TRUE, FALSE,
-
- _("Cancel"), NULL,
- NULL, NULL, &p->cancelbutton, TRUE, TRUE,
-
- NULL);
-
- vbox = gtk_vbox_new (FALSE, 2);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
- gtk_container_add (GTK_CONTAINER (GTK_DIALOG (p->dialog)->vbox), vbox);
- gtk_widget_show (vbox);
-
- p->dialog_label = gtk_label_new (message ? message :
- _("Please wait..."));
- gtk_misc_set_alignment (GTK_MISC (p->dialog_label), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (vbox), p->dialog_label, FALSE, TRUE, 0);
- gtk_widget_show (p->dialog_label);
-
- p->progressbar = gtk_progress_bar_new ();
- gtk_widget_set_usize (p->progressbar, 150, 20);
- gtk_box_pack_start (GTK_BOX (vbox), p->progressbar, TRUE, TRUE, 0);
- gtk_widget_show (p->progressbar);
-
- gtk_widget_show (p->dialog);
- }
-
- progress_signal_setup (p, cancel_callback, cancel_data);
-
- return p;
- }
-
-
- /* Update the message and/or the callbacks for a progress and reset
- * the bar to zero, with the minimum of disturbance to the user. */
- gimp_progress *
- progress_restart (gimp_progress *p,
- const char *message,
- GtkSignalFunc cancel_callback,
- gpointer cancel_data)
- {
- int cid;
- GtkWidget *bar;
-
- g_return_val_if_fail (p != NULL, p);
-
- /* change the message */
- if (p->gdisp)
- {
- cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (p->gdisp->statusbar),
- "progress");
- gtk_statusbar_pop (GTK_STATUSBAR (p->gdisp->statusbar), cid);
-
- if (message)
- gtk_statusbar_push (GTK_STATUSBAR (p->gdisp->statusbar), cid, message);
-
- bar = p->gdisp->progressbar;
- }
- else
- {
- gtk_label_set_text (GTK_LABEL (p->dialog_label),
- message ? message : _("Please wait..."));
- bar = p->progressbar;
- }
-
- /* reset the progress bar */
- gtk_progress_bar_update (GTK_PROGRESS_BAR (bar), 0.0);
-
- /* do we need to change the callbacks? */
- progress_signal_setup (p, cancel_callback, cancel_data);
-
- return p;
- }
-
-
- void
- progress_update (gimp_progress *progress,
- float percentage)
- {
- GtkWidget *bar;
-
- g_return_if_fail (progress != NULL);
-
- if (!(percentage >= 0.0 && percentage <= 1.0))
- return;
-
- /* do we have a dialog box, or are we using the statusbar? */
- if (progress->gdisp)
- bar = progress->gdisp->progressbar;
- else
- bar = progress->progressbar;
-
- gtk_progress_bar_update (GTK_PROGRESS_BAR (bar), percentage);
- }
-
-
- /* This function's prototype is conveniently the same as progress_func_t */
- void
- progress_update_and_flush (int ymin,
- int ymax,
- int curr_y,
- gpointer data)
- {
- progress_update ((gimp_progress *)data,
- (float)(curr_y - ymin) / (float)(ymax - ymin));
-
- /* HACK until we do long-running operations in the gtk idle thread */
- while (gtk_events_pending())
- gtk_main_iteration();
- }
-
-
- /* Step the progress bar by one percent, wrapping at 100% */
- void
- progress_step (gimp_progress *progress)
- {
- GtkWidget *bar;
- float val;
-
- g_return_if_fail (progress != NULL);
-
- if (progress->gdisp)
- bar = progress->gdisp->progressbar;
- else
- bar = progress->progressbar;
-
- val = gtk_progress_get_current_percentage (GTK_PROGRESS (bar)) + 0.01;
- if (val > 1.0)
- val = 0.0;
-
- progress_update (progress, val);
- }
-
-
- /* Finish using the progress bar "p" */
- void
- progress_end (gimp_progress *p)
- {
- int cid;
-
- g_return_if_fail (p != NULL);
-
- /* remove all callbacks so they don't get called while we're
- * destroying widgets */
- progress_signal_setup (p, NULL, NULL);
-
- if (p->gdisp)
- {
- cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (p->gdisp->statusbar),
- "progress");
- gtk_statusbar_pop (GTK_STATUSBAR (p->gdisp->statusbar), cid);
-
- gtk_progress_bar_update (GTK_PROGRESS_BAR (p->gdisp->progressbar), 0.0);
-
- if (p->gdisp->progressid > 0)
- p->gdisp->progressid--;
- }
- else
- {
- gtk_widget_destroy (p->dialog);
- }
-
- g_free (p);
- }
-
-
- /* Helper function to add or remove signals */
- static void
- progress_signal_setup (gimp_progress *p,
- GtkSignalFunc cancel_callback,
- gpointer cancel_data)
- {
- GtkWidget *button;
- GtkWidget *dialog;
-
- if (p->cancel_callback == cancel_callback && p->cancel_data == cancel_data)
- return;
-
- /* are we using the statusbar or a freestanding dialog? */
- if (p->gdisp)
- {
- dialog = NULL;
- button = p->gdisp->cancelbutton;
- }
- else
- {
- dialog = p->dialog;
- button = p->cancelbutton;
- }
-
- /* remove any existing signal handlers */
- if (p->cancel_callback)
- {
- gtk_signal_disconnect_by_func (GTK_OBJECT (button),
- p->cancel_callback, p->cancel_data);
- if (dialog)
- gtk_signal_disconnect_by_func (GTK_OBJECT (dialog),
- p->cancel_callback, p->cancel_data);
- }
-
- /* add the new handlers */
- if (cancel_callback)
- {
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- cancel_callback, cancel_data);
-
- if (dialog)
- gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
- cancel_callback, cancel_data);
- }
-
- gtk_widget_set_sensitive (GTK_WIDGET (button),
- cancel_callback ? TRUE : FALSE);
-
- p->cancel_callback = cancel_callback;
- p->cancel_data = cancel_data;
- }
-
- /* End of gimpprogress.c */
-