Using GTK's GResources with GtkD with DUB
hi, this is just a short post on how to use GResources in GtkD with DUB using the D programming language.
First we can create a gresources file and layout in the app, like you would do it in other apps. I have taken the example code from the GNOME Icon Library app which can give me a default layout:
Folder layout:
data/
+-- icons/
| +-- puzzle-piece-symbolic.svg
+-- ui/
| +-- main.ui
+-- resources.gresource.xml
data/resources.gresource.xml
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/example/MyApp">
<file>ui/main.ui</file>
<!--
GTK automatically searches in icons/ folder inside the app path.
See https://wiki.gnome.org/HowDoI/ThemedIcons#Automatic_resources
-->
<file preprocess="xml-stripblanks">icons/puzzle-piece-symbolic.svg</file>
</gresource>
</gresources>
Once you have your resource files layout setup we can actually generate the compiled gresources file using the glib-compile-resources
command line tool, which is included with glib. On ArchLinux the package for this is glib2
, on Ubuntu it should come with libglib2.0-bin
.
First off, let me explain the command we will introduce to our build:
glib-compile-resources --sourcedir=data data/resources.gresource.xml
glib-compile-resources
is a tool that bundles all of the resources we declared in our resources.gresource.xml
file into one big binary file that can be interpreted by GLib at runtime. The --sourcedir=data
makes it search for the resources in the data
directory instead of the current directory. We could also just cd
into the data directory and run the command from there, but this makes it easier to include the command in DUB as we will see in a second. The last argument is the gresource.xml file we want to parse, it tells the tool where all the assets to include are located.
Now to actually use this command on every build we can use DUB's preBuildCommands. In a dub.sdl
file that would be:
stringImportPaths "data"
preBuildCommands "glib-compile-resources --sourcedir=data --target=views/resources.gresource data/resources.gresource.xml"
or in dub.json
:
"stringImportPaths": ["data"],
"preBuildCommands": [
"glib-compile-resources --sourcedir=data --target=views/resources.gresource data/resources.gresource.xml"
]
We also add stringImportPaths
so dub triggers a recompilation every time something in that folder has changed as well as enabling us to use import("resources.gresource")
to copy the bytes of the generated file into the executable.
now in your D code create a shared static constructor which will tell GIO about the resource file:
shared static this()
{
import gio.Resource;
import glib.Bytes;
auto bytes = new Bytes(cast(ubyte[]) import("resources.gresource"));
Resource.register(new Resource(bytes));
}
This code uses import
to embed the bytes into the executable to not be required to use the filesystem.
And that's it! Now you can start using resources, here is an example app.d using GTK4 and libadwaita:
import gtk.Application,
gtk.Builder;
import adw.Window; // I'm using libadwaita, you want to use gtk.Window here
// instead if you use GtkWindow.
int main(string[] args)
{
Application app = new Application(
// make sure the casing is the same as in the paths for icons to work
"org.example.MyApp",
GApplicationFlags.FLAGS_NONE);
app.addOnActivate((gioApp) {
scope builder = new Builder();
builder.addFromResource("/org/example/MyApp/ui/main.ui");
Window window = cast(Window) builder.getObject("window");
assert(window, "did not define a window");
window.setApplication(app);
window.show();
});
return app.run(args);
}
shared static this()
{
import gio.Resource;
import glib.Bytes;
auto bytes = new Bytes(cast(ubyte[]) import("resources.gresource"));
Resource.register(new Resource(bytes));
}
Want to use LibAdwaita and GTK4 in your DUB project? Use my PR on d_adw https://github.com/KonstantIMP/d_adw/pull/1 which updates it to 1.0.0.alpha.3-1 and add the dependency line I wrote in my description there to use the last gtk4 commit from GtkD. This is more stable than using branches and doesn't make your project recheck the dependency every time you build.
Checkout LibAdwaita UI examples on https://gitlab.gnome.org/GNOME/libadwaita/-/tree/main/demo