Tabbed Document Interface framework for GtkSourceView

Currently the GtkSourceView library is not aware of multiple documents. Most text editors and IDEs have a Tabbed Document Interface (TDI). A TDI framework in GtkSourceView would ease the implementation of text editors.

A related project is to make the gedit source code more reusable.

In GtkSourceView there would be the low-level API (i.e. the current API, with the main classes GtkSourceView and GtkSourceBuffer). The TDI framework would be implemented as a higher-level API. The low-level API cannot depend on the high-level API, but the reverse is perfectly fine.

If the gedit code architecture is used, there would be the following classes: GtkSourceTab, GtkSourceNotebook, GtkSourceMultiNotebook (or GtkSourceStack and one or more GtkSourceStackSwitcher), and maybe GtkSourceStatusbar, GtkSourceWindow, GtkSourcePanel, GtkSourceApplication, etc.

For the latter classes, especially for GtkSourceApplication, it would probably not fit an IDE if GtkSourceApplication is a subclass of GtkApplication. If another library useful for an IDE (debugger, git, API browser, …) provides another GtkApplication subclass, which one to choose? So at least for the application class, but maybe also for the main window, the re-usable features provided by a library should be used by composition, not by inheritance.

Such a TDI framework (specific for text editors and IDEs) would provide higher-level APIs for features like the search and replace, or the file loading and saving. With the current APIs (GtkSourceSearchContext, GtkSourceFile, …), there is still quite a lot of work to do in the applications. There could be a simple boolean property to have automagically a decent search and replace UI for your text editor!

Of course, if such a TDI framework is created, we must ensure that the framework is useful for a wide range of applications: gedit, gnome-builder, LaTeXila, gCSVedit, etc.

Taking the gedit core as a starting point

gedit has a quite simple code architecture (when you look only at the *.h public files) and is a small text editor (if you don't take the plugin system into account). It's a small text editor, but it takes care of lots of details, such as error handling, showing progress bars, etc etc. So the gedit core is a good starting point for creating the TDI framework.

Where to put the re-usable code?

The gedit core needs to be refactored to make the code re-usable. Once a code is re-usable, there are several places where it could go:

  1. In GtkSourceView, as unstable API (at least at the beginning).

  2. In a separate directory inside gedit. Drawback: other text editors need to manually copy/paste the code and translations.
  3. In a git submodule. Drawback: handling translations and GTK-Doc is more complicated.
  4. In a new shared library with an unstable API (at least at the beginning).
  5. In a new shared library with a stable API but with a major version bump each time an API break is needed. It doesn't matter if we end up with libfoo-10 and if there are 10 different versions available in distros (it's also the distro job to remove old packages if they are no longer used).

The end goal is to have a stable API in GtkSourceView. But creating a framework needs many iterations to get it right. If there is only an unstable API available, applications are forced to keep track with the API changes, which can lead to a lot of maintenance work. So the option 5 has the advantage to have a stable API, and applications can be ported to the latest major version when the developers have the time. And maybe not so many API breaks would be actually needed.

About breaking gedit plugins

Once a code is re-usable, it needs to be used in a real-world text editor to see if the API is convenient to use and provide the right features. Since the plan is to take the gedit code as a basis for the TDI framework, the most natural thing to do is to port gedit to the new API, of course. But doing so can break gedit plugins if the gedit API is modified (as it was the case for the file loading and saving).

Breaking the gedit API frequently is not a good idea: most plugins are not ported when the new stable gedit version is released. Users then report bugs (including crashes) to the gedit bugzilla due to non-ported third-party plugins, and users are angry because they cannot use their favorite plugins with the latest gedit versions.

So, to test the new APIs of the TDI framework, it's maybe a better solution to choose another text editor which hasn't a plugin system. It would be roughly these steps: take a gedit class; make it re-usable and put it in the TDI framework; port the other text editor to the new API. Iterate this process until the TDI framework is more or less complete, or when we are confident about the API stability. Then port gedit to this new framework, by breaking the gedit plugin API only once. Not sure if it's a good idea, porting gedit at once can be a lot of work, and in the meantime the features are duplicated between gedit and the TDI framework.

Or, to not break gedit plugins, we must create an adapter between the gedit API and the TDI framework. Some of the gedit API could become deprecated in favor of the TDI framework, but if the TDI framework breaks its API, plugins will also be broken. So maybe the TDI framework API should not be exposed for plugins, and the gedit API tries to keep a stable API as long as possible.

Tepl

Done in the Tepl shared library.

Projects/GtkSourceView/TdiFramework (last edited 2017-09-11 09:46:14 by SébastienWilmet)