ElyDoc, ElyTable, ElyShow (LibreOfficeKit), ElyPDF (MuPDF), ElyTree (Git), ElyMark (Milkdown and CodeMirror in CEF). ElyMail and ElyAgent follow.
137 lines
4.2 KiB
Rust
137 lines
4.2 KiB
Rust
//! New, and ElyDoc's own dialogs (DOC-01).
|
|
|
|
use std::rc::Rc;
|
|
|
|
use ely_gpui_component::{
|
|
buttons::Button,
|
|
documents::{Template as Pick, TemplatePicker},
|
|
forms::TextInput,
|
|
overlays::Dialog as Card,
|
|
};
|
|
use ely_office::prelude::*;
|
|
use ely_ui::commands::New;
|
|
use gpui::{AnyElement, App, Context, Entity, IntoElement, ParentElement as _, Window};
|
|
|
|
use crate::docs::Docs;
|
|
use crate::files::TEMPLATES;
|
|
use crate::refs::Ask;
|
|
|
|
pub enum Dialog {
|
|
Templates,
|
|
Table {
|
|
columns: f64,
|
|
rows: f64,
|
|
},
|
|
Section,
|
|
Ask {
|
|
ask: Ask,
|
|
field: Entity<TextInput>,
|
|
},
|
|
Link {
|
|
text: Entity<TextInput>,
|
|
url: Entity<TextInput>,
|
|
},
|
|
Reference {
|
|
marks: Vec<String>,
|
|
mark: String,
|
|
show: &'static str,
|
|
},
|
|
Output {
|
|
tab: u64,
|
|
print: bool,
|
|
all: bool,
|
|
pdf: ely_lok::Pdf,
|
|
},
|
|
}
|
|
|
|
impl Docs {
|
|
pub fn on_new(&mut self, _: &New, _: &mut Window, cx: &mut Context<Self>) {
|
|
self.dialog = Some(Dialog::Templates);
|
|
cx.notify();
|
|
}
|
|
|
|
/// The open dialog, if any.
|
|
pub fn dialog_element(&mut self, _: &mut Window, cx: &mut Context<Self>) -> Option<AnyElement> {
|
|
let this = cx.entity();
|
|
let dismiss = {
|
|
let this = this.clone();
|
|
move |_: &mut Window, cx: &mut App| {
|
|
this.update(cx, |docs, cx| {
|
|
docs.dialog = None;
|
|
cx.notify();
|
|
})
|
|
}
|
|
};
|
|
let card = match self.dialog.as_ref()? {
|
|
Dialog::Templates => templates(this, dismiss, cx),
|
|
Dialog::Section => {
|
|
return Some(crate::insert::section_dialog(this, dismiss, cx).into_any_element());
|
|
}
|
|
Dialog::Ask { ask, field } => {
|
|
let prompt = crate::refs::ask_dialog(this, ask, field, dismiss, cx);
|
|
return Some(prompt.into_any_element());
|
|
}
|
|
Dialog::Link { text, url } => crate::refs::link_dialog(this, (text, url), dismiss, cx),
|
|
Dialog::Reference { marks, mark, show } => {
|
|
crate::refs::reference_dialog(this, (marks, mark, show), dismiss, cx)
|
|
}
|
|
Dialog::Output {
|
|
tab,
|
|
print,
|
|
all,
|
|
pdf,
|
|
} => {
|
|
let last = self
|
|
.tab(*tab)
|
|
.expect("a modal keeps its tab")
|
|
.view
|
|
.read(cx)
|
|
.pages()
|
|
.len();
|
|
let last = u32::try_from(last).expect("a page count");
|
|
crate::output::output_dialog(this, (*print, *all, *pdf, last), dismiss, cx)
|
|
}
|
|
Dialog::Table { columns, rows } => {
|
|
crate::insert::table_dialog(this, (*columns, *rows), dismiss, cx)
|
|
}
|
|
};
|
|
Some(card.into_any_element())
|
|
}
|
|
}
|
|
|
|
/// The New dialog: bundled templates and a local file (DOC-01).
|
|
fn templates(
|
|
this: Entity<Docs>,
|
|
dismiss: impl Fn(&mut Window, &mut App) + 'static,
|
|
cx: &mut Context<Docs>,
|
|
) -> Card {
|
|
let picks: Vec<Pick> = TEMPLATES
|
|
.iter()
|
|
.map(|template| Pick {
|
|
name: Docs::text(cx, &format!("doc.template.{}", template.key()), &[]),
|
|
icon: "▤".into(),
|
|
category: Docs::text(cx, "doc.template.category", &[]),
|
|
description: Docs::text(cx, &format!("doc.template.{}.about", template.key()), &[]),
|
|
markdown: template.preview(cx).into(),
|
|
})
|
|
.collect();
|
|
let used = this.clone();
|
|
let picker = TemplatePicker::new("doc-templates", Rc::new(picks)).on_use(move |ix, _, cx| {
|
|
used.update(cx, |docs, cx| {
|
|
docs.dialog = None;
|
|
docs.new_from(TEMPLATES[ix], cx);
|
|
})
|
|
});
|
|
let label = Docs::text(cx, "doc.new.from_file", &[]);
|
|
Card::new("doc-new", Docs::text(cx, "doc.new.title", &[]), dismiss)
|
|
.child(picker)
|
|
.action(move |close| {
|
|
Button::new("doc-new-file", label).on_click(move |_, window, cx| {
|
|
close(window, cx);
|
|
this.update(cx, |docs, cx| {
|
|
docs.pick(false, cx, |docs, path, cx| docs.new_from_file(&path, cx))
|
|
});
|
|
})
|
|
})
|
|
}
|