Here's a summary of my work at the Boston Hackfest.
Before I continue, I'd like to thank everyone who donated their money or time to support this Hackfest. This has been a really useful event - it's so much easier to deal with tricky design challenges and project management stuff when we can meet face to face. It has also brought together people with very diverse expertise across the project (UI, web, build, extensions, project management etc). This week, we've figured out a path to deliver long desired features (multipage support etc), roadmapped our final route to deliver Inkscape 1.0, done some great website design work, and handled some tricky code structure issues that I'll discuss in this message.
If you're able to donate some money to support Inkscape, and future Hackfests, we really appreciate this. You can find the donation link on our website: https://inkscape.org/en/support-us/hackfests/
It would also be great to get some more of the regular contributors from our wider community to join us at future events (i.e., designers, bug-team, experienced users... not just C++ developers!). The developers can learn so much more about the project by discussing it with you.
So... what have I been doing this week?
== What are Actions? ==
Basically, an "action" is a thing that Inkscape can do (e.g., flip an object horizontally), which we can identify using an ID code (e.g., "SP_VERB_OBJECT_FLIP_HORIZONTAL"). We can then hook up buttons, menu items etc to activate these actions. In this example, we would set up our Flip Horizontal button in the select-tool toolbar so that when the user clicks it, it activates the required action.
My work this week has focused on improving the way we implement actions in our code, which will
- Allow Inkscape to run on machines with future versions of the Gtk+ library (Gtk 4+)
- Provide much better separation between the behaviour and user interface (i.e.,, separate pieces of the code will describe what Inkscape "does", and what it "looks like")
- Make it much easier to create new "flavours" of the Inkscape user interface - for example, an "Inkscape for Kids" or "Inkscape CAD"
- Make it easier for "non-programmers" to create and reorganise custom toolbars and dialogs
- Allow us to remove a lot of older "C" code that is very difficult for current "C++" developers to maintain
== Where we are now? ==
In the Inkscape code, we have a mechanism called "verbs" that acts as a kind of action mechanism... it provides a way of using an ID code to look up the required commands to perform an action.
On top of this, we have another structure called SPAction that essentially hooks up a couple of signals to the verb.
Finally(ish), we use objects called GtkActions from the Gtk+ library, which let us create GUI elements (buttons etc) that we can add to our menus or toolbars that activate the required action.
We have also got a few custom sub-classes of GtkAction that let us create special kinds of tool-item that can activate actions... for example, one of these creates a spin-button (a box with a number in it, and "up/down" arrows) that can also handle units, basic arithmetic, and provides a label.
== What's the problem? ==
First, the GtkAction widget (and hence all our custom sub-classes) is deprecated and has been removed from Gtk+ 4, so we need to change. Since Inkscape 1.0 is intended as a "stable" release, we want to make it as future-proof as possible.
The main reason for this deprecation is that the GtkAction widget is a slightly weird mix of paradigms: it mixes information about how to display a tool/menu item with information about behaviour. This causes some problems... what if we wanted to run a "headless" Inkscape on a system that has no display? What if we wanted to provide several different GUI options for different kinds of user to trigger the same behaviour?
This is one of the reasons why we have the "verbs" system is in place, as it separates behaviour from the GUI. However, there is still quite a lot of code "overhead" needed if we want to hook up Inkscape's Verb behaviour to a GUI element. Essentially, it's "programmers only" territory. What if a designer wanted to add a new toolbar button to their Inkscape to handle a useful feature that is currently buried deep in a menu? What if a teacher wanted to strip out a lot of "advanced" behaviour from the interface to make it easier to introduce Inkscape to their class? At the moment, they have to edit the C++ code, and recompile it... a slow and complicated process!
== Where are we going? ==
We need to move to using GActions (a feature in the Glib/GIO library). This *only* describes the action's behaviour and provides an "activated" signal that we can trigger by simply knowing the action's name. This is completely separated from the GUI. These actions can be activated very easily from a whole range of places, for example:
- By attaching the action's name to a GUI element in the C++ code (replacing our SPAction/GtkAction code)
- By activating the action (using its name) from a command-line interface (replacing some of our verbs code)
- By attaching the action's name to elements in a customised GUI file
- From external applications, using the DBus system
Number 3 in the list provides some very exciting opportunities for future releases, as non-programmers will be able to make a customised user interface by drawing one in the Glade application. You then just attach the name of the required Inkscape action to each GUI element. Want a new button? Just edit Inkscape's user-interface file in Glade and see the changes immediately next time you start... no C++ knowledge needed!
== What have I done so far? ==
I've started working through Inkscape's toolbars, and have replaced the deprecated GtkAction-based widgets with standard widgets (buttons etc). Some of these now hook up to GAction descriptions of behaviour, while others are just based on handling GUI signals (e.g., Button::clicked).
So far, I have migrated the toolbars for the Select, Dropper and Connector toolbar, and have killed off a couple of the custom GtkAction-based widgets that were only used in these.
In the process, I have also migrated the toolbar code to C++, which should make it a little easier for the current core developers to maintain. Since all the data is now stored as C++ member variables, rather than as GObject data, we now benefit from better compile-time and run-time type-checking that will help to safeguard against errors being introduced in the code in future.
I have placed the updated toolbars in the Inkscape::UI::Toolbar namespace and made them into proper sub-classes of the Gtk::Toolbar class.