From 7e724934a515d05d46621de6e744dac6a3070761 Mon Sep 17 00:00:00 2001 From: Benedikt Terhechte Date: Fri, 3 Mar 2023 12:05:51 +0100 Subject: [PATCH] add support for popovers --- examples/popover.rs | 195 +++++++++++++++++++++++++++++++++++++++ src/appkit/app/mod.rs | 13 ++- src/appkit/window/mod.rs | 15 ++- src/geometry.rs | 8 ++ src/view/mod.rs | 2 + src/view/popover/mod.rs | 95 +++++++++++++++++++ 6 files changed, 325 insertions(+), 3 deletions(-) create mode 100644 examples/popover.rs create mode 100644 src/view/popover/mod.rs diff --git a/examples/popover.rs b/examples/popover.rs new file mode 100644 index 0000000..8fd92f8 --- /dev/null +++ b/examples/popover.rs @@ -0,0 +1,195 @@ +//! This example showcases how to use a `Popover`. +//! This requires multiple types: +//! - A Window with a Controller / View +//! - A Popover +//! - Another Controller / View + +use cacao::appkit::menu::{Menu, MenuItem}; +use cacao::appkit::window::{Window, WindowConfig, WindowController, WindowDelegate}; +use cacao::appkit::{App, AppDelegate}; +use cacao::button::Button; +use cacao::geometry::{Edge, Rect}; +use cacao::layout::{Layout, LayoutConstraint}; +use cacao::notification_center::Dispatcher; +use cacao::text::{Font, Label}; +use cacao::view::{Popover, PopoverConfig, View, ViewController, ViewDelegate}; + +struct BasicApp { + window: WindowController, +} + +impl AppDelegate for BasicApp { + fn did_finish_launching(&self) { + App::set_menu(vec![ + Menu::new( + "", + vec![ + MenuItem::Services, + MenuItem::Separator, + MenuItem::Hide, + MenuItem::HideOthers, + MenuItem::ShowAll, + MenuItem::Separator, + MenuItem::Quit, + ], + ), + Menu::new("File", vec![MenuItem::CloseWindow]), + Menu::new("View", vec![MenuItem::EnterFullScreen]), + Menu::new( + "Window", + vec![ + MenuItem::Minimize, + MenuItem::Zoom, + MenuItem::Separator, + MenuItem::new("Bring All to Front"), + ], + ), + ]); + + App::activate(); + + self.window.show(); + } + + fn should_terminate_after_last_window_closed(&self) -> bool { + true + } +} + +#[derive(Default)] +struct MyWindow { + controller: Option>, +} + +impl WindowDelegate for MyWindow { + const NAME: &'static str = "MyWindow"; + + fn did_load(&mut self, window: Window) { + window.set_minimum_content_size(400., 400.); + window.set_title("A Basic Window!?"); + let view = PopoverExampleContentView::new(); + let controller = ViewController::new(view); + window.set_content_view_controller(&controller); + self.controller = Some(controller); + } + + fn will_close(&self) { + println!("Closing now!"); + } +} + +impl MyWindow { + pub fn on_message(&self, message: Msg) { + if let Some(delegate) = self.controller.as_ref().map(|e| &e.view).and_then(|v| v.delegate.as_ref()) { + delegate.on_message(message); + } + } +} + +fn main() { + App::new( + "com.test.window-delegate", + BasicApp { + window: WindowController::with(WindowConfig::default(), MyWindow::default()), + }, + ) + .run(); +} + +#[derive(Clone, Debug)] +pub enum Msg { + Click, +} + +#[derive(Debug, Default)] +struct PopoverExampleContentView { + view: Option, + button: Option