A new gutter for Builder

The GtkSourceView library has this handy concept of a GtkSourceGutterRenderer. They are similar in concept to a GtkCellRenderer but for the gutter to the left or right of the text editor.

Like a GtkCellRenderer, you pack it into a container and they are placed one after another with some amount of optional spacing in-between. This is convenient because you can start quickly by mixing and matching what you need from existing components. Those include text (such as line numbers), pixbuf rendering, or even code folding regions.

However, there is a cost to this sort of composition. One is function call overhead, but that isn’t particularly interesting to me because there are ways to amortize that away (like we did with the pixel cache). The real problem is one of physical space. Each time a renderer is added, the width of the gutter is increased.

Builder 3.26.0 added a new column for breakpoints, and so we increased our width by another 18 pixels or so. Enough to be cumbersome. It looked like the following which has 4 renderers displayed.

  • Breakpoints renderer
  • Diagnostics renderer
  • Line numbers
  • Line changes (git)

Once you reach some level of complexity, you need to bite the bullet and implement a single renderer that has all the features you want in one place. It allows you to overlap content for density and use the background itself as a component. We just did that for Builder and here is what it looks like.

There are a couple other nice points performance-wise by implementing the gutter as a single renderer. We can take a number of “shortcuts” in the render path that a generic renderer cannot without sacrificing flexibility. Since the gutter is not pixel cached, this has improved the performance of kinetic scrolling on various HiDPI displays. There is always more performance work to do, but I’m rather happy with the result so far.

You’ll find this in the upcoming 3.26.1 release of Builder and is already available in Builder’s Nightly flatpak.

Builder 3.26 Sightings

We’re getting close to 3.26 and a number of features have landed. Let’s take a quick screenshot tour to see what you’re likely to see in 3.26.

Most of us have seen the new visual design by now

Visual refresh

A modest debugger

A debugger for Builder

Integrated Symbol Search by GSoC student Anoop Chandu

symbol search

Inline Documentation by GSoC student Lucie Charvát

Inline documentation

Word Completion based on distance from cursor by GSoC student Umang Jain

word completion

I expect the word completion to gain some fancy features like following #include files and custom sort ordering which will look and feel similar to Vim users.

This week in Builder

I’ve been aggressively pushing forward our new layout branch to integrate the new design work we’ve been iterating on. I don’t think we need to have it all done to merge to master, so we are rapidly approaching the time-frame for the branch to land.

There is much from the design still missing, but every day more pieces come together. I expect to have a good portion of it done by GUADEC.

A lot happened this week on the wip/chergert/layout branch. Here are some highlights.

  • Georges landed a “focus mode” fullscreen mode for Builder.
  • We’ve landed a patch in flatpak-builder to update terminal titles. This will allow us to scrape that info via the PTY in Builder for better progress messages.
  • Document titlebars now match the primary-color of the content. We also fade between states. This took some craftiness to avoid cascading the entire CSS tree. Video example below.
  • DzlPropertiesGroup is a convenient GActionGroup implementation for exporting multiple object properties from a GObject. This is more convenient than GPropertyAction when you are exposing lots of properties together.
  • The TODO plugin was ported to C and employs various techniques to use reduce memory overhead.
  • Dazzle gained convenience API to do insertion sort on a GtkListStore in O(log n) time by accessing the GSequence directly. This should be a safe layer-violation on Gtk+ 3.x.
  • Terminal, Devhelp, and HTML-Preview were ported to the new layout design.
  • IdeSymbolResolver gained a “find nearest scope” API which is used to update the scope name in the document titlebar. Both C and Vala are supported. Other languages need an implementation still.
  • The project tree was tweaked to look more like the mockup. While this won’t be our default project-tree for 3.26, we will keep it around and therefore it should match the design.
  • Overview map was ported to the new layout design.
  • Plugins should use the new IdeBuffer::change-settled API to be notified of when they should update their state based on buffer content (unless alternate API is provided via the plugin interface).
  • We’ve added type icons to the devhelp search that match the language-feature icons used elsewhere in Builder.
  • Scrolling to the insertion point on buffer load has been vastly improved.
  • Performance of buffer loading has also improved.
  • Todo and build diagnostics have been ported to the new design.

Reflowing text in GtkTreeView

You can do some pretty evil things with GtkTreeView if you put your mind to it. One of the most common questions over the years has been how to reflow (wrap) text. The short answer is you can’t. The answer for those willing to hack around it is something like:

So the real question is “Why not use GtkListBox?”

GtkListBox is a fantastic widget. But there are some things it does not deal well with today. I presume that once it can deal with only keeping a minimum number of widgets in memory (and the size-request magic that goes with it) it would be a better solution.

Builder keeps a lot of widgets active during the lifetime of the application, and that makes style propagation particularly slow. The fewer widgets we can use, the more responsive we can keep things. (And of course, there are multiple ways to do this).

evil tree view
evil cell renderer

Troubleshooting Builder

If you find yourself needing to troubleshoot Builder (hopefully just during our development cycles) you can now run the command “counters” from the command bar (Ctrl+Enter). This gives you access to some internal counters.

You can get these out of process too, using dazzle-list-counters PID which cracks open the shared memory page and dumps the counters.

A screenshot of the counters displayed for the program.

As you might imagine, the counters are in libdazzle now so you can have the same sort of feature in your (C-based) applications quite easily.

JCON – Part 2

I just finished the JCON_EXTRACT() support and it is already making my consumption of JSON easier. Here is an example:

g_autoptr(JsonNode) node = NULL;
JsonArray *ar = NULL;
gboolean success;

node = JCON_NEW (
  "foo", "{",
    "bar", "[", JCON_INT (1), JCON_INT (2), "]",
  "}"
);

success = JCON_EXTRACT (node,
  "foo", "{",
    "bar", JCONE_ARRAY (ar),
  "}"
);

And for now, you can just copy/paste the jcon.c and jcon.h files into your project, but I’d expect to come up with a patch we can push into json-glib at some point. It really belongs there.

JCON

Years ago during my tenure at MongoDB I worked on a couple libraries. Notably the libbson and mongo-c-driver libraries. One neat feature we had was this concept called BCON which stood for BSON C Object Notation. It was a succinct format for creating BSON documents that made it easier to reason about what you were creating.

So I decided to do the same thing this evening around json-glib because I found I was writing a lot of code to create objects/arrays/etc.

It looks something like this

g_autoptr(JsonNode) params = NULL;

params = JCON_NEW (                                                      
  "changes", "["                                                         
    "{",                                                                 
      "uri", JCON_STRING (src_uri),                                      
      "type", JCON_INT (FILE_CHANGE_TYPE_DELETED),                       
    "}",                                                                 
    "{",                                                                 
      "uri", JCON_STRING (dst_uri),                                      
      "type", JCON_INT (FILE_CHANGE_TYPE_CREATED),                       
    "}",                                                                 
  "]"                                                                    
);                                                                       

Since this uses va_list it’s technically less type safe than your other options. But it uses some magic struct initializers to get things in a situation where we can bail at runtime if you did something wrong.

The other half that I’m currently still missing is the extraction support. If you replace JCON_NEW() with JCON_EXTRACT(node) and the values with pointers to values, you can quickly extract documents.

But that’s not done yet… so for next time…

jcon.h jcon.c

LAS, hosted by GNOME

Sri and many members of our community have spearheaded a wonderful new conference named Libre Application Summit. It’s hosted by the GNOME Foundation and has aspirations to bring together a wide spectrum of contributors.

This conference is meant to bridge a gap in Free Software communication. We need a place for application and game developers, desktop developers, systems implementers, distributions, hardware producers, and driver developers to communicate and solve problems face to face. There are so many moving parts to a modern operating system that it is very rare to have all of these passionate people in the same room.

This will be a great place to learn about how to contribute to these technologies as well. It seems likely that I’ll do tutorial workshops and other training for participants at LAS.

I’m very excited to see where this conference goes and hope to see you in Portland come September!