Styling for QR Code using theme framework
This commit is contained in:
parent
99a3f25c5f
commit
c2d82833a0
4 changed files with 94 additions and 20 deletions
|
|
@ -24,6 +24,7 @@ pub mod menu;
|
|||
pub mod pane_grid;
|
||||
pub mod pick_list;
|
||||
pub mod progress_bar;
|
||||
pub mod qr_code;
|
||||
pub mod radio;
|
||||
pub mod rule;
|
||||
pub mod scrollable;
|
||||
|
|
|
|||
20
style/src/qr_code.rs
Normal file
20
style/src/qr_code.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
//! Change the appearance of a QR code.
|
||||
use crate::core::Color;
|
||||
|
||||
/// The appearance of a QR code.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Appearance {
|
||||
/// The color of the QR code data cells
|
||||
pub cell: Color,
|
||||
/// The color of the QR code background
|
||||
pub background: Color,
|
||||
}
|
||||
|
||||
/// A set of rules that dictate the style of a QR code.
|
||||
pub trait StyleSheet {
|
||||
/// The supported style of the [`StyleSheet`].
|
||||
type Style: Default;
|
||||
|
||||
/// Produces the style of a QR code.
|
||||
fn appearance(&self, style: &Self::Style) -> Appearance;
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ use crate::menu;
|
|||
use crate::pane_grid;
|
||||
use crate::pick_list;
|
||||
use crate::progress_bar;
|
||||
use crate::qr_code;
|
||||
use crate::radio;
|
||||
use crate::rule;
|
||||
use crate::scrollable;
|
||||
|
|
@ -956,6 +957,46 @@ impl<T: Fn(&Theme) -> progress_bar::Appearance> progress_bar::StyleSheet for T {
|
|||
}
|
||||
}
|
||||
|
||||
/// The style of a QR Code.
|
||||
#[derive(Default)]
|
||||
pub enum QRCode {
|
||||
/// The default style.
|
||||
#[default]
|
||||
Default,
|
||||
/// A custom style.
|
||||
Custom(Box<dyn qr_code::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
impl<T: Fn(&Theme) -> qr_code::Appearance + 'static> From<T> for QRCode {
|
||||
fn from(f: T) -> Self {
|
||||
Self::Custom(Box::new(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl qr_code::StyleSheet for Theme {
|
||||
type Style = QRCode;
|
||||
|
||||
fn appearance(&self, style: &Self::Style) -> qr_code::Appearance {
|
||||
let palette = self.palette();
|
||||
|
||||
match style {
|
||||
QRCode::Default => qr_code::Appearance {
|
||||
cell: palette.text,
|
||||
background: palette.background,
|
||||
},
|
||||
QRCode::Custom(custom) => custom.appearance(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Fn(&Theme) -> qr_code::Appearance> qr_code::StyleSheet for T {
|
||||
type Style = Theme;
|
||||
|
||||
fn appearance(&self, style: &Self::Style) -> qr_code::Appearance {
|
||||
(self)(style)
|
||||
}
|
||||
}
|
||||
|
||||
/// The style of a rule.
|
||||
#[derive(Default)]
|
||||
pub enum Rule {
|
||||
|
|
|
|||
|
|
@ -5,51 +5,59 @@ use crate::core::mouse;
|
|||
use crate::core::renderer::{self, Renderer as _};
|
||||
use crate::core::widget::Tree;
|
||||
use crate::core::{
|
||||
Color, Element, Layout, Length, Point, Rectangle, Size, Vector, Widget,
|
||||
Element, Layout, Length, Point, Rectangle, Size, Vector, Widget,
|
||||
};
|
||||
use crate::graphics::geometry::Renderer as _;
|
||||
use crate::Renderer;
|
||||
use thiserror::Error;
|
||||
|
||||
pub use crate::style::qr_code::StyleSheet;
|
||||
|
||||
const DEFAULT_CELL_SIZE: u16 = 4;
|
||||
const QUIET_ZONE: usize = 2;
|
||||
|
||||
/// A type of matrix barcode consisting of squares arranged in a grid which
|
||||
/// can be read by an imaging device, such as a camera.
|
||||
#[derive(Debug)]
|
||||
pub struct QRCode<'a> {
|
||||
pub struct QRCode<'a, Theme = crate::Theme>
|
||||
where
|
||||
Theme: StyleSheet,
|
||||
{
|
||||
state: &'a State,
|
||||
dark: Color,
|
||||
light: Color,
|
||||
cell_size: u16,
|
||||
style: Theme::Style,
|
||||
}
|
||||
|
||||
impl<'a> QRCode<'a> {
|
||||
impl<'a, Theme> QRCode<'a, Theme>
|
||||
where
|
||||
Theme: StyleSheet,
|
||||
{
|
||||
/// Creates a new [`QRCode`] with the provided [`State`].
|
||||
pub fn new(state: &'a State) -> Self {
|
||||
Self {
|
||||
cell_size: DEFAULT_CELL_SIZE,
|
||||
dark: Color::BLACK,
|
||||
light: Color::WHITE,
|
||||
state,
|
||||
style: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets both the dark and light [`Color`]s of the [`QRCode`].
|
||||
pub fn color(mut self, dark: Color, light: Color) -> Self {
|
||||
self.dark = dark;
|
||||
self.light = light;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the size of the squares of the grid cell of the [`QRCode`].
|
||||
pub fn cell_size(mut self, cell_size: u16) -> Self {
|
||||
self.cell_size = cell_size;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the style of the [`QRCode`].
|
||||
pub fn style(mut self, style: impl Into<Theme::Style>) -> Self {
|
||||
self.style = style.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme> Widget<Message, Theme, Renderer> for QRCode<'a> {
|
||||
impl<'a, Message, Theme> Widget<Message, Theme, Renderer> for QRCode<'a, Theme>
|
||||
where
|
||||
Theme: StyleSheet,
|
||||
{
|
||||
fn size(&self) -> Size<Length> {
|
||||
Size {
|
||||
width: Length::Shrink,
|
||||
|
|
@ -73,7 +81,7 @@ impl<'a, Message, Theme> Widget<Message, Theme, Renderer> for QRCode<'a> {
|
|||
&self,
|
||||
_state: &Tree,
|
||||
renderer: &mut Renderer,
|
||||
_theme: &Theme,
|
||||
theme: &Theme,
|
||||
_style: &renderer::Style,
|
||||
layout: Layout<'_>,
|
||||
_cursor: mouse::Cursor,
|
||||
|
|
@ -82,6 +90,8 @@ impl<'a, Message, Theme> Widget<Message, Theme, Renderer> for QRCode<'a> {
|
|||
let bounds = layout.bounds();
|
||||
let side_length = self.state.width + 2 * QUIET_ZONE;
|
||||
|
||||
let style = theme.appearance(&self.style);
|
||||
|
||||
// Reuse cache if possible
|
||||
let geometry =
|
||||
self.state.cache.draw(renderer, bounds.size(), |frame| {
|
||||
|
|
@ -92,7 +102,7 @@ impl<'a, Message, Theme> Widget<Message, Theme, Renderer> for QRCode<'a> {
|
|||
frame.fill_rectangle(
|
||||
Point::ORIGIN,
|
||||
Size::new(side_length as f32, side_length as f32),
|
||||
self.light,
|
||||
style.background,
|
||||
);
|
||||
|
||||
// Avoid drawing on the quiet zone
|
||||
|
|
@ -114,7 +124,7 @@ impl<'a, Message, Theme> Widget<Message, Theme, Renderer> for QRCode<'a> {
|
|||
frame.fill_rectangle(
|
||||
Point::new(column as f32, row as f32),
|
||||
Size::UNIT,
|
||||
self.dark,
|
||||
style.cell,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -128,10 +138,12 @@ impl<'a, Message, Theme> Widget<Message, Theme, Renderer> for QRCode<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme> From<QRCode<'a>>
|
||||
impl<'a, Message, Theme> From<QRCode<'a, Theme>>
|
||||
for Element<'a, Message, Theme, Renderer>
|
||||
where
|
||||
Theme: StyleSheet + 'a,
|
||||
{
|
||||
fn from(qr_code: QRCode<'a>) -> Self {
|
||||
fn from(qr_code: QRCode<'a, Theme>) -> Self {
|
||||
Self::new(qr_code)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue