ui: draw the sidebar tabs without the placeholder icon
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
5bb23e6a0a
commit
0c6e69957d
6 files changed
+75
-8
No files matched your search
+10
-4
@@ -3060,8 +3060,11 @@ void note_panel_controls(App& app) {
|
||||
// pill count reads 0 and the label count means nothing, rather than passing vacuously.
|
||||
int pills = 0;
|
||||
int drawn_labels = 0;
|
||||
int drawn_images = 0;
|
||||
const std::function<void(GtkWidget*)> count_drawn = [&](GtkWidget* w) {
|
||||
if (GTK_IS_TOGGLE_BUTTON(w) && gtk_widget_get_mapped(w)) ++pills;
|
||||
// A *mapped* image is an icon (or its missing-icon placeholder) on a tab: tabs are words only.
|
||||
if (GTK_IS_IMAGE(w) && gtk_widget_get_mapped(w)) ++drawn_images;
|
||||
// A *mapped* label with text: an empty label would be counted by "mapped" alone.
|
||||
if (GTK_IS_LABEL(w) && gtk_widget_get_mapped(w) && gtk_label_get_text(GTK_LABEL(w))[0] != '\0') {
|
||||
++drawn_labels;
|
||||
@@ -3074,6 +3077,7 @@ void note_panel_controls(App& app) {
|
||||
if (app.side_switcher != nullptr) count_drawn(app.side_switcher);
|
||||
app.dbg_switcher_pills = pills;
|
||||
app.dbg_switcher_labels = drawn_labels;
|
||||
app.dbg_switcher_images = drawn_images;
|
||||
// Walked through `get_pages()`, not the widget tree: an `AdwViewStackPage` is a plain `GObject`.
|
||||
app.dbg_switcher_pages =
|
||||
app.side_stack != nullptr
|
||||
@@ -5203,7 +5207,9 @@ void on_activate(GtkApplication* application, gpointer user) {
|
||||
G_CALLBACK(on_side_tab_changed), app);
|
||||
}
|
||||
// The source kind's own tabs (a generator, digital I/O), added before the first tick so the
|
||||
// pages-versus-pills reading below counts them too.
|
||||
// pages-versus-pills reading below counts them too. The tabs are words, so the switcher's icons
|
||||
// are hidden first and kept hidden for the pages this call adds.
|
||||
keep_tabs_icon_free(*app);
|
||||
build_source_panels(*app);
|
||||
|
||||
// The left side is the events pane *and* the plot, in one row: the pane is a column of its own
|
||||
@@ -6240,10 +6246,10 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
|
||||
app.dbg_panel_switch_trigger, app.dbg_toolbar_switch_trigger,
|
||||
app.dbg_panel_switch_cursors, app.dbg_toolbar_switch_cursors,
|
||||
app.dbg_panel_drove_toolbar);
|
||||
std::printf("[udpscope] switcher: policy=%s pills=%d labels=%d pages=%d size=%dx%d\n",
|
||||
std::printf("[udpscope] switcher: policy=%s pills=%d labels=%d images=%d pages=%d size=%dx%d\n",
|
||||
app.dbg_switcher_policy == 0 ? "narrow" : (app.dbg_switcher_policy == 1 ? "wide" : "?"),
|
||||
app.dbg_switcher_pills, app.dbg_switcher_labels, app.dbg_switcher_pages,
|
||||
app.dbg_switcher_w, app.dbg_switcher_h);
|
||||
app.dbg_switcher_pills, app.dbg_switcher_labels, app.dbg_switcher_images,
|
||||
app.dbg_switcher_pages, app.dbg_switcher_w, app.dbg_switcher_h);
|
||||
// The help affordance layer: what the contextual-help toggle left on the surfaces, and where the
|
||||
// guided tour stood when the last capture ran. Both are captured on the tick (`capture_help_state`),
|
||||
// so neither asks a destroyed widget anything.
|
||||
|
||||
@@ -444,6 +444,9 @@ struct App {
|
||||
/// are words (`wide` policy, a title per page), so the label count must equal the page count.
|
||||
int dbg_switcher_pills = -1;
|
||||
int dbg_switcher_labels = -1;
|
||||
/// How many `GtkImage`s the switcher has *mapped*: a tab is its title and nothing else, so this
|
||||
/// must be 0 -- an icon, or the missing-icon placeholder GTK draws for a page with no `icon-name`.
|
||||
int dbg_switcher_images = -1;
|
||||
/// How many pages the sidebar stack holds: `pills` and `labels` must both equal it.
|
||||
int dbg_switcher_pages = -1;
|
||||
/// The switcher's own size, beside it: what the tab bar costs the column.
|
||||
@@ -1560,6 +1563,11 @@ void config_dialog_refresh(ConfigDialog& d);
|
||||
void open_configurations(App& app);
|
||||
void save_layout_now(App& app);
|
||||
|
||||
/// The sidebar's tabs are words: hide the icon every `AdwViewSwitcherButton` draws (the
|
||||
/// missing-icon placeholder, for a page with a title and no `icon-name`), for the buttons that exist
|
||||
/// and for any page added later. Call once, before `build_source_panels()`.
|
||||
void keep_tabs_icon_free(App& app);
|
||||
|
||||
/// Capability panels (`src/ui_source.cpp`). `build_source_panels` adds the source kind's panels as
|
||||
/// pages of `side_stack`, once, before the first tick. `apply_source_panels` sets every panel's
|
||||
/// sensitivity from `connected` -- disabled, never hidden: the tab switcher owns visibility.
|
||||
|
||||
@@ -11,6 +11,48 @@
|
||||
namespace udpscope {
|
||||
namespace ui_impl {
|
||||
|
||||
namespace {
|
||||
|
||||
/// Hide every `GtkImage` inside `w`, and keep it hidden. `AdwViewSwitcherButton` always builds an
|
||||
/// icon -- in both of its layouts -- and a page with no `icon-name` gets `image-missing`, which is
|
||||
/// the placeholder the sidebar's text tabs used to draw. There is no property or policy that turns
|
||||
/// the icon off, so the image is hidden (a hidden child takes no space: the label gets the pill) and
|
||||
/// a `notify::visible` handler puts it back to hidden if the button ever shows it again.
|
||||
void hide_tab_icons(GtkWidget* w) {
|
||||
if (GTK_IS_IMAGE(w)) {
|
||||
if (g_object_get_data(G_OBJECT(w), "udpscope-icon-hidden") == nullptr) {
|
||||
g_object_set_data(G_OBJECT(w), "udpscope-icon-hidden", GINT_TO_POINTER(1));
|
||||
g_signal_connect(w, "notify::visible", G_CALLBACK(+[](GObject* o, GParamSpec*, gpointer) {
|
||||
GtkWidget* img = GTK_WIDGET(o);
|
||||
if (gtk_widget_get_visible(img)) gtk_widget_set_visible(img, FALSE);
|
||||
}),
|
||||
nullptr);
|
||||
}
|
||||
gtk_widget_set_visible(w, FALSE);
|
||||
return;
|
||||
}
|
||||
for (GtkWidget* c = gtk_widget_get_first_child(w); c != nullptr; c = gtk_widget_get_next_sibling(c)) {
|
||||
hide_tab_icons(c);
|
||||
}
|
||||
}
|
||||
|
||||
void on_tab_pages_changed(GListModel*, guint, guint, guint, gpointer sw) {
|
||||
hide_tab_icons(GTK_WIDGET(sw));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void keep_tabs_icon_free(App& app) {
|
||||
if (app.side_switcher == nullptr || app.side_stack == nullptr) return;
|
||||
hide_tab_icons(app.side_switcher);
|
||||
// A page added later gets a button when the model reports it; this handler is connected *after*
|
||||
// the switcher's own, so the button already exists when it runs.
|
||||
g_signal_connect_after(adw_view_stack_get_pages(ADW_VIEW_STACK(app.side_stack)), "items-changed",
|
||||
G_CALLBACK(on_tab_pages_changed), app.side_switcher);
|
||||
// And once more when the switcher is (re)mapped, which also covers a rebuild of the buttons.
|
||||
g_signal_connect_swapped(app.side_switcher, "map", G_CALLBACK(hide_tab_icons), app.side_switcher);
|
||||
}
|
||||
|
||||
void build_source_panels(App& app) {
|
||||
if (app.side_stack == nullptr || app.acq == nullptr || app.acq->source() == nullptr) return;
|
||||
SourceKind* kind = find_kind(app.source_kind);
|
||||
|
||||
Reference in new issue
Block a user