1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpviewabledialog.c
5 * Copyright (C) 2000 Michael Natterer <mitch@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <gegl.h>
24 #include <gtk/gtk.h>
25
26 #include "libgimpwidgets/gimpwidgets.h"
27
28 #include "widgets-types.h"
29
30 #include "core/gimpcontext.h"
31 #include "core/gimpimage.h"
32 #include "core/gimpitem.h"
33
34 #include "gimpview.h"
35 #include "gimpviewabledialog.h"
36 #include "gimpviewrenderer.h"
37
38
39 enum
40 {
41 PROP_0,
42 PROP_VIEWABLE,
43 PROP_CONTEXT,
44 PROP_ICON_NAME,
45 PROP_DESC
46 };
47
48
49 static void gimp_viewable_dialog_dispose (GObject *object);
50 static void gimp_viewable_dialog_set_property (GObject *object,
51 guint property_id,
52 const GValue *value,
53 GParamSpec *pspec);
54 static void gimp_viewable_dialog_get_property (GObject *object,
55 guint property_id,
56 GValue *value,
57 GParamSpec *pspec);
58
59 static void gimp_viewable_dialog_name_changed (GimpObject *object,
60 GimpViewableDialog *dialog);
61 static void gimp_viewable_dialog_close (GimpViewableDialog *dialog);
62
63
G_DEFINE_TYPE(GimpViewableDialog,gimp_viewable_dialog,GIMP_TYPE_DIALOG)64 G_DEFINE_TYPE (GimpViewableDialog, gimp_viewable_dialog, GIMP_TYPE_DIALOG)
65
66 #define parent_class gimp_viewable_dialog_parent_class
67
68
69 static void
70 gimp_viewable_dialog_class_init (GimpViewableDialogClass *klass)
71 {
72 GObjectClass *object_class = G_OBJECT_CLASS (klass);
73
74 object_class->dispose = gimp_viewable_dialog_dispose;
75 object_class->get_property = gimp_viewable_dialog_get_property;
76 object_class->set_property = gimp_viewable_dialog_set_property;
77
78 g_object_class_install_property (object_class, PROP_VIEWABLE,
79 g_param_spec_object ("viewable", NULL, NULL,
80 GIMP_TYPE_VIEWABLE,
81 GIMP_PARAM_READWRITE));
82
83 g_object_class_install_property (object_class, PROP_CONTEXT,
84 g_param_spec_object ("context", NULL, NULL,
85 GIMP_TYPE_CONTEXT,
86 GIMP_PARAM_READWRITE |
87 G_PARAM_CONSTRUCT));
88
89 g_object_class_install_property (object_class, PROP_ICON_NAME,
90 g_param_spec_string ("icon-name", NULL, NULL,
91 NULL,
92 GIMP_PARAM_WRITABLE |
93 G_PARAM_CONSTRUCT));
94
95 g_object_class_install_property (object_class, PROP_DESC,
96 g_param_spec_string ("description", NULL, NULL,
97 NULL,
98 GIMP_PARAM_WRITABLE |
99 G_PARAM_CONSTRUCT));
100 }
101
102 static void
gimp_viewable_dialog_init(GimpViewableDialog * dialog)103 gimp_viewable_dialog_init (GimpViewableDialog *dialog)
104 {
105 GtkWidget *content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
106 GtkWidget *frame;
107 GtkWidget *hbox;
108 GtkWidget *vbox;
109
110 frame = gtk_frame_new (NULL);
111 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
112 gtk_box_pack_start (GTK_BOX (content_area), frame, FALSE, FALSE, 0);
113 gtk_widget_show (frame);
114
115 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
116 gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
117 gtk_container_add (GTK_CONTAINER (frame), hbox);
118 gtk_widget_show (hbox);
119
120 dialog->icon = gtk_image_new ();
121 gtk_misc_set_alignment (GTK_MISC (dialog->icon), 0.5, 0.0);
122 gtk_box_pack_start (GTK_BOX (hbox), dialog->icon, FALSE, FALSE, 0);
123 gtk_widget_show (dialog->icon);
124
125 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
126 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
127 gtk_widget_show (vbox);
128
129 dialog->desc_label = gtk_label_new (NULL);
130 gtk_label_set_xalign (GTK_LABEL (dialog->desc_label), 0.0);
131 gimp_label_set_attributes (GTK_LABEL (dialog->desc_label),
132 PANGO_ATTR_SCALE, PANGO_SCALE_LARGE,
133 PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
134 -1);
135 gtk_box_pack_start (GTK_BOX (vbox), dialog->desc_label, FALSE, FALSE, 0);
136 gtk_widget_show (dialog->desc_label);
137
138 dialog->viewable_label = g_object_new (GTK_TYPE_LABEL,
139 "xalign", 0.0,
140 "yalign", 0.5,
141 "ellipsize", PANGO_ELLIPSIZE_END,
142 NULL);
143 gimp_label_set_attributes (GTK_LABEL (dialog->viewable_label),
144 PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
145 -1);
146 gtk_box_pack_start (GTK_BOX (vbox), dialog->viewable_label, FALSE, FALSE, 0);
147 gtk_widget_show (dialog->viewable_label);
148 }
149
150 static void
gimp_viewable_dialog_dispose(GObject * object)151 gimp_viewable_dialog_dispose (GObject *object)
152 {
153 GimpViewableDialog *dialog = GIMP_VIEWABLE_DIALOG (object);
154
155 if (dialog->view)
156 gimp_viewable_dialog_set_viewable (dialog, NULL, NULL);
157
158 G_OBJECT_CLASS (parent_class)->dispose (object);
159 }
160
161 static void
gimp_viewable_dialog_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)162 gimp_viewable_dialog_set_property (GObject *object,
163 guint property_id,
164 const GValue *value,
165 GParamSpec *pspec)
166 {
167 GimpViewableDialog *dialog = GIMP_VIEWABLE_DIALOG (object);
168
169 switch (property_id)
170 {
171 case PROP_VIEWABLE:
172 gimp_viewable_dialog_set_viewable (dialog,
173 g_value_get_object (value),
174 dialog->context);
175 break;
176
177 case PROP_CONTEXT:
178 gimp_viewable_dialog_set_viewable (dialog,
179 dialog->view ?
180 GIMP_VIEW (dialog->view)->viewable :
181 NULL,
182 g_value_get_object (value));
183 break;
184
185 case PROP_ICON_NAME:
186 gtk_image_set_from_icon_name (GTK_IMAGE (dialog->icon),
187 g_value_get_string (value),
188 GTK_ICON_SIZE_LARGE_TOOLBAR);
189 break;
190
191 case PROP_DESC:
192 gtk_label_set_text (GTK_LABEL (dialog->desc_label),
193 g_value_get_string (value));
194 break;
195
196 default:
197 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
198 break;
199 }
200 }
201
202 static void
gimp_viewable_dialog_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)203 gimp_viewable_dialog_get_property (GObject *object,
204 guint property_id,
205 GValue *value,
206 GParamSpec *pspec)
207 {
208 GimpViewableDialog *dialog = GIMP_VIEWABLE_DIALOG (object);
209
210 switch (property_id)
211 {
212 case PROP_VIEWABLE:
213 g_value_set_object (value,
214 dialog->view ?
215 GIMP_VIEW (dialog->view)->viewable : NULL);
216 break;
217
218 case PROP_CONTEXT:
219 g_value_set_object (value, dialog->context);
220 break;
221
222 default:
223 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
224 break;
225 }
226 }
227
228 GtkWidget *
gimp_viewable_dialog_new(GimpViewable * viewable,GimpContext * context,const gchar * title,const gchar * role,const gchar * icon_name,const gchar * desc,GtkWidget * parent,GimpHelpFunc help_func,const gchar * help_id,...)229 gimp_viewable_dialog_new (GimpViewable *viewable,
230 GimpContext *context,
231 const gchar *title,
232 const gchar *role,
233 const gchar *icon_name,
234 const gchar *desc,
235 GtkWidget *parent,
236 GimpHelpFunc help_func,
237 const gchar *help_id,
238 ...)
239 {
240 GimpViewableDialog *dialog;
241 va_list args;
242
243 g_return_val_if_fail (viewable == NULL || GIMP_IS_VIEWABLE (viewable), NULL);
244 g_return_val_if_fail (context == NULL || GIMP_IS_CONTEXT (context), NULL);
245 g_return_val_if_fail (title != NULL, NULL);
246 g_return_val_if_fail (role != NULL, NULL);
247 g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), NULL);
248
249 if (! viewable)
250 g_warning ("Use of GimpViewableDialog with a NULL viewable is deprecated!");
251
252 dialog = g_object_new (GIMP_TYPE_VIEWABLE_DIALOG,
253 "viewable", viewable,
254 "context", context,
255 "title", title,
256 "role", role,
257 "help-func", help_func,
258 "help-id", help_id,
259 "icon-name", icon_name,
260 "description", desc,
261 "parent", parent,
262 NULL);
263
264 va_start (args, help_id);
265 gimp_dialog_add_buttons_valist (GIMP_DIALOG (dialog), args);
266 va_end (args);
267
268 return GTK_WIDGET (dialog);
269 }
270
271 void
gimp_viewable_dialog_set_viewable(GimpViewableDialog * dialog,GimpViewable * viewable,GimpContext * context)272 gimp_viewable_dialog_set_viewable (GimpViewableDialog *dialog,
273 GimpViewable *viewable,
274 GimpContext *context)
275 {
276 g_return_if_fail (GIMP_IS_VIEWABLE_DIALOG (dialog));
277 g_return_if_fail (viewable == NULL || GIMP_IS_VIEWABLE (viewable));
278 g_return_if_fail (context == NULL || GIMP_IS_CONTEXT (context));
279
280 dialog->context = context;
281
282 if (dialog->view)
283 {
284 GimpViewable *old_viewable = GIMP_VIEW (dialog->view)->viewable;
285
286 if (viewable == old_viewable)
287 {
288 gimp_view_renderer_set_context (GIMP_VIEW (dialog->view)->renderer,
289 context);
290 return;
291 }
292
293 gtk_widget_destroy (dialog->view);
294
295 if (old_viewable)
296 {
297 g_signal_handlers_disconnect_by_func (old_viewable,
298 gimp_viewable_dialog_name_changed,
299 dialog);
300
301 g_signal_handlers_disconnect_by_func (old_viewable,
302 gimp_viewable_dialog_close,
303 dialog);
304 }
305 }
306
307 if (viewable)
308 {
309 GtkWidget *box;
310
311 g_signal_connect_object (viewable,
312 GIMP_VIEWABLE_GET_CLASS (viewable)->name_changed_signal,
313 G_CALLBACK (gimp_viewable_dialog_name_changed),
314 dialog,
315 0);
316
317 box = gtk_widget_get_parent (dialog->icon);
318
319 dialog->view = gimp_view_new (context, viewable, 32, 1, TRUE);
320 gtk_box_pack_end (GTK_BOX (box), dialog->view, FALSE, FALSE, 2);
321 gtk_widget_show (dialog->view);
322
323 g_object_add_weak_pointer (G_OBJECT (dialog->view),
324 (gpointer) &dialog->view);
325
326 gimp_viewable_dialog_name_changed (GIMP_OBJECT (viewable), dialog);
327
328 if (GIMP_IS_ITEM (viewable))
329 {
330 g_signal_connect_object (viewable, "removed",
331 G_CALLBACK (gimp_viewable_dialog_close),
332 dialog,
333 G_CONNECT_SWAPPED);
334 }
335 else
336 {
337 g_signal_connect_object (viewable, "disconnect",
338 G_CALLBACK (gimp_viewable_dialog_close),
339 dialog,
340 G_CONNECT_SWAPPED);
341 }
342 }
343 }
344
345
346 /* private functions */
347
348 static void
gimp_viewable_dialog_name_changed(GimpObject * object,GimpViewableDialog * dialog)349 gimp_viewable_dialog_name_changed (GimpObject *object,
350 GimpViewableDialog *dialog)
351 {
352 gchar *name;
353
354 name = gimp_viewable_get_description (GIMP_VIEWABLE (object), NULL);
355
356 if (GIMP_IS_ITEM (object))
357 {
358 GimpImage *image = gimp_item_get_image (GIMP_ITEM (object));
359 gchar *tmp;
360
361 tmp = name;
362 name = g_strdup_printf ("%s-%d (%s)",
363 tmp,
364 gimp_item_get_ID (GIMP_ITEM (object)),
365 gimp_image_get_display_name (image));
366 g_free (tmp);
367 }
368
369 gtk_label_set_text (GTK_LABEL (dialog->viewable_label), name);
370 g_free (name);
371 }
372
373 static void
gimp_viewable_dialog_close(GimpViewableDialog * dialog)374 gimp_viewable_dialog_close (GimpViewableDialog *dialog)
375 {
376 g_signal_emit_by_name (dialog, "close");
377 }
378