use std::{
collections::HashMap,
hash::{DefaultHasher, Hash, Hasher},
};
use chart::Chart;
use gpui::{AnyElement, App, Global, SharedString, Window, div, prelude::*, px};
use theme::Theme;
pub const LANGUAGE: &str = "vega-lite";
const CACHED: usize = 64;
const HEIGHT: f32 = 260.0;
const PADDING: f32 = 12.0;
#[derive(Default)]
struct Cache(HashMap<u64, Option<Chart>>);
impl Global for Cache {}
pub fn render(code: &str, height: Option<u32>, _: &mut Window, cx: &mut App) -> Option<AnyElement> {
let mut hasher = DefaultHasher::new();
code.hash(&mut hasher);
let key = hasher.finish();
let cache = &mut cx.default_global::<Cache>().0;
let chart = match cache.get(&key) {
Some(chart) => chart.clone(),
None => {
if cache.len() >= CACHED {
cache.clear();
}
let chart = chart::vega_lite::import(code);
cache.insert(key, chart.clone());
chart
}
}?;
let theme = Theme::of(cx);
let id = SharedString::from(format!("vega-lite-{key:x}"));
Some(
div()
.debug_selector(|| LANGUAGE.into())
.h(px(height.map_or(HEIGHT, |height| height as f32)))
.p(px(PADDING))
.rounded(px(Theme::BASE_RADIUS))
.bg(theme.ink(0.02))
.child(chart::view(id, chart).size_full())
.into_any_element(),
)
}