nativeshell 0.1.16

NativeShell Rust package
Documentation
use std::{cell::RefCell, collections::HashSet, rc::Weak};

use crate::{
    codec::{
        value::{from_value, to_value},
        MethodCallResult, Value,
    },
    util::{Late, OkLog},
    Context, Error, Result,
};

use super::{
    api_constants::{channel, method},
    platform::screen_manager::PlatformScreenManager,
    EngineHandle, MethodCallHandler, MethodInvokerProvider, RegisteredMethodCallHandler,
};

pub trait ScreenManagerDelegate {
    fn screen_configuration_changed(&self);
}

pub struct ScreenManager {
    platform_manager: Late<PlatformScreenManager>,
    invoker_provider: Late<MethodInvokerProvider>,
    engines: HashSet<EngineHandle>,
}

impl ScreenManager {
    pub(super) fn new(context: Context) -> RegisteredMethodCallHandler<Self> {
        Self {
            platform_manager: Late::new(),
            invoker_provider: Late::new(),
            engines: HashSet::new(),
        }
        .register(context, channel::SCREEN_MANAGER)
    }

    fn map_result<T>(result: Result<T>) -> MethodCallResult<Value>
    where
        T: serde::Serialize,
    {
        result.map(|v| to_value(v).unwrap()).map_err(|e| e.into())
    }
}

impl MethodCallHandler for ScreenManager {
    fn on_method_call(
        &mut self,
        call: crate::codec::MethodCall<Value>,
        reply: crate::codec::MethodCallReply<Value>,
        engine: super::EngineHandle,
    ) {
        self.engines.insert(engine);
        match call.method.as_str() {
            method::screen_manager::GET_SCREENS => {
                let screens = self.platform_manager.get_screens();
                reply.send(Self::map_result(screens.map_err(Error::from)));
            }
            method::screen_manager::GET_MAIN_SCREEN => {
                let id = self.platform_manager.get_main_screen();
                reply.send(Self::map_result(id.map_err(Error::from)));
            }
            method::screen_manager::LOGICAL_TO_SYSTEM => {
                let offset = self
                    .platform_manager
                    .logical_to_system(from_value(&call.args).unwrap());
                reply.send(Self::map_result(offset.map_err(Error::from)));
            }
            method::screen_manager::SYSTEM_TO_LOGICAL => {
                let offset = self
                    .platform_manager
                    .system_to_logical(from_value(&call.args).unwrap());
                reply.send(Self::map_result(offset.map_err(Error::from)));
            }
            _ => {}
        }
    }

    fn on_engine_destroyed(&mut self, engine: EngineHandle) {
        self.engines.remove(&engine);
    }

    fn assign_weak_self(&mut self, weak_self: Weak<RefCell<Self>>) {
        self.platform_manager
            .set(PlatformScreenManager::new(weak_self));
    }

    fn assign_invoker_provider(&mut self, provider: MethodInvokerProvider) {
        self.invoker_provider.set(provider);
    }
}

impl ScreenManagerDelegate for ScreenManager {
    fn screen_configuration_changed(&self) {
        for engine in &self.engines {
            let invoker = self.invoker_provider.get_method_invoker_for_engine(*engine);
            invoker
                .call_method(method::screen_manager::SCREENS_CHANGED, Value::Null, |_| {})
                .ok_log();
        }
    }
}