modal: refactoring to allow modification of global state from opened modal

This commit is contained in:
ardocrat 2024-05-04 02:14:27 +03:00
parent 11ac0ea84b
commit df6fafd256
2 changed files with 39 additions and 37 deletions

View file

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::RwLock; use std::sync::{Arc, RwLock};
use egui::{Align2, Rect, RichText, Rounding, Stroke, Vec2}; use egui::{Align2, Rect, RichText, Rounding, Stroke, Vec2};
use egui::epaint::RectShape; use egui::epaint::RectShape;
@ -25,19 +25,18 @@ use crate::gui::views::types::{ModalPosition, ModalState};
lazy_static! { lazy_static! {
/// Showing [`Modal`] state to be accessible from different ui parts. /// Showing [`Modal`] state to be accessible from different ui parts.
static ref MODAL_STATE: RwLock<ModalState> = RwLock::new(ModalState::default()); static ref MODAL_STATE: Arc<RwLock<ModalState>> = Arc::new(RwLock::new(ModalState::default()));
} }
/// Stores data to draw modal [`egui::Window`] at ui. /// Stores data to draw modal [`egui::Window`] at ui.
#[derive(Clone)]
pub struct Modal { pub struct Modal {
/// Identifier for modal. /// Identifier for modal.
pub(crate) id: &'static str, pub(crate) id: &'static str,
/// Position on the screen. /// Position on the screen.
position: ModalPosition, position: ModalPosition,
/// Flag to show the content.
open: AtomicBool,
/// To check if it can be closed. /// To check if it can be closed.
closeable: AtomicBool, closeable: Arc<AtomicBool>,
/// Title text /// Title text
title: Option<String> title: Option<String>
} }
@ -48,13 +47,12 @@ impl Modal {
/// Maximum width of the content. /// Maximum width of the content.
const DEFAULT_WIDTH: f32 = Root::SIDE_PANEL_WIDTH - (2.0 * Self::DEFAULT_MARGIN); const DEFAULT_WIDTH: f32 = Root::SIDE_PANEL_WIDTH - (2.0 * Self::DEFAULT_MARGIN);
/// Create opened and closeable [`Modal`] with center position. /// Create closeable [`Modal`] with center position.
pub fn new(id: &'static str) -> Self { pub fn new(id: &'static str) -> Self {
Self { Self {
id, id,
position: ModalPosition::Center, position: ModalPosition::Center,
open: AtomicBool::new(true), closeable: Arc::new(AtomicBool::new(true)),
closeable: AtomicBool::new(true),
title: None title: None
} }
} }
@ -65,14 +63,10 @@ impl Modal {
self self
} }
/// Check if [`Modal`] is open.
pub fn is_open(&self) -> bool {
self.open.load(Ordering::Relaxed)
}
/// Mark [`Modal`] closed. /// Mark [`Modal`] closed.
pub fn close(&self) { pub fn close(&self) {
self.open.store(false, Ordering::Relaxed); let mut w_nav = MODAL_STATE.write().unwrap();
w_nav.modal = None;
} }
/// Setup possibility to close [`Modal`]. /// Setup possibility to close [`Modal`].
@ -119,37 +113,32 @@ impl Modal {
true true
} }
/// Return id of opened [`Modal`] or remove its instance from [`ModalState`] if it was closed. /// Return id of opened [`Modal`].
pub fn opened() -> Option<&'static str> { pub fn opened() -> Option<&'static str> {
// Check if Modal is showing. // Check if modal is showing.
{ {
if MODAL_STATE.read().unwrap().modal.is_none() { if MODAL_STATE.read().unwrap().modal.is_none() {
return None; return None;
} }
} }
// Check if Modal is open. // Get identifier of opened modal.
let (is_open, id) = { let r_state = MODAL_STATE.read().unwrap();
let r_state = MODAL_STATE.read().unwrap(); let modal = r_state.modal.as_ref().unwrap();
let modal = r_state.modal.as_ref().unwrap(); Some(modal.id)
(modal.is_open(), modal.id)
};
// If Modal is not open, remove it from navigator state.
if !is_open {
let mut w_state = MODAL_STATE.write().unwrap();
w_state.modal = None;
return None;
}
Some(id)
} }
/// Draw opened [`Modal`] content. /// Draw opened [`Modal`] content.
pub fn ui(ctx: &egui::Context, add_content: impl FnOnce(&mut egui::Ui, &Modal)) { pub fn ui(ctx: &egui::Context, add_content: impl FnOnce(&mut egui::Ui, &Modal)) {
if let Some(modal) = &MODAL_STATE.read().unwrap().modal { let has_modal = {
if modal.is_open() { MODAL_STATE.read().unwrap().modal.is_some()
modal.window_ui(ctx, add_content); };
} if has_modal {
let modal = {
let r_state = MODAL_STATE.read().unwrap();
r_state.modal.clone().unwrap()
};
modal.window_ui(ctx, add_content);
} }
} }

View file

@ -32,6 +32,7 @@ pub enum TitleContentType {
} }
/// Position of [`Modal`] on the screen. /// Position of [`Modal`] on the screen.
#[derive(Clone)]
pub enum ModalPosition { pub enum ModalPosition {
CenterTop, CenterTop,
Center Center
@ -40,7 +41,8 @@ pub enum ModalPosition {
/// Global [`Modal`] state. /// Global [`Modal`] state.
#[derive(Default)] #[derive(Default)]
pub struct ModalState { pub struct ModalState {
pub modal: Option<Modal> /// Opened [`Modal`].
pub modal: Option<Modal>,
} }
/// Contains identifiers to draw opened [`Modal`] content for current ui container. /// Contains identifiers to draw opened [`Modal`] content for current ui container.
@ -138,12 +140,23 @@ impl TextEditOptions {
} }
} }
/// QR code scanning state. /// QR code scan result.
#[derive(Clone)]
pub enum QrScanResult {
/// Slatepack message.
Slatepack(String),
/// Slatepack address.
Address(String),
/// Parsed text.
Text(String)
}
/// QR code scan state.
pub struct QrScanState { pub struct QrScanState {
// Flag to check if image is processing to find QR code. // Flag to check if image is processing to find QR code.
pub(crate) image_processing: bool, pub(crate) image_processing: bool,
// Found QR code content. // Found QR code content.
pub qr_scan_result: Option<String> pub qr_scan_result: Option<QrScanResult>
} }
impl Default for QrScanState { impl Default for QrScanState {