static void
ide_highlight_engine__buffer_delete_range_cb (IdeHighlightEngine *self,
        GtkTextIter        *range_begin,
        GtkTextIter        *range_end,
        IdeBuffer          *buffer)
{
    GtkTextBuffer *text_buffer = (GtkTextBuffer *)buffer;
    GtkTextIter begin;
    GtkTextIter end;

    IDE_ENTRY;

    g_assert (IDE_IS_HIGHLIGHT_ENGINE (self));
    g_assert (range_begin);
    g_assert (IDE_IS_BUFFER (buffer));
    g_assert (GTK_IS_TEXT_BUFFER (text_buffer));

    /*
     * No need to use the range_end since everything that
     * was after range_end will now be after range_begin
     */
    begin = *range_begin;
    end = *range_begin;

    invalidate_and_highlight (self, &begin, &end);

    IDE_EXIT;
}
static void
ide_highlight_engine__buffer_insert_text_cb (IdeHighlightEngine *self,
        GtkTextIter        *location,
        gchar              *text,
        gint                len,
        IdeBuffer          *buffer)
{
    GtkTextBuffer *text_buffer = (GtkTextBuffer *)buffer;
    GtkTextIter begin;
    GtkTextIter end;

    IDE_ENTRY;

    g_assert (IDE_IS_HIGHLIGHT_ENGINE (self));
    g_assert (location);
    g_assert (text);
    g_assert (IDE_IS_BUFFER (buffer));
    g_assert (GTK_IS_TEXT_BUFFER (text_buffer));

    /*
     * Backward the begin iter len characters from location
     * (location points to the end of the string) in order to get
     * the iter position where our inserted text was started.
     */
    begin = *location;
    gtk_text_iter_backward_chars (&begin, g_utf8_strlen (text, len));

    end = *location;

    invalidate_and_highlight (self, &begin, &end);

    IDE_EXIT;
}
static void
on_line_spacing_changed_cb (GbpLineSpacingBufferAddin *self,
                            const gchar               *key,
                            GSettings                 *settings)
{
  gint spacing;

  g_assert (GBP_IS_LINE_SPACING_BUFFER_ADDIN (self));
  g_assert (IDE_IS_BUFFER (self->buffer));
  g_assert (G_IS_SETTINGS (settings));

  if (self->tag != NULL)
    {
      GtkTextTagTable *table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (self->buffer));
      gtk_text_tag_table_remove (table, self->tag);
      self->tag = NULL;
    }

  spacing = g_settings_get_int (settings, "line-spacing");

  if (spacing > 0)
    {
      self->tag = gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (self->buffer), NULL,
                                              "pixels-above-lines", spacing,
                                              "pixels-below-lines", spacing,
                                              NULL);
      gbp_line_spacing_buffer_addin_apply (self);
    }
}
示例#4
0
static void
ide_lsp_formatter_format_call_cb (GObject      *object,
                                  GAsyncResult *result,
                                  gpointer      user_data)
{
  IdeLspClient *client = (IdeLspClient *)object;
  g_autoptr(IdeTask) task = user_data;
  g_autoptr(GError) error = NULL;
  g_autoptr(GVariant) reply = NULL;
  IdeLspFormatter *self;
  IdeBuffer *buffer;

  g_return_if_fail (IDE_IS_LSP_CLIENT (client));
  g_return_if_fail (G_IS_ASYNC_RESULT (result));

  if (!ide_lsp_client_call_finish (client, result, &reply, &error))
    {
      ide_task_return_error (task, g_steal_pointer (&error));
      return;
    }

  self = ide_task_get_source_object (task);
  buffer = ide_task_get_task_data (task);

  g_assert (IDE_IS_LSP_FORMATTER (self));
  g_assert (IDE_IS_BUFFER (buffer));

  ide_lsp_formatter_apply_changes (self, buffer, reply);

  ide_task_return_boolean (task, TRUE);
}
static void
ide_highlight_engine__bind_buffer_cb (IdeHighlightEngine *self,
                                      IdeBuffer          *buffer,
                                      EggSignalGroup     *group)
{
    GtkTextBuffer *text_buffer = (GtkTextBuffer *)buffer;
    GtkTextIter begin;
    GtkTextIter end;

    IDE_ENTRY;

    g_assert (IDE_IS_HIGHLIGHT_ENGINE (self));
    g_assert (IDE_IS_BUFFER (buffer));
    g_assert (EGG_IS_SIGNAL_GROUP (group));

    ide_set_weak_pointer (&self->buffer, buffer);

    g_object_set_qdata (G_OBJECT (buffer), gEngineQuark, self);

    gtk_text_buffer_get_bounds (text_buffer, &begin, &end);

    self->invalid_begin = gtk_text_buffer_create_mark (text_buffer, NULL, &begin, TRUE);
    self->invalid_end = gtk_text_buffer_create_mark (text_buffer, NULL, &end, FALSE);

    ide_highlight_engine_reload (self);

    IDE_EXIT;
}
static gboolean
looks_like_makefile (IdeBuffer *buffer)
{
  GtkSourceLanguage *language;
  const gchar *path;
  IdeFile *file;

  g_assert (IDE_IS_BUFFER (buffer));

  file = ide_buffer_get_file (buffer);
  path = ide_file_get_path (file);

  if (path != NULL)
    {
      if (g_str_has_suffix (path, "Makefile.am") || g_str_has_suffix (path, ".mk"))
        return TRUE;
    }

  language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (buffer));

  if (language != NULL)
    {
      const gchar *lang_id;

      lang_id = gtk_source_language_get_id (language);

      if (ide_str_equal0 (lang_id, "automake") || ide_str_equal0 (lang_id, "makefile"))
        return TRUE;
    }

  return FALSE;
}
static void
gbp_line_spacing_buffer_addin_load (IdeBufferAddin *addin,
                                    IdeBuffer      *buffer)
{
  GbpLineSpacingBufferAddin *self = (GbpLineSpacingBufferAddin *)addin;

  g_assert (GBP_IS_LINE_SPACING_BUFFER_ADDIN (self));
  g_assert (IDE_IS_BUFFER (buffer));

  self->buffer = buffer;
  self->settings = g_settings_new ("org.gnome.builder.editor");

  g_signal_connect_object (self->settings,
                           "changed::line-spacing",
                           G_CALLBACK (on_line_spacing_changed_cb),
                           self,
                           G_CONNECT_SWAPPED);

  on_line_spacing_changed_cb (self, NULL, self->settings);

  g_signal_connect_object (self->buffer,
                           "changed",
                           G_CALLBACK (on_buffer_changed_cb),
                           self,
                           G_CONNECT_SWAPPED);
}
示例#8
0
void
_ide_project_edit_prepare (IdeProjectEdit *self,
                           IdeBuffer      *buffer)
{
  IdeProjectEditPrivate *priv = ide_project_edit_get_instance_private (self);
  IdeSourceLocation *begin;
  IdeSourceLocation *end;
  GtkTextIter begin_iter;
  GtkTextIter end_iter;

  g_assert (IDE_IS_PROJECT_EDIT (self));
  g_assert (IDE_IS_BUFFER (buffer));

  begin = ide_source_range_get_begin (priv->range);
  end = ide_source_range_get_end (priv->range);

  ide_buffer_get_iter_at_source_location (buffer, &begin_iter, begin);
  ide_buffer_get_iter_at_source_location (buffer, &end_iter, end);

  priv->begin_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (buffer),
                                                  NULL,
                                                  &begin_iter,
                                                  TRUE);

  priv->end_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (buffer),
                                                NULL,
                                                &end_iter,
                                                FALSE);
}
static void
on_load_buffer (GbpEditorWorkspaceAddin *self,
                IdeBuffer               *buffer,
                gboolean                 create_new_view,
                IdeBufferManager        *buffer_manager)
{
  g_autofree gchar *title = NULL;

  g_assert (GBP_IS_EDITOR_WORKSPACE_ADDIN (self));
  g_assert (IDE_IS_BUFFER (buffer));
  g_assert (IDE_IS_BUFFER_MANAGER (buffer_manager));

  /* We only want to create a new view when the buffer is originally created,
   * not when it's reloaded.
   */
  if (!create_new_view)
    return;

  /* If another workspace is active and it has an editor surface, then we
   * don't want to open the buffer in this window.
   */
  if (!is_topmost_workspace_with_editor (self))
    return;

  title = ide_buffer_dup_title (buffer);
  g_debug ("Loading editor page for \"%s\"", title);

  ide_editor_surface_focus_buffer (self->surface, buffer);
}
static void
buffer_insert_text_after_cb (GbpGitBufferChangeMonitor *self,
                             GtkTextIter               *location,
                             gchar                     *text,
                             gint                       len,
                             IdeBuffer                 *buffer)
{
  guint line;

  g_assert (GBP_IS_GIT_BUFFER_CHANGE_MONITOR (self));
  g_assert (location != NULL);
  g_assert (text != NULL);
  g_assert (IDE_IS_BUFFER (buffer));

  /*
   * We need to recalculate the diff when text is inserted if:
   *
   * 1) A newline is included in the text.
   * 2) The line currently has flags of NONE.
   *
   * Technically we need to do it on every change to be more correct, but that
   * wastes a lot of power. So instead, we'll be a bit lazy about it here and
   * pick up the other changes on a much more conservative timeout
   */

  line = gtk_text_iter_get_line (location);

  if (self->cache == NULL ||
      NULL != memmem (text, len, "\n", 1) ||
      !line_cache_get_mark (self->cache, line))
    gbp_git_buffer_change_monitor_queue_update (self, FAST);
}
示例#11
0
static void
gbp_git_buffer_addin_file_laoded (IdeBufferAddin *addin,
                                  IdeBuffer      *buffer,
                                  GFile          *file)
{
  GbpGitBufferAddin *self = (GbpGitBufferAddin *)addin;
  g_autoptr(IdeBufferChangeMonitor) monitor = NULL;
  g_autoptr(IdeContext) context = NULL;
  IpcGitRepository *repository;
  IdeObjectBox *box;
  IdeVcs *vcs;

  g_assert (GBP_IS_GIT_BUFFER_ADDIN (self));
  g_assert (IDE_IS_BUFFER (buffer));
  g_assert (G_IS_FILE (file));

  if (!(context = ide_buffer_ref_context (buffer)) ||
      !(vcs = ide_context_peek_child_typed (context, IDE_TYPE_VCS)) ||
      !GBP_IS_GIT_VCS (vcs) ||
      !(repository = gbp_git_vcs_get_repository (GBP_GIT_VCS (vcs))) ||
      !(monitor = gbp_git_buffer_change_monitor_new (buffer, repository, file, NULL, NULL)))
    return;

  ide_clear_and_destroy_object (&self->monitor);
  self->monitor = g_steal_pointer (&monitor);

  box = ide_object_box_from_object (G_OBJECT (buffer));
  ide_object_append (IDE_OBJECT (box), IDE_OBJECT (self->monitor));
  ide_buffer_set_change_monitor (buffer, self->monitor);
}
示例#12
0
static gboolean
ide_editor_perspective_focus_if_found (IdeEditorPerspective *self,
                                       IdeBuffer            *buffer,
                                       gboolean              any_stack)
{
  IdeLayoutStack *stack;
  struct {
    IdeBuffer     *buffer;
    IdeLayoutView *view;
  } lookup = { buffer };

  g_return_val_if_fail (IDE_IS_EDITOR_PERSPECTIVE (self), FALSE);
  g_return_val_if_fail (IDE_IS_BUFFER (buffer), FALSE);

  stack = ide_layout_grid_get_current_stack (self->grid);

  if (any_stack)
    ide_layout_grid_foreach_view (self->grid, locate_view_for_buffer, &lookup);
  else
    ide_layout_stack_foreach_view (stack, locate_view_for_buffer, &lookup);

  if (lookup.view != NULL)
    {
      stack = IDE_LAYOUT_STACK (gtk_widget_get_ancestor (GTK_WIDGET (lookup.view),
                                                         IDE_TYPE_LAYOUT_STACK));
      ide_layout_stack_set_visible_child (stack, lookup.view);
      gtk_widget_grab_focus (GTK_WIDGET (lookup.view));
      return TRUE;
    }

  return FALSE;
}
示例#13
0
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);
    }
}
IdeBufferChangeMonitor *
gbp_git_buffer_change_monitor_new (IdeBuffer         *buffer,
                                   IpcGitRepository  *repository,
                                   GFile             *file,
                                   GCancellable      *cancellable,
                                   GError           **error)
{
  GbpGitBufferChangeMonitor *ret;
  g_autoptr(IpcGitChangeMonitor) proxy = NULL;
  g_autoptr(IdeContext) context = NULL;
  g_autoptr(GFile) workdir = NULL;
  g_autofree gchar *relative_path = NULL;
  g_autofree gchar *obj_path = NULL;
  GDBusConnection *connection;

  g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL);
  g_return_val_if_fail (IDE_IS_BUFFER (buffer), NULL);
  g_return_val_if_fail (G_IS_FILE (file), NULL);
  g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);

  context = ide_buffer_ref_context (buffer);
  workdir = ide_context_ref_workdir (context);

  if (!g_file_has_prefix (file, workdir))
    {
      g_set_error (error,
                   G_IO_ERROR,
                   G_IO_ERROR_NOT_SUPPORTED,
                   "Cannot monitor files outside the working directory");
      return NULL;
    }

  relative_path = g_file_get_relative_path (workdir, file);

  if (!ipc_git_repository_call_create_change_monitor_sync (repository,
                                                           relative_path,
                                                           &obj_path,
                                                           cancellable,
                                                           error))
    return NULL;

  connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (repository));

  if (!(proxy = ipc_git_change_monitor_proxy_new_sync (connection,
                                                       G_DBUS_PROXY_FLAGS_NONE,
                                                       NULL,
                                                       obj_path,
                                                       cancellable,
                                                       error)))
    return NULL;

  ret = g_object_new (GBP_TYPE_GIT_BUFFER_CHANGE_MONITOR,
                      "buffer", buffer,
                      NULL);
  ret->proxy = g_steal_pointer (&proxy);

  return IDE_BUFFER_CHANGE_MONITOR (g_steal_pointer (&ret));
}
示例#15
0
static void
ide_source_map__buffer_line_flags_changed (IdeSourceMap *self,
                                           IdeBuffer    *buffer)
{
  g_assert (IDE_IS_SOURCE_MAP (self));
  g_assert (IDE_IS_BUFFER (buffer));

  gtk_source_gutter_renderer_queue_draw (self->line_renderer);
}
static void
buffer_changed_after_cb (GbpGitBufferChangeMonitor *self,
                         IdeBuffer                 *buffer)
{
  g_assert (IDE_IS_BUFFER_CHANGE_MONITOR (self));
  g_assert (IDE_IS_BUFFER (buffer));

  gbp_git_buffer_change_monitor_queue_update (self, SLOW);
}
static void
on_buffer_changed_cb (GbpLineSpacingBufferAddin *self,
                      IdeBuffer                 *buffer)
{
  g_assert (GBP_IS_LINE_SPACING_BUFFER_ADDIN (self));
  g_assert (IDE_IS_BUFFER (buffer));

  if (self->tag != NULL)
    gbp_line_spacing_buffer_addin_apply (self);
}
示例#18
0
/**
 * ide_editor_frame_get_document:
 *
 * Gets the #IdeEditorFrame:document property.
 *
 * Returns: (transfer none) (nullable): An #IdeBuffer or %NULL.
 */
IdeBuffer *
ide_editor_frame_get_document (IdeEditorFrame *self)
{
  GtkTextBuffer *buffer;

  g_return_val_if_fail (IDE_IS_EDITOR_FRAME (self), NULL);

  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->source_view));

  return IDE_IS_BUFFER (buffer) ? IDE_BUFFER (buffer) : NULL;
}
static void
ide_xml_highlighter_set_buffer (IdeXmlHighlighter *highlighter,
                                IdeBuffer         *buffer)
{
  IdeXmlHighlighter *self = (IdeXmlHighlighter *)highlighter;

  g_assert (IDE_IS_HIGHLIGHTER (self));
  g_assert (!buffer || IDE_IS_BUFFER (buffer));

  egg_signal_group_set_target (self->signal_group, buffer);
}
static void
gbp_line_spacing_buffer_addin_apply (GbpLineSpacingBufferAddin *self)
{
  GtkTextIter begin;
  GtkTextIter end;

  g_assert (IDE_IS_BUFFER (self->buffer));
  g_assert (GTK_IS_TEXT_TAG (self->tag));

  gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (self->buffer), &begin, &end);
  gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (self->buffer), self->tag, &begin, &end);
}
static void
ide_autotools_build_system__buffer_saved_cb (IdeAutotoolsBuildSystem *self,
                                             IdeBuffer               *buffer,
                                             IdeBufferManager        *buffer_manager)
{
  g_assert (IDE_IS_AUTOTOOLS_BUILD_SYSTEM (self));
  g_assert (IDE_IS_BUFFER (buffer));
  g_assert (IDE_IS_BUFFER_MANAGER (buffer_manager));

  if (looks_like_makefile (buffer))
    egg_task_cache_evict (self->task_cache, MAKECACHE_KEY);
}
static void
gbp_git_buffer_change_monitor_load (IdeBufferChangeMonitor *monitor,
                                    IdeBuffer              *buffer)
{
  GbpGitBufferChangeMonitor *self = (GbpGitBufferChangeMonitor *)monitor;

  g_assert (IDE_IS_MAIN_THREAD ());
  g_assert (GBP_IS_GIT_BUFFER_CHANGE_MONITOR (self));
  g_assert (IDE_IS_BUFFER (buffer));

  dzl_signal_group_set_target (self->buffer_signals, buffer);
  gbp_git_buffer_change_monitor_queue_update (self, FAST);
}
static void
ide_buffer_change_monitor_set_buffer (IdeBufferChangeMonitor *self,
                                      IdeBuffer              *buffer)
{
  g_return_if_fail (IDE_IS_BUFFER_CHANGE_MONITOR (self));
  g_return_if_fail (IDE_IS_BUFFER (buffer));

  if (IDE_BUFFER_CHANGE_MONITOR_GET_CLASS (self)->set_buffer)
    IDE_BUFFER_CHANGE_MONITOR_GET_CLASS (self)->set_buffer (self, buffer);
  else
    g_warning ("%s does not implement set_buffer() vfunc",
               g_type_name (G_TYPE_FROM_INSTANCE (self)));
}
IdeHighlightEngine *
ide_highlight_engine_new (IdeBuffer *buffer)
{
    IdeContext *context;

    g_return_val_if_fail (IDE_IS_BUFFER (buffer), NULL);

    context = ide_buffer_get_context (buffer);

    return g_object_new (IDE_TYPE_HIGHLIGHT_ENGINE,
                         "buffer", buffer,
                         "context", context,
                         NULL);
}
示例#25
0
static void
ide_source_map__view_notify_buffer (IdeSourceMap  *self,
                                    GParamSpec    *pspec,
                                    GtkSourceView *view)
{
  GtkTextBuffer *buffer;

  g_assert (IDE_IS_SOURCE_MAP (self));
  g_assert (GTK_SOURCE_IS_VIEW (view));

  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
  if (IDE_IS_BUFFER (buffer))
    dzl_signal_group_set_target (self->buffer_signals, buffer);
}
示例#26
0
static void
gbp_git_buffer_addin_unload (IdeBufferAddin *addin,
                             IdeBuffer      *buffer)
{
  GbpGitBufferAddin *self = (GbpGitBufferAddin *)addin;

  g_assert (GBP_IS_GIT_BUFFER_ADDIN (self));
  g_assert (IDE_IS_BUFFER (buffer));

  if (self->monitor != NULL)
    {
      ide_buffer_set_change_monitor (buffer, NULL);
      ide_clear_and_destroy_object (&self->monitor);
    }
}
示例#27
0
static GtkTextTag *
get_misspelled_tag (GbpSpellNavigator *self)
{
  IdeBufferAddin *buffer_addin;

  g_assert (GBP_IS_SPELL_NAVIGATOR (self));
  g_assert (self->buffer != NULL);
  g_assert (IDE_IS_BUFFER (self->buffer));

  buffer_addin = ide_buffer_addin_find_by_module_name (IDE_BUFFER (self->buffer), "spellcheck-plugin");
  if (buffer_addin != NULL)
    return gbp_spell_buffer_addin_get_misspelled_tag (GBP_SPELL_BUFFER_ADDIN (buffer_addin));

  return NULL;
}
static void
ide_highlight_engine__notify_language_cb (IdeHighlightEngine *self,
        GParamSpec         *pspec,
        IdeBuffer          *buffer)
{
    GtkSourceLanguage *language;
    const gchar *lang_id = NULL;

    g_assert (IDE_IS_HIGHLIGHT_ENGINE (self));
    g_assert (IDE_IS_BUFFER (buffer));

    if ((language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (buffer))))
        lang_id = gtk_source_language_get_id (language);

    ide_extension_adapter_set_value (self->extension, lang_id);
}
static void
ide_highlight_engine_set_buffer (IdeHighlightEngine *self,
                                 IdeBuffer          *buffer)
{
    g_assert (IDE_IS_HIGHLIGHT_ENGINE (self));
    g_assert (!buffer || GTK_IS_TEXT_BUFFER (buffer));

    /*
     * We can get GtkSourceBuffer intermittently here.
     */
    if (!buffer || IDE_IS_BUFFER (buffer))
    {
        egg_signal_group_set_target (self->signal_group, buffer);
        g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_BUFFER]);
    }
}
示例#30
0
/**
 * ide_vcs_get_buffer_change_monitor:
 *
 * Gets an #IdeBufferChangeMonitor for the buffer provided. If the #IdeVcs implementation does not
 * support change monitoring, or cannot for the current file, then %NULL is returned.
 *
 * Returns: (transfer full) (nullable): An #IdeBufferChangeMonitor or %NULL.
 */
IdeBufferChangeMonitor *
ide_vcs_get_buffer_change_monitor (IdeVcs    *self,
                                   IdeBuffer *buffer)
{
  IdeBufferChangeMonitor *ret = NULL;

  g_return_val_if_fail (IDE_IS_VCS (self), NULL);
  g_return_val_if_fail (IDE_IS_BUFFER (buffer), NULL);

  if (IDE_VCS_GET_IFACE (self)->get_buffer_change_monitor)
    ret = IDE_VCS_GET_IFACE (self)->get_buffer_change_monitor (self, buffer);

  g_return_val_if_fail (!ret || IDE_IS_BUFFER_CHANGE_MONITOR (ret), NULL);

  return ret;
}