Store separate and sorted horizontal and vertical guides

This commit is contained in:
Belén Albeza 2026-06-04 17:23:41 +02:00
parent 4f4f195113
commit 54fb6901f9
5 changed files with 99 additions and 13 deletions

View File

@ -66,7 +66,8 @@ pub fn render(render_state: &mut RenderState, shapes: ShapesPoolRef) {
let ruler_state = render_state.rulers;
rulers::render(canvas, viewbox, &render_state.fonts, &ruler_state);
// TODO: pass guides data here
guides::render(canvas, zoom, viewbox.area, &get_ui_state().guides);
let (horizontal, vertical) = get_ui_state().guides();
guides::render(canvas, zoom, viewbox.area, horizontal, vertical);
canvas.restore();

View File

@ -5,8 +5,17 @@ use crate::ui::{Guide, GuideKind};
/// Renders the ruler guides overlay using the guides provided by the host
/// (ClojureScript) and stored in the render state.
pub fn render(canvas: &skia::Canvas, zoom: f32, area: Rect, guides: &[Guide]) {
for guide in guides {
pub fn render(
canvas: &skia::Canvas,
zoom: f32,
area: Rect,
horizontal: &[Guide],
vertical: &[Guide],
) {
for guide in horizontal {
render_guide(canvas, zoom, area, *guide);
}
for guide in vertical {
render_guide(canvas, zoom, area, *guide);
}
}

View File

@ -1,16 +1,58 @@
use crate::ui::Guide;
use crate::ui::{Guide, GuideKind};
use crate::uuid::Uuid;
pub struct GuidePool {
horizontal: Vec<Guide>,
vertical: Vec<Guide>,
}
impl GuidePool {
pub fn new() -> Self {
Self {
horizontal: Vec::new(),
vertical: Vec::new(),
}
}
pub fn set(&mut self, guides: Vec<Guide>) {
for guide in guides {
match guide.kind {
GuideKind::Vertical(_) => self.vertical.push(guide),
GuideKind::Horizontal(_) => self.horizontal.push(guide),
}
}
// TODO: handle the unwraps here
self.horizontal
.sort_by(|a, b| a.position().total_cmp(&b.position()));
self.vertical
.sort_by(|a, b| a.position().total_cmp(&b.position()));
}
}
pub struct UIState {
pub guides: Vec<Guide>,
guides: GuidePool,
pub _show_grid: Option<Uuid>,
}
impl UIState {
pub fn new() -> Self {
Self {
guides: Vec::new(),
guides: GuidePool::new(),
_show_grid: None,
}
}
pub fn guides(&self) -> (&Vec<Guide>, &Vec<Guide>) {
(&self.guides.horizontal, &self.guides.vertical)
}
pub fn set_guides(&mut self, guides: Vec<Guide>) {
self.guides.set(guides);
}
#[allow(dead_code)]
fn find_guide_at(&self, _x: f32, _y: f32, _zoom: f32) -> Option<&Guide> {
unimplemented!("TODO: Implement guide finding");
}
}

View File

@ -1,19 +1,46 @@
use std::cmp::Ordering;
use crate::shapes::Color;
#[derive(Debug, Clone, PartialEq, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum GuideKind {
Vertical(f32),
Horizontal(f32),
}
#[derive(Debug, Clone, PartialEq, Copy)]
impl GuideKind {
fn value(self) -> f32 {
match self {
GuideKind::Vertical(x) => x,
GuideKind::Horizontal(y) => y,
}
}
}
impl PartialOrd for GuideKind {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.value().partial_cmp(&other.value())
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Guide {
pub kind: GuideKind,
pub color: Color,
/// Index of the guide in the guide list (clojure side)
pub index: usize,
}
impl Guide {
pub fn new(kind: GuideKind, color: Color) -> Self {
Self { kind, color }
pub fn new(kind: GuideKind, color: Color, index: Option<usize>) -> Self {
Self {
kind,
color,
index: index.unwrap_or_default(),
}
}
pub fn position(&self) -> f32 {
self.kind.value()
}
}

View File

@ -43,7 +43,7 @@ impl From<RawGuide> for Guide {
RawGuideKind::Vertical => GuideKind::Vertical(value.position),
RawGuideKind::Horizontal => GuideKind::Horizontal(value.position),
};
Guide::new(kind, value.color.into())
Guide::new(kind, value.color.into(), None)
}
}
@ -67,7 +67,14 @@ fn read_guides_from_bytes(buffer: &[u8], count: usize) -> Result<Vec<Guide>> {
buffer
.chunks_exact(RAW_GUIDE_SIZE)
.take(count)
.map(|bytes| RawGuide::try_from(bytes).map(|guide| guide.into()))
.enumerate()
.map(|(i, bytes)| {
RawGuide::try_from(bytes).map(|raw_guide| {
let mut guide: Guide = raw_guide.into();
guide.index = i;
guide
})
})
.collect::<Result<Vec<Guide>>>()
}
@ -83,7 +90,7 @@ pub extern "C" fn set_guides() -> Result<()> {
.unwrap_or([0; 4]),
) as usize;
let guides = read_guides_from_bytes(&bytes[4..], count)?;
get_ui_state().guides = guides;
get_ui_state().set_guides(guides);
mem::free_bytes()?;
Ok(())