matrix_gui/helper/matrix_utils.rs
1//! Utility functions for matrix_gui framework.
2//!
3//! This module provides common utility functions used throughout the framework
4//! for creating and manipulating graphical elements.
5//!
6//! # Functions
7//!
8//! - [`make_rounded_rect`]: Creates a rounded rectangle with equal corner radii
9//! - [`make_text`]: Creates a text element with specified styling
10//! - [`text_align_translate`]: Aligns and positions text within a rectangle
11//! - [`select`]: Selects one of two values based on a condition
12//!
13//! # Example
14//!
15//! ```ignore
16//! use matrix_gui::prelude::*;
17//! use embedded_graphics::primitives::Rectangle;
18//!
19//! // Create a rounded rectangle
20//! let rect = Rectangle::new(Point::new(10, 10), Size::new(100, 50));
21//! let rounded = matrix_utils::make_rounded_rect(&rect, 5);
22//!
23//! // Create and align text
24//! let mut text = matrix_utils::make_text("Hello", font, Rgb565::WHITE);
25//! matrix_utils::text_align_translate(&mut text, &rect, HorizontalAlign::Center);
26//! ```
27
28use crate::ui::HorizontalAlign;
29use crate::ui_font::{UiFont, UiTextStyle};
30use embedded_graphics::prelude::*;
31use embedded_graphics::primitives::RoundedRectangle;
32use embedded_graphics::text::Baseline;
33use embedded_graphics::{
34 prelude::{PixelColor, Point},
35 primitives::Rectangle,
36 text::Text,
37};
38
39/// Creates a rounded rectangle with equal corner radii.
40///
41/// This is a convenience function for creating rounded rectangles where all
42/// corners have the same radius.
43///
44/// # Arguments
45///
46/// * `area` - The rectangle defining the bounds of the rounded rectangle.
47/// * `corner_radius` - The radius for all corners.
48///
49/// # Returns
50///
51/// A `RoundedRectangle` with equal corner radii.
52///
53/// # Example
54///
55/// ```rust
56/// use matrix_gui::prelude::*;
57/// use embedded_graphics::primitives::Rectangle;
58///
59/// let rect = Rectangle::new(Point::new(10, 10), Size::new(100, 50));
60/// let rounded = matrix_utils::make_rounded_rect(&rect, 5);
61/// ```
62#[inline]
63pub const fn make_rounded_rect(area: &Rectangle, corner_radius: u32) -> RoundedRectangle {
64 RoundedRectangle::with_equal_corners(*area, Size::new(corner_radius, corner_radius))
65}
66
67/// Creates a text element with specified styling.
68///
69/// This is a convenience function for creating text elements with a given
70/// label, font, and color. The text is positioned at the origin (0, 0)
71/// with top baseline alignment.
72///
73/// # Type Parameters
74///
75/// * `'a` - The lifetime of the label string.
76/// * `COL` - The pixel color type implementing [`PixelColor`].
77///
78/// # Arguments
79///
80/// * `label` - The text string to display.
81/// * `font` - The font to use for rendering.
82/// * `text_color` - The color of the text.
83///
84/// # Returns
85///
86/// A `Text` element with the specified styling.
87///
88/// # Example
89///
90/// ```ignore
91/// use matrix_gui::prelude::*;
92///
93/// let text = matrix_utils::make_text("Hello", my_font, Rgb565::WHITE);
94/// ```
95#[inline]
96pub const fn make_text<'a, COL: PixelColor>(
97 label: &'a str,
98 font: UiFont<'a>,
99 text_color: COL,
100) -> Text<'a, UiTextStyle<'a, COL>> {
101 Text::with_baseline(
102 label,
103 Point::new(0, 0),
104 UiTextStyle::new(font, text_color),
105 Baseline::Top,
106 )
107}
108
109/// Aligns and positions text within a rectangle.
110///
111/// This function calculates the appropriate offset to center the text within
112/// the rectangle based on the specified horizontal alignment. The text is
113/// positioned at the top-left corner of the rectangle plus the calculated offset.
114///
115/// # Type Parameters
116///
117/// * `COL` - The pixel color type implementing [`PixelColor`].
118///
119/// # Arguments
120///
121/// * `text` - Mutable reference to the text element to align.
122/// * `rect` - The rectangle to align the text within.
123/// * `align` - The horizontal alignment strategy.
124///
125/// # Example
126///
127/// ```ignore
128/// use matrix_gui::prelude::*;
129///
130/// let mut text = matrix_utils::make_text("Hello", font, Rgb565::WHITE);
131/// let rect = Rectangle::new(Point::new(10, 10), Size::new(100, 50));
132/// matrix_utils::text_align_translate(&mut text, &rect, HorizontalAlign::Center);
133/// ```
134pub fn text_align_translate<COL: PixelColor>(
135 text: &mut Text<'_, UiTextStyle<'_, COL>>,
136 rect: &Rectangle,
137 align: HorizontalAlign,
138) {
139 let text_size = text.bounding_box().size;
140 let offset_x = match align {
141 HorizontalAlign::Left => 0,
142 HorizontalAlign::Center | HorizontalAlign::Justify => {
143 (rect.size.width as i32 - text_size.width as i32) / 2
144 }
145 HorizontalAlign::Right => rect.size.width as i32 - text_size.width as i32,
146 };
147 let offset_y = (rect.size.height as i32 - text_size.height as i32) / 2;
148
149 text.position = rect.top_left;
150 text.translate_mut(Point::new(offset_x, offset_y));
151}
152
153/// Selects one of two values based on a condition.
154///
155/// This is a convenience function for conditional value selection, similar to
156/// the ternary operator in other languages.
157///
158/// # Type Parameters
159///
160/// * `T` - The type of values to select from.
161///
162/// # Arguments
163///
164/// * `condition` - If `true`, returns `true_val`; otherwise returns `false_val`.
165/// * `true_val` - The value to return if condition is `true`.
166/// * `false_val` - The value to return if condition is `false`.
167///
168/// # Returns
169///
170/// `true_val` if `condition` is `true`, otherwise `false_val`.
171///
172/// # Example
173///
174/// ```rust
175/// use matrix_gui::prelude::*;
176///
177/// let value = matrix_utils::select(true, 10, 20); // Returns 10
178/// let value2 = matrix_utils::select(false, 10, 20); // Returns 20
179/// ```
180#[inline]
181pub fn select<T>(condition: bool, true_val: T, false_val: T) -> T {
182 if condition { true_val } else { false_val }
183}