Add widget-drop-down for Air
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
198
src/widget-drop-down.c
Normal 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
13
src/widget-drop-down.h
Normal 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
|
||||
);
|
||||
Reference in New Issue
Block a user