WIP widgets struct -> trait work

This commit is contained in:
emilis 2023-01-20 14:51:36 +00:00
parent 1960123e3f
commit b39fa32674
4 changed files with 153 additions and 19 deletions

View File

@ -121,12 +121,12 @@ impl SectionWidth {
}
#[derive(Debug, Clone, Eq)]
pub struct Widget {
pub struct Section {
want_width: SectionWidth,
per_line: Vec<Token>,
}
impl PartialEq for Widget {
impl PartialEq for Section {
fn eq(&self, other: &Self) -> bool {
self.want_width == other.want_width
&& self.per_line.len() == other.per_line.len()
@ -137,7 +137,7 @@ impl PartialEq for Widget {
}
}
impl Widget {
impl Section {
pub fn new(
width: SectionWidth,
tokens_per_line: Vec<Token>,
@ -155,7 +155,7 @@ impl Widget {
#[derive(Debug, Clone, Eq)]
pub enum Instruction {
FixedHeight(Box<Instruction>, usize, Vec<Widget>),
FixedHeight(Box<Instruction>, usize, Vec<Section>),
End,
}
@ -260,15 +260,15 @@ impl Instruction {
Self::End
}
pub fn fixed(self, height: usize, widgets: Vec<Widget>) -> Self {
pub fn fixed(self, height: usize, widgets: Vec<Section>) -> Self {
Self::FixedHeight(Box::new(self), height, widgets)
}
}
#[derive(Clone, Debug)]
pub enum Plan {
FixedHeight(Box<Plan>, usize, Vec<Widget>),
Fill(Box<Plan>, Vec<Widget>),
FixedHeight(Box<Plan>, usize, Vec<Section>),
Fill(Box<Plan>, Vec<Section>),
End,
}
@ -277,7 +277,7 @@ impl Plan {
Self::End
}
fn fit_check(widgets: &Vec<Widget>) {
fn fit_check(widgets: &Vec<Section>) {
if widgets
.into_iter()
.map(|wd| wd.want_width.abs_size(100))
@ -341,12 +341,12 @@ impl Plan {
}
}
pub fn fixed(self, height: usize, widgets: Vec<Widget>) -> Self {
pub fn fixed(self, height: usize, widgets: Vec<Section>) -> Self {
Self::fit_check(&widgets);
Self::FixedHeight(Box::new(self), height, widgets)
}
pub fn fill(self, widgets: Vec<Widget>) -> Self {
pub fn fill(self, widgets: Vec<Section>) -> Self {
Self::fit_check(&widgets);
Self::Fill(Box::new(self), widgets)
}
@ -368,19 +368,19 @@ impl Plan {
mod tests {
use super::*;
fn test_widgets() -> (Widget, Widget, Widget) {
fn test_widgets() -> (Section, Section, Section) {
(
Widget::new(
Section::new(
SectionWidth::Third,
vec![Token::text("hello").centered()],
),
Widget::new(
Section::new(
SectionWidth::Third,
vec![Token::text("hello")
.pad_char('*', 16)
.bg(Color::RED)],
),
Widget::new(
Section::new(
SectionWidth::Third,
vec![Token::text("hello").limited(16).padded(20)],
),

View File

@ -1,10 +1,19 @@
use crate::component::Cursed;
use component::{Plan, Widget};
use component::{Plan, Section};
use event::Event;
use std::{
io::{Stdout, Write},
time::Duration,
};
use termion::raw::{IntoRawMode, RawTerminal};
use termion::{
clear,
input::{MouseTerminal, TermRead},
};
use termion::{
cursor,
raw::{IntoRawMode, RawTerminal},
screen::{AlternateScreen, IntoAlternateScreen},
};
use theme::{Color, ColorSet};
use token::Token;
@ -12,16 +21,45 @@ extern crate termion;
mod component;
mod theme;
mod token;
mod widget;
pub struct Display {
// needs to hold the termion display
screen: RawTerminal<Stdout>,
screen: MouseTerminal<RawTerminal<Stdout>>,
}
impl Display {
pub fn new() -> Result<Self, anyhow::Error> {
Ok(Self {
screen: std::io::stdout().into_raw_mode()?,
screen: MouseTerminal::from(
std::io::stdout().into_raw_mode()?,
),
})
}
pub fn testing_loop_show_input() -> ! {
let mut scr = MouseTerminal::from(
std::io::stdout()
.into_alternate_screen()
.unwrap()
.into_raw_mode()
.unwrap(),
);
write!(scr, "{}", clear::All).unwrap();
scr.flush().unwrap();
let inp = std::io::stdin();
let mut evs = inp.events();
loop {
let ev = evs.next().unwrap().unwrap();
write!(
scr,
"{clear}{oo}{:#?}",
ev,
oo = cursor::Goto(1, 1),
clear = clear::All
)
.unwrap();
scr.flush().unwrap();
}
}
}

95
kkdisp/src/widget.rs Normal file
View File

@ -0,0 +1,95 @@
use termion::event::MouseEvent;
use crate::token::Token;
type Result<T> = std::result::Result<T, anyhow::Error>;
pub trait Widget {
fn width(&self, max: usize) -> usize;
fn line(&self, line: usize) -> Option<&Token>;
fn on_event(
&mut self,
event: termion::event::Event,
) -> Result<()>;
}
pub enum WidgetWidth {
Percent(u8),
Absolute(usize),
}
impl WidgetWidth {
pub fn absolute(&self, budget: usize) -> usize {
match self {
Self::Percent(p) => {
// budget = 100%
// absolute = p%
// absolute = (p * budget) / 100
(*p as usize * budget) / 100
}
Self::Absolute(a) => *a,
}
}
}
pub struct ScrollableDisplay {
lines: Vec<Token>,
scrolled_offset: usize,
width: WidgetWidth,
}
impl ScrollableDisplay {
pub fn new(lines: Vec<Token>, width: WidgetWidth) -> Self {
Self {
lines,
width,
scrolled_offset: 0,
}
}
}
impl Widget for ScrollableDisplay {
fn on_event(
&mut self,
event: termion::event::Event,
) -> Result<()> {
let moving_value = match event {
termion::event::Event::Key(_) => todo!(),
termion::event::Event::Mouse(mus) => {
if let MouseEvent::Press(mus, _, _) = mus {
match mus {
termion::event::MouseButton::WheelUp => {
(self.lines.len() - 1)
.min(self.scrolled_offset + 1)
}
termion::event::MouseButton::WheelDown => {
if self.scrolled_offset == 0 {
0
} else {
self.scrolled_offset - 1
}
}
_ => 0,
}
} else {
0
}
}
termion::event::Event::Unsupported(_) => 0,
};
if moving_value == 0 {
return Ok(());
}
self.scrolled_offset = moving_value;
Ok(())
}
#[inline(always)]
fn width(&self, max: usize) -> usize {
self.width.absolute(max)
}
fn line(&self, line: usize) -> Option<&Token> {
self.lines.get(line + self.scrolled_offset)
}
}

View File

@ -3,5 +3,6 @@ use kkdisp::Display;
fn main() {
// let disp = Display::new();
// let widget_idk = Widget::new()
Display::test();
// Display::new();
Display::testing_loop_show_input();
}