WIP widgets struct -> trait work
This commit is contained in:
parent
1960123e3f
commit
b39fa32674
|
@ -121,12 +121,12 @@ impl SectionWidth {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq)]
|
#[derive(Debug, Clone, Eq)]
|
||||||
pub struct Widget {
|
pub struct Section {
|
||||||
want_width: SectionWidth,
|
want_width: SectionWidth,
|
||||||
per_line: Vec<Token>,
|
per_line: Vec<Token>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Widget {
|
impl PartialEq for Section {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.want_width == other.want_width
|
self.want_width == other.want_width
|
||||||
&& self.per_line.len() == other.per_line.len()
|
&& self.per_line.len() == other.per_line.len()
|
||||||
|
@ -137,7 +137,7 @@ impl PartialEq for Widget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget {
|
impl Section {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
width: SectionWidth,
|
width: SectionWidth,
|
||||||
tokens_per_line: Vec<Token>,
|
tokens_per_line: Vec<Token>,
|
||||||
|
@ -155,7 +155,7 @@ impl Widget {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq)]
|
#[derive(Debug, Clone, Eq)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
FixedHeight(Box<Instruction>, usize, Vec<Widget>),
|
FixedHeight(Box<Instruction>, usize, Vec<Section>),
|
||||||
End,
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,15 +260,15 @@ impl Instruction {
|
||||||
Self::End
|
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)
|
Self::FixedHeight(Box::new(self), height, widgets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Plan {
|
pub enum Plan {
|
||||||
FixedHeight(Box<Plan>, usize, Vec<Widget>),
|
FixedHeight(Box<Plan>, usize, Vec<Section>),
|
||||||
Fill(Box<Plan>, Vec<Widget>),
|
Fill(Box<Plan>, Vec<Section>),
|
||||||
End,
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ impl Plan {
|
||||||
Self::End
|
Self::End
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fit_check(widgets: &Vec<Widget>) {
|
fn fit_check(widgets: &Vec<Section>) {
|
||||||
if widgets
|
if widgets
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|wd| wd.want_width.abs_size(100))
|
.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::fit_check(&widgets);
|
||||||
Self::FixedHeight(Box::new(self), height, 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::fit_check(&widgets);
|
||||||
Self::Fill(Box::new(self), widgets)
|
Self::Fill(Box::new(self), widgets)
|
||||||
}
|
}
|
||||||
|
@ -368,19 +368,19 @@ impl Plan {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn test_widgets() -> (Widget, Widget, Widget) {
|
fn test_widgets() -> (Section, Section, Section) {
|
||||||
(
|
(
|
||||||
Widget::new(
|
Section::new(
|
||||||
SectionWidth::Third,
|
SectionWidth::Third,
|
||||||
vec![Token::text("hello").centered()],
|
vec![Token::text("hello").centered()],
|
||||||
),
|
),
|
||||||
Widget::new(
|
Section::new(
|
||||||
SectionWidth::Third,
|
SectionWidth::Third,
|
||||||
vec![Token::text("hello")
|
vec![Token::text("hello")
|
||||||
.pad_char('*', 16)
|
.pad_char('*', 16)
|
||||||
.bg(Color::RED)],
|
.bg(Color::RED)],
|
||||||
),
|
),
|
||||||
Widget::new(
|
Section::new(
|
||||||
SectionWidth::Third,
|
SectionWidth::Third,
|
||||||
vec![Token::text("hello").limited(16).padded(20)],
|
vec![Token::text("hello").limited(16).padded(20)],
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
use crate::component::Cursed;
|
use crate::component::Cursed;
|
||||||
use component::{Plan, Widget};
|
use component::{Plan, Section};
|
||||||
|
use event::Event;
|
||||||
use std::{
|
use std::{
|
||||||
io::{Stdout, Write},
|
io::{Stdout, Write},
|
||||||
time::Duration,
|
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 theme::{Color, ColorSet};
|
||||||
use token::Token;
|
use token::Token;
|
||||||
|
|
||||||
|
@ -12,16 +21,45 @@ extern crate termion;
|
||||||
mod component;
|
mod component;
|
||||||
mod theme;
|
mod theme;
|
||||||
mod token;
|
mod token;
|
||||||
|
mod widget;
|
||||||
|
|
||||||
pub struct Display {
|
pub struct Display {
|
||||||
// needs to hold the termion display
|
// needs to hold the termion display
|
||||||
screen: RawTerminal<Stdout>,
|
screen: MouseTerminal<RawTerminal<Stdout>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display {
|
impl Display {
|
||||||
pub fn new() -> Result<Self, anyhow::Error> {
|
pub fn new() -> Result<Self, anyhow::Error> {
|
||||||
Ok(Self {
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,5 +3,6 @@ use kkdisp::Display;
|
||||||
fn main() {
|
fn main() {
|
||||||
// let disp = Display::new();
|
// let disp = Display::new();
|
||||||
// let widget_idk = Widget::new()
|
// let widget_idk = Widget::new()
|
||||||
Display::test();
|
// Display::new();
|
||||||
|
Display::testing_loop_show_input();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue