use std::sync::Arc; use app::App; use cosmic_text::Family; use render::Renderer; use ui::prelude::*; use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window}; use crate::testing::input::Input; mod app; mod input; mod render; pub fn main() { App::run(); } pub struct Client { renderer: Renderer, input: Input, ui: Ui, info: WidgetId, focus: Option>, } impl Client { pub fn new(window: Arc) -> Self { let renderer = Renderer::new(window); let mut ui = Ui::new(); let rrect = rect(Color::WHITE).radius(20); let pad_test = ( rrect.color(Color::BLUE), ( rrect.color(Color::RED).size(100).center(), ( rrect.color(Color::ORANGE), rrect.color(Color::LIME).pad(10.0), ) .span(Dir::RIGHT, ratio(1)), rrect.color(Color::YELLOW), ) .span(Dir::RIGHT, [2, 2, 1]) .pad(10), ) .span(Dir::RIGHT, [1, 3]) .add_static(&mut ui); let span_test = ( rrect.color(Color::GREEN), rrect.color(Color::ORANGE), rrect.color(Color::CYAN), rrect.color(Color::BLUE), rrect.color(Color::MAGENTA), rrect.color(Color::RED), ) .span( Dir::LEFT, [ fixed(100), ratio(1), ratio(1), relative(0.5), fixed(100), fixed(100), ], ) .add_static(&mut ui); let span_add = Span::empty(Dir::RIGHT).add_static(&mut ui); let add_button = rect(Color::LIME) .radius(30) .on(Sense::click(), move |ctx: &mut Client, _| { let child = ctx .ui .add(image(include_bytes!("assets/sungals.png")).center()) .any(); ctx.ui[span_add].children.push((child, sized())); }) .size(150) .align(Align::BotRight); let del_button = rect(Color::RED) .radius(30) .on(Sense::click(), move |ctx: &mut Client, _| { ctx.ui[span_add].children.pop(); }) .size(150) .align(Align::BotLeft); let span_add_test = (span_add, add_button, del_button) .stack() .add_static(&mut ui); let main = pad_test.pad(10).add_static(&mut ui); let btext = |content| text(content).font_size(30); let text_test = ( btext("this is a").align(Align::Left), btext("teeeeeeeest").align(Align::Right), btext("okkk\nokkkkkk!").align(Align::Left), btext("hmm"), btext("a"), ( btext("'").family(Family::Monospace).align(Align::Top), btext("'").family(Family::Monospace), btext(":gamer mode").family(Family::Monospace), rect(Color::CYAN).size(10).center(), rect(Color::RED).size(100).center(), rect(Color::PURPLE).size(50).align(Align::Top), ) .span(Dir::RIGHT, sized()) .center(), text("pretty cool right?").font_size(50), ) .span(Dir::DOWN, sized()) .add_static(&mut ui); let texts = Span::empty(Dir::DOWN).add(&mut ui); let add_text = text_edit("add") .text_align(Align::Left) .font_size(30) .id_on(Sense::click(), |id, client: &mut Client, ctx| { client.ui.text(id).select(ctx.cursor, ctx.size); client.focus = Some(id.clone()); }) .add(&mut ui); let text_edit_scroll = ( (Rect::new(Color::SKY), texts.clone()).stack(), ( add_text.clone(), Rect::new(Color::GREEN) .on(Sense::click(), move |client: &mut Client, _| { let content = client.ui.text(&add_text).take(); let text = text_edit(content) .font_size(30) .id_on(Sense::click(), |id, client: &mut Client, ctx| { client.ui.text(id).select(ctx.cursor, ctx.size); client.focus = Some(id.clone()); }) .pad(10) .add(&mut client.ui); client.ui[&texts].children.push((text.any(), sized())); }) .size(40), ) .span(Dir::RIGHT, [ratio(1), sized()]) .pad(30), ) .span(Dir::DOWN, [ratio(1), sized()]) .add_static(&mut ui); let switch_button = |color, to, label| { let rect = rect(color) .id_on(Sense::click(), move |id, ctx: &mut Client, _| { ctx.ui[main].inner.set_static(to); ctx.ui[id].color = color.mul_rgb(0.7); }) .edit_on(Sense::HoverStart | Sense::unclick(), move |r, _| { r.color = color.add_rgb(0.2); }) .edit_on(Sense::HoverEnd, move |r, _| { r.color = color; }); (rect, text(label).font_size(30)).stack() }; let tabs = ( switch_button(Color::RED, pad_test.any(), "pad"), switch_button(Color::GREEN, span_test.any(), "span"), switch_button(Color::BLUE, span_add_test.any(), "image span"), switch_button(Color::MAGENTA, text_test.any(), "text layout"), switch_button( Color::YELLOW.mul_rgb(0.5), text_edit_scroll.any(), "text edit scroll", ), ) .span(Dir::RIGHT, ratio(1)); let info = text("").add(&mut ui); let info_sect = info.clone().pad(10).align(Align::BotLeft); ( (tabs, main).span(Dir::DOWN, [fixed(40), ratio(1)]), info_sect, ) .stack() .set_root(&mut ui); Self { renderer, input: Input::default(), ui, info, focus: None, } } pub fn event(&mut self, event: WindowEvent, event_loop: &ActiveEventLoop) { self.input.event(&event); let cursor_state = self.cursor_state().clone(); let window_size = self.window_size(); if let Some(focus) = &self.focus && cursor_state.buttons.left.is_start() { self.ui.text(focus).deselect(); self.focus = None; } run_sensors(self, &cursor_state, window_size); match event { WindowEvent::CloseRequested => event_loop.exit(), WindowEvent::RedrawRequested => { self.ui.update(); self.renderer.update(&mut self.ui); self.renderer.draw() } WindowEvent::Resized(size) => { self.ui.resize((size.width, size.height)); self.renderer.resize(&size) } WindowEvent::KeyboardInput { event, .. } => { if let Some(sel) = &self.focus && event.state.is_pressed() && self.ui.text(sel).apply_event(&event).unfocus() { self.focus = None; } } _ => (), } let new = format!( "widgets: {}\nactive:{}\nviews: {}", self.ui.num_widgets(), self.ui.active_widgets(), self.renderer.ui.view_count() ); if new != *self.ui[&self.info].content { *self.ui[&self.info].content = new; } if self.ui.needs_redraw() { self.renderer.window().request_redraw(); } self.input.end_frame(); } } impl UiCtx for Client { fn ui(&mut self) -> &mut Ui { &mut self.ui } }