fixed up subframes and started work on refactoring into components
This commit is contained in:
parent
cf0b013204
commit
e6323d4009
|
@ -81,33 +81,60 @@ pub struct SigninPage {
|
||||||
hostname: String,
|
hostname: String,
|
||||||
username: String,
|
username: String,
|
||||||
cursor: SigninCursorLocation,
|
cursor: SigninCursorLocation,
|
||||||
cursor_position: u16,
|
|
||||||
frame: Option<Frame>,
|
frame: Option<Frame>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum SigninCursorLocation {
|
enum SigninCursorLocation {
|
||||||
Hostname,
|
Hostname(u16),
|
||||||
Username,
|
Ok,
|
||||||
Next,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SigninCursorLocation {
|
impl Default for SigninCursorLocation {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Hostname
|
Self::Ok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SigninPage {
|
impl SigninPage {
|
||||||
#[inline]
|
#[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 frame = self.frame.unwrap();
|
||||||
|
let fr_width = frame.size().0;
|
||||||
|
let total_width = fr_width / 3;
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"{header}{hostname}",
|
"{header}{hostname}{retheme}{ok}",
|
||||||
header = frame.write_centered("login kk", 1)
|
header = frame.write_centered("login kk", HEADER_Y),
|
||||||
hostname = frame.write_centered("instance:", 3),
|
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 {
|
impl Page for SigninPage {
|
||||||
|
@ -140,22 +167,25 @@ impl Page for SigninPage {
|
||||||
screen: &mut RawTerminal<Stdout>,
|
screen: &mut RawTerminal<Stdout>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.frame = Some(env.frame.sub(
|
self.frame = Some(env.frame.sub(
|
||||||
env.theme.colors.subwin,
|
env.theme.colors.subframe,
|
||||||
super::frame::FrameSize::ByPercent(80, 80),
|
super::frame::FrameSize::ByPercent(50, 50),
|
||||||
2,
|
2,
|
||||||
));
|
));
|
||||||
write!(
|
write!(
|
||||||
screen,
|
screen,
|
||||||
"{theme}{clear}{frame}{subframe}{show_cursor}{content}",
|
"{theme}{clear}{frame}{subframe}{content}{hide_cursor}",
|
||||||
theme = env.theme.frame(),
|
theme = env.theme.frame(),
|
||||||
clear = clear::All,
|
clear = clear::All,
|
||||||
frame = env.frame.frame_str(env.theme.primary()),
|
frame = env.frame.frame_str(env.theme.primary()),
|
||||||
subframe = self
|
subframe = self
|
||||||
.frame
|
.frame
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.frame_str(ColorSet::default().to_string()),
|
.frame_str(env.theme.colors.subwin.to_string()),
|
||||||
show_cursor = cursor::Show,
|
hide_cursor = cursor::Hide,
|
||||||
content = self.draw(),
|
content = self.draw(
|
||||||
|
env.theme.colors.highlight,
|
||||||
|
env.theme.colors.subwin
|
||||||
|
),
|
||||||
)?;
|
)?;
|
||||||
screen.flush()?;
|
screen.flush()?;
|
||||||
|
|
||||||
|
|
|
@ -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>()
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,10 +28,14 @@ impl Frame {
|
||||||
&self,
|
&self,
|
||||||
theme: ColorSet,
|
theme: ColorSet,
|
||||||
size: FrameSize,
|
size: FrameSize,
|
||||||
width: u16,
|
border: u16,
|
||||||
) -> Frame {
|
) -> Frame {
|
||||||
let (p_width, p_height) = self.size();
|
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)]
|
#[inline(always)]
|
||||||
|
@ -61,6 +65,8 @@ impl Frame {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn write_centered_clear(&self, s: &str) -> String {
|
fn write_centered_clear(&self, s: &str) -> String {
|
||||||
let width = self.size().0 as usize;
|
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 len = s.len();
|
||||||
let base_size = ((width - len) / 2) - self.border as usize;
|
let base_size = ((width - len) / 2) - self.border as usize;
|
||||||
format!(
|
format!(
|
||||||
|
@ -81,6 +87,8 @@ impl Frame {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn write_clear_to_end(&self, s: &str) -> String {
|
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
|
let clear_length = self.size().0 as usize
|
||||||
- s.len()
|
- s.len()
|
||||||
- (self.border * 2) as usize;
|
- (self.border * 2) as usize;
|
||||||
|
@ -115,6 +123,10 @@ impl Frame {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn size(&self) -> (u16, u16) {
|
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)
|
(self.end.0 - self.start.0, self.end.1 - self.start.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,24 +136,71 @@ impl Frame {
|
||||||
width: u16,
|
width: u16,
|
||||||
) -> Result<Self, anyhow::Error> {
|
) -> Result<Self, anyhow::Error> {
|
||||||
let term = termion::terminal_size()?;
|
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))
|
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)]
|
#[inline(always)]
|
||||||
fn from_bottom_right(
|
fn from_bottom_right(
|
||||||
(pos_w, pos_h): (u16, u16),
|
(pos_w, pos_h): (u16, u16),
|
||||||
(term_w, term_h): (u16, u16),
|
(term_w, term_h): (u16, u16),
|
||||||
width: u16,
|
border: u16,
|
||||||
theme: ColorSet,
|
theme: ColorSet,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
let start = (1.max(term_w - pos_w), 1.max(term_h - pos_h));
|
||||||
start: (1.max(term_w - pos_w), 1.max(term_h - pos_h)),
|
let frame = Self {
|
||||||
end: (pos_w, pos_h),
|
end: (start.0 + pos_w, start.1 + pos_h),
|
||||||
border: width,
|
start,
|
||||||
|
border,
|
||||||
theme,
|
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 {
|
pub fn frame_str(&self, body_theme: String) -> String {
|
||||||
|
@ -188,14 +247,12 @@ impl FrameSize {
|
||||||
fn abs_size(
|
fn abs_size(
|
||||||
&self,
|
&self,
|
||||||
(term_width, term_height): (u16, u16),
|
(term_width, term_height): (u16, u16),
|
||||||
theme: ColorSet,
|
) -> (u16, u16) {
|
||||||
width: u16,
|
match self {
|
||||||
) -> Frame {
|
FrameSize::ByAbsolute(w, h) => {
|
||||||
let pos = match self {
|
|
||||||
FrameSize::ByAbsolute(h, w) => {
|
|
||||||
((*w).min(term_width), (*h).min(term_height))
|
((*w).min(term_width), (*h).min(term_height))
|
||||||
}
|
}
|
||||||
FrameSize::ByPercent(h, w) => {
|
FrameSize::ByPercent(w, h) => {
|
||||||
// term_height = 100%
|
// term_height = 100%
|
||||||
// x = h%
|
// x = h%
|
||||||
//
|
//
|
||||||
|
@ -205,12 +262,6 @@ impl FrameSize {
|
||||||
term_height * (*h).min(100) / 100,
|
term_height * (*h).min(100) / 100,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
Frame::from_bottom_right(
|
|
||||||
pos,
|
|
||||||
(term_width, term_height),
|
|
||||||
width,
|
|
||||||
theme,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use self::frame::Frame;
|
||||||
use self::theme::{Color, Theme};
|
use self::theme::{Color, Theme};
|
||||||
|
|
||||||
pub mod body;
|
pub mod body;
|
||||||
|
pub mod compose;
|
||||||
pub mod frame;
|
pub mod frame;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
type Result<T> = std::result::Result<T, anyhow::Error>;
|
type Result<T> = std::result::Result<T, anyhow::Error>;
|
||||||
|
@ -54,11 +55,7 @@ impl Display for Event {
|
||||||
) -> std::fmt::Result {
|
) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Event::Key(key) => {
|
Event::Key(key) => {
|
||||||
write!(
|
write!(f, "{}", format!("{:#?}", key))
|
||||||
f,
|
|
||||||
"{}",
|
|
||||||
format!("{:#?}", key)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,7 +164,7 @@ impl Screen {
|
||||||
clear = clear::All,
|
clear = clear::All,
|
||||||
show_cursor = cursor::Show,
|
show_cursor = cursor::Show,
|
||||||
)?;
|
)?;
|
||||||
scr.flush();
|
scr.flush()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,9 @@ impl ToString for ColorSet {
|
||||||
pub struct Colors {
|
pub struct Colors {
|
||||||
pub primary: ColorSet,
|
pub primary: ColorSet,
|
||||||
pub frame: ColorSet,
|
pub frame: ColorSet,
|
||||||
|
pub subframe: ColorSet,
|
||||||
pub subwin: ColorSet,
|
pub subwin: ColorSet,
|
||||||
|
pub highlight: ColorSet,
|
||||||
}
|
}
|
||||||
impl Theme {}
|
impl Theme {}
|
||||||
|
|
||||||
|
@ -86,7 +88,18 @@ impl Default for Theme {
|
||||||
fg: "#ffe6ff".into(),
|
fg: "#ffe6ff".into(),
|
||||||
bg: "#330033".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(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue