add gui in os
This commit is contained in:
parent
10e1c57b7d
commit
07029a2e5f
20 changed files with 649 additions and 4 deletions
61
os/src/gui/button.rs
Normal file
61
os/src/gui/button.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use alloc::{sync::Arc, string::String};
|
||||
use embedded_graphics::{prelude::{Size, Point, Primitive, RgbColor, Dimensions}, primitives::{Rectangle, PrimitiveStyle}, pixelcolor::Rgb888, Drawable, text::{Text, Alignment}, mono_font::{ascii::{FONT_6X10, FONT_10X20}, MonoTextStyle}};
|
||||
|
||||
use crate::{sync::UPIntrFreeCell, drivers::GPU_DEVICE};
|
||||
|
||||
use super::{Component, Graphics};
|
||||
|
||||
pub struct Button {
|
||||
inner: UPIntrFreeCell<ButtonInner>
|
||||
}
|
||||
|
||||
pub struct ButtonInner {
|
||||
graphic: Graphics,
|
||||
text: String,
|
||||
parent: Option<Arc<dyn Component>>
|
||||
}
|
||||
|
||||
impl Button {
|
||||
pub fn new(size: Size, point: Point, parent: Option<Arc<dyn Component>>,text:String) -> Self {
|
||||
let point = match &parent {
|
||||
Some(p) => {
|
||||
let (_, p) = p.bound();
|
||||
Point::new(p.x + point.x,p.y + point.y)
|
||||
},
|
||||
None => point,
|
||||
};
|
||||
Self {
|
||||
inner: unsafe {
|
||||
UPIntrFreeCell::new(
|
||||
ButtonInner {
|
||||
graphic: Graphics { size, point, drv:GPU_DEVICE.clone() },
|
||||
text,
|
||||
parent,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Button {
|
||||
fn paint(&self) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let text = inner.text.clone();
|
||||
Text::with_alignment(
|
||||
text.as_str(),
|
||||
inner.graphic.bounding_box().center(),
|
||||
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||
Alignment::Center
|
||||
).draw(&mut inner.graphic);
|
||||
}
|
||||
|
||||
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn bound(&self) -> (embedded_graphics::prelude::Size, embedded_graphics::prelude::Point) {
|
||||
let inner = self.inner.exclusive_access();
|
||||
(inner.graphic.size, inner.graphic.point)
|
||||
}
|
||||
}
|
56
os/src/gui/graphic.rs
Normal file
56
os/src/gui/graphic.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
use alloc::sync::Arc;
|
||||
use embedded_graphics::{
|
||||
draw_target::DrawTarget,
|
||||
pixelcolor::Rgb888,
|
||||
prelude::{OriginDimensions, Point, RgbColor, Size},
|
||||
};
|
||||
|
||||
use crate::drivers::{GPUDevice, GPU_DEVICE};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Graphics {
|
||||
pub size: Size,
|
||||
pub point: Point,
|
||||
pub drv: Arc<dyn GPUDevice>,
|
||||
}
|
||||
|
||||
impl Graphics {
|
||||
pub fn new(size: Size, point: Point) -> Self {
|
||||
Self {
|
||||
size,
|
||||
point,
|
||||
drv: GPU_DEVICE.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OriginDimensions for Graphics {
|
||||
fn size(&self) -> Size {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawTarget for Graphics {
|
||||
type Color = Rgb888;
|
||||
|
||||
type Error = core::convert::Infallible;
|
||||
|
||||
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
|
||||
where
|
||||
I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>>,
|
||||
{
|
||||
let fb = self.drv.getfreambuffer();
|
||||
|
||||
pixels.into_iter().for_each(|px| {
|
||||
let idx = ((self.point.y + px.0.y) * 1024 + self.point.x + px.0.x) as usize * 4;
|
||||
if idx + 2 >= fb.len() {
|
||||
return;
|
||||
}
|
||||
fb[idx] = px.1.b();
|
||||
fb[idx + 1] = px.1.g();
|
||||
fb[idx + 2] = px.1.r();
|
||||
});
|
||||
self.drv.flush();
|
||||
Ok(())
|
||||
}
|
||||
}
|
78
os/src/gui/icon.rs
Normal file
78
os/src/gui/icon.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
|
||||
|
||||
use alloc::{vec::Vec, string::String, sync::Arc};
|
||||
use embedded_graphics::{prelude::{Size, Point, RgbColor}, image::Image, text::Text, mono_font::{MonoTextStyle, iso_8859_13::FONT_6X12, ascii::FONT_10X20}, pixelcolor::Rgb888, Drawable};
|
||||
use tinybmp::Bmp;
|
||||
|
||||
use crate::{sync::UPIntrFreeCell, drivers::GPU_DEVICE};
|
||||
|
||||
use super::{Graphics, Component, ImageComp};
|
||||
|
||||
static FILEICON: &[u8] = include_bytes!("../assert/file.bmp");
|
||||
|
||||
pub struct IconController {
|
||||
inner: UPIntrFreeCell<IconControllerInner>
|
||||
}
|
||||
|
||||
pub struct IconControllerInner {
|
||||
files: Vec<String>,
|
||||
graphic: Graphics,
|
||||
parent: Option<Arc<dyn Component>>
|
||||
}
|
||||
|
||||
impl IconController {
|
||||
pub fn new(files: Vec<String>,parent: Option<Arc<dyn Component>>) -> Self {
|
||||
IconController {
|
||||
inner: unsafe {
|
||||
UPIntrFreeCell::new(
|
||||
IconControllerInner {
|
||||
files,
|
||||
graphic: Graphics {
|
||||
size: Size::new(1024, 768),
|
||||
point: Point::new(0, 0),
|
||||
drv: GPU_DEVICE.clone()
|
||||
},
|
||||
parent,
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for IconController {
|
||||
fn paint(&self) {
|
||||
println!("demo");
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let mut x = 10;
|
||||
let mut y = 10;
|
||||
let v = inner.files.clone();
|
||||
for file in v {
|
||||
println!("file");
|
||||
let bmp = Bmp::<Rgb888>::from_slice(FILEICON).unwrap();
|
||||
Image::new(&bmp, Point::new(x, y),).draw(&mut inner.graphic);
|
||||
let text = Text::new(
|
||||
file.as_str(),
|
||||
Point::new(x + 20, y + 80),
|
||||
MonoTextStyle::new(&FONT_10X20,Rgb888::BLACK)
|
||||
);
|
||||
text.draw(&mut inner.graphic);
|
||||
if y >= 600 {
|
||||
x = x + 70;
|
||||
y = 10;
|
||||
} else {
|
||||
y = y + 90;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&self, comp: Arc<dyn Component>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bound(&self) -> (Size, Point) {
|
||||
todo!()
|
||||
}
|
||||
}
|
72
os/src/gui/image.rs
Normal file
72
os/src/gui/image.rs
Normal file
|
@ -0,0 +1,72 @@
|
|||
use alloc::{vec::Vec, sync::Arc};
|
||||
use embedded_graphics::{
|
||||
image::Image,
|
||||
prelude::{Point, Size}, pixelcolor::Rgb888, Drawable,
|
||||
};
|
||||
use tinybmp::Bmp;
|
||||
|
||||
use crate::{
|
||||
drivers::{BLOCK_DEVICE, GPU_DEVICE},
|
||||
sync::UPIntrFreeCell,
|
||||
};
|
||||
|
||||
use super::{Graphics, Component};
|
||||
|
||||
pub struct ImageComp {
|
||||
|
||||
inner: UPIntrFreeCell<ImageInner>,
|
||||
}
|
||||
|
||||
pub struct ImageInner {
|
||||
image: &'static [u8],
|
||||
graphic: Graphics,
|
||||
parent: Option<Arc<dyn Component>>
|
||||
}
|
||||
|
||||
impl ImageComp {
|
||||
pub fn new(size: Size, point: Point, v: &'static [u8],parent: Option<Arc<dyn Component>>) -> Self {
|
||||
unsafe {
|
||||
ImageComp {
|
||||
inner: UPIntrFreeCell::new(ImageInner {
|
||||
parent,
|
||||
image: v,
|
||||
graphic: Graphics {
|
||||
size,
|
||||
point,
|
||||
drv: GPU_DEVICE.clone(),
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for ImageComp {
|
||||
fn paint(&self) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let b = unsafe {
|
||||
let len = inner.image.len();
|
||||
let ptr = inner.image
|
||||
.as_ptr() as *const u8;
|
||||
core::slice::from_raw_parts(ptr, len)
|
||||
};
|
||||
let bmp = Bmp::<Rgb888>::from_slice(b).unwrap();
|
||||
let point = match &inner.parent {
|
||||
Some(parent) => {
|
||||
let (_, point) = parent.bound();
|
||||
Point::new(point.x + inner.graphic.point.x, point.y + inner.graphic.point.y)
|
||||
}
|
||||
None => inner.graphic.point,
|
||||
};
|
||||
Image::new(&bmp, point,).draw(&mut inner.graphic);
|
||||
}
|
||||
|
||||
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bound(&self) -> (Size, Point) {
|
||||
let inner = self.inner.exclusive_access();
|
||||
(inner.graphic.size, inner.graphic.point)
|
||||
}
|
||||
}
|
21
os/src/gui/mod.rs
Normal file
21
os/src/gui/mod.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
mod graphic;
|
||||
mod image;
|
||||
mod panel;
|
||||
mod icon;
|
||||
mod button;
|
||||
mod terminal;
|
||||
use alloc::sync::Arc;
|
||||
use embedded_graphics::prelude::{Size, Point};
|
||||
use core::any::Any;
|
||||
pub use graphic::*;
|
||||
pub use panel::*;
|
||||
pub use image::*;
|
||||
pub use icon::*;
|
||||
pub use terminal::*;
|
||||
pub use button::*;
|
||||
|
||||
pub trait Component: Send + Sync + Any {
|
||||
fn paint(&self);
|
||||
fn add(&self, comp: Arc<dyn Component>);
|
||||
fn bound(&self) -> (Size, Point);
|
||||
}
|
66
os/src/gui/panel.rs
Normal file
66
os/src/gui/panel.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use alloc::{collections::VecDeque, sync::Arc, rc::Weak};
|
||||
use embedded_graphics::{
|
||||
pixelcolor::Rgb888,
|
||||
prelude::{Point, Primitive, RgbColor, Size},
|
||||
primitives::{PrimitiveStyle, Rectangle},
|
||||
Drawable,
|
||||
};
|
||||
|
||||
use crate::{drivers::GPU_DEVICE, sync::UPIntrFreeCell};
|
||||
|
||||
use super::{Component, Graphics};
|
||||
|
||||
pub struct Panel {
|
||||
inner: UPIntrFreeCell<PanelInner>,
|
||||
}
|
||||
struct PanelInner {
|
||||
graphic: Graphics,
|
||||
comps: VecDeque<Arc<dyn Component>>,
|
||||
}
|
||||
|
||||
impl Panel {
|
||||
pub fn new(size: Size, point: Point) -> Self {
|
||||
Self {
|
||||
inner: unsafe {
|
||||
UPIntrFreeCell::new(PanelInner {
|
||||
graphic: Graphics {
|
||||
size,
|
||||
point,
|
||||
drv: GPU_DEVICE.clone(),
|
||||
},
|
||||
comps: VecDeque::new(),
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Panel {
|
||||
fn paint(&self) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
|
||||
Rectangle::new(Point::new(0, 0), inner.graphic.size)
|
||||
.into_styled(PrimitiveStyle::with_fill(Rgb888::WHITE))
|
||||
.draw(&mut inner.graphic)
|
||||
.unwrap();
|
||||
|
||||
let len = inner.comps.len();
|
||||
drop(inner);
|
||||
for i in 0..len {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let comp = Arc::downgrade(&inner.comps[i]);
|
||||
drop(inner);
|
||||
comp.upgrade().unwrap().paint();
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
inner.comps.push_back(comp);
|
||||
}
|
||||
|
||||
fn bound(&self) -> (Size, Point) {
|
||||
let inner = self.inner.exclusive_access();
|
||||
(inner.graphic.size, inner.graphic.point)
|
||||
}
|
||||
}
|
89
os/src/gui/terminal.rs
Normal file
89
os/src/gui/terminal.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
use alloc::{collections::VecDeque, sync::Arc, string::{String, ToString}};
|
||||
use embedded_graphics::{prelude::{Size, Point, RgbColor, Primitive, Dimensions}, text::{Text, Alignment}, mono_font::{MonoTextStyle, ascii::FONT_10X20}, pixelcolor::Rgb888, Drawable, primitives::{Rectangle, PrimitiveStyle}};
|
||||
|
||||
use crate::{sync::UPIntrFreeCell, drivers::GPU_DEVICE};
|
||||
|
||||
use super::{Graphics, Component, Panel, button::Button};
|
||||
|
||||
pub struct Terminal {
|
||||
inner: UPIntrFreeCell<TerminalInner>
|
||||
}
|
||||
|
||||
pub struct TerminalInner {
|
||||
pub text: String,
|
||||
titel:Option<String>,
|
||||
graphic: Graphics,
|
||||
comps: VecDeque<Arc<dyn Component>>,
|
||||
}
|
||||
|
||||
impl Terminal {
|
||||
pub fn new(size: Size, point: Point, parent: Option<Arc<dyn Component>>,titel: Option<String>,text:String) -> Self {
|
||||
Self {
|
||||
inner: unsafe {
|
||||
UPIntrFreeCell::new(
|
||||
TerminalInner {
|
||||
text,
|
||||
titel,
|
||||
graphic: Graphics {
|
||||
size,
|
||||
point,
|
||||
drv: GPU_DEVICE.clone(),
|
||||
},
|
||||
comps: VecDeque::new(),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn repaint(&self, text:String){
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
inner.text += text.as_str();
|
||||
Text::with_alignment(
|
||||
inner.text.clone().as_str(),
|
||||
Point::new( 20, 50),
|
||||
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||
Alignment::Left
|
||||
).draw(&mut inner.graphic);
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Terminal {
|
||||
fn paint(&self) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let len = inner.comps.len();
|
||||
drop(inner);
|
||||
for i in 0..len {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let comp = Arc::downgrade(&inner.comps[i]);
|
||||
drop(inner);
|
||||
comp.upgrade().unwrap().paint();
|
||||
}
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let titel = inner.titel.get_or_insert("No Titel".to_string()).clone();
|
||||
let text = Text::new(
|
||||
titel.as_str(),
|
||||
Point::new(20, 20),
|
||||
MonoTextStyle::new(&FONT_10X20,Rgb888::BLACK)
|
||||
);
|
||||
text.draw(&mut inner.graphic);
|
||||
|
||||
Text::with_alignment(
|
||||
inner.text.clone().as_str(),
|
||||
Point::new( 20, 50),
|
||||
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||
Alignment::Left
|
||||
).draw(&mut inner.graphic);
|
||||
|
||||
}
|
||||
|
||||
fn add(&self, comp: Arc<dyn Component>) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
inner.comps.push_back(comp);
|
||||
}
|
||||
|
||||
fn bound(&self) -> (Size, Point) {
|
||||
let inner = self.inner.exclusive_access();
|
||||
(inner.graphic.size, inner.graphic.point)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue