Step towards the importer screen.

pull/1/head
Benedikt Terhechte 3 years ago
parent 5dcc29a819
commit 17c3326c36

1
Cargo.lock generated

@ -860,6 +860,7 @@ dependencies = [
"mbox-reader",
"num-format",
"objc",
"rand",
"rayon",
"regex",
"rfd",

@ -49,6 +49,7 @@ emlx = { git = "https://github.com/terhechte/emlx", features = []}
walkdir = "*"
mbox-reader = "0.2.0"
rfd = "0.5.1"
rand = "0.8.4"
[features]
default = ["gui"]

@ -4,10 +4,11 @@ use eframe::{
};
use eyre::Result;
use super::app_state::{self, Startup, Visualize};
use super::app_state::{self, Import, Startup, Visualize};
pub enum GmailDBApp {
Startup { panel: Startup },
Import { panel: Import },
Visualize { panel: Visualize },
}
@ -15,8 +16,8 @@ impl GmailDBApp {
pub fn new() -> Result<Self> {
// Temporarily create config without state machine
let config = app_state::make_temporary_ui_config();
Ok(GmailDBApp::Startup {
panel: Startup::default(),
Ok(GmailDBApp::Import {
panel: Import::new(config),
})
}
}
@ -50,6 +51,7 @@ impl epi::App for GmailDBApp {
fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) {
match self {
GmailDBApp::Startup { panel } => Self::update_panel(panel, ctx, frame),
GmailDBApp::Import { panel } => Self::update_panel(panel, ctx, frame),
_ => panic!(),
}
@ -59,7 +61,7 @@ impl epi::App for GmailDBApp {
}
impl GmailDBApp {
fn update_panel(panel: &mut Startup, ctx: &egui::CtxRef, _frame: &mut epi::Frame<'_>) {
fn update_panel(panel: impl egui::Widget, ctx: &egui::CtxRef, _frame: &mut epi::Frame<'_>) {
egui::CentralPanel::default()
.frame(egui::containers::Frame::none())
.show(ctx, |ui| {

@ -0,0 +1,116 @@
//! The startup form to configure what and how to import
use eframe::egui::epaint::Shadow;
use eframe::egui::{self, vec2, Color32, Pos2, Rect, Response, Stroke, TextStyle, Vec2, Widget};
use rand::seq::SliceRandom;
use super::super::platform::platform_colors;
use super::super::widgets::background::{shadow_background, AnimatedBackground};
use crate::types::Config;
use crate::types::FormatType;
pub struct Import {
config: Config,
/// The animation divisions
animation_divisions: usize,
/// time counter
timer: f64,
/// recursive offset counter
offset_counter: usize,
/// We use this to have the initial background resize
/// animation
intro_timer: f64,
/// This defines the amount of progress blocks we intend
/// to animate
progress_blocks: Vec<usize>,
/// The progress divisions
progress_divisions: usize,
}
impl Import {
pub fn new(config: Config) -> Self {
// Build a random distribution of elements
// to animate the import process
let mut rng = rand::thread_rng();
let animation_divisions = 6;
let progress_divisions = 4;
// the amount of progress blocks
let progress_block_count =
(animation_divisions * progress_divisions) * (animation_divisions * progress_divisions);
let mut progress_blocks: Vec<usize> = (0..progress_block_count).collect();
dbg!(progress_block_count);
progress_blocks.shuffle(&mut rng);
Self {
animation_divisions,
config,
timer: 0.0,
offset_counter: 0,
intro_timer: 0.0,
progress_blocks,
progress_divisions,
}
}
}
impl Widget for &mut Import {
fn ui(self, ui: &mut egui::Ui) -> Response {
self.intro_timer += ui.input().unstable_dt as f64;
let growth = self.intro_timer.clamp(0.0, 1.0);
let available = ui.available_size();
// We take the progress as a value fromt the blocks
// FIXME: temporary using intro timer
let p = ((self.intro_timer * 5.0) / 100.0);
let n = (self.progress_blocks.len() as f64 * p) as usize;
//println!("{} / {}", n, self.progress_blocks.len());
let slice = &self.progress_blocks[0..=n];
AnimatedBackground {
divisions: self.animation_divisions,
animate_progress: Some((slice, self.progress_divisions)),
timer: &mut self.timer,
offset_counter: &mut self.offset_counter,
}
.draw_background(ui, available);
let desired_height = 370.0 - (270.0 * growth) as f32;
let desired_size = egui::vec2(330.0, desired_height);
let paint_rect = Rect::from_min_size(
Pos2 {
x: available.x / 2.0 - desired_size.x / 2.0,
y: available.y / 2.0 - desired_size.y / 2.0,
},
desired_size,
);
// calculate in margin
let center = paint_rect.shrink(15.0);
let colors = platform_colors();
// Draw a backround with a shadow
shadow_background(
ui.painter(),
paint_rect,
colors.window_background_dark,
Stroke::new(1.0, Color32::from_gray(90)),
12.0,
Shadow::big_dark(),
);
ui.allocate_ui_at_rect(center, |ui| {
ui.centered_and_justified(|ui| {
ui.vertical_centered_justified(|ui| {
ui.heading("Import in Progress");
let bar = egui::widgets::ProgressBar::new(0.5).animate(true);
ui.add(bar);
ui.small("133 / 1000");
});
})
})
.response
}
}

@ -2,6 +2,7 @@ mod import;
mod startup;
mod visualize;
pub use import::Import;
pub use startup::Startup;
pub use visualize::{UIState, Visualize};

@ -1,7 +1,6 @@
//! The startup form to configure what and how to import
use eframe::egui::epaint::Shadow;
use eframe::egui::{
self, vec2, Color32, Painter, Pos2, Rect, Response, Shape, Stroke, TextStyle, Vec2, Widget,
};
use eframe::egui::{self, vec2, Color32, Pos2, Rect, Response, Stroke, TextStyle, Vec2, Widget};
use rfd;
use std::path::PathBuf;
@ -34,6 +33,8 @@ impl Widget for &mut Startup {
let available = ui.available_size();
AnimatedBackground {
divisions: 6,
animate_progress: None,
timer: &mut self.timer,
offset_counter: &mut self.offset_counter,
}

@ -62,6 +62,10 @@ pub fn shadow_background(
/// A animated backwround with some parameters.
/// Used in some `app_states`.
pub struct AnimatedBackground<'a> {
/// The divisions
pub divisions: usize,
/// For each division cell, we take 8 sub divisions
pub animate_progress: Option<(&'a [usize], usize)>,
/// time counter
pub timer: &'a mut f64,
/// recursive offset counter
@ -72,30 +76,37 @@ impl<'a> AnimatedBackground<'a> {
pub fn draw_background(&mut self, ui: &mut egui::Ui, size: Vec2) {
let painter = ui.painter();
let division = 6.0;
let divisions = self.divisions as f32;
// paint stuff
let rect_size = vec2(size.x / division, size.y / division);
let rect_size = vec2(size.x / divisions, size.y / divisions);
let offset = *self.timer * 42.5;
// we only animate if there's no progress
let (offset, add) = if self.animate_progress.is_none() {
// Define the animation speed
let offset = *self.timer * 42.5;
if offset > rect_size.x as f64 {
*self.timer = 0.0;
*self.offset_counter += 1;
}
if offset > rect_size.x as f64 {
*self.timer = 0.0;
*self.offset_counter += 1;
}
// Reset the offset counter as we're going out of the size
if (*self.offset_counter as f32 * rect_size.x) > (size.x * 1.1) {
*self.offset_counter = 0;
}
// Reset the offset counter as we're going out of the size
if (*self.offset_counter as f32 * rect_size.x) > (size.x * 1.1) {
*self.offset_counter = 0;
}
// figure out the offset addition
let add = *self.offset_counter as i8;
// figure out the offset addition
let add = *self.offset_counter as i8;
(offset, add)
} else {
(0.0, 0)
};
Self::draw_rectangles(
painter,
offset,
division,
divisions,
rect_size,
&[
(4 + add, 4, 3),
@ -110,9 +121,33 @@ impl<'a> AnimatedBackground<'a> {
(1 + add, 5, 4),
(3 + add, 6, 5),
],
division as usize,
self.divisions,
);
// Next, draw the rectangles
if let Some((blocks, d)) = self.animate_progress {
// the resolution of the block animation
let divisor = self.divisions * d;
let w = rect_size.x / d as f32;
let h = rect_size.y / d as f32;
let mut color_adder = self.divisions;
for n in blocks {
// calculate x/y from the value
let y = n / divisor;
let x = n % divisor;
let y = y as f32;
let x = x as f32;
let pos = Pos2::new(x * w, y * h);
let size = vec2(w, h);
let rect = Rect::from_min_size(pos, size);
// the fill color is based on the added block count
color_adder += *n;
let color = (color_adder % 50) as u8;
painter.rect_filled(rect, 0.0, Color32::from_gray(color));
painter.rect_stroke(rect, 0.0, Stroke::new(1.0, Color32::from_gray(110)));
}
}
let diff = ui.input().unstable_dt as f64;
*self.timer += diff;

Loading…
Cancel
Save