Ongoing cleaning efforts
This commit is contained in:
parent
6891e83019
commit
4266c4c8dc
|
@ -1,9 +1,44 @@
|
|||
//! Wraps the application lifecycle across platforms.
|
||||
//!
|
||||
//! This is where the bulk of your application logic starts out from. macOS and iOS are driven
|
||||
//! heavily by lifecycle events - in this case, your boilerplate would look something like this:
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use cacao::app::{App, AppDelegate};
|
||||
//! use cacao::window::Window;
|
||||
//!
|
||||
//! #[derive(Default)]
|
||||
//! struct BasicApp;
|
||||
//!
|
||||
//! impl AppDelegate for BasicApp {
|
||||
//! fn did_finish_launching(&self) {
|
||||
//! // Your program in here
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! App::new("com.my.app", BasicApp::default()).run();
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Why do I need to do this?
|
||||
//! A good question. Cocoa does many things for you (e.g, setting up and managing a runloop,
|
||||
//! handling the view/window heirarchy, and so on). This requires certain things happen before your
|
||||
//! code can safely run, which `App` in this framework does for you.
|
||||
//!
|
||||
//! - It ensures that the `sharedApplication` is properly initialized with your delegate.
|
||||
//! - It ensures that Cocoa is put into multi-threaded mode, so standard POSIX threads work as they
|
||||
//! should.
|
||||
//!
|
||||
//! ### Platform specificity
|
||||
//! Certain lifecycle events are specific to certain platforms. Where this is the case, the
|
||||
//! documentation makes every effort to note.
|
||||
|
||||
use objc_id::Id;
|
||||
use objc::runtime::Object;
|
||||
use objc::{class, msg_send, sel, sel_impl};
|
||||
|
||||
use crate::dispatcher::Dispatcher;
|
||||
use crate::foundation::{id, YES, NO, NSUInteger, AutoReleasePool};
|
||||
use crate::menu::Menu;
|
||||
|
||||
|
@ -14,10 +49,10 @@ mod delegate;
|
|||
use delegate::register_app_delegate_class;
|
||||
|
||||
pub mod enums;
|
||||
pub use enums::AppDelegateResponse;
|
||||
use enums::AppDelegateResponse;
|
||||
|
||||
pub mod traits;
|
||||
pub use traits::{AppDelegate, Dispatcher};
|
||||
use traits::AppDelegate;
|
||||
|
||||
pub(crate) static APP_PTR: &str = "rstAppPtr";
|
||||
|
||||
|
|
|
@ -13,14 +13,6 @@ use crate::user_activity::UserActivity;
|
|||
#[cfg(feature = "cloudkit")]
|
||||
use crate::cloudkit::share::CKShareMetaData;
|
||||
|
||||
/// Controllers interested in processing messages can implement this to respond to messages as
|
||||
/// they're dispatched. All messages come in on the main thread.
|
||||
pub trait Dispatcher {
|
||||
type Message: Send + Sync;
|
||||
|
||||
fn on_message(&self, _message: Self::Message) {}
|
||||
}
|
||||
|
||||
/// `AppDelegate` is more or less `NSAppDelegate` from the Objective-C/Swift side, just named
|
||||
/// differently to fit in with the general naming scheme found within this framework. You can
|
||||
/// implement methods from this trait in order to respond to lifecycle events that the system will
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
//! Traits used for `CollectionView` controllers. More or less maps to the iOS/macOS routines,
|
||||
//! mapping over the differences between them where appropriate.
|
||||
|
||||
pub trait CollectionViewController {
|
||||
|
||||
}
|
8
src/dispatcher.rs
Normal file
8
src/dispatcher.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
/// Controllers interested in processing messages can implement this to respond to messages as
|
||||
/// they're dispatched. All messages come in on the main thread.
|
||||
pub trait Dispatcher {
|
||||
type Message: Send + Sync;
|
||||
|
||||
fn on_message(&self, _message: Self::Message) {}
|
||||
}
|
28
src/lib.rs
28
src/lib.rs
|
@ -80,8 +80,8 @@ pub mod button;
|
|||
pub mod cloudkit;
|
||||
|
||||
pub mod color;
|
||||
pub mod collection_view;
|
||||
pub mod constants;
|
||||
pub mod dispatcher;
|
||||
pub mod dragdrop;
|
||||
pub mod error;
|
||||
pub mod events;
|
||||
|
@ -107,28 +107,4 @@ pub mod webview;
|
|||
|
||||
pub mod window;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::app::{App, AppDelegate, Dispatcher};
|
||||
|
||||
pub use crate::layout::LayoutConstraint;
|
||||
|
||||
pub use crate::menu::{Menu, MenuItem};
|
||||
|
||||
#[cfg(feature = "user-notifications")]
|
||||
pub use crate::notifications::{Notification, NotificationCenter, NotificationAuthOption};
|
||||
|
||||
pub use crate::toolbar::{Toolbar, ToolbarController, ToolbarHandle};
|
||||
|
||||
pub use crate::networking::URLRequest;
|
||||
|
||||
pub use crate::window::{
|
||||
Window, WindowConfig, WindowDelegate
|
||||
};
|
||||
|
||||
#[cfg(feature = "webview")]
|
||||
pub use crate::webview::{
|
||||
WebView, WebViewConfig, WebViewDelegate
|
||||
};
|
||||
|
||||
pub use crate::view::{View, ViewDelegate};
|
||||
}
|
||||
pub mod prelude;
|
||||
|
|
29
src/prelude.rs
Normal file
29
src/prelude.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
//! The prelude imports a large amount of useful widgets and traits. You're of course free to
|
||||
//! thread imports yourself, but for many smaller applications this module can be quite a time
|
||||
//! saver.
|
||||
|
||||
pub use crate::app::{App, traits::AppDelegate};
|
||||
|
||||
pub use crate::dispatcher::Dispatcher;
|
||||
|
||||
pub use crate::layout::LayoutConstraint;
|
||||
|
||||
pub use crate::menu::{Menu, MenuItem};
|
||||
|
||||
#[cfg(feature = "user-notifications")]
|
||||
pub use crate::notifications::{Notification, NotificationCenter, NotificationAuthOption};
|
||||
|
||||
pub use crate::toolbar::{Toolbar, ToolbarController, ToolbarHandle};
|
||||
|
||||
pub use crate::networking::URLRequest;
|
||||
|
||||
pub use crate::window::{
|
||||
Window, config::WindowConfig, traits::WindowDelegate
|
||||
};
|
||||
|
||||
#[cfg(feature = "webview")]
|
||||
pub use crate::webview::{
|
||||
WebView, WebViewConfig, WebViewDelegate
|
||||
};
|
||||
|
||||
pub use crate::view::{View, traits::ViewDelegate};
|
|
@ -1,9 +1,45 @@
|
|||
//! A `ViewHandle` represents an underlying `NSView`. You're passed a reference to one during your
|
||||
//! `ViewController::did_load()` method. This method is safe to store and use, however as it's
|
||||
//! UI-specific it's not thread safe.
|
||||
//! Wraps `NSView` and `UIView` across platforms.
|
||||
//!
|
||||
//! You can use this struct to configure how a view should look and layout. It implements
|
||||
//! AutoLayout - for more information, see the AutoLayout tutorial.
|
||||
//! This implementation errs towards the `UIView` side of things, and mostly acts as a wrapper to
|
||||
//! bring `NSView` to the modern era. It does this by flipping the coordinate system to be what
|
||||
//! people expect in 2020, and layer-backing all views by default.
|
||||
//!
|
||||
//! Views implement Autolayout, which enable you to specify how things should appear on the screen.
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use cacao::color::rgb;
|
||||
//! use cacao::layout::{Layout, LayoutConstraint};
|
||||
//! use cacao::view::View;
|
||||
//! use cacao::window::{Window, WindowDelegate};
|
||||
//!
|
||||
//! #[derive(Default)]
|
||||
//! struct AppWindow {
|
||||
//! content: View,
|
||||
//! red: View,
|
||||
//! window: Window
|
||||
//! }
|
||||
//!
|
||||
//! impl WindowDelegate for AppWindow {
|
||||
//! fn did_load(&mut self, window: Window) {
|
||||
//! window.set_minimum_content_size(300., 300.);
|
||||
//! self.window = window;
|
||||
//!
|
||||
//! self.red.set_background_color(rgb(224, 82, 99));
|
||||
//! self.content.add_subview(&self.red);
|
||||
//!
|
||||
//! self.window.set_content_view(&self.content);
|
||||
//!
|
||||
//! LayoutConstraint::activate(&[
|
||||
//! self.red.top.constraint_equal_to(&self.content.top).offset(16.),
|
||||
//! self.red.leading.constraint_equal_to(&self.content.leading).offset(16.),
|
||||
//! self.red.trailing.constraint_equal_to(&self.content.trailing).offset(-16.),
|
||||
//! self.red.bottom.constraint_equal_to(&self.content.bottom).offset(-16.),
|
||||
//! ]);
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! For more information on Autolayout, view the module or check out the examples folder.
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
@ -21,10 +57,9 @@ mod class;
|
|||
use class::{register_view_class, register_view_class_with_delegate};
|
||||
|
||||
pub mod controller;
|
||||
pub use controller::ViewController;
|
||||
|
||||
pub mod traits;
|
||||
pub use traits::ViewDelegate;
|
||||
use traits::ViewDelegate;
|
||||
|
||||
pub(crate) static VIEW_DELEGATE_PTR: &str = "rstViewDelegatePtr";
|
||||
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
//! Implements a WebView, which wraps a number of different classes/delegates/controllers into one
|
||||
//! Wraps `WKWebView` across all platforms.
|
||||
//!
|
||||
//! Wraps a number of different classes/delegates/controllers into one
|
||||
//! useful interface. This encompasses...
|
||||
//!
|
||||
//! - `WKWebView`
|
||||
//! - `WKUIDelegate`
|
||||
//! - `WKScriptMessageHandler`
|
||||
//!
|
||||
//! This is, thankfully, a pretty similar class across platforms.
|
||||
//!
|
||||
//! ### WebView is not available for tvOS
|
||||
//! Apple does not ship `WKWebView` on tvOS, and as a result this control is not provided on that
|
||||
//! platform.
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
|
|
@ -1,3 +1,31 @@
|
|||
//! A `WindowController` is useful for handling certain document patterns on macOS.
|
||||
//!
|
||||
//! (iOS has no equivalent, as `UIWindowController` is private there).
|
||||
//!
|
||||
//! In particular, this is useful for certain situations regarding document handling
|
||||
//! (which this framework does not yet cover, but may eventually). Note that this control can only
|
||||
//! be created by providing a `WindowDelegate`.
|
||||
//!
|
||||
//! >If your application only uses a single `Window`, you may not even need this - just set the
|
||||
//! autosave name on your `Window` to get the benefit of cached window location across restarts.
|
||||
//!
|
||||
//! # How to use
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use cacao::app::AppDelegate;
|
||||
//! use cacao::window::{WindowController, WindowDelegate};
|
||||
//!
|
||||
//! #[derive(Default)]
|
||||
//! struct MyWindow;
|
||||
//!
|
||||
//! impl WindowDelegate for MyWindow {
|
||||
//! // Your implementation here...
|
||||
//! }
|
||||
//!
|
||||
//! struct MyApp {
|
||||
//! pub window: WindowController<MyWindow>
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use objc::runtime::Object;
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
|
@ -10,10 +38,13 @@ use crate::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR};
|
|||
mod class;
|
||||
use class::register_window_controller_class;
|
||||
|
||||
/// A `Window` represents your way of interacting with an `NSWindow`. It wraps the various moving
|
||||
/// pieces to enable you to focus on reacting to lifecycle methods and doing your thing.
|
||||
/// A `WindowController` wraps your `WindowDelegate` into an underlying `Window`, and
|
||||
/// provides some extra lifecycle methods.
|
||||
pub struct WindowController<T> {
|
||||
/// A handler to the underlying `NSWindowController`.
|
||||
pub objc: ShareId<Object>,
|
||||
|
||||
/// The underlying `Window` that this controller wraps.
|
||||
pub window: Window<T>
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
//! Implements an `NSWindow` wrapper for MacOS, backed by Cocoa and associated widgets.
|
||||
//! Wraps `NSWindow` on macOS and `UIWindow` on iOS.
|
||||
//!
|
||||
//! 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.
|
||||
//! Using `WindowDelegate`, you're able to handle lifecycle events on your `Window` (such as
|
||||
//! resizing, closing, and so on). Note that interaction patterns are different between macOS and
|
||||
//! iOS windows, so your codebase may need to differ quite a bit here.
|
||||
//!
|
||||
//! 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.
|
||||
//! Of note: on macOS, 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.
|
||||
|
||||
use std::unreachable;
|
||||
use std::rc::Rc;
|
||||
|
@ -28,16 +29,15 @@ mod class;
|
|||
use class::{register_window_class, register_window_class_with_delegate};
|
||||
|
||||
pub mod config;
|
||||
pub use config::WindowConfig;
|
||||
use config::WindowConfig;
|
||||
|
||||
pub mod controller;
|
||||
pub use controller::WindowController;
|
||||
|
||||
pub mod enums;
|
||||
use enums::TitleVisibility;
|
||||
|
||||
pub mod traits;
|
||||
pub use traits::WindowDelegate;
|
||||
use traits::WindowDelegate;
|
||||
|
||||
pub(crate) static WINDOW_DELEGATE_PTR: &str = "rstWindowDelegate";
|
||||
|
||||
|
@ -45,10 +45,10 @@ pub(crate) static WINDOW_DELEGATE_PTR: &str = "rstWindowDelegate";
|
|||
/// pieces to enable you to focus on reacting to lifecycle methods and doing your thing.
|
||||
#[derive(Debug)]
|
||||
pub struct Window<T = ()> {
|
||||
/// A pointer to the Objective-C `NSWindow`. Used in callback orchestration.
|
||||
/// A pointer to the Objective-C `NS/UIWindow`. Used in callback orchestration.
|
||||
pub(crate) internal_callback_ptr: Option<*const RefCell<T>>,
|
||||
|
||||
/// Represents an `NSWindow` in the Objective-C runtime.
|
||||
/// Represents an `NS/UIWindow` in the Objective-C runtime.
|
||||
pub objc: ShareId<Object>,
|
||||
|
||||
/// A delegate for this window.
|
||||
|
|
Loading…
Reference in a new issue