lernie 0.1.68

lernie: the operator seat — the window and wire client for a yog server
//! **The acts on one aimed wall** — the eight controls that hang under the
//! aimed row, in the order DESIGN §4.20 fixes: its rank, the enrollment, the
//! four reads of its configuration, the fleet, and the unmaking last.
//!
//! Split from [`super`] at the design-time budget on the seam that module's
//! own doc draws: that file is *one workspace's row* — the line it wears and
//! whether this seat can address it at all — and this is *what an operator
//! can do to it once it is aimed at*. The first changes when a row grows a
//! fact; this one when a wall-level op lands a control.

use super::{PIN, UNPIN};
use crate::reply::roster::WsRow;
use crate::ui::Model;

/// **Paint the band and take its clicks**, in the order DESIGN §4.20 fixes:
/// the rank, the enrollment, the four reads of its configuration, the fleet,
/// and the unmaking last.
pub(super) fn render(ui: &mut egui::Ui, model: &mut Model, row: &WsRow) {
    // **The pin is a control whose WORD and op follow the row's own rank**
    // (bl-7782), because the wire's two ops are assertions and not a toggle:
    // a pinned row is offered the unpin and an unpinned one the pin, so the
    // control always names the act it fires. Reading the rank off the row is
    // reading what is on the glass rather than holding a second opinion about
    // a list only the engine keeps.
    let pinned = row.pinned.is_some();
    let strip = ui.button(if pinned { UNPIN } else { PIN });
    crate::ui::act::tag(
        &strip,
        &[if pinned {
            crate::verbs::UNPIN.word
        } else {
            crate::verbs::PIN.word
        }],
    );
    if strip.clicked() {
        model.post_pin(!pinned);
    }
    if ui.button(crate::ui::enroll::OPEN).clicked() {
        model.begin_enrollment();
    }
    // **The read this gesture reaches**, exactly as the wall's own seat above
    // carries the conversation list's: opening the tuning pane is what makes
    // this seat read that wall's roles (`crate::state::Standing`), and the read
    // has no control of its own.
    let tune = ui.button(crate::ui::tuning::OPEN);
    crate::ui::act::tag(&tune, &[crate::verbs::ROLES.word]);
    if tune.clicked() {
        model.begin_tuning();
    }
    // **The sign-in hangs beside the tuning control**, because both are about
    // the wall's own configuration and neither destroys anything. It carries
    // the read the gesture reaches, exactly as the tuning control does:
    // opening the login pane is what makes this seat read that wall's provider
    // table (`crate::state::Standing`), and the read has no control of its own.
    let sign = ui.button(crate::ui::login::OPEN);
    crate::ui::act::tag(&sign, &[crate::verbs::PROVIDERS.word]);
    if sign.clicked() {
        model.begin_login();
    }
    // **The machines hang beside the sign-in**, because a wall's registered
    // clients are the third fact about its configuration and reading them
    // destroys nothing (bl-e53c). It carries the read the gesture reaches, as
    // the two above do: opening the pane is what makes this seat ask that wall
    // which machines it holds (`crate::state::Standing`), and the read has no
    // control of its own.
    let machines = ui.button(crate::ui::clients::OPEN);
    crate::ui::act::tag(&machines, &[crate::verbs::CLIENTS.word]);
    if machines.clicked() {
        model.begin_clients();
    }
    // **The config pane hangs beside them**, the fourth read of a wall's own
    // configuration and the last that destroys nothing (bl-5c53). It carries
    // the read the gesture reaches, as the three above do.
    let files = ui.button(crate::ui::config::OPEN);
    crate::ui::act::tag(&files, &[crate::verbs::LINEAGES.word]);
    if files.clicked() {
        model.begin_configuring();
    }
    // **The fleet hangs after the four reads and before the unmaking**
    // (bl-a43a), which is where an act that STARTS things belongs: it is the
    // one per-wall control that spawns drones and spends money, and it is not
    // the unmaking. It carries no `act:` token, because what it opens is a
    // pane and each of its five ACTS is tagged on the control inside that
    // fires one — the division `enroll a box…` keeps with `mint`. What it
    // does carry is its two READS, exactly as the tuning and login controls
    // carry theirs: opening the pane is what makes this seat ask that wall for
    // its attempts and for what its agents changed
    // (`crate::state::Standing`), and neither read has a control of its own.
    let drones = ui.button(crate::ui::fleet::OPEN);
    crate::ui::act::tag(
        &drones,
        &[crate::verbs::SCIENCE.word, crate::verbs::WORK_DIFF.word],
    );
    if drones.clicked() {
        model.begin_fleet();
    }
    // **The unmaking hangs here and LAST**, under the two controls that make
    // and change things, because that is the order a destructive act belongs in
    // wherever it is offered beside others (DESIGN §4.20). It carries no `act:`
    // token: what it opens is a pane, and the op is tagged on the control
    // inside it that actually fires one (`crate::ui::unmake`) — the same
    // division `enroll a box…` keeps with `mint`.
    if ui.button(crate::ui::unmake::OPEN).clicked() {
        model.begin_unmaking();
    }
}