84
105
GimpStatusbar *statusbar);
85
106
static guint gimp_statusbar_get_context_id (GimpStatusbar *statusbar,
86
107
const gchar *context);
89
static GtkHBoxClass *parent_class = NULL;
93
gimp_statusbar_get_type (void)
95
static GType statusbar_type = 0;
99
static const GTypeInfo statusbar_info =
101
sizeof (GimpStatusbarClass),
102
(GBaseInitFunc) NULL,
103
(GBaseFinalizeFunc) NULL,
104
(GClassInitFunc) gimp_statusbar_class_init,
105
NULL, /* class_finalize */
106
NULL, /* class_data */
107
sizeof (GimpStatusbar),
109
(GInstanceInitFunc) gimp_statusbar_init,
112
static const GInterfaceInfo progress_iface_info =
114
(GInterfaceInitFunc) gimp_statusbar_progress_iface_init,
115
NULL, /* iface_finalize */
116
NULL /* iface_data */
119
statusbar_type = g_type_register_static (GTK_TYPE_HBOX,
123
g_type_add_interface_static (statusbar_type, GIMP_TYPE_PROGRESS,
124
&progress_iface_info);
127
return statusbar_type;
108
static gboolean gimp_statusbar_temp_timeout (GimpStatusbar *statusbar);
110
static void gimp_statusbar_msg_free (GimpStatusbarMsg *msg);
112
static gchar * gimp_statusbar_vprintf (const gchar *format,
116
G_DEFINE_TYPE_WITH_CODE (GimpStatusbar, gimp_statusbar, GTK_TYPE_HBOX,
117
G_IMPLEMENT_INTERFACE (GIMP_TYPE_PROGRESS,
118
gimp_statusbar_progress_iface_init))
120
#define parent_class gimp_statusbar_parent_class
131
124
gimp_statusbar_class_init (GimpStatusbarClass *klass)
133
GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
134
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
136
parent_class = g_type_class_peek_parent (klass);
138
object_class->destroy = gimp_statusbar_destroy;
140
gtk_widget_class_install_style_property (widget_class,
141
g_param_spec_enum ("shadow_type",
143
_("Style of bevel around the statusbar text"),
144
GTK_TYPE_SHADOW_TYPE,
126
GObjectClass *object_class = G_OBJECT_CLASS (klass);
127
GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
129
object_class->finalize = gimp_statusbar_finalize;
131
gtk_object_class->destroy = gimp_statusbar_destroy;
135
gimp_statusbar_progress_iface_init (GimpProgressInterface *iface)
137
iface->start = gimp_statusbar_progress_start;
138
iface->end = gimp_statusbar_progress_end;
139
iface->is_active = gimp_statusbar_progress_is_active;
140
iface->set_text = gimp_statusbar_progress_set_text;
141
iface->set_value = gimp_statusbar_progress_set_value;
142
iface->get_value = gimp_statusbar_progress_get_value;
143
iface->pulse = gimp_statusbar_progress_pulse;
144
iface->message = gimp_statusbar_progress_message;
150
148
gimp_statusbar_init (GimpStatusbar *statusbar)
152
150
GtkBox *box = GTK_BOX (statusbar);
155
151
GimpUnitStore *store;
156
GtkShadowType shadow_type;
157
gboolean has_focus_on_click;
160
box->homogeneous = FALSE;
162
statusbar->shell = NULL;
153
statusbar->shell = NULL;
154
statusbar->messages = NULL;
155
statusbar->context_ids = g_hash_table_new_full (g_str_hash, g_str_equal,
157
statusbar->seq_context_id = 1;
159
statusbar->temp_context_id =
160
gimp_statusbar_get_context_id (statusbar, "gimp-statusbar-temp");
163
162
statusbar->cursor_format_str[0] = '\0';
164
163
statusbar->length_format_str[0] = '\0';
165
165
statusbar->progress_active = FALSE;
167
gtk_box_set_spacing (box, 1);
169
gtk_widget_style_get (GTK_WIDGET (statusbar),
170
"shadow_type", &shadow_type,
173
statusbar->cursor_frame = gtk_frame_new (NULL);
174
gtk_frame_set_shadow_type (GTK_FRAME (statusbar->cursor_frame), shadow_type);
168
box->homogeneous = FALSE;
170
statusbar->cursor_frame = gtk_hbox_new (FALSE, 0);
175
171
gtk_box_pack_start (box, statusbar->cursor_frame, FALSE, FALSE, 0);
176
172
gtk_box_reorder_child (box, statusbar->cursor_frame, 0);
177
173
gtk_widget_show (statusbar->cursor_frame);
179
hbox = gtk_hbox_new (FALSE, 1);
180
gtk_container_add (GTK_CONTAINER (statusbar->cursor_frame), hbox);
181
gtk_widget_show (hbox);
183
175
statusbar->cursor_label = gtk_label_new ("0, 0");
184
176
gtk_misc_set_alignment (GTK_MISC (statusbar->cursor_label), 0.5, 0.5);
185
gtk_container_add (GTK_CONTAINER (hbox), statusbar->cursor_label);
177
gtk_container_add (GTK_CONTAINER (statusbar->cursor_frame),
178
statusbar->cursor_label);
186
179
gtk_widget_show (statusbar->cursor_label);
188
181
store = gimp_unit_store_new (2);
189
182
statusbar->unit_combo = gimp_unit_combo_box_new_with_model (store);
190
183
g_object_unref (store);
193
g_object_class_find_property (G_OBJECT_GET_CLASS (statusbar->unit_combo),
194
"focus-on-click") != NULL;
196
185
GTK_WIDGET_UNSET_FLAGS (statusbar->unit_combo, GTK_CAN_FOCUS);
197
if (has_focus_on_click)
198
g_object_set (statusbar->unit_combo, "focus-on-click", FALSE, NULL);
199
gtk_container_add (GTK_CONTAINER (hbox), statusbar->unit_combo);
186
g_object_set (statusbar->unit_combo, "focus-on-click", FALSE, NULL);
187
gtk_container_add (GTK_CONTAINER (statusbar->cursor_frame),
188
statusbar->unit_combo);
200
189
gtk_widget_show (statusbar->unit_combo);
202
191
g_signal_connect (statusbar->unit_combo, "changed",
203
192
G_CALLBACK (gimp_statusbar_unit_changed),
206
frame = gtk_frame_new (NULL);
207
gtk_frame_set_shadow_type (GTK_FRAME (frame), shadow_type);
208
gtk_box_pack_start (box, frame, FALSE, FALSE, 0);
209
gtk_widget_show (frame);
211
195
statusbar->scale_combo = gimp_scale_combo_box_new ();
212
196
GTK_WIDGET_UNSET_FLAGS (statusbar->scale_combo, GTK_CAN_FOCUS);
213
if (has_focus_on_click)
214
g_object_set (statusbar->scale_combo, "focus-on-click", FALSE, NULL);
215
gtk_container_add (GTK_CONTAINER (frame), statusbar->scale_combo);
197
g_object_set (statusbar->scale_combo, "focus-on-click", FALSE, NULL);
198
gtk_box_pack_start (box, statusbar->scale_combo, FALSE, FALSE, 0);
216
199
gtk_widget_show (statusbar->scale_combo);
218
201
g_signal_connect (statusbar->scale_combo, "changed",
222
205
statusbar->progressbar = gtk_progress_bar_new ();
206
gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (statusbar->progressbar),
207
PANGO_ELLIPSIZE_END);
208
g_object_set (statusbar->progressbar,
223
212
gtk_box_pack_start (box, statusbar->progressbar, TRUE, TRUE, 0);
224
213
gtk_widget_show (statusbar->progressbar);
226
GTK_PROGRESS_BAR (statusbar->progressbar)->progress.x_align = 0.0;
227
GTK_PROGRESS_BAR (statusbar->progressbar)->progress.y_align = 0.5;
215
g_signal_connect_after (statusbar->progressbar, "style-set",
216
G_CALLBACK (gimp_statusbar_progress_style_set),
218
g_signal_connect_after (statusbar->progressbar, "expose-event",
219
G_CALLBACK (gimp_statusbar_progress_expose),
229
222
statusbar->cancel_button = gtk_button_new_with_label (_("Cancel"));
230
223
gtk_widget_set_sensitive (statusbar->cancel_button, FALSE);
231
224
gtk_box_pack_start (box, statusbar->cancel_button, FALSE, FALSE, 0);
232
225
GTK_WIDGET_UNSET_FLAGS (statusbar->cancel_button, GTK_CAN_FOCUS);
233
gtk_widget_show (statusbar->cancel_button);
235
227
g_signal_connect (statusbar->cancel_button, "clicked",
236
228
G_CALLBACK (gimp_statusbar_progress_canceled),
239
/* Update the statusbar once to work around a canvas size problem:
241
* The first update of the statusbar used to queue a resize which
242
* in term caused the canvas to be resized. That made it shrink by
243
* one pixel in height resulting in the last row not being displayed.
244
* Shrink-wrapping the display used to fix this reliably. With the
245
* next call the resize doesn't seem to happen any longer.
248
gtk_progress_bar_set_text (GTK_PROGRESS_BAR (statusbar->progressbar),
251
statusbar->seq_context_id = 1;
252
statusbar->messages = NULL;
253
statusbar->keys = NULL;
257
gimp_statusbar_progress_iface_init (GimpProgressInterface *progress_iface)
259
progress_iface->start = gimp_statusbar_progress_start;
260
progress_iface->end = gimp_statusbar_progress_end;
261
progress_iface->is_active = gimp_statusbar_progress_is_active;
262
progress_iface->set_text = gimp_statusbar_progress_set_text;
263
progress_iface->set_value = gimp_statusbar_progress_set_value;
264
progress_iface->get_value = gimp_statusbar_progress_get_value;
268
gimp_statusbar_destroy (GtkObject *object)
233
gimp_statusbar_finalize (GObject *object)
270
235
GimpStatusbar *statusbar = GIMP_STATUSBAR (object);
273
for (list = statusbar->messages; list; list = list->next)
275
GimpStatusbarMsg *msg = list->data;
237
g_slist_foreach (statusbar->messages, (GFunc) gimp_statusbar_msg_free, NULL);
281
238
g_slist_free (statusbar->messages);
282
239
statusbar->messages = NULL;
284
for (list = statusbar->keys; list; list = list->next)
287
g_slist_free (statusbar->keys);
288
statusbar->keys = NULL;
241
g_hash_table_destroy (statusbar->context_ids);
242
statusbar->context_ids = NULL;
244
g_free (statusbar->temp_spaces);
245
statusbar->temp_spaces = NULL;
247
G_OBJECT_CLASS (parent_class)->finalize (object);
251
gimp_statusbar_destroy (GtkObject *object)
253
GimpStatusbar *statusbar = GIMP_STATUSBAR (object);
255
if (statusbar->temp_timeout_id)
257
g_source_remove (statusbar->temp_timeout_id);
258
statusbar->temp_timeout_id = 0;
290
261
GTK_OBJECT_CLASS (parent_class)->destroy (object);
476
555
const gchar *title,
478
557
const gchar *separator,
481
561
GimpDisplayShell *shell;
482
gchar buf[CURSOR_LEN];
484
563
g_return_if_fail (GIMP_IS_STATUSBAR (statusbar));
485
564
g_return_if_fail (title != NULL);
486
565
g_return_if_fail (separator != NULL);
488
571
shell = statusbar->shell;
490
573
if (shell->unit == GIMP_UNIT_PIXEL)
492
g_snprintf (buf, sizeof (buf), statusbar->cursor_format_str,
575
gimp_statusbar_push (statusbar, context,
576
statusbar->cursor_format_str,
498
583
else /* show real world units */
500
GimpImage *image = shell->gdisp->gimage;
585
GimpImage *image = shell->display->image;
501
586
gdouble unit_factor = _gimp_unit_get_factor (image->gimp,
504
g_snprintf (buf, sizeof (buf), statusbar->cursor_format_str,
506
x * unit_factor / image->xresolution,
508
y * unit_factor / image->yresolution);
589
gimp_statusbar_push (statusbar, context,
590
statusbar->cursor_format_str,
592
x * unit_factor / image->xresolution,
594
y * unit_factor / image->yresolution,
511
gimp_statusbar_push (statusbar, context, buf);
557
g_snprintf (buf, sizeof (buf), statusbar->length_format_str,
559
value * unit_factor / resolution);
648
gimp_statusbar_push (statusbar, context,
649
statusbar->length_format_str,
651
value * unit_factor / resolution,
562
gimp_statusbar_push (statusbar, context, buf);
566
657
gimp_statusbar_replace (GimpStatusbar *statusbar,
567
658
const gchar *context,
568
const gchar *message)
664
g_return_if_fail (GIMP_IS_STATUSBAR (statusbar));
665
g_return_if_fail (context != NULL);
666
g_return_if_fail (format != NULL);
668
va_start (args, format);
669
gimp_statusbar_replace_valist (statusbar, context, format, args);
674
gimp_statusbar_replace_valist (GimpStatusbar *statusbar,
675
const gchar *context,
570
679
GimpStatusbarMsg *msg;
571
681
guint context_id;
574
684
g_return_if_fail (GIMP_IS_STATUSBAR (statusbar));
575
g_return_if_fail (message != NULL);
685
g_return_if_fail (context != NULL);
686
g_return_if_fail (format != NULL);
577
if (! statusbar->messages)
579
gimp_statusbar_push (statusbar, context, message);
688
message = gimp_statusbar_vprintf (format, args);
583
690
context_id = gimp_statusbar_get_context_id (statusbar, context);
585
msg = statusbar->messages->data;
587
if (msg->context_id == context_id)
589
gimp_statusbar_pop (statusbar, context);
590
gimp_statusbar_push (statusbar, context, message);
595
692
for (list = statusbar->messages; list; list = g_slist_next (list))
597
694
msg = list->data;
633
737
if (msg->context_id == context_id)
635
739
statusbar->messages = g_slist_remove (statusbar->messages, msg);
740
gimp_statusbar_msg_free (msg);
746
gimp_statusbar_update (statusbar);
750
gimp_statusbar_push_temp (GimpStatusbar *statusbar,
751
const gchar *stock_id,
757
g_return_if_fail (GIMP_IS_STATUSBAR (statusbar));
758
g_return_if_fail (format != NULL);
760
va_start (args, format);
761
gimp_statusbar_push_temp_valist (statusbar, stock_id, format, args);
766
gimp_statusbar_push_temp_valist (GimpStatusbar *statusbar,
767
const gchar *stock_id,
771
GimpStatusbarMsg *msg = NULL;
774
g_return_if_fail (GIMP_IS_STATUSBAR (statusbar));
775
g_return_if_fail (format != NULL);
777
message = gimp_statusbar_vprintf (format, args);
779
if (statusbar->temp_timeout_id)
780
g_source_remove (statusbar->temp_timeout_id);
782
statusbar->temp_timeout_id =
783
g_timeout_add (MESSAGE_TIMEOUT,
784
(GSourceFunc) gimp_statusbar_temp_timeout, statusbar);
786
if (statusbar->messages)
788
msg = statusbar->messages->data;
790
if (msg->context_id == statusbar->temp_context_id)
792
if (strcmp (msg->text, message) == 0)
798
g_free (msg->stock_id);
799
msg->stock_id = g_strdup (stock_id);
636
801
g_free (msg->text);
804
gimp_statusbar_update (statusbar);
809
msg = g_new0 (GimpStatusbarMsg, 1);
811
msg->context_id = statusbar->temp_context_id;
812
msg->stock_id = g_strdup (stock_id);
815
statusbar->messages = g_slist_prepend (statusbar->messages, msg);
643
817
gimp_statusbar_update (statusbar);
647
gimp_statusbar_set_cursor (GimpStatusbar *statusbar,
821
gimp_statusbar_pop_temp (GimpStatusbar *statusbar)
823
g_return_if_fail (GIMP_IS_STATUSBAR (statusbar));
825
if (statusbar->temp_timeout_id)
827
g_source_remove (statusbar->temp_timeout_id);
828
statusbar->temp_timeout_id = 0;
831
if (statusbar->messages)
833
GimpStatusbarMsg *msg = statusbar->messages->data;
835
if (msg->context_id == statusbar->temp_context_id)
837
statusbar->messages = g_slist_remove (statusbar->messages, msg);
838
gimp_statusbar_msg_free (msg);
840
gimp_statusbar_update (statusbar);
846
gimp_statusbar_update_cursor (GimpStatusbar *statusbar,
651
850
GimpDisplayShell *shell;
652
851
GtkTreeModel *model;
699
898
gtk_widget_set_sensitive (statusbar->cursor_label, TRUE);
902
/* private functions */
905
gimp_statusbar_progress_style_set (GtkWidget *widget,
906
GtkStyle *prev_style,
907
GimpStatusbar *statusbar)
914
layout = gtk_widget_create_pango_layout (widget, " ");
915
pixbuf = gtk_widget_render_icon (widget, GIMP_STOCK_WARNING,
916
GTK_ICON_SIZE_MENU, NULL);
918
pango_layout_get_pixel_size (layout, &layout_width, NULL);
920
while (layout_width < gdk_pixbuf_get_width (pixbuf) + 4)
924
statusbar->temp_spaces = g_realloc (statusbar->temp_spaces, n_spaces + 1);
926
memset (statusbar->temp_spaces, ' ', n_spaces);
927
statusbar->temp_spaces[n_spaces] = '\0';
929
pango_layout_set_text (layout, statusbar->temp_spaces, -1);
930
pango_layout_get_pixel_size (layout, &layout_width, NULL);
933
g_object_unref (layout);
934
g_object_unref (pixbuf);
938
gimp_statusbar_progress_expose (GtkWidget *widget,
939
GdkEventExpose *event,
940
GimpStatusbar *statusbar)
943
const gchar *stock_id = NULL;
948
if (statusbar->messages)
950
GimpStatusbarMsg *msg = statusbar->messages->data;
952
stock_id = msg->stock_id;
958
pixbuf = gtk_widget_render_icon (widget, stock_id,
959
GTK_ICON_SIZE_MENU, NULL);
961
g_object_get (widget,
962
"text-xalign", &text_xalign,
963
"text-yalign", &text_yalign,
966
x = (widget->style->xthickness + 2);
967
y = ((widget->allocation.height - gdk_pixbuf_get_height (pixbuf)) / 2);
969
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
970
x += (widget->allocation.width - 2 * (widget->style->xthickness + 1) -
971
gdk_pixbuf_get_width (pixbuf));
973
gdk_draw_pixbuf (widget->window, widget->style->black_gc,
976
gdk_pixbuf_get_width (pixbuf),
977
gdk_pixbuf_get_height (pixbuf),
978
GDK_RGB_DITHER_NORMAL, 0, 0);
980
g_object_unref (pixbuf);
703
986
gimp_statusbar_shell_scaled (GimpDisplayShell *shell,
704
987
GimpStatusbar *statusbar)
706
989
static PangoLayout *layout = NULL;
708
GimpImage *image = shell->gdisp->gimage;
991
GimpImage *image = shell->display->image;
709
992
GtkTreeModel *model;
710
993
const gchar *text;
799
1082
gimp_statusbar_get_context_id (GimpStatusbar *statusbar,
800
1083
const gchar *context)
805
g_return_val_if_fail (GIMP_IS_STATUSBAR (statusbar), 0);
806
g_return_val_if_fail (context != NULL, 0);
808
/* we need to preserve namespaces on object datas */
809
string = g_strconcat ("gimp-status-bar-context:", context, NULL);
811
id = g_object_get_data (G_OBJECT (statusbar), string);
814
id = g_new (guint, 1);
815
*id = statusbar->seq_context_id++;
816
g_object_set_data_full (G_OBJECT (statusbar), string, id, g_free);
817
statusbar->keys = g_slist_prepend (statusbar->keys, string);
1085
guint id = GPOINTER_TO_UINT (g_hash_table_lookup (statusbar->context_ids,
1090
id = statusbar->seq_context_id++;
1092
g_hash_table_insert (statusbar->context_ids,
1093
g_strdup (context), GUINT_TO_POINTER (id));
1100
gimp_statusbar_temp_timeout (GimpStatusbar *statusbar)
1102
gimp_statusbar_pop_temp (statusbar);
1104
statusbar->temp_timeout_id = 0;
1110
gimp_statusbar_msg_free (GimpStatusbarMsg *msg)
1112
g_free (msg->stock_id);
1118
gimp_statusbar_vprintf (const gchar *format,
1124
message = g_strdup_vprintf (format, args);
1126
/* guard us from multi-line strings */
1127
newline = strchr (message, '\n');