use std::sync::Arc;
use ek_cfg::LoadOutcome;
use ek_cfg::Store as CfgStore;
use ek_core::cfg_face::CfgHost;
use ek_core::main_engine::MainEngine;
use ek_core::plugin::Plugin;
use ek_core::section::SectionMap;
use crate::pluginwin::WinState;
use crate::state::UiShared;
const NS_DM: &str = "dm";
const NS_OMS: &str = "oms";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FaceKind {
Dm,
Oms,
Tq,
Ctp,
}
pub struct CfgBridge {
pub cfg: Option<CfgStore>,
pub shared: Arc<UiShared>,
}
impl CfgBridge {
#[must_use]
pub fn new(shared: &Arc<UiShared>) -> Self {
Self {
cfg: CfgStore::eco().ok(),
shared: Arc::clone(shared),
}
}
}
impl CfgHost for CfgBridge {
fn cfg_save(&self, ns: &str, map: &SectionMap) -> Result<(), String> {
match &self.cfg {
Some(c) => c.store(ns, map).map_err(|e| e.to_string()),
None => Err("档案托底根不可用(Store::eco 失败)".to_string()),
}
}
fn cfg_load(&self, ns: &str) -> Result<Option<SectionMap>, String> {
match &self.cfg {
Some(c) => match c.load(ns) {
Ok(LoadOutcome::Loaded { map, .. }) => Ok(Some(map)),
Ok(LoadOutcome::Fresh) => Ok(None),
Err(e) => Err(e.to_string()),
},
None => Err("档案托底根不可用(Store::eco 失败)".to_string()),
}
}
fn log(&self, line: &str) {
self.shared.log_line(line);
}
}
#[derive(Default)]
pub struct FaceStates {
pub dm: ek_dm::ui_face::DmUiState,
pub oms: ek_oms::ui_face::OmsUiState,
pub tq: ek_tq::ui_face::TqUiState,
pub wins: std::collections::HashMap<String, WinState>,
}
impl FaceStates {
#[must_use]
pub fn new() -> Self {
Self::default()
}
}
#[must_use]
pub fn face_of(engine: &MainEngine, name: &str) -> Option<FaceKind> {
if engine
.get_typed::<ek_dm::plugin::DmPlugin>(name)
.is_some_and(|p| p.as_configurable().is_some())
{
return Some(FaceKind::Dm);
}
if engine
.get_typed::<ek_oms::plugin::OmsPlugin>(name)
.is_some_and(|p| p.as_configurable().is_some())
{
return Some(FaceKind::Oms);
}
if engine
.get_typed::<ek_tq::plugin::TqPlugin>(name)
.is_some_and(|p| p.as_configurable().is_some())
{
return Some(FaceKind::Tq);
}
if engine
.get_typed::<ek_ctp::plugin::CtpPlugin>(name)
.is_some_and(|p| p.as_configurable().is_some())
{
return Some(FaceKind::Ctp);
}
None
}
#[must_use]
pub fn mounted(engine: &MainEngine) -> Vec<(String, String)> {
let mut out: Vec<(String, String)> = Vec::new();
for name in engine.plugin_names() {
let title = match face_of(engine, &name) {
Some(FaceKind::Dm) => "数据管理器 dm",
Some(FaceKind::Oms) => "统一受理 oms",
Some(FaceKind::Tq) => "天勤桥 tq",
Some(FaceKind::Ctp) => "行情网关 ctp",
None => continue,
};
out.push((name, title.to_string()));
}
out
}
pub fn apply_section(engine: &MainEngine, ns: &str, section: &SectionMap) -> Option<String> {
let rep = match ns {
NS_DM => {
let p = engine.get_typed::<ek_dm::plugin::DmPlugin>(ns)?;
p.as_configurable()?.apply_config(section).ok()?
}
NS_OMS => {
let p = engine.get_typed::<ek_oms::plugin::OmsPlugin>(ns)?;
p.as_configurable()?.apply_config(section).ok()?
}
_ => {
let mut found = None;
for name in engine.plugin_names() {
if let Some(kind) = face_of(engine, &name) {
let hit = match kind {
FaceKind::Tq => engine
.get_typed::<ek_tq::plugin::TqPlugin>(&name)
.and_then(|p| {
let c = p.as_configurable()?;
(c.config_ns() == ns).then(|| c.apply_config(section).ok())
}),
FaceKind::Ctp => engine
.get_typed::<ek_ctp::plugin::CtpPlugin>(&name)
.and_then(|p| {
let c = p.as_configurable()?;
(c.config_ns() == ns).then(|| c.apply_config(section).ok())
}),
_ => None,
};
if let Some(Some(r)) = hit {
found = Some(r);
break;
}
}
}
found?
}
};
Some(format!(
"受理 采纳{}/待重启{}",
rep.adopted.len(),
rep.deferred.len()
))
}
pub fn render_face(
ui: &mut egui::Ui,
engine: &MainEngine,
name: &str,
host: &dyn CfgHost,
fs: &mut FaceStates,
) -> bool {
match face_of(engine, name) {
Some(FaceKind::Dm) => {
let Some(p) = engine.get_typed::<ek_dm::plugin::DmPlugin>(name) else {
ui.label("dm 壳取不到(未装配?)");
return false;
};
ek_dm::ui_face::render(ui, &p, host, &mut fs.dm)
}
Some(FaceKind::Oms) => {
let Some(p) = engine.get_typed::<ek_oms::plugin::OmsPlugin>(name) else {
ui.label("oms 壳取不到(未装配?)");
return false;
};
ek_oms::ui_face::render(ui, &p, host, &mut fs.oms)
}
Some(FaceKind::Tq) => {
let Some(p) = engine.get_typed::<ek_tq::plugin::TqPlugin>(name) else {
ui.label("tq 壳取不到(未装配?)");
return false;
};
ek_tq::ui_face::render(ui, &p, host, &mut fs.tq)
}
Some(FaceKind::Ctp) => {
let Some(p) = engine.get_typed::<ek_ctp::plugin::CtpPlugin>(name) else {
ui.label("ctp 壳取不到(未装配?)");
return false;
};
let st = fs.wins.entry(name.to_string()).or_default();
crate::pluginwin::render_window(ui, p.as_ref(), host, st)
}
None => {
ui.label(format!("{name}:无自带面(不在挂载表)"));
false
}
}
}