use crate::core::{Color, Font, ObjectId, Point, Rect};
use crate::event::{Event, EventHandler};
use crate::render::RenderContext;
use crate::signal::GenericSignal;
use crate::widget::{BaseWidget, Draw, Widget, WidgetKind};
pub struct Window {
base: BaseWidget,
title: String,
title_bar_height: u32,
close_button_size: u32,
button_spacing: u32,
pub closed: GenericSignal,
}
impl Window {
pub fn new(title: String, geometry: Rect) -> Self {
Self {
base: BaseWidget::new(WidgetKind::Window, geometry, "Window"),
title,
title_bar_height: 32,
close_button_size: 14,
button_spacing: 40,
closed: GenericSignal::new(),
}
}
pub fn add_child(&mut self, child: ObjectId) {
self.base.add_child(child);
}
pub fn title(&self) -> &str {
&self.title
}
pub fn set_title(&mut self, title: String) {
self.title = title;
}
pub fn title_bar_height(&self) -> u32 {
self.title_bar_height
}
pub fn set_title_bar_height(&mut self, height: u32) {
self.title_bar_height = height;
self.base.request_redraw();
}
pub fn close_button_size(&self) -> u32 {
self.close_button_size
}
pub fn set_close_button_size(&mut self, size: u32) {
self.close_button_size = size;
self.base.request_redraw();
}
pub fn button_spacing(&self) -> u32 {
self.button_spacing
}
pub fn set_button_spacing(&mut self, spacing: u32) {
self.button_spacing = spacing;
self.base.request_redraw();
}
pub fn close(&mut self) {
self.closed.emit();
}
}
impl Widget for Window {
fn base(&self) -> &BaseWidget {
&self.base
}
fn base_mut(&mut self) -> &mut BaseWidget {
&mut self.base
}
}
impl EventHandler for Window {
fn handle_event(&mut self, event: &Event) {
self.base.handle_event(event);
if matches!(event, Event::Quit) {
self.closed.emit();
}
}
}
impl Draw for Window {
fn draw(&mut self, context: &mut RenderContext) {
let rect = self.geometry();
let style = self.style();
let bg_color = style.background_color.unwrap_or(Color::rgb(240, 240, 240));
let border_color = style.border_color.unwrap_or(Color::GRAY);
let title_bar_color = Color::rgb(53, 53, 53);
let title_text_color = Color::WHITE;
let border_width = style.border_width;
context.fill_rect(rect, bg_color);
let title_bar_height = self.title_bar_height;
let title_bar_rect = Rect::new(rect.x, rect.y, rect.width, title_bar_height);
context.fill_rect(title_bar_rect, title_bar_color);
let title_font = Font::new("Arial", 12.0, false, false);
let title_x = rect.x + 10;
let title_y = rect.y + title_bar_height as i32 / 2;
context.draw_text(Point::new(title_x, title_y), &self.title, &title_font, title_text_color);
if border_width > 0 {
context.draw_rect_stroke(rect, border_color, border_width);
}
let close_button_size = self.close_button_size;
let close_button_rect = Rect::new(
rect.x + rect.width as f32 as i32 - close_button_size as i32 - 10,
rect.y + (title_bar_height as i32 - close_button_size as i32) / 2,
close_button_size,
close_button_size,
);
context.fill_rect(close_button_rect, Color::rgba(232, 17, 35, 255));
let padding = 3;
let x1 = Point::new(close_button_rect.x + padding, close_button_rect.y + padding);
let x2 = Point::new(
close_button_rect.x + close_button_rect.width as i32 - padding,
close_button_rect.y + close_button_rect.height as i32 - padding,
);
let x3 = Point::new(
close_button_rect.x + close_button_rect.width as i32 - padding,
close_button_rect.y + padding,
);
let x4 = Point::new(
close_button_rect.x + padding,
close_button_rect.y + close_button_rect.height as i32 - padding,
);
context.draw_line(x1, x2, Color::WHITE);
context.draw_line(x3, x4, Color::WHITE);
let minimize_button_rect = Rect::new(
rect.x + rect.width as i32
- close_button_size as i32
- (self.button_spacing * 2 + self.close_button_size * 2) as i32,
rect.y + (title_bar_height as i32 - close_button_size as i32) / 2,
close_button_size,
close_button_size,
);
context.fill_rect(minimize_button_rect, Color::rgba(255, 255, 255, 50));
let minimize_y = minimize_button_rect.y + minimize_button_rect.height as i32 / 2;
context.draw_line(
Point::new(minimize_button_rect.x + 2, minimize_y),
Point::new(minimize_button_rect.x + minimize_button_rect.width as i32 - 2, minimize_y),
Color::WHITE,
);
let maximize_button_rect = Rect::new(
rect.x + rect.width as f32 as i32
- close_button_size as i32
- (self.button_spacing + self.close_button_size) as i32,
rect.y + (title_bar_height as i32 - close_button_size as i32) / 2,
close_button_size,
close_button_size,
);
context.fill_rect(maximize_button_rect, Color::rgba(255, 255, 255, 50));
let max_padding = 3;
context.draw_rect_stroke(
Rect::new(
maximize_button_rect.x + max_padding as i32,
maximize_button_rect.y + max_padding as i32,
maximize_button_rect.width - max_padding * 2,
maximize_button_rect.height - max_padding * 2,
),
Color::WHITE,
1,
);
}
}