1 /*
2 * e-html-editor-image-dialog.h
3 *
4 * Copyright (C) 2012 Dan Vrátil <dvratil@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) version 3.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with the program; if not, see <http://www.gnu.org/licenses/>
18 *
19 */
20
21 #include "evolution-config.h"
22
23 #include <stdlib.h>
24 #include <glib/gi18n-lib.h>
25
26 #include "e-image-chooser-dialog.h"
27 #include "e-misc-utils.h"
28
29 #include "e-html-editor-image-dialog.h"
30
31 #define E_HTML_EDITOR_IMAGE_DIALOG_GET_PRIVATE(obj) \
32 (G_TYPE_INSTANCE_GET_PRIVATE \
33 ((obj), E_TYPE_HTML_EDITOR_IMAGE_DIALOG, EHTMLEditorImageDialogPrivate))
34
35 typedef enum {
36 E_SYNC_ASPECT_RATIO_BY_WIDTH,
37 E_SYNC_ASPECT_RATIO_BY_HEIGHT
38 } ESyncAspectRatio;
39
40 struct _EHTMLEditorImageDialogPrivate {
41 GtkWidget *file_chooser;
42 GtkWidget *description_edit;
43
44 GtkWidget *width_edit;
45 GtkWidget *height_edit;
46 GtkWidget *size_units;
47 GtkWidget *alignment;
48
49 GtkWidget *x_padding_edit;
50 GtkWidget *y_padding_edit;
51 GtkWidget *border_edit;
52
53 GtkWidget *url_edit;
54 GtkWidget *test_url_button;
55
56 gboolean preserve_aspect_ratio;
57 };
58
59 G_DEFINE_TYPE (
60 EHTMLEditorImageDialog,
61 e_html_editor_image_dialog,
62 E_TYPE_HTML_EDITOR_DIALOG);
63
64 static void
html_editor_image_dialog_set_src(EHTMLEditorImageDialog * dialog)65 html_editor_image_dialog_set_src (EHTMLEditorImageDialog *dialog)
66 {
67 EHTMLEditor *editor;
68 EContentEditor *cnt_editor;
69 gchar *uri;
70
71 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
72 return;
73
74 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
75 cnt_editor = e_html_editor_get_content_editor (editor);
76
77 uri = gtk_file_chooser_get_uri (
78 GTK_FILE_CHOOSER (dialog->priv->file_chooser));
79
80 e_content_editor_image_set_src (cnt_editor, uri);
81
82 g_free (uri);
83 }
84
85 static void
html_editor_image_dialog_set_alt(EHTMLEditorImageDialog * dialog)86 html_editor_image_dialog_set_alt (EHTMLEditorImageDialog *dialog)
87 {
88 EHTMLEditor *editor;
89 EContentEditor *cnt_editor;
90 const gchar *value;
91
92 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
93 return;
94
95 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
96 cnt_editor = e_html_editor_get_content_editor (editor);
97
98 value = gtk_entry_get_text (GTK_ENTRY (dialog->priv->description_edit));
99
100 e_content_editor_image_set_alt (cnt_editor, value);
101 }
102
103 static void
maybe_sync_aspect_ration(EHTMLEditorImageDialog * dialog,ESyncAspectRatio kind)104 maybe_sync_aspect_ration (EHTMLEditorImageDialog *dialog,
105 ESyncAspectRatio kind)
106 {
107 EHTMLEditor *editor;
108 EContentEditor *cnt_editor;
109 gint32 natural_width, natural_height;
110 gint width = -1, height = -1, requested;
111
112 if (!dialog->priv->preserve_aspect_ratio)
113 return;
114
115 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
116 cnt_editor = e_html_editor_get_content_editor (editor);
117
118 natural_width = e_content_editor_image_get_natural_width (cnt_editor);
119 natural_height = e_content_editor_image_get_natural_height (cnt_editor);
120
121 requested = kind == E_SYNC_ASPECT_RATIO_BY_WIDTH ?
122 gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->priv->width_edit)) :
123 gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->priv->height_edit));
124
125 switch (gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->priv->size_units))) {
126 case 0: /* px */
127 if (kind == E_SYNC_ASPECT_RATIO_BY_WIDTH) {
128 if (!natural_width)
129 height = 0;
130 else
131 height = ((gdouble) natural_height) * requested / natural_width;
132 } else { /* E_SYNC_ASPECT_RATIO_BY_HEIGHT */
133 if (!natural_height)
134 width = 0;
135 else
136 width = ((gdouble) natural_width) * requested / natural_height;
137 }
138 break;
139
140 case 1: /* percent */
141 if (kind == E_SYNC_ASPECT_RATIO_BY_WIDTH)
142 height = requested;
143 else /* E_SYNC_ASPECT_RATIO_BY_HEIGHT */
144 width = requested;
145 break;
146
147 case 2: /* follow */
148 /* ignore */
149 break;
150 }
151
152 /* To avoid recursion on set */
153 dialog->priv->preserve_aspect_ratio = FALSE;
154
155 if (width != -1) {
156 if (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->priv->width_edit)) == width)
157 g_signal_emit_by_name (dialog->priv->width_edit, "value-changed", NULL);
158 else
159 gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->width_edit), width);
160 }
161
162 if (height != -1) {
163 if (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->priv->height_edit)) == height)
164 g_signal_emit_by_name (dialog->priv->height_edit, "value-changed", NULL);
165 else
166 gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->height_edit), height);
167 }
168
169 dialog->priv->preserve_aspect_ratio = TRUE;
170 }
171
172 static void
html_editor_image_dialog_set_width(EHTMLEditorImageDialog * dialog)173 html_editor_image_dialog_set_width (EHTMLEditorImageDialog *dialog)
174 {
175 EHTMLEditor *editor;
176 EContentEditor *cnt_editor;
177 gint requested;
178 gint32 natural = 0;
179 gint width;
180
181 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
182 return;
183
184 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
185 cnt_editor = e_html_editor_get_content_editor (editor);
186
187 natural = e_content_editor_image_get_natural_width (cnt_editor);
188
189 requested = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->priv->width_edit));
190
191 switch (gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->priv->size_units))) {
192 case 0: /* px */
193 width = requested;
194 break;
195
196 case 1: /* percent */
197 if (requested)
198 width = natural * requested / 100.0;
199 else
200 width = natural;
201 break;
202
203 case 2: /* follow */
204 width = natural;
205 break;
206
207 default:
208 return;
209 }
210
211 e_content_editor_image_set_width (cnt_editor, width);
212
213 maybe_sync_aspect_ration (dialog, E_SYNC_ASPECT_RATIO_BY_WIDTH);
214 }
215
216 static void
html_editor_image_dialog_set_height(EHTMLEditorImageDialog * dialog)217 html_editor_image_dialog_set_height (EHTMLEditorImageDialog *dialog)
218 {
219 EHTMLEditor *editor;
220 EContentEditor *cnt_editor;
221 gint requested;
222 gint32 natural = 0;
223 gint height;
224
225 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
226 return;
227
228 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
229 cnt_editor = e_html_editor_get_content_editor (editor);
230
231 natural = e_content_editor_image_get_natural_height (cnt_editor);
232
233 requested = gtk_spin_button_get_value_as_int (
234 GTK_SPIN_BUTTON (dialog->priv->height_edit));
235
236 switch (gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->priv->size_units))) {
237 case 0: /* px */
238 height = requested;
239 break;
240
241 case 1: /* percent */
242 if (requested)
243 height = natural * requested / 100.0;
244 else
245 height = natural;
246 break;
247
248 case 2: /* follow */
249 height = natural;
250 break;
251
252 default:
253 return;
254 }
255
256 e_content_editor_image_set_height (cnt_editor, height);
257
258 maybe_sync_aspect_ration (dialog, E_SYNC_ASPECT_RATIO_BY_HEIGHT);
259 }
260
261 static void
html_editor_image_dialog_set_size_units(EHTMLEditorImageDialog * dialog)262 html_editor_image_dialog_set_size_units (EHTMLEditorImageDialog *dialog)
263 {
264 EHTMLEditor *editor;
265 EContentEditor *cnt_editor;
266 gint requested_width, requested_height;
267 gint32 natural_width, natural_height;
268 gint width = -1, height = -1;
269
270 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
271 return;
272
273 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
274 cnt_editor = e_html_editor_get_content_editor (editor);
275
276 natural_width = e_content_editor_image_get_natural_width (cnt_editor);
277 natural_height = e_content_editor_image_get_natural_height (cnt_editor);
278
279 requested_width = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->priv->width_edit));
280 requested_height = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->priv->height_edit));
281
282 switch (gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->priv->size_units))) {
283 case 0: /* px */
284 if (gtk_widget_is_sensitive (dialog->priv->width_edit)) {
285 width = requested_width * natural_width * 0.01;
286 height = requested_height * natural_height * 0.01;
287 } else {
288 width = natural_width;
289 height = natural_height;
290 }
291 gtk_widget_set_sensitive (dialog->priv->width_edit, TRUE);
292 gtk_widget_set_sensitive (dialog->priv->height_edit, TRUE);
293 break;
294
295 case 1: /* percent */
296 if (natural_width && gtk_widget_is_sensitive (dialog->priv->width_edit)) {
297 width = (((gdouble) requested_width) / natural_width) * 100;
298 } else {
299 width = 100;
300 }
301 if (natural_height && gtk_widget_is_sensitive (dialog->priv->height_edit)) {
302 height = (((gdouble) requested_height) / natural_height) * 100;
303 } else {
304 height = 100;
305 }
306 gtk_widget_set_sensitive (dialog->priv->width_edit, TRUE);
307 gtk_widget_set_sensitive (dialog->priv->height_edit, TRUE);
308 break;
309
310 case 2: /* follow */
311 gtk_widget_set_sensitive (dialog->priv->width_edit, FALSE);
312 gtk_widget_set_sensitive (dialog->priv->height_edit, FALSE);
313 break;
314 }
315
316 e_content_editor_image_set_width_follow (cnt_editor, !gtk_widget_get_sensitive (dialog->priv->width_edit));
317 e_content_editor_image_set_height_follow (cnt_editor, !gtk_widget_get_sensitive (dialog->priv->height_edit));
318
319 if (width != -1)
320 gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->width_edit), width);
321 if (height != -1)
322 gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->height_edit), height);
323 }
324
325 static void
html_editor_image_dialog_set_alignment(EHTMLEditorImageDialog * dialog)326 html_editor_image_dialog_set_alignment (EHTMLEditorImageDialog *dialog)
327 {
328 EHTMLEditor *editor;
329 EContentEditor *cnt_editor;
330 const gchar *value;
331
332 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
333 return;
334
335 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
336 cnt_editor = e_html_editor_get_content_editor (editor);
337
338 value = gtk_combo_box_get_active_id (GTK_COMBO_BOX (dialog->priv->alignment));
339 e_content_editor_image_set_align (cnt_editor, value);
340 }
341
342 static void
html_editor_image_dialog_set_x_padding(EHTMLEditorImageDialog * dialog)343 html_editor_image_dialog_set_x_padding (EHTMLEditorImageDialog *dialog)
344 {
345 EHTMLEditor *editor;
346 EContentEditor *cnt_editor;
347 gint value;
348
349 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
350 return;
351
352 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
353 cnt_editor = e_html_editor_get_content_editor (editor);
354
355 value = gtk_spin_button_get_value_as_int (
356 GTK_SPIN_BUTTON (dialog->priv->x_padding_edit));
357 e_content_editor_image_set_hspace (cnt_editor, value);
358 }
359
360 static void
html_editor_image_dialog_set_y_padding(EHTMLEditorImageDialog * dialog)361 html_editor_image_dialog_set_y_padding (EHTMLEditorImageDialog *dialog)
362 {
363 EHTMLEditor *editor;
364 EContentEditor *cnt_editor;
365 gint value;
366
367 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
368 return;
369
370 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
371 cnt_editor = e_html_editor_get_content_editor (editor);
372
373 value = gtk_spin_button_get_value_as_int (
374 GTK_SPIN_BUTTON (dialog->priv->y_padding_edit));
375 e_content_editor_image_set_vspace (cnt_editor, value);
376 }
377
378 static void
html_editor_image_dialog_set_border(EHTMLEditorImageDialog * dialog)379 html_editor_image_dialog_set_border (EHTMLEditorImageDialog *dialog)
380 {
381 EHTMLEditor *editor;
382 EContentEditor *cnt_editor;
383 gint value;
384
385 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
386 return;
387
388 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
389 cnt_editor = e_html_editor_get_content_editor (editor);
390
391 value = gtk_spin_button_get_value_as_int (
392 GTK_SPIN_BUTTON (dialog->priv->border_edit));
393
394 e_content_editor_image_set_border (cnt_editor, value);
395 }
396
397 static void
html_editor_image_dialog_set_url(EHTMLEditorImageDialog * dialog)398 html_editor_image_dialog_set_url (EHTMLEditorImageDialog *dialog)
399 {
400 EHTMLEditor *editor;
401 EContentEditor *cnt_editor;
402 const gchar *value;
403
404 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
405 return;
406
407 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
408 cnt_editor = e_html_editor_get_content_editor (editor);
409
410 value = gtk_entry_get_text (GTK_ENTRY (dialog->priv->url_edit));
411
412 e_content_editor_image_set_url (cnt_editor, value);
413 }
414
415 static void
html_editor_image_dialog_test_url(EHTMLEditorImageDialog * dialog)416 html_editor_image_dialog_test_url (EHTMLEditorImageDialog *dialog)
417 {
418 e_show_uri (
419 GTK_WINDOW (dialog),
420 gtk_entry_get_text (GTK_ENTRY (dialog->priv->url_edit)));
421 }
422
423 static void
html_editor_image_dialog_show(GtkWidget * widget)424 html_editor_image_dialog_show (GtkWidget *widget)
425 {
426 EHTMLEditor *editor;
427 EHTMLEditorImageDialog *dialog;
428 EContentEditor *cnt_editor;
429 gchar *value;
430
431 dialog = E_HTML_EDITOR_IMAGE_DIALOG (widget);
432 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
433 cnt_editor = e_html_editor_get_content_editor (editor);
434
435 e_content_editor_on_dialog_open (cnt_editor, E_CONTENT_EDITOR_DIALOG_IMAGE);
436
437 value = e_content_editor_image_get_src (cnt_editor);
438 if (value && *value) {
439 gtk_file_chooser_set_uri (
440 GTK_FILE_CHOOSER (dialog->priv->file_chooser), value);
441 gtk_widget_set_sensitive (
442 GTK_WIDGET (dialog->priv->file_chooser), TRUE);
443 } else {
444 gtk_file_chooser_set_uri (
445 GTK_FILE_CHOOSER (dialog->priv->file_chooser), "");
446 gtk_widget_set_sensitive (
447 GTK_WIDGET (dialog->priv->file_chooser), FALSE);
448 }
449 g_free (value);
450
451 value = e_content_editor_image_get_alt (cnt_editor);
452 gtk_entry_set_text (
453 GTK_ENTRY (dialog->priv->description_edit), value ? value : "");
454 g_free (value);
455
456 gtk_spin_button_set_value (
457 GTK_SPIN_BUTTON (dialog->priv->width_edit),
458 e_content_editor_image_get_width (cnt_editor));
459
460 gtk_spin_button_set_value (
461 GTK_SPIN_BUTTON (dialog->priv->height_edit),
462 e_content_editor_image_get_height (cnt_editor));
463
464 gtk_combo_box_set_active_id (
465 GTK_COMBO_BOX (dialog->priv->size_units), "units-px");
466
467 gtk_spin_button_set_value (
468 GTK_SPIN_BUTTON (dialog->priv->border_edit),
469 e_content_editor_image_get_border (cnt_editor));
470
471 value = e_content_editor_image_get_align (cnt_editor);
472 gtk_combo_box_set_active_id (
473 GTK_COMBO_BOX (dialog->priv->alignment),
474 (value && *value) ? value : "bottom");
475 g_free (value);
476
477 gtk_spin_button_set_value (
478 GTK_SPIN_BUTTON (dialog->priv->y_padding_edit),
479 e_content_editor_image_get_hspace (cnt_editor));
480
481 gtk_spin_button_set_value (
482 GTK_SPIN_BUTTON (dialog->priv->y_padding_edit),
483 e_content_editor_image_get_vspace (cnt_editor));
484
485 value = e_content_editor_image_get_url (cnt_editor);
486 if (value && *value)
487 gtk_entry_set_text (GTK_ENTRY (dialog->priv->url_edit), value);
488 g_free (value);
489
490 /* Chain up to parent implementation */
491 GTK_WIDGET_CLASS (e_html_editor_image_dialog_parent_class)->show (widget);
492 }
493
494 static void
aspect_ration_clicked_cb(GtkButton * button,gpointer user_data)495 aspect_ration_clicked_cb (GtkButton *button,
496 gpointer user_data)
497 {
498 EHTMLEditorImageDialog *dialog = user_data;
499 const gchar *icon_name;
500
501 dialog->priv->preserve_aspect_ratio = !dialog->priv->preserve_aspect_ratio;
502
503 if (dialog->priv->preserve_aspect_ratio)
504 icon_name = "aspect-ratio-lock";
505 else
506 icon_name = "aspect-ratio-unlock";
507
508 gtk_button_set_image (button, gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON));
509
510 maybe_sync_aspect_ration (dialog, E_SYNC_ASPECT_RATIO_BY_WIDTH);
511 }
512
513 static void
html_editor_image_dialog_hide(GtkWidget * widget)514 html_editor_image_dialog_hide (GtkWidget *widget)
515 {
516 EHTMLEditor *editor;
517 EHTMLEditorImageDialog *dialog;
518 EContentEditor *cnt_editor;
519
520 dialog = E_HTML_EDITOR_IMAGE_DIALOG (widget);
521 editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
522 cnt_editor = e_html_editor_get_content_editor (editor);
523
524 e_content_editor_on_dialog_close (cnt_editor, E_CONTENT_EDITOR_DIALOG_IMAGE);
525
526 GTK_WIDGET_CLASS (e_html_editor_image_dialog_parent_class)->hide (widget);
527 }
528
529 static void
e_html_editor_image_dialog_class_init(EHTMLEditorImageDialogClass * class)530 e_html_editor_image_dialog_class_init (EHTMLEditorImageDialogClass *class)
531 {
532 GtkWidgetClass *widget_class;
533
534 g_type_class_add_private (class, sizeof (EHTMLEditorImageDialogPrivate));
535
536 widget_class = GTK_WIDGET_CLASS (class);
537 widget_class->show = html_editor_image_dialog_show;
538 widget_class->hide = html_editor_image_dialog_hide;
539 }
540
541 static void
e_html_editor_image_dialog_init(EHTMLEditorImageDialog * dialog)542 e_html_editor_image_dialog_init (EHTMLEditorImageDialog *dialog)
543 {
544 GtkGrid *main_layout, *grid;
545 GtkWidget *widget;
546 GtkFileFilter *file_filter;
547
548 dialog->priv = E_HTML_EDITOR_IMAGE_DIALOG_GET_PRIVATE (dialog);
549
550 main_layout = e_html_editor_dialog_get_container (E_HTML_EDITOR_DIALOG (dialog));
551
552 /* == General == */
553 widget = gtk_label_new ("");
554 gtk_label_set_markup (GTK_LABEL (widget), _("<b>General</b>"));
555 gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
556 gtk_grid_attach (main_layout, widget, 0, 0, 1, 1);
557
558 grid = GTK_GRID (gtk_grid_new ());
559 gtk_grid_set_row_spacing (grid, 5);
560 gtk_grid_set_column_spacing (grid, 5);
561 gtk_grid_attach (main_layout, GTK_WIDGET (grid), 0, 1, 1, 1);
562 gtk_widget_set_margin_left (GTK_WIDGET (grid), 10);
563
564 file_filter = gtk_file_filter_new ();
565 gtk_file_filter_set_name (file_filter, _("Images"));
566 gtk_file_filter_add_mime_type (file_filter, "image/*");
567
568 /* Source */
569 if (e_util_is_running_flatpak ()) {
570 widget = gtk_file_chooser_button_new (_("Choose Background Image"), GTK_FILE_CHOOSER_ACTION_OPEN);
571 } else {
572 widget = e_image_chooser_dialog_new (
573 _("Choose Background Image"),
574 GTK_WINDOW (dialog));
575 gtk_file_chooser_set_action (
576 GTK_FILE_CHOOSER (widget), GTK_FILE_CHOOSER_ACTION_OPEN);
577
578 widget = gtk_file_chooser_button_new_with_dialog (widget);
579 }
580
581 gtk_widget_set_hexpand (widget, TRUE);
582 gtk_grid_attach (grid, widget, 1, 0, 1, 1);
583 g_signal_connect_swapped (
584 widget, "file-set",
585 G_CALLBACK (html_editor_image_dialog_set_src), dialog);
586 dialog->priv->file_chooser = widget;
587
588 widget = gtk_label_new_with_mnemonic (_("_Source:"));
589 gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT);
590 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->file_chooser);
591 gtk_grid_attach (grid, widget, 0, 0, 1, 1);
592
593 /* Description */
594 widget = gtk_entry_new ();
595 gtk_widget_set_hexpand (widget, TRUE);
596 gtk_grid_attach (grid, widget, 1, 1, 1, 1);
597 g_signal_connect_swapped (
598 widget, "notify::text",
599 G_CALLBACK (html_editor_image_dialog_set_alt), dialog);
600 dialog->priv->description_edit = widget;
601
602 widget = gtk_label_new_with_mnemonic (_("_Description:"));
603 gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT);
604 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->description_edit);
605 gtk_grid_attach (grid, widget, 0, 1, 1, 1);
606
607 /* == Layout == */
608 widget = gtk_label_new ("");
609 gtk_label_set_markup (GTK_LABEL (widget), _("<b>Layout</b>"));
610 gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
611 gtk_grid_attach (main_layout, widget, 0, 2, 1, 1);
612
613 grid = GTK_GRID (gtk_grid_new ());
614 gtk_grid_set_row_spacing (grid, 5);
615 gtk_grid_set_column_spacing (grid, 5);
616 gtk_grid_attach (main_layout, GTK_WIDGET (grid), 0, 3, 1, 1);
617 gtk_widget_set_margin_left (GTK_WIDGET (grid), 10);
618
619 /* Width */
620 widget = gtk_spin_button_new_with_range (1, G_MAXUINT, 1);
621 gtk_grid_attach (grid, widget, 1, 0, 1, 1);
622 g_signal_connect_swapped (
623 widget, "value-changed",
624 G_CALLBACK (html_editor_image_dialog_set_width), dialog);
625 dialog->priv->width_edit = widget;
626
627 widget = gtk_label_new_with_mnemonic (_("_Width:"));
628 gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT);
629 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->width_edit);
630 gtk_grid_attach (grid, widget, 0, 0, 1, 1);
631
632 /* Height */
633 widget = gtk_spin_button_new_with_range (1, G_MAXUINT, 1);
634 gtk_grid_attach (grid, widget, 1, 1, 1, 1);
635 g_signal_connect_swapped (
636 widget, "value-changed",
637 G_CALLBACK (html_editor_image_dialog_set_height), dialog);
638 dialog->priv->height_edit = widget;
639
640 widget = gtk_label_new_with_mnemonic (_("_Height:"));
641 gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT);
642 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->height_edit);
643 gtk_grid_attach (grid, widget, 0, 1, 1, 1);
644
645 widget = gtk_combo_box_text_new ();
646 gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (widget), "units-px", "px");
647 gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (widget), "units-percent", "%");
648 gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (widget), "units-follow", "follow");
649 gtk_combo_box_set_active_id (GTK_COMBO_BOX (widget), "units-px");
650 gtk_grid_attach (grid, widget, 2, 1, 1, 1);
651 g_signal_connect_swapped (
652 widget, "changed",
653 G_CALLBACK (html_editor_image_dialog_set_size_units), dialog);
654 dialog->priv->size_units = widget;
655
656 widget = gtk_button_new ();
657 gtk_button_set_always_show_image (GTK_BUTTON (widget), TRUE);
658 gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new_from_icon_name ("aspect-ratio-lock", GTK_ICON_SIZE_BUTTON));
659 gtk_widget_set_tooltip_text (widget, _("Preserve aspect ratio"));
660 gtk_grid_attach (grid, widget, 3, 0, 1, 2);
661 dialog->priv->preserve_aspect_ratio = TRUE;
662
663 g_signal_connect_object (widget, "clicked",
664 G_CALLBACK (aspect_ration_clicked_cb), dialog, 0);
665
666 /* Alignment */
667 widget = gtk_combo_box_text_new ();
668 gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (widget), "top", _("Top"));
669 gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (widget), "middle", _("Middle"));
670 gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (widget), "bottom", _("Bottom"));
671 gtk_combo_box_set_active_id (GTK_COMBO_BOX (widget), "bottom");
672 gtk_grid_attach (grid, widget, 1, 2, 1, 1);
673 g_signal_connect_swapped (
674 widget, "changed",
675 G_CALLBACK (html_editor_image_dialog_set_alignment), dialog);
676 dialog->priv->alignment = widget;
677
678 widget = gtk_label_new_with_mnemonic (_("_Alignment"));
679 gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT);
680 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->alignment);
681 gtk_grid_attach (grid, widget, 0, 2, 1, 1);
682
683 /* X Padding */
684 widget = gtk_spin_button_new_with_range (0, G_MAXUINT, 1);
685 gtk_grid_attach (grid, widget, 6, 0, 1, 1);
686 g_signal_connect_swapped (
687 widget, "value-changed",
688 G_CALLBACK (html_editor_image_dialog_set_x_padding), dialog);
689 dialog->priv->x_padding_edit = widget;
690
691 widget = gtk_label_new_with_mnemonic (_("_X-Padding:"));
692 gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT);
693 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->x_padding_edit);
694 gtk_grid_attach (grid, widget, 5, 0, 1, 1);
695
696 widget = gtk_label_new ("px");
697 gtk_grid_attach (grid, widget, 7, 0, 1, 1);
698
699 /* Y Padding */
700 widget = gtk_spin_button_new_with_range (0, G_MAXUINT, 1);
701 gtk_grid_attach (grid, widget, 6, 1, 1, 1);
702 g_signal_connect_swapped (
703 widget, "value-changed",
704 G_CALLBACK (html_editor_image_dialog_set_y_padding), dialog);
705 dialog->priv->y_padding_edit = widget;
706
707 widget = gtk_label_new_with_mnemonic (_("_Y-Padding:"));
708 gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT);
709 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->y_padding_edit);
710 gtk_grid_attach (grid, widget, 5, 1, 1, 1);
711
712 widget = gtk_label_new ("px");
713 gtk_grid_attach (grid, widget, 7, 1, 1, 1);
714
715 /* Border */
716 widget = gtk_spin_button_new_with_range (0, G_MAXUINT, 1);
717 gtk_grid_attach (grid, widget, 6, 2, 1, 1);
718 g_signal_connect_swapped (
719 widget, "value-changed",
720 G_CALLBACK (html_editor_image_dialog_set_border), dialog);
721 dialog->priv->border_edit = widget;
722
723 widget = gtk_label_new_with_mnemonic (_("_Border:"));
724 gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT);
725 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->border_edit);
726 gtk_grid_attach (grid, widget, 5, 2, 1, 1);
727
728 widget = gtk_label_new ("px");
729 gtk_grid_attach (grid, widget, 7, 2, 1, 1);
730
731 /* == Layout == */
732 widget = gtk_label_new ("");
733 gtk_label_set_markup (GTK_LABEL (widget), _("<b>Link</b>"));
734 gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
735 gtk_grid_attach (main_layout, widget, 0, 4, 1, 1);
736
737 grid = GTK_GRID (gtk_grid_new ());
738 gtk_grid_set_row_spacing (grid, 5);
739 gtk_grid_set_column_spacing (grid, 5);
740 gtk_grid_attach (main_layout, GTK_WIDGET (grid), 0, 6, 1, 1);
741 gtk_widget_set_margin_left (GTK_WIDGET (grid), 10);
742
743 widget = gtk_entry_new ();
744 gtk_grid_attach (grid, widget, 1 ,0, 1, 1);
745 gtk_widget_set_hexpand (widget, TRUE);
746 g_signal_connect_swapped (
747 widget, "notify::text",
748 G_CALLBACK (html_editor_image_dialog_set_url), dialog);
749 dialog->priv->url_edit = widget;
750
751 widget = gtk_label_new_with_mnemonic (_("_URL:"));
752 gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT);
753 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->url_edit);
754 gtk_grid_attach (grid, widget, 0, 0, 1, 1);
755
756 widget = gtk_button_new_with_mnemonic (_("_Test URL…"));
757 gtk_grid_attach (grid, widget, 2, 0, 1, 1);
758 g_signal_connect_swapped (
759 widget, "clicked",
760 G_CALLBACK (html_editor_image_dialog_test_url), dialog);
761 dialog->priv->test_url_button = widget;
762
763 gtk_widget_show_all (GTK_WIDGET (main_layout));
764 }
765
766 GtkWidget *
e_html_editor_image_dialog_new(EHTMLEditor * editor)767 e_html_editor_image_dialog_new (EHTMLEditor *editor)
768 {
769 return GTK_WIDGET (
770 g_object_new (
771 E_TYPE_HTML_EDITOR_IMAGE_DIALOG,
772 "editor", editor,
773 "title", _("Image Properties"),
774 NULL));
775 }
776
777 void
e_html_editor_image_dialog_show(EHTMLEditorImageDialog * dialog)778 e_html_editor_image_dialog_show (EHTMLEditorImageDialog *dialog)
779 {
780 EHTMLEditorImageDialogClass *class;
781
782 g_return_if_fail (E_IS_HTML_EDITOR_IMAGE_DIALOG (dialog));
783
784 class = E_HTML_EDITOR_IMAGE_DIALOG_GET_CLASS (dialog);
785 GTK_WIDGET_CLASS (class)->show (GTK_WIDGET (dialog));
786 }
787