mirror of
https://github.com/FliegendeWurst/raspi-oled.git
synced 2024-12-04 07:09:06 +00:00
Tweak github draw
This commit is contained in:
parent
beee5fe970
commit
8ffaf1f809
@ -1,13 +1,15 @@
|
||||
use std::cell::RefCell;
|
||||
use std::{cell::RefCell, collections::HashSet};
|
||||
|
||||
use color_space::{Hsv, ToRgb};
|
||||
use embedded_graphics::{
|
||||
mono_font::{iso_8859_10::FONT_8X13, MonoTextStyleBuilder},
|
||||
pixelcolor::Rgb565,
|
||||
prelude::{DrawTarget, Point, RgbColor},
|
||||
primitives::Rectangle,
|
||||
text::Text,
|
||||
Drawable,
|
||||
Drawable, Pixel,
|
||||
};
|
||||
use rand_xoshiro::rand_core::RngCore;
|
||||
use raspi_oled::github::get_new_notifications;
|
||||
|
||||
use crate::{
|
||||
@ -42,7 +44,6 @@ impl<D: DrawTarget<Color = Rgb565>> Schedule<D> for GithubNotifications {
|
||||
return;
|
||||
}
|
||||
let max_lines = 8;
|
||||
let max_line_length = 16;
|
||||
let mut lines = vec![];
|
||||
let mut relevant = relevant.into_iter();
|
||||
while lines.len() < max_lines {
|
||||
@ -59,9 +60,7 @@ impl<D: DrawTarget<Color = Rgb565>> Schedule<D> for GithubNotifications {
|
||||
}
|
||||
lines.push(format!("{} #{}", parts[5], parts[7]));
|
||||
if lines.len() < max_lines {
|
||||
let mut desc = format!(" {}", x.subject.title);
|
||||
desc.truncate(desc.floor_char_boundary(max_line_length));
|
||||
lines.push(desc);
|
||||
lines.push(x.subject.title.clone());
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
@ -75,6 +74,7 @@ impl<D: DrawTarget<Color = Rgb565>> Schedule<D> for GithubNotifications {
|
||||
calls: RefCell::new(0),
|
||||
screen: &GITHUB,
|
||||
lines,
|
||||
circles: RefCell::new(vec![]),
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -84,36 +84,108 @@ struct GithubNotificationsDraw {
|
||||
calls: RefCell<usize>,
|
||||
screen: &'static SimpleScreensaver,
|
||||
lines: Vec<String>,
|
||||
circles: RefCell<Vec<((u32, u32), u32, Rgb565, Vec<(u32, u32)>)>>,
|
||||
}
|
||||
|
||||
impl<D: DrawTarget<Color = Rgb565>> Draw<D> for GithubNotificationsDraw {
|
||||
fn draw(&self, disp: &mut D, _rng: &mut crate::Rng) -> Result<bool, D::Error> {
|
||||
fn draw(&self, disp: &mut D, rng: &mut crate::Rng) -> Result<bool, D::Error> {
|
||||
let calls = *self.calls.borrow();
|
||||
if calls < 40 {
|
||||
if calls == 0 {
|
||||
self.screen
|
||||
.draw_all_colored(disp, Rgb565::new(0xff >> 3, 0xff >> 2, 0xff >> 3))?;
|
||||
}
|
||||
if calls < 70 {
|
||||
let hue = calls as f64 / 40.0 * 360.0;
|
||||
let hsv = Hsv::new(hue, 1.0, 1.0);
|
||||
let rgb = hsv.to_rgb();
|
||||
let r = rgb.r as u8 >> 3;
|
||||
let g = rgb.g as u8 >> 2;
|
||||
let b = rgb.b as u8 >> 3;
|
||||
self.screen.draw_all_colored(disp, Rgb565::new(r, g, b))?;
|
||||
let rgb = Rgb565::new(r, g, b);
|
||||
let mut x;
|
||||
let mut y;
|
||||
loop {
|
||||
x = rng.next_u32() % 128;
|
||||
y = rng.next_u32() % 128;
|
||||
if self.screen.get_pixel(x, y) == Rgb565::WHITE {
|
||||
break;
|
||||
}
|
||||
}
|
||||
disp.fill_contiguous(&Rectangle::new((x as i32, y as i32).into(), (1, 1).into()), Some(rgb))?;
|
||||
// advance other circles
|
||||
let mut circles = self.circles.borrow_mut();
|
||||
for ((ox, oy), radius, color, points) in &mut *circles {
|
||||
*radius += 1;
|
||||
let mut seen = HashSet::new();
|
||||
let mut next_points = vec![];
|
||||
loop {
|
||||
let mut new_points = vec![];
|
||||
for (x, y) in &*points {
|
||||
for (dx, dy) in [(-1, 0), (0, -1), (1, 0), (0, 1)] {
|
||||
let Some(x) = x.checked_add_signed(dx) else {
|
||||
continue;
|
||||
};
|
||||
let Some(y) = y.checked_add_signed(dy) else {
|
||||
continue;
|
||||
};
|
||||
if x >= 128 || y >= 128 {
|
||||
continue;
|
||||
}
|
||||
if self.screen.get_pixel(x, y) != Rgb565::WHITE {
|
||||
continue;
|
||||
}
|
||||
if seen.contains(&(x, y)) {
|
||||
continue;
|
||||
}
|
||||
seen.insert((x, y));
|
||||
let dist2 = x.abs_diff(*ox).pow(2) + y.abs_diff(*oy).pow(2);
|
||||
if dist2 > (*radius - 1).pow(2) && dist2 <= (*radius).pow(2) {
|
||||
new_points.push((x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
if new_points.is_empty() {
|
||||
break;
|
||||
}
|
||||
next_points.extend_from_slice(&new_points);
|
||||
*points = new_points;
|
||||
}
|
||||
disp.draw_iter(
|
||||
next_points
|
||||
.iter()
|
||||
.map(|&x| Pixel(Point::new(x.0 as _, x.1 as _), *color)),
|
||||
)?;
|
||||
*points = next_points;
|
||||
}
|
||||
circles.push(((x, y), 0, rgb, vec![(x, y)]));
|
||||
} else {
|
||||
let idx = calls - 70;
|
||||
disp.clear(Rgb565::BLACK)?;
|
||||
// fit 9 lines
|
||||
let max_line_length = 16;
|
||||
let text_style_clock = MonoTextStyleBuilder::new()
|
||||
.font(&FONT_8X13)
|
||||
.text_color(Rgb565::WHITE)
|
||||
.build();
|
||||
for (y, line) in self.lines.iter().enumerate() {
|
||||
Text::new(line, Point::new(0, (12 + y * 14) as _), text_style_clock).draw(disp)?;
|
||||
let mut line = if calls >= 139 {
|
||||
format!(" {line}")
|
||||
} else if line.len() > max_line_length {
|
||||
let line = format!(" {line} ");
|
||||
line[line.ceil_char_boundary(idx % line.len())..].to_string()
|
||||
} else {
|
||||
line.clone()
|
||||
};
|
||||
line.truncate(line.floor_char_boundary(max_line_length));
|
||||
Text::new(&line, Point::new(0, (12 + y * 14) as _), text_style_clock).draw(disp)?;
|
||||
}
|
||||
}
|
||||
*self.calls.borrow_mut() += 1;
|
||||
Ok(calls < 90)
|
||||
Ok(calls < 140)
|
||||
}
|
||||
|
||||
fn expired(&self) -> bool {
|
||||
*self.calls.borrow() > 90
|
||||
*self.calls.borrow() > 140
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
|
@ -105,6 +105,12 @@ impl SimpleScreensaver {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_pixel(&self, x: u32, y: u32) -> Rgb565 {
|
||||
let idx = y as usize * 128 + x as usize;
|
||||
let (red, green, blue) = (self.data[3 * idx], self.data[3 * idx + 1], self.data[3 * idx + 2]);
|
||||
Rgb565::new(red >> 3, green >> 2, blue >> 3)
|
||||
}
|
||||
|
||||
pub fn draw_all_colored<D: DrawTarget<Color = Rgb565>>(&self, disp: &mut D, color: Rgb565) -> Result<(), D::Error> {
|
||||
disp.fill_contiguous(
|
||||
&Rectangle::new((0, 0).into(), (128, 128).into()),
|
||||
|
Loading…
Reference in New Issue
Block a user