From 8d490b3e3382e0982346e021dad462cdcbb8cd2b Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Fri, 27 Mar 2020 20:13:51 -0700 Subject: [PATCH] Further work on docs --- src/app/mod.rs | 4 +-- src/lib.rs | 78 ++++++++++++++++++++++++++++++++++++++------- src/window/enums.rs | 12 +++---- src/window/mod.rs | 53 +++++++++++++++++++++++++----- 4 files changed, 119 insertions(+), 28 deletions(-) diff --git a/src/app/mod.rs b/src/app/mod.rs index 180ee63..2b49398 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,6 +1,4 @@ -//! A wrapper for `NSApplicationDelegate` on macOS. Handles looping back events and providing a very janky -//! messaging architecture. -//! +//! use objc_id::Id; use objc::runtime::Object; diff --git a/src/lib.rs b/src/lib.rs index a0dc152..df5b932 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,17 +1,76 @@ -//! This crate provides pieces necessary for interfacing with `AppKit` on macOS and (eventually) `UIKit` on iOS. It +//#![deny(missing_docs)] +//#![deny(missing_debug_implementations)] + +// Copyright 2019+, the appkit-rs developers. +// See the COPYRIGHT file at the top-level directory of this distribution. +// Dual-licensed under an MIT/MPL-2.0 license, see the LICENSE files in this repository. + +//! # Cacao +//! +//! This library provides safe Rust bindings for `AppKit` on macOS and (eventually) `UIKit` on iOS. It //! tries to do so in a way that, if you've done programming for the framework before (in Swift or //! Objective-C), will feel familiar. This is tricky in Rust due to the ownership model, but some //! creative coding and assumptions can get us pretty far. //! -//! Note that this crate relies on the Objective-C runtime. Interfacing with the runtime _requires_ -//! unsafe blocks; this crate handles those unsafe interactions for you, but by using this crate -//! you understand that usage of `unsafe` is a given and will be somewhat rampant for wrapped -//! controls. This does _not_ mean you can't assess, review, or question unsafe usage - just know -//! it's happening, and in large part it's not going away. -//! -//! This crate is also, currently, _very_ early stage and may have bugs. Your usage of it is at +//! This library is currently _very_ early stage and may have bugs. Your usage of it is at //! your own risk. With that said, provided you follow the rules (regarding memory/ownership) it's //! already fine for some apps. +//! +//! _Note that this crate relies on the Objective-C runtime. Interfacing with the runtime *requires* +//! unsafe blocks; this crate handles those unsafe interactions for you and provides a safe wrapper, +//! but by using this crate you understand that usage of `unsafe` is a given and will be somewhat +//! rampant for wrapped controls. This does _not_ mean you can't assess, review, or question unsafe +//! usage - just know it's happening, and in large part it's not going away._ +//! +//! # Hello World +//! +//! ```rust,no_run +//! use cacao::app::{App, AppDelegate}; +//! use cacao::window::Window; +//! +//! #[derive(Default)] +//! struct BasicApp { +//! window: Window +//! } +//! +//! impl AppDelegate for BasicApp { +//! fn did_finish_launching(&self) { +//! self.window.set_minimum_content_size(400., 400.); +//! self.window.set_title("Hello World!"); +//! self.window.show(); +//! } +//! } +//! +//! fn main() { +//! App::new("com.hello.world", BasicApp::default()).run(); +//! } +//! ``` +//! +//! ## Initialization +//! Due to the way that AppKit and UIKit programs typically work, you're encouraged to do the bulk +//! of your work starting from the `did_finish_launching()` method of your `AppDelegate`. This +//! ensures the application has had time to initialize and do any housekeeping necessary behind the +//! scenes. +//! +//! ## Optional Features +//! +//! The following are a list of [Cargo features][cargo-features] that can be enabled or disabled. +//! +//! - **cloudkit**: Links `CloudKit.framework` and provides some wrappers around CloudKit +//! functionality. Currently not feature complete. +//! - **user-notifications**: Links `UserNotifications.framework` and provides functionality for +//! emitting notifications on macOS and iOS. Note that this _requires_ your application be +//! code-signed, and will not work without it. +//! - **webview**: Links `WebKit.framework` and provides a `WebView` control backed by `WKWebView`. +//! - **webview-downloading**: Enables downloading files from the `WebView` via a private +//! interface. This is not an App-Store-safe feature, so be aware of that before enabling. +//! +//! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section + +pub use core_foundation; +pub use core_graphics; +pub use objc; +pub use url; pub mod alert; pub mod app; @@ -48,9 +107,6 @@ pub mod webview; pub mod window; -// We re-export these so that they can be used without increasing build times. -pub use url; - pub mod prelude { pub use crate::app::{App, AppDelegate, Dispatcher}; diff --git a/src/window/enums.rs b/src/window/enums.rs index e25f688..0e8a48f 100644 --- a/src/window/enums.rs +++ b/src/window/enums.rs @@ -1,6 +1,6 @@ //! Enums used in Window construction and handling. -use crate::foundation::NSUInteger; +use crate::foundation::{NSInteger, NSUInteger}; /// Describes window styles that can be displayed. pub enum WindowStyle { @@ -80,7 +80,7 @@ impl From<&WindowStyle> for NSUInteger { } /// Describes whether a window shows a title or not. -pub enum WindowTitleVisibility { +pub enum TitleVisibility { /// Title is visible. Visible, @@ -88,11 +88,11 @@ pub enum WindowTitleVisibility { Hidden } -impl From for usize { - fn from(visibility: WindowTitleVisibility) -> usize { +impl From for NSInteger { + fn from(visibility: TitleVisibility) -> Self { match visibility { - WindowTitleVisibility::Visible => 0, - WindowTitleVisibility::Hidden => 1 + TitleVisibility::Visible => 0, + TitleVisibility::Hidden => 1 } } } diff --git a/src/window/mod.rs b/src/window/mod.rs index 5ca0bf4..96466ce 100644 --- a/src/window/mod.rs +++ b/src/window/mod.rs @@ -1,7 +1,8 @@ -//! Implements an `NSWindow` wrapper for MacOS, backed by Cocoa and associated widgets. This also handles looping back -//! lifecycle events, such as window resizing or close events. It currently implements a good chunk -//! of the API, however it should be noted that in places where things are outright deprecated, -//! this framework will opt to not bother providing access to them. +//! Implements an `NSWindow` wrapper for MacOS, backed by Cocoa and associated widgets. +//! +//! This also handles looping back lifecycle events, such as window resizing or close events. It +//! currently implements a good chunk of the API, however it should be noted that in places where +//! things are outright deprecated, this framework will opt to not bother providing access to them. //! //! If you require functionality like that, you're free to use the `objc` field on a `Window` to //! instrument it with the Objective-C runtime on your own. @@ -18,7 +19,7 @@ use objc::runtime::Object; use objc_id::ShareId; use crate::color::Color; -use crate::foundation::{id, nil, YES, NO, NSString, NSUInteger}; +use crate::foundation::{id, nil, YES, NO, NSString, NSInteger, NSUInteger}; use crate::layout::traits::Layout; use crate::toolbar::{Toolbar, ToolbarController}; use crate::utils::Controller; @@ -33,6 +34,7 @@ pub mod controller; pub use controller::WindowController; pub mod enums; +use enums::TitleVisibility; pub mod traits; pub use traits::WindowDelegate; @@ -113,9 +115,10 @@ impl Window { } /// Sets the title visibility for the underlying window. - pub fn set_title_visibility(&self, visibility: usize) { + pub fn set_title_visibility(&self, visibility: TitleVisibility) { unsafe { - let _: () = msg_send![&*self.objc, setTitleVisibility:visibility]; + let v = NSInteger::from(visibility); + let _: () = msg_send![&*self.objc, setTitleVisibility:v]; } } @@ -199,7 +202,7 @@ impl Window { } /// Given a view, sets it as the content view controller for this window. - pub fn set_content_view_controller(&self, controller: &C) { + pub fn set_content_view_controller(&self, controller: &VC) { let backing_node = controller.get_backing_node(); unsafe { @@ -238,6 +241,7 @@ impl Window { } } + /// Returns whether this window is opaque or not. pub fn is_opaque(&self) -> bool { unsafe { match msg_send![&*self.objc, isOpaque] { @@ -248,6 +252,39 @@ impl Window { } } + /// Returns whether this window is miniaturized or not. + pub fn is_miniaturized(&self) -> bool { + unsafe { + match msg_send![&*self.objc, isMiniaturized] { + YES => true, + NO => false, + _ => unreachable!() + } + } + } + + /// Miniaturize this window. + pub fn miniaturize(&self) { + unsafe { + let _: () = msg_send![&*self.objc, miniaturize]; + } + } + + /// De-mimizes this window. + pub fn deminiaturize(&self) { + unsafe { + let _: () = msg_send![&*self.objc, deminiaturize]; + } + } + + /// Runs the print panel, and if the user does anything except cancel, prints the window and + /// its contents. + pub fn print(&self) { + unsafe { + let _: () = msg_send![&*self.objc, print]; + } + } + /// Indicates whether the window is on a currently active space. /// /// From Apple's documentation: