fixed up subframes and started work on refactoring into components

This commit is contained in:
emilis 2023-01-15 11:41:26 +00:00
parent cf0b013204
commit e6323d4009
5 changed files with 199 additions and 44 deletions

View File

@ -81,33 +81,60 @@ pub struct SigninPage {
hostname: String,
username: String,
cursor: SigninCursorLocation,
cursor_position: u16,
frame: Option<Frame>,
}
#[derive(Debug, Clone)]
enum SigninCursorLocation {
Hostname,
Username,
Next,
Hostname(u16),
Ok,
}
impl Default for SigninCursorLocation {
fn default() -> Self {
Self::Hostname
Self::Ok
}
}
impl SigninPage {
#[inline]
fn draw(&self) -> String {
fn draw(&self, highlight: ColorSet, normal: ColorSet) -> String {
const HEADER_Y: u16 = 1;
const HOSTNAME_Y: u16 = 3;
const OK_Y: u16 = 5;
let frame = self.frame.unwrap();
let fr_width = frame.size().0;
let total_width = fr_width / 3;
format!(
"{header}{hostname}",
header = frame.write_centered("login kk", 1)
hostname = frame.write_centered("instance:", 3),
"{header}{hostname}{retheme}{ok}",
header = frame.write_centered("login kk", HEADER_Y),
hostname = frame.write_centered(
&self.field_str(
highlight,
total_width,
"hostname",
"",
),
HOSTNAME_Y,
),
retheme = normal.to_string(),
ok = frame.write_centered("[ok]", OK_Y),
)
}
#[inline]
fn field_str(
&self,
color: ColorSet,
width: u16,
field: &str,
field_content: &str,
) -> String {
let unpadded = format!("{field}: {field_content}",);
let len = field.len() + field_content.len() + 2;
unpadded + &"_".repeat(width as usize - len)
}
}
impl Page for SigninPage {
@ -140,22 +167,25 @@ impl Page for SigninPage {
screen: &mut RawTerminal<Stdout>,
) -> Result<()> {
self.frame = Some(env.frame.sub(
env.theme.colors.subwin,
super::frame::FrameSize::ByPercent(80, 80),
env.theme.colors.subframe,
super::frame::FrameSize::ByPercent(50, 50),
2,
));
write!(
screen,
"{theme}{clear}{frame}{subframe}{show_cursor}{content}",
"{theme}{clear}{frame}{subframe}{content}{hide_cursor}",
theme = env.theme.frame(),
clear = clear::All,
frame = env.frame.frame_str(env.theme.primary()),
subframe = self
.frame
.unwrap()
.frame_str(ColorSet::default().to_string()),
show_cursor = cursor::Show,
content = self.draw(),
.frame_str(env.theme.colors.subwin.to_string()),
hide_cursor = cursor::Hide,
content = self.draw(
env.theme.colors.highlight,
env.theme.colors.subwin
),
)?;
screen.flush()?;

64
src/display/compose.rs Normal file
View File

@ -0,0 +1,64 @@
use std::ops::Deref;
use super::{frame::Frame, theme::ColorSet};
#[derive(Clone, Debug)]
pub enum Component {
String(String),
Goto(u16, u16),
Theme(ColorSet),
Clear,
}
impl Component {
pub fn prepare_for(&self, frame: &Frame) -> String {
match self {
Component::String(s) => s.to_owned(),
Component::Goto(x, y) => frame.goto(*x, *y),
Component::Theme(c) => c.to_string(),
Component::Clear => termion::clear::All.to_string(),
}
}
}
#[derive(Clone, Debug)]
pub struct Components(Vec<Component>);
impl Deref for Components {
type Target = Vec<Component>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Vec<Component>> for Components {
fn from(value: Vec<Component>) -> Self {
Self(value)
}
}
impl From<Component> for Components {
fn from(value: Component) -> Self {
Self(vec![value])
}
}
impl Components {
pub fn str_len(&self) -> u16 {
let mut len_cnt: u16 = 0;
for elem in &self.0 {
if let Component::String(s) = elem {
len_cnt += s.len() as u16;
}
}
len_cnt
}
pub fn concat_for(self, frame: &Frame) -> String {
self.0
.into_iter()
.map(|component| component.prepare_for(frame))
.collect::<String>()
}
}

View File

@ -28,10 +28,14 @@ impl Frame {
&self,
theme: ColorSet,
size: FrameSize,
width: u16,
border: u16,
) -> Frame {
let (p_width, p_height) = self.size();
size.abs_size((p_width - 1, p_height - 1), theme, width)
let sub_size = size.abs_size((
p_width - self.border * 2,
p_height - self.border * 2,
));
self.child_centered(sub_size, border, theme)
}
#[inline(always)]
@ -61,6 +65,8 @@ impl Frame {
#[inline(always)]
fn write_centered_clear(&self, s: &str) -> String {
let width = self.size().0 as usize;
let limit = width - self.border as usize * 2;
let s = if s.len() > limit { &s[..limit] } else { s };
let len = s.len();
let base_size = ((width - len) / 2) - self.border as usize;
format!(
@ -81,6 +87,8 @@ impl Frame {
#[inline(always)]
fn write_clear_to_end(&self, s: &str) -> String {
let limit = (self.size().0 - self.border * 2) as usize;
let s = if s.len() > limit { &s[..limit] } else { s };
let clear_length = self.size().0 as usize
- s.len()
- (self.border * 2) as usize;
@ -115,6 +123,10 @@ impl Frame {
#[inline(always)]
pub fn size(&self) -> (u16, u16) {
eprintln!(
"end.0: {}, start.0: {}, end.1: {}, start.1: {}",
self.end.0, self.start.0, self.end.1, self.start.1
);
(self.end.0 - self.start.0, self.end.1 - self.start.1)
}
@ -124,24 +136,71 @@ impl Frame {
width: u16,
) -> Result<Self, anyhow::Error> {
let term = termion::terminal_size()?;
// Swap term dimensions to use x/y
// let term = (term.1, term.0);
Ok(Self::from_bottom_right(term, term, width, theme))
}
#[inline(always)]
fn child_centered(
&self,
(pos_w, pos_h): (u16, u16),
border: u16,
theme: ColorSet,
) -> Frame {
let parent_offset = self.border / 2;
let (parent_w, parent_h) = self.size();
let (parent_w, parent_h) =
(parent_w - self.border, parent_h - self.border);
let start = (
1.max(
(parent_w - pos_w) / 2
+ ((parent_w - pos_w) % 2)
+ parent_offset,
),
1.max(
(parent_h - pos_h) / 2
+ ((parent_h - pos_h) % 2)
+ parent_offset,
),
);
let frame = Self {
end: (start.0 + pos_w, start.1 + pos_h),
start,
border,
theme,
};
frame
}
#[inline(always)]
fn from_bottom_right(
(pos_w, pos_h): (u16, u16),
(term_w, term_h): (u16, u16),
width: u16,
border: u16,
theme: ColorSet,
) -> Self {
Self {
start: (1.max(term_w - pos_w), 1.max(term_h - pos_h)),
end: (pos_w, pos_h),
border: width,
let start = (1.max(term_w - pos_w), 1.max(term_h - pos_h));
let frame = Self {
end: (start.0 + pos_w, start.1 + pos_h),
start,
border,
theme,
};
if frame.start.0 > frame.end.0 || frame.start.1 > frame.end.1
{
eprintln!(
"pos_w {}, pos_h {}, term_w {}, term_h {}, border {}",
pos_w, pos_h, term_w, term_h, border
);
panic!(
"start.0: {} end.0: {}, start.1: {}, end.1: {}",
frame.start.0,
frame.end.0,
frame.start.1,
frame.end.1
);
}
frame
}
pub fn frame_str(&self, body_theme: String) -> String {
@ -188,14 +247,12 @@ impl FrameSize {
fn abs_size(
&self,
(term_width, term_height): (u16, u16),
theme: ColorSet,
width: u16,
) -> Frame {
let pos = match self {
FrameSize::ByAbsolute(h, w) => {
) -> (u16, u16) {
match self {
FrameSize::ByAbsolute(w, h) => {
((*w).min(term_width), (*h).min(term_height))
}
FrameSize::ByPercent(h, w) => {
FrameSize::ByPercent(w, h) => {
// term_height = 100%
// x = h%
//
@ -205,12 +262,6 @@ impl FrameSize {
term_height * (*h).min(100) / 100,
)
}
};
Frame::from_bottom_right(
pos,
(term_width, term_height),
width,
theme,
)
}
}
}

View File

@ -13,6 +13,7 @@ use self::frame::Frame;
use self::theme::{Color, Theme};
pub mod body;
pub mod compose;
pub mod frame;
pub mod theme;
type Result<T> = std::result::Result<T, anyhow::Error>;
@ -54,11 +55,7 @@ impl Display for Event {
) -> std::fmt::Result {
match self {
Event::Key(key) => {
write!(
f,
"{}",
format!("{:#?}", key)
)
write!(f, "{}", format!("{:#?}", key))
}
}
}
@ -167,7 +164,7 @@ impl Screen {
clear = clear::All,
show_cursor = cursor::Show,
)?;
scr.flush();
scr.flush()?;
Ok(())
}

View File

@ -33,7 +33,9 @@ impl ToString for ColorSet {
pub struct Colors {
pub primary: ColorSet,
pub frame: ColorSet,
pub subframe: ColorSet,
pub subwin: ColorSet,
pub highlight: ColorSet,
}
impl Theme {}
@ -86,7 +88,18 @@ impl Default for Theme {
fg: "#ffe6ff".into(),
bg: "#330033".into(),
},
subwin: ColorSet{ fg: "#ffe6ff".into(), bg: "#110011".into() },
subframe: ColorSet{
fg: "#ffe6ff".into(),
bg: "#110011".into()
},
highlight: ColorSet{
fg: "#ffffff".into(),
bg: "#0000ff".into()
},
subwin: ColorSet{
fg: "#ffffff".into(),
bg: "#000000".into(),
},
},
}
}