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
/* Copyright (C) 2020 Casper Meijn <casper@meijn.net>
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

use crate::battery_icon::{BatteryIconBuilder, ChargerAlignment};
use crate::font::OverpassNumbersFont;
use crate::styled::Styled;
use crate::watchface_data::Watchface;
use core::fmt::Write;
use embedded_graphics::fonts::Text;
use embedded_graphics::style::TextStyleBuilder;
use embedded_graphics::DrawTarget;
use embedded_layout::prelude::*;
use heapless::consts::*;
use heapless::String;

/// Simple watchface style
///
/// This implements a simple watchface style, all watchface data will just be drawn as text on the
/// screen.
///
/// # Examples
///
/// ```
/// use chrono::Local;
/// use embedded_graphics::drawable::Drawable;
/// use embedded_graphics::mock_display::MockDisplay;
/// use embedded_graphics::pixelcolor::Rgb888;
/// use watchface::battery::ChargerState;
/// use watchface::battery::StateOfCharge;
/// use watchface::SimpleWatchfaceStyle;
/// use watchface::Watchface;
///
/// let style = SimpleWatchfaceStyle::default();
///
/// let styled_watchface = Watchface::build()
///      .with_time(Local::now())
///      .with_battery(StateOfCharge::from_percentage(100))
///      .with_charger(ChargerState::Full)
///      .into_styled(style);
///
/// let mut display = MockDisplay::<Rgb888>::new();
/// styled_watchface.draw(&mut display);
/// ```
#[derive(Default)]
pub struct SimpleWatchfaceStyle {}

impl<C> Drawable<C> for Styled<Watchface, SimpleWatchfaceStyle>
where
    C: RgbColor,
{
    fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), <D as DrawTarget<C>>::Error> {
        let display_area = display.display_area();

        display.clear(C::BLACK)?;

        if let Some(time) = &self.watchface.time {
            let time_text_style = TextStyleBuilder::new(OverpassNumbersFont {})
                .text_color(C::WHITE)
                .background_color(C::BLACK)
                .build();

            let mut text = String::<U8>::new();
            write!(
                &mut text,
                "{:02}:{:02}",
                time.hours_local(),
                time.minutes_local(),
            )
            .unwrap();

            Text::new(&text, Point::new(10, 70))
                .into_styled(time_text_style)
                .align_to(&display_area, horizontal::Center, vertical::Center)
                .draw(display)?
        }

        if let Some(battery) = &self.watchface.battery {
            if let Some(charger) = &self.watchface.charger {
                BatteryIconBuilder::new(Point::new(10, 10))
                    .with_charger(*charger)
                    .with_state_of_charge(*battery)
                    .with_charger_alignment(ChargerAlignment::Left)
                    .build()
                    .align_to(&display_area, horizontal::Right, vertical::Top)
                    .draw(display)?;
            }
        }

        Ok(())
    }
}