Add from_data

This commit is contained in:
kieran 2025-01-10 21:02:25 +00:00
parent 113ac26d38
commit 09b86d9aab
No known key found for this signature in database
GPG Key ID: DE71CEB3925BE941
2 changed files with 65 additions and 23 deletions

View File

@ -1,23 +1,36 @@
use eframe::{Frame, NativeOptions};
use egui::{CentralPanel, Context, Widget};
use egui::{CentralPanel, Context, TextEdit, TopBottomPanel, Widget};
use egui_qr::QrCodeWidget;
use qrcode::QrCode;
fn main() {
let _ = eframe::run_native(
"egui_qr",
NativeOptions::default(),
Box::new(|_| Box::new(App)),
Box::new(|_| Box::new(App::new())),
);
}
struct App;
struct App {
data: String,
}
impl App {
pub fn new() -> Self {
Self {
data: String::new(),
}
}
}
impl eframe::App for App {
fn update(&mut self, ctx: &Context, frame: &mut Frame) {
let code = QrCode::new(b"hello").unwrap();
fn update(&mut self, ctx: &Context, _frame: &mut Frame) {
TopBottomPanel::top("main").show(ctx, |ui| TextEdit::singleline(&mut self.data).ui(ui));
CentralPanel::default().show(ctx, |ui| {
QrCodeWidget::new(&code).ui(ui);
if let Ok(q) = QrCodeWidget::from_data(self.data.as_bytes()) {
q.ui(ui)
} else {
ui.label("Invalid data")
}
});
}
}

View File

@ -1,13 +1,28 @@
use egui::{vec2, Color32, Rect, Response, Rounding, Sense, Stroke, Ui, Widget};
use qrcode::types::QrError;
use qrcode::{Color, QrCode};
enum CodeSrc<'a> {
Ref(&'a QrCode),
Owned(QrCode),
}
pub struct QrCodeWidget<'a> {
code: &'a QrCode,
code: CodeSrc<'a>,
}
impl<'a> QrCodeWidget<'a> {
pub fn new(code: &'a QrCode) -> Self {
QrCodeWidget { code }
QrCodeWidget {
code: CodeSrc::Ref(code),
}
}
pub fn from_data(data: &[u8]) -> Result<Self, QrError> {
let code = QrCode::new(data)?;
Ok(QrCodeWidget {
code: CodeSrc::Owned(code),
})
}
}
@ -15,25 +30,39 @@ impl Widget for QrCodeWidget<'_> {
fn ui(self, ui: &mut Ui) -> Response {
let size = ui.available_size();
let (response, painter) = ui.allocate_painter(size, Sense::click());
let w = self.code.width();
let start = response.rect.min;
let code_ref = match &self.code {
CodeSrc::Ref(code) => code,
CodeSrc::Owned(q) => q,
};
let w = code_ref.width();
let scale = (size.x.min(size.y) / w as f32).floor();
let start = ui.cursor().min;
let (response, painter) =
ui.allocate_painter(vec2(w as f32 * scale, w as f32 * scale), Sense::click());
painter.rect(
response.rect,
Rounding::none(),
Color32::WHITE,
Stroke::NONE,
);
let mut ctr = 0;
let scale = (size.x / w as f32).floor();
for c in self.code.to_colors() {
for c in code_ref.to_colors() {
let row = ctr / w;
let col = ctr % w;
let c_start = start + vec2(col as f32 * scale, row as f32 * scale);
let c_end = c_start + vec2(scale, scale);
painter.rect(
Rect::from_min_max(c_start, c_end),
Rounding::none(),
match c {
Color::Light => Color32::WHITE,
Color::Dark => Color32::BLACK,
},
Stroke::NONE,
);
if matches!(c, Color::Dark) {
painter.rect(
Rect::from_min_max(c_start, c_end),
Rounding::none(),
match c {
Color::Light => Color32::WHITE,
Color::Dark => Color32::BLACK,
},
Stroke::NONE,
);
}
ctr += 1;
}
response