use std::sync::Arc; use crate::{ layout::{make_id, Data, Direction}, widgets::Label, *, }; #[derive(Clone, Copy, Debug)] pub struct WindowState { /// Last known pos/size pub rect: Rect, } pub struct Window { /// The title of the window and by default the source of its identity. title: String, } impl Window { pub fn new>(title: S) -> Self { Self { title: title.into(), } } pub fn show(self, data: Arc, add_contents: F) where F: FnOnce(&mut Region), { let id = make_id(&self.title); let mut state = data.memory.lock().unwrap().get_or_create_window( id, Rect::from_min_size( vec2(400.0, 200.0), // TODO vec2(200.0, 200.0), // TODO ), ); let layer = Layer::Window(id); let where_to_put_background = data.graphics.lock().unwrap().layer(layer).len(); let style = data.style(); let window_padding = style.window_padding; let mut contents_region = Region { data: data.clone(), layer: Layer::Popup, style, id: Default::default(), dir: Direction::Vertical, align: Align::Min, cursor: state.rect.min() + window_padding, bounding_size: vec2(0.0, 0.0), available_space: vec2(data.input.screen_size.x.min(350.0), std::f32::INFINITY), // TODO: window.width }; // Show top bar: contents_region.add(Label::new(self.title).text_style(TextStyle::Heading)); add_contents(&mut contents_region); // Now insert window background: // TODO: handle the last item_spacing in a nicer way let inner_size = contents_region.bounding_size - style.item_spacing; let outer_size = inner_size + 2.0 * window_padding; state.rect = Rect::from_min_size(state.rect.min(), outer_size); let mut graphics = data.graphics.lock().unwrap(); let graphics = graphics.layer(layer); graphics.insert( where_to_put_background, PaintCmd::Rect { corner_radius: 5.0, fill_color: Some(style.background_fill_color()), outline: Some(Outline { color: color::WHITE, width: 1.0, }), rect: state.rect, }, ); let interact = data.interact(layer, state.rect, Some(id)); if interact.active { state.rect = state.rect.translate(data.input().mouse_move); } let mut memory = data.memory.lock().unwrap(); if interact.active || interact.clicked { memory.move_window_to_top(id); } memory.set_window_state(id, state); } }