// Copyright 2018 The Druid Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use std::any::Any; use druid_shell::kurbo::{Line, Size}; use druid_shell::piet::{Color, RenderContext}; use druid_shell::{ Application, Cursor, FileDialogOptions, FileDialogToken, FileInfo, FileSpec, HotKey, KeyEvent, Menu, MouseEvent, Region, SysMods, TimerToken, WinHandler, WindowBuilder, WindowHandle, }; const BG_COLOR: Color = Color::rgb8(0x27, 0x28, 0x22); const FG_COLOR: Color = Color::rgb8(0xf0, 0xf0, 0xea); #[derive(Default)] struct HelloState { size: Size, handle: WindowHandle, } impl WinHandler for HelloState { fn connect(&mut self, handle: &WindowHandle) { self.handle = handle.clone(); } fn prepare_paint(&mut self) {} fn paint(&mut self, piet: &mut piet_common::Piet, _: &Region) { let rect = self.size.to_rect(); piet.fill(rect, &BG_COLOR); piet.stroke(Line::new((10.0, 50.0), (90.0, 90.0)), &FG_COLOR, 1.0); } fn command(&mut self, id: u32) { match id { 0x100 => { self.handle.close(); Application::global().quit() } 0x101 => { let options = FileDialogOptions::new().show_hidden().allowed_types(vec![ FileSpec::new("Rust Files", &["rs", "toml"]), FileSpec::TEXT, FileSpec::JPG, ]); self.handle.open_file(options); } 0x102 => { let options = FileDialogOptions::new().show_hidden().allowed_types(vec![ FileSpec::new("Rust Files", &["rs", "toml"]), FileSpec::TEXT, FileSpec::JPG, ]); self.handle.save_as(options); } _ => println!("unexpected id {id}"), } } fn open_file(&mut self, _token: FileDialogToken, file_info: Option) { println!("open file result: {file_info:?}"); } fn save_as(&mut self, _token: FileDialogToken, file: Option) { println!("save file result: {file:?}"); } fn key_down(&mut self, event: KeyEvent) -> bool { println!("keydown: {event:?}"); false } fn key_up(&mut self, event: KeyEvent) { println!("keyup: {event:?}"); } fn wheel(&mut self, event: &MouseEvent) { println!("mouse_wheel {event:?}"); } fn mouse_move(&mut self, event: &MouseEvent) { self.handle.set_cursor(&Cursor::Arrow); println!("mouse_move {event:?}"); } fn mouse_down(&mut self, event: &MouseEvent) { println!("mouse_down {event:?}"); } fn mouse_up(&mut self, event: &MouseEvent) { println!("mouse_up {event:?}"); } fn timer(&mut self, id: TimerToken) { println!("timer fired: {id:?}"); } fn size(&mut self, size: Size) { self.size = size; } fn got_focus(&mut self) { println!("Got focus"); } fn lost_focus(&mut self) { println!("Lost focus"); } fn request_close(&mut self) { self.handle.close(); } fn destroy(&mut self) { Application::global().quit() } fn as_any(&mut self) -> &mut dyn Any { self } } fn main() { tracing_subscriber::fmt().init(); let mut file_menu = Menu::new(); file_menu.add_item( 0x100, "E&xit", Some(&HotKey::new(SysMods::Cmd, "q")), None, true, ); file_menu.add_item( 0x101, "O&pen", Some(&HotKey::new(SysMods::Cmd, "o")), None, true, ); file_menu.add_item( 0x102, "S&ave", Some(&HotKey::new(SysMods::Cmd, "s")), None, true, ); let mut menubar = Menu::new(); menubar.add_dropdown(Menu::new(), "Application", true); menubar.add_dropdown(file_menu, "&File", true); let app = Application::new().unwrap(); let mut builder = WindowBuilder::new(app.clone()); builder.set_handler(Box::::default()); builder.set_title("Hello example"); builder.set_menu(menubar); let window = builder.build().unwrap(); window.show(); app.run(None); }