file explorer file info, multi-byte char deleting fix
more docs, reversi game win/lose/tie and restart
This commit is contained in:
@@ -12,7 +12,7 @@ use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||
use ming_wm::messages::{ WindowMessage, WindowMessageResponse };
|
||||
use ming_wm::framebuffer::Dimensions;
|
||||
use ming_wm::themes::ThemeInfo;
|
||||
use ming_wm::utils::{ concat_paths, format_seconds };
|
||||
use ming_wm::utils::{ concat_paths, format_seconds, Substring };
|
||||
use ming_wm::fs::get_all_files;
|
||||
use ming_wm::ipc::listen;
|
||||
|
||||
@@ -47,7 +47,7 @@ impl WindowLike for AudioPlayer {
|
||||
self.command = String::new();
|
||||
} else if key_press.key == '𐘁' { //backspace
|
||||
if self.command.len() > 0 {
|
||||
self.command = self.command[..self.command.len() - 1].to_string();
|
||||
self.command = self.command.remove_last();
|
||||
}
|
||||
} else {
|
||||
self.command += &key_press.key.to_string();
|
||||
@@ -74,6 +74,9 @@ impl WindowLike for AudioPlayer {
|
||||
let time_string = format!("{}/{}", format_seconds(sink.get_pos().as_secs()), format_seconds(current.1));
|
||||
instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - time_string.len() * MONO_WIDTH as usize / 2, LINE_HEIGHT * 2 + 2], vec!["times-new-romono".to_string()], time_string, theme_info.text, theme_info.background, Some(0), Some(MONO_WIDTH)));
|
||||
}
|
||||
} else {
|
||||
instructions.push(DrawInstructions::Text([2, 2], vec!["times-new-roman".to_string()], "type to write commands, enter to execute.".to_string(), theme_info.text, theme_info.background, None, None));
|
||||
instructions.push(DrawInstructions::Text([2, 2 + LINE_HEIGHT], vec!["times-new-roman".to_string()], "See help in start menu for commands.".to_string(), theme_info.text, theme_info.background, None, None));
|
||||
}
|
||||
//
|
||||
instructions
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::vec::Vec;
|
||||
use std::vec;
|
||||
use std::fs::read_dir;
|
||||
use std::fs::{ read_dir, metadata, Metadata };
|
||||
use std::path::PathBuf;
|
||||
|
||||
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||
@@ -18,6 +18,13 @@ struct DirectoryChild {
|
||||
is_file: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq)]
|
||||
enum State {
|
||||
#[default]
|
||||
List,
|
||||
Info,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FileExplorer {
|
||||
dimensions: Dimensions,
|
||||
@@ -26,6 +33,8 @@ pub struct FileExplorer {
|
||||
//for scrolling and selecting dirs
|
||||
position: usize,
|
||||
top_position: usize,
|
||||
state: State,
|
||||
metadata: Option<Metadata>,
|
||||
}
|
||||
|
||||
impl WindowLike for FileExplorer {
|
||||
@@ -42,6 +51,7 @@ impl WindowLike for FileExplorer {
|
||||
WindowMessageResponse::JustRedraw
|
||||
},
|
||||
WindowMessage::KeyPress(key_press) => {
|
||||
self.state = State::List;
|
||||
if key_press.key == '𐘂' { //the enter key
|
||||
if self.current_dir_contents.len() > 0 {
|
||||
let selected_entry = &self.current_dir_contents[self.position];
|
||||
@@ -73,14 +83,20 @@ impl WindowLike for FileExplorer {
|
||||
//calculate position
|
||||
let max_height = self.dimensions[1] - HEIGHT;
|
||||
if self.position > self.top_position {
|
||||
let current_height = (self.position - self.top_position) * HEIGHT;
|
||||
let current_height = (self.position - self.top_position + 1) * HEIGHT;
|
||||
if current_height > self.dimensions[1] {
|
||||
self.top_position += (current_height - max_height) / HEIGHT + 1;
|
||||
//somehow this is slightly off sometimes
|
||||
self.top_position += (current_height - max_height).div_ceil(HEIGHT);
|
||||
}
|
||||
} else {
|
||||
self.top_position = self.position;
|
||||
};
|
||||
WindowMessageResponse::JustRedraw
|
||||
} else if key_press.key == 'i' {
|
||||
self.state = State::Info;
|
||||
let selected_entry = &self.current_dir_contents[self.position];
|
||||
self.metadata = Some(metadata(&selected_entry.path).unwrap());
|
||||
WindowMessageResponse::JustRedraw
|
||||
} else {
|
||||
WindowMessageResponse::DoNothing
|
||||
}
|
||||
@@ -91,29 +107,38 @@ impl WindowLike for FileExplorer {
|
||||
|
||||
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
|
||||
let mut instructions = Vec::new();
|
||||
//top bar with path name
|
||||
instructions.push(DrawInstructions::Text([5, 0], vec!["times-new-roman".to_string(), "shippori-mincho".to_string()], "Current: ".to_string() + &self.current_path.to_string_lossy().to_string(), theme_info.text, theme_info.background, None, None));
|
||||
//the actual files and directories
|
||||
let mut start_y = HEIGHT;
|
||||
let mut i = self.top_position;
|
||||
for entry in self.current_dir_contents.iter().skip(self.top_position) {
|
||||
if start_y > self.dimensions[1] {
|
||||
break;
|
||||
if self.state == State::List {
|
||||
//top bar with path name
|
||||
instructions.push(DrawInstructions::Text([5, 0], vec!["times-new-roman".to_string(), "shippori-mincho".to_string()], "Current: ".to_string() + &self.current_path.to_string_lossy().to_string(), theme_info.text, theme_info.background, None, None));
|
||||
//the actual files and directories
|
||||
let mut start_y = HEIGHT;
|
||||
let mut i = self.top_position;
|
||||
for entry in self.current_dir_contents.iter().skip(self.top_position) {
|
||||
if start_y > self.dimensions[1] {
|
||||
break;
|
||||
}
|
||||
let is_selected = i == self.position;
|
||||
if is_selected {
|
||||
instructions.push(DrawInstructions::Rect([0, start_y], [self.dimensions[0], HEIGHT], theme_info.top));
|
||||
}
|
||||
//unwrap_or not used because "Arguments passed to unwrap_or are eagerly evaluated", apparently
|
||||
let name = entry.override_name.clone();
|
||||
let name = if name.is_none() {
|
||||
entry.path.file_name().unwrap().to_os_string().into_string().unwrap()
|
||||
} else {
|
||||
name.unwrap()
|
||||
};
|
||||
instructions.push(DrawInstructions::Text([5, start_y], vec!["times-new-roman".to_string(), "shippori-mincho".to_string()], name, if is_selected { theme_info.top_text } else { theme_info.text }, if is_selected { theme_info.top } else { theme_info.background }, None, None));
|
||||
start_y += HEIGHT;
|
||||
i += 1;
|
||||
}
|
||||
let is_selected = i == self.position;
|
||||
if is_selected {
|
||||
instructions.push(DrawInstructions::Rect([0, start_y], [self.dimensions[0], HEIGHT], theme_info.top));
|
||||
}
|
||||
//unwrap_or not used because "Arguments passed to unwrap_or are eagerly evaluated", apparently
|
||||
let name = entry.override_name.clone();
|
||||
let name = if name.is_none() {
|
||||
entry.path.file_name().unwrap().to_os_string().into_string().unwrap()
|
||||
} else {
|
||||
name.unwrap()
|
||||
};
|
||||
instructions.push(DrawInstructions::Text([5, start_y], vec!["times-new-roman".to_string(), "shippori-mincho".to_string()], name, if is_selected { theme_info.top_text } else { theme_info.text }, if is_selected { theme_info.top } else { theme_info.background }, None, None));
|
||||
} else if self.state == State::Info {
|
||||
let metadata = self.metadata.clone().unwrap();
|
||||
let mut start_y = HEIGHT;
|
||||
let bytes_len = metadata.len();
|
||||
instructions.push(DrawInstructions::Text([5, start_y], vec!["times-new-roman".to_string()], format!("Size: {} mb ({} b)", bytes_len / (1024_u64).pow(2), bytes_len), theme_info.text, theme_info.background, None, None));
|
||||
start_y += HEIGHT;
|
||||
i += 1;
|
||||
//todo: other stuff
|
||||
}
|
||||
instructions
|
||||
}
|
||||
@@ -165,4 +190,3 @@ impl FileExplorer {
|
||||
pub fn main() {
|
||||
listen(FileExplorer::new());
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,15 @@ impl Tile {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq)]
|
||||
enum State {
|
||||
#[default]
|
||||
InProgress,
|
||||
WhiteWin,
|
||||
BlackWin,
|
||||
Tie,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Reversi {
|
||||
dimensions: Dimensions,
|
||||
@@ -50,6 +59,7 @@ struct Reversi {
|
||||
current_number: Option<u8>, //the first number of the tile that user wants to place piece on
|
||||
valid_moves: Vec<ValidMove>,
|
||||
white_turn: bool, //if false, black turn
|
||||
state: State,
|
||||
}
|
||||
|
||||
impl WindowLike for Reversi {
|
||||
@@ -62,7 +72,11 @@ impl WindowLike for Reversi {
|
||||
WindowMessageResponse::JustRedraw
|
||||
},
|
||||
WindowMessage::KeyPress(key_press) => {
|
||||
if let Ok(n) = key_press.key.to_string().parse::<u8>() {
|
||||
if self.state != State::InProgress {
|
||||
self.state = State::InProgress;
|
||||
self.new_tiles();
|
||||
self.valid_moves = self.get_valid_moves();
|
||||
} else if let Ok(n) = key_press.key.to_string().parse::<u8>() {
|
||||
if let Some(current_number) = self.current_number {
|
||||
let y = current_number as usize;
|
||||
let x = n as usize;
|
||||
@@ -74,6 +88,27 @@ impl WindowLike for Reversi {
|
||||
}
|
||||
self.white_turn = !self.white_turn;
|
||||
self.valid_moves = self.get_valid_moves();
|
||||
if self.valid_moves.len() == 0 {
|
||||
//game has ended
|
||||
let mut white_tiles = 0;
|
||||
let mut black_tiles = 0;
|
||||
for row in &self.tiles {
|
||||
for tile in row {
|
||||
if tile == &Tile::White {
|
||||
white_tiles += 1;
|
||||
} else if tile == &Tile::Black {
|
||||
black_tiles += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if white_tiles == black_tiles {
|
||||
self.state = State::Tie;
|
||||
} else if white_tiles > black_tiles {
|
||||
self.state = State::WhiteWin;
|
||||
} else {
|
||||
self.state = State::BlackWin;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.current_number = None;
|
||||
} else {
|
||||
@@ -124,6 +159,16 @@ impl WindowLike for Reversi {
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.state != State::InProgress {
|
||||
instructions.push(DrawInstructions::Rect([0, 0], [self.dimensions[0], 25], theme_info.background));
|
||||
instructions.push(DrawInstructions::Text([4, 4], vec!["times-new-roman".to_string()], if self.state == State::WhiteWin {
|
||||
"White wins, press any key to restart"
|
||||
} else if self.state == State::BlackWin {
|
||||
"Black wins, press any key to restart"
|
||||
} else {
|
||||
"Tie, press any key to restart"
|
||||
}.to_string(), theme_info.text, theme_info.background, None, None));
|
||||
}
|
||||
instructions
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||
use ming_wm::messages::{ WindowMessage, WindowMessageResponse };
|
||||
use ming_wm::framebuffer::Dimensions;
|
||||
use ming_wm::themes::ThemeInfo;
|
||||
use ming_wm::utils::concat_paths;
|
||||
use ming_wm::utils::{ concat_paths, Substring };
|
||||
use ming_wm::ipc::listen;
|
||||
|
||||
const MONO_WIDTH: u8 = 10;
|
||||
@@ -54,7 +54,7 @@ impl WindowLike for Terminal {
|
||||
if self.state == State::Input {
|
||||
if key_press.key == '𐘁' { //backspace
|
||||
if self.current_input.len() > 0 {
|
||||
self.current_input = self.current_input[..self.current_input.len() - 1].to_string();
|
||||
self.current_input = self.current_input.remove_last();
|
||||
} else {
|
||||
return WindowMessageResponse::DoNothing;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user