Gfret Gtk4 Port Part 3
Current status
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.
2021-07-25