summaryrefslogtreecommitdiffstats
path: root/core/src/core_shapes.rs
blob: 805d82e3c1a315e67c20b1b339153b4091a44f29 (plain)
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) })
    }
}