use std::{any::TypeId, collections::HashMap, marker::PhantomData};
use duat_core::prelude::*;
use crate::modes::PromptMode;
pub struct PromptLine<U> {
text: Text,
prompts: HashMap<TypeId, Text>,
_ghost: PhantomData<U>,
}
impl<U: Ui> PromptLine<U> {
pub fn prompt_of<M: PromptMode<U>>(&self) -> Option<Text> {
self.prompts.get(&TypeId::of::<M>()).cloned()
}
pub fn set_prompt<M: PromptMode<U>>(&mut self, text: Text) {
self.prompts.entry(TypeId::of::<M>()).or_insert(text);
}
}
impl<U: Ui> Widget<U> for PromptLine<U> {
type Cfg = PromptLineCfg<U>;
fn update(pa: &mut Pass, handle: &Handle<Self, U>) {
let pl = handle.read(pa);
if let Some(main) = pl.text.selections().get_main() {
handle
.area(pa)
.scroll_around_point(&pl.text, main.caret(), pl.print_cfg());
}
}
fn needs_update(&self, _: &Pass) -> bool {
false
}
fn cfg() -> Self::Cfg {
Self::Cfg {
prompts: HashMap::new(),
specs: PushSpecs::below().ver_len(1.0),
_ghost: PhantomData,
}
}
fn text(&self) -> &Text {
&self.text
}
fn text_mut(&mut self) -> &mut Text {
&mut self.text
}
fn print_cfg(&self) -> PrintCfg {
*PrintCfg::default_for_input().set_forced_horizontal_scrolloff(true)
}
fn once() -> Result<(), Text> {
Ok(())
}
}
impl<U: Ui> WidgetCfg<U> for PromptLineCfg<U> {
type Widget = PromptLine<U>;
fn build(self, _: &mut Pass, _: BuildInfo<U>) -> (Self::Widget, PushSpecs) {
let specs = if hook::group_exists("HidePromptLine") {
self.specs.ver_len(0.0)
} else {
self.specs
};
let widget = PromptLine {
text: Text::default(),
prompts: HashMap::new(),
_ghost: PhantomData,
};
(widget, specs)
}
}
#[doc(hidden)]
pub struct PromptLineCfg<U> {
prompts: HashMap<TypeId, Text>,
specs: PushSpecs,
_ghost: PhantomData<U>,
}
impl<U: Ui> PromptLineCfg<U> {
pub fn set_prompt<M: PromptMode<U>>(mut self, prompt: Text) -> Self {
self.prompts.insert(TypeId::of::<M>(), prompt);
self
}
pub fn above(self) -> Self {
Self {
specs: PushSpecs::above().ver_len(1.0),
..self
}
}
pub fn below(self) -> Self {
Self {
specs: PushSpecs::below().ver_len(1.0),
..self
}
}
pub fn hidden(self) -> Self {
Self { specs: self.specs.hidden(), ..self }
}
pub fn left_ratioed(self, den: u16, div: u16) -> Self {
Self {
specs: PushSpecs::left().hor_ratio(den, div),
..self
}
}
}
impl<U: Ui> Default for PromptLineCfg<U> {
fn default() -> Self {
PromptLine::cfg()
}
}