monorepo/otg/gtk/src/lib.rs

95 lines
3.2 KiB
Rust
Raw Normal View History

/*
Copyright 2024, Savanni D'Gerinel <savanni@luminescent-dreams.com>
2024-03-22 03:48:48 +00:00
This file is part of On the Grid.
2024-03-22 03:48:48 +00:00
On the Grid is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
2024-03-22 03:48:48 +00:00
On the Grid is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
2024-03-22 03:48:48 +00:00
You should have received a copy of the GNU General Public License along with On the Grid. If not, see <https://www.gnu.org/licenses/>.
*/
2024-03-22 02:39:28 +00:00
pub mod components;
mod app_window;
pub use app_window::AppWindow;
mod views;
use async_std::task::{spawn, yield_now};
2024-03-22 03:48:48 +00:00
use otg_core::{Core, Observable, CoreRequest, CoreResponse};
use std::{rc::Rc, sync::Arc};
use tokio::runtime::Runtime;
2023-04-07 01:52:39 +00:00
#[derive(Clone)]
pub struct CoreApi {
pub core: Core,
2023-04-07 01:52:39 +00:00
}
impl CoreApi {
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {
self.core.dispatch(request).await
2023-04-07 01:52:39 +00:00
}
}
pub fn perftrace<F, A>(trace_name: &str, f: F) -> A
where
F: FnOnce() -> A,
{
let start = std::time::Instant::now();
let result = f();
let end = std::time::Instant::now();
println!("[Trace: {}] {:?}", trace_name, end - start);
2023-10-05 16:19:57 +00:00
result
}
/// LocalObserver creates a task on the current thread which watches the specified observer for notifications and calls the handler function with each one.
///
/// The LocalObserver starts a task which listens for notifications during the constructor. When the observer goes out of scope, it will make a point of aborting the task. This combination means that anything which uses the observer can create it, hold on to a reference of it, and then drop it when done, and not have to do anything else with the observer object.
struct LocalObserver<T> {
join_handle: glib::JoinHandle<()>,
handler: Rc<dyn Fn(T)>,
}
impl<T: 'static> LocalObserver<T> {
/// Construct a new LocalObserver and start it running.
///
/// observable -- any object which emits events
/// handler -- a function which can process events
fn new(observable: &dyn Observable<T>, handler: impl Fn(T) + 'static) -> Self {
let listener = observable.subscribe();
let handler = Rc::new(handler);
let join_handle = glib::spawn_future_local({
let handler = handler.clone();
async move {
loop {
match listener.recv().await {
Ok(msg) => handler(msg),
Err(_) => {
// recv only fails if the channel has been closed and no other notifications are pending. This will break out of the loop and terminate the observer.
return;
}
}
yield_now().await;
}
}
});
Self {
join_handle,
handler,
}
}
}
impl<T> Drop for LocalObserver<T> {
fn drop(&mut self) {
// Abort the task when the observer goes out of scope.
self.join_handle.abort();
}
}