GtkWidget *editor_new(const gchar *title, EDITOR *e) { GtkActionGroup *action_group; GtkUIManager *manager; GtkWidget *editor; GError *error = NULL; editor = gtkhtml_editor_new(); e->window = editor; e->html_widget = GTK_WIDGET(gtkhtml_editor_get_html(GTKHTML_EDITOR(editor))); gtk_window_set_title(GTK_WINDOW(editor), title); set_window_icon(GTK_WINDOW(editor)); manager = gtkhtml_editor_get_ui_manager(GTKHTML_EDITOR(editor)); if (e->type == STUDYPAD_EDITOR) gtk_ui_manager_add_ui_from_string(manager, file_ui, -1, &error); else gtk_ui_manager_add_ui_from_string(manager, note_file_ui, -1, &error); handle_error(&error); gtk_ui_manager_add_ui_from_string(manager, view_ui, -1, &error); handle_error(&error); if (e->type == STUDYPAD_EDITOR) gtk_ui_manager_add_ui_from_string(manager, main_ui_studypad, -1, &error); else gtk_ui_manager_add_ui_from_string(manager, main_ui_note, -1, &error); handle_error(&error); action_group = gtk_action_group_new("file"); gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE); gtk_action_group_add_actions(action_group, file_entries, G_N_ELEMENTS(file_entries), e); gtk_ui_manager_insert_action_group(manager, action_group, 0); action_group = gtk_action_group_new("view"); gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE); gtk_action_group_add_actions(action_group, view_entries, G_N_ELEMENTS(view_entries), editor); gtk_ui_manager_insert_action_group(manager, action_group, 0); action_group = gtk_action_group_new("main"); gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE); gtk_action_group_add_actions(action_group, main_entries, G_N_ELEMENTS(main_entries), e); gtk_ui_manager_insert_action_group(manager, action_group, 0); action_group = gtk_action_group_new("context-menu"); gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE); gtk_action_group_add_actions(action_group, test_entries, G_N_ELEMENTS(test_entries), e); gtk_ui_manager_insert_action_group(manager, action_group, 0); gtk_ui_manager_ensure_update(manager); gtk_widget_show(editor); gtkhtml_editor_drop_undo(GTKHTML_EDITOR(e->window)); gtkhtml_editor_set_changed(GTKHTML_EDITOR(e->window), FALSE); g_signal_connect(editor, "delete-event", G_CALLBACK(app_delete_cb), (EDITOR *)e); return editor; }
/* Helper for gtkhtml_editor_update_context() */ static void editor_spell_checkers_foreach (GtkhtmlSpellChecker *checker, GtkhtmlEditor *editor) { const GtkhtmlSpellLanguage *language; const gchar *language_code; GtkActionGroup *action_group; GtkUIManager *manager; GtkHTML *html; GList *list; gchar *path; gchar *word; gint count = 0; guint merge_id; language = gtkhtml_spell_checker_get_language (checker); language_code = gtkhtml_spell_language_get_code (language); html = gtkhtml_editor_get_html (editor); word = html_engine_get_spell_word (html->engine); list = gtkhtml_spell_checker_get_suggestions (checker, word, -1); manager = gtkhtml_editor_get_ui_manager (editor); action_group = editor->priv->suggestion_actions; merge_id = editor->priv->spell_suggestions_merge_id; path = g_strdup_printf ( "/context-menu/context-spell-suggest/" "context-spell-suggest-%s-menu", language_code); while (list != NULL) { gchar *suggestion = list->data; gchar *action_name; gchar *action_label; GtkAction *action; GtkWidget *child; GSList *proxies; /* Action name just needs to be unique. */ action_name = g_strdup_printf ( "suggest-%s-%d", language_code, count++); action_label = g_markup_printf_escaped ( "<b>%s</b>", suggestion); action = gtk_action_new ( action_name, action_label, NULL, NULL); g_object_set_data_full ( G_OBJECT (action), "word", g_strdup (suggestion), g_free); g_signal_connect ( action, "activate", G_CALLBACK ( action_context_spell_suggest_cb), editor); gtk_action_group_add_action (action_group, action); gtk_ui_manager_add_ui ( manager, merge_id, path, action_name, action_name, GTK_UI_MANAGER_AUTO, FALSE); /* XXX GtkAction offers no supports for Pango markup, * so we have to manually set "use-markup" on the * child of the proxy widget. */ gtk_ui_manager_ensure_update (manager); proxies = gtk_action_get_proxies (action); child = gtk_bin_get_child (proxies->data); g_object_set (child, "use-markup", TRUE, NULL); g_free (suggestion); g_free (action_name); g_free (action_label); list = g_list_delete_link (list, list); } g_free (path); g_free (word); }
void gtkhtml_editor_update_context (GtkhtmlEditor *editor) { GtkHTML *html; HTMLType type; HTMLObject *object; GtkUIManager *manager; GtkActionGroup *action_group; GList *list; gboolean visible; guint merge_id; html = gtkhtml_editor_get_html (editor); manager = gtkhtml_editor_get_ui_manager (editor); gtk_html_update_styles (html); /* Update context menu item visibility. */ object = html->engine->cursor->object; if (object != NULL) type = HTML_OBJECT_TYPE (object); else type = HTML_TYPE_NONE; visible = (type == HTML_TYPE_IMAGE); gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_IMAGE), visible); visible = (type == HTML_TYPE_LINKTEXT); gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_LINK), visible); visible = (type == HTML_TYPE_RULE); gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_RULE), visible); visible = (type == HTML_TYPE_TEXT); gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_TEXT), visible); visible = gtk_action_get_visible (ACTION (CONTEXT_PROPERTIES_IMAGE)) || gtk_action_get_visible (ACTION (CONTEXT_PROPERTIES_LINK)) || gtk_action_get_visible (ACTION (CONTEXT_PROPERTIES_TEXT)); gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_PARAGRAPH), visible); /* Set to visible if any of these are true: * - Selection is active and contains a link. * - Cursor is on a link. * - Cursor is on an image that has a URL or target. */ visible = (html_engine_is_selection_active (html->engine) && html_engine_selection_contains_link (html->engine)) || (type == HTML_TYPE_LINKTEXT) || (type == HTML_TYPE_IMAGE && (HTML_IMAGE (object)->url != NULL || HTML_IMAGE (object)->target != NULL)); gtk_action_set_visible (ACTION (CONTEXT_REMOVE_LINK), visible); /* Get the parent object. */ object = (object != NULL) ? object->parent : NULL; /* Get the grandparent object. */ object = (object != NULL) ? object->parent : NULL; if (object != NULL) type = HTML_OBJECT_TYPE (object); else type = HTML_TYPE_NONE; visible = (type == HTML_TYPE_TABLECELL); gtk_action_set_visible (ACTION (CONTEXT_DELETE_CELL), visible); gtk_action_set_visible (ACTION (CONTEXT_DELETE_COLUMN), visible); gtk_action_set_visible (ACTION (CONTEXT_DELETE_ROW), visible); gtk_action_set_visible (ACTION (CONTEXT_DELETE_TABLE), visible); gtk_action_set_visible (ACTION (CONTEXT_INSERT_COLUMN_AFTER), visible); gtk_action_set_visible (ACTION (CONTEXT_INSERT_COLUMN_BEFORE), visible); gtk_action_set_visible (ACTION (CONTEXT_INSERT_ROW_ABOVE), visible); gtk_action_set_visible (ACTION (CONTEXT_INSERT_ROW_BELOW), visible); gtk_action_set_visible (ACTION (CONTEXT_INSERT_TABLE), visible); gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_CELL), visible); /* Get the great grandparent object. */ object = (object != NULL) ? object->parent : NULL; if (object != NULL) type = HTML_OBJECT_TYPE (object); else type = HTML_TYPE_NONE; /* Note the |= (cursor must be in a table cell). */ visible |= (type == HTML_TYPE_TABLE); gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_TABLE), visible); /********************** Spell Check Suggestions **********************/ object = html->engine->cursor->object; action_group = editor->priv->suggestion_actions; /* Remove the old content from the context menu. */ merge_id = editor->priv->spell_suggestions_merge_id; if (merge_id > 0) { gtk_ui_manager_remove_ui (manager, merge_id); editor->priv->spell_suggestions_merge_id = 0; } /* Clear the action group for spelling suggestions. */ list = gtk_action_group_list_actions (action_group); while (list != NULL) { GtkAction *action = list->data; gtk_action_group_remove_action (action_group, action); list = g_list_delete_link (list, list); } /* Decide if we should show spell checking items. */ visible = !html_engine_is_selection_active (html->engine) && object != NULL && html_object_is_text (object) && !html_engine_spell_word_is_valid (html->engine); action_group = editor->priv->spell_check_actions; gtk_action_group_set_visible (action_group, visible); /* Exit early if spell checking items are invisible. */ if (!visible) return; list = editor->priv->active_spell_checkers; merge_id = gtk_ui_manager_new_merge_id (manager); editor->priv->spell_suggestions_merge_id = merge_id; /* Handle a single active language as a special case. */ if (g_list_length (list) == 1) { editor_inline_spelling_suggestions (editor, list->data); return; } /* Add actions and context menu content for active languages. */ g_list_foreach (list, (GFunc) editor_spell_checkers_foreach, editor); }
static void editor_inline_spelling_suggestions (GtkhtmlEditor *editor, GtkhtmlSpellChecker *checker) { GtkActionGroup *action_group; GtkUIManager *manager; GtkHTML *html; GList *list; const gchar *path; gchar *word; guint count = 0; guint length; guint merge_id; guint threshold; html = gtkhtml_editor_get_html (editor); word = html_engine_get_spell_word (html->engine); list = gtkhtml_spell_checker_get_suggestions (checker, word, -1); path = "/context-menu/context-spell-suggest/"; manager = gtkhtml_editor_get_ui_manager (editor); action_group = editor->priv->suggestion_actions; merge_id = editor->priv->spell_suggestions_merge_id; /* Calculate how many suggestions to put directly in the * context menu. The rest will go in a secondary menu. */ length = g_list_length (list); if (length <= MAX_LEVEL1_SUGGESTIONS) threshold = length; else if (length - MAX_LEVEL1_SUGGESTIONS < MIN_LEVEL2_SUGGESTIONS) threshold = length; else threshold = MAX_LEVEL1_SUGGESTIONS; while (list != NULL) { gchar *suggestion = list->data; gchar *action_name; gchar *action_label; GtkAction *action; GtkWidget *child; GSList *proxies; /* Once we reach the threshold, put all subsequent * spelling suggestions in a secondary menu. */ if (count == threshold) path = "/context-menu/context-more-suggestions-menu/"; /* Action name just needs to be unique. */ action_name = g_strdup_printf ("suggest-%d", count++); action_label = g_markup_printf_escaped ( "<b>%s</b>", suggestion); action = gtk_action_new ( action_name, action_label, NULL, NULL); g_object_set_data_full ( G_OBJECT (action), "word", g_strdup (suggestion), g_free); g_signal_connect ( action, "activate", G_CALLBACK ( action_context_spell_suggest_cb), editor); gtk_action_group_add_action (action_group, action); gtk_ui_manager_add_ui ( manager, merge_id, path, action_name, action_name, GTK_UI_MANAGER_AUTO, FALSE); /* XXX GtkAction offers no support for Pango markup, * so we have to manually set "use-markup" on the * child of the proxy widget. */ gtk_ui_manager_ensure_update (manager); proxies = gtk_action_get_proxies (action); child = gtk_bin_get_child (proxies->data); g_object_set (child, "use-markup", TRUE, NULL); g_free (suggestion); g_free (action_name); g_free (action_label); list = g_list_delete_link (list, list); } g_free (word); }