Gfret Gtk4 Port Part 3
Earlier in the week, the preferences were brought back without too much
trouble. I've taken some time to do a bit of extra work to the public
API of the backend crate, fretboard_layout. Rather than
storing colors as a string, we now save the individual RGBA channel
values, and can do so using u8 or f64 storage types. This morning I
spent a little bit of time on making the file saving code a bit more
idiomatic and bringing the templates features back.
#[derive(Clone, Deserialize, Debug, Serialize)] pub struct HexColor { pub color: String, pub alpha: f64, } #[derive(Clone, Deserialize, Debug, Serialize)] pub struct RGBA { pub red: f64, pub green: f64, pub blue: f64, pub alpha: f64, } #[derive(Clone, Deserialize, Debug, Serialize)] pub struct ReducedRGBA { pub red: u8, pub green: u8, pub blue: u8, pub alpha: u8, } #[derive(Clone, Deserialize, Debug, Serialize)] #[serde(tag = "ColorType")] pub enum Color { Hex(HexColor), Reduced(ReducedRGBA), Rgba(RGBA), }
This is the storage types for color values. As can be seen, we're using
an enum here, but it turns out that the serde and
toml combination won't work here unless we specify a
tag for our Color enum. I've been bouncing
back and forth from Rust to Zig a lot lately, and this is interesting
to me. Instead of having an enum type which accepts
values, Zig has enum, union, and tagged
union types. An enum is just that, an enumerated
type, but without any storage. A union is roughly
equivalent to the C counterpart, but where things get interesting (and
indead very useful) is the tagged union type, which can be
used in many of the same ways as a Rust enum with
associated value. I've speculated before that under the hood the two
types function fairly similarly. In the case of Zig, one can
switch on the tag and extract the value as a
payload. Anyway, interesting to me that in serde we're
having to specify an external tag.
What's left
So there are three major things to reimplement before I'm calling feature parity with the gtk3 version. The preferences dialog needs to be able to get it's values from the saved configuration when it opens. Currently, the configuration is saved, but when the dialog is opened the widgets display default values.
Second, I need to reimplement loading of templates from the command
line when the program first loads. This is hampered right now by the
fact that in Gtk4, command line arguments are no longer passed into the
GtkApplication struct. Instead, it is expected that every
application will register with Dbus and be told through the system bus
when it is time to open a file. Well, I'm not a fan, at least not if
that's the only option. The solution I have in mind is to just check
whether we have a valid template file if one is requested on the
command line, and then copy it's contents into the
statefile before loading the gui. Not great, but look Ma,
no Dbus.
The last one is a little easier. I just need to hook the saved configuration back up to the CLI again.
There are a few minor differences like the menu items no longer having icons. The upstream devs are all very Gnome centric, and while I could still put them back in I'm not sure it's something that I care about.
Ah, one more major thing before feature parity actually. Keyboard shortcuts. But since I intend to make use of a gtk shortcut map and make them user configurable, this will actually be tied cosely to the mapped out upgrades planned for this cycle.
Upgrades
So let's talk upgrades then. The original Gfret only supported metric system measurements in spite of my being an "American". I'm going to go both the backend and gui and add support for Imperial measurements, because I'm sure that almost anyone besides myself in this country will want that. This is going to be a configuration option, not a runtime specification.
I'm also going to add the ability to do left handed designs. Logically speaking, there is no difference between a left and right handed fretboard assuming that we are looking at a monoscale design, so this gives us an enumeration of three basic neck variants. So instead of a boolean and an optional treble side scale, the storage type for this specification is going to change to an enum with scale values embedded into it. On the gui I'm planning to imlement this with a combo box, which will hide the treble scale widgets completely when set to monoscale. Currently, the scale and spinbox widgets are just set insensitive.
Tags for this post: Programming Rust Gtk+ Gfret