use std::iter;
use crate::theme::ComponentColor;
use wgpu::{Device, Queue, RenderPipeline, Surface, SurfaceConfiguration, TextureFormat};
use winit::dpi::PhysicalSize;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::platform::windows::WindowExtWindows;
use winit::window::{CursorIcon, Icon, WindowBuilder};
use winit::window::Window;
use crate::{RSGTError, Size};
use crate::wgpu::WGSL;
use crate::widget::Widget;
pub type ID = i32;
pub enum CloseOperation {
ExitAndClose,
HideAndClose,
}
struct State {
pub color:wgpu::Color,
pub surface: Surface,
pub device: Device,
pub queue: Queue,
pub pipeline: RenderPipeline,
pub config: SurfaceConfiguration,
pub size: PhysicalSize<u32>
}
impl State{
pub fn resize(&mut self, new_size: PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let frame = self.surface.get_current_texture().unwrap();
let view = frame
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
{
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});
{
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(self.color),
store: true,
},
})],
depth_stencil_attachment: None,
});
rpass.set_pipeline(&self.pipeline);
}
self.queue.submit(iter::once(encoder.finish()));
}
let command_buffer = encoder.finish();
self.queue.submit(Some(command_buffer));
frame.present();
Ok(())
}
}
pub struct RFrame {
id: ID,
handle: Window,
event_loop: Option<EventLoop<()>>,
close_operation: CloseOperation,
window_listener: 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."));
}
println!("Err");
let event_loop = EventLoop::new();
let window_size: PhysicalSize<u32> = window_size.into();
let window = WindowBuilder::new()
.with_fullscreen(None)
.with_inner_size(window_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.width,
height: window_size.height,
present_mode: wgpu::PresentMode::Immediate,
alpha_mode: wgpu::CompositeAlphaMode::Auto,
};
surface.configure(&device, &config);
let state = State {
color: crate::wgpu::parse_color(ComponentColor::WhiteGray),
surface,
device,
queue,
pipeline,
config,
size: window_size,
};
Ok(Self {
id,
handle: window,
event_loop: Some(event_loop),
close_operation: CloseOperation::ExitAndClose,
window_listener: Box::new(crate::event::DefaultWindowListener {}),
state
})
}
pub fn add_window_listener(&mut self, listener: (impl crate::event::WindowListener + 'static)) {
self.window_listener = 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, width: u32, height: u32) {
let window_size: PhysicalSize<u32> = (width, height).into();
if width > 0 && height > 0 {
self.state.size = window_size;
self.state.config.width = window_size.width;
self.state.config.height = window_size.height;
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, x: i32, y: i32) {
self.handle
.set_outer_position(winit::dpi::LogicalPosition::new(x, y));
}
pub fn set_maximum_window_size(&self,width:u32,height:u32) {
self.handle.set_max_inner_size(Some(PhysicalSize::new(width,height)));
}
pub fn set_minimum_window_size(&self,width:u32,height:u32) {
self.handle.set_min_inner_size(Some(PhysicalSize::new(width,height)));
}
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: winit::window::Icon) {
self.handle.set_window_icon(Some(icon));
}
pub fn set_taskbar_icon(&self,icon: winit::window::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 set_background_color(&mut self,color: ComponentColor) {
self.state.color = crate::wgpu::parse_color(color);
}
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.width,self.state.size.height)
}
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();
self.handle.set_visible(true);
self.window_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 {
self.window_listener
.window_focused(&self);
}
}
Event::WindowEvent {
event: WindowEvent::Moved(pos),
..
} => {
self.window_listener
.window_moved(pos,&self);
}
Event::WindowEvent {
event: WindowEvent::HoveredFile(pathbuf),
..
} => {
self.window_listener.window_hovered_file(pathbuf,&self);
}
Event::WindowEvent {
event: WindowEvent::HoveredFileCancelled,
..
} => {
self.window_listener.window_hovered_file_canceled(&self);
}
Event::WindowEvent {
event: WindowEvent::DroppedFile(pathbuf),
..
} => {
self.window_listener
.window_dropped_file(pathbuf, &self);
}
Event::WindowEvent {
event: WindowEvent::ReceivedCharacter(character),
..
} => {
self.window_listener
.window_received_character(character, &self);
}
Event::WindowEvent {
event: WindowEvent::Resized(window_size),
..
} => {
self.state.resize(window_size);
self.window_listener
.window_resized(&self);
}
Event::WindowEvent {
event: WindowEvent::ScaleFactorChanged {
new_inner_size,
..
},
..
} => {
self.set_size(new_inner_size.width,new_inner_size.height);
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
self.window_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) {
}
}