mod edit;
mod settings;
use crate::reply::lineages::Lineage;
use crate::ui::{Model, keys, theme};
use crate::verbs::Where;
pub const OPEN: &str = "config…";
pub const CLOSE: &str = "done";
pub const HEADING: &str = "config";
pub const WORKFLOW: &str = "workflow";
const NAME_WIDTH: f32 = 220.0;
pub const NOTHING_PICKED: &str = "pick a file to read";
pub const NOT_ANSWERED: &str = "waiting to hear which lineages this wall holds";
pub const NO_LINEAGES: &str = "this wall holds no config lineage";
pub const NOT_READ: &str = "waiting to hear what this file holds";
pub const NO_BYTES: &str = "this file has no bytes yet";
pub const NO_SETTINGS: &str = "this file has no typed settings — its bytes are the whole of it";
pub fn render(ui: &mut egui::Ui, model: &mut Model) -> bool {
if model.configuring.is_none() {
return false;
}
ui.heading(HEADING);
if let Some(aim) = model.aim.clone() {
ui.label(format!("on {} — {}", aim.address, aim.channel));
}
ui.horizontal_wrapped(|ui| {
if ui.button(CLOSE).clicked() {
model.close_configuring();
}
});
ui.separator();
egui::ScrollArea::vertical()
.id_salt(HEADING)
.auto_shrink(false)
.show(ui, |ui| {
destinations(ui, model);
ui.separator();
file(ui, model);
});
true
}
fn destinations(ui: &mut egui::Ui, model: &mut Model) {
let Some(aim) = model.aim.clone() else {
return;
};
ui.horizontal_wrapped(|ui| {
for at in [
Where::Brazen {
workspace: aim.address.clone(),
},
Where::LitanyModels,
Where::Cadence,
] {
pick(ui, model, &at);
}
});
workflow(ui, model);
match model.lineages.clone() {
None => {
ui.label(NOT_ANSWERED);
}
Some(rows) if rows.is_empty() => {
ui.label(NO_LINEAGES);
}
Some(rows) => {
for row in &rows {
lineage(ui, model, row, &aim.address);
}
}
}
}
fn workflow(ui: &mut egui::Ui, model: &mut Model) {
ui.horizontal_wrapped(|ui| {
if let Some(name) = model.workflow_box() {
ui.add(
egui::TextEdit::singleline(name)
.id(egui::Id::new(keys::WORKFLOW_ID))
.desired_width(NAME_WIDTH)
.hint_text(WORKFLOW),
);
}
let name = model.workflow_named();
let at = Where::LitanyWorkflow { name: name.clone() };
let chosen = model.configured().as_ref() == Some(&at);
let control = ui.add_enabled(
!name.is_empty(),
egui::SelectableLabel::new(chosen, WORKFLOW),
);
crate::ui::act::tag(&control, &[crate::verbs::CONFIG]);
if control.clicked() {
model.read_config(&at);
}
});
}
fn lineage(ui: &mut egui::Ui, model: &mut Model, row: &Lineage, workspace: &str) {
ui.colored_label(
theme::tone_ink(&crate::reply::convs::Tone::Weak),
row.line(),
);
ui.horizontal_wrapped(|ui| {
for path in &row.files {
pick(
ui,
model,
&Where::Branch {
workspace: workspace.to_owned(),
lineage: row.name.clone(),
path: path.clone(),
},
);
}
});
}
fn pick(ui: &mut egui::Ui, model: &mut Model, at: &Where) {
let chosen = model.configured().as_ref() == Some(at);
let control = ui.selectable_label(chosen, at.label());
crate::ui::act::tag(&control, &[crate::verbs::CONFIG]);
if control.clicked() {
model.read_config(at);
}
}
fn file(ui: &mut egui::Ui, model: &mut Model) {
let Some(at) = model.configured() else {
ui.label(NOTHING_PICKED);
return;
};
ui.label(at.label());
let Some(held) = model.config.clone() else {
ui.label(NOT_READ);
return;
};
settings::render(ui, &held);
ui.separator();
if held.text.is_empty() {
ui.label(NO_BYTES);
}
edit::render(ui, model, &at, &held.text);
}
#[cfg(test)]
mod tests;