GtkSourceGutter - 如何在特定行上呈现图标或文本

GtkSourceGutter - How to render icon or text on a specific line

我已插入自定义 gtk 源装订线渲染器 pixbuf,我想在特定行上渲染图标。

参考文献 API 指出该界面与 GtkTreeView 上的界面非常相似,但不适用于树模型。 那么...如果 GtkSourceGutter 不适用于树模型,我应该如何将数据呈现到特定行?

我检查了整个库中的每个函数,每个建议的 api 和子对象,甚至没有任何提示。

只是没有意义。手册页说 GtkSourceGutterRendererPixbuf 用于在 CELL 中显示图标。 执行 gtk_source_gutter_renderer_pixbuf_set_pixbuf(renderer, pixbuf); 将呈现装订线中所有单元格的图标。 如果唯一的方法是使用 cairo 手动绘制 pixbuf ..那些渲染器有什么意义?

如何使用 gtksourcegutterrenderer 在特定行 中渲染 pixbuf


我没有使用过 GtkSourceView,但我可以给你一些线索。


GtkSourceView作者是怎么做到的

首先,我们需要一些链接:

让我们从 GtkSourceGutterRendererPixbuf 开始。从它的 class_init 方法我们发现,它仅覆盖 draw 方法。它的唯一目的是渲染一个 pixbuf 或图标。纯绘图.

但是,GtkSourceGutterRenderer 文档说,有一个 query-data 信号可用于调整渲染器的内部状态。此时我们应该看一下继承自RendererPixbuf 的GtkSourceGutterRendererMarks。它不会覆盖 draw,但会覆盖 query_data(由于某些原因GtkSourceGutterRendererClass在文档中没有描述。我不知道为什么。)

/* Read my comments. */
static void
gutter_renderer_query_data (GtkSourceGutterRenderer      *renderer,
                            GtkTextIter                  *start,
                            GtkTextIter                  *end,
                            GtkSourceGutterRendererState  state)
{
  GSList *marks;
  GdkPixbuf *pixbuf = NULL;
  
  view = GTK_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
  buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));

  marks = gtk_source_buffer_get_source_marks_at_iter (buffer,
                                                      start,
                                                      NULL);
  
  /* If there are marks, we find a pixbuf for one of them. 
   * Otherwise pixbuf is NULL. */
  if (marks != NULL)
  {
    size = measure_line_height (view);
    pixbuf = composite_marks (view, marks, size);

    g_slist_free (marks);
  }
  
  /* Now tell parent class to render certain pixbuf
   * It will render nothing if pixbuf is NULL. */
  g_object_set (G_OBJECT (renderer),
                   "pixbuf", pixbuf,
                   NULL);
}

我的建议。

您想在某些行绘制标记(例如,想突出显示当前调试器行)。如果我是你,我会继承 RendererPixbuf,覆盖 query_data 并在 GtkTextIter *start 上使用 gtk_text_iter_get_line。看起来这是最低限度。

如有任何问题,请随时提出。

我个人不能简单地同意创建自定义对象很容易的说法。这并不容易,对每个人来说都不是。

主要是因为,这个问题被标记了c,不了解面向对象编程的人可能不熟悉它的概念。

这是一个阅读和练习的问题。

因此,如果您不知道如何创建自己的小部件,请不要惊慌。

我能想到的最简单的解决方案,不涉及创建自己的渲染器,而是告诉渲染器如何查询渲染数据。

只需将 GtkSourceGutterRenderer 上的 query-data 信号连接到如下所示的信号处理程序:

G_MODULE_EXPORT void gutter_renderer_query_data (GtkSourceGutterRenderer *renderer, GtkTextIter *start, GtkTextIter *end, GtkSourceGutterRendererState state)
{
    GtkSourceView*      view    = NULL;
    GtkSourceBuffer*    buffer  = NULL;
    GSList*             marks   = NULL;
    GdkPixbuf*          pixbuf  = NULL;

    view    = GTK_SOURCE_VIEW(gtk_source_gutter_renderer_get_view(renderer));
    buffer  = GTK_SOURCE_BUFFER(gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)));

    marks   = gtk_source_buffer_get_source_marks_at_iter(buffer, start, NULL);

    if(marks != NULL)
    {
        char *category = gtk_source_mark_get_category(marks->data);

        if(!g_strcmp0(category, "CERTAIN_CATEGORY")) /* See note 1) */
            pixbuf = gtk_image_get_pixbuf(gtk_image_new_from_file("icon_file_here")); /* See note 2) */

        g_slist_free(marks);
    }

    g_object_set(G_OBJECT(renderer), "pixbuf", pixbuf, "yalign", 0.5, NULL);
}

备注:

  1. GtkSourceMark 共享 GtkSourceGutterRenderer 接口,因此您可能希望通过指定应用于特定行的源标记类别来过滤其他源标记。否则您的自定义渲染器 pixbuf 也将被渲染留给您的其他源标记。

  2. 您应该指定要在内部呈现的确切 pixbuf。这样做,您不必调用 gtk_source_gutter_renderer_pixbuf_set_pixbuf() 。您让 API 进行资源处理。