gentex/tikz/
line.rs

1use super::{commands::draw::Draw, point::Point, ArrowType, ExtendPath, PathCommand};
2
3pub struct Line<T>
4where
5    T: ExtendPath,
6{
7    parent: T,
8    x: String,
9    y: String,
10    thick: bool,
11    start: ArrowType,
12    end: ArrowType,
13}
14
15impl<T> Line<T>
16where
17    T: ExtendPath,
18{
19    fn new(
20        parent: T,
21        x: impl num::Num + std::fmt::Display,
22        y: impl num::Num + std::fmt::Display,
23    ) -> Self {
24        Line {
25            parent,
26            x: x.to_string(),
27            y: y.to_string(),
28            thick: false,
29            start: ArrowType::Default,
30            end: ArrowType::Default,
31        }
32    }
33
34    pub fn start(mut self, start: ArrowType) -> Self {
35        self.start = start;
36        self
37    }
38
39    pub fn end(mut self, end: ArrowType) -> Self {
40        self.end = end;
41        self
42    }
43
44    pub fn thick(mut self, thick: bool) -> Self {
45        self.thick = thick;
46        self
47    }
48
49    fn options(&self) -> String {
50        let mut options = Vec::new();
51        if self.thick {
52            options.push("thick".into());
53        }
54
55        match (&self.start, &self.end) {
56            (ArrowType::Default, ArrowType::Default) => {}
57            (start, end) => options.push(format!("{}-{}", start, end)),
58        };
59
60        if options.is_empty() {
61            "".into()
62        } else {
63            format!(" [{}]", options.join(","))
64        }
65    }
66}
67
68impl<T> ExtendPath for Line<T> where T: ExtendPath {}
69
70impl<T> PathCommand for Line<T>
71where
72    T: ExtendPath,
73{
74    fn text(&self) -> String {
75        format!(
76            "{}{} -- ({}, {})",
77            self.parent.text(),
78            self.options(),
79            self.x,
80            self.y
81        )
82    }
83}
84
85impl<T> Draw<T>
86where
87    T: ExtendPath,
88{
89    pub fn extend_line(
90        self,
91        x: impl num::Num + std::fmt::Display,
92        y: impl num::Num + std::fmt::Display,
93    ) -> Draw<Line<T>> {
94        Draw {
95            current: Line::new(self.current, x, y),
96        }
97    }
98}
99
100impl<T> Draw<T>
101where
102    T: PathCommand,
103{
104    pub fn line(
105        self,
106        x1: impl num::Num + std::fmt::Display,
107        y1: impl num::Num + std::fmt::Display,
108        x2: impl num::Num + std::fmt::Display,
109        y2: impl num::Num + std::fmt::Display,
110    ) -> Draw<Line<Point<T>>> {
111        self.point(x1, y1).extend_line(x2, y2)
112    }
113}
114
115impl<T> Draw<Line<T>>
116where
117    T: ExtendPath,
118{
119    pub fn arrow_start(mut self, style: ArrowType) -> Self {
120        self.current = self.current.start(style);
121        self
122    }
123
124    pub fn arrow_end(mut self, style: ArrowType) -> Self {
125        self.current = self.current.end(style);
126        self
127    }
128
129    pub fn thick(mut self, thick: bool) -> Self {
130        self.current = self.current.thick(thick);
131        self
132    }
133}
134
135#[cfg(test)]
136#[test]
137fn does_it_work() {
138    use super::TikzPicture;
139
140    let no_options = TikzPicture::begin()
141        .and(Draw::new().point(0, 0).extend_line(1, 1))
142        .end();
143
144    let thick = TikzPicture::begin()
145        .and(Draw::new().point(0, 0).extend_line(1, 1).thick(true))
146        .end();
147
148    let styled_arrow = TikzPicture::begin()
149        .and(
150            Draw::new()
151                .point(0, 0)
152                .extend_line(1, 1)
153                .arrow_start(ArrowType::Stealth),
154        )
155        .end();
156
157    let multiple_options = TikzPicture::begin()
158        .and(
159            Draw::new()
160                .line(0, 0, 1, 1)
161                .arrow_start(ArrowType::Stealth)
162                .arrow_end(ArrowType::Stealth)
163                .thick(true),
164        )
165        .end();
166
167    assert_eq!(
168        no_options,
169        "\\begin{tikzpicture}\n\t\\draw (0, 0) -- (1, 1);\n\\end{tikzpicture}"
170    );
171    assert_eq!(
172        thick,
173        "\\begin{tikzpicture}\n\t\\draw (0, 0) [thick] -- (1, 1);\n\\end{tikzpicture}"
174    );
175    assert_eq!(
176        styled_arrow,
177        "\\begin{tikzpicture}\n\t\\draw (0, 0) [stealth-] -- (1, 1);\n\\end{tikzpicture}"
178    );
179    assert_eq!(
180        multiple_options,
181        "\\begin{tikzpicture}\n\t\\draw (0, 0) [thick,stealth-stealth] -- (1, 1);\n\\end{tikzpicture}");
182}