1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
use super::complex_shapes::{ComplexShape, DrawResult};
use super::rendering::{Render, Renderer};
use super::solving::{Constrainable, SolverContext, SolverModel};
use super::types::*;
pub trait CoreShape {
fn constrain(
&self,
_context: &ShapeContext,
_solver: &mut dyn SolverContext,
_renderer: &dyn Renderer,
) {
}
fn to_render(&self, model: &dyn SolverModel) -> Option<Box<dyn Render>>;
}
impl<T: CoreShape + Clone + 'static> ComplexShape for T {
fn as_core_shape(&self) -> Option<&dyn CoreShape> {
Some(self)
}
fn draw(&self, _context: &ShapeContext, _solver: &mut dyn SolverContext) -> DrawResult {
panic!("Tried to decompose core shape")
}
}
// TODO: add default
#[derive(Copy, Clone, Debug, Default)]
pub struct Rectangle {}
impl CoreShape for Rectangle {
fn to_render(&self, _model: &dyn SolverModel) -> Option<Box<dyn Render>> {
Some(Box::new(*self))
}
}
pub use super::text::{DefinedText, Text};
impl CoreShape for Text {
fn constrain(
&self,
context: &ShapeContext,
solver: &mut dyn SolverContext,
renderer: &dyn Renderer,
) {
let height_constraint = solver.float_eq(context.bounds.height, self.font.size);
solver.constrain(height_constraint);
// TODO: handle multiline
let (width, height) = renderer.text_extents(&self.content, &self.font);
dbg!(height);
let scale = solver.float_div(self.font.size, Float::Fixed(height));
let calculated_width = solver.float_mul(&[Float::Fixed(width), scale]);
let width_constraint = solver.float_eq(context.bounds.width, calculated_width);
solver.constrain(width_constraint);
}
fn to_render(&self, model: &dyn SolverModel) -> Option<Box<dyn Render>> {
self.fixate(model)
.map(|path| -> Box<dyn Render> { Box::new(path) })
}
}
#[derive(Clone, Debug, Default)]
pub struct StraightPath {
pub(crate) points: Vec<Point2D>,
}
impl StraightPath {
pub fn new(points: Vec<Point2D>) -> Self {
Self { points }
}
}
pub struct DefinedStraightPath {
pub(crate) points: Vec<DefinedPoint2D>,
}
impl CoreShape for StraightPath {
fn to_render(&self, model: &dyn SolverModel) -> Option<Box<dyn Render>> {
self.fixate(model)
.map(|path| -> Box<dyn Render> { Box::new(path) })
}
}
|