use std::iter;
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
use wgpu::SurfaceConfiguration;
use winit::dpi::{LogicalPosition, PhysicalSize};
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::platform::windows::WindowExtWindows;
use winit::window::Window;
use winit::window::{CursorIcon, Icon, WindowBuilder};
use crate::error::RSGTError;
use crate::widget::Widget;
use crate::{Size,Position};
use rsgt_wgpu::wgsl::WGSL;
use rsgt_wgpu::state::State;
use crate::event::{DefaultWindowListener, WindowListener};
pub type ID = i32;
pub enum CloseOperation {
ExitAndClose,
HideAndClose,
}
pub struct RFrame {
id: ID,
handle: Window,
event_loop: Option<EventLoop<()>>,
close_operation: CloseOperation,
window_listener: Option<Box<dyn crate::event::WindowListener>>,
state: State,
}
impl RFrame {
pub fn new(
title: impl Into<String>,
id: ID,
window_size: Size<u32>,
) -> Result<Self, RSGTError> {
if window_size.0 == 0 || window_size.1 == 0 {
return Err(RSGTError::illegal_argument(
"Either of the window sizes is set to 0. Window size is set to 0.",
));
}
let event_loop = EventLoop::new();
let size: PhysicalSize<u32> = window_size.into();
let window = WindowBuilder::new()
.with_fullscreen(None)
.with_inner_size(size)
.with_title(title)
.with_visible(false)
.build(&event_loop)
.unwrap();
let instance = wgpu::Instance::new(wgpu::Backends::all());
dbg!(instance.generate_report());
let surface = unsafe { instance.create_surface(&window) };
let adapter_options = wgpu::RequestAdapterOptions {
compatible_surface: Some(&surface),
..Default::default()
};
let adapter_future = instance.request_adapter(&adapter_options);
let adapter = pollster::block_on(adapter_future).unwrap();
println!("Selected adapter: {}", adapter.get_info().name);
let device_descriptor = wgpu::DeviceDescriptor::default();
let device_future = adapter.request_device(&device_descriptor, None);
let (device, queue) = pollster::block_on(device_future).unwrap();
let wgsl = WGSL::new();
let shader_code = wgsl.build();
let descriptor = wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(shader_code.into()),
};
let shader_module = device.create_shader_module(descriptor);
let surface_format = surface.get_supported_formats(&adapter)[0];
let color_target = wgpu::ColorTargetState {
format: surface_format,
blend: None,
write_mask: Default::default(),
};
let color_targets = [Some(color_target)];
let descriptor = wgpu::RenderPipelineDescriptor {
label: None,
primitive: Default::default(),
vertex: wgpu::VertexState {
buffers: &[],
module: &shader_module,
entry_point: "vs_main",
},
fragment: Some(wgpu::FragmentState {
targets: &color_targets,
module: &shader_module,
entry_point: "fs_main",
}),
layout: None,
depth_stencil: None,
multisample: Default::default(),
multiview: None,
};
let pipeline = device.create_render_pipeline(&descriptor);
let config = SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface_format,
width: window_size.0,
height: window_size.1,
present_mode: wgpu::PresentMode::Immediate,
alpha_mode: wgpu::CompositeAlphaMode::Auto,
};
surface.configure(&device, &config);
let state = State {
color: rsgt_wgpu::color::parse_color(rsgt_wgpu::Vec4(0.85, 0.85, 0.85, 1.0)),
surface,
device,
queue,
pipeline,
config,
size: window_size.into_tuple(),
};
Ok(Self {
id,
handle: window,
event_loop: Some(event_loop),
close_operation: CloseOperation::ExitAndClose,
window_listener: None,
state,
})
}
pub fn add_window_listener(&mut self, listener: (impl crate::event::WindowListener + 'static)) {
self.window_listener = Some(Box::new(listener));
}
pub fn show(&self) {
self.handle.set_visible(true);
}
pub fn hide(&self) {
self.handle.set_visible(false);
}
pub fn set_maximized(&self) {
self.handle.set_maximized(true);
}
pub fn set_minimized(&self) {
if self.handle.is_maximized() == false {
self.handle.set_minimized(true);
} else {
self.handle.set_maximized(false);
}
}
pub fn set_undecorated(&self) {
self.handle.set_decorations(false);
}
pub fn set_decorated(&self) {
self.handle.set_decorations(true);
}
pub fn set_enable(&self) {
self.handle.set_enable(true);
}
pub fn set_disable(&self) {
self.handle.set_enable(false);
}
pub fn set_title(&self, title: &str) {
self.handle.set_title(title);
}
pub fn set_size(&mut self, window_size: Size<u32>) {
if window_size.0 > 0 && window_size.1 > 0 {
self.state.size = window_size.into_tuple();
self.state.config.width = window_size.0;
self.state.config.height = window_size.1;
self.state
.surface
.configure(&self.state.device, &self.state.config);
}
self.state
.surface
.configure(&self.state.device, &self.state.config);
}
pub fn set_location(&self, pos:Position<u32>) {
self.handle
.set_outer_position::<LogicalPosition<u32>>(pos.into());
}
pub fn set_maximum_window_size(&self, size:Size<u32>) {
let size: PhysicalSize<u32> = size.into();
self.handle
.set_max_inner_size(Some(size));
}
pub fn set_minimum_window_size(&self, size:Size<u32>) {
let size: PhysicalSize<u32> = size.into();
self.handle
.set_min_inner_size(Some(size));
}
pub fn set_resizable(&self) {
self.handle.set_resizable(true);
}
pub fn set_non_resizable(&self) {
self.handle.set_resizable(false);
}
pub fn set_icon(&self, icon: Icon) {
self.handle.set_window_icon(Some(icon));
}
pub fn set_taskbar_icon(&self, icon: Icon) {
self.handle.set_taskbar_icon(Some(icon));
}
pub fn set_default_close_operation(&mut self, operation: CloseOperation) {
self.close_operation = operation;
}
pub fn set_cursor_icon(&self, icon: crate::CursorIcon) {
self.handle.set_cursor_icon(match icon {
crate::CursorIcon::Arrow => CursorIcon::Arrow,
crate::CursorIcon::ScrollAll => CursorIcon::AllScroll,
crate::CursorIcon::CrossHair => CursorIcon::Crosshair,
crate::CursorIcon::Hand => CursorIcon::Hand,
crate::CursorIcon::Help => CursorIcon::Help,
crate::CursorIcon::NotAllowed => CursorIcon::NotAllowed,
crate::CursorIcon::Progress => CursorIcon::Progress,
});
}
pub fn get_raw_handle(&self) -> RawWindowHandle {
self.handle.raw_window_handle()
}
pub fn set_background_color(&mut self, color: crate::color::Color) {
self.state.color = rsgt_wgpu::color::parse_color(match color {
crate::color::Color::CustomColor(r, g, b, a) => rsgt_wgpu::Vec4(r, g, b, a),
})
}
pub fn enable_ime(&self) {
self.handle.set_ime_allowed(true);
}
pub fn disable_ime(&self) {
self.handle.set_ime_allowed(false);
}
pub fn get_window_size(&self) -> (u32, u32) {
(self.state.size.0, self.state.size.1)
}
pub fn is_resizable(&self) -> bool {
self.handle.is_resizable()
}
pub fn is_decorated(&self) -> bool {
self.handle.is_decorated()
}
pub fn is_maximized(&self) -> bool {
self.handle.is_maximized()
}
pub fn run(mut self) {
let event_loop = self.event_loop.take().unwrap();
let mut listener = match self.window_listener.take() {
None => {Box::new(DefaultWindowListener{}) as Box<dyn WindowListener>}
Some(listener) => {listener}
};
self.handle.set_visible(true);
listener.window_opened(&self);
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::RedrawRequested(window_id) if window_id == self.handle.id() => {
match self.state.render() {
Ok(_) => {}
Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => {
self.state.resize(self.state.size)
}
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::Timeout) => println!("Surface timeout"),
}
}
Event::WindowEvent {
event: WindowEvent::Focused(is_focused),
..
} => {
if is_focused == true {
listener.window_focused(&self);
}
}
Event::WindowEvent {
event: WindowEvent::Moved(pos),
..
} => {
listener.window_moved(pos, &self);
}
Event::WindowEvent {
event: WindowEvent::HoveredFile(pathbuf),
..
} => {
listener.window_hovered_file(pathbuf, &self);
}
Event::WindowEvent {
event: WindowEvent::HoveredFileCancelled,
..
} => {
listener.window_hovered_file_canceled(&self);
}
Event::WindowEvent {
event: WindowEvent::DroppedFile(pathbuf),
..
} => {
listener.window_dropped_file(pathbuf, &self);
}
Event::WindowEvent {
event: WindowEvent::ReceivedCharacter(character),
..
} => {
listener
.window_received_character(character, &self);
}
Event::WindowEvent {
event: WindowEvent::Resized(window_size),
..
} => {
self.state.resize(window_size.into());
listener.window_resized(&self);
}
Event::WindowEvent {
event: WindowEvent::ScaleFactorChanged { new_inner_size, .. },
..
} => {
self.set_size(Size(new_inner_size.width, new_inner_size.height));
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
listener.window_closed(&self);
match self.close_operation {
CloseOperation::ExitAndClose => {
*control_flow = ControlFlow::Exit;
}
CloseOperation::HideAndClose => {
*control_flow = ControlFlow::Wait;
self.hide();
}
}
}
_ => {}
}
});
}
}
pub struct RFrameBuilder {
title: String,
size: Size<u32>,
visible: bool,
icon: Option<Icon>,
close_operation: CloseOperation,
}
impl RFrameBuilder {
pub fn new() -> Self {
Default::default()
}
pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.title = title.into();
self
}
pub fn with_size(mut self, size: Size<u32>) -> Self {
self.size = size;
self
}
pub fn with_visible(mut self, visible: bool) -> Self {
self.visible = visible;
self
}
pub fn with_icon(mut self, icon: Icon) -> Self {
self.icon = Some(icon);
self
}
pub fn with_close_operation(mut self, operation: CloseOperation) -> Self {
self.close_operation = operation;
self
}
pub fn build(self) -> Result<RFrame, RSGTError> {
let mut rf = match RFrame::new(self.title, 0, self.size) {
Ok(rf) => rf,
Err(err) => return Err(err),
};
match self.icon {
None => {}
Some(icn) => {
rf.set_icon(icn);
}
};
rf.set_default_close_operation(self.close_operation);
Ok(rf)
}
}
impl Default for RFrameBuilder {
fn default() -> Self {
Self {
title: "RSGT window".parse().unwrap(),
size: Size(400, 400),
visible: false,
icon: None,
close_operation: CloseOperation::ExitAndClose,
}
}
}
pub struct RegistrationContentPanel {
components: Vec<Box<dyn Widget>>,
}
impl RegistrationContentPanel {
pub fn new() -> Self {
Self { components: vec![] }
}
pub fn add(&mut self, widget: (impl Widget + 'static)) {
self.components.push(Box::new(widget));
}
pub fn draw_all(&self) {}
pub fn draw_by_id(&self) {}
}