From 8650fb139a9143f04615de74ff569bce3e0c4ce3 Mon Sep 17 00:00:00 2001 From: Tomas Popela Date: Mon, 9 Jun 2014 16:32:25 +0200 Subject: Bug 540362: [webkit-composer] Use webkit for composer Merge wip/webkit-composer branch into master. --- e-util/e-html-editor-link-dialog.c | 390 +++++++++++++++++++++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 e-util/e-html-editor-link-dialog.c (limited to 'e-util/e-html-editor-link-dialog.c') diff --git a/e-util/e-html-editor-link-dialog.c b/e-util/e-html-editor-link-dialog.c new file mode 100644 index 0000000000..0572d07c09 --- /dev/null +++ b/e-util/e-html-editor-link-dialog.c @@ -0,0 +1,390 @@ +/* + * e-html-editor-link-dialog.h + * + * Copyright (C) 2012 Dan Vrátil + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "e-html-editor-link-dialog.h" +#include "e-html-editor-selection.h" +#include "e-html-editor-utils.h" +#include "e-html-editor-view.h" + +#include + +#define E_HTML_EDITOR_LINK_DIALOG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_HTML_EDITOR_LINK_DIALOG, EHTMLEditorLinkDialogPrivate)) + +G_DEFINE_TYPE ( + EHTMLEditorLinkDialog, + e_html_editor_link_dialog, + E_TYPE_HTML_EDITOR_DIALOG); + +struct _EHTMLEditorLinkDialogPrivate { + GtkWidget *url_edit; + GtkWidget *label_edit; + GtkWidget *test_button; + + GtkWidget *remove_link_button; + GtkWidget *ok_button; + + gboolean label_autofill; +}; + +static void +html_editor_link_dialog_test_link (EHTMLEditorLinkDialog *dialog) +{ + gtk_show_uri ( + gtk_window_get_screen (GTK_WINDOW (dialog)), + gtk_entry_get_text (GTK_ENTRY (dialog->priv->url_edit)), + GDK_CURRENT_TIME, + NULL); +} + +static void +html_editor_link_dialog_url_changed (EHTMLEditorLinkDialog *dialog) +{ + if (dialog->priv->label_autofill && + gtk_widget_is_sensitive (dialog->priv->label_edit)) { + const gchar *text; + + text = gtk_entry_get_text ( + GTK_ENTRY (dialog->priv->url_edit)); + gtk_entry_set_text ( + GTK_ENTRY (dialog->priv->label_edit), text); + } +} + +static gboolean +html_editor_link_dialog_description_changed (EHTMLEditorLinkDialog *dialog) +{ + const gchar *text; + + text = gtk_entry_get_text (GTK_ENTRY (dialog->priv->label_edit)); + dialog->priv->label_autofill = (*text == '\0'); + + return FALSE; +} + +static void +html_editor_link_dialog_remove_link (EHTMLEditorLinkDialog *dialog) +{ + EHTMLEditor *editor; + EHTMLEditorView *view; + EHTMLEditorSelection *selection; + + editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog)); + view = e_html_editor_get_view (editor); + selection = e_html_editor_view_get_selection (view); + e_html_editor_selection_unlink (selection); + + gtk_widget_hide (GTK_WIDGET (dialog)); +} + +static void +html_editor_link_dialog_ok (EHTMLEditorLinkDialog *dialog) +{ + EHTMLEditor *editor; + EHTMLEditorView *view; + EHTMLEditorSelection *selection; + WebKitDOMDocument *document; + WebKitDOMDOMWindow *window; + WebKitDOMDOMSelection *dom_selection; + WebKitDOMRange *range; + WebKitDOMElement *link; + + editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog)); + view = e_html_editor_get_view (editor); + selection = e_html_editor_view_get_selection (view); + + document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); + window = webkit_dom_document_get_default_view (document); + dom_selection = webkit_dom_dom_window_get_selection (window); + + if (!dom_selection || + (webkit_dom_dom_selection_get_range_count (dom_selection) == 0)) { + gtk_widget_hide (GTK_WIDGET (dialog)); + return; + } + + range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL); + link = e_html_editor_dom_node_find_parent_element ( + webkit_dom_range_get_start_container (range, NULL), "A"); + if (!link) { + if ((webkit_dom_range_get_start_container (range, NULL) != + webkit_dom_range_get_end_container (range, NULL)) || + (webkit_dom_range_get_start_offset (range, NULL) != + webkit_dom_range_get_end_offset (range, NULL))) { + + WebKitDOMDocumentFragment *fragment; + fragment = webkit_dom_range_extract_contents (range, NULL); + link = e_html_editor_dom_node_find_child_element ( + WEBKIT_DOM_NODE (fragment), "A"); + webkit_dom_range_insert_node ( + range, WEBKIT_DOM_NODE (fragment), NULL); + + webkit_dom_dom_selection_set_base_and_extent ( + dom_selection, + webkit_dom_range_get_start_container (range, NULL), + webkit_dom_range_get_start_offset (range, NULL), + webkit_dom_range_get_end_container (range, NULL), + webkit_dom_range_get_end_offset (range, NULL), + NULL); + } else { + /* get element that was clicked on */ + link = e_html_editor_view_get_element_under_mouse_click (view); + if (!WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link)) + link = NULL; + } + } + + if (link) { + webkit_dom_html_anchor_element_set_href ( + WEBKIT_DOM_HTML_ANCHOR_ELEMENT (link), + gtk_entry_get_text (GTK_ENTRY (dialog->priv->url_edit))); + webkit_dom_html_element_set_inner_html ( + WEBKIT_DOM_HTML_ELEMENT (link), + gtk_entry_get_text (GTK_ENTRY (dialog->priv->label_edit)), + NULL); + } else { + gchar *text; + + /* Check whether a text is selected or not */ + text = webkit_dom_range_get_text (range); + if (text && *text) { + e_html_editor_selection_create_link ( + selection, + gtk_entry_get_text ( + GTK_ENTRY (dialog->priv->url_edit))); + } else { + gchar *html = g_strdup_printf ( + "%s", + gtk_entry_get_text ( + GTK_ENTRY (dialog->priv->url_edit)), + gtk_entry_get_text ( + GTK_ENTRY (dialog->priv->label_edit))); + + e_html_editor_view_exec_command ( + view, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, html); + + g_free (html); + + } + + g_free (text); + } + + gtk_widget_hide (GTK_WIDGET (dialog)); +} + +static gboolean +html_editor_link_dialog_entry_key_pressed (EHTMLEditorLinkDialog *dialog, + GdkEventKey *event) +{ + /* We can't do thins in key_released, because then you could not open + * this dialog from main menu by pressing enter on Insert->Link action */ + if (event->keyval == GDK_KEY_Return) { + html_editor_link_dialog_ok (dialog); + return TRUE; + } + + return FALSE; +} + +static void +html_editor_link_dialog_show (GtkWidget *widget) +{ + EHTMLEditor *editor; + EHTMLEditorView *view; + EHTMLEditorLinkDialog *dialog; + WebKitDOMDocument *document; + WebKitDOMDOMWindow *window; + WebKitDOMDOMSelection *dom_selection; + WebKitDOMRange *range; + WebKitDOMElement *link; + + dialog = E_HTML_EDITOR_LINK_DIALOG (widget); + editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog)); + view = e_html_editor_get_view (editor); + + document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); + window = webkit_dom_document_get_default_view (document); + dom_selection = webkit_dom_dom_window_get_selection (window); + + /* Reset to default values */ + gtk_entry_set_text (GTK_ENTRY (dialog->priv->url_edit), "http://"); + gtk_entry_set_text (GTK_ENTRY (dialog->priv->label_edit), ""); + gtk_widget_set_sensitive (dialog->priv->label_edit, TRUE); + gtk_widget_set_sensitive (dialog->priv->remove_link_button, TRUE); + dialog->priv->label_autofill = TRUE; + + /* No selection at all */ + if (!dom_selection || + webkit_dom_dom_selection_get_range_count (dom_selection) < 1) { + gtk_widget_set_sensitive (dialog->priv->remove_link_button, FALSE); + goto chainup; + } + + range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL); + link = e_html_editor_dom_node_find_parent_element ( + webkit_dom_range_get_start_container (range, NULL), "A"); + if (!link) { + if ((webkit_dom_range_get_start_container (range, NULL) != + webkit_dom_range_get_end_container (range, NULL)) || + (webkit_dom_range_get_start_offset (range, NULL) != + webkit_dom_range_get_end_offset (range, NULL))) { + + WebKitDOMDocumentFragment *fragment; + fragment = webkit_dom_range_clone_contents (range, NULL); + link = e_html_editor_dom_node_find_child_element ( + WEBKIT_DOM_NODE (fragment), "A"); + } else { + /* get element that was clicked on */ + link = e_html_editor_view_get_element_under_mouse_click (view); + if (!WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link)) + link = NULL; + } + } + + if (link) { + gchar *href, *text; + + href = webkit_dom_html_anchor_element_get_href ( + WEBKIT_DOM_HTML_ANCHOR_ELEMENT (link)); + text = webkit_dom_html_element_get_inner_text ( + WEBKIT_DOM_HTML_ELEMENT (link)); + + gtk_entry_set_text ( + GTK_ENTRY (dialog->priv->url_edit), href); + gtk_entry_set_text ( + GTK_ENTRY (dialog->priv->label_edit), text); + + g_free (text); + g_free (href); + } else { + gchar *text; + + text = webkit_dom_range_get_text (range); + if (text && *text) { + gtk_entry_set_text ( + GTK_ENTRY (dialog->priv->label_edit), text); + gtk_widget_set_sensitive ( + dialog->priv->label_edit, FALSE); + gtk_widget_set_sensitive ( + dialog->priv->remove_link_button, FALSE); + } + g_free (text); + } + + chainup: + /* Chain up to parent implementation */ + GTK_WIDGET_CLASS (e_html_editor_link_dialog_parent_class)->show (widget); +} + +static void +e_html_editor_link_dialog_class_init (EHTMLEditorLinkDialogClass *class) +{ + GtkWidgetClass *widget_class; + + g_type_class_add_private (class, sizeof (EHTMLEditorLinkDialogPrivate)); + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->show = html_editor_link_dialog_show; +} + +static void +e_html_editor_link_dialog_init (EHTMLEditorLinkDialog *dialog) +{ + GtkGrid *main_layout; + GtkBox *button_box; + GtkWidget *widget; + + dialog->priv = E_HTML_EDITOR_LINK_DIALOG_GET_PRIVATE (dialog); + + main_layout = e_html_editor_dialog_get_container (E_HTML_EDITOR_DIALOG (dialog)); + + widget = gtk_entry_new (); + gtk_grid_attach (main_layout, widget, 1, 0, 1, 1); + g_signal_connect_swapped ( + widget, "notify::text", + G_CALLBACK (html_editor_link_dialog_url_changed), dialog); + g_signal_connect_swapped ( + widget, "key-press-event", + G_CALLBACK (html_editor_link_dialog_entry_key_pressed), dialog); + dialog->priv->url_edit = widget; + + widget = gtk_label_new_with_mnemonic (_("_URL:")); + gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT); + gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->url_edit); + gtk_grid_attach (main_layout, widget, 0, 0, 1, 1); + + widget = gtk_button_new_with_mnemonic (_("_Test URL...")); + gtk_grid_attach (main_layout, widget, 2, 0, 1, 1); + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (html_editor_link_dialog_test_link), dialog); + dialog->priv->test_button = widget; + + widget = gtk_entry_new (); + gtk_grid_attach (main_layout, widget, 1, 1, 2, 1); + g_signal_connect_swapped ( + widget, "key-release-event", + G_CALLBACK (html_editor_link_dialog_description_changed), dialog); + g_signal_connect_swapped ( + widget, "key-press-event", + G_CALLBACK (html_editor_link_dialog_entry_key_pressed), dialog); + dialog->priv->label_edit = widget; + + widget = gtk_label_new_with_mnemonic (_("_Description:")); + gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT); + gtk_label_set_mnemonic_widget (GTK_LABEL (widget), dialog->priv->label_edit); + gtk_grid_attach (main_layout, widget, 0, 1, 1, 1); + + button_box = e_html_editor_dialog_get_button_box (E_HTML_EDITOR_DIALOG (dialog)); + + widget = gtk_button_new_with_mnemonic (_("_Remove Link")); + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (html_editor_link_dialog_remove_link), dialog); + gtk_box_pack_start (button_box, widget, FALSE, FALSE, 5); + dialog->priv->remove_link_button = widget; + + widget = gtk_button_new_from_stock (GTK_STOCK_OK); + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (html_editor_link_dialog_ok), dialog); + gtk_box_pack_end (button_box, widget, FALSE, FALSE, 5); + dialog->priv->ok_button = widget; + + gtk_widget_show_all (GTK_WIDGET (main_layout)); +} + +GtkWidget * +e_html_editor_link_dialog_new (EHTMLEditor *editor) +{ + return GTK_WIDGET ( + g_object_new ( + E_TYPE_HTML_EDITOR_LINK_DIALOG, + "editor", editor, + "icon-name", "insert-link", + "title", N_("Link Properties"), + NULL)); +} -- cgit v1.2.3