mirror of https://github.com/TaKO8Ki/gobang
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.1 KiB
Rust
90 lines
2.1 KiB
Rust
use easy_cast::CastFloat;
|
|
use std::convert::TryFrom;
|
|
use tui::{
|
|
backend::Backend,
|
|
buffer::Buffer,
|
|
layout::{Margin, Rect},
|
|
style::{Color, Style},
|
|
symbols::{block::FULL, line::DOUBLE_VERTICAL},
|
|
widgets::Widget,
|
|
Frame,
|
|
};
|
|
|
|
struct Scrollbar {
|
|
max: u16,
|
|
pos: u16,
|
|
style_bar: Style,
|
|
style_pos: Style,
|
|
inside: bool,
|
|
border: bool,
|
|
}
|
|
|
|
impl Scrollbar {
|
|
fn new(max: usize, pos: usize, border: bool, inside: bool) -> Self {
|
|
Self {
|
|
max: u16::try_from(max).unwrap_or_default(),
|
|
pos: u16::try_from(pos).unwrap_or_default(),
|
|
style_pos: Style::default(),
|
|
style_bar: Style::default(),
|
|
inside,
|
|
border,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Widget for Scrollbar {
|
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
if area.height <= 2 {
|
|
return;
|
|
}
|
|
|
|
if self.max == 0 {
|
|
return;
|
|
}
|
|
|
|
let right = if self.inside {
|
|
area.right().saturating_sub(1)
|
|
} else {
|
|
area.right()
|
|
};
|
|
if right <= area.left() {
|
|
return;
|
|
};
|
|
|
|
let (bar_top, bar_height) = {
|
|
let scrollbar_area = area.inner(&Margin {
|
|
horizontal: 0,
|
|
vertical: if self.border { 1 } else { 0 },
|
|
});
|
|
|
|
(scrollbar_area.top(), scrollbar_area.height)
|
|
};
|
|
|
|
for y in bar_top..(bar_top + bar_height) {
|
|
buf.set_string(right, y, DOUBLE_VERTICAL, self.style_bar);
|
|
}
|
|
|
|
let progress = f32::from(self.pos) / f32::from(self.max);
|
|
let progress = if progress > 1.0 { 1.0 } else { progress };
|
|
let pos = f32::from(bar_height) * progress;
|
|
|
|
let pos: u16 = pos.cast_nearest();
|
|
let pos = pos.saturating_sub(1);
|
|
|
|
buf.set_string(right, bar_top + pos, FULL, self.style_pos);
|
|
}
|
|
}
|
|
|
|
pub fn draw_scrollbar<B: Backend>(
|
|
f: &mut Frame<B>,
|
|
r: Rect,
|
|
max: usize,
|
|
pos: usize,
|
|
border: bool,
|
|
inside: bool,
|
|
) {
|
|
let mut widget = Scrollbar::new(max, pos, border, inside);
|
|
widget.style_pos = Style::default().fg(Color::Blue);
|
|
f.render_widget(widget, r);
|
|
}
|