.
.
This commit is contained in:
+154
-156
@@ -1,18 +1,17 @@
|
|||||||
|
|
||||||
use volatile::Volatile;
|
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
use volatile::Volatile;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
|
||||||
use alloc::vec;
|
|
||||||
use alloc::borrow::ToOwned;
|
use alloc::borrow::ToOwned;
|
||||||
|
use alloc::vec;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Color {
|
pub enum Color {
|
||||||
Black = 0,
|
Black = 0,
|
||||||
Blue = 1,
|
Blue = 1,
|
||||||
Green = 2,
|
Green = 2,
|
||||||
Cyan = 3,
|
Cyan = 3,
|
||||||
@@ -35,16 +34,16 @@ pub enum Color {
|
|||||||
pub struct ColorCode(u8);
|
pub struct ColorCode(u8);
|
||||||
|
|
||||||
impl ColorCode {
|
impl ColorCode {
|
||||||
pub fn new(foreground: Color, background: Color) -> ColorCode {
|
pub fn new(foreground: Color, background: Color) -> ColorCode {
|
||||||
ColorCode((background as u8) << 5 | (foreground as u8))
|
ColorCode((background as u8) << 5 | (foreground as u8))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct ScreenChar {
|
struct ScreenChar {
|
||||||
character: u8,
|
character: u8,
|
||||||
colour: ColorCode,
|
colour: ColorCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const BUFFER_HEIGHT: usize = 25;
|
pub const BUFFER_HEIGHT: usize = 25;
|
||||||
@@ -52,34 +51,31 @@ pub const BUFFER_WIDTH: usize = 80;
|
|||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BufferSwap {
|
struct BufferSwap {
|
||||||
chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
||||||
}
|
}
|
||||||
struct CharGrid {
|
struct CharGrid {
|
||||||
chars: Vec<[ScreenChar; BUFFER_WIDTH]>
|
chars: Vec<[ScreenChar; BUFFER_WIDTH]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
col_pos: usize,
|
col_pos: usize,
|
||||||
pub col_code: ColorCode,
|
pub col_code: ColorCode,
|
||||||
buffer: &'static mut Buffer,
|
buffer: &'static mut Buffer,
|
||||||
userspace: BufferSwap,
|
userspace: BufferSwap,
|
||||||
upwards: CharGrid,
|
upwards: CharGrid,
|
||||||
downwards: CharGrid,
|
downwards: CharGrid,
|
||||||
pub sandbox: bool,
|
pub sandbox: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref RENDERER: Mutex<Renderer> = Mutex::new(Renderer {
|
pub static ref RENDERER: Mutex<Renderer> = Mutex::new(Renderer {
|
||||||
col_pos: 0,
|
col_pos: 0,
|
||||||
col_code: ColorCode::new(Color::White, Color::Black),
|
col_code: ColorCode::new(Color::White, Color::Black),
|
||||||
buffer: unsafe {
|
buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
|
||||||
&mut *(0xb8000 as *mut Buffer)
|
|
||||||
},
|
|
||||||
userspace: BufferSwap {
|
userspace: BufferSwap {
|
||||||
chars: [[ScreenChar {
|
chars: [[ScreenChar {
|
||||||
character: 179u8,
|
character: 179u8,
|
||||||
@@ -93,7 +89,7 @@ lazy_static! {
|
|||||||
colour: ColorCode::new(Color::White, Color::Black),
|
colour: ColorCode::new(Color::White, Color::Black),
|
||||||
}; 80]
|
}; 80]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
downwards: CharGrid {
|
downwards: CharGrid {
|
||||||
chars: vec![
|
chars: vec![
|
||||||
[ScreenChar {
|
[ScreenChar {
|
||||||
@@ -103,31 +99,30 @@ lazy_static! {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
|
pub fn text_mode(&mut self) -> Result<(), ()> {
|
||||||
pub fn text_mode(&mut self) -> Result<(), ()> {
|
if !self.sandbox {
|
||||||
if !self.sandbox { return Err(()) };
|
return Err(());
|
||||||
|
};
|
||||||
self.buffer_swap().unwrap();
|
self.buffer_swap().unwrap();
|
||||||
self.sandbox = false;
|
self.sandbox = false;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sandbox_mode(&mut self) -> Result<(), ()> {
|
pub fn sandbox_mode(&mut self) -> Result<(), ()> {
|
||||||
if self.sandbox { return Err(()) };
|
if self.sandbox {
|
||||||
|
return Err(());
|
||||||
|
};
|
||||||
self.buffer_swap().unwrap();
|
self.buffer_swap().unwrap();
|
||||||
self.sandbox = true;
|
self.sandbox = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buffer_swap(&mut self) -> Result<(), ()> {
|
fn buffer_swap(&mut self) -> Result<(), ()> {
|
||||||
|
|
||||||
for (i, _) in self.userspace.chars.clone().iter().enumerate() {
|
for (i, _) in self.userspace.chars.clone().iter().enumerate() {
|
||||||
|
|
||||||
let tmp = self.buffer.chars[i].clone();
|
let tmp = self.buffer.chars[i].clone();
|
||||||
|
|
||||||
for (j, col) in self.userspace.chars[i].clone().iter().enumerate() {
|
for (j, col) in self.userspace.chars[i].clone().iter().enumerate() {
|
||||||
@@ -142,122 +137,127 @@ impl Renderer {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_frame(&mut self, frame: [ [ char; BUFFER_WIDTH ]; BUFFER_HEIGHT]) {
|
pub fn render_frame(&mut self, frame: [[char; BUFFER_WIDTH]; BUFFER_HEIGHT]) {
|
||||||
for (i, row) in frame.iter().enumerate() {
|
for (i, row) in frame.iter().enumerate() {
|
||||||
for (j, col) in row.iter().enumerate() {
|
for (j, col) in row.iter().enumerate() {
|
||||||
|
if let Some(c) = self.fancy_char(*col) {
|
||||||
|
self.buffer.chars[i][j].write(ScreenChar {
|
||||||
|
character: c,
|
||||||
|
colour: self.col_code,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.buffer.chars[i][j].write(ScreenChar {
|
||||||
|
character: *col as u8,
|
||||||
|
colour: self.col_code,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(c) = self.fancy_char(*col) {
|
pub fn write_string(&mut self, string: &str) {
|
||||||
self.buffer.chars[i][j].write(ScreenChar { character: c, colour: self.col_code});
|
for ch in string.chars() {
|
||||||
} else {
|
if let Some(x) = self.fancy_char(ch) {
|
||||||
self.buffer.chars[i][j].write(ScreenChar { character: *col as u8, colour: self.col_code});
|
self.write_byte(x)
|
||||||
}
|
} else {
|
||||||
}
|
match ch as u8 {
|
||||||
}
|
0x20..=0xff | b'\n' => self.write_byte(ch as u8),
|
||||||
}
|
_ => self.write_byte(0xfe),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fancy_char(&self, ch: char) -> Option<u8> {
|
||||||
|
let res: u8 = match ch {
|
||||||
|
'│' => 179,
|
||||||
|
'─' => 196,
|
||||||
|
'┴' => 193,
|
||||||
|
'┤' => 180,
|
||||||
|
'═' => 205,
|
||||||
|
'║' => 186,
|
||||||
|
'╗' => 187,
|
||||||
|
'╝' => 188,
|
||||||
|
'╚' => 200,
|
||||||
|
'╔' => 201,
|
||||||
|
'»' => 175,
|
||||||
|
'┐' => 191,
|
||||||
|
'└' => 192,
|
||||||
|
'┘' => 217,
|
||||||
|
'┌' => 218,
|
||||||
|
'┼' => 197,
|
||||||
|
'░' => 176,
|
||||||
|
'▓' => 178,
|
||||||
|
'«' => 174,
|
||||||
|
'»' => 175,
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_string(&mut self, string: &str) {
|
pub fn backspace(&mut self) -> Result<(), ()> {
|
||||||
for ch in string.chars() {
|
if self.col_pos == 0 {
|
||||||
|
self.undonewline();
|
||||||
|
}
|
||||||
|
self.col_pos -= 1;
|
||||||
|
let row = BUFFER_HEIGHT - 1;
|
||||||
|
let col = self.col_pos;
|
||||||
|
|
||||||
if let Some(x) = self.fancy_char(ch) {
|
let blank = ScreenChar {
|
||||||
self.write_byte(x)
|
character: b' ',
|
||||||
} else {
|
colour: self.col_code,
|
||||||
match ch as u8 {
|
};
|
||||||
0x20..=0xff | b'\n' => self.write_byte(ch as u8),
|
self.buffer.chars[row][col].write(blank);
|
||||||
_ => self.write_byte(0xfe),
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fancy_char(&self, ch: char) -> Option<u8> {
|
pub fn write_byte(&mut self, byte: u8) {
|
||||||
let res: u8 = match ch {
|
match byte {
|
||||||
'│' => 179,
|
b'\n' => self.newline(),
|
||||||
'─' => 196,
|
byte => {
|
||||||
'┴' => 193,
|
if self.col_pos >= BUFFER_WIDTH {
|
||||||
'┤' => 180,
|
self.newline();
|
||||||
'═' => 205,
|
}
|
||||||
'║' => 186,
|
let row = BUFFER_HEIGHT - 1;
|
||||||
'╗' => 187,
|
let col = self.col_pos;
|
||||||
'╝' => 188,
|
let col_code = self.col_code;
|
||||||
'╚' => 200,
|
self.buffer.chars[row][col].write(ScreenChar {
|
||||||
'╔' => 201,
|
character: byte,
|
||||||
'»' => 175,
|
colour: col_code,
|
||||||
'┐' => 191,
|
});
|
||||||
'└' => 192,
|
self.col_pos += 1
|
||||||
'┘' => 217,
|
}
|
||||||
'┌' => 218,
|
}
|
||||||
'┼' => 197,
|
}
|
||||||
'░' => 176,
|
fn newline(&mut self) {
|
||||||
'▓' => 178,
|
for row in 1..BUFFER_HEIGHT {
|
||||||
_ => { return None; }
|
for col in 0..BUFFER_WIDTH {
|
||||||
};
|
let character = self.buffer.chars[row][col].read();
|
||||||
Some(res)
|
self.buffer.chars[row - 1][col].write(character);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
self.clear_row(BUFFER_HEIGHT - 1);
|
||||||
|
self.col_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn backspace(&mut self) -> Result<(), ()> {
|
pub fn undonewline(&mut self) {
|
||||||
if self.col_pos == 0 {
|
for row in (0..BUFFER_HEIGHT - 1).rev() {
|
||||||
self.undonewline();
|
for col in 0..BUFFER_WIDTH {
|
||||||
}
|
let character = self.buffer.chars[row][col].read();
|
||||||
self.col_pos -= 1;
|
self.buffer.chars[row + 1][col].write(character);
|
||||||
let row = BUFFER_HEIGHT -1;
|
}
|
||||||
let col = self.col_pos;
|
}
|
||||||
|
self.clear_row(0);
|
||||||
|
self.col_pos = BUFFER_WIDTH;
|
||||||
|
}
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
for row in (0..BUFFER_HEIGHT - 1).rev() {
|
||||||
|
self.clear_row(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let blank = ScreenChar {
|
|
||||||
character: b' ',
|
|
||||||
colour: self.col_code,
|
|
||||||
};
|
|
||||||
self.buffer.chars[row][col].write(blank);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_byte(&mut self, byte: u8) {
|
|
||||||
match byte {
|
|
||||||
b'\n' => {
|
|
||||||
self.newline()
|
|
||||||
},
|
|
||||||
byte => {
|
|
||||||
if self.col_pos >= BUFFER_WIDTH {
|
|
||||||
self.newline();
|
|
||||||
}
|
|
||||||
let row = BUFFER_HEIGHT -1;
|
|
||||||
let col = self.col_pos;
|
|
||||||
let col_code = self.col_code;
|
|
||||||
self.buffer.chars[row][col].write(ScreenChar {
|
|
||||||
character: byte,
|
|
||||||
colour: col_code,
|
|
||||||
});
|
|
||||||
self.col_pos += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn newline(&mut self) {
|
|
||||||
for row in 1..BUFFER_HEIGHT {
|
|
||||||
for col in 0..BUFFER_WIDTH {
|
|
||||||
let character = self.buffer.chars[row][col].read();
|
|
||||||
self.buffer.chars[row - 1][col].write(character);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.clear_row(BUFFER_HEIGHT -1);
|
|
||||||
self.col_pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn undonewline(&mut self) {
|
|
||||||
for row in (0..BUFFER_HEIGHT-1).rev() {
|
|
||||||
for col in 0..BUFFER_WIDTH {
|
|
||||||
let character = self.buffer.chars[row][col].read();
|
|
||||||
self.buffer.chars[row + 1][col].write(character);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.clear_row(0);
|
|
||||||
self.col_pos = BUFFER_WIDTH;
|
|
||||||
}
|
|
||||||
pub fn clear(&mut self) {
|
|
||||||
for row in (0..BUFFER_HEIGHT-1).rev() {
|
|
||||||
self.clear_row(row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear_row(&mut self, row: usize) {
|
fn clear_row(&mut self, row: usize) {
|
||||||
let blank = ScreenChar {
|
let blank = ScreenChar {
|
||||||
character: b' ',
|
character: b' ',
|
||||||
@@ -270,20 +270,18 @@ impl Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Write for Renderer {
|
impl fmt::Write for Renderer {
|
||||||
fn write_str(&mut self, string:&str) -> fmt::Result {
|
fn write_str(&mut self, string: &str) -> fmt::Result {
|
||||||
self.write_string(string);
|
self.write_string(string);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(args: fmt::Arguments, cols: (Color, Color)) {
|
pub fn write(args: fmt::Arguments, cols: (Color, Color)) {
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use x86_64::instructions::interrupts;
|
use x86_64::instructions::interrupts;
|
||||||
interrupts::without_interrupts(|| {
|
interrupts::without_interrupts(|| {
|
||||||
let mut writer = RENDERER.lock();
|
let mut writer = RENDERER.lock();
|
||||||
writer.col_code = ColorCode::new(cols.0, cols.1);
|
writer.col_code = ColorCode::new(cols.0, cols.1);
|
||||||
writer.write_fmt(args).unwrap()
|
writer.write_fmt(args).unwrap()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,19 +25,17 @@ impl Pos {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// all interface elements must implement this trait in order to be
|
/// all interface elements must implement this trait in order to be
|
||||||
/// rendered on the screen
|
/// rendered on the screen
|
||||||
pub trait Element {
|
pub trait Element {
|
||||||
// default behaviour for all elements
|
// default behaviour for all elements
|
||||||
|
|
||||||
fn render(&self) -> (Vec<Vec<char>>, (usize, usize)) {
|
fn render(&self) -> (Vec<Vec<char>>, Pos) {
|
||||||
// recursive method for rendering the
|
// recursive method for rendering the
|
||||||
// specified frame to the screen
|
// specified frame to the screen
|
||||||
// insert rendering code for specific frame here
|
// insert rendering code for specific frame here
|
||||||
// this should also render all children of the element
|
// this should also render all children of the element
|
||||||
(Vec::<Vec<char>>::new(), (0, 0))
|
(Vec::<Vec<char>>::new(), Pos::new(0, 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,16 +44,16 @@ pub struct Container {
|
|||||||
// other containers together
|
// other containers together
|
||||||
frame: Vec<Vec<char>>,
|
frame: Vec<Vec<char>>,
|
||||||
elements: Vec<Box<dyn Element>>,
|
elements: Vec<Box<dyn Element>>,
|
||||||
position: (usize, usize), // x,y
|
position: Pos, // x,y
|
||||||
//
|
//
|
||||||
outlined: bool,
|
outlined: bool,
|
||||||
dimensions: (usize, usize), // x,y
|
dimensions: Pos, // x,y
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Container {
|
impl Container {
|
||||||
fn new(position: (usize, usize), dimensions: (usize, usize), outlined: bool) -> Container {
|
fn new(position: Pos, dimensions: Pos, outlined: bool) -> Container {
|
||||||
Self {
|
Self {
|
||||||
frame: vec![vec![' '; dimensions.0 as usize]; dimensions.1 as usize],
|
frame: vec![vec![' '; dimensions.x as usize]; dimensions.y as usize],
|
||||||
elements: Vec::new(),
|
elements: Vec::new(),
|
||||||
position,
|
position,
|
||||||
outlined,
|
outlined,
|
||||||
@@ -68,7 +66,7 @@ impl Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Element for Container {
|
impl Element for Container {
|
||||||
fn render(&self) -> (Vec<Vec<char>>, (usize, usize)) {
|
fn render(&self) -> (Vec<Vec<char>>, Pos) {
|
||||||
// returns all elements as a single frame
|
// returns all elements as a single frame
|
||||||
|
|
||||||
let mut charmap = Vec::<Vec<char>>::new();
|
let mut charmap = Vec::<Vec<char>>::new();
|
||||||
@@ -78,23 +76,7 @@ impl Element for Container {
|
|||||||
let mut lastline: Vec<char>;
|
let mut lastline: Vec<char>;
|
||||||
|
|
||||||
if self.outlined {
|
if self.outlined {
|
||||||
frstline = vec!['┌'];
|
charmap = gen_outline(self.dimensions);
|
||||||
midlines = vec!['│'];
|
|
||||||
lastline = vec!['└'];
|
|
||||||
|
|
||||||
frstline.append(&mut vec!['─'; self.dimensions.0 - 2]);
|
|
||||||
midlines.append(&mut vec![' '; self.dimensions.0 - 2]);
|
|
||||||
lastline.append(&mut vec!['─'; self.dimensions.0 - 2]);
|
|
||||||
|
|
||||||
frstline.append(&mut vec!['┐']);
|
|
||||||
midlines.append(&mut vec!['│']);
|
|
||||||
lastline.append(&mut vec!['┘']);
|
|
||||||
|
|
||||||
charmap.push(frstline);
|
|
||||||
for _ in 0..self.dimensions.1 - 2 {
|
|
||||||
charmap.push(midlines.clone());
|
|
||||||
}
|
|
||||||
charmap.push(lastline);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// render child elements
|
// render child elements
|
||||||
@@ -110,7 +92,7 @@ impl Element for Container {
|
|||||||
for (j, chr) in row.iter().enumerate() {
|
for (j, chr) in row.iter().enumerate() {
|
||||||
// r.0 is the rendered element
|
// r.0 is the rendered element
|
||||||
// r.1.0 is the x offset
|
// r.1.0 is the x offset
|
||||||
charmap[i + r.1 .1][j + r.1 .0] = *chr; // r.1.1 is the y offset
|
charmap[i + r.1.y][j + r.1.x] = *chr; // r.1.1 is the y offset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,31 +105,41 @@ pub struct IndicatorBar {
|
|||||||
length: usize,
|
length: usize,
|
||||||
filled: usize,
|
filled: usize,
|
||||||
abs: usize,
|
abs: usize,
|
||||||
position: (usize, usize),
|
position: Pos,
|
||||||
|
text: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndicatorBar {
|
impl IndicatorBar {
|
||||||
fn new(position: (usize, usize), length: usize) -> IndicatorBar {
|
fn new(position: Pos, length: usize) -> IndicatorBar {
|
||||||
IndicatorBar {
|
IndicatorBar {
|
||||||
position,
|
position,
|
||||||
length,
|
length,
|
||||||
abs: 0,
|
abs: 0,
|
||||||
filled: 0,
|
filled: 0,
|
||||||
|
text: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn set_value(&mut self, value: usize) {
|
fn set_value(&mut self, value: usize) {
|
||||||
// takes a value from 1-100%
|
// takes a value from 1-100%
|
||||||
// and turns it into a corresponding length filled
|
// and turns it into a corresponding length filled
|
||||||
self.filled = value
|
self.filled = value;
|
||||||
|
}
|
||||||
|
fn set_text(&mut self, s: String) {
|
||||||
|
self.text = Some(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element for IndicatorBar {
|
impl Element for IndicatorBar {
|
||||||
fn render(&self) -> (Vec<Vec<char>>, (usize, usize)) {
|
fn render(&self) -> (Vec<Vec<char>>, Pos) {
|
||||||
let numlen = (self.abs.to_string().as_str()).len();
|
let numlen = (self.abs.to_string().as_str()).len();
|
||||||
let relfilled = (self.filled as f64 / 100.0 * ((self.length - numlen) as f64)) as usize;
|
let relfilled = (self.filled as f64 / 100.0 * ((self.length - numlen) as f64)) as usize;
|
||||||
|
|
||||||
let mut line = Vec::<char>::new();
|
let mut line = Vec::<char>::new();
|
||||||
|
if let Some(t) = &self.text {
|
||||||
|
line.append(&mut t.chars().collect());
|
||||||
|
line.push(':');
|
||||||
|
line.push(' ');
|
||||||
|
}
|
||||||
line.append(&mut (self.abs.to_string().chars().collect()));
|
line.append(&mut (self.abs.to_string().chars().collect()));
|
||||||
line.append(&mut vec!['▓'; relfilled]);
|
line.append(&mut vec!['▓'; relfilled]);
|
||||||
line.append(&mut vec!['░'; self.length - numlen - relfilled]);
|
line.append(&mut vec!['░'; self.length - numlen - relfilled]);
|
||||||
@@ -172,9 +164,9 @@ pub fn render_frame(elements: Vec<Container>) {
|
|||||||
|
|
||||||
for (i, row) in f.0.iter().enumerate() {
|
for (i, row) in f.0.iter().enumerate() {
|
||||||
for (j, chr) in row.iter().enumerate() {
|
for (j, chr) in row.iter().enumerate() {
|
||||||
let mut current = &buffer[i + f.1 .1][j + f.1 .0];
|
let mut current = &buffer[i + f.1.y][j + f.1.x];
|
||||||
let newchar = overlap_check(*current, *chr);
|
let newchar = overlap_check(*current, *chr);
|
||||||
buffer[i + f.1 .1][j + f.1 .0] = newchar;
|
buffer[i + f.1.y][j + f.1.x] = newchar;
|
||||||
|
|
||||||
//print!("{}", buffer[i+frame.position.1][j+frame.position.0]);
|
//print!("{}", buffer[i+frame.position.1][j+frame.position.0]);
|
||||||
}
|
}
|
||||||
@@ -226,10 +218,12 @@ pub fn gen_outline(dimensions: Pos) -> Vec<Vec<char>> {
|
|||||||
// testing functions
|
// testing functions
|
||||||
|
|
||||||
pub fn test_elements() {
|
pub fn test_elements() {
|
||||||
println!("e");
|
use super::libgui_elements;
|
||||||
|
|
||||||
let mut containers = Vec::<Container>::new();
|
let mut containers = Vec::<Container>::new();
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
//for _ in 0..10 {
|
//for _ in 0..10 {
|
||||||
// containers.push(generate_box());
|
// containers.push(generate_box());
|
||||||
//}
|
//}
|
||||||
@@ -247,10 +241,9 @@ pub fn test_elements() {
|
|||||||
containers[1].elements.push(Box::new(bar));
|
containers[1].elements.push(Box::new(bar));
|
||||||
containers[1].elements.push(Box::new(bar2));
|
containers[1].elements.push(Box::new(bar2));
|
||||||
|
|
||||||
use super::libgui_elements;
|
|
||||||
let tbox = libgui_elements::TextBox::new(
|
let tbox = libgui_elements::TextBox::new(
|
||||||
String::from("title"),
|
String::from("panic attack simps"),
|
||||||
String::from("text boxes are working gg but how well will they work if they go over the end of the textbox, will it cause a crash, well ima have to keep testing to figure that out properly, this could take a while lmao, i hope it works"),
|
String::from("i have finally obtained evidence of his simpiness against tari and crystal, however i cannot reveal this evidence for now, however, once the contract is over NO ONE CAN STOP ME MWHAHAHAHAHA"),
|
||||||
Pos::new(25, 10),
|
Pos::new(25, 10),
|
||||||
Pos::new(10, 9),
|
Pos::new(10, 9),
|
||||||
true,
|
true,
|
||||||
@@ -258,6 +251,23 @@ pub fn test_elements() {
|
|||||||
|
|
||||||
containers[1].elements.push(Box::new(tbox));
|
containers[1].elements.push(Box::new(tbox));
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
containers.push(Container::new(Pos::new(0, 1), Pos::new(80, 24), true));
|
||||||
|
|
||||||
|
containers[0]
|
||||||
|
.elements
|
||||||
|
.push(Box::new(libgui_elements::TextBox::new(
|
||||||
|
String::from("ANNOUNCEMENTS"),
|
||||||
|
String::from(
|
||||||
|
"CrystalRPG coming soon! XD
|
||||||
|
this is gonna be the best game ever",
|
||||||
|
),
|
||||||
|
Pos::new(25, 10),
|
||||||
|
Pos::new(0, 0),
|
||||||
|
true,
|
||||||
|
)));
|
||||||
|
|
||||||
render_frame(containers);
|
render_frame(containers);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -271,5 +281,5 @@ fn generate_box() -> Container {
|
|||||||
let height = Random::int(5, 10);
|
let height = Random::int(5, 10);
|
||||||
let xoffset = Random::int(5, 50);
|
let xoffset = Random::int(5, 50);
|
||||||
let yoffset = Random::int(5, 10);
|
let yoffset = Random::int(5, 10);
|
||||||
Container::new((width, height), (xoffset, yoffset), true)
|
Container::new(Pos::new(width, height), Pos::new(xoffset, yoffset), true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
use super::libgui_core::{self, Pos};
|
use super::libgui_core::{self, Pos};
|
||||||
|
use crate::std::io::println;
|
||||||
use alloc::{
|
use alloc::{
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use crate::std::io::println;
|
|
||||||
|
|
||||||
// TEXT BOX
|
// TEXT BOX
|
||||||
|
// a widget to display text in a box
|
||||||
|
// has a title and a body
|
||||||
pub struct TextBox {
|
pub struct TextBox {
|
||||||
dimensions: Pos,
|
dimensions: Pos,
|
||||||
position: Pos,
|
position: Pos,
|
||||||
@@ -15,58 +16,61 @@ pub struct TextBox {
|
|||||||
outlined: bool,
|
outlined: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// implements all rendering for TextBox widget
|
||||||
impl libgui_core::Element for TextBox {
|
impl libgui_core::Element for TextBox {
|
||||||
fn render(&self) -> (Vec<Vec<char>>, (usize, usize)) {
|
fn render(&self) -> (Vec<Vec<char>>, Pos) {
|
||||||
let mut charmap = Vec::<Vec<char>>::new();
|
let mut charmap = Vec::<Vec<char>>::new();
|
||||||
|
let mut inner_dims = Pos::new(self.dimensions.x - 2, self.dimensions.y - 2);
|
||||||
|
|
||||||
let mut inner_dims = Pos::new(self.dimensions.x -2, self.dimensions.y -2);
|
// generate outline if required
|
||||||
|
|
||||||
if self.outlined {
|
if self.outlined {
|
||||||
charmap = libgui_core::gen_outline(self.dimensions);
|
charmap = libgui_core::gen_outline(self.dimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let mut titlechars = self.title.chars().collect::<Vec<char>>();
|
|
||||||
// render title
|
// render title
|
||||||
|
let mut titlechars = self.title.chars().collect::<Vec<char>>();
|
||||||
for (i, char) in titlechars.iter().enumerate() {
|
for (i, char) in titlechars.iter().enumerate() {
|
||||||
if i < inner_dims.x {
|
if i < inner_dims.x {
|
||||||
charmap[0][i + 1] = *char;
|
charmap[0][i + 1] = *char;
|
||||||
} else {
|
} else {
|
||||||
|
charmap[0][inner_dims.x - 0] = '.';
|
||||||
|
charmap[0][inner_dims.x - 1] = '.';
|
||||||
|
charmap[0][inner_dims.x - 2] = '.';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut idx = 0;
|
|
||||||
|
|
||||||
// render text
|
// render text
|
||||||
|
let mut pos = Pos::new(0, 0);
|
||||||
let mut pos = Pos::new(0,0);
|
|
||||||
|
|
||||||
for chr in self.content.chars().collect::<Vec<char>>() {
|
for chr in self.content.chars().collect::<Vec<char>>() {
|
||||||
|
|
||||||
if pos.x < inner_dims.x {
|
if pos.x < inner_dims.x {
|
||||||
charmap[pos.y + 1][pos.x + 1] = chr;
|
if chr != '\n' {
|
||||||
pos.x += 1;
|
charmap[pos.y + 1][pos.x + 1] = chr;
|
||||||
|
pos.x += 1;
|
||||||
|
} else {
|
||||||
|
pos.y += 1;
|
||||||
|
pos.x = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// next line
|
||||||
pos.y += 1;
|
pos.y += 1;
|
||||||
pos.x = 1;
|
pos.x = 1;
|
||||||
|
|
||||||
if pos.y < inner_dims.y {
|
if pos.y < inner_dims.y {
|
||||||
charmap[pos.y + 1][1] = chr;
|
charmap[pos.y + 1][1] = chr;
|
||||||
} else {
|
} else {
|
||||||
charmap[inner_dims.y][inner_dims.x] = '.';
|
// handles overflow out of the end of the box
|
||||||
charmap[inner_dims.y][inner_dims.x -1] = '.';
|
charmap[inner_dims.y][inner_dims.x] = '»';
|
||||||
charmap[inner_dims.y][inner_dims.x -2] = '.';
|
charmap[inner_dims.y + 1][inner_dims.x - 0] = '.';
|
||||||
|
charmap[inner_dims.y + 1][inner_dims.x - 1] = '.';
|
||||||
|
charmap[inner_dims.y + 1][inner_dims.x - 2] = '.';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (charmap, self.position);
|
||||||
|
|
||||||
|
|
||||||
return (charmap, (self.position.x, self.position.y));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,3 +91,24 @@ impl TextBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct IndicatorBox {
|
||||||
|
pub bars: Vec<libgui_core::IndicatorBar>,
|
||||||
|
position: Pos,
|
||||||
|
dimensions: Pos,
|
||||||
|
}
|
||||||
|
impl IndicatorBox {
|
||||||
|
pub fn new(position: Pos, dimensions: Pos) -> IndicatorBox {
|
||||||
|
Self {
|
||||||
|
bars: Vec::new(),
|
||||||
|
position,
|
||||||
|
dimensions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn add_item(&mut self) {}
|
||||||
|
}
|
||||||
|
impl libgui_core::Element for IndicatorBox {
|
||||||
|
fn render(&self) -> (Vec<Vec<char>>, Pos) {
|
||||||
|
(Vec::<Vec<char>>::new(), Pos::new(0, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user