Add widget-drop-down for Air

This commit is contained in:
Geoffrey D. Bennett
2024-01-20 19:07:16 +10:30
parent ade852163b
commit bc9d8867f3
4 changed files with 230 additions and 1 deletions

View File

@@ -50,6 +50,11 @@ button:disabled {
color: #505050;
}
/* Stop text shadows on buttons from being applied to the popup menu */
button > label > * {
text-shadow: none;
}
/* Button controls that are always disabled because they indicate status */
button.fixed {
color: #ffffff;
@@ -94,10 +99,22 @@ button.inst:checked {
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
}
/* Air Checked (Gen 3) */
button.air:checked {
text-shadow: 0 0 5px #ffc000, 0 0 15px #ffc000;
}
/* Air Selections (Gen 4) */
button.air.selected-presence > label {
color: #ffffff;
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
}
button.air.selected-presencedrive > label {
color: #ffffff;
text-shadow: 0 0 5px #ffc000, 0 0 15px #ffc000;
}
button.pad:checked {
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
}

View File

@@ -7,6 +7,7 @@
#include "tooltips.h"
#include "widget-boolean.h"
#include "widget-combo.h"
#include "widget-drop-down.h"
#include "widget-dual.h"
#include "widget-gain.h"
#include "widget-input-select.h"
@@ -262,7 +263,7 @@ static void create_input_air_enum_control(
int current_row,
int column_num
) {
GtkWidget *w = make_combo_box_alsa_elem(elem);
GtkWidget *w = make_drop_down_alsa_elem(elem, "Air");
gtk_widget_add_css_class(w, "air");
gtk_widget_set_tooltip_text(w, air_descr);

198
src/widget-drop-down.c Normal file
View File

@@ -0,0 +1,198 @@
// SPDX-FileCopyrightText: 2023-2024 Geoffrey D. Bennett <g@b4.vu>
// SPDX-License-Identifier: GPL-3.0-or-later
#include <ctype.h>
#include "widget-drop-down.h"
struct drop_down {
struct alsa_elem *elem;
GtkWidget *button;
GtkWidget *popover;
GtkWidget *listview;
GtkSingleSelection *selection;
int fixed_text;
};
static void remove_selected_classes(GtkWidget *widget) {
char **classes = gtk_widget_get_css_classes(widget);
for (char **i = classes; *i != NULL; i++)
if (strncmp(*i, "selected-", 9) == 0)
gtk_widget_remove_css_class(widget, *i);
g_strfreev(classes);
}
static void sanitise_class_name(char *s) {
char *dst = s;
while (*s) {
if (isalnum(*s) || *s == '-')
*dst++ = tolower(*s);
s++;
}
*dst = '\0';
}
static void add_class(GtkWidget *widget, const char *class) {
char *class_name = g_strdup_printf("selected-%s", class);
sanitise_class_name(class_name);
gtk_widget_add_css_class(widget, class_name);
g_free(class_name);
}
static void list_item_activated(
GtkListItem *list_item,
guint index,
struct drop_down *data
) {
alsa_set_elem_value(data->elem, index);
gtk_popover_popdown(GTK_POPOVER(data->popover));
}
static void toggle_button_clicked(GtkWidget *widget, struct drop_down *data) {
gtk_popover_popup(GTK_POPOVER(data->popover));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->button), FALSE);
}
static void setup_factory(
GtkListItemFactory *factory,
GtkListItem *list_item,
gpointer user_data
) {
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
GtkWidget *label = gtk_label_new(NULL);
gtk_label_set_xalign(GTK_LABEL(label), 0.0);
gtk_box_append(GTK_BOX(box), label);
GtkWidget *icon = gtk_image_new_from_icon_name("object-select-symbolic");
gtk_box_append(GTK_BOX(box), icon);
gtk_list_item_set_child(list_item, box);
}
static void update_list_item(
GtkListItem *list_item,
struct drop_down *data
) {
GtkWidget *box = gtk_list_item_get_child(list_item);
GtkWidget *icon = gtk_widget_get_last_child(box);
int index = gtk_single_selection_get_selected(data->selection);
if (index == gtk_list_item_get_position(list_item))
gtk_widget_set_opacity(icon, 1.0);
else
gtk_widget_set_opacity(icon, 0.0);
}
static void bind_factory(
GtkListItemFactory *factory,
GtkListItem *list_item,
gpointer user_data
) {
struct drop_down *data = user_data;
GtkWidget *box = gtk_list_item_get_child(list_item);
GtkWidget *label = gtk_widget_get_first_child(box);
int index = gtk_list_item_get_position(list_item);
const char *text = alsa_get_item_name(data->elem, index);
gtk_label_set_text(GTK_LABEL(label), text);
update_list_item(list_item, data);
}
static void drop_down_updated(
struct alsa_elem *elem,
void *private
) {
struct drop_down *data = private;
int is_writable = alsa_get_elem_writable(elem);
gtk_widget_set_sensitive(data->button, is_writable);
int value = alsa_get_elem_value(elem);
gtk_single_selection_set_selected(data->selection, value);
remove_selected_classes(data->button);
add_class(data->button, alsa_get_item_name(elem, value));
if (data->fixed_text)
return;
gtk_button_set_label(
GTK_BUTTON(data->button),
alsa_get_item_name(elem, value)
);
}
static void drop_down_destroy(GtkWidget *widget, GtkWidget *popover) {
gtk_widget_unparent(popover);
}
GtkWidget *make_drop_down_alsa_elem(
struct alsa_elem *elem,
const char *label_text
) {
struct drop_down *data = g_malloc(sizeof(struct drop_down));
data->elem = elem;
data->button = gtk_toggle_button_new_with_label(label_text);
gtk_widget_add_css_class(data->button, "drop-down");
data->fixed_text = !!label_text;
data->popover = gtk_popover_new();
gtk_popover_set_has_arrow(GTK_POPOVER(data->popover), FALSE);
gtk_widget_set_parent(
data->popover,
gtk_widget_get_first_child(data->button)
);
g_signal_connect(
gtk_widget_get_first_child(data->button),
"destroy", G_CALLBACK(drop_down_destroy), data->popover
);
GListModel *model = G_LIST_MODEL(gtk_string_list_new(NULL));
int count = alsa_get_item_count(elem);
for (int i = 0; i < count; i++) {
const char *text = alsa_get_item_name(elem, i);
gtk_string_list_append(GTK_STRING_LIST(model), text);
}
GtkListItemFactory *factory = gtk_signal_list_item_factory_new();
g_signal_connect(
factory, "setup", G_CALLBACK(setup_factory), data
);
g_signal_connect(
factory, "bind", G_CALLBACK(bind_factory), data
);
data->selection = gtk_single_selection_new(model);
data->listview = gtk_list_view_new(
GTK_SELECTION_MODEL(data->selection),
factory
);
gtk_list_view_set_single_click_activate(GTK_LIST_VIEW(data->listview), TRUE);
gtk_popover_set_child(GTK_POPOVER(data->popover), data->listview);
g_signal_connect(
data->button, "clicked", G_CALLBACK(toggle_button_clicked), data
);
g_signal_connect(
data->listview, "activate", G_CALLBACK(list_item_activated), data
);
drop_down_updated(elem, data);
alsa_elem_add_callback(elem, drop_down_updated, data);
return data->button;
}

13
src/widget-drop-down.h Normal file
View File

@@ -0,0 +1,13 @@
// SPDX-FileCopyrightText: 2023-2024 Geoffrey D. Bennett <g@b4.vu>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <gtk/gtk.h>
#include "alsa.h"
GtkWidget *make_drop_down_alsa_elem(
struct alsa_elem *elem,
const char *label_text
);