Browse Source
Note: there's some issue in release mode causing a segfault. Currently investigating.pull/14/head
AzureMarker
3 years ago
1 changed files with 156 additions and 0 deletions
@ -0,0 +1,156 @@
@@ -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…
Reference in new issue