Pick the text stage's font with a font chooser

A new Font param type (ParamSpec::makeFont) is a font family as the
machine names it. The interface shows it as a family-only
FontDialogButton; the command line and the project file treat it as a
plain string, as they did the Text param it replaces, so existing
projects and --font-family keep working. A family the machine lacks is
kept as written. Bumps the version to 0.8.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Si
2026-09-26 22:58:44 +02:00
co-authored by Claude Opus 5.5
parent 8acf85ddb8
commit f9fe6e0fa5
11 changed files with 100 additions and 5 deletions
+1
View File
@@ -182,6 +182,7 @@ Options parseOptions(int argc, char** argv) {
}
case ParamSpec::Type::Path:
case ParamSpec::Type::Text:
case ParamSpec::Type::Font:
options.params[spec->key] = requireValue(argc, argv, i, arg);
break;
case ParamSpec::Type::Color: {
+12
View File
@@ -100,6 +100,17 @@ ParamSpec ParamSpec::makeColor(std::string key, std::string label, std::string d
return spec;
}
ParamSpec ParamSpec::makeFont(std::string key, std::string label, std::string defaultFamily,
std::string help) {
ParamSpec spec;
spec.type = Type::Font;
spec.key = std::move(key);
spec.label = std::move(label);
spec.help = std::move(help);
spec.defaultChoice = std::move(defaultFamily);
return spec;
}
namespace {
const ParamValue* find(const ParamValues& values, const std::string& key) {
@@ -121,6 +132,7 @@ ParamValue paramDefault(const ParamSpec& spec) {
case ParamSpec::Type::Path:
case ParamSpec::Type::Text:
case ParamSpec::Type::Color:
case ParamSpec::Type::Font:
break;
}
return spec.defaultChoice;
+6 -1
View File
@@ -11,7 +11,7 @@ namespace effector {
// Declarative description of one effect knob. The GUI turns these into widgets
// and the CLI turns them into flags, so neither knows about any effect.
struct ParamSpec {
enum class Type { Int, Double, Bool, Choice, Path, Text, Color };
enum class Type { Int, Double, Bool, Choice, Path, Text, Color, Font };
Type type = Type::Int;
std::string key;
@@ -56,6 +56,11 @@ struct ParamSpec {
// spelling as a flag value.
static ParamSpec makeColor(std::string key, std::string label, std::string defaultColor,
std::string help = {});
// A font family as it is named on this machine ("Sans", "DejaVu Serif"):
// a font chooser in the interface, a flag taking any string on the
// command line. A family the machine lacks is kept as written.
static ParamSpec makeFont(std::string key, std::string label, std::string defaultFamily,
std::string help = {});
};
using ParamValue = std::variant<long, double, bool, std::string>;
+2
View File
@@ -366,6 +366,7 @@ void writeParams(std::ostream& out, const std::vector<ParamSpec>& specs, const P
break;
case ParamSpec::Type::Choice:
case ParamSpec::Type::Text:
case ParamSpec::Type::Font:
out << quote(paramText(values, spec.key, spec.defaultChoice));
break;
case ParamSpec::Type::Color: {
@@ -412,6 +413,7 @@ void readParams(const std::vector<ParamSpec>& specs, const Json& params,
}
break;
case ParamSpec::Type::Text:
case ParamSpec::Type::Font:
if (value->kind == Json::Kind::String) values[spec.key] = value->text;
break;
case ParamSpec::Type::Color: {
+1 -1
View File
@@ -16,7 +16,7 @@ const std::vector<ParamSpec>& TextEffect::params() const {
static const std::vector<ParamSpec> specs = {
ParamSpec::makeText("text", "Text", "Effector",
"What to write; a line break starts a new line."),
ParamSpec::makeText("font_family", "Font", "Sans",
ParamSpec::makeFont("font_family", "Font", "Sans",
"Font family, as it is named on this machine: Sans, Serif, Monospace, "
"\"DejaVu Serif\", ...")
.styled(),
+23
View File
@@ -995,6 +995,21 @@ void EffectorWindow::buildParamWidgets() {
widget = std::move(button);
break;
}
case ParamSpec::Type::Font: {
// Only the family is chosen here: weight, slant and size are
// params of their own.
auto button = std::make_unique<Gtk::FontDialogButton>(Gtk::FontDialog::create());
button->set_halign(Gtk::Align::START);
button->set_level(Gtk::FontLevel::FAMILY);
button->set_use_font(true);
Pango::FontDescription font;
font.set_family(paramText(values, spec.key, spec.defaultChoice));
button->set_font_desc(font);
button->property_font_desc().signal_changed().connect(
sigc::mem_fun(*this, &EffectorWindow::onParamChanged));
widget = std::move(button);
break;
}
case ParamSpec::Type::Choice: {
std::vector<Glib::ustring> choices(spec.choices.begin(), spec.choices.end());
auto dropdown = std::make_unique<Gtk::DropDown>();
@@ -1051,6 +1066,14 @@ ParamValues EffectorWindow::paramValues() const {
values[entry.spec.key] = formatColor(rgb);
break;
}
case ParamSpec::Type::Font: {
// A family the machine lacks keeps its name, so a project
// from elsewhere still says which font it wanted.
const auto family =
static_cast<Gtk::FontDialogButton*>(entry.widget)->get_font_desc().get_family();
if (!family.empty()) values[entry.spec.key] = std::string(family);
break;
}
case ParamSpec::Type::Choice: {
const auto index = static_cast<Gtk::DropDown*>(entry.widget)->get_selected();
if (index < entry.spec.choices.size()) values[entry.spec.key] = entry.spec.choices[index];