2 * e-html-editor-link-dialog.h
4 * Copyright (C) 2012 Dan Vrátil <dvratil@redhat.com>
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.
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.
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/>
25 #include "e-html-editor-link-dialog.h"
26 #include "e-html-editor-selection.h"
27 #include "e-html-editor-utils.h"
28 #include "e-html-editor-view.h"
30 #include <glib/gi18n-lib.h>
32 #define E_HTML_EDITOR_LINK_DIALOG_GET_PRIVATE(obj) \
33 (G_TYPE_INSTANCE_GET_PRIVATE \
34 ((obj), E_TYPE_HTML_EDITOR_LINK_DIALOG, EHTMLEditorLinkDialogPrivate))
37 EHTMLEditorLinkDialog
,
38 e_html_editor_link_dialog
,
39 E_TYPE_HTML_EDITOR_DIALOG
);
41 struct _EHTMLEditorLinkDialogPrivate
{
43 GtkWidget
*label_edit
;
44 GtkWidget
*test_button
;
46 GtkWidget
*remove_link_button
;
49 gboolean label_autofill
;
53 html_editor_link_dialog_test_link (EHTMLEditorLinkDialog
*dialog
)
56 gtk_window_get_screen (GTK_WINDOW (dialog
)),
57 gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->url_edit
)),
63 html_editor_link_dialog_url_changed (EHTMLEditorLinkDialog
*dialog
)
65 if (dialog
->priv
->label_autofill
&&
66 gtk_widget_is_sensitive (dialog
->priv
->label_edit
)) {
69 text
= gtk_entry_get_text (
70 GTK_ENTRY (dialog
->priv
->url_edit
));
72 GTK_ENTRY (dialog
->priv
->label_edit
), text
);
77 html_editor_link_dialog_description_changed (EHTMLEditorLinkDialog
*dialog
)
81 text
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->label_edit
));
82 dialog
->priv
->label_autofill
= (*text
== '\0');
88 html_editor_link_dialog_remove_link (EHTMLEditorLinkDialog
*dialog
)
91 EHTMLEditorView
*view
;
92 EHTMLEditorSelection
*selection
;
94 editor
= e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog
));
95 view
= e_html_editor_get_view (editor
);
96 selection
= e_html_editor_view_get_selection (view
);
97 e_html_editor_selection_unlink (selection
);
99 gtk_widget_hide (GTK_WIDGET (dialog
));
103 html_editor_link_dialog_ok (EHTMLEditorLinkDialog
*dialog
)
106 EHTMLEditorView
*view
;
107 EHTMLEditorSelection
*selection
;
108 WebKitDOMDocument
*document
;
109 WebKitDOMDOMWindow
*window
;
110 WebKitDOMDOMSelection
*dom_selection
;
111 WebKitDOMRange
*range
;
112 WebKitDOMElement
*link
;
114 editor
= e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog
));
115 view
= e_html_editor_get_view (editor
);
116 selection
= e_html_editor_view_get_selection (view
);
118 document
= webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view
));
119 window
= webkit_dom_document_get_default_view (document
);
120 dom_selection
= webkit_dom_dom_window_get_selection (window
);
122 if (!dom_selection
||
123 (webkit_dom_dom_selection_get_range_count (dom_selection
) == 0)) {
124 gtk_widget_hide (GTK_WIDGET (dialog
));
128 range
= webkit_dom_dom_selection_get_range_at (dom_selection
, 0, NULL
);
129 link
= e_html_editor_dom_node_find_parent_element (
130 webkit_dom_range_get_start_container (range
, NULL
), "A");
132 if ((webkit_dom_range_get_start_container (range
, NULL
) !=
133 webkit_dom_range_get_end_container (range
, NULL
)) ||
134 (webkit_dom_range_get_start_offset (range
, NULL
) !=
135 webkit_dom_range_get_end_offset (range
, NULL
))) {
137 WebKitDOMDocumentFragment
*fragment
;
138 fragment
= webkit_dom_range_extract_contents (range
, NULL
);
139 link
= e_html_editor_dom_node_find_child_element (
140 WEBKIT_DOM_NODE (fragment
), "A");
141 webkit_dom_range_insert_node (
142 range
, WEBKIT_DOM_NODE (fragment
), NULL
);
144 webkit_dom_dom_selection_set_base_and_extent (
146 webkit_dom_range_get_start_container (range
, NULL
),
147 webkit_dom_range_get_start_offset (range
, NULL
),
148 webkit_dom_range_get_end_container (range
, NULL
),
149 webkit_dom_range_get_end_offset (range
, NULL
),
154 /* get element that was clicked on */
155 node
= webkit_dom_range_get_common_ancestor_container (range
, NULL
);
156 if (node
&& !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node
)) {
157 link
= e_html_editor_dom_node_find_parent_element (node
, "A");
158 if (link
&& !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link
))
161 link
= WEBKIT_DOM_ELEMENT (node
);
166 webkit_dom_html_anchor_element_set_href (
167 WEBKIT_DOM_HTML_ANCHOR_ELEMENT (link
),
168 gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->url_edit
)));
169 webkit_dom_html_element_set_inner_html (
170 WEBKIT_DOM_HTML_ELEMENT (link
),
171 gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->label_edit
)),
176 /* Check whether a text is selected or not */
177 text
= webkit_dom_range_get_text (range
);
179 e_html_editor_selection_create_link (
182 GTK_ENTRY (dialog
->priv
->url_edit
)));
184 gchar
*html
= g_strdup_printf (
185 "<a href=\"%s\">%s</a>",
187 GTK_ENTRY (dialog
->priv
->url_edit
)),
189 GTK_ENTRY (dialog
->priv
->label_edit
)));
191 e_html_editor_view_exec_command (
192 view
, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML
, html
);
201 gtk_widget_hide (GTK_WIDGET (dialog
));
205 html_editor_link_dialog_entry_key_pressed (EHTMLEditorLinkDialog
*dialog
,
208 /* We can't do thins in key_released, because then you could not open
209 * this dialog from main menu by pressing enter on Insert->Link action */
210 if (event
->keyval
== GDK_KEY_Return
) {
211 html_editor_link_dialog_ok (dialog
);
219 html_editor_link_dialog_show (GtkWidget
*widget
)
222 EHTMLEditorView
*view
;
223 EHTMLEditorLinkDialog
*dialog
;
224 WebKitDOMDocument
*document
;
225 WebKitDOMDOMWindow
*window
;
226 WebKitDOMDOMSelection
*dom_selection
;
227 WebKitDOMRange
*range
;
228 WebKitDOMElement
*link
;
230 dialog
= E_HTML_EDITOR_LINK_DIALOG (widget
);
231 editor
= e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog
));
232 view
= e_html_editor_get_view (editor
);
234 document
= webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view
));
235 window
= webkit_dom_document_get_default_view (document
);
236 dom_selection
= webkit_dom_dom_window_get_selection (window
);
238 /* Reset to default values */
239 gtk_entry_set_text (GTK_ENTRY (dialog
->priv
->url_edit
), "http://");
240 gtk_entry_set_text (GTK_ENTRY (dialog
->priv
->label_edit
), "");
241 gtk_widget_set_sensitive (dialog
->priv
->label_edit
, TRUE
);
242 gtk_widget_set_sensitive (dialog
->priv
->remove_link_button
, TRUE
);
243 dialog
->priv
->label_autofill
= TRUE
;
245 /* No selection at all */
246 if (!dom_selection
||
247 webkit_dom_dom_selection_get_range_count (dom_selection
) < 1) {
248 gtk_widget_set_sensitive (dialog
->priv
->remove_link_button
, FALSE
);
252 range
= webkit_dom_dom_selection_get_range_at (dom_selection
, 0, NULL
);
253 link
= e_html_editor_dom_node_find_parent_element (
254 webkit_dom_range_get_start_container (range
, NULL
), "A");
256 if ((webkit_dom_range_get_start_container (range
, NULL
) !=
257 webkit_dom_range_get_end_container (range
, NULL
)) ||
258 (webkit_dom_range_get_start_offset (range
, NULL
) !=
259 webkit_dom_range_get_end_offset (range
, NULL
))) {
261 WebKitDOMDocumentFragment
*fragment
;
262 fragment
= webkit_dom_range_clone_contents (range
, NULL
);
263 link
= e_html_editor_dom_node_find_child_element (
264 WEBKIT_DOM_NODE (fragment
), "A");
268 node
= webkit_dom_range_get_common_ancestor_container (range
, NULL
);
269 if (node
&& !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node
)) {
270 link
= e_html_editor_dom_node_find_parent_element (node
, "A");
271 if (link
&& !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link
))
274 link
= WEBKIT_DOM_ELEMENT (node
);
281 href
= webkit_dom_html_anchor_element_get_href (
282 WEBKIT_DOM_HTML_ANCHOR_ELEMENT (link
));
283 text
= webkit_dom_html_element_get_inner_text (
284 WEBKIT_DOM_HTML_ELEMENT (link
));
287 GTK_ENTRY (dialog
->priv
->url_edit
), href
);
289 GTK_ENTRY (dialog
->priv
->label_edit
), text
);
296 text
= webkit_dom_range_get_text (range
);
299 GTK_ENTRY (dialog
->priv
->label_edit
), text
);
300 gtk_widget_set_sensitive (
301 dialog
->priv
->label_edit
, FALSE
);
302 gtk_widget_set_sensitive (
303 dialog
->priv
->remove_link_button
, FALSE
);
309 /* Chain up to parent implementation */
310 GTK_WIDGET_CLASS (e_html_editor_link_dialog_parent_class
)->show (widget
);
314 e_html_editor_link_dialog_class_init (EHTMLEditorLinkDialogClass
*class)
316 GtkWidgetClass
*widget_class
;
318 g_type_class_add_private (class, sizeof (EHTMLEditorLinkDialogPrivate
));
320 widget_class
= GTK_WIDGET_CLASS (class);
321 widget_class
->show
= html_editor_link_dialog_show
;
325 e_html_editor_link_dialog_init (EHTMLEditorLinkDialog
*dialog
)
327 GtkGrid
*main_layout
;
331 dialog
->priv
= E_HTML_EDITOR_LINK_DIALOG_GET_PRIVATE (dialog
);
333 main_layout
= e_html_editor_dialog_get_container (E_HTML_EDITOR_DIALOG (dialog
));
335 widget
= gtk_entry_new ();
336 gtk_grid_attach (main_layout
, widget
, 1, 0, 1, 1);
337 g_signal_connect_swapped (
338 widget
, "notify::text",
339 G_CALLBACK (html_editor_link_dialog_url_changed
), dialog
);
340 g_signal_connect_swapped (
341 widget
, "key-press-event",
342 G_CALLBACK (html_editor_link_dialog_entry_key_pressed
), dialog
);
343 dialog
->priv
->url_edit
= widget
;
345 widget
= gtk_label_new_with_mnemonic (_("_URL:"));
346 gtk_label_set_justify (GTK_LABEL (widget
), GTK_JUSTIFY_RIGHT
);
347 gtk_label_set_mnemonic_widget (GTK_LABEL (widget
), dialog
->priv
->url_edit
);
348 gtk_grid_attach (main_layout
, widget
, 0, 0, 1, 1);
350 widget
= gtk_button_new_with_mnemonic (_("_Test URL..."));
351 gtk_grid_attach (main_layout
, widget
, 2, 0, 1, 1);
352 g_signal_connect_swapped (
354 G_CALLBACK (html_editor_link_dialog_test_link
), dialog
);
355 dialog
->priv
->test_button
= widget
;
357 widget
= gtk_entry_new ();
358 gtk_grid_attach (main_layout
, widget
, 1, 1, 2, 1);
359 g_signal_connect_swapped (
360 widget
, "key-release-event",
361 G_CALLBACK (html_editor_link_dialog_description_changed
), dialog
);
362 g_signal_connect_swapped (
363 widget
, "key-press-event",
364 G_CALLBACK (html_editor_link_dialog_entry_key_pressed
), dialog
);
365 dialog
->priv
->label_edit
= widget
;
367 widget
= gtk_label_new_with_mnemonic (_("_Description:"));
368 gtk_label_set_justify (GTK_LABEL (widget
), GTK_JUSTIFY_RIGHT
);
369 gtk_label_set_mnemonic_widget (GTK_LABEL (widget
), dialog
->priv
->label_edit
);
370 gtk_grid_attach (main_layout
, widget
, 0, 1, 1, 1);
372 button_box
= e_html_editor_dialog_get_button_box (E_HTML_EDITOR_DIALOG (dialog
));
374 widget
= gtk_button_new_with_mnemonic (_("_Remove Link"));
375 g_signal_connect_swapped (
377 G_CALLBACK (html_editor_link_dialog_remove_link
), dialog
);
378 gtk_box_pack_start (button_box
, widget
, FALSE
, FALSE
, 5);
379 dialog
->priv
->remove_link_button
= widget
;
381 widget
= gtk_button_new_with_mnemonic (_("_OK"));
382 g_signal_connect_swapped (
384 G_CALLBACK (html_editor_link_dialog_ok
), dialog
);
385 gtk_box_pack_end (button_box
, widget
, FALSE
, FALSE
, 5);
386 dialog
->priv
->ok_button
= widget
;
388 gtk_widget_show_all (GTK_WIDGET (main_layout
));
392 e_html_editor_link_dialog_new (EHTMLEditor
*editor
)
396 E_TYPE_HTML_EDITOR_LINK_DIALOG
,
398 "icon-name", "insert-link",
399 "title", N_("Link Properties"),