mirror of
https://github.com/LegitCamper/picocalc-os-rs.git
synced 2025-12-27 15:55:25 +00:00
selection menu works for multiple binaries, and shows selection box
This commit is contained in:
@@ -17,6 +17,7 @@ rp235x = ["embassy-rp/rp235xb"]
|
|||||||
trouble = ["dep:bt-hci", "dep:cyw43", "dep:cyw43-pio", "dep:trouble-host"]
|
trouble = ["dep:bt-hci", "dep:cyw43", "dep:cyw43-pio", "dep:trouble-host"]
|
||||||
defmt = [
|
defmt = [
|
||||||
"dep:defmt",
|
"dep:defmt",
|
||||||
|
"shared/defmt",
|
||||||
"panic-probe/print-defmt",
|
"panic-probe/print-defmt",
|
||||||
"embassy-executor/defmt",
|
"embassy-executor/defmt",
|
||||||
"embassy-time/defmt",
|
"embassy-time/defmt",
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ mod ui;
|
|||||||
mod usb;
|
mod usb;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
display::{FRAMEBUFFER, display_handler, init_display},
|
display::{FRAMEBUFFER, display_handler, init_display},
|
||||||
peripherals::{
|
peripherals::{
|
||||||
@@ -31,6 +29,7 @@ use crate::{
|
|||||||
ui::{SELECTIONS, clear_selection, ui_handler},
|
ui::{SELECTIONS, clear_selection, ui_handler},
|
||||||
};
|
};
|
||||||
use abi_sys::EntryFn;
|
use abi_sys::EntryFn;
|
||||||
|
use alloc::string::String;
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
pixelcolor::Rgb565,
|
pixelcolor::Rgb565,
|
||||||
prelude::{DrawTarget, RgbColor},
|
prelude::{DrawTarget, RgbColor},
|
||||||
@@ -38,6 +37,7 @@ use embedded_graphics::{
|
|||||||
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
use defmt::unwrap;
|
use defmt::unwrap;
|
||||||
use embassy_executor::{Executor, Spawner};
|
use embassy_executor::{Executor, Spawner};
|
||||||
use embassy_futures::{join::join, select::select};
|
use embassy_futures::{join::join, select::select};
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
|
|||||||
use embassy_time::Timer;
|
use embassy_time::Timer;
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
Drawable,
|
Drawable,
|
||||||
mono_font::{MonoTextStyle, ascii::FONT_9X15},
|
mono_font::{
|
||||||
|
MonoTextStyle,
|
||||||
|
ascii::{FONT_9X15, FONT_10X20},
|
||||||
|
},
|
||||||
pixelcolor::Rgb565,
|
pixelcolor::Rgb565,
|
||||||
prelude::{Dimensions, Point, Primitive, RgbColor, Size},
|
prelude::{Dimensions, Point, Primitive, RgbColor, Size},
|
||||||
primitives::{PrimitiveStyle, Rectangle},
|
primitives::{PrimitiveStyle, Rectangle},
|
||||||
@@ -14,8 +17,7 @@ use embedded_graphics::{
|
|||||||
};
|
};
|
||||||
use embedded_layout::{
|
use embedded_layout::{
|
||||||
align::{horizontal, vertical},
|
align::{horizontal, vertical},
|
||||||
layout::linear::LinearLayout,
|
layout::linear::{FixedMargin, LinearLayout},
|
||||||
object_chain::Chain,
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
use embedded_text::TextBox;
|
use embedded_text::TextBox;
|
||||||
@@ -29,19 +31,18 @@ pub async fn ui_handler() {
|
|||||||
if let Some(event) = keyboard::read_keyboard_fifo().await {
|
if let Some(event) = keyboard::read_keyboard_fifo().await {
|
||||||
if let KeyState::Pressed = event.state {
|
if let KeyState::Pressed = event.state {
|
||||||
match event.key {
|
match event.key {
|
||||||
KeyCode::JoyUp => {
|
KeyCode::Up => {
|
||||||
let mut selections = SELECTIONS.lock().await;
|
let mut selections = SELECTIONS.lock().await;
|
||||||
selections.up();
|
selections.up();
|
||||||
}
|
}
|
||||||
KeyCode::JoyDown => {
|
KeyCode::Down => {
|
||||||
let mut selections = SELECTIONS.lock().await;
|
let mut selections = SELECTIONS.lock().await;
|
||||||
selections.down();
|
selections.down();
|
||||||
}
|
}
|
||||||
KeyCode::Enter | KeyCode::JoyRight => {
|
KeyCode::Enter | KeyCode::Right => {
|
||||||
let selections = SELECTIONS.lock().await;
|
let selections = SELECTIONS.lock().await;
|
||||||
let selection = selections.selections
|
let selection =
|
||||||
[selections.current_selection as usize - 1]
|
selections.selections[selections.current_selection as usize].clone();
|
||||||
.clone();
|
|
||||||
|
|
||||||
let entry = unsafe { load_binary(&selection.short_name).await.unwrap() };
|
let entry = unsafe { load_binary(&selection.short_name).await.unwrap() };
|
||||||
BINARY_CH.send(entry).await;
|
BINARY_CH.send(entry).await;
|
||||||
@@ -56,8 +57,6 @@ pub async fn ui_handler() {
|
|||||||
clear_selection().await;
|
clear_selection().await;
|
||||||
draw_selection().await;
|
draw_selection().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer::after_millis(50).await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,12 +72,10 @@ pub async fn clear_selection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn draw_selection() {
|
async fn draw_selection() {
|
||||||
let file_names: Vec<FileName> = {
|
let mut guard = SELECTIONS.lock().await;
|
||||||
let guard = SELECTIONS.lock().await;
|
let file_names = &guard.selections.clone();
|
||||||
guard.selections.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
let text_style = MonoTextStyle::new(&FONT_9X15, Rgb565::WHITE);
|
let text_style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
|
||||||
let display_area = unsafe { FRAMEBUFFER.bounding_box() };
|
let display_area = unsafe { FRAMEBUFFER.bounding_box() };
|
||||||
|
|
||||||
const NO_BINS: &str = "No Programs found on SD Card. Ensure programs end with '.bin', and are located in the root directory";
|
const NO_BINS: &str = "No Programs found on SD Card. Ensure programs end with '.bin', and are located in the root directory";
|
||||||
@@ -96,37 +93,37 @@ async fn draw_selection() {
|
|||||||
.draw(unsafe { &mut FRAMEBUFFER })
|
.draw(unsafe { &mut FRAMEBUFFER })
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
let mut file_names = file_names.iter();
|
let mut views: alloc::vec::Vec<Text<MonoTextStyle<Rgb565>>> = Vec::new();
|
||||||
let Some(first) = file_names.next() else {
|
|
||||||
Text::new(NO_BINS, Point::zero(), text_style)
|
|
||||||
.draw(unsafe { &mut FRAMEBUFFER })
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
return;
|
for i in file_names {
|
||||||
};
|
views.push(Text::new(&i.long_name, Point::zero(), text_style));
|
||||||
|
}
|
||||||
|
|
||||||
let chain = Chain::new(Text::new(&first.long_name, Point::zero(), text_style));
|
let views_group = Views::new(views.as_mut_slice());
|
||||||
|
|
||||||
// for _ in 0..file_names.len() {
|
let layout = LinearLayout::vertical(views_group)
|
||||||
// let chain = chain.append(Text::new(
|
|
||||||
// file_names.next().unwrap(),
|
|
||||||
// Point::zero(),
|
|
||||||
// text_style,
|
|
||||||
// ));
|
|
||||||
// }
|
|
||||||
|
|
||||||
let layout = LinearLayout::vertical(chain)
|
|
||||||
.with_alignment(horizontal::Center)
|
.with_alignment(horizontal::Center)
|
||||||
|
.with_spacing(FixedMargin(5))
|
||||||
.arrange()
|
.arrange()
|
||||||
.align_to(&display_area, horizontal::Center, vertical::Center);
|
.align_to(&display_area, horizontal::Center, vertical::Center);
|
||||||
|
|
||||||
SELECTIONS.lock().await.last_bounds = Some(layout.bounds());
|
// draw selected box
|
||||||
|
let selected_bounds = layout
|
||||||
|
.inner()
|
||||||
|
.get(guard.current_selection as usize)
|
||||||
|
.expect("Selected binary missing")
|
||||||
|
.bounding_box();
|
||||||
|
Rectangle::new(selected_bounds.top_left, selected_bounds.size)
|
||||||
|
.into_styled(PrimitiveStyle::with_stroke(Rgb565::WHITE, 1))
|
||||||
|
.draw(unsafe { &mut FRAMEBUFFER })
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
guard.last_bounds = Some(layout.bounds());
|
||||||
|
|
||||||
layout.draw(unsafe { &mut FRAMEBUFFER }).unwrap();
|
layout.draw(unsafe { &mut FRAMEBUFFER }).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut sel = SELECTIONS.lock().await;
|
guard.changed = false;
|
||||||
sel.changed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -167,15 +164,17 @@ impl SelectionList {
|
|||||||
self.changed = true;
|
self.changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn down(&mut self) {
|
fn up(&mut self) {
|
||||||
if self.current_selection + 1 < self.selections.len() as u16 {
|
if self.current_selection > 0 {
|
||||||
self.current_selection += 1
|
self.current_selection -= 1;
|
||||||
|
self.changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn up(&mut self) {
|
fn down(&mut self) {
|
||||||
if self.current_selection > self.selections.len() as u16 {
|
if self.current_selection + 1 < self.selections.len() as u16 {
|
||||||
self.current_selection -= 1
|
self.current_selection += 1;
|
||||||
|
self.changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = []
|
||||||
defmt = ["dep:defmt"]
|
defmt = ["dep:defmt"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
Reference in New Issue
Block a user