diff options
Diffstat (limited to 'frontend/pisa_progress_window.cc')
-rw-r--r-- | frontend/pisa_progress_window.cc | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/frontend/pisa_progress_window.cc b/frontend/pisa_progress_window.cc new file mode 100644 index 0000000..6cc5b50 --- /dev/null +++ b/frontend/pisa_progress_window.cc @@ -0,0 +1,263 @@ +/* pisa_progress_window.cc + Copyright (C) 2001, 2004 SEIKO EPSON CORPORATION + + This file is part of the `iscan' program. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + As a special exception, the copyright holders give permission + to link the code of this program with the esmod library and + distribute linked combinations including the two. You must obey + the GNU General Public License in all respects for all of the + code used other then esmod. +*/ + +#include <config.h> + +#include "pisa_progress_window.h" +#include "gettext.h" +#define _(msg_id) gettext (msg_id) + +#include <cmath> +#include <iostream> + +#include "pisa_main_window.h" +#include "pisa_view_manager.h" + + +// callbacks for use by the GTK+ toolkit +static gint _delete (GtkWidget *, progress_window *); +static void _cancel (GtkWidget *, progress_window *); + + +/*! Creates an instance as the child of a \a parent widget. The \a + parent widget, by default, is the root window. + + Initially, the message will be set to progress_window::WARMING_UP + with the control button disabled. The instance will \e not be made + visible. Use the show() and hide() members to control visibility. +*/ +progress_window:: progress_window (GtkWidget *parent) + : _msg (-1), _can (false), _last_step (0) +{ + // first, let's gtk_*_new all the main players + _box = (GtkDialog *) gtk_dialog_new (); + _txt = (GtkLabel *) gtk_label_new (""); + _bar = (GtkProgressBar *) gtk_progress_bar_new (); + _btn = (GtkButton *) gtk_button_new (); + + _btn_cancel = gtk_label_new (_(" Cancel ")); + _btn_finish = gtk_label_new (_(" Finish ")); + + if (!_box || !_txt || !_bar || !_btn + || !_btn_cancel || !_btn_finish) { + if (_btn_finish) gtk_widget_destroy (_btn_finish); + if (_btn_cancel) gtk_widget_destroy (_btn_cancel); + + if (_btn) gtk_widget_destroy (GTK_WIDGET (_btn)); + if (_bar) gtk_widget_destroy (GTK_WIDGET (_bar)); + if (_txt) gtk_widget_destroy (GTK_WIDGET (_txt)); + if (_box) gtk_widget_destroy (GTK_WIDGET (_box)); + throw std::bad_alloc (); + } + + // container + gtk_window_set_policy (GTK_WINDOW (_box), false, false, true); + gtk_window_set_title (GTK_WINDOW (_box), PACKAGE); + gtk_container_border_width (GTK_CONTAINER (_box->vbox), 5); + gtk_widget_realize (GTK_WIDGET (_box)); + gtk_signal_connect (GTK_OBJECT (_box), "delete_event", + GTK_SIGNAL_FUNC (_delete), this); + + // message + gtk_box_pack_start (GTK_BOX (_box->vbox), GTK_WIDGET(_txt), + false, false, 5); + + // progress + gtk_widget_set_usize (GTK_WIDGET (_bar), 350, 20); + gtk_box_pack_start (GTK_BOX (_box->vbox), GTK_WIDGET(_bar), + false, false, 5); + + // actions + GTK_WIDGET_SET_FLAGS (GTK_WIDGET (_btn), GTK_CAN_DEFAULT); + gtk_box_pack_start (GTK_BOX (_box->action_area), GTK_WIDGET (_btn), + false, false, 0); + gtk_signal_connect (GTK_OBJECT (_btn), "clicked", + GTK_SIGNAL_FUNC (_cancel), this); + gtk_widget_grab_default (GTK_WIDGET (_btn)); + + set_text (WARMING_UP); + + gtk_window_set_modal (GTK_WINDOW (_box), true); + gtk_window_set_transient_for (GTK_WINDOW (_box), GTK_WINDOW (parent)); +} + +progress_window::~progress_window (void) +{ + gtk_widget_destroy (GTK_WIDGET (_btn_cancel)); + gtk_widget_destroy (GTK_WIDGET (_btn_finish)); + + gtk_widget_destroy (GTK_WIDGET (_box)); +} + +void +progress_window::show (void) +{ + gtk_widget_show_all (GTK_WIDGET (_box)); +} + +void +progress_window::hide (void) +{ + gtk_widget_hide (GTK_WIDGET (_box)); +} + +/*! This member function sets the progress indicator to show the + percentage of \a progress that has been made in terms of an \a + estimated_total. + + In many situations the estimated total can be known beforehand and + will not vary, but in some circumstances this estimate may change, + or become more precisely known, so that you may want to update the + progress indicator even if there was \e no \a progress. +*/ +void +progress_window::set_progress (double progress, double estimated_total) +{ + if (0 == estimated_total) return; + + int step = _step_count * (progress / estimated_total); + + if (_last_step != step) + { + gtk_progress_bar_set_fraction (_bar, progress / estimated_total); + _last_step = step; + } +} + +/*! Changes the text in the message area to an arbitrary \a message. + */ +void +progress_window::set_text (const char *message) +{ + gtk_label_set_text (_txt, message); +} + +/*! Changes the text in the message area to one of the "canned" + messages and adjusts the control button's look and behaviour as + specified in the progress_window::message documentation. + */ +void +progress_window::set_text (message id) +{ + _last_step = 0; + if (id == _msg) // nothing to do + return; + + switch (id) { + case WARMING_UP: + set_text (_("Scanner is warming up. Please wait...")); + break; + case PREVIEWING: + set_text (_("Pre-scanning in Progress")); + break; + case SCANNING: + set_text (_("Scanning in Progress")); + break; + case WAITING: + set_text (_("Starting a sequence of scans.\n" + "Press to scanner's Start button to start each scan.")); + break; + default: // should have been caught by the compiler! + throw; + } + + if (-1 == _msg) { // we were called by the constructor + GtkWidget *lbl = (WAITING == id) ? _btn_finish : _btn_cancel; + gtk_container_add (GTK_CONTAINER (_btn), lbl); + } + + if (WAITING == id && WAITING != _msg) { + flip_label (_btn_cancel, _btn_finish); + } + if (WAITING != id && WAITING == _msg) { + flip_label (_btn_finish, _btn_cancel); + } + + gtk_widget_set_sensitive (GTK_WIDGET (_btn), (WARMING_UP != id)); + + _msg = id; +} + +/*! Returns true when the user has requested cancellation of the + action(s) the object is reporting progress on, false otherwise. + */ +bool +progress_window::is_cancelled (void) const +{ + return _can; +} + +/*! Mainly intended for internal use (by the GTK+ callbacks, to be + precise), this member function raises a flag indicating that the + user requested cancellation of the action(s) that this object is + reporting on. + + Cancellation requests can not be revoked. + + \note It is up to the application to check for and honour such + requests. + */ +void +progress_window::cancel (void) +{ + if (WARMING_UP != _msg) + _can = true; +} + +/*! Changes the control button's label \a from one \a to another. + + \internal Just removing the label from its container would result in + its destruction unless someone holds onto a reference for the label + object. Since we may want to reuse the label, we add a reference + before its removal. + */ +void +progress_window::flip_label (GtkWidget *from, GtkWidget *to) +{ + gtk_object_ref (GTK_OBJECT (from)); + gtk_container_remove (GTK_CONTAINER (_btn), from); + gtk_container_add (GTK_CONTAINER (_btn), to); + gtk_widget_show (to); +} + + +static +gint +_delete (GtkWidget *, progress_window *p) +{ + if (p) + p->cancel (); + + return true; +} + +static +void +_cancel (GtkWidget *, progress_window *p) +{ + if (p) + p->cancel (); +} |