This commit is contained in:
Snorre 2025-02-17 17:01:44 +01:00
parent 3485c89905
commit 8cb8d510ca
5 changed files with 284 additions and 205 deletions

View file

@ -1,13 +1,18 @@
use std::{ use std::{
cell::RefCell, cell::RefCell, collections::{HashMap, HashSet}, rc::Rc
collections::{HashMap, HashSet},
rc::Rc,
}; };
mod gui; pub mod gui;
use clay_layout::render_commands::RenderCommandConfig; use clay_layout::render_commands::RenderCommandConfig;
use gui::GUI; use gui::{
GUI,
document::{
State,
line::{Line, LineSegment, Theme},
},
};
use libopenbirch::node::{add::Add, constant::Constant, divide::Divide, multiply::Multiply};
use raylib::{ use raylib::{
RaylibHandle, RaylibThread, RaylibHandle, RaylibThread,
color::Color, color::Color,
@ -23,6 +28,8 @@ struct FontStore {
fonts_to_be_loaded: HashSet<i32>, fonts_to_be_loaded: HashSet<i32>,
} }
static CHAR_SET: &'static str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ1234567890(){}[]./,?><|\\=+-_*&^%$#@!~`·×≤≥±∞≈∝≠∅∈∉∩∪⊂⊃⊆⊇¬∧∨∃∀⇒⇔→↔↑↓ℵ";
impl FontStore { impl FontStore {
// const SIZE_PARAGRAPH: f32 = 20.; // const SIZE_PARAGRAPH: f32 = 20.;
// const SIZE_HEADER: f32 = 30.; // const SIZE_HEADER: f32 = 30.;
@ -64,7 +71,7 @@ impl FontStore {
for size in self.fonts_to_be_loaded.clone() { for size in self.fonts_to_be_loaded.clone() {
assert!(size != 0, "HOW IS THIS ZERO?"); assert!(size != 0, "HOW IS THIS ZERO?");
println!("Loading {} in {size}px", self.font); println!("Loading {} in {size}px", self.font);
let font = Rc::new(handle.load_font_ex(&thread, &self.font, size, None)?); let font = Rc::new(handle.load_font_ex(&thread, &self.font, size, Some(CHAR_SET))?);
self.fonts.insert(size, font.clone()); self.fonts.insert(size, font.clone());
} }
self.fonts_to_be_loaded.clear(); self.fonts_to_be_loaded.clear();
@ -122,6 +129,18 @@ fn main() -> Result<(), String> {
let mut gui = GUI::new(); let mut gui = GUI::new();
gui.document.add_line("This is a test line".to_string());
let a = Constant::new(69.);
let b = Constant::new(420.);
let meth = Divide::new(a.clone().into(), b.into());
let meth2 = Add::new(a.into(), meth.clone().into());
let meth3 = Multiply::new(meth2.into(), meth.into());
gui.document.add_line(Line {
segments: vec![LineSegment::Math(Rc::new(meth3.into()), 16)],
});
let mut previous_left_button = false; let mut previous_left_button = false;
let mut previous_right_button = false; let mut previous_right_button = false;
@ -188,6 +207,13 @@ fn main() -> Result<(), String> {
let mut debug = false; let mut debug = false;
let theme = Theme {
text_color: (236, 239, 244).into(),
text_font: 0,
math_color: (129, 161, 193).into(),
math_font: 1,
};
while !rl.window_should_close() { while !rl.window_should_close() {
if rl.is_window_resized() { if rl.is_window_resized() {
let size = (rl.get_screen_width() as f32, rl.get_screen_height() as f32); let size = (rl.get_screen_width() as f32, rl.get_screen_height() as f32);
@ -228,13 +254,17 @@ fn main() -> Result<(), String> {
left_button, left_button,
); );
let render_commands = gui.render( let state = State {
&clay, mouse_left_held: left_button,
(left_button, left_button && !previous_left_button), mouse_left_pressed: left_button && !previous_left_button,
(right_button, right_button && !previous_right_button), mouse_right_held: right_button,
(rl.get_char_pressed(), rl.get_key_pressed_number()), mouse_right_pressed: right_button && !previous_right_button,
rl.get_time(), latest_char: rl.get_char_pressed(),
); latest_key: rl.get_key_pressed_number(),
time: rl.get_time(),
};
let render_commands = gui.render(&clay, &state, &theme);
let mut d = rl.begin_drawing(&thread); let mut d = rl.begin_drawing(&thread);

View file

@ -1,19 +1,199 @@
use std::rc::Rc; use std::rc::Rc;
use clay_layout::{
Declaration, fit, grow,
layout::{
Alignment, LayoutAlignmentX, LayoutAlignmentY,
LayoutDirection::{self, TopToBottom},
Padding,
},
text::{TextConfig, TextElementConfig},
};
use libopenbirch::node::NodeEnum; use libopenbirch::node::NodeEnum;
use super::{Document, State};
pub struct Line { pub struct Line {
segments: Vec<LineSegment>, pub segments: Vec<LineSegment>,
}
impl From<String> for Line {
fn from(value: String) -> Self {
Line {
segments: vec![LineSegment::Text(value, 20)],
}
}
}
impl Line {
pub fn draw<'a>(&'a mut self, clay: &'a clay_layout::Clay, theme: &Theme, state: &'a State) {
for segment in self.segments.iter_mut() {
segment.draw(clay, theme, state);
}
}
}
pub struct Theme {
pub text_color: clay_layout::color::Color,
pub text_font: u16,
pub math_color: clay_layout::color::Color,
pub math_font: u16,
} }
pub enum LineSegment { pub enum LineSegment {
Text(String), Text(String, u16),
// Link(String, Link), // Link(String, Link),
Math(Rc<NodeEnum>), Math(Rc<NodeEnum>, u16),
} }
impl LineSegment { impl LineSegment {
pub fn draw<'a>(&'a self, clay: &'a clay_layout::Clay) { pub fn draw<'a>(&'a mut self, clay: &'a clay_layout::Clay, theme: &'a Theme, state: &'a State) {
match self {
LineSegment::Text(text, font_size) => clay.text(
text.as_str(),
TextConfig::new()
.font_id(theme.text_font)
.font_size(*font_size)
.color(theme.text_color)
.end(),
),
LineSegment::Math(node_enum, font_size) => {
draw_math_enum(node_enum.clone(), clay, theme, *font_size, state);
}
}
}
}
fn draw_binary(
symbol: &'static str,
left: Rc<NodeEnum>,
right: Rc<NodeEnum>,
font_size: u16,
clay: &clay_layout::Clay,
theme: &Theme,
state: &State,
) {
clay.with(
&Declaration::new()
.layout()
.direction(LayoutDirection::LeftToRight)
.width(fit!(0.))
.height(fit!(0.))
.child_alignment(Alignment::new(
LayoutAlignmentX::Center,
LayoutAlignmentY::Center,
))
.padding(Padding::new(2, 2, 3, 3))
.end(),
|clay| {
// Left side
draw_math_enum(left, clay, theme, font_size, state);
// add symbol
clay.text(
symbol,
TextConfig::new()
.color(theme.math_color)
.font_size(font_size)
.font_id(theme.math_font)
.end(),
);
// Right side
draw_math_enum(right, clay, theme, font_size, state);
},
)
}
fn draw_math_enum<'a>(
node: Rc<NodeEnum>,
clay: &'a clay_layout::Clay,
theme: &'a Theme,
font_size: u16,
state: &'a State,
) {
match node.as_ref() {
NodeEnum::Constant(constant) => {
let str = std::mem::ManuallyDrop::new(constant.get_value().to_string());
clay.text(
str.as_str(),
TextConfig::new()
.color(theme.math_color)
.font_size(font_size)
.font_id(theme.math_font)
.end(),
)
}
NodeEnum::Add(add) => draw_binary(
" + ",
add.get_left(),
add.get_right(),
font_size,
clay,
theme,
state,
),
NodeEnum::Subtract(sub) => draw_binary(
" - ",
sub.get_left(),
sub.get_right(),
font_size,
clay,
theme,
state,
),
NodeEnum::Multiply(mul) => draw_binary(
"× ",
mul.get_left(),
mul.get_right(),
font_size,
clay,
theme,
state,
),
NodeEnum::Assign(assign) => draw_binary(
" := ",
assign.get_left(),
assign.get_right(),
font_size,
clay,
theme,
state,
),
NodeEnum::Divide(divide) => clay.with(
&Declaration::new()
.layout()
.direction(TopToBottom)
.width(fit!(0.))
.height(fit!(0.))
.child_alignment(Alignment::new(
LayoutAlignmentX::Center,
LayoutAlignmentY::Center,
))
.padding(Padding::new(4, 4, 2, 2))
.end(),
|clay| {
// Left side
draw_math_enum(divide.get_left(), clay, theme, font_size, state);
// Seperator bar
clay.with(
&Declaration::new()
.layout()
.width(grow!(0.))
.height(fit!(1.))
.end()
.background_color(theme.math_color),
|_| {},
);
// Right side
draw_math_enum(divide.get_right(), clay, theme, font_size, state);
},
),
NodeEnum::Symbol(symbol) => todo!(),
NodeEnum::Function(function) => todo!(),
NodeEnum::Call(call) => todo!(),
NodeEnum::Empty(empty) => {}
} }
} }

View file

@ -5,107 +5,51 @@ use clay_layout::{
layout::{LayoutDirection, Padding}, layout::{LayoutDirection, Padding},
text::TextConfig, text::TextConfig,
}; };
use line::{Line, Theme};
use raylib::ffi::KeyboardKey; use raylib::ffi::KeyboardKey;
pub type LineType = String; pub mod line;
mod line; pub struct State {
pub mouse_left_held: bool,
pub mouse_left_pressed: bool,
pub mouse_right_held: bool,
pub mouse_right_pressed: bool,
pub latest_char: Option<char>,
pub latest_key: Option<u32>,
pub time: f64,
}
pub struct Document { pub struct Document {
lines: Vec<(String, LineType)>, lines: Vec<(String, Line)>,
total_lines: usize, total_lines: usize,
current_line: Option<usize>,
current_char: usize,
lines_to_delete: Vec<usize>,
lines_to_add: Vec<(usize, LineType)>,
last_type_time: f64,
} }
impl Document { impl Document {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
lines: vec![("0".to_owned(), "".to_string())], lines: vec![],
total_lines: 1, total_lines: 0,
current_line: Some(0),
current_char: 0,
lines_to_delete: vec![],
lines_to_add: vec![],
last_type_time: -100.,
} }
} }
pub fn add_line(&mut self, content: impl Into<LineType>) { pub fn add_line(&mut self, content: impl Into<Line>) {
self.add_line_at(self.lines.len(), content); self.add_line_at(self.lines.len(), content);
} }
pub fn add_line_at(&mut self, idx: usize, content: impl Into<LineType>) { pub fn add_line_at(&mut self, idx: usize, content: impl Into<Line>) {
self.lines self.lines.insert(idx, (self.total_lines.to_string(), content.into()));
.insert(idx, (self.total_lines.to_string(), content.into()));
self.total_lines += 1; self.total_lines += 1;
} }
pub fn render<'a>( pub fn render<'a>(
&'a mut self, &'a mut self,
clay: &'a Clay, clay: &'a Clay,
(left_held, left_pressed): (bool, bool), state: &'a State,
(righ_held, right_pressed): (bool, bool), theme: &'a Theme
(latest_char, latest_key): (Option<char>, Option<u32>),
time: f64,
) { ) {
// if !self.lines_to_delete.is_empty() {
// self.lines_to_delete.sort();
//
// for line in self.lines_to_delete.iter().rev() {
// let contents = &self.lines.remove(*line).1;
// self.lines[*line - 1].1 += contents;
// }
//
// self.lines_to_delete.clear();
//
// self.current_line = if let Some(i) = self.current_line {
// if self.lines.len() == 0 {
// self.add_line("".to_string());
// }
// Some(
// (TryInto::<i32>::try_into(i).unwrap() - 1)
// .max(0)
// .min(TryInto::<i32>::try_into(self.lines.len()).unwrap() - 1)
// .try_into()
// .unwrap(),
// )
// } else {
// None
// };
// }
//
// if !self.lines_to_add.is_empty() {
// // i am NOT cloning this shit
// let lines_to_add: ManuallyDrop<Vec<(usize, String)>> = unsafe {
// let len = self.lines_to_add.len();
// let cap = self.lines_to_add.capacity();
// let fuck = self.lines_to_add.as_mut_ptr();
// std::mem::ManuallyDrop::new(Vec::from_raw_parts(fuck, len, cap))
// };
//
// for (idx, line) in lines_to_add.iter() {
// self.add_line_at(*idx, line);
// }
//
// self.lines_to_add.clear();
// self.current_line = if let Some(i) = self.current_line {
// Some(i + 1)
// } else {
// None
// };
// }
//
// if left_pressed && clay.pointer_over(clay.id("document")) {
// self.current_line = None;
// }
//
// let len = self.lines.len();
// let mut can_go_down = true;
clay.with( clay.with(
&Declaration::new() &Declaration::new()
.id(clay.id("document")) .id(clay.id("document"))
@ -122,107 +66,27 @@ impl Document {
.background_color((67, 76, 94).into()) .background_color((67, 76, 94).into())
.scroll(false, true), .scroll(false, true),
|clay| { |clay| {
// for (i, line) in self.lines.iter_mut().enumerate() { for (id,line) in self.lines.iter_mut() {
// let current_selected = clay.with(
// if left_pressed && clay.pointer_over(clay.id(line.0.as_str())) { &Declaration::new()
// self.current_line = Some(i); .id(clay.id(id))
// true .layout()
// } else { .width(grow!(0.))
// Some(i) == self.current_line .height(fit!(0.))
// }; .direction(LayoutDirection::TopToBottom)
// .padding(Padding::all(8))
// if current_selected { .child_gap(0)
// if let Some(char) = latest_char { .end()
// line.1 += char.to_string().as_str(); .corner_radius()
// self.last_type_time = time; .all(8.)
// } .end()
// .background_color((67, 76, 94).into())
// match latest_key { .scroll(false, true),
// Some(val) if val == KeyboardKey::KEY_BACKSPACE as u32 => { |clay| {
// if line.1.len() == 0 { line.draw(clay, theme, state);
// self.lines_to_delete.push(i); },
// } else { );
// // let _ = line.1.pop(); }
// line.1.remove(self.current_char);
// }
// }
// Some(val) if val == KeyboardKey::KEY_ENTER as u32 => {
// self.lines_to_add.push((i + 1, "".to_string()));
// }
// Some(val) if val == KeyboardKey::KEY_UP as u32 => {
// self.current_line = Some(
// (TryInto::<i32>::try_into(self.current_line.unwrap()).unwrap()
// - 1)
// .max(0)
// .try_into()
// .unwrap(),
// );
// }
// Some(val) if val == KeyboardKey::KEY_DOWN as u32 && can_go_down => {
// self.current_line = Some(
// (TryInto::<i32>::try_into(self.current_line.unwrap()).unwrap()
// + 1)
// .min(TryInto::<i32>::try_into(len).unwrap() - 1)
// .try_into()
// .unwrap(),
// );
// can_go_down = false;
// }
// _ => {}
// }
// }
//
// clay.with(
// &Declaration::new()
// .id(clay.id(line.0.as_str()))
// .layout()
// .width(grow!(0.))
// .height(fit!(21.))
// .direction(LayoutDirection::LeftToRight)
// .padding(Padding::new(4, 4, 0, 1))
// .child_alignment(clay_layout::layout::Alignment {
// x: clay_layout::layout::LayoutAlignmentX::Left,
// y: clay_layout::layout::LayoutAlignmentY::Center,
// })
// // .child_gap(2)
// // .end()
// // .border()
// // .color((67, 76, 94).into())
// // .bottom(2)
// // .end()
// // .corner_radius()
// // .all(4.)
// .end(),
// |clay| {
// clay.text(
// line.1.as_str(),
// TextConfig::new()
// .color((229, 233, 240).into())
// .font_size(20)
// .font_id(0)
// .letter_spacing(2)
// .end(),
// );
// if current_selected
// && can_go_down
// && ((time - self.last_type_time) < 0.5 || time % 1.2 < 0.6)
// {
// clay.with(
// &Declaration::new()
// .id(clay.id("text_cursor"))
// .layout()
// .height(grow!(0.))
// .width(fixed!(8.))
// .end()
// .background_color((229, 233, 240, 100).into()), // .corner_radius()
// // .all(2.)
// // .end(),
// |_| {},
// );
// }
// },
// );
// }
}, },
); );
} }

View file

@ -3,9 +3,9 @@ use clay_layout::{
layout::{LayoutDirection, Padding}, layout::{LayoutDirection, Padding},
render_commands::RenderCommand, render_commands::RenderCommand,
}; };
use document::Document; use document::{Document, State, line::Theme};
mod document; pub mod document;
pub struct GUI { pub struct GUI {
pub document: Document, pub document: Document,
@ -21,15 +21,12 @@ impl GUI {
pub fn render<'a>( pub fn render<'a>(
&'a mut self, &'a mut self,
clay: &'a Clay, clay: &'a Clay,
left_mouse: (bool, bool), state: &'a State,
right_mouse: (bool, bool), theme: &'a Theme,
latest_char: (Option<char>, Option<u32>),
time: f64,
) -> impl Iterator<Item = RenderCommand> { ) -> impl Iterator<Item = RenderCommand> {
clay.begin(); clay.begin();
self.document self.document.render(clay, state, theme);
.render(clay, left_mouse, right_mouse, latest_char, time);
clay.end() clay.end()
} }

View file

@ -32,16 +32,24 @@ mod call;
#[derive(Debug, Clone, PartialEq, PartialOrd)] #[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum NodeEnum { pub enum NodeEnum {
Constant, Constant,
// Operators
Add, Add,
Subtract, Subtract,
Multiply, Multiply,
Divide, Divide,
Symbol, Symbol,
// NodeRef, // DEPRECATED, use Symbol // NodeRef, // DEPRECATED, use Symbol
Assign, Assign,
Empty, Empty,
Function, Function,
Call Call,
// Logical
// In,
// Or,
// Not,
} }
#[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(PartialEq, Eq, PartialOrd, Ord)]