diff --git a/Cargo.toml b/Cargo.toml index 451d33e..7d2232a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,3 +99,6 @@ required-features = ["appkit"] [[example]] name = "window_controller" required-features = ["appkit"] +[[exmaple]] +name = "safe_area" +required-features = ["appkit"] \ No newline at end of file diff --git a/examples/readme.md b/examples/readme.md index 6311536..35f6a8b 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -40,6 +40,11 @@ This example showcases text input, and logs it to the underlying console. It's m `cargo run --example text_input` +## Safe Area +This example showcases A window containg the text "Hello, world!" while keeping everything in the safearea to keep it visible. + +`cargo run --example safe_area` + ## Calculator A Rust-rendition of the macOS Calculator app. diff --git a/examples/safe_area.rs b/examples/safe_area.rs new file mode 100644 index 0000000..08165a9 --- /dev/null +++ b/examples/safe_area.rs @@ -0,0 +1,63 @@ +//! This example showcases setting up a basic application and view with safe area constraints. + +use cacao::appkit::window::Window; +use cacao::appkit::{App, AppDelegate}; +use cacao::layout::{Layout, LayoutConstraint}; +use cacao::text::{Font, Label}; +use cacao::view::{View, ViewDelegate}; + +struct BasicApp { + window: Window, + content_view: View +} + +impl AppDelegate for BasicApp { + fn did_finish_launching(&self) { + App::activate(); + + self.window.set_minimum_content_size(400., 400.); + self.window.set_title("Safe Area Demo"); + self.window.set_content_view(&self.content_view); + self.window.show(); + } + + fn should_terminate_after_last_window_closed(&self) -> bool { + true + } +} + +#[derive(Default)] +struct ContentView { + content: View, + label: Label +} + +impl ViewDelegate for ContentView { + const NAME: &'static str = "SafeAreaView"; + + fn did_load(&mut self, view: View) { + let font = Font::system(30.); + self.label.set_font(&font); + self.label.set_text("Hello World"); + self.label.set_text_color(cacao::color::Color::rgb(255, 255, 255)); + + self.content.add_subview(&self.label); + view.add_subview(&self.content); + + // Add layout constraints to be 100% excluding the safe area + // Do last because it will crash because the view needs to be inside the hierarchy + cacao::layout::LayoutConstraint::activate(&[ + self.content.top.constraint_equal_to(&view.safe_layout_guide.top), + self.content.leading.constraint_equal_to(&view.safe_layout_guide.leading), + self.content.trailing.constraint_equal_to(&view.safe_layout_guide.trailing), + self.content.bottom.constraint_equal_to(&view.safe_layout_guide.bottom), + ]) + } +} + +fn main() { + App::new("com.test.window", BasicApp { + window: Window::default(), + content_view: View::with(ContentView::default()) + }).run(); +} diff --git a/src/appkit/window/mod.rs b/src/appkit/window/mod.rs index bae5d57..5008a3a 100644 --- a/src/appkit/window/mod.rs +++ b/src/appkit/window/mod.rs @@ -205,6 +205,19 @@ impl Window { } } + /// Sets the subtitle (smaller text bellow the title on unified and expanded title bars) on the + /// underlying window. When this property is an empty string, the system removes the subtitle + /// from the window layout. Allocates and passes an `NSString` over to the Objective C runtime. + /// Does nothing when less than version 11. + pub fn set_subtittle(&self, subtitle: &str) { + if !os::is_minimum_version(11) return; + + unsafe { + let subtitle = NSString::new(subtitle); + let _: () = msg_send![&*self.objc, setTitle: title]; + } + } + /// Sets the title visibility for the underlying window. pub fn set_title_visibility(&self, visibility: TitleVisibility) { unsafe {