ori_core/views/
aligned.rs

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use ori_macro::example;

use crate::{
    context::{BuildCx, DrawCx, EventCx, LayoutCx, RebuildCx},
    event::Event,
    layout::{Alignment, Size, Space},
    rebuild::Rebuild,
    view::{Pod, PodState, View},
};

/// Create a new [`Aligned`] view.
pub fn align<V>(alignment: impl Into<Alignment>, view: V) -> Aligned<V> {
    Aligned::new(alignment.into(), view)
}

/// Create a new [`Aligned`] view that aligns its content to the center.
pub fn center<V>(view: V) -> Aligned<V> {
    Aligned::new(Alignment::CENTER, view)
}

/// Create a new [`Aligned`] view that aligns its content to the top left.
pub fn top_left<V>(view: V) -> Aligned<V> {
    Aligned::new(Alignment::TOP_LEFT, view)
}

/// Create a new [`Aligned`] view that aligns its content to the top.
pub fn top<V>(view: V) -> Aligned<V> {
    Aligned::new(Alignment::TOP, view)
}

/// Create a new [`Aligned`] view that aligns its content to the top right.
pub fn top_right<V>(view: V) -> Aligned<V> {
    Aligned::new(Alignment::TOP_RIGHT, view)
}

/// Create a new [`Aligned`] view that aligns its content to the left.
pub fn left<V>(view: V) -> Aligned<V> {
    Aligned::new(Alignment::LEFT, view)
}

/// Create a new [`Aligned`] view that aligns its content to the right.
pub fn right<V>(view: V) -> Aligned<V> {
    Aligned::new(Alignment::RIGHT, view)
}

/// Create a new [`Aligned`] view that aligns its content to the bottom left.
pub fn bottom_left<V>(view: V) -> Aligned<V> {
    Aligned::new(Alignment::BOTTOM_LEFT, view)
}

/// Create a new [`Aligned`] view that aligns its content to the bottom.
pub fn bottom<V>(view: V) -> Aligned<V> {
    Aligned::new(Alignment::BOTTOM, view)
}

/// Create a new [`Aligned`] view that aligns its content to the bottom right.
pub fn bottom_right<V>(view: V) -> Aligned<V> {
    Aligned::new(Alignment::BOTTOM_RIGHT, view)
}

/// A view that aligns its content.
#[example(name = "align", width = 400, height = 300)]
#[derive(Rebuild)]
pub struct Aligned<V> {
    /// The content to align.
    pub content: Pod<V>,
    /// The alignment.
    #[rebuild(layout)]
    pub alignment: Alignment,
}

impl<V> Aligned<V> {
    /// Create a new aligned view.
    pub fn new(alignment: Alignment, content: V) -> Self {
        Self {
            content: Pod::new(content),
            alignment,
        }
    }
}

impl<T, V: View<T>> View<T> for Aligned<V> {
    type State = PodState<T, V>;

    fn build(&mut self, cx: &mut BuildCx, data: &mut T) -> Self::State {
        self.content.build(cx, data)
    }

    fn rebuild(&mut self, state: &mut Self::State, cx: &mut RebuildCx, data: &mut T, old: &Self) {
        Rebuild::rebuild(self, cx, old);

        self.content.rebuild(state, cx, data, &old.content);
    }

    fn event(
        &mut self,
        state: &mut Self::State,
        cx: &mut EventCx,
        data: &mut T,
        event: &Event,
    ) -> bool {
        self.content.event(state, cx, data, event)
    }

    fn layout(
        &mut self,
        state: &mut Self::State,
        cx: &mut LayoutCx,
        data: &mut T,
        space: Space,
    ) -> Size {
        let content_space = space.loosen();
        let content_size = self.content.layout(state, cx, data, content_space);

        let size = content_size
            .max(space.min.finite_or_zero())
            .max(space.max.finite_or_zero());

        let align = self.alignment.align(content_size, size);
        state.translate(align);

        size
    }

    fn draw(&mut self, state: &mut Self::State, cx: &mut DrawCx, data: &mut T) {
        self.content.draw(state, cx, data);
    }
}