mirror of
https://github.com/penpot/penpot.git
synced 2026-06-20 06:12:04 +00:00
✨ Store separate and sorted horizontal and vertical guides
This commit is contained in:
parent
4f4f195113
commit
54fb6901f9
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -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(())
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user