mirror of
https://github.com/penpot/penpot.git
synced 2025-07-13 08:07:16 +02:00
✨ Add grid helpers to wasm
This commit is contained in:
parent
3624a14141
commit
0be8a6e0e6
11 changed files with 259 additions and 68 deletions
|
@ -13,7 +13,6 @@
|
||||||
[app.common.files.helpers :as cfh]
|
[app.common.files.helpers :as cfh]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.types.shape :as cts]
|
[app.common.types.shape :as cts]
|
||||||
[app.common.types.shape-tree :as ctt]
|
|
||||||
[app.common.types.shape.layout :as ctl]
|
[app.common.types.shape.layout :as ctl]
|
||||||
[app.main.data.workspace.transforms :as dwt]
|
[app.main.data.workspace.transforms :as dwt]
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
|
@ -329,6 +328,12 @@
|
||||||
(when (and @canvas-init? initialized?)
|
(when (and @canvas-init? initialized?)
|
||||||
(wasm.api/set-canvas-background background)))
|
(wasm.api/set-canvas-background background)))
|
||||||
|
|
||||||
|
(mf/with-effect [@canvas-init? hover-grid? @hover-top-frame-id]
|
||||||
|
(when @canvas-init?
|
||||||
|
(if hover-grid?
|
||||||
|
(wasm.api/show-grid @hover-top-frame-id)
|
||||||
|
(wasm.api/clear-grid))))
|
||||||
|
|
||||||
(hooks/setup-dom-events zoom disable-paste in-viewport? read-only? drawing-tool drawing-path?)
|
(hooks/setup-dom-events zoom disable-paste in-viewport? read-only? drawing-tool drawing-path?)
|
||||||
(hooks/setup-viewport-size vport viewport-ref)
|
(hooks/setup-viewport-size vport viewport-ref)
|
||||||
(hooks/setup-cursor cursor alt? mod? space? panning drawing-tool drawing-path? node-editing? z? read-only?)
|
(hooks/setup-cursor cursor alt? mod? space? panning drawing-tool drawing-path? node-editing? z? read-only?)
|
||||||
|
@ -639,25 +644,14 @@
|
||||||
:zoom zoom}])
|
:zoom zoom}])
|
||||||
|
|
||||||
[:g.grid-layout-editor {:clipPath "url(#clip-handlers)"}
|
[:g.grid-layout-editor {:clipPath "url(#clip-handlers)"}
|
||||||
(when (or show-grid-editor? hover-grid?)
|
(when show-grid-editor?
|
||||||
[:& grid-layout/editor
|
[:& grid-layout/editor
|
||||||
{:zoom zoom
|
{:zoom zoom
|
||||||
:objects objects-modified
|
:objects objects-modified
|
||||||
:shape (or (get base-objects edition)
|
:shape (or (get base-objects edition)
|
||||||
(get base-objects @hover-top-frame-id))
|
(get base-objects @hover-top-frame-id))
|
||||||
:view-only (not show-grid-editor?)}])
|
:view-only (not show-grid-editor?)}])]
|
||||||
|
|
||||||
(for [frame (ctt/get-frames objects)]
|
|
||||||
(when (and (ctl/grid-layout? frame)
|
|
||||||
(empty? (:shapes frame))
|
|
||||||
(not= edition (:id frame))
|
|
||||||
(not= @hover-top-frame-id (:id frame)))
|
|
||||||
[:& grid-layout/editor
|
|
||||||
{:zoom zoom
|
|
||||||
:key (dm/str (:id frame))
|
|
||||||
:objects objects-modified
|
|
||||||
:shape frame
|
|
||||||
:view-only true}]))]
|
|
||||||
[:g.scrollbar-wrapper {:clipPath "url(#clip-handlers)"}
|
[:g.scrollbar-wrapper {:clipPath "url(#clip-handlers)"}
|
||||||
[:& scroll-bars/viewport-scrollbars
|
[:& scroll-bars/viewport-scrollbars
|
||||||
{:objects base-objects
|
{:objects base-objects
|
||||||
|
|
|
@ -995,6 +995,21 @@
|
||||||
;; TODO: perform corresponding cleaning
|
;; TODO: perform corresponding cleaning
|
||||||
(h/call wasm/internal-module "_clean_up"))
|
(h/call wasm/internal-module "_clean_up"))
|
||||||
|
|
||||||
|
(defn show-grid
|
||||||
|
[id]
|
||||||
|
(let [buffer (uuid/get-u32 id)]
|
||||||
|
(h/call wasm/internal-module "_show_grid"
|
||||||
|
(aget buffer 0)
|
||||||
|
(aget buffer 1)
|
||||||
|
(aget buffer 2)
|
||||||
|
(aget buffer 3)))
|
||||||
|
(request-render "show-grid"))
|
||||||
|
|
||||||
|
(defn clear-grid
|
||||||
|
[]
|
||||||
|
(h/call wasm/internal-module "_hide_grid")
|
||||||
|
(request-render "clear-grid"))
|
||||||
|
|
||||||
(defonce module
|
(defonce module
|
||||||
(delay
|
(delay
|
||||||
(if (exists? js/dynamicImport)
|
(if (exists? js/dynamicImport)
|
||||||
|
|
|
@ -104,8 +104,7 @@ pub extern "C" fn render(_: i32) {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn render_from_cache(_: i32) {
|
pub extern "C" fn render_from_cache(_: i32) {
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
let render_state = state.render_state();
|
state.render_from_cache();
|
||||||
render_state.render_from_cache();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -691,6 +690,21 @@ pub extern "C" fn set_grid_cells() {
|
||||||
mem::free_bytes();
|
mem::free_bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn show_grid(a: u32, b: u32, c: u32, d: u32) {
|
||||||
|
with_state!(state, {
|
||||||
|
let id = uuid_from_u32_quartet(a, b, c, d);
|
||||||
|
state.render_state.show_grid = Some(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn hide_grid() {
|
||||||
|
with_state!(state, {
|
||||||
|
state.render_state.show_grid = None;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
init_gl!();
|
init_gl!();
|
||||||
|
|
|
@ -3,12 +3,14 @@ mod debug;
|
||||||
mod fills;
|
mod fills;
|
||||||
mod fonts;
|
mod fonts;
|
||||||
mod gpu_state;
|
mod gpu_state;
|
||||||
|
pub mod grid_layout;
|
||||||
mod images;
|
mod images;
|
||||||
mod options;
|
mod options;
|
||||||
mod shadows;
|
mod shadows;
|
||||||
mod strokes;
|
mod strokes;
|
||||||
mod surfaces;
|
mod surfaces;
|
||||||
mod text;
|
mod text;
|
||||||
|
mod ui;
|
||||||
|
|
||||||
use skia_safe::{self as skia, Matrix, RRect, Rect};
|
use skia_safe::{self as skia, Matrix, RRect, Rect};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -104,6 +106,7 @@ pub(crate) struct RenderState {
|
||||||
// can affect its child elements if they don't specify one themselves. If the planned
|
// can affect its child elements if they don't specify one themselves. If the planned
|
||||||
// migration to remove group-level fills is completed, this code should be removed.
|
// migration to remove group-level fills is completed, this code should be removed.
|
||||||
pub nested_fills: Vec<Vec<Fill>>,
|
pub nested_fills: Vec<Vec<Fill>>,
|
||||||
|
pub show_grid: Option<Uuid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cache_size(viewbox: Viewbox, scale: f32) -> skia::ISize {
|
pub fn get_cache_size(viewbox: Viewbox, scale: f32) -> skia::ISize {
|
||||||
|
@ -170,6 +173,7 @@ impl RenderState {
|
||||||
),
|
),
|
||||||
pending_tiles: PendingTiles::new_empty(),
|
pending_tiles: PendingTiles::new_empty(),
|
||||||
nested_fills: vec![],
|
nested_fills: vec![],
|
||||||
|
show_grid: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,7 +496,12 @@ impl RenderState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_from_cache(&mut self) {
|
pub fn render_from_cache(
|
||||||
|
&mut self,
|
||||||
|
shapes: &HashMap<Uuid, &mut Shape>,
|
||||||
|
modifiers: &HashMap<Uuid, Matrix>,
|
||||||
|
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||||
|
) {
|
||||||
let scale = self.get_cached_scale();
|
let scale = self.get_cached_scale();
|
||||||
if let Some(snapshot) = &self.cached_target_snapshot {
|
if let Some(snapshot) = &self.cached_target_snapshot {
|
||||||
let canvas = self.surfaces.canvas(SurfaceId::Target);
|
let canvas = self.surfaces.canvas(SurfaceId::Target);
|
||||||
|
@ -523,6 +532,10 @@ impl RenderState {
|
||||||
canvas.clear(self.background_color);
|
canvas.clear(self.background_color);
|
||||||
canvas.draw_image(snapshot, (0, 0), Some(&skia::Paint::default()));
|
canvas.draw_image(snapshot, (0, 0), Some(&skia::Paint::default()));
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
|
|
||||||
|
ui::render(self, shapes, modifiers, structure);
|
||||||
|
debug::render_wasm_label(self);
|
||||||
|
|
||||||
self.flush_and_submit();
|
self.flush_and_submit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -947,6 +960,7 @@ impl RenderState {
|
||||||
debug::render(self);
|
debug::render(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui::render(self, tree, modifiers, structure);
|
||||||
debug::render_wasm_label(self);
|
debug::render_wasm_label(self);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
77
render-wasm/src/render/grid_layout.rs
Normal file
77
render-wasm/src/render/grid_layout.rs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
use skia_safe::{self as skia};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::math::{Bounds, Matrix, Rect};
|
||||||
|
use crate::shapes::modifiers::grid_layout::{calculate_tracks, create_cell_data};
|
||||||
|
use crate::shapes::{modified_children_ids, Frame, Layout, Shape, StructureEntry, Type};
|
||||||
|
use crate::uuid::Uuid;
|
||||||
|
|
||||||
|
pub fn render_overlay(
|
||||||
|
zoom: f32,
|
||||||
|
canvas: &skia::Canvas,
|
||||||
|
shape: &Shape,
|
||||||
|
shapes: &HashMap<Uuid, &mut Shape>,
|
||||||
|
modifiers: &HashMap<Uuid, Matrix>,
|
||||||
|
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||||
|
) {
|
||||||
|
let Type::Frame(Frame {
|
||||||
|
layout: Some(Layout::GridLayout(layout_data, grid_data)),
|
||||||
|
..
|
||||||
|
}) = &shape.shape_type
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let bounds = &HashMap::<Uuid, Bounds>::new();
|
||||||
|
|
||||||
|
let shape = &mut shape.clone();
|
||||||
|
if let Some(modifiers) = modifiers.get(&shape.id) {
|
||||||
|
shape.apply_transform(modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
let layout_bounds = shape.bounds();
|
||||||
|
let children = modified_children_ids(shape, structure.get(&shape.id));
|
||||||
|
|
||||||
|
let column_tracks = calculate_tracks(
|
||||||
|
true,
|
||||||
|
shape,
|
||||||
|
layout_data,
|
||||||
|
grid_data,
|
||||||
|
&layout_bounds,
|
||||||
|
&grid_data.cells,
|
||||||
|
shapes,
|
||||||
|
bounds,
|
||||||
|
);
|
||||||
|
|
||||||
|
let row_tracks = calculate_tracks(
|
||||||
|
false,
|
||||||
|
shape,
|
||||||
|
layout_data,
|
||||||
|
grid_data,
|
||||||
|
&layout_bounds,
|
||||||
|
&grid_data.cells,
|
||||||
|
shapes,
|
||||||
|
bounds,
|
||||||
|
);
|
||||||
|
|
||||||
|
let cells = create_cell_data(
|
||||||
|
&layout_bounds,
|
||||||
|
&children,
|
||||||
|
shapes,
|
||||||
|
&grid_data.cells,
|
||||||
|
&column_tracks,
|
||||||
|
&row_tracks,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut paint = skia::Paint::default();
|
||||||
|
paint.set_style(skia::PaintStyle::Stroke);
|
||||||
|
paint.set_color(skia::Color::from_rgb(255, 111, 224));
|
||||||
|
|
||||||
|
paint.set_stroke_width(1.0 / zoom);
|
||||||
|
|
||||||
|
for cell in cells.iter() {
|
||||||
|
let rect = Rect::from_xywh(cell.anchor.x, cell.anchor.y, cell.width, cell.height);
|
||||||
|
canvas.draw_rect(rect, &paint);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,14 +17,15 @@ const TILE_SIZE_MULTIPLIER: i32 = 2;
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
pub enum SurfaceId {
|
pub enum SurfaceId {
|
||||||
Target = 0b0000_0001,
|
Target = 0b0_0000_0001,
|
||||||
Cache = 0b0000_0010,
|
Cache = 0b0_0000_0010,
|
||||||
Current = 0b0000_0100,
|
Current = 0b0_0000_0100,
|
||||||
Fills = 0b0000_1000,
|
Fills = 0b0_0000_1000,
|
||||||
Strokes = 0b0001_0000,
|
Strokes = 0b0_0001_0000,
|
||||||
DropShadows = 0b0010_0000,
|
DropShadows = 0b0_0010_0000,
|
||||||
InnerShadows = 0b0100_0000,
|
InnerShadows = 0b0_0100_0000,
|
||||||
Debug = 0b1000_0000,
|
UI = 0b0_1000_0000,
|
||||||
|
Debug = 0b1_0000_0000,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Surfaces {
|
pub struct Surfaces {
|
||||||
|
@ -39,8 +40,10 @@ pub struct Surfaces {
|
||||||
shape_strokes: skia::Surface,
|
shape_strokes: skia::Surface,
|
||||||
// used for rendering shadows
|
// used for rendering shadows
|
||||||
drop_shadows: skia::Surface,
|
drop_shadows: skia::Surface,
|
||||||
// used fo rendering over shadows.
|
// used for rendering over shadows.
|
||||||
inner_shadows: skia::Surface,
|
inner_shadows: skia::Surface,
|
||||||
|
// used for displaying auxiliary workspace elements
|
||||||
|
ui: skia::Surface,
|
||||||
// for drawing debug info.
|
// for drawing debug info.
|
||||||
debug: skia::Surface,
|
debug: skia::Surface,
|
||||||
// for drawing tiles.
|
// for drawing tiles.
|
||||||
|
@ -74,6 +77,8 @@ impl Surfaces {
|
||||||
gpu_state.create_surface_with_isize("shape_fills".to_string(), extra_tile_dims);
|
gpu_state.create_surface_with_isize("shape_fills".to_string(), extra_tile_dims);
|
||||||
let shape_strokes =
|
let shape_strokes =
|
||||||
gpu_state.create_surface_with_isize("shape_strokes".to_string(), extra_tile_dims);
|
gpu_state.create_surface_with_isize("shape_strokes".to_string(), extra_tile_dims);
|
||||||
|
|
||||||
|
let ui = gpu_state.create_surface_with_dimensions("ui".to_string(), width, height);
|
||||||
let debug = gpu_state.create_surface_with_dimensions("debug".to_string(), width, height);
|
let debug = gpu_state.create_surface_with_dimensions("debug".to_string(), width, height);
|
||||||
|
|
||||||
let tiles = TileTextureCache::new();
|
let tiles = TileTextureCache::new();
|
||||||
|
@ -85,6 +90,7 @@ impl Surfaces {
|
||||||
inner_shadows,
|
inner_shadows,
|
||||||
shape_fills,
|
shape_fills,
|
||||||
shape_strokes,
|
shape_strokes,
|
||||||
|
ui,
|
||||||
debug,
|
debug,
|
||||||
tiles,
|
tiles,
|
||||||
sampling_options,
|
sampling_options,
|
||||||
|
@ -198,6 +204,7 @@ impl Surfaces {
|
||||||
SurfaceId::Fills => &mut self.shape_fills,
|
SurfaceId::Fills => &mut self.shape_fills,
|
||||||
SurfaceId::Strokes => &mut self.shape_strokes,
|
SurfaceId::Strokes => &mut self.shape_strokes,
|
||||||
SurfaceId::Debug => &mut self.debug,
|
SurfaceId::Debug => &mut self.debug,
|
||||||
|
SurfaceId::UI => &mut self.ui,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +212,7 @@ impl Surfaces {
|
||||||
let dim = (target.width(), target.height());
|
let dim = (target.width(), target.height());
|
||||||
self.target = target;
|
self.target = target;
|
||||||
self.debug = self.target.new_surface_with_dimensions(dim).unwrap();
|
self.debug = self.target.new_surface_with_dimensions(dim).unwrap();
|
||||||
|
self.ui = self.target.new_surface_with_dimensions(dim).unwrap();
|
||||||
// The rest are tile size surfaces
|
// The rest are tile size surfaces
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,6 +269,10 @@ impl Surfaces {
|
||||||
self.canvas(SurfaceId::Debug)
|
self.canvas(SurfaceId::Debug)
|
||||||
.clear(skia::Color::TRANSPARENT)
|
.clear(skia::Color::TRANSPARENT)
|
||||||
.reset_matrix();
|
.reset_matrix();
|
||||||
|
|
||||||
|
self.canvas(SurfaceId::UI)
|
||||||
|
.clear(skia::Color::TRANSPARENT)
|
||||||
|
.reset_matrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cache_current_tile_texture(
|
pub fn cache_current_tile_texture(
|
||||||
|
|
43
render-wasm/src/render/ui.rs
Normal file
43
render-wasm/src/render/ui.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
use skia_safe::{self as skia, Color4f};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::math::Matrix;
|
||||||
|
use crate::render::grid_layout;
|
||||||
|
use crate::shapes::{Shape, StructureEntry};
|
||||||
|
use crate::uuid::Uuid;
|
||||||
|
|
||||||
|
use super::{RenderState, SurfaceId};
|
||||||
|
|
||||||
|
pub fn render(
|
||||||
|
render_state: &mut RenderState,
|
||||||
|
shapes: &HashMap<Uuid, &mut Shape>,
|
||||||
|
modifiers: &HashMap<Uuid, Matrix>,
|
||||||
|
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||||
|
) {
|
||||||
|
let canvas = render_state.surfaces.canvas(SurfaceId::UI);
|
||||||
|
|
||||||
|
canvas.clear(Color4f::new(0.0, 0.0, 0.0, 0.0));
|
||||||
|
canvas.save();
|
||||||
|
|
||||||
|
let viewbox = render_state.viewbox;
|
||||||
|
let zoom = viewbox.zoom * render_state.options.dpr();
|
||||||
|
|
||||||
|
canvas.scale((zoom, zoom));
|
||||||
|
|
||||||
|
canvas.translate((-viewbox.area.left, -viewbox.area.top));
|
||||||
|
|
||||||
|
let canvas = render_state.surfaces.canvas(SurfaceId::UI);
|
||||||
|
|
||||||
|
if let Some(id) = render_state.show_grid {
|
||||||
|
if let Some(shape) = shapes.get(&id) {
|
||||||
|
grid_layout::render_overlay(zoom, canvas, shape, shapes, modifiers, structure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.restore();
|
||||||
|
render_state.surfaces.draw_into(
|
||||||
|
SurfaceId::UI,
|
||||||
|
SurfaceId::Target,
|
||||||
|
Some(&skia::Paint::default()),
|
||||||
|
);
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ mod fonts;
|
||||||
mod frames;
|
mod frames;
|
||||||
mod groups;
|
mod groups;
|
||||||
mod layouts;
|
mod layouts;
|
||||||
mod modifiers;
|
pub mod modifiers;
|
||||||
mod paths;
|
mod paths;
|
||||||
mod rects;
|
mod rects;
|
||||||
mod shadows;
|
mod shadows;
|
||||||
|
@ -424,6 +424,19 @@ impl Shape {
|
||||||
padding_left: f32,
|
padding_left: f32,
|
||||||
) {
|
) {
|
||||||
if let Type::Frame(data) = &mut self.shape_type {
|
if let Type::Frame(data) = &mut self.shape_type {
|
||||||
|
if let Some(Layout::GridLayout(layout_data, grid_data)) = &mut data.layout {
|
||||||
|
layout_data.align_items = align_items;
|
||||||
|
layout_data.align_content = align_content;
|
||||||
|
layout_data.justify_items = justify_items;
|
||||||
|
layout_data.justify_content = justify_content;
|
||||||
|
layout_data.padding_top = padding_top;
|
||||||
|
layout_data.padding_right = padding_right;
|
||||||
|
layout_data.padding_bottom = padding_bottom;
|
||||||
|
layout_data.padding_left = padding_left;
|
||||||
|
layout_data.row_gap = row_gap;
|
||||||
|
layout_data.column_gap = column_gap;
|
||||||
|
grid_data.direction = direction;
|
||||||
|
} else {
|
||||||
let layout_data = LayoutData {
|
let layout_data = LayoutData {
|
||||||
align_items,
|
align_items,
|
||||||
align_content,
|
align_content,
|
||||||
|
@ -436,12 +449,12 @@ impl Shape {
|
||||||
row_gap,
|
row_gap,
|
||||||
column_gap,
|
column_gap,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut grid_data = GridData::default();
|
let mut grid_data = GridData::default();
|
||||||
grid_data.direction = direction;
|
grid_data.direction = direction;
|
||||||
data.layout = Some(Layout::GridLayout(layout_data, grid_data));
|
data.layout = Some(Layout::GridLayout(layout_data, grid_data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_grid_columns(&mut self, tracks: Vec<RawGridTrack>) {
|
pub fn set_grid_columns(&mut self, tracks: Vec<RawGridTrack>) {
|
||||||
let Type::Frame(frame_data) = &mut self.shape_type else {
|
let Type::Frame(frame_data) = &mut self.shape_type else {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
mod common;
|
mod common;
|
||||||
mod constraints;
|
mod constraints;
|
||||||
mod flex_layout;
|
mod flex_layout;
|
||||||
mod grid_layout;
|
pub mod grid_layout;
|
||||||
|
|
||||||
use common::GetBounds;
|
use common::GetBounds;
|
||||||
|
|
||||||
|
|
|
@ -14,28 +14,28 @@ const MIN_SIZE: f32 = 0.01;
|
||||||
const MAX_SIZE: f32 = f32::INFINITY;
|
const MAX_SIZE: f32 = f32::INFINITY;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct CellData<'a> {
|
pub struct CellData<'a> {
|
||||||
shape: &'a Shape,
|
pub shape: Option<&'a Shape>,
|
||||||
anchor: Point,
|
pub anchor: Point,
|
||||||
width: f32,
|
pub width: f32,
|
||||||
height: f32,
|
pub height: f32,
|
||||||
align_self: Option<AlignSelf>,
|
pub align_self: Option<AlignSelf>,
|
||||||
justify_self: Option<JustifySelf>,
|
pub justify_self: Option<JustifySelf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TrackData {
|
pub struct TrackData {
|
||||||
track_type: GridTrackType,
|
pub track_type: GridTrackType,
|
||||||
value: f32,
|
pub value: f32,
|
||||||
size: f32,
|
pub size: f32,
|
||||||
max_size: f32,
|
pub max_size: f32,
|
||||||
anchor_start: Point,
|
pub anchor_start: Point,
|
||||||
anchor_end: Point,
|
pub anchor_end: Point,
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: We might be able to simplify these arguments
|
// FIXME: We might be able to simplify these arguments
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn calculate_tracks(
|
pub fn calculate_tracks(
|
||||||
is_column: bool,
|
is_column: bool,
|
||||||
shape: &Shape,
|
shape: &Shape,
|
||||||
layout_data: &LayoutData,
|
layout_data: &LayoutData,
|
||||||
|
@ -513,29 +513,32 @@ fn cell_bounds(
|
||||||
Some(Bounds::new(nw, ne, se, sw))
|
Some(Bounds::new(nw, ne, se, sw))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_cell_data<'a>(
|
pub fn create_cell_data<'a>(
|
||||||
layout_bounds: &Bounds,
|
layout_bounds: &Bounds,
|
||||||
children: &IndexSet<Uuid>,
|
children: &IndexSet<Uuid>,
|
||||||
shapes: &'a HashMap<Uuid, &mut Shape>,
|
shapes: &'a HashMap<Uuid, &mut Shape>,
|
||||||
cells: &Vec<GridCell>,
|
cells: &Vec<GridCell>,
|
||||||
column_tracks: &[TrackData],
|
column_tracks: &[TrackData],
|
||||||
row_tracks: &[TrackData],
|
row_tracks: &[TrackData],
|
||||||
|
allow_empty: bool,
|
||||||
) -> Vec<CellData<'a>> {
|
) -> Vec<CellData<'a>> {
|
||||||
let mut result = Vec::<CellData<'a>>::new();
|
let mut result = Vec::<CellData<'a>>::new();
|
||||||
|
|
||||||
for cell in cells {
|
for cell in cells {
|
||||||
let Some(shape_id) = cell.shape else {
|
let shape: Option<&Shape> = if let Some(shape_id) = cell.shape {
|
||||||
continue;
|
if !children.contains(&shape_id) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
shapes.get(&shape_id).map(|v| &**v)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
if !children.contains(&shape_id) {
|
if !allow_empty && shape.is_none() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(shape) = shapes.get(&shape_id) else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let column_start = (cell.column - 1) as usize;
|
let column_start = (cell.column - 1) as usize;
|
||||||
let column_end = (cell.column + cell.column_span - 2) as usize;
|
let column_end = (cell.column + cell.column_span - 2) as usize;
|
||||||
let row_start = (cell.row - 1) as usize;
|
let row_start = (cell.row - 1) as usize;
|
||||||
|
@ -662,10 +665,11 @@ pub fn reflow_grid_layout(
|
||||||
&grid_data.cells,
|
&grid_data.cells,
|
||||||
&column_tracks,
|
&column_tracks,
|
||||||
&row_tracks,
|
&row_tracks,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
for cell in cells.iter() {
|
for cell in cells.iter() {
|
||||||
let child = cell.shape;
|
let Some(child) = cell.shape else { continue };
|
||||||
let child_bounds = bounds.find(child);
|
let child_bounds = bounds.find(child);
|
||||||
|
|
||||||
let mut new_width = child_bounds.width();
|
let mut new_width = child_bounds.width();
|
||||||
|
|
|
@ -108,6 +108,11 @@ impl<'a> State<'a> {
|
||||||
&mut self.render_state
|
&mut self.render_state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render_from_cache(&mut self) {
|
||||||
|
self.render_state
|
||||||
|
.render_from_cache(&self.shapes, &self.modifiers, &self.structure);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn start_render_loop(&mut self, timestamp: i32) -> Result<(), String> {
|
pub fn start_render_loop(&mut self, timestamp: i32) -> Result<(), String> {
|
||||||
self.render_state.start_render_loop(
|
self.render_state.start_render_loop(
|
||||||
&mut self.shapes,
|
&mut self.shapes,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue