diff --git a/src/display/body.rs b/src/display/body.rs
index 5e33df9..7377556 100644
--- a/src/display/body.rs
+++ b/src/display/body.rs
@@ -81,33 +81,60 @@ pub struct SigninPage {
hostname: String,
username: String,
cursor: SigninCursorLocation,
- cursor_position: u16,
frame: Option,
}
#[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,
) -> 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()?;
diff --git a/src/display/compose.rs b/src/display/compose.rs
new file mode 100644
index 0000000..c5d88b7
--- /dev/null
+++ b/src/display/compose.rs
@@ -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);
+
+impl Deref for Components {
+ type Target = Vec;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl From> for Components {
+ fn from(value: Vec) -> Self {
+ Self(value)
+ }
+}
+
+impl From 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::()
+ }
+}
diff --git a/src/display/frame.rs b/src/display/frame.rs
index 0ce7a2e..25e4a8e 100644
--- a/src/display/frame.rs
+++ b/src/display/frame.rs
@@ -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 {
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,
- )
+ }
}
}
diff --git a/src/display/mod.rs b/src/display/mod.rs
index 50e3ab0..9e8cb04 100644
--- a/src/display/mod.rs
+++ b/src/display/mod.rs
@@ -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 = std::result::Result;
@@ -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(())
}
diff --git a/src/display/theme.rs b/src/display/theme.rs
index 562f3f0..b0bcd56 100644
--- a/src/display/theme.rs
+++ b/src/display/theme.rs
@@ -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(),
+ },
},
}
}