summaryrefslogtreecommitdiffstats
path: root/examples/lib-dfscq-log/src/labeled_delimiter.rs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/lib-dfscq-log/src/labeled_delimiter.rs')
-rw-r--r--examples/lib-dfscq-log/src/labeled_delimiter.rs121
1 files changed, 121 insertions, 0 deletions
diff --git a/examples/lib-dfscq-log/src/labeled_delimiter.rs b/examples/lib-dfscq-log/src/labeled_delimiter.rs
new file mode 100644
index 0000000..5a1c610
--- /dev/null
+++ b/examples/lib-dfscq-log/src/labeled_delimiter.rs
@@ -0,0 +1,121 @@
1use diaphragm_core::{
2 core_shapes::{StraightPath, Text},
3 types::{Bounds, Float, Point2D, ShapeContext},
4 ComplexShape, DrawResult, Drawable, SolverContext,
5};
6
7#[derive(Debug, Clone)]
8pub struct Delimiter {
9 pub width: Float,
10 pub label: Drawable<Text>,
11}
12
13#[derive(Debug, Clone)]
14pub struct LabeledDelimiter {
15 pub delimiters: Vec<Delimiter>,
16 pub tick_height: Float,
17}
18
19impl ComplexShape for LabeledDelimiter {
20 fn draw(&self, context: &ShapeContext, solver: &mut dyn SolverContext) -> DrawResult {
21 let mut result = DrawResult::new();
22
23 let bounds_left = context.bounds().left(solver);
24 let bounds_right = context.bounds().right(solver);
25 let bounds_bottom = context.bounds().bottom(solver);
26 let bounds_width = context.bounds().width(solver);
27
28 let tick_top = context.bounds().top(solver);
29 let tick_bottom = solver.float_add(&[tick_top, self.tick_height]);
30
31 let first_tick = Drawable::builder(StraightPath::new(vec![
32 context.bounds().top_left(solver),
33 Point2D::new(bounds_left, tick_bottom),
34 ]))
35 .bounds(
36 Bounds::builder()
37 .top(tick_top)
38 .left(bounds_left)
39 .height(self.tick_height)
40 .width(Float::Fixed(0.))
41 .build(solver),
42 )
43 .stroke(context.stroke().clone())
44 .build(solver);
45
46 let baseline_y = first_tick.bounds().vert_center(solver);
47
48 result.push(first_tick);
49
50 // TODO: split everything into functions
51
52 let baseline = Drawable::builder(StraightPath::new(vec![
53 Point2D::new(bounds_left, baseline_y),
54 Point2D::new(bounds_right, baseline_y),
55 ]))
56 .bounds(
57 Bounds::builder()
58 .top(baseline_y)
59 .left(bounds_left)
60 .width(bounds_width)
61 .height(Float::Fixed(0.))
62 .build(solver),
63 )
64 .stroke(context.stroke().clone())
65 .build(solver);
66
67 result.push(baseline);
68
69 let mut section_end = bounds_left;
70 let mut all_label_bottoms = vec![];
71
72 for &Delimiter {
73 width: section_width,
74 ref label,
75 } in &self.delimiters
76 {
77 let section_begin = section_end;
78 section_end = solver.float_add(&[section_end, section_width]);
79
80 let section_half_width = solver.float_div(section_width, Float::Fixed(2.));
81 let section_middle = solver.float_add(&[section_begin, section_half_width]);
82
83 let tick = Drawable::builder(StraightPath::new(vec![
84 Point2D::new(section_end, tick_top),
85 Point2D::new(section_end, tick_bottom),
86 ]))
87 .bounds(
88 Bounds::builder()
89 .top(tick_top)
90 .left(section_end)
91 .height(self.tick_height)
92 .width(Float::Fixed(0.))
93 .build(solver),
94 )
95 .stroke(context.stroke().clone())
96 .build(solver);
97
98 result.push(tick);
99
100 let label_top = label.bounds().top(solver);
101 let label_bottom = label.bounds().bottom(solver);
102 let label_horiz_center = label.bounds().horiz_center(solver);
103
104 let label_top_constraint = solver.float_eq(label_top, tick_bottom);
105 solver.constrain(label_top_constraint);
106
107 let label_middle_constraint = solver.float_eq(label_horiz_center, section_middle);
108 solver.constrain(label_middle_constraint);
109
110 result.push(label.clone());
111
112 all_label_bottoms.push(label_bottom);
113 }
114
115 let wanted_bounds_bottom = solver.float_max(&all_label_bottoms);
116 let bounds_bottom_constraint = solver.float_eq(bounds_bottom, wanted_bounds_bottom);
117 solver.constrain(bounds_bottom_constraint);
118
119 result
120 }
121}