diff --git a/advotracker/src/callbacks/policycheck_state.rs b/advotracker/src/callbacks/policycheck_state.rs index 0b94e72..c38d747 100644 --- a/advotracker/src/callbacks/policycheck_state.rs +++ b/advotracker/src/callbacks/policycheck_state.rs @@ -1,8 +1,10 @@ -use locales::t; +use chrono::{Local, DateTime}; use dotenv::dotenv; +use locales::t; use orbtk::prelude::*; +use orbtk::shell::WindowRequest; use serde::Deserialize; -use std::{env, process}; +use std::{env, process, thread, time}; use std::collections::HashMap; use tracing::{debug, error, info, trace}; @@ -22,7 +24,12 @@ pub enum Action { InputTextChanged(Entity), OpenMenu(Entity), ParseEntry(Entity), + AddProgress(f64), + ResetProgress, + SetProgress(f64), + SetPopupBox(Entity), RemoveFocus(Entity), + RemovePopupBox(Entity), SetEntry(Entity), SetVisibility(Entity), TextChanged(Entity, usize), @@ -45,7 +52,8 @@ pub struct PolicyCheckState { //policy_check: PolicyCheck, policy_data_count: usize, //policy_number_text_box: Entity, - policy_numbers: HashMap + policy_numbers: HashMap, + popup_box: Option } impl GlobalState for PolicyCheckState {} @@ -83,7 +91,8 @@ impl PolicyCheckState { //let mut csv_import_path = v.get::("import_file").unwrap(); let mut csv_import_path = String::from("POLLFNR_WOECHENTLICH.txt"); match import(&mut csv_import_path, &mut policy_data, - &mut policy_numbers, &lang) { + &mut policy_numbers, &mut self.policy_data_count, + &lang) { Ok(count) => { self.policy_data_count = count; trace!(target: "advotracker", csv_import_path = ?csv_import_path, @@ -102,19 +111,32 @@ impl PolicyCheckState { /// Clear text in text box. pub fn clear_entry(&mut self, text_box: Entity, ctx: &mut Context<'_>) { let mut text_box = TextBox::get(ctx.get_widget(text_box)); - let text = text_box.text_mut(); + let _text = text_box.text_mut(); } /// Import policy numbers into hashmap - fn import_data(&mut self) -> Result<(), Box> { - //fn import_data(&mut self, entity: Entity, ctx: &mut Context<'_>) - // -> Result<(), Box> { - // WIP: for now, only import once per session + fn import_data(&mut self, ctx: &mut Context<'_>) + -> Result<(), Box> { + // WIP: for now, only import once per session + let two_seconds = time::Duration::from_secs(2); + let sender = ctx.window_sender(); + if self.policy_data_count == 0 { //let mut text_block_wrapper: TextBlockCtx<'_> = text_block(ctx.child("policy_check_result")); //text_block_wrapper.set_enabled(true); //text_block_wrapper.set_text("Importieren der Prüflisten-Elemnte ..."); + self.set_popup_box(ctx); + progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).set_val(0.25); + // for i in 1..4 { + // let old_width = *progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).val(); + // let new_width = old_width + 0.33; + // progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).set_val(new_width); + // thread::sleep(two_seconds); + // } + + sender.send(WindowRequest::Redraw).unwrap(); + match self.create_hashmap() { Ok(()) => { //let res = t!("policy.hashmap.success", lang); @@ -132,6 +154,10 @@ impl PolicyCheckState { trace!(target: "advotracker", hashmap_status = "failed"); } } + + // remove popup widget now, that we are done + self.remove_popup_box(ctx); + } else { trace!(target: "advotracker", hashmap_status = "consume", @@ -143,8 +169,7 @@ impl PolicyCheckState { /// Open menu. pub fn open_menu(&mut self, text_block: Entity, ctx: &mut Context<'_>) { - let mut text_block = TextBlock::get(ctx.get_widget(text_block)); - let text = text_block.text_mut(); + let menu_string = ctx.get_widget(text_block).get::("text"); } /// Parse validity of the given policy number. @@ -164,8 +189,23 @@ impl PolicyCheckState { Err(e) => { debug!(target: "advotracker", "{}", e); } } - // trace!(target: "advotracker", state = "importing"); - // match self.import_data() { + // let sender = ctx.window_sender(); + // self.set_popup_box(ctx); + // let one_seconds = time::Duration::from_secs(1); + // for i in 1..4 { + // let old_width = *progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).val(); + // let new_width = old_width + 0.33; + // println!("progress changed: {}", new_width); + // sender.send(WindowRequest::Redraw).unwrap(); + + // progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).set_val(new_width); + // thread::sleep(one_seconds); + // } + //self.remove_popup_box(ctx); + + // Load data into hashmap + trace!(target: "advotracker", state = "importing"); + // match self.import_data(ctx) { // Ok(()) => { // trace!(target: "advotracker", import_data = "success"); // } @@ -173,7 +213,7 @@ impl PolicyCheckState { // error!("Importing data failed!"); // trace!(target: "advotracker", import_data = "failed"); // } - //} + // } trace!(target: "advotracker", state = "parsing", policy_number = ?policy_string); @@ -248,6 +288,14 @@ impl PolicyCheckState { } } + /// Remove a popup box showing the data import status in a progress bar + fn remove_popup_box(&mut self, ctx: &mut Context<'_>) { + if let Some(popup_box) = self.popup_box { + ctx.remove_child(popup_box); + println!("PopupBox removed !"); + } + } + /// If TextBox 'policy_check_policy_number' is empty, disable button "clear" /// otherwise enabled it. // fn set_policy_check_clear_button(&self, policy_check_policy_number: Entity, ctx: &mut Context<' >) { @@ -261,7 +309,7 @@ impl PolicyCheckState { // } /// Change status of given text box to edit mode. - fn set_entry(&self, policy_check_policy_number: Entity, ctx: &mut Context<'_>) { + fn set_entry(&mut self, policy_check_policy_number: Entity, ctx: &mut Context<'_>) { if *ctx.get_widget(policy_check_policy_number).get::("focused") { //let mut my_ctx: WidgetContainer<'_> = ctx.widget(); //let mut child: WidgetContainer<'_> = ctx.get_widget(policy_check_policy_number); @@ -294,8 +342,24 @@ impl PolicyCheckState { ctx.get_widget(self.label_result_text_block).update_theme_by_state(true); } - // Update count of elements in the policy data list. - fn _update_data_count(&self, ctx: &mut Context<'_>) { + /// Set a popup box that updates the import status in a progress bar + fn set_popup_box(&mut self, ctx: &mut Context<'_>) { + //println!("Set up Popup box: {:?}", text_box); + let stack = ctx + .entity_of_child(ID_POLICY_CHECK_RESULT) + .expect("PolicyCheckState.init: Can't find entity of resource 'ID_POLICY_CHECK_RESULT'."); + let current_entity = ctx.entity; + let build_context = &mut ctx.build_context(); + + let popup_box = new_popup_box(current_entity, "Importing data ...", build_context); + // create a popup_box widget as a child of entity "ID_POLICY_CHECK_POLICY_NUMBER" + build_context.append_child(stack, popup_box); + self.popup_box = Some(popup_box); + println!("PopupBox created: {:?}", Some(popup_box)); + } + + /// Update count of elements in the policy data list. + fn update_data_count(&self, ctx: &mut Context<'_>) { let data_list_count = ctx.widget().get::(PROP_POLICY_DATA_LIST).len(); ctx.widget().set(PROP_POLICY_DATA_COUNT, data_list_count); } @@ -305,9 +369,13 @@ impl PolicyCheckState { impl State for PolicyCheckState { /// Initialize the widget state fn init(&mut self, _: &mut Registry, ctx: &mut Context<'_>) { + let dt_start: DateTime = Local::now(); + + trace!(target: "advotracker", init = "started"); + self.menu_button = ctx .entity_of_child(ID_POLICY_CHECK_BUTTON_MENU) - .expect("PolicyCheckState.init: Can't find entity id defined as resource 'ID_POLICY_CHECK_POLICY_MENU_BUTTON'."); + .expect("PolicyCheckState.init: Can't find entity of resource 'ID_POLICY_CHECK_POLICY_MENU_BUTTON'."); // // Load the saved data from a file in 'ron' format into our data structure. // // The cargo package identifier (default: 'nwx.advotracker') is used as the @@ -324,6 +392,15 @@ impl State for PolicyCheckState { // number of elements in the restored policy data //policy_data_count = policy_data.len().clone; //self.update_data_count(ctx); + + // Load data into hashmap + //self.import_data(ctx); + + let dt_end: DateTime = Local::now(); + let duration = dt_end.signed_duration_since(dt_start); + + trace!(target: "advotracker", init = ?duration); + } /// Update the widget state. @@ -340,20 +417,34 @@ impl State for PolicyCheckState { if let Some(action) = self.action { match action { + Action::AddProgress(increment) => { + let old_width = *progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).val(); + let new_width = old_width + increment; + // Set the ProgressBar's val property to the calculated percentage + // (whereas 0.0 means 0 %, and 1.0 means 100 %) to increment the progress + if new_width <= 1.0 { + progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).set_val(new_width); + } else { + progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).set_val(1.); + } + } Action::ClearEntry(policy_check_policy_number) => { ctx.get_widget(policy_check_policy_number).set("enabled", false); } Action::InputTextChanged(entity) => { - //println!("entry changed: {}", text_box(ctx.get_widget(entity)).text()); + println!("entry changed: {}", text_box(ctx.get_widget(entity)).text()); + //self.set_popup_box(ctx); //self.set_check_button(policy_check_label_policy_number, ctx); - self.set_visibility(entity, ctx); + //self.set_visibility(entity, ctx); } Action::OpenMenu(text_block) => { self.open_menu(text_block, ctx); } Action::ParseEntry(text_box) => { + println!("set_popup_box: {:#?}", text_box); + self.set_popup_box(ctx); self.parse_entry(text_box, ctx); - ctx.get_widget(text_box).get::("text").as_string(); + //ctx.get_widget(text_box).get::("text").as_string(); //self.parse_entry(text_box, &mut policy_numbers, // &lang, ctx); } @@ -361,11 +452,30 @@ impl State for PolicyCheckState { ctx.get_widget(policy_check_policy_number).set("enabled", false); ctx.push_event_by_window(FocusEvent::RemoveFocus(policy_check_policy_number)); } + Action::RemovePopupBox(text_box) => { + self.remove_popup_box(ctx); + } + Action::ResetProgress => { + progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).set_val(0.); + } + Action::SetProgress(value) => { + if value >= 0. || value <= 1. { + progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).set_val(value); + } else { + progress_bar(ctx.child(ID_POLICY_CHECK_PROGRESS_BAR)).set_val(0.); + } + } + Action::SetPopupBox(entity) => { + //println!("set_popup_box: {:#?}", ctx.widget().get::("water_mark")); + //println!("set_popup_box: {:#?}", entity); + self.set_popup_box(ctx); + //let text = text_box(ctx.child(ID_POLICY_CHECK_POLICY_NUMBER)); + } Action::SetEntry(policy_check_policy_number) => { //self.last_focused = Some(); self.set_entry(policy_check_policy_number, ctx); } - Action::SetVisibility(entity) => { + Action::SetVisibility(_entity) => { //text_block(ctx.child(entity).set_visibility(Visibility::Visible)); //println!("Entity: {:?}", entity); //text_block(ctx.child(entity).set_visibility(Visibility::Collapsed)); @@ -390,7 +500,47 @@ impl State for PolicyCheckState { string_data_count = format!("{} {:?}", string_data_count, self.policy_numbers.len()); text_block(ctx.child(ID_POLICY_DATA_COUNT_BLOCK)).set_text(string_data_count); - - let _ = self.import_data(); } } + +fn new_popup_box(target: Entity, text: &str, ctx: &mut BuildContext<'_>) -> Entity { + Popup::new() + .id(ID_POLICY_CHECK_PROGRESS_POPUP) + .target(target) + .open(true) + .width(280.0) + .height(100.0) + .child( + Container::new() + .background("transparent") + .border_radius(3.) + .border_width(2.) + //.border_brush("#000000") + .padding(16.) + .child( Stack::new() + .h_align("center") + .margin((16., 16., 16., 16.)) + .spacing(16.) + // default: .orientation("vertical") + .child( + TextBlock::new() + .id(ID_POLICY_CHECK_PROGRESS_TEXT) + .h_align("center") + .v_align("top") + //.foreground("#000000") + .text(text) + .build(ctx) + ) + .child( + ProgressBar::new() + .id(ID_POLICY_CHECK_PROGRESS_BAR) + .val(0.) + .width(250.) + .build(ctx) + ) + .build(ctx) + ) + .build(ctx) + ) + .build(ctx) +}