1use color;
4use graph;
5use std;
6use utils::{vec2_add, vec2_sub};
7use widget;
8use {Point, Positionable, Rect, Scalar, Sizeable, Theme, Widget};
9
10#[derive(Copy, Clone, Debug, WidgetCommon_)]
12pub struct Triangles<S, I> {
13    #[conrod(common_builder)]
15    pub common: widget::CommonBuilder,
16    pub style: S,
18    pub triangles: I,
20    pub maybe_shift_to_centre_from: Option<Point>,
22}
23
24pub trait Vertex: Clone + Copy + PartialEq {
26    fn point(&self) -> Point;
28    fn add(self, p: Point) -> Self;
30}
31
32pub trait Style: widget::Style + Clone + Send {
34    type Vertex: Vertex + Send;
36}
37
38#[derive(Copy, Clone, Debug, PartialEq)]
40pub struct SingleColor(pub color::Rgba);
41
42#[derive(Copy, Clone, Debug, PartialEq)]
44pub struct MultiColor;
45
46#[derive(Copy, Clone, Debug, PartialEq)]
48pub struct Triangle<V>(pub [V; 3])
49where
50    V: Vertex;
51
52pub type ColoredPoint = (Point, color::Rgba);
54
55#[derive(Clone, Debug, PartialEq)]
57pub struct State<T> {
58    pub triangles: T,
60}
61
62impl Vertex for Point {
63    fn point(&self) -> Point {
64        *self
65    }
66    fn add(self, add: Point) -> Self {
67        vec2_add(self, add)
68    }
69}
70
71impl Vertex for ColoredPoint {
72    fn point(&self) -> Point {
73        self.0
74    }
75    fn add(self, add: Point) -> Self {
76        let (p, c) = self;
77        (vec2_add(p, add), c)
78    }
79}
80
81impl Style for SingleColor {
82    type Vertex = Point;
83}
84
85impl Style for MultiColor {
86    type Vertex = ColoredPoint;
87}
88
89#[derive(Copy, Clone, Debug)]
94pub struct TrianglesUnpositioned<S, I> {
95    triangles: Triangles<S, I>,
96}
97
98impl<V> Triangle<V>
99where
100    V: Vertex,
101{
102    pub fn add(self, amount: Point) -> Self {
104        let a = self[0].add(amount);
105        let b = self[1].add(amount);
106        let c = self[2].add(amount);
107        Triangle([a, b, c])
108    }
109
110    pub fn points(self) -> [Point; 3] {
112        [self[0].point(), self[1].point(), self[2].point()]
113    }
114}
115
116impl Triangle<Point> {
117    pub fn color(self, a: color::Rgba, b: color::Rgba, c: color::Rgba) -> Triangle<ColoredPoint> {
119        Triangle([(self[0], a), (self[1], b), (self[2], c)])
120    }
121
122    pub fn color_all(self, color: color::Rgba) -> Triangle<ColoredPoint> {
124        Triangle([(self[0], color), (self[1], color), (self[2], color)])
125    }
126}
127
128impl<V> std::ops::Deref for Triangle<V>
129where
130    V: Vertex,
131{
132    type Target = [V; 3];
133    fn deref(&self) -> &Self::Target {
134        &self.0
135    }
136}
137
138impl<V> From<[V; 3]> for Triangle<V>
139where
140    V: Vertex,
141{
142    fn from(points: [V; 3]) -> Self {
143        Triangle(points)
144    }
145}
146
147impl<V> From<(V, V, V)> for Triangle<V>
148where
149    V: Vertex,
150{
151    fn from((a, b, c): (V, V, V)) -> Self {
152        Triangle([a, b, c])
153    }
154}
155
156impl<V> Into<[V; 3]> for Triangle<V>
157where
158    V: Vertex,
159{
160    fn into(self) -> [V; 3] {
161        self.0
162    }
163}
164
165impl<V> Into<(V, V, V)> for Triangle<V>
166where
167    V: Vertex,
168{
169    fn into(self) -> (V, V, V) {
170        (self[0], self[1], self[2])
171    }
172}
173
174impl<S, I> Triangles<S, I> {
175    fn new(style: S, triangles: I) -> Self {
176        Triangles {
177            common: widget::CommonBuilder::default(),
178            style: style,
179            triangles: triangles,
180            maybe_shift_to_centre_from: None,
181        }
182    }
183}
184
185impl<I> Triangles<SingleColor, I>
186where
187    I: IntoIterator<Item = Triangle<<SingleColor as Style>::Vertex>>,
188{
189    pub fn single_color<C>(color: C, points: I) -> TrianglesUnpositioned<SingleColor, I>
193    where
194        C: Into<color::Rgba>,
195    {
196        let style = SingleColor(color.into());
197        TrianglesUnpositioned::new(Triangles::new(style, points))
198    }
199}
200
201impl<I> Triangles<MultiColor, I>
202where
203    I: IntoIterator<Item = Triangle<<MultiColor as Style>::Vertex>>,
204{
205    pub fn multi_color(points: I) -> TrianglesUnpositioned<MultiColor, I> {
209        TrianglesUnpositioned::new(Triangles::new(MultiColor, points))
210    }
211}
212
213fn bounding_rect_for_triangles<I, V>(triangles: I) -> Rect
214where
215    I: IntoIterator<Item = Triangle<V>>,
216    V: Vertex,
217{
218    struct TriangleVertices<V>
219    where
220        V: Vertex,
221    {
222        index: usize,
223        triangle: Triangle<V>,
224    }
225
226    impl<V> Iterator for TriangleVertices<V>
227    where
228        V: Vertex,
229    {
230        type Item = V;
231        fn next(&mut self) -> Option<Self::Item> {
232            let v = self.triangle.get(self.index).map(|&v| v);
233            self.index += 1;
234            v
235        }
236    }
237
238    let points = triangles.into_iter().flat_map(|t| {
239        let vs = TriangleVertices {
240            index: 0,
241            triangle: t,
242        };
243        vs.map(|v| v.point())
244    });
245    super::super::bounding_box_for_points(points)
246}
247
248impl<S, I> TrianglesUnpositioned<S, I>
249where
250    S: Style,
251    I: IntoIterator<Item = Triangle<S::Vertex>>,
252    Triangles<S, I>: Widget,
253{
254    fn new(triangles: Triangles<S, I>) -> Self {
255        TrianglesUnpositioned {
256            triangles: triangles,
257        }
258    }
259
260    pub fn with_bounding_rect(self, rect: Rect) -> Triangles<S, I> {
269        let TrianglesUnpositioned { triangles } = self;
270        let (xy, dim) = rect.xy_dim();
271        triangles.wh(dim).xy(xy)
272    }
273
274    pub fn calc_bounding_rect(self) -> Triangles<S, I>
289    where
290        I: Clone,
291    {
292        let TrianglesUnpositioned { triangles } = self;
293        let (xy, dim) = bounding_rect_for_triangles(triangles.triangles.clone()).xy_dim();
294        triangles.wh(dim).xy(xy)
295    }
296
297    pub fn centre_points_to_bounding_rect(self) -> Triangles<S, I>
312    where
313        I: Clone,
314    {
315        let TrianglesUnpositioned { mut triangles } = self;
316        let (xy, dim) = bounding_rect_for_triangles(triangles.triangles.clone()).xy_dim();
317        triangles.maybe_shift_to_centre_from = Some(xy);
318        triangles.wh(dim)
319    }
320}
321
322impl<S, I> Widget for Triangles<S, I>
323where
324    S: Style,
325    I: IntoIterator<Item = Triangle<S::Vertex>>,
326{
327    type State = State<Vec<Triangle<S::Vertex>>>;
328    type Style = S;
329    type Event = ();
330
331    fn init_state(&self, _: widget::id::Generator) -> Self::State {
332        State {
333            triangles: Vec::new(),
334        }
335    }
336
337    fn style(&self) -> Self::Style {
338        self.style.clone()
339    }
340
341    fn is_over(&self) -> widget::IsOverFn {
342        is_over_widget::<S>
343    }
344
345    fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
346        use utils::{iter_diff, IterDiff};
347        let widget::UpdateArgs { rect, state, .. } = args;
348        let Triangles {
349            triangles,
350            maybe_shift_to_centre_from,
351            ..
352        } = self;
353
354        fn update_triangles<I>(state: &mut widget::State<State<Vec<I::Item>>>, triangles: I)
357        where
358            I: IntoIterator,
359            I::Item: PartialEq,
360        {
361            match iter_diff(&state.triangles, triangles) {
362                Some(IterDiff::FirstMismatch(i, mismatch)) => state.update(|state| {
363                    state.triangles.truncate(i);
364                    state.triangles.extend(mismatch);
365                }),
366                Some(IterDiff::Longer(remaining)) => {
367                    state.update(|state| state.triangles.extend(remaining))
368                }
369                Some(IterDiff::Shorter(total)) => {
370                    state.update(|state| state.triangles.truncate(total))
371                }
372                None => (),
373            }
374        }
375
376        match maybe_shift_to_centre_from {
377            Some(original) => {
378                let xy = rect.xy();
379                let difference = vec2_sub(xy, original);
380                let triangles = triangles.into_iter().map(|tri| tri.add(difference));
381                update_triangles(state, triangles)
382            }
383            None => update_triangles(state, triangles),
384        }
385    }
386}
387
388#[inline]
437pub fn from_quad(points: [Point; 4]) -> (Triangle<Point>, Triangle<Point>) {
438    let (a, b, c, d) = (points[0], points[1], points[2], points[3]);
439    (Triangle([a, b, c]), Triangle([a, c, d]))
440}
441
442impl<V> AsRef<Triangle<V>> for Triangle<V>
443where
444    V: Vertex,
445{
446    fn as_ref(&self) -> &Triangle<V> {
447        self
448    }
449}
450
451pub fn is_over_triangle<V>(t: &Triangle<V>, p: Point) -> bool
453where
454    V: Vertex,
455{
456    let ps = t.points();
457    let (a, b, c) = (ps[0], ps[1], ps[2]);
458
459    fn sign(a: Point, b: Point, c: Point) -> Scalar {
460        (a[0] - c[0]) * (b[1] - c[1]) - (b[0] - c[0]) * (a[1] - c[1])
461    }
462
463    let b1 = sign(p, a, b) < 0.0;
464    let b2 = sign(p, b, c) < 0.0;
465    let b3 = sign(p, c, a) < 0.0;
466
467    (b1 == b2) && (b2 == b3)
468}
469
470pub fn is_over<V, I, T>(ts: I, p: Point) -> bool
472where
473    V: Vertex,
474    T: AsRef<Triangle<V>>,
475    I: IntoIterator<Item = T>,
476{
477    ts.into_iter().any(|t| is_over_triangle(t.as_ref(), p))
478}
479
480pub fn is_over_widget<S>(widget: &graph::Container, point: Point, _: &Theme) -> widget::IsOver
482where
483    S: Style,
484{
485    widget
486        .state_and_style::<State<Vec<Triangle<S::Vertex>>>, S>()
487        .map(|widget| is_over(widget.state.triangles.iter().cloned(), point))
488        .unwrap_or_else(|| widget.rect.is_over(point))
489        .into()
490}