Draw the grid and a grain of sand

This commit is contained in:
Savanni D'Gerinel 2024-02-04 11:06:54 -05:00
parent c27ce7fe80
commit 2323443378
1 changed files with 104 additions and 17 deletions

View File

@ -1,38 +1,122 @@
use cairo::Context;
use glib::Object; use glib::Object;
use gtk::{prelude::*, subclass::prelude::*}; use gtk::{prelude::*, subclass::prelude::*};
use std::cell::RefCell;
const WIDTH: i32 = 600; const WIDTH: usize = 601;
const HEIGHT: i32 = 600; const HEIGHT: usize = 601;
const CELL_SIZE: usize = 10;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct SandPrivate; pub struct SandViewPrivate {
area: RefCell<SandArea>,
}
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for SandPrivate { impl ObjectSubclass for SandViewPrivate {
const NAME: &'static str = "Sand"; const NAME: &'static str = "SandView";
type Type = Sand; type Type = SandView;
type ParentType = gtk::DrawingArea; type ParentType = gtk::DrawingArea;
} }
impl ObjectImpl for SandPrivate {} impl ObjectImpl for SandViewPrivate {}
impl WidgetImpl for SandPrivate {} impl WidgetImpl for SandViewPrivate {}
impl DrawingAreaImpl for SandPrivate {} impl DrawingAreaImpl for SandViewPrivate {}
glib::wrapper! { glib::wrapper! {
pub struct Sand(ObjectSubclass<SandPrivate>) @extends gtk::DrawingArea, gtk::Widget; pub struct SandView(ObjectSubclass<SandViewPrivate>) @extends gtk::DrawingArea, gtk::Widget;
} }
impl Sand { impl Default for SandView {
pub fn new() -> Self { fn default() -> Self {
let s: Self = Object::builder().build(); let s: Self = Object::builder().build();
s.set_width_request(WIDTH); s.set_width_request(WIDTH as i32);
s.set_height_request(HEIGHT); s.set_height_request(HEIGHT as i32);
s.set_draw_func({
let s = s.clone();
move |_, context, width, height| {
println!("{} {}", width, height);
context.set_source_rgb(0., 0., 0.);
let _ = context.paint();
context.set_source_rgb(0.1, 0.1, 0.1);
for x in (0..width).step_by(CELL_SIZE) {
context.move_to(x as f64, 0.);
context.line_to(x as f64, HEIGHT as f64);
}
for y in (0..height).step_by(CELL_SIZE) {
context.move_to(0., y as f64);
context.line_to(WIDTH as f64, y as f64);
}
let _ = context.stroke();
let area = s.imp().area.borrow();
for x in 0..area.width {
for y in 0..area.height {
if area.grain(x, y) {
context.set_source_rgb(0.8, 0.8, 0.8);
} else {
context.set_source_rgb(0., 0., 0.);
}
context.rectangle(
(x * CELL_SIZE + 1) as f64,
(y * CELL_SIZE + 1) as f64,
(CELL_SIZE - 2) as f64,
(CELL_SIZE - 2) as f64,
);
let _ = context.fill();
}
}
}
});
s s
} }
} }
impl SandView {
fn set_area(&self, area: SandArea) {
*self.imp().area.borrow_mut() = area;
}
}
#[derive(Clone, Debug)]
struct SandArea {
width: usize,
height: usize,
grains: Vec<bool>,
}
impl Default for SandArea {
fn default() -> Self {
let width = WIDTH / CELL_SIZE;
let height = HEIGHT / CELL_SIZE;
Self {
width,
height,
grains: vec![false; width * height],
}
}
}
impl SandArea {
pub fn add_grain(&mut self, x: usize, y: usize) {
let addr = self.addr(x, y);
self.grains[addr] = true;
}
pub fn grain(&self, x: usize, y: usize) -> bool {
self.grains[self.addr(x, y)]
}
pub fn tick(self) -> Self {
unimplemented!()
}
fn addr(&self, x: usize, y: usize) -> usize {
y * self.width + x
}
}
fn main() { fn main() {
let app = gtk::Application::builder() let app = gtk::Application::builder()
.application_id("com.luminescent-dreams.falling-sand") .application_id("com.luminescent-dreams.falling-sand")
@ -42,9 +126,12 @@ fn main() {
let window = gtk::ApplicationWindow::new(app); let window = gtk::ApplicationWindow::new(app);
window.present(); window.present();
let sand = Sand::new(); let view = SandView::default();
let mut sand_area = SandArea::default();
sand_area.add_grain(20, 20);
view.set_area(sand_area.clone());
window.set_child(Some(&sand)); window.set_child(Some(&view));
}); });
app.run(); app.run();