effing works
Signed-off-by: Frank Villaro-Dixon <frank@villaro-dixon.eu>
This commit is contained in:
parent
fa132e2230
commit
91172deddd
4 changed files with 170 additions and 50 deletions
29
src/apps.rs
29
src/apps.rs
|
@ -2,9 +2,9 @@ pub struct BeoApps {
|
|||
pub apps: Vec<Box<dyn App>>,
|
||||
}
|
||||
|
||||
struct MainMenu {
|
||||
pub last_id: usize,
|
||||
pub default_id: usize,
|
||||
pub struct MainMenu {
|
||||
// Can either be the default, or the current
|
||||
pub selected_id: usize,
|
||||
pub names: Vec<String>,
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ impl AppBase {
|
|||
|
||||
pub trait App {
|
||||
fn base(&self) -> &AppBase;
|
||||
fn base_mut(&mut self) -> &mut AppBase;
|
||||
// fn main_menu(&self) -> &MainMenu;
|
||||
}
|
||||
|
||||
|
@ -34,12 +35,15 @@ impl Spotify {
|
|||
base: AppBase {
|
||||
name: "Spotify".to_string(),
|
||||
main_menu: MainMenu {
|
||||
last_id: 0,
|
||||
default_id: 0,
|
||||
selected_id: 0,
|
||||
names: vec![
|
||||
"Playlists".to_string(),
|
||||
"Artists".to_string(),
|
||||
"Albums".to_string(),
|
||||
"Songs".to_string(),
|
||||
"Genres".to_string(),
|
||||
"New Releases".to_string(),
|
||||
"Charts".to_string(),
|
||||
],
|
||||
},
|
||||
},
|
||||
|
@ -51,6 +55,9 @@ impl App for Spotify {
|
|||
fn base(&self) -> &AppBase {
|
||||
&self.base
|
||||
}
|
||||
fn base_mut(&mut self) -> &mut AppBase {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
// Similar implementations for other apps like Radio and Settings
|
||||
|
@ -64,8 +71,7 @@ impl Radio {
|
|||
base: AppBase {
|
||||
name: "Radio".to_string(),
|
||||
main_menu: MainMenu {
|
||||
last_id: 0,
|
||||
default_id: 0,
|
||||
selected_id: 0,
|
||||
names: vec![
|
||||
"Favorites".to_string(),
|
||||
"Local".to_string(),
|
||||
|
@ -81,6 +87,9 @@ impl App for Radio {
|
|||
fn base(&self) -> &AppBase {
|
||||
&self.base
|
||||
}
|
||||
fn base_mut(&mut self) -> &mut AppBase {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
struct Settings {
|
||||
|
@ -93,8 +102,7 @@ impl Settings {
|
|||
base: AppBase {
|
||||
name: "Settings".to_string(),
|
||||
main_menu: MainMenu {
|
||||
last_id: 0,
|
||||
default_id: 0,
|
||||
selected_id: 0,
|
||||
names: vec![
|
||||
"Display".to_string(),
|
||||
"Sound".to_string(),
|
||||
|
@ -110,6 +118,9 @@ impl App for Settings {
|
|||
fn base(&self) -> &AppBase {
|
||||
&self.base
|
||||
}
|
||||
fn base_mut(&mut self) -> &mut AppBase {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_beo_apps() -> BeoApps {
|
||||
|
|
22
src/hid.rs
22
src/hid.rs
|
@ -133,23 +133,25 @@ impl Beo5Device {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
evdev::InputEventKind::Switch(switch) => {
|
||||
/*
|
||||
evdev::InputEventKind::Key(switch) => {
|
||||
match switch {
|
||||
evdev::SwitchType::LE=> {
|
||||
evdev::Key::BTN_DPAD_RIGHT => {
|
||||
if ev.value() == 1 {
|
||||
return Beo5Event::RightButtonPressed;
|
||||
return Some(Beo5Event::RightButtonPressed);
|
||||
} else {
|
||||
return Beo5Event::RightButtonReleased;
|
||||
return Some(Beo5Event::RightButtonReleased);
|
||||
}
|
||||
}
|
||||
evdev::Switch::SW_LEFT => {
|
||||
evdev::Key::BTN_DPAD_LEFT => {
|
||||
if ev.value() == 1 {
|
||||
return Beo5Event::LeftButtonPressed;
|
||||
} else {
|
||||
return Beo5Event::LeftButtonReleased;
|
||||
if ev.value() == 1 {
|
||||
return Some(Beo5Event::LeftButtonPressed);
|
||||
} else {
|
||||
return Some(Beo5Event::LeftButtonReleased);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
evdev::Switch::SW_GO => {
|
||||
if ev.value() == 1 {
|
||||
return Beo5Event::GoButtonPressed;
|
||||
|
@ -164,12 +166,12 @@ impl Beo5Device {
|
|||
return Beo5Event::PowerButtonReleased;
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Shouldn't be any other switches
|
||||
_ => {
|
||||
panic!("Unknown switch event: {ev:?}")
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
_ => {} //SYN et al
|
||||
}
|
||||
|
|
39
src/main.rs
39
src/main.rs
|
@ -13,9 +13,13 @@ use winit::{
|
|||
mod helpers;
|
||||
use helpers::PerfGraph;
|
||||
|
||||
// XXX rename to smth else
|
||||
struct Fonts {
|
||||
sans: FontId,
|
||||
bold: FontId,
|
||||
app_title: Paint,
|
||||
app_menu: Paint,
|
||||
app_menu_selected: Paint,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -41,13 +45,36 @@ fn run(
|
|||
surface: glutin::surface::Surface<glutin::surface::WindowSurface>,
|
||||
window: Window,
|
||||
) {
|
||||
let font_bold = canvas
|
||||
.add_font_mem(&resource!("assets/Roboto-Bold.ttf"))
|
||||
.expect("Cannot add font");
|
||||
let font_sans = canvas
|
||||
.add_font_mem(&resource!("assets/Roboto-Regular.ttf"))
|
||||
.expect("Cannot add font");
|
||||
|
||||
let mut app_title = Paint::color(Color::hex("FFFFFF"));
|
||||
app_title.set_font(&[font_bold]);
|
||||
app_title.set_text_baseline(Baseline::Top);
|
||||
app_title.set_text_align(Align::Center);
|
||||
app_title.set_font_size(20.);
|
||||
|
||||
let mut app_menu = Paint::color(Color::hex("F0F0FF"));
|
||||
app_menu.set_font(&[font_sans]);
|
||||
app_menu.set_text_baseline(Baseline::Top);
|
||||
app_menu.set_text_align(Align::Center);
|
||||
app_menu.set_font_size(14.);
|
||||
let mut app_menu_selected = Paint::color(Color::hex("F0F0FF"));
|
||||
app_menu_selected.set_font(&[font_bold]);
|
||||
app_menu_selected.set_text_baseline(Baseline::Top);
|
||||
app_menu_selected.set_text_align(Align::Center);
|
||||
app_menu_selected.set_font_size(14.);
|
||||
|
||||
let fonts = Fonts {
|
||||
sans: canvas
|
||||
.add_font_mem(&resource!("assets/Roboto-Regular.ttf"))
|
||||
.expect("Cannot add font"),
|
||||
bold: canvas
|
||||
.add_font_mem(&resource!("assets/Roboto-Bold.ttf"))
|
||||
.expect("Cannot add font"),
|
||||
sans: font_sans,
|
||||
bold: font_bold,
|
||||
app_title,
|
||||
app_menu,
|
||||
app_menu_selected,
|
||||
};
|
||||
|
||||
let apps = get_beo_apps();
|
||||
|
|
130
src/ui.rs
130
src/ui.rs
|
@ -6,9 +6,14 @@ use crate::apps::{App, BeoApps};
|
|||
use crate::roundy_math;
|
||||
|
||||
pub struct BeoUi {
|
||||
pub beo_apps: BeoApps,
|
||||
pub current_app_id: Option<usize>,
|
||||
pub laser_pct: f32,
|
||||
beo_apps: BeoApps,
|
||||
current_app_id: Option<usize>,
|
||||
|
||||
// Basically the id of the current menu. However it is float, because
|
||||
// it's UI and it will move smoothly on the screen.
|
||||
// XXX for items in menu
|
||||
//displayed_menu_item_id: Option<f32>,
|
||||
laser_pct: f32, // XXX this could be removed as only used when laser moved, could be given to fn directly
|
||||
}
|
||||
|
||||
const CANVAS_HEIGHT: f32 = 768.;
|
||||
|
@ -36,6 +41,18 @@ impl BeoUi {
|
|||
self.laser_pct = pct;
|
||||
self.choose_app_from_laser_pct();
|
||||
}
|
||||
Beo5Event::LeftButtonPressed => {
|
||||
println!("Left button pressed");
|
||||
if let Some(selected_app) = self.current_app_mut() {
|
||||
selected_app.base_mut().main_menu.selected_id += 1;
|
||||
}
|
||||
}
|
||||
Beo5Event::RightButtonPressed => {
|
||||
println!("Right button pressed");
|
||||
if let Some(selected_app) = self.current_app_mut() {
|
||||
selected_app.base_mut().main_menu.selected_id -= 1;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// TODO: pass event to current app
|
||||
}
|
||||
|
@ -44,18 +61,9 @@ impl BeoUi {
|
|||
|
||||
pub fn draw<T: Renderer>(&self, canvas: &mut Canvas<T>, fonts: &Fonts) {
|
||||
self.draw_main_menu(canvas, fonts);
|
||||
|
||||
if let Some(selected_app) = self.current_app() {
|
||||
let mut paint_title = Paint::color(Color::hex("FFFFFF"));
|
||||
paint_title.set_font(&[fonts.bold]);
|
||||
paint_title.set_text_baseline(Baseline::Top);
|
||||
paint_title.set_text_align(Align::Center);
|
||||
paint_title.set_font_size(20.);
|
||||
let _ = canvas.fill_text(
|
||||
CANVAS_WIDTH / 2.,
|
||||
10.,
|
||||
selected_app.base().name(),
|
||||
&paint_title,
|
||||
);
|
||||
self.draw_app(canvas, fonts, selected_app);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +83,6 @@ impl BeoUi {
|
|||
if delta < LASER_EPS_MATCH {
|
||||
self.current_app_id = Some(i);
|
||||
return;
|
||||
//Some(&self.beo_apps.apps[i]);
|
||||
}
|
||||
}
|
||||
self.current_app_id = None;
|
||||
|
@ -84,6 +91,9 @@ impl BeoUi {
|
|||
fn current_app(&self) -> Option<&Box<dyn App>> {
|
||||
self.current_app_id.map(|id| &self.beo_apps.apps[id])
|
||||
}
|
||||
fn current_app_mut(&mut self) -> Option<&mut Box<dyn App>> {
|
||||
self.current_app_id.map(|id| &mut self.beo_apps.apps[id])
|
||||
}
|
||||
|
||||
fn draw_main_menu<T: Renderer>(&self, canvas: &mut Canvas<T>, fonts: &Fonts) {
|
||||
let canvas_width = canvas.width();
|
||||
|
@ -103,10 +113,11 @@ impl BeoUi {
|
|||
y: canvas_height as f32,
|
||||
};
|
||||
|
||||
let apps = &self.beo_apps.apps;
|
||||
// draw the main apps in the circle
|
||||
let apps = &self.beo_apps.apps;
|
||||
let pts = main_menu_circle.get_equidistant_points(apps.len(), canvas_size);
|
||||
|
||||
// XXX To be taken from global struct
|
||||
let mut paint_normal = Paint::color(Color::hex("B7410E"));
|
||||
paint_normal.set_font(&[fonts.sans]);
|
||||
paint_normal.set_text_baseline(Baseline::Top);
|
||||
|
@ -115,15 +126,16 @@ impl BeoUi {
|
|||
paint_selected.set_font(&[fonts.bold]);
|
||||
paint_selected.set_text_baseline(Baseline::Top);
|
||||
|
||||
let mut i = 0;
|
||||
for app in apps {
|
||||
//if self.current_app == Some(app) {
|
||||
// let _ =
|
||||
// canvas.fill_text(pts[i].x, pts[i].y, apps[i].base().name(), &paint_selected);
|
||||
//} else {
|
||||
let _ = canvas.fill_text(pts[i].x, pts[i].y, app.base().name(), &paint_normal);
|
||||
// }
|
||||
i += 1;
|
||||
for appid in 0..apps.len() {
|
||||
let paint;
|
||||
if self.current_app_id == Some(appid) {
|
||||
paint = &paint_selected;
|
||||
} else {
|
||||
paint = &paint_normal;
|
||||
}
|
||||
|
||||
let app = &apps[appid];
|
||||
let _ = canvas.fill_text(pts[appid].x, pts[appid].y, app.base().name(), paint);
|
||||
}
|
||||
|
||||
// draw the laser
|
||||
|
@ -135,4 +147,72 @@ impl BeoUi {
|
|||
path.ellipse(ex + 15., ey, 30., 10.);
|
||||
canvas.fill_path(&path, &ellipse_color);
|
||||
}
|
||||
|
||||
fn draw_app<T: Renderer>(&self, canvas: &mut Canvas<T>, fonts: &Fonts, app: &Box<dyn App>) {
|
||||
/*
|
||||
let biggest_menu_name = app
|
||||
.base()
|
||||
.main_menu
|
||||
.names
|
||||
.iter()
|
||||
.max_by_key(|x| x.len())
|
||||
.unwrap();
|
||||
|
||||
let menu_separated_px = biggest_menu_name.len() as f32 * 8.;
|
||||
*/
|
||||
|
||||
let num_menu_elements_before = 1;
|
||||
let num_menu_elements_after = 2;
|
||||
// That means max 1 + >1< + 2 = 4 elements in total
|
||||
// Minimum aronud 3: 0 + >1< + 2
|
||||
|
||||
let current_menu_id = app.base().main_menu.selected_id;
|
||||
let menu_elements = &app.base().main_menu.names;
|
||||
|
||||
// Calculate indices for slices
|
||||
let start_before =
|
||||
(current_menu_id as isize - num_menu_elements_before as isize).max(0) as usize;
|
||||
let end_before = current_menu_id;
|
||||
let start_after = current_menu_id + 1;
|
||||
let end_after =
|
||||
((current_menu_id + 1 + num_menu_elements_after).min(menu_elements.len())) as usize;
|
||||
|
||||
// Safely getting slices using clamping
|
||||
let menu_elems_before = &menu_elements[start_before..end_before];
|
||||
let menu_elem_selected = &menu_elements[current_menu_id];
|
||||
let menu_elems_after = &menu_elements[start_after..end_after];
|
||||
|
||||
//println!("menu_elems_before: {:?}", menu_elems_before);
|
||||
//println!("current_menu: {:?}", menu_elem_selected);
|
||||
//println!("menu_elems_after: {:?}", menu_elems_after);
|
||||
|
||||
let mut toti = 0.;
|
||||
for i in 0..menu_elems_before.len() {
|
||||
let _ = canvas.fill_text(
|
||||
toti * 100. + 50.,
|
||||
CANVAS_HEIGHT - 80.,
|
||||
&menu_elems_before[i],
|
||||
&fonts.app_menu,
|
||||
);
|
||||
toti += 1.;
|
||||
}
|
||||
|
||||
let _ = canvas.fill_text(
|
||||
toti * 100. + 50.,
|
||||
CANVAS_HEIGHT - 80.,
|
||||
&menu_elem_selected,
|
||||
&fonts.app_menu_selected,
|
||||
);
|
||||
toti += 1.;
|
||||
|
||||
for i in 0..menu_elems_after.len() {
|
||||
let _ = canvas.fill_text(
|
||||
toti * 100. + 50.,
|
||||
CANVAS_HEIGHT - 80.,
|
||||
&menu_elems_after[i],
|
||||
&fonts.app_menu,
|
||||
);
|
||||
toti += 1.;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue