Browse Source

Add file-explorer example to test file system via std

Note: there's some issue in release mode causing a segfault.
Currently investigating.
pull/14/head
AzureMarker 3 years ago
parent
commit
564d75e518
No known key found for this signature in database
GPG Key ID: 47A133F3BF9D03D3
  1. 156
      ctru-rs/examples/file-explorer.rs

156
ctru-rs/examples/file-explorer.rs

@ -0,0 +1,156 @@
//! A file explorer which shows off using standard library file system APIs to
//! read the SD card.
use ctru::applets::swkbd::{Button, Swkbd};
use ctru::console::Console;
use ctru::gfx::Screen;
use ctru::services::hid::KeyPad;
use ctru::services::{Apt, Hid};
use ctru::Gfx;
use std::fs::DirEntry;
use std::path::PathBuf;
fn main() {
ctru::init();
let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap();
let gfx = Gfx::default();
FileExplorer::init(&apt, &hid, &gfx).run();
}
struct FileExplorer<'a> {
apt: &'a Apt,
hid: &'a Hid,
gfx: &'a Gfx,
console: Console<'a>,
path: PathBuf,
entries: Vec<DirEntry>,
running: bool,
}
impl<'a> FileExplorer<'a> {
fn init(apt: &'a Apt, hid: &'a Hid, gfx: &'a Gfx) -> Self {
gfx.set_wide_mode(true);
let console = Console::init(gfx, Screen::Top);
FileExplorer {
apt,
hid,
gfx,
console,
path: PathBuf::from("/"),
entries: Vec::new(),
running: false,
}
}
fn run(&mut self) {
self.running = true;
self.print_menu();
while self.running && self.apt.main_loop() {
self.hid.scan_input();
let input = self.hid.keys_down();
if input.contains(KeyPad::KEY_START) {
break;
} else if input.contains(KeyPad::KEY_B) {
self.path.pop();
self.console.clear();
self.print_menu();
} else if input.contains(KeyPad::KEY_A) {
self.get_next_path();
}
self.gfx.wait_for_vblank();
}
}
fn print_menu(&mut self) {
println!("Viewing {}", self.path.display());
let dir_listing = std::fs::read_dir(&self.path).expect("Failed to open path");
self.entries = Vec::new();
for (i, entry) in dir_listing.enumerate() {
match entry {
Ok(entry) => {
println!("{:2} - {}", i, entry.file_name().to_string_lossy());
self.entries.push(entry);
// Paginate the output
if (i + 1) % 20 == 0 {
println!("Press A to go to next page, or Start to exit");
while self.apt.main_loop() {
self.hid.scan_input();
let input = self.hid.keys_down();
if input.contains(KeyPad::KEY_A) {
break;
}
if input.contains(KeyPad::KEY_START) {
self.running = false;
return;
}
self.gfx.wait_for_vblank();
}
}
}
Err(e) => {
println!("{} - Error: {}", i, e);
}
}
}
println!("Start to exit, A to select an entry by number, B to go up a directory");
}
fn get_next_path(&mut self) {
let mut keyboard = Swkbd::default();
let mut next_path_index = String::new();
match keyboard.get_utf8(&mut next_path_index) {
Ok(Button::Right) => {
// Clicked "OK"
let next_path_index: usize = match next_path_index.parse() {
Ok(index) => index,
Err(e) => {
println!("Number parsing error: {}", e);
return;
}
};
let next_entry = match self.entries.get(next_path_index) {
Some(entry) => entry,
None => {
println!("Input number of bounds");
return;
}
};
if !next_entry.file_type().unwrap().is_dir() {
println!("Not a directory: {}", next_path_index);
return;
}
self.console.clear();
self.path = next_entry.path();
self.print_menu();
}
Ok(Button::Left) => {
// Clicked "Cancel"
}
Ok(Button::Middle) => {
// This button wasn't shown
unreachable!()
}
Err(e) => {
panic!("Error: {:?}", e)
}
}
}
}
Loading…
Cancel
Save