progress.*: cosmetix
[k8lowj.git] / src / progress.c
blob9e85d0b7ac2afc28ba0e1bf139f7777067d92db5
1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
3 */
4 #include "gtk-all.h"
6 #include "progress.h"
7 #include "throbber.h"
8 #include "util.h"
11 struct _ProgressWindow {
12 GtkWindow win;
13 GtkWidget *parent, *box, *clientbox;
14 GtkWidget *titlelabel, *label, *progress;
15 gboolean showing_error;
16 GtkWidget *throbber;
18 ProgressWindowCancelFunc cancel_cb;
19 gpointer cancel_cb_data;
23 __attribute__ ((format(printf, 2, 3))) void progress_window_show_error (ProgressWindow *pw, const char *fmt, ...) {
24 char buf[1024];
25 va_list ap;
27 va_start(ap, fmt);
28 g_vsnprintf(buf, 1024, fmt, ap);
29 va_end(ap);
31 if (pw) {
32 progress_window_set_title(pw, _("Error"));
33 gtk_label_set_text(GTK_LABEL(pw->label), buf);
34 throbber_stop(THROBBER(pw->throbber));
35 gtk_image_set_from_stock(GTK_IMAGE(pw->throbber), GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG);
36 gtk_widget_hide(pw->progress);
37 if (pw->clientbox)
38 gtk_widget_hide(pw->clientbox);
39 pw->showing_error = TRUE;
40 gtk_main();
41 } else {
42 g_print(_("Error: %s\n"), buf);
47 static void cancel_cb (ProgressWindow *pw) {
48 if (pw->showing_error) gtk_main_quit();
49 else if (pw->cancel_cb) pw->cancel_cb(pw->cancel_cb_data);
53 static void destroy_cb (GtkWidget *w, ProgressWindow *pw) {
54 throbber_stop(THROBBER(pw->throbber));
55 if (pw->parent) g_signal_handlers_disconnect_matched(pw->parent, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, pw);
59 static gboolean delete_event_cb (GtkWidget *w, GdkEvent *e, ProgressWindow *pw) {
60 cancel_cb(pw);
61 return TRUE; /* don't destroy us. */
65 static void reposition (ProgressWindow *pw, gint w, gint h) {
66 gint ox, oy, px, py, x, y;
67 if (!pw->parent) return;
68 gdk_window_get_origin(pw->parent->window, &px, &py);
69 if (w == -1) w = GTK_WIDGET(pw)->allocation.width;
70 if (h == -1) h = GTK_WIDGET(pw)->allocation.height;
71 x = px+(pw->parent->allocation.width-w)/2;
72 y = py+(pw->parent->allocation.height-h)/2;
73 gdk_window_get_origin(GTK_WIDGET(pw)->window, &ox, &oy);
74 if (x != ox || y != oy) gtk_window_move(GTK_WINDOW(pw), x, y);
78 static gboolean parent_configure_cb (GtkWidget *w, GdkEvent *e, ProgressWindow *pw) {
79 reposition(pw, -1, -1);
80 return FALSE;
84 static gboolean configure_cb (GtkWidget *w, GdkEventConfigure *e, ProgressWindow *pw) {
85 if (GTK_WIDGET(pw)->allocation.width != e->width || GTK_WIDGET(pw)->allocation.height != e->height) reposition(pw, e->width, e->height);
86 return FALSE;
90 static void progress_window_set_parent (ProgressWindow *pw, GtkWindow *parent) {
91 pw->parent = GTK_WIDGET(parent);
92 gtk_window_set_transient_for(GTK_WINDOW(pw), parent);
93 g_signal_connect(G_OBJECT(parent), "configure-event", G_CALLBACK(parent_configure_cb), pw);
97 static void progress_window_init (ProgressWindow *pw) {
98 GtkWidget *frame;
99 GtkWidget *vbox;
100 GtkWidget *hbox, *align, *bbox, *button, *lbox;
102 gtk_window_set_decorated(GTK_WINDOW(pw), FALSE);
103 gtk_window_set_type_hint(GTK_WINDOW(pw), GDK_WINDOW_TYPE_HINT_DIALOG);
104 gtk_window_set_modal(GTK_WINDOW(pw), TRUE);
105 gtk_window_set_default_size(GTK_WINDOW(pw), 250, -1);
106 g_signal_connect(G_OBJECT(pw), "destroy", G_CALLBACK(destroy_cb), pw);
107 g_signal_connect(G_OBJECT(pw), "delete-event", G_CALLBACK(delete_event_cb), pw);
108 gtk_window_set_position(GTK_WINDOW(pw), GTK_WIN_POS_CENTER_ON_PARENT);
109 g_signal_connect(G_OBJECT(pw), "configure-event", G_CALLBACK(configure_cb), pw);
111 vbox = gtk_vbox_new(FALSE, 6);
112 gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
114 hbox = gtk_hbox_new(FALSE, 6);
116 pw->throbber = throbber_new();
117 align = gtk_alignment_new(0.5, 0, 0, 0);
118 gtk_container_add(GTK_CONTAINER(align), pw->throbber);
119 gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, FALSE, 0);
120 throbber_start(THROBBER(pw->throbber));
122 pw->box = lbox = gtk_vbox_new(FALSE, 6);
123 pw->titlelabel = gtk_label_new(NULL);
124 gtk_box_pack_start(GTK_BOX(lbox), pw->titlelabel, TRUE, TRUE, 0);
126 pw->label = gtk_label_new(NULL);
127 gtk_label_set_line_wrap(GTK_LABEL(pw->label), TRUE);
128 gtk_box_pack_start(GTK_BOX(lbox), pw->label, TRUE, TRUE, 0);
130 pw->progress = gtk_progress_bar_new();
131 gtk_box_pack_end(GTK_BOX(lbox), pw->progress, FALSE, FALSE, 0);
133 gtk_box_pack_start(GTK_BOX(hbox), lbox, TRUE, TRUE, 0);
135 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
137 bbox = gtk_hbutton_box_new();
138 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
139 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
140 g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(cancel_cb), pw);
141 gtk_box_pack_end(GTK_BOX(bbox), button, FALSE, FALSE, 0);
142 gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
144 frame = gtk_frame_new(NULL);
145 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
146 gtk_container_add(GTK_CONTAINER(frame), vbox);
147 gtk_widget_show_all(frame);
148 gtk_widget_hide(pw->progress);
149 gtk_container_add(GTK_CONTAINER(pw), frame);
151 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
152 gtk_widget_grab_default(button);
156 void progress_window_pack (ProgressWindow *pw, GtkWidget *contents) {
157 if (!pw->clientbox) {
158 pw->clientbox = gtk_vbox_new(FALSE, 6);
159 gtk_box_pack_start(GTK_BOX(pw->box), pw->clientbox, TRUE, TRUE, 0);
160 gtk_widget_show(pw->clientbox);
162 gtk_box_pack_start(GTK_BOX(pw->clientbox), contents, FALSE, FALSE, 0);
166 void progress_window_set_title (ProgressWindow *pw, const char *title) {
167 char *t;
168 gtk_window_set_title(GTK_WINDOW(pw), title);
169 t = (title ? g_strdup_printf("<b>%s</b>", title) : g_strdup(""));
170 gtk_label_set_markup(GTK_LABEL(pw->titlelabel), t);
171 g_free(t);
175 void progress_window_set_text (ProgressWindow *pw, const char *text) {
176 gtk_label_set_text(GTK_LABEL(pw->label), text);
180 void progress_window_set_progress (ProgressWindow *pw, float frac) {
181 if (frac >= 0) gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pw->progress), frac);
182 if (frac > 0) gtk_widget_show(pw->progress); //else gtk_widget_hide(pw->progress);
186 void progress_window_set_cancel_cb (ProgressWindow *pw, ProgressWindowCancelFunc func, gpointer data) {
187 pw->cancel_cb = func;
188 pw->cancel_cb_data = data;
192 GtkWidget *progress_window_new (GtkWindow *parent, const char *title) {
193 ProgressWindow *pw = PROGRESS_WINDOW(g_object_new(progress_window_get_type(), NULL));
194 if (parent) progress_window_set_parent(pw, parent);
195 progress_window_set_title(pw, title);
196 return GTK_WIDGET(pw);
200 GType progress_window_get_type (void) {
201 static GType pw_type = 0;
202 if (!pw_type) {
203 static const GTypeInfo pw_info = {
204 sizeof(GtkWindowClass),
205 NULL,
206 NULL,
207 NULL, /*(GClassInitFunc) progress_window_class_init, */
208 NULL,
209 NULL,
210 sizeof(ProgressWindow),
212 (GInstanceInitFunc) progress_window_init,
214 pw_type = g_type_register_static(GTK_TYPE_WINDOW, "ProgressWindow", &pw_info, 0);
216 return pw_type;