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
//! Enable simple layout operations in [`embedded-graphics`]
//!
//! This crate extends `embedded-graphics` objects that implement the `Transform` trait
//! to be aligned to other objects that have `Dimensions`.
//!
//! # Example
//!
//! Draw some text to the center of the display:
//!
//! ```rust
//! # use embedded_graphics::mock_display::MockDisplay;
//! # let mut disp: MockDisplay<BinaryColor> = MockDisplay::new();
//! #
//! use embedded_layout::prelude::*;
//! use embedded_graphics::{
//!     prelude::*,
//!     fonts::{Font6x8, Text},
//!     geometry::Point,
//!     primitives::Rectangle,
//!     pixelcolor::BinaryColor,
//!     style::TextStyleBuilder,
//! };
//!
//! let display_area = disp.display_area();
//!
//! let text_style = TextStyleBuilder::new(Font6x8)
//!                         .text_color(BinaryColor::On)
//!                         .build();
//!
//! Text::new("Hello, world!", Point::zero())
//!      .into_styled(text_style)
//!      .align_to(display_area, horizontal::Center, vertical::Center)
//!      .draw(&mut disp)
//!      .unwrap();
//! ```
//!
//! [`embedded-graphics`]: https://github.com/jamwaffles/embedded-graphics/

#![cfg_attr(not(test), no_std)]

use embedded_graphics::{geometry::Point, prelude::*, primitives::Rectangle, DrawTarget};

pub mod horizontal;
pub mod vertical;

/// The essentials
pub mod prelude {
    pub use crate::{horizontal, vertical, Align, DisplayArea};
}

/// Helper trait to retrieve display area as a `Rectangle`.
pub trait DisplayArea<C>: DrawTarget<C>
where
    C: PixelColor,
{
    fn display_area(&self) -> Rectangle;
}

impl<C, T> DisplayArea<C> for T
where
    C: PixelColor,
    T: DrawTarget<C>,
{
    fn display_area(&self) -> Rectangle {
        Rectangle::new(
            Point::new(0, 0),
            Point::new(
                (self.size().width - 1) as i32,
                (self.size().height - 1) as i32,
            ),
        )
    }
}

/// Implement this trait for horizontal alignment algorithms
pub trait HorizontalAlignment: Copy + Clone {
    fn align(&self, what: &impl Dimensions, reference: &impl Dimensions) -> i32;
}

/// Implement this trait for vertical alignment algorithms
///
/// Vertical alignment assumes lower coordinate values are higher up
pub trait VerticalAlignment: Copy + Clone {
    fn align(&self, what: &impl Dimensions, reference: &impl Dimensions) -> i32;
}

/// This trait enables alignment operations of `embedded-graphics` primitives
pub trait Align: Transform {
    fn align_to<D, H, V>(self, reference: D, horizontal: H, vertical: V) -> Self
    where
        D: Dimensions,
        H: HorizontalAlignment,
        V: VerticalAlignment;

    fn align_to_mut<D, H, V>(&mut self, reference: D, horizontal: H, vertical: V) -> &mut Self
    where
        D: Dimensions,
        H: HorizontalAlignment,
        V: VerticalAlignment;
}

impl<T> Align for T
where
    T: Dimensions + Transform,
{
    fn align_to<D, H, V>(self, reference: D, horizontal: H, vertical: V) -> Self
    where
        D: Dimensions,
        H: HorizontalAlignment,
        V: VerticalAlignment,
    {
        let h = horizontal.align(&self, &reference);
        let v = vertical.align(&self, &reference);
        self.translate(Point::new(h, v))
    }

    fn align_to_mut<D, H, V>(&mut self, reference: D, horizontal: H, vertical: V) -> &mut Self
    where
        D: Dimensions,
        H: HorizontalAlignment,
        V: VerticalAlignment,
    {
        let h = horizontal.align(self, &reference);
        let v = vertical.align(self, &reference);
        self.translate_mut(Point::new(h, v))
    }
}