static void gb_editor_view_actions_reload_buffer (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; IdeContext *context; IdeBufferManager *buffer_manager; IdeFile *file; g_autoptr(IdeProgress) progress = NULL; g_assert (GB_IS_EDITOR_VIEW (self)); context = ide_buffer_get_context (IDE_BUFFER (self->document)); file = ide_buffer_get_file (IDE_BUFFER (self->document)); buffer_manager = ide_context_get_buffer_manager (context); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->progress_bar), 0.0); gtk_widget_show (GTK_WIDGET (self->progress_bar)); ide_buffer_manager_load_file_async (buffer_manager, file, TRUE, &progress, NULL, gb_editor_view_actions_reload_buffer_cb, g_object_ref (self)); g_object_bind_property (progress, "fraction", self->progress_bar, "fraction", G_BINDING_SYNC_CREATE); }
static void gb_editor_view__buffer_changed_on_volume (GbEditorView *self, GParamSpec *pspec, IdeBuffer *buffer) { g_assert (GB_IS_EDITOR_VIEW (self)); g_assert (IDE_IS_BUFFER (buffer)); if (ide_buffer_get_changed_on_volume (buffer)) gtk_revealer_set_reveal_child (self->modified_revealer, TRUE); else if (gtk_revealer_get_reveal_child (self->modified_revealer)) { GtkTextIter iter; gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter); gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer), &iter, &iter); /* * FIXME: * * Without this delay, I see a condition with split view where the * non-focused split will just render blank. Well that isn't totally * correct, it renders empty gutters and proper line grid background. But * no textual content. And the adjustment is way out of sync. Even * changing the adjustment manually doesn't help. So whatever, I'll * insert a short delay and we'll pick up after the textview has * stablized. */ g_timeout_add (10, no_really_scroll_to_the_top, g_object_ref (self)); gtk_revealer_set_reveal_child (self->modified_revealer, FALSE); } }
static void gb_editor_view_set_split_view (GbView *view, gboolean split_view) { GbEditorView *self = (GbEditorView *)view; g_assert (GB_IS_EDITOR_VIEW (self)); if (split_view && (self->frame2 != NULL)) return; if (!split_view && (self->frame2 == NULL)) return; if (split_view) { self->frame2 = g_object_new (GB_TYPE_EDITOR_FRAME, "document", self->document, "visible", TRUE, NULL); gtk_container_add_with_properties (GTK_CONTAINER (self->paned), GTK_WIDGET (self->frame2), "shrink", FALSE, "resize", TRUE, NULL); gtk_widget_grab_focus (GTK_WIDGET (self->frame2)); } else { GtkWidget *copy = GTK_WIDGET (self->frame2); self->frame2 = NULL; gtk_container_remove (GTK_CONTAINER (self->paned), copy); gtk_widget_grab_focus (GTK_WIDGET (self->frame1)); } }
static void gb_editor_view_actions_reload_buffer_cb (GObject *object, GAsyncResult *result, gpointer user_data) { IdeBufferManager *buffer_manager = (IdeBufferManager *)object; g_autoptr(GbEditorView) self = user_data; g_autoptr(GError) error = NULL; g_autoptr(IdeBuffer) buffer = NULL; g_assert (IDE_IS_BUFFER_MANAGER (buffer_manager)); g_assert (GB_IS_EDITOR_VIEW (self)); gtk_revealer_set_reveal_child (self->modified_revealer, FALSE); if (!(buffer = ide_buffer_manager_load_file_finish (buffer_manager, result, &error))) { g_warning ("%s", error->message); } else { g_signal_emit_by_name (self->frame1->source_view, "movement", IDE_SOURCE_VIEW_MOVEMENT_FIRST_LINE, FALSE, TRUE, FALSE); if (self->frame2 != NULL) g_signal_emit_by_name (self->frame2->source_view, "movement", IDE_SOURCE_VIEW_MOVEMENT_FIRST_LINE, FALSE, TRUE, FALSE); } gb_widget_fade_hide (GTK_WIDGET (self->progress_bar)); }
static void gb_editor_view_actions_print (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; GtkWidget *toplevel; g_autoptr(GbEditorPrintOperation) operation; GtkPrintOperationResult result; g_assert (GB_IS_EDITOR_VIEW (self)); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self)); operation = gb_editor_print_operation_new (self->frame1->source_view); /* keep a ref until "done" is emitted */ g_object_ref (operation); g_signal_connect_after (operation, "done", G_CALLBACK (print_done), g_object_ref (self)); result = gtk_print_operation_run (GTK_PRINT_OPERATION (operation), GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, GTK_WINDOW (toplevel), NULL); handle_print_result (self, GTK_PRINT_OPERATION (operation), result); }
static void gb_editor_view_hide_reload_bar (GbEditorView *self, GtkWidget *button) { g_assert (GB_IS_EDITOR_VIEW (self)); gtk_revealer_set_reveal_child (self->modified_revealer, FALSE); }
static void gb_editor_view_actions_preview (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; GtkSourceLanguage *language; const gchar *lang_id = NULL; g_autoptr(GbDocument) document = NULL; g_assert (GB_IS_EDITOR_VIEW (self)); language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (self->document)); if (!language) return; lang_id = gtk_source_language_get_id (language); if (!lang_id) return; #if 0 if (g_str_equal (lang_id, "html")) { document = g_object_new (GB_TYPE_HTML_DOCUMENT, "buffer", self->document, NULL); } else if (g_str_equal (lang_id, "markdown")) { document = g_object_new (GB_TYPE_HTML_DOCUMENT, "buffer", self->document, NULL); gb_html_document_set_transform_func (GB_HTML_DOCUMENT (document), gb_html_markdown_transform); } #endif if (document) { GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self)); while (parent && !GB_IS_VIEW_GRID (parent)) parent = gtk_widget_get_parent (parent); if (parent == NULL) { while (parent && !GB_IS_VIEW_STACK (parent)) parent = gtk_widget_get_parent (parent); g_assert (GB_IS_VIEW_STACK (parent)); gb_view_stack_focus_document (GB_VIEW_STACK (parent), document); return; } g_assert (GB_IS_VIEW_GRID (parent)); gb_view_grid_focus_document (GB_VIEW_GRID (parent), document); } }
static void gb_editor_view__buffer_modified_changed (GbEditorView *self, GParamSpec *pspec, GtkTextBuffer *buffer) { g_assert (GB_IS_EDITOR_VIEW (self)); g_object_notify (G_OBJECT (self), "modified"); }
static GbDocument * gb_editor_view_get_document (GbView *view) { GbEditorView *self = (GbEditorView *)view; g_assert (GB_IS_EDITOR_VIEW (self)); return GB_DOCUMENT (self->document); }
static gboolean gb_editor_view_get_modified (GbView *view) { GbEditorView *self = (GbEditorView *)view; g_assert (GB_IS_EDITOR_VIEW (self)); return gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (self->document)); }
static void gb_editor_view__buffer_notify_title (GbEditorView *self, GParamSpec *pspec, IdeBuffer *buffer) { g_assert (GB_IS_EDITOR_VIEW (self)); g_assert (GB_IS_EDITOR_DOCUMENT (buffer)); g_object_notify (G_OBJECT (self), "title"); }
static void gb_editor_view_grab_focus (GtkWidget *widget) { GbEditorView *self = (GbEditorView *)widget; g_assert (GB_IS_EDITOR_VIEW (self)); /* todo: track last focus frame */ gtk_widget_grab_focus (GTK_WIDGET (self->frame1->source_view)); }
static gboolean set_split_view (gpointer data) { g_autoptr(GbEditorView) self = data; g_assert (GB_IS_EDITOR_VIEW (self)); gb_view_set_split_view (GB_VIEW (self), (self->frame2 == NULL)); return G_SOURCE_REMOVE; }
static void gb_editor_view_actions_goto_line (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; g_assert (GB_IS_EDITOR_VIEW (self)); gtk_widget_activate (GTK_WIDGET (self->goto_line_button)); }
static void gb_editor_view_actions_toggle_split (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; g_assert (GB_IS_EDITOR_VIEW (self)); g_timeout_add (0, set_split_view, g_object_ref (self)); }
static void gb_editor_view_actions_find_other_file (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; IdeFile *file; g_assert (GB_IS_EDITOR_VIEW (self)); file = ide_buffer_get_file (IDE_BUFFER (self->document)); ide_file_find_other_async (file, NULL, find_other_file_cb, g_object_ref (self)); }
static void gb_editor_view__extension_removed (PeasExtensionSet *set, PeasPluginInfo *info, GbEditorViewAddin *addin, GbEditorView *self) { g_assert (PEAS_IS_EXTENSION_SET (set)); g_assert (info != NULL); g_assert (GB_IS_EDITOR_VIEW_ADDIN (addin)); g_assert (GB_IS_EDITOR_VIEW (self)); gb_editor_view_addin_unload (addin, self); }
static void save_temp_response (GtkWidget *widget, gint response, gpointer user_data) { g_autoptr(GbEditorView) self = user_data; g_autoptr(GFile) target = NULL; g_autoptr(IdeProgress) progress = NULL; GtkFileChooser *chooser = (GtkFileChooser *)widget; g_assert (GTK_IS_FILE_CHOOSER (chooser)); g_assert (GB_IS_EDITOR_VIEW (self)); switch (response) { case GTK_RESPONSE_OK: target = gtk_file_chooser_get_file (chooser); break; case GTK_RESPONSE_CANCEL: default: break; } if (target != NULL) { IdeBufferManager *buffer_manager; IdeContext *context; IdeProject *project; IdeBuffer *buffer = IDE_BUFFER (self->document); g_autoptr(IdeFile) file = NULL; context = ide_buffer_get_context (buffer); project = ide_context_get_project (context); buffer_manager = ide_context_get_buffer_manager (context); file = ide_project_get_project_file (project, target); ide_buffer_set_file (buffer, file); ide_buffer_manager_save_file_async (buffer_manager, buffer, file, &progress, NULL, gb_editor_view_actions__save_temp_cb, g_object_ref (self)); } gtk_widget_destroy (widget); }
static void gb_editor_view_set_document (GbEditorView *self, GbEditorDocument *document) { g_return_if_fail (GB_IS_EDITOR_VIEW (self)); g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document)); if (g_set_object (&self->document, document)) { if (self->frame1) gb_editor_frame_set_document (self->frame1, document); if (self->frame2) gb_editor_frame_set_document (self->frame2, document); g_settings_bind (self->settings, "style-scheme-name", document, "style-scheme-name", G_SETTINGS_BIND_GET); g_settings_bind (self->settings, "highlight-matching-brackets", document, "highlight-matching-brackets", G_SETTINGS_BIND_GET); g_object_bind_property_full (document, "language", self->tweak_button, "label", G_BINDING_SYNC_CREATE, language_to_string, NULL, NULL, NULL); g_signal_connect_object (document, "modified-changed", G_CALLBACK (gb_editor_view__buffer_modified_changed), self, G_CONNECT_SWAPPED); g_signal_connect_object (document, "notify::title", G_CALLBACK (gb_editor_view__buffer_notify_title), self, G_CONNECT_SWAPPED); g_signal_connect_object (document, "notify::changed-on-volume", G_CALLBACK (gb_editor_view__buffer_changed_on_volume), self, G_CONNECT_SWAPPED); g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_DOCUMENT]); gb_editor_view_actions_update (self); } }
static GbView * gb_editor_view_create_split (GbView *view) { GbEditorView *self = (GbEditorView *)view; GbView *ret; g_assert (GB_IS_EDITOR_VIEW (self)); ret = g_object_new (GB_TYPE_EDITOR_VIEW, "document", self->document, "visible", TRUE, NULL); return ret; }
static void gb_editor_view_actions_save_as (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; IdeBuffer *buffer; GtkWidget *suggested; GtkWidget *toplevel; GtkWidget *dialog; IdeFile *file; GFile *gfile; g_assert (GB_IS_EDITOR_VIEW (self)); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self)); dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_SAVE, "do-overwrite-confirmation", TRUE, "local-only", FALSE, "modal", TRUE, "select-multiple", FALSE, "show-hidden", FALSE, "transient-for", toplevel, "title", _("Save Document As"), NULL); buffer = IDE_BUFFER (self->document); file = ide_buffer_get_file (buffer); gfile = ide_file_get_file (file); if (gfile != NULL) gtk_file_chooser_set_file (GTK_FILE_CHOOSER (dialog), gfile, NULL); gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), GTK_RESPONSE_CANCEL, _("Save"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); suggested = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_style_context_add_class (gtk_widget_get_style_context (suggested), GTK_STYLE_CLASS_SUGGESTED_ACTION); g_signal_connect (dialog, "response", G_CALLBACK (save_as_response), g_object_ref (self)); gtk_window_present (GTK_WINDOW (dialog)); }
static void gb_editor_view_actions_reveal (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; GbWorkbench *workbench; IdeFile *file; GFile *gfile; g_assert (G_IS_SIMPLE_ACTION (action)); g_assert (GB_IS_EDITOR_VIEW (self)); file = ide_buffer_get_file (IDE_BUFFER (self->document)); gfile = ide_file_get_file (file); workbench = gb_widget_get_workbench (GTK_WIDGET (self)); gb_workbench_reveal_file (workbench, gfile); }
static void gb_editor_view_actions_close (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; g_assert (GB_IS_EDITOR_VIEW (self)); /* just close our current frame if we have split view */ if (self->frame2 != NULL) { /* todo: swap frame1/frame2 if frame2 was last focused. */ g_timeout_add (0, set_split_view, g_object_ref (self)); } else { gb_widget_activate_action (GTK_WIDGET (self), "view-stack", "close", NULL); } }
static void gb_editor_view_navigate_to (GbView *view, IdeSourceLocation *location) { GbEditorView *self = (GbEditorView *)view; GbEditorFrame *frame; GtkTextMark *insert; GtkTextBuffer *buffer; GtkTextIter iter; guint line; guint line_offset; IDE_ENTRY; g_assert (GB_IS_EDITOR_VIEW (self)); g_assert (location != NULL); frame = gb_editor_view_get_last_focused (self); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (frame->source_view)); line = ide_source_location_get_line (location); line_offset = ide_source_location_get_line_offset (location); gtk_text_buffer_get_iter_at_line (buffer, &iter, line); for (; line_offset; line_offset--) if (gtk_text_iter_ends_line (&iter) || !gtk_text_iter_forward_char (&iter)) break; gtk_text_buffer_select_range (buffer, &iter, &iter); insert = gtk_text_buffer_get_insert (buffer); gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (frame->source_view), insert, 0.0, TRUE, 1.0, 0.5); g_signal_emit_by_name (frame->source_view, "save-insert-mark"); IDE_EXIT; }
void gb_editor_view_actions_update (GbEditorView *self) { GtkSourceLanguage *language; const gchar *lang_id = NULL; GActionGroup *group; GAction *action; gboolean enabled; g_assert (GB_IS_EDITOR_VIEW (self)); group = gtk_widget_get_action_group (GTK_WIDGET (self), "view"); if (!G_IS_SIMPLE_ACTION_GROUP (group)) return; /* update preview sensitivity */ language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (self->document)); if (language) lang_id = gtk_source_language_get_id (language); enabled = ((g_strcmp0 (lang_id, "html") == 0) || (g_strcmp0 (lang_id, "markdown") == 0)); action = g_action_map_lookup_action (G_ACTION_MAP (group), "preview"); g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled); }
static void gb_editor_view_actions_language (GSimpleAction *action, GVariant *variant, gpointer user_data) { GbEditorView *self = user_data; GtkSourceLanguageManager *manager; GtkSourceLanguage *language; GtkSourceBuffer *buffer; const gchar *name; g_assert (GB_IS_EDITOR_VIEW (self)); manager = gtk_source_language_manager_get_default (); name = g_variant_get_string (variant, NULL); buffer = GTK_SOURCE_BUFFER (self->document); if (name != NULL) { language = gtk_source_language_manager_get_language (manager, name); gtk_source_buffer_set_language (buffer, language); gb_editor_view_actions_update (self); } }
static void gb_editor_view_actions_save (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; IdeContext *context; IdeBufferManager *buffer_manager; IdeFile *file; IdeProgress *progress = NULL; IdeVcs *vcs; GFile *workdir; g_assert (GB_IS_EDITOR_VIEW (self)); file = ide_buffer_get_file (IDE_BUFFER (self->document)); context = ide_buffer_get_context (IDE_BUFFER (self->document)); buffer_manager = ide_context_get_buffer_manager (context); vcs = ide_context_get_vcs (context); workdir = ide_vcs_get_working_directory (vcs); if (ide_file_get_is_temporary (file)) { GtkDialog *dialog; GtkWidget *toplevel; GtkWidget *suggested; toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self)); dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_SAVE, "do-overwrite-confirmation", TRUE, "local-only", FALSE, "modal", TRUE, "select-multiple", FALSE, "show-hidden", FALSE, "transient-for", toplevel, "title", _("Save Document"), NULL); gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog), workdir, NULL); gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), GTK_RESPONSE_CANCEL, _("Save"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); suggested = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_style_context_add_class (gtk_widget_get_style_context (suggested), GTK_STYLE_CLASS_SUGGESTED_ACTION); g_signal_connect (dialog, "response", G_CALLBACK (save_temp_response), g_object_ref (self)); gtk_window_present (GTK_WINDOW (dialog)); return; } ide_buffer_manager_save_file_async (buffer_manager, IDE_BUFFER (self->document), file, &progress, NULL, save_file_cb, g_object_ref (self)); g_object_bind_property (progress, "fraction", self->progress_bar, "fraction", G_BINDING_SYNC_CREATE); gtk_widget_show (GTK_WIDGET (self->progress_bar)); g_clear_object (&progress); }