asked the clanker to change the arcidecture a bit
This commit is contained in:
+32
-54
@@ -7,7 +7,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use iced::widget::{column, container, text};
|
||||
use iced::{window, Alignment, Element, Length, Rectangle, Subscription, Task, Theme};
|
||||
use iced::{window, Alignment, Element, Length, Subscription, Task, Theme};
|
||||
use iced_layershell::daemon;
|
||||
use iced_layershell::reexport::Anchor;
|
||||
use iced_layershell::settings::{LayerShellSettings, Settings, StartMode};
|
||||
@@ -38,8 +38,9 @@ struct Bar {
|
||||
|
||||
impl Bar {
|
||||
fn new() -> Self {
|
||||
let mut modules: BTreeMap<&'static str, Box<dyn BarModule>> = BTreeMap::new();
|
||||
modules.insert("clock", Box::new(module_clock::Clock::new()));
|
||||
// Registry owns construction: adding a module never edits this file.
|
||||
let modules: BTreeMap<&'static str, Box<dyn BarModule>> =
|
||||
modules::all().into_iter().map(|m| (m.id(), m)).collect();
|
||||
let routes = modules
|
||||
.iter()
|
||||
.map(|(id, module)| (*id, module.services()))
|
||||
@@ -68,24 +69,15 @@ pub(crate) enum Msg {
|
||||
WindowClosed(window::Id),
|
||||
}
|
||||
|
||||
/// App-level effects (popups, window ops), emitted via `Task<Message>`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum Cmd {
|
||||
/// Toggle a module's popup: close if open for it, else open it.
|
||||
RequestPopup(String, String),
|
||||
/// Widget-tree pass reported a module's laid-out bounds; anchor popup.
|
||||
BoundsFound(String, Rectangle),
|
||||
/// Request removal of the popup surface.
|
||||
ClosePopup(window::Id),
|
||||
}
|
||||
|
||||
/// iced needs one `Message` type. `to_layer_message` must sit here: it
|
||||
/// injects the layer-shell effect variants + their `TryInto` impl.
|
||||
#[to_layer_message(multi)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum Message {
|
||||
Event(Msg),
|
||||
Effect(Cmd),
|
||||
/// Effects. `common::ModuleEffect` is the one effect vocabulary, so
|
||||
/// mapping module output is a plain `.map(Message::Effect)`.
|
||||
Effect(ModuleEffect),
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -96,24 +88,22 @@ fn namespace() -> String {
|
||||
String::from("barbar")
|
||||
}
|
||||
|
||||
/// Maps a module-requested effect into an app message. Modules never name
|
||||
/// app types; this is the only place the two meet.
|
||||
fn module_effect_to_message(effect: ModuleEffect) -> Message {
|
||||
match effect {
|
||||
ModuleEffect::RequestPopup(module_id, element_id) => {
|
||||
Message::Effect(Cmd::RequestPopup(module_id, element_id))
|
||||
}
|
||||
ModuleEffect::ClosePopup(id) => Message::Effect(Cmd::ClosePopup(id)),
|
||||
}
|
||||
}
|
||||
|
||||
/// One arm per service kind: turns a route key into its subscription.
|
||||
/// Adding a service touches only this match (plus the leaf crate).
|
||||
fn service_subscription(service: &ModuleService) -> Subscription<Message> {
|
||||
match service {
|
||||
ModuleService::Clock(_) => service_datatime::ClockTicker::run()
|
||||
.map(|event| Message::Event(Msg::Subscription(event))),
|
||||
}
|
||||
/// Route subscriptions + window-close events (popup really destroyed).
|
||||
/// Each module's wants go through the services registry, so adding a
|
||||
/// service never edits this file.
|
||||
fn gather_subscriptions(bar: &Bar) -> Subscription<Message> {
|
||||
let route_sub = Subscription::batch(
|
||||
bar.routes
|
||||
.values()
|
||||
.flat_map(|wants| wants.iter())
|
||||
.map(|service| {
|
||||
services::subscription(service)
|
||||
.map(|event| Message::Event(Msg::Subscription(event)))
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
let close_events = window::close_events().map(|id| Message::Event(Msg::WindowClosed(id)));
|
||||
Subscription::batch(vec![route_sub, close_events])
|
||||
}
|
||||
|
||||
fn main() -> Result<(), iced_layershell::Error> {
|
||||
@@ -138,18 +128,6 @@ fn main() -> Result<(), iced_layershell::Error> {
|
||||
.run()
|
||||
}
|
||||
|
||||
/// Route subscriptions + window-close events (popup really destroyed).
|
||||
fn gather_subscriptions(bar: &Bar) -> Subscription<Message> {
|
||||
let route_sub = Subscription::batch(
|
||||
bar.routes
|
||||
.values()
|
||||
.flat_map(|x| x.iter().map(service_subscription))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
let close_events = window::close_events().map(|id| Message::Event(Msg::WindowClosed(id)));
|
||||
Subscription::batch(vec![route_sub, close_events])
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Update
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -157,7 +135,7 @@ fn gather_subscriptions(bar: &Bar) -> Subscription<Message> {
|
||||
fn update(bar: &mut Bar, msg: Message) -> Task<Message> {
|
||||
match msg {
|
||||
Message::Event(event) => handle_event(bar, event),
|
||||
Message::Effect(cmd) => handle_effect(bar, cmd),
|
||||
Message::Effect(effect) => handle_effect(bar, effect),
|
||||
// Layer-shell variants injected by `to_layer_message`.
|
||||
_ => Task::none(),
|
||||
}
|
||||
@@ -167,8 +145,8 @@ fn update(bar: &mut Bar, msg: Message) -> Task<Message> {
|
||||
fn handle_event(bar: &mut Bar, event: Msg) -> Task<Message> {
|
||||
match event {
|
||||
Msg::Module(m) => match bar.modules.get_mut(m.id) {
|
||||
// Modules return protocol tasks; map effects into `Cmd`s.
|
||||
Some(module) => module.update(m).map(module_effect_to_message),
|
||||
// Modules return protocol tasks; wrap effects into messages.
|
||||
Some(module) => module.update(m).map(Message::Effect),
|
||||
None => Task::none(),
|
||||
},
|
||||
|
||||
@@ -190,7 +168,7 @@ fn handle_event(bar: &mut Bar, event: Msg) -> Task<Message> {
|
||||
id: module.id(),
|
||||
payload: payload.clone(),
|
||||
})
|
||||
.map(module_effect_to_message)
|
||||
.map(Message::Effect)
|
||||
})
|
||||
.fold(Task::none(), |acc, t| acc.chain(t))
|
||||
}
|
||||
@@ -208,9 +186,9 @@ fn handle_event(bar: &mut Bar, event: Msg) -> Task<Message> {
|
||||
}
|
||||
|
||||
/// Runs an effect; may set up bar state for it (e.g. which popup is open).
|
||||
fn handle_effect(bar: &mut Bar, cmd: Cmd) -> Task<Message> {
|
||||
match cmd {
|
||||
Cmd::RequestPopup(module_id, element_id) => {
|
||||
fn handle_effect(bar: &mut Bar, effect: ModuleEffect) -> Task<Message> {
|
||||
match effect {
|
||||
ModuleEffect::RequestPopup(module_id, element_id) => {
|
||||
// Toggle: close if already open for this module, else open.
|
||||
if bar.active_popup.as_deref() == Some(module_id.as_str()) {
|
||||
popup::close_popup(bar)
|
||||
@@ -219,9 +197,9 @@ fn handle_effect(bar: &mut Bar, cmd: Cmd) -> Task<Message> {
|
||||
}
|
||||
}
|
||||
|
||||
Cmd::BoundsFound(module_id, bounds) => popup::open_popup(bar, module_id, bounds),
|
||||
ModuleEffect::BoundsFound(module_id, bounds) => popup::open_popup(bar, module_id, bounds),
|
||||
|
||||
Cmd::ClosePopup(id) => {
|
||||
ModuleEffect::ClosePopup(id) => {
|
||||
// Request removal only; keep popup state so the popup content
|
||||
// renders until `WindowClosed` confirms it's gone.
|
||||
Task::done(Message::RemoveWindow(id))
|
||||
|
||||
@@ -10,7 +10,9 @@ use iced::{Alignment, Element, Length, Rectangle, Task};
|
||||
use iced_layershell::actions::IcedNewPopupSettings;
|
||||
use iced_layershell::reexport::{PopupAnchor, PopupGravity};
|
||||
|
||||
use crate::{Bar, Cmd, Message, Msg};
|
||||
use common::ModuleEffect;
|
||||
|
||||
use crate::{Bar, Message, Msg};
|
||||
|
||||
/// Default (small menu) popup size.
|
||||
const POPUP_W: u32 = 150;
|
||||
@@ -52,7 +54,7 @@ pub fn open_popup(bar: &mut Bar, module_id: String, bounds: Rectangle) -> Task<M
|
||||
/// `Msg::WindowClosed`, so popup content keeps rendering until then.
|
||||
pub fn close_popup(bar: &mut Bar) -> Task<Message> {
|
||||
if let Some(id) = bar.popup_id {
|
||||
return Task::done(Message::Effect(Cmd::ClosePopup(id)));
|
||||
return Task::done(Message::Effect(ModuleEffect::ClosePopup(id)));
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
@@ -93,7 +95,7 @@ pub fn capture_bounds(module_id: String, element_id: String) -> Task<Message> {
|
||||
target,
|
||||
found: None,
|
||||
})
|
||||
.map(move |bounds| Message::Effect(Cmd::BoundsFound(module_id.clone(), bounds)))
|
||||
.map(move |bounds| Message::Effect(ModuleEffect::BoundsFound(module_id.clone(), bounds)))
|
||||
}
|
||||
|
||||
/// Popup widget tree on its own LayerShell surface; the active module
|
||||
@@ -117,7 +119,8 @@ pub fn view(bar: &Bar) -> Element<'_, Message> {
|
||||
.width(Length::Fill)
|
||||
.align_x(Alignment::Center),
|
||||
content,
|
||||
mouse_area(text("close").size(12)).on_press(Message::Effect(Cmd::ClosePopup(popup_id))),
|
||||
mouse_area(text("close").size(12))
|
||||
.on_press(Message::Effect(ModuleEffect::ClosePopup(popup_id))),
|
||||
]
|
||||
.spacing(1)
|
||||
.into()
|
||||
|
||||
Reference in New Issue
Block a user