bar: route Lua widgets to any [bar.slots] slot, not just four fixed spots
Phase 3b of the shell theme system. A slot list entry can now be `widget:<key>`, where `<key>` is either a WidgetPlacement alias (right_of_workspaces, left_of_clock, right_of_clock, left_of_stats, tray) or a Lua module name. ModuleRegistry::for_each_in_slot creates each widget container on demand at its slot position; reconcile_widgets routes each WidgetSpec by module name first, falling back to its placement alias, and logs+drops (never panics) a spec with no matching container. bread_shared::widget::WidgetPlacement stays untouched — it's still the wire type breadd sends, unmodified and unshadowed; only the container map that placement now resolves through is theme-driven.
This commit is contained in:
parent
c5f7dd1ee3
commit
8d80a05d9b
2 changed files with 150 additions and 86 deletions
|
|
@ -1,4 +1,5 @@
|
|||
//! Module registry for the theme manifest's `[bar.slots]` (plan Phase 3a).
|
||||
//! Module registry for the theme manifest's `[bar.slots]` (plan Phase 3a),
|
||||
//! extended in Phase 3b to also route `widget:<key>` entries.
|
||||
//!
|
||||
//! Each bar module (`workspaces`, `media`, `clock`, `volume`, `wifi`,
|
||||
//! `battery`, `control`, …) is still built exactly where it always was in
|
||||
|
|
@ -9,10 +10,14 @@
|
|||
//! done, then walks `ShellTheme::slots()` to append them in the theme's
|
||||
//! order instead of a hardcoded sequence.
|
||||
//!
|
||||
//! The Lua-declared `widget_*` containers (`WidgetPlacement`) are NOT part
|
||||
//! of this registry — their fixed interleave (right-of-workspaces,
|
||||
//! left/right-of-clock, left-of-stats) stays exactly as it is today.
|
||||
//! Generalizing their placement is Phase 3b, not this task.
|
||||
//! A slot entry may also be `widget:<key>`, where `<key>` is either a
|
||||
//! `WidgetPlacement` alias (`right_of_workspaces`, `left_of_clock`,
|
||||
//! `right_of_clock`, `left_of_stats`, `tray`) or a Lua module name (see
|
||||
//! `bread_shared::widget::WidgetSpec::module`) — these route through
|
||||
//! `for_each_in_slot`'s `on_widget` callback rather than this registry,
|
||||
//! since their containers are Lua-widget slots created on demand by the
|
||||
//! caller, not modules registered here. `WidgetPlacement` itself is a wire
|
||||
//! type from `bread-shared` and is never referenced in this file.
|
||||
|
||||
use gtk4::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
|
@ -32,22 +37,50 @@ impl ModuleRegistry {
|
|||
self.0.insert(name, widget.clone().upcast());
|
||||
}
|
||||
|
||||
/// Appends every module named in `names` (a manifest slot list, in
|
||||
/// theme order) into `container` via `on_widget`, which lets the
|
||||
/// caller interleave fixed Lua widget containers around specific
|
||||
/// modules (e.g. the clock). A name with no registered widget is
|
||||
/// logged and skipped — an unrecognized or unmapped module in a theme
|
||||
/// manifest must never crash the bar.
|
||||
/// Walks every entry named in `names` (a manifest slot list, in theme
|
||||
/// order). A `widget:<key>` entry calls `on_widget(key)`, letting the
|
||||
/// caller create-or-fetch that Lua widget container and append it at
|
||||
/// this exact position. Anything else is looked up as a registered
|
||||
/// module name and passed to `on_module`; a name with no registered
|
||||
/// widget is logged and skipped — an unrecognized or unmapped module in
|
||||
/// a theme manifest must never crash the bar.
|
||||
pub fn for_each_in_slot(
|
||||
&self,
|
||||
names: &[String],
|
||||
mut on_widget: impl FnMut(&str, >k4::Widget),
|
||||
mut on_module: impl FnMut(&str, >k4::Widget),
|
||||
mut on_widget: impl FnMut(&str),
|
||||
) {
|
||||
for name in names {
|
||||
if let Some(key) = name.strip_prefix("widget:") {
|
||||
on_widget(key);
|
||||
continue;
|
||||
}
|
||||
match self.0.get(name.as_str()) {
|
||||
Some(widget) => on_widget(name, widget),
|
||||
Some(widget) => on_module(name, widget),
|
||||
None => eprintln!("breadbar: [bar.slots] names unknown module '{name}' — skipping"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the widget container keyed `key` in `containers`, creating it
|
||||
/// (a plain horizontal box, styled like every other Lua widget slot) on
|
||||
/// first use. Called from `for_each_in_slot`'s `on_widget` callback so a
|
||||
/// `widget:<key>` slot entry gets a container the first time a theme
|
||||
/// places one there, regardless of whether `key` is a `WidgetPlacement`
|
||||
/// alias or a Lua module name — `reconcile_widgets` (main.rs) is what
|
||||
/// gives that distinction meaning when it routes specs into these
|
||||
/// containers.
|
||||
pub fn widget_slot_container(
|
||||
containers: &mut HashMap<String, gtk4::Box>,
|
||||
key: &str,
|
||||
) -> gtk4::Box {
|
||||
containers
|
||||
.entry(key.to_string())
|
||||
.or_insert_with(|| {
|
||||
let b = gtk4::Box::new(gtk4::Orientation::Horizontal, 6);
|
||||
b.add_css_class("bread-widget-slot");
|
||||
b
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue