kk/src/display/body.rs

323 lines
8.2 KiB
Rust
Raw Normal View History

use std::io::{Stdout, Write};
use termion::{clear, cursor, raw::RawTerminal};
2023-01-14 23:07:07 +00:00
use super::{
2023-01-15 22:45:03 +00:00
compose::{Component, Components, HorizontalAlignment, Text},
frame::Frame,
theme::ColorSet,
Environment, Event, Page,
2023-01-14 23:07:07 +00:00
};
type Result<T> = std::result::Result<T, anyhow::Error>;
#[derive(Debug, Clone)]
pub enum Body {
Echo,
2023-01-14 23:07:07 +00:00
Signin(SigninPage),
}
impl Body {
2023-01-14 23:07:07 +00:00
fn echo(
env: Environment,
screen: &mut RawTerminal<Stdout>,
event: Event,
) -> Result<()> {
2023-01-15 22:45:03 +00:00
let echo_comps =
Components::break_into(format!("Event: {}", event))
.nextline_after_text(
0,
HorizontalAlignment::Left,
2023-01-15 23:17:17 +00:00
env.frame.inner_size().0,
2023-01-15 22:45:03 +00:00
);
write!(screen, "{}", env.frame.make(echo_comps))?;
2023-01-14 23:07:07 +00:00
screen.flush()?;
Ok(())
}
fn echo_init(
&self,
env: Environment,
screen: &mut RawTerminal<Stdout>,
) -> Result<()> {
write!(
screen,
"{hide}{clear}{fr}{cursor}",
2023-01-14 17:59:45 +00:00
clear = clear::All,
2023-01-14 23:07:07 +00:00
hide = cursor::Hide,
2023-01-16 15:23:44 +00:00
fr = env.frame.frame_str(env.theme.windows.primary),
2023-01-14 23:07:07 +00:00
cursor = env.frame.goto(0, 0),
)?;
screen.flush()?;
Ok(())
}
}
impl Page for Body {
fn receive_event(
&mut self,
env: Environment,
screen: &mut RawTerminal<Stdout>,
event: Event,
) -> Result<()> {
match self {
2023-01-14 23:07:07 +00:00
Body::Signin(b) => b.receive_event(env, screen, event)?,
Body::Echo => Body::echo(env, screen, event)?,
};
Ok(())
}
2023-01-14 23:07:07 +00:00
fn init(
&mut self,
env: Environment,
screen: &mut RawTerminal<Stdout>,
) -> Result<()> {
match self {
Body::Echo => self.echo_init(env, screen),
Body::Signin(signin) => signin.init(env, screen),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct SigninPage {
hostname: String,
token: String,
2023-01-14 23:07:07 +00:00
cursor: SigninCursorLocation,
frame: Option<Frame>,
}
#[derive(Debug, Clone)]
enum SigninCursorLocation {
2023-01-15 23:17:17 +00:00
Hostname,
Token,
Ok,
2023-01-14 23:07:07 +00:00
}
impl Default for SigninCursorLocation {
fn default() -> Self {
2023-01-15 23:17:17 +00:00
Self::Hostname
2023-01-14 23:07:07 +00:00
}
}
impl SigninPage {
#[inline]
2023-01-15 23:17:17 +00:00
fn next(&mut self) {
self.cursor = match self.cursor {
SigninCursorLocation::Hostname => {
SigninCursorLocation::Token
2023-01-15 23:17:17 +00:00
}
SigninCursorLocation::Token => SigninCursorLocation::Ok,
2023-01-15 23:17:17 +00:00
SigninCursorLocation::Ok => {
SigninCursorLocation::Hostname
}
}
}
#[inline]
fn previous(&mut self) {
self.cursor = match self.cursor {
SigninCursorLocation::Hostname => {
SigninCursorLocation::Ok
}
SigninCursorLocation::Token => {
SigninCursorLocation::Hostname
}
SigninCursorLocation::Ok => SigninCursorLocation::Token,
}
2023-01-15 23:17:17 +00:00
}
fn draw(
&self,
highlight: ColorSet,
normal: ColorSet,
) -> Components {
const HEADER_Y: u16 = 1;
const HOSTNAME_Y: u16 = 3;
const TOKEN_Y: u16 = 4;
const OK_Y: u16 = 6;
2023-01-14 23:07:07 +00:00
let frame = self.frame.unwrap();
2023-01-15 22:45:03 +00:00
let (w, _) = frame.inner_size();
let exp_w = w - (w / 3);
2023-01-15 22:45:03 +00:00
let (hostname_theme, token_theme, ok_theme) = match self
.cursor
{
SigninCursorLocation::Hostname => {
(highlight, normal, normal)
}
SigninCursorLocation::Token => {
(normal, highlight, normal)
}
SigninCursorLocation::Ok => (normal, normal, highlight),
2023-01-15 23:17:17 +00:00
};
2023-01-15 22:45:03 +00:00
vec![
frame
.prefix_centered_goto(
vec![Component::String(Text::Normal(
"login kk".into(),
))]
.into(),
HEADER_Y,
)
.0,
frame
.prefix_centered_goto(
self.field(
2023-01-15 23:17:17 +00:00
hostname_theme,
2023-01-15 22:45:03 +00:00
normal,
exp_w,
"hostname",
&self.hostname,
),
HOSTNAME_Y,
)
.0,
frame
.prefix_centered_goto(
self.field(
token_theme,
normal,
exp_w,
"token",
&self.token,
),
TOKEN_Y,
)
.0,
2023-01-15 23:17:17 +00:00
vec![Component::Theme(ok_theme)],
HorizontalAlignment::Center
.align(Text::Normal("[ok]".into()), w, OK_Y)
2023-01-15 22:45:03 +00:00
.0,
2023-01-15 23:17:17 +00:00
vec![Component::Theme(normal)],
2023-01-15 22:45:03 +00:00
]
.into_iter()
.flatten()
.collect::<Vec<Component>>()
.into()
2023-01-14 23:07:07 +00:00
}
#[inline]
2023-01-15 22:45:03 +00:00
fn field<C>(
&self,
color: ColorSet,
2023-01-15 22:45:03 +00:00
normal: ColorSet,
exp_width: u16,
field: C,
field_content: C,
) -> Components
where
C: Into<String>,
{
let (field, field_content) =
(field.into(), field_content.into());
let budget_for_content = exp_width - field.len() as u16 - 3;
vec![
Component::String((field + &": ").into()),
Component::Theme(color),
Component::String(Text::LimitedOrPadded(
field_content,
'_',
budget_for_content,
)),
Component::Theme(normal),
]
.into()
}
fn del(&mut self) {
match self.cursor {
SigninCursorLocation::Hostname => {
self.hostname.pop();
}
SigninCursorLocation::Token => {
self.token.pop();
}
SigninCursorLocation::Ok => {}
}
}
#[inline]
fn char(&mut self, c: char) {
2023-01-16 15:23:44 +00:00
if ['\t', '\n', '\r'].contains(&c) {
return;
}
match self.cursor {
SigninCursorLocation::Hostname => {
self.hostname.push(c);
}
SigninCursorLocation::Token => {
self.token.push(c);
}
SigninCursorLocation::Ok => {}
}
}
2023-01-14 23:07:07 +00:00
}
impl Page for SigninPage {
fn receive_event(
&mut self,
env: Environment,
screen: &mut RawTerminal<Stdout>,
event: Event,
) -> Result<()> {
match event {
Event::Key(key) => match key {
termion::event::Key::Char(c) => self.char(c),
termion::event::Key::Up => self.previous(),
termion::event::Key::Down => self.next(),
2023-01-16 15:23:44 +00:00
termion::event::Key::Backspace => self.del(),
2023-01-14 23:07:07 +00:00
termion::event::Key::Delete => {}
termion::event::Key::Left => {}
termion::event::Key::Right => {}
//
_ => {}
},
}
2023-01-15 23:17:17 +00:00
let fr = self.frame.unwrap();
write!(
screen,
"{}{}{}",
env.primary_frame(),
2023-01-16 15:23:44 +00:00
fr.frame_str(env.theme.windows.subwin),
2023-01-15 23:17:17 +00:00
fr.make(self.draw(
2023-01-16 15:23:44 +00:00
env.theme.windows.highlight,
env.theme.windows.subwin
2023-01-15 23:17:17 +00:00
))
)?;
screen.flush()?;
2023-01-14 23:07:07 +00:00
Ok(())
}
fn init(
&mut self,
env: Environment,
screen: &mut RawTerminal<Stdout>,
) -> Result<()> {
self.frame = Some(env.frame.sub(
2023-01-16 15:23:44 +00:00
env.theme.frames.inner,
super::frame::FrameSize::ByAbsolute(70, 10),
2023-01-14 23:07:07 +00:00
));
write!(
screen,
2023-01-16 15:23:44 +00:00
"{frame}{subframe}{content}{hide_cursor}",
frame = env.frame.frame_str(env.theme.windows.primary),
2023-01-14 23:07:07 +00:00
subframe = self
.frame
.unwrap()
2023-01-16 15:23:44 +00:00
.frame_str(env.theme.windows.subwin),
hide_cursor = cursor::Hide,
2023-01-15 22:45:03 +00:00
content = self.frame.unwrap().make(self.draw(
2023-01-16 15:23:44 +00:00
env.theme.windows.highlight,
env.theme.windows.subwin
2023-01-15 22:45:03 +00:00
))
)?;
screen.flush()?;
2023-01-14 23:07:07 +00:00
Ok(())
}
}