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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//! Items related to the styling of text.

use crate::text::{Align, Font, FontSize, Justify, Scalar, Wrap};

/// A context for building a text layout.
#[derive(Clone, Debug, Default)]
pub struct Builder {
    pub line_spacing: Option<Scalar>,
    pub line_wrap: Option<Option<Wrap>>,
    pub font_size: Option<FontSize>,
    pub justify: Option<Justify>,
    pub font: Option<Option<Font>>,
    pub y_align: Option<Align>,
}

/// Properties related to the layout of multi-line text for a single font and font size.
#[derive(Clone, Debug)]
pub struct Layout {
    pub line_spacing: Scalar,
    pub line_wrap: Option<Wrap>,
    pub justify: Justify,
    pub font_size: FontSize,
    pub font: Option<Font>,
    pub y_align: Align,
}

pub const DEFAULT_LINE_WRAP: Option<Wrap> = Some(Wrap::Whitespace);
pub const DEFAULT_FONT_SIZE: u32 = 12;
pub const DEFAULT_LINE_SPACING: f32 = 0.0;
pub const DEFAULT_JUSTIFY: Justify = Justify::Center;
pub const DEFAULT_Y_ALIGN: Align = Align::Middle;

impl Builder {
    /// The font size to use for the text.
    pub fn font_size(mut self, size: FontSize) -> Self {
        self.font_size = Some(size);
        self
    }

    /// Specify whether or not text should be wrapped around some width and how to do so.
    ///
    /// The default value is `DEFAULT_LINE_WRAP`.
    pub fn line_wrap(mut self, line_wrap: Option<Wrap>) -> Self {
        self.line_wrap = Some(line_wrap);
        self
    }

    /// Specify that the **Text** should not wrap lines around the width.
    ///
    /// Shorthand for `builder.line_wrap(None)`.
    pub fn no_line_wrap(self) -> Self {
        self.line_wrap(None)
    }

    /// Line wrap the **Text** at the beginning of the first word that exceeds the width.
    ///
    /// Shorthand for `builder.line_wrap(Some(Wrap::Whitespace))`.
    pub fn wrap_by_word(self) -> Self {
        self.line_wrap(Some(Wrap::Whitespace))
    }

    /// Line wrap the **Text** at the beginning of the first character that exceeds the width.
    ///
    /// Shorthand for `builder.line_wrap(Some(Wrap::Character))`.
    pub fn wrap_by_character(self) -> Self {
        self.line_wrap(Some(Wrap::Character))
    }

    /// A method for specifying the `Font` used for displaying the `Text`.
    pub fn font(mut self, font: Font) -> Self {
        self.font = Some(Some(font));
        self
    }

    /// Describe the end along the *x* axis to which the text should be aligned.
    pub fn justify(mut self, justify: Justify) -> Self {
        self.justify = Some(justify);
        self
    }

    /// Align the text to the left of its bounding **Rect**'s *x* axis range.
    pub fn left_justify(self) -> Self {
        self.justify(Justify::Left)
    }

    /// Align the text to the middle of its bounding **Rect**'s *x* axis range.
    pub fn center_justify(self) -> Self {
        self.justify(Justify::Center)
    }

    /// Align the text to the right of its bounding **Rect**'s *x* axis range.
    pub fn right_justify(self) -> Self {
        self.justify(Justify::Right)
    }

    /// Specify how much vertical space should separate each line of text.
    pub fn line_spacing(mut self, spacing: Scalar) -> Self {
        self.line_spacing = Some(spacing);
        self
    }

    /// Specify how the whole text should be aligned along the y axis of its bounding rectangle
    pub fn y_align(mut self, align: Align) -> Self {
        self.y_align = Some(align);
        self
    }

    /// Align the top edge of the text with the top edge of its bounding rectangle.
    pub fn align_top(self) -> Self {
        self.y_align(Align::End)
    }

    /// Align the middle of the text with the middle of the bounding rect along the y axis..
    ///
    /// This is the default behaviour.
    pub fn align_middle_y(self) -> Self {
        self.y_align(Align::Middle)
    }

    /// Align the bottom edge of the text with the bottom edge of its bounding rectangle.
    pub fn align_bottom(self) -> Self {
        self.y_align(Align::Start)
    }

    /// Set all the parameters via an existing `Layout`
    pub fn layout(mut self, layout: &Layout) -> Self {
        self.font = Some(layout.font.clone());
        self.line_spacing(layout.line_spacing)
            .line_wrap(layout.line_wrap)
            .justify(layout.justify)
            .font_size(layout.font_size)
            .y_align(layout.y_align)
    }

    /// Build the text layout.
    pub fn build(self) -> Layout {
        Layout {
            line_spacing: self.line_spacing.unwrap_or(DEFAULT_LINE_SPACING),
            line_wrap: self.line_wrap.unwrap_or(DEFAULT_LINE_WRAP),
            justify: self.justify.unwrap_or(DEFAULT_JUSTIFY),
            font_size: self.font_size.unwrap_or(DEFAULT_FONT_SIZE),
            font: self.font.unwrap_or(None),
            y_align: self.y_align.unwrap_or(DEFAULT_Y_ALIGN),
        }
    }
}

impl Default for Layout {
    fn default() -> Self {
        Layout {
            line_spacing: DEFAULT_LINE_SPACING,
            line_wrap: DEFAULT_LINE_WRAP,
            justify: DEFAULT_JUSTIFY,
            font_size: DEFAULT_FONT_SIZE,
            font: None,
            y_align: DEFAULT_Y_ALIGN,
        }
    }
}