From c71319426248967e3f2f0393e0510a5a42626b01 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Sat, 7 Aug 2021 22:31:48 -0700 Subject: [PATCH] v0.3. - Changes internal target_os flags to be feature flags; macOS is now appkit, and iOS/tvOS are now uikit. This enables platforms that are not Apple-specific platforms that use frameworks to be compiled for. - Updates the examples to handle closing/quitting better. --- Cargo.toml | 10 ++- README.md | 16 +++- build.rs | 14 ++- examples/autolayout.rs | 37 +++++++- examples/browser/main.rs | 8 +- examples/browser/toolbar.rs | 2 +- examples/calculator/calculator.rs | 2 +- examples/calculator/content_view.rs | 2 +- examples/calculator/main.rs | 7 +- examples/defaults.rs | 2 +- examples/ios-beta/main.rs | 2 +- examples/ios-beta/readme.md | 2 +- examples/text_input.rs | 11 ++- examples/todos_list/add/mod.rs | 2 +- examples/todos_list/app.rs | 2 +- examples/todos_list/main.rs | 2 +- examples/todos_list/menu.rs | 2 +- examples/todos_list/preferences/mod.rs | 4 +- examples/todos_list/preferences/toolbar.rs | 2 +- examples/todos_list/storage/mod.rs | 2 +- examples/todos_list/todos/mod.rs | 4 +- examples/todos_list/todos/toolbar.rs | 2 +- examples/todos_list/windows.rs | 2 +- examples/window.rs | 36 +++++++- examples/window_controller.rs | 36 +++++++- examples/window_delegate.rs | 37 +++++++- src/{macos => appkit}/alert.rs | 4 +- src/{macos => appkit}/app/class.rs | 0 src/{macos => appkit}/app/delegate.rs | 4 +- src/{macos => appkit}/app/enums.rs | 0 src/{macos => appkit}/app/mod.rs | 4 +- src/{macos => appkit}/app/traits.rs | 8 +- src/{macos => appkit}/cursor.rs | 0 src/{macos => appkit}/enums.rs | 2 - src/{macos => appkit}/event/mod.rs | 0 src/{macos => appkit}/menu/item.rs | 0 src/{macos => appkit}/menu/menu.rs | 2 +- src/{macos => appkit}/menu/mod.rs | 0 src/{macos => appkit}/mod.rs | 0 src/{macos => appkit}/printing/enums.rs | 0 src/{macos => appkit}/printing/mod.rs | 0 src/{macos => appkit}/printing/settings.rs | 0 src/{macos => appkit}/toolbar/class.rs | 2 +- src/{macos => appkit}/toolbar/enums.rs | 0 src/{macos => appkit}/toolbar/item.rs | 2 +- src/{macos => appkit}/toolbar/mod.rs | 0 src/{macos => appkit}/toolbar/traits.rs | 2 +- src/{macos => appkit}/window/class.rs | 2 +- src/{macos => appkit}/window/config.rs | 2 +- .../window/controller/class.rs | 2 +- .../window/controller/mod.rs | 6 +- src/{macos => appkit}/window/enums.rs | 0 src/{macos => appkit}/window/mod.rs | 2 +- src/{macos => appkit}/window/traits.rs | 4 +- src/button/enums.rs | 6 +- src/button/mod.rs | 26 +++--- ...namic_color.rs => appkit_dynamic_color.rs} | 6 ++ src/color/mod.rs | 44 +++++----- src/filesystem/select.rs | 3 +- src/image/{macos.rs => appkit.rs} | 0 src/image/icons.rs | 1 - src/image/image.rs | 4 +- src/image/mod.rs | 16 ++-- src/image/{ios.rs => uikit.rs} | 0 src/input/{macos.rs => appkit.rs} | 0 src/input/mod.rs | 18 ++-- src/layout/traits.rs | 18 ++-- src/lib.rs | 56 ++++++------ src/listview/{macos.rs => appkit.rs} | 2 +- src/listview/mod.rs | 85 ++++++++++--------- src/listview/row/{macos.rs => appkit.rs} | 0 src/listview/row/mod.rs | 22 ++--- src/listview/row/{ios.rs => uikit.rs} | 0 src/listview/traits.rs | 2 +- src/progress/ios.rs | 45 ---------- src/progress/mod.rs | 10 +-- src/scrollview/{macos.rs => appkit.rs} | 0 src/scrollview/mod.rs | 14 +-- src/text/label/{macos.rs => appkit.rs} | 0 src/text/label/mod.rs | 22 ++--- src/{ios => uikit}/app/class.rs | 0 src/{ios => uikit}/app/delegate.rs | 4 +- src/{ios => uikit}/app/enums.rs | 0 src/{ios => uikit}/app/mod.rs | 2 +- src/{ios => uikit}/app/traits.rs | 2 +- src/{ios => uikit}/mod.rs | 0 src/{ios => uikit}/scene/config.rs | 2 +- src/{ios => uikit}/scene/delegate.rs | 4 +- src/{ios => uikit}/scene/enums.rs | 0 src/{ios => uikit}/scene/mod.rs | 0 src/{ios => uikit}/scene/options.rs | 0 src/{ios => uikit}/scene/session.rs | 2 +- src/{ios => uikit}/scene/traits.rs | 2 +- src/{ios => uikit}/window/mod.rs | 2 +- src/view/{macos.rs => appkit.rs} | 0 src/view/controller/{macos.rs => appkit.rs} | 0 src/view/controller/mod.rs | 20 ++--- src/view/controller/{ios.rs => uikit.rs} | 0 src/view/mod.rs | 32 +++---- src/view/splitviewcontroller/mod.rs | 39 +++++---- src/view/traits.rs | 12 +-- src/view/{ios.rs => uikit.rs} | 0 src/webview/mod.rs | 4 +- 103 files changed, 468 insertions(+), 355 deletions(-) rename src/{macos => appkit}/alert.rs (92%) rename src/{macos => appkit}/app/class.rs (100%) rename src/{macos => appkit}/app/delegate.rs (99%) rename src/{macos => appkit}/app/enums.rs (100%) rename src/{macos => appkit}/app/mod.rs (98%) rename src/{macos => appkit}/app/traits.rs (98%) rename src/{macos => appkit}/cursor.rs (100%) rename src/{macos => appkit}/enums.rs (94%) rename src/{macos => appkit}/event/mod.rs (100%) rename src/{macos => appkit}/menu/item.rs (100%) rename src/{macos => appkit}/menu/menu.rs (98%) rename src/{macos => appkit}/menu/mod.rs (100%) rename src/{macos => appkit}/mod.rs (100%) rename src/{macos => appkit}/printing/enums.rs (100%) rename src/{macos => appkit}/printing/mod.rs (100%) rename src/{macos => appkit}/printing/settings.rs (100%) rename src/{macos => appkit}/toolbar/class.rs (98%) rename src/{macos => appkit}/toolbar/enums.rs (100%) rename src/{macos => appkit}/toolbar/item.rs (97%) rename src/{macos => appkit}/toolbar/mod.rs (100%) rename src/{macos => appkit}/toolbar/traits.rs (96%) rename src/{macos => appkit}/window/class.rs (99%) rename src/{macos => appkit}/window/config.rs (97%) rename src/{macos => appkit}/window/controller/class.rs (93%) rename src/{macos => appkit}/window/controller/mod.rs (94%) rename src/{macos => appkit}/window/enums.rs (100%) rename src/{macos => appkit}/window/mod.rs (99%) rename src/{macos => appkit}/window/traits.rs (98%) rename src/color/{macos_dynamic_color.rs => appkit_dynamic_color.rs} (97%) rename src/image/{macos.rs => appkit.rs} (100%) rename src/image/{ios.rs => uikit.rs} (100%) rename src/input/{macos.rs => appkit.rs} (100%) rename src/listview/{macos.rs => appkit.rs} (99%) rename src/listview/row/{macos.rs => appkit.rs} (100%) rename src/listview/row/{ios.rs => uikit.rs} (100%) delete mode 100644 src/progress/ios.rs rename src/scrollview/{macos.rs => appkit.rs} (100%) rename src/text/label/{macos.rs => appkit.rs} (100%) rename src/{ios => uikit}/app/class.rs (100%) rename src/{ios => uikit}/app/delegate.rs (95%) rename src/{ios => uikit}/app/enums.rs (100%) rename src/{ios => uikit}/app/mod.rs (98%) rename src/{ios => uikit}/app/traits.rs (93%) rename src/{ios => uikit}/mod.rs (100%) rename src/{ios => uikit}/scene/config.rs (96%) rename src/{ios => uikit}/scene/delegate.rs (94%) rename src/{ios => uikit}/scene/enums.rs (100%) rename src/{ios => uikit}/scene/mod.rs (100%) rename src/{ios => uikit}/scene/options.rs (100%) rename src/{ios => uikit}/scene/session.rs (91%) rename src/{ios => uikit}/scene/traits.rs (70%) rename src/{ios => uikit}/window/mod.rs (97%) rename src/view/{macos.rs => appkit.rs} (100%) rename src/view/controller/{macos.rs => appkit.rs} (100%) rename src/view/controller/{ios.rs => uikit.rs} (100%) rename src/view/{ios.rs => uikit.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index 2a92847..bdb6a7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cacao" -description = "Rust bindings for AppKit (macOS, beta) and UIKit (iOS/tvOS, alpha)." -version = "0.2.1" +description = "Rust bindings for AppKit (macOS/Airyx/GNUStep, beta) and UIKit (iOS/tvOS, alpha)." +version = "0.3.0" edition = "2018" authors = ["Ryan McGrath "] build = "build.rs" @@ -20,7 +20,7 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] block = "0.1.6" -core-foundation = { version = "0.9", features = ["with-chrono", "mac_os_10_8_features"] } +core-foundation = { version = "0.9", features = ["with-chrono"] } core-graphics = "0.22" dispatch = "0.2.0" lazy_static = "1.4.0" @@ -36,7 +36,9 @@ infer = { version = "0.4", optional = true } eval = "0.4" [features] -default = [] +appkit = ["core-foundation/mac_os_10_8_features"] +uikit = [] +default = ["appkit"] cloudkit = [] color_fallbacks = [] quicklook = [] diff --git a/README.md b/README.md index 10cd2f8..f19d42a 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,17 @@ It tries to do so in a way that, if you've done programming for the framework be 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. -`0.2.0` exists on crates.io in part to enable the project to see wider usage, which can +This exists on crates.io in part to enable the project to see wider usage, which can inform development. That said, this library is currently early stages and may have bugs - your usage of it is at your own risk. However, provided you follow the rules (regarding memory/ownership) it's already fine for some apps. The core repository has a wealth of examples to help you get started. +> **Important** +> +> If you are migrating from 0.2 to 0.3, you should elect either `appkit` or `uikit` as a feature in your `Cargo.toml`. This change was made to +> support platforms that aren't just macOS/iOS/tvOS (e.g, gnustep, airyx). One of these features is required to work; `appkit` is defaulted for +> ease of development. + >_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 @@ -20,8 +26,8 @@ existence of unsafe will be closed without comment._ # Hello World ```rust -use cacao::macos::{App, AppDelegate}; -use cacao::macos::window::Window; +use cacao::appkit::{App, AppDelegate}; +use cacao::appkit::window::Window; #[derive(Default)] struct BasicApp { @@ -79,11 +85,13 @@ The following are a list of [Cargo features][cargo-features] that can be enabled The following are a list of [Cargo features][cargo-features] that can be enabled or disabled. +- `appkit`: Links `AppKit.framework`. +- `uikit`: Links `UIKit.framework` (iOS/tvOS only). - `cloudkit`: Links `CloudKit.framework` and provides some wrappers around CloudKit functionality. Currently not feature complete. - `color_fallbacks`: Provides fallback colors for older systems where `systemColor` types don't exist. This feature is very uncommon and you probably don't need it. - `quicklook`: Links `QuickLook.framework` and offers methods for generating preview images for files. - `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`. This feature is not supported on tvOS, as the platform has no webview control. +- `webview`: Links `WebKit.framework` and provides a `WebView` control backed by `WKWebView`. This feature is not supported on tvOS, as the platform has no webview control. This feature is also potentially only supported for macOS/iOS due to the WKWebView control and varying support on non-Apple platforms. - `webview-downloading-macos`: 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. This feature is not supported on iOS (a user would handle downloads very differently) or tvOS (there's no web browser there at all). [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section diff --git a/build.rs b/build.rs index 8b4e9b7..26896e3 100644 --- a/build.rs +++ b/build.rs @@ -1,17 +1,13 @@ //! Emits linker flags depending on platforms and features. -//! -//! (iOS/macOS only right now... maybe tvOS one day?) fn main() { - let target = std::env::var("TARGET").unwrap(); - println!("cargo:rustc-link-lib=framework=Foundation"); - if target.contains("-ios") { - println!("cargo:rustc-link-lib=framework=UIKit"); - } else { - println!("cargo:rustc-link-lib=framework=AppKit"); - } + #[cfg(feature = "appkit")] + println!("cargo:rustc-link-lib=framework=AppKit"); + + #[cfg(feature = "uikit")] + println!("cargo:rustc-link-lib=framework=UIKit"); println!("cargo:rustc-link-lib=framework=CoreGraphics"); println!("cargo:rustc-link-lib=framework=QuartzCore"); diff --git a/examples/autolayout.rs b/examples/autolayout.rs index fb564c4..880b3bf 100644 --- a/examples/autolayout.rs +++ b/examples/autolayout.rs @@ -5,8 +5,9 @@ use cacao::color::{Color, Theme}; use cacao::layout::{Layout, LayoutConstraint}; use cacao::view::View; -use cacao::macos::{App, AppDelegate}; -use cacao::macos::window::{Window, WindowConfig, WindowDelegate}; +use cacao::appkit::{App, AppDelegate}; +use cacao::appkit::menu::{Menu, MenuItem}; +use cacao::appkit::window::{Window, WindowConfig, WindowDelegate}; struct BasicApp { window: Window @@ -14,9 +15,41 @@ struct BasicApp { 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)] diff --git a/examples/browser/main.rs b/examples/browser/main.rs index e34219d..5b8fdf1 100644 --- a/examples/browser/main.rs +++ b/examples/browser/main.rs @@ -4,10 +4,10 @@ use cacao::notification_center::Dispatcher; use cacao::webview::{WebView, WebViewConfig, WebViewDelegate}; -use cacao::macos::{App, AppDelegate}; -use cacao::macos::menu::{Menu, MenuItem}; -use cacao::macos::toolbar::Toolbar; -use cacao::macos::window::{Window, WindowConfig, WindowDelegate, WindowToolbarStyle}; +use cacao::appkit::{App, AppDelegate}; +use cacao::appkit::menu::{Menu, MenuItem}; +use cacao::appkit::toolbar::Toolbar; +use cacao::appkit::window::{Window, WindowConfig, WindowDelegate, WindowToolbarStyle}; mod toolbar; use toolbar::BrowserToolbar; diff --git a/examples/browser/toolbar.rs b/examples/browser/toolbar.rs index 14f817b..b27628d 100644 --- a/examples/browser/toolbar.rs +++ b/examples/browser/toolbar.rs @@ -4,7 +4,7 @@ use cacao::objc::{msg_send, sel, sel_impl}; use cacao::button::Button; use cacao::input::{TextField, TextFieldDelegate}; -use cacao::macos::toolbar::{Toolbar, ToolbarDisplayMode, ToolbarItem, ItemIdentifier, ToolbarDelegate}; +use cacao::appkit::toolbar::{Toolbar, ToolbarDisplayMode, ToolbarItem, ItemIdentifier, ToolbarDelegate}; use super::Action; diff --git a/examples/calculator/calculator.rs b/examples/calculator/calculator.rs index 407a9c5..17783ff 100644 --- a/examples/calculator/calculator.rs +++ b/examples/calculator/calculator.rs @@ -1,7 +1,7 @@ use std::sync::{Arc, RwLock}; use cacao::lazy_static::lazy_static; -use cacao::macos::App; +use cacao::appkit::App; use crate::CalculatorApp; diff --git a/examples/calculator/content_view.rs b/examples/calculator/content_view.rs index ca55804..bed52b8 100644 --- a/examples/calculator/content_view.rs +++ b/examples/calculator/content_view.rs @@ -2,7 +2,7 @@ use cacao::text::{Font, Label, TextAlign}; use cacao::layout::{LayoutConstraint, Layout}; use cacao::button::{Button, BezelStyle}; use cacao::color::Color; -use cacao::macos::FocusRingType; +use cacao::appkit::FocusRingType; use cacao::view::{View, ViewDelegate}; use crate::button_row::ButtonRow; diff --git a/examples/calculator/main.rs b/examples/calculator/main.rs index f7df4bc..eeec9fd 100644 --- a/examples/calculator/main.rs +++ b/examples/calculator/main.rs @@ -11,9 +11,9 @@ use std::sync::RwLock; -use cacao::macos::{App, AppDelegate}; -use cacao::macos::window::{Window, WindowConfig, TitleVisibility}; -use cacao::macos::{Event, EventMask, EventMonitor}; +use cacao::appkit::{App, AppDelegate}; +use cacao::appkit::window::{Window, WindowConfig, TitleVisibility}; +use cacao::appkit::{Event, EventMask, EventMonitor}; use cacao::color::Color; use cacao::notification_center::Dispatcher; use cacao::view::View; @@ -48,6 +48,7 @@ impl AppDelegate for CalculatorApp { self.window.set_content_view(&self.content); self.window.show(); } + fn should_terminate_after_last_window_closed(&self) -> bool { true } diff --git a/examples/defaults.rs b/examples/defaults.rs index d01eed5..6502bb7 100644 --- a/examples/defaults.rs +++ b/examples/defaults.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; -use cacao::macos::{App, AppDelegate}; +use cacao::appkit::{App, AppDelegate}; use cacao::defaults::{UserDefaults, Value}; #[derive(Default)] diff --git a/examples/ios-beta/main.rs b/examples/ios-beta/main.rs index e8d362d..89b282f 100644 --- a/examples/ios-beta/main.rs +++ b/examples/ios-beta/main.rs @@ -1,6 +1,6 @@ use std::sync::RwLock; -use cacao::ios::{ +use cacao::uikit::{ App, AppDelegate, Scene, SceneConfig, SceneSession, SceneConnectionOptions, WindowSceneDelegate, Window }; diff --git a/examples/ios-beta/readme.md b/examples/ios-beta/readme.md index 08217c3..571ec55 100644 --- a/examples/ios-beta/readme.md +++ b/examples/ios-beta/readme.md @@ -7,7 +7,7 @@ Since this needs to run in an iOS simulator or on a device, you can't run it lik - Start a simulator (Simulator.app). - `cargo install cargo-bundle` - `cargo bundle --example ios-beta --target x86_64-apple-ios` -- `xcrun simctl install booted target/x86_64-apple-ios/debug/examples/bundle/ios/cacao-ios-test.app` +- `xcrun simctl install booted target/x86_64-apple-ios/debug/examples/bundle/ios/cacao-ios-beta.app` - `xcrun simctl launch --console booted com.cacao.ios-test` ## Current Support diff --git a/examples/text_input.rs b/examples/text_input.rs index d6994b2..521c74c 100644 --- a/examples/text_input.rs +++ b/examples/text_input.rs @@ -5,9 +5,9 @@ use cacao::layout::{Layout, LayoutConstraint}; use cacao::input::{TextField, TextFieldDelegate}; use cacao::view::View; -use cacao::macos::{App, AppDelegate}; -use cacao::macos::menu::{Menu, MenuItem}; -use cacao::macos::window::{Window, WindowConfig, WindowDelegate}; +use cacao::appkit::{App, AppDelegate}; +use cacao::appkit::menu::{Menu, MenuItem}; +use cacao::appkit::window::{Window, WindowConfig, WindowDelegate}; struct BasicApp { window: Window @@ -41,7 +41,6 @@ impl AppDelegate for BasicApp { MenuItem::SelectAll ]), - // Sidebar option is 11.0+ only. Menu::new("View", vec![ MenuItem::EnterFullScreen ]), @@ -59,6 +58,10 @@ impl AppDelegate for BasicApp { App::activate(); self.window.show(); } + + fn should_terminate_after_last_window_closed(&self) -> bool { + true + } } #[derive(Debug, Default)] diff --git a/examples/todos_list/add/mod.rs b/examples/todos_list/add/mod.rs index d94ac77..7ea5dd5 100644 --- a/examples/todos_list/add/mod.rs +++ b/examples/todos_list/add/mod.rs @@ -1,6 +1,6 @@ //! Implements a window for adding a new Todo. -use cacao::macos::window::{Window, WindowDelegate}; +use cacao::appkit::window::{Window, WindowDelegate}; use cacao::view::ViewController; use crate::storage::{dispatch_ui, Message}; diff --git a/examples/todos_list/app.rs b/examples/todos_list/app.rs index 19c41a2..67dfff5 100644 --- a/examples/todos_list/app.rs +++ b/examples/todos_list/app.rs @@ -1,7 +1,7 @@ //! Implements the start of the App lifecycle. Handles creating the required menu and window //! components and message dispatching. -use cacao::macos::{App, AppDelegate}; +use cacao::appkit::{App, AppDelegate}; use cacao::notification_center::Dispatcher; use crate::menu::menu; diff --git a/examples/todos_list/main.rs b/examples/todos_list/main.rs index b7fa587..726c962 100644 --- a/examples/todos_list/main.rs +++ b/examples/todos_list/main.rs @@ -3,7 +3,7 @@ //! //! This may get extracted into a different repo some day in the future. -use cacao::macos::App; +use cacao::appkit::App; mod add; mod app; diff --git a/examples/todos_list/menu.rs b/examples/todos_list/menu.rs index 9e9ddd6..c1f288e 100644 --- a/examples/todos_list/menu.rs +++ b/examples/todos_list/menu.rs @@ -4,7 +4,7 @@ //! Correctly functioning menus are a key part of what makes a macOS app feel right, though, so //! this is here for those who might want to use this todos example as a starting point. -use cacao::macos::menu::{Menu, MenuItem}; +use cacao::appkit::menu::{Menu, MenuItem}; use crate::storage::{dispatch_ui, Message}; diff --git a/examples/todos_list/preferences/mod.rs b/examples/todos_list/preferences/mod.rs index 5af1dc9..4774f1a 100644 --- a/examples/todos_list/preferences/mod.rs +++ b/examples/todos_list/preferences/mod.rs @@ -1,7 +1,7 @@ //! Implements a stock-ish Preferences window. -use cacao::macos::window::{Window, WindowDelegate}; -use cacao::macos::toolbar::Toolbar; +use cacao::appkit::window::{Window, WindowDelegate}; +use cacao::appkit::toolbar::Toolbar; use cacao::view::ViewController; use crate::storage::Message; diff --git a/examples/todos_list/preferences/toolbar.rs b/examples/todos_list/preferences/toolbar.rs index ee47414..895b4cb 100644 --- a/examples/todos_list/preferences/toolbar.rs +++ b/examples/todos_list/preferences/toolbar.rs @@ -1,7 +1,7 @@ //! Implements an example toolbar for a Preferences app. Could be cleaner, probably worth cleaning //! up at some point. -use cacao::macos::toolbar::{Toolbar, ToolbarDelegate, ToolbarItem, ItemIdentifier}; +use cacao::appkit::toolbar::{Toolbar, ToolbarDelegate, ToolbarItem, ItemIdentifier}; use cacao::image::{Image, MacSystemIcon}; use crate::storage::{dispatch_ui, Message}; diff --git a/examples/todos_list/storage/mod.rs b/examples/todos_list/storage/mod.rs index 0513221..ed6ecca 100644 --- a/examples/todos_list/storage/mod.rs +++ b/examples/todos_list/storage/mod.rs @@ -1,7 +1,7 @@ //! Messages that we used to thread control throughout the application. //! If you come from React/Redux, you can liken it to that world. -use cacao::macos::App; +use cacao::appkit::App; use crate::app::TodosApp; diff --git a/examples/todos_list/todos/mod.rs b/examples/todos_list/todos/mod.rs index eb88166..aaacb5f 100644 --- a/examples/todos_list/todos/mod.rs +++ b/examples/todos_list/todos/mod.rs @@ -1,7 +1,7 @@ //! The main Todos window. -use cacao::macos::window::{Window, WindowDelegate}; -use cacao::macos::toolbar::Toolbar; +use cacao::appkit::window::{Window, WindowDelegate}; +use cacao::appkit::toolbar::Toolbar; use cacao::view::ViewController; use crate::storage::Message; diff --git a/examples/todos_list/todos/toolbar.rs b/examples/todos_list/todos/toolbar.rs index ec2edeb..447389b 100644 --- a/examples/todos_list/todos/toolbar.rs +++ b/examples/todos_list/todos/toolbar.rs @@ -1,7 +1,7 @@ //! The main Todos window toolbar. Contains a button to enable adding a new task. use cacao::button::Button; -use cacao::macos::toolbar::{ +use cacao::appkit::toolbar::{ Toolbar, ToolbarDelegate, ToolbarItem, ToolbarDisplayMode, ItemIdentifier }; diff --git a/examples/todos_list/windows.rs b/examples/todos_list/windows.rs index ecc0389..4e7692a 100644 --- a/examples/todos_list/windows.rs +++ b/examples/todos_list/windows.rs @@ -5,7 +5,7 @@ use std::sync::RwLock; -use cacao::macos::window::{Window, WindowConfig, WindowStyle, WindowDelegate, WindowToolbarStyle}; +use cacao::appkit::window::{Window, WindowConfig, WindowStyle, WindowDelegate, WindowToolbarStyle}; use cacao::notification_center::Dispatcher; use crate::storage::Message; diff --git a/examples/window.rs b/examples/window.rs index 92e6248..719fee3 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -1,7 +1,8 @@ //! This example showcases setting up a basic application and window. -use cacao::macos::{App, AppDelegate}; -use cacao::macos::window::Window; +use cacao::appkit::{App, AppDelegate}; +use cacao::appkit::menu::{Menu, MenuItem}; +use cacao::appkit::window::Window; #[derive(Default)] struct BasicApp { @@ -10,12 +11,43 @@ struct BasicApp { 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.set_minimum_content_size(400., 400.); self.window.set_title("A Basic Window"); self.window.show(); } + + fn should_terminate_after_last_window_closed(&self) -> bool { + true + } } fn main() { diff --git a/examples/window_controller.rs b/examples/window_controller.rs index d7239f9..8f5e54e 100644 --- a/examples/window_controller.rs +++ b/examples/window_controller.rs @@ -4,8 +4,9 @@ //! //! If you're not using that, you can probably get by fine with a standard `NSWindow`. -use cacao::macos::{App, AppDelegate}; -use cacao::macos::window::{Window, WindowConfig, WindowController, WindowDelegate}; +use cacao::appkit::{App, AppDelegate}; +use cacao::appkit::menu::{Menu, MenuItem}; +use cacao::appkit::window::{Window, WindowConfig, WindowController, WindowDelegate}; struct BasicApp { window: WindowController @@ -13,10 +14,41 @@ struct BasicApp { 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)] diff --git a/examples/window_delegate.rs b/examples/window_delegate.rs index 267c4a0..9e40b9b 100644 --- a/examples/window_delegate.rs +++ b/examples/window_delegate.rs @@ -1,8 +1,9 @@ //! This example showcases setting up a basic application and window delegate. //! Window Delegate's give you lifecycle methods that you can respond to. -use cacao::macos::{App, AppDelegate}; -use cacao::macos::window::{Window, WindowConfig, WindowDelegate}; +use cacao::appkit::{App, AppDelegate}; +use cacao::appkit::menu::{Menu, MenuItem}; +use cacao::appkit::window::{Window, WindowConfig, WindowDelegate}; struct BasicApp { window: Window @@ -10,9 +11,41 @@ struct BasicApp { 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)] diff --git a/src/macos/alert.rs b/src/appkit/alert.rs similarity index 92% rename from src/macos/alert.rs rename to src/appkit/alert.rs index ea12ec9..7e886f2 100644 --- a/src/macos/alert.rs +++ b/src/appkit/alert.rs @@ -1,6 +1,6 @@ //! A wrapper for `NSAlert`. //! -//! This is housed inside `macos` as it's a useful tool for a few cases, but it doesn't match the +//! This is housed inside `appkit` as it's a useful tool for a few cases, but it doesn't match the //! iOS API, so we make no guarantees about it being a universal control. In general this also //! doesn't produce an amazing user experience, and you may want to shy away from using it. //! @@ -8,7 +8,7 @@ //! `Sheet`. //! //! ```rust -//! use cacao::macos::{App, AppDelegate, Alert}; +//! use cacao::appkit::{App, AppDelegate, Alert}; //! //! #[derive(Default)] //! struct ExampleApp; diff --git a/src/macos/app/class.rs b/src/appkit/app/class.rs similarity index 100% rename from src/macos/app/class.rs rename to src/appkit/app/class.rs diff --git a/src/macos/app/delegate.rs b/src/appkit/app/delegate.rs similarity index 99% rename from src/macos/app/delegate.rs rename to src/appkit/app/delegate.rs index 9703b4d..4e7c6c5 100644 --- a/src/macos/app/delegate.rs +++ b/src/appkit/app/delegate.rs @@ -15,8 +15,8 @@ use url::Url; use crate::error::Error; use crate::foundation::{id, nil, to_bool, BOOL, YES, NO, NSUInteger, NSArray, NSString}; -use crate::macos::app::{APP_PTR, AppDelegate}; -use crate::macos::printing::PrintSettings; +use crate::appkit::app::{APP_PTR, AppDelegate}; +use crate::appkit::printing::PrintSettings; use crate::user_activity::UserActivity; #[cfg(feature = "cloudkit")] diff --git a/src/macos/app/enums.rs b/src/appkit/app/enums.rs similarity index 100% rename from src/macos/app/enums.rs rename to src/appkit/app/enums.rs diff --git a/src/macos/app/mod.rs b/src/appkit/app/mod.rs similarity index 98% rename from src/macos/app/mod.rs rename to src/appkit/app/mod.rs index 001d7a5..437a68b 100644 --- a/src/macos/app/mod.rs +++ b/src/appkit/app/mod.rs @@ -45,7 +45,7 @@ use objc::{class, msg_send, sel, sel_impl}; use crate::foundation::{id, nil, YES, NO, NSUInteger, AutoReleasePool}; use crate::invoker::TargetActionHandler; -use crate::macos::menu::Menu; +use crate::appkit::menu::Menu; use crate::notification_center::Dispatcher; use crate::utils::activate_cocoa_multithreading; @@ -70,7 +70,7 @@ fn shared_application(handler: F) { handler(app); } -/// A wrapper for `NSApplication` on macOS, and `UIApplication` on iOS. +/// A wrapper for `NSApplication` in AppKit/Cocoa, and `UIApplication` in UIKit/Cocoa Touch. /// /// It holds (retains) a pointer to the Objective-C runtime shared application object, as well as /// handles setting up a few necessary pieces: diff --git a/src/macos/app/traits.rs b/src/appkit/app/traits.rs similarity index 98% rename from src/macos/app/traits.rs rename to src/appkit/app/traits.rs index 1735aa6..20f1b57 100644 --- a/src/macos/app/traits.rs +++ b/src/appkit/app/traits.rs @@ -6,10 +6,10 @@ use url::Url; use crate::error::Error; use crate::user_activity::UserActivity; -use crate::macos::app::enums::TerminateResponse; -use crate::macos::menu::Menu; -use crate::macos::printing::enums::PrintResponse; -use crate::macos::printing::settings::PrintSettings; +use crate::appkit::app::enums::TerminateResponse; +use crate::appkit::menu::Menu; +use crate::appkit::printing::enums::PrintResponse; +use crate::appkit::printing::settings::PrintSettings; #[cfg(feature = "cloudkit")] use crate::cloudkit::share::CKShareMetaData; diff --git a/src/macos/cursor.rs b/src/appkit/cursor.rs similarity index 100% rename from src/macos/cursor.rs rename to src/appkit/cursor.rs diff --git a/src/macos/enums.rs b/src/appkit/enums.rs similarity index 94% rename from src/macos/enums.rs rename to src/appkit/enums.rs index c60515d..f93f554 100644 --- a/src/macos/enums.rs +++ b/src/appkit/enums.rs @@ -3,7 +3,6 @@ use crate::foundation::{NSUInteger}; /// Used to set whether and/or how a view or cell draws a focus ring. -#[cfg(target_os = "macos")] #[derive(Debug)] pub enum FocusRingType { /// Whatever the default is. @@ -20,7 +19,6 @@ pub enum FocusRingType { Unknown(NSUInteger) } -#[cfg(target_os = "macos")] impl From for NSUInteger { fn from(ring_type: FocusRingType) -> Self { match ring_type { diff --git a/src/macos/event/mod.rs b/src/appkit/event/mod.rs similarity index 100% rename from src/macos/event/mod.rs rename to src/appkit/event/mod.rs diff --git a/src/macos/menu/item.rs b/src/appkit/menu/item.rs similarity index 100% rename from src/macos/menu/item.rs rename to src/appkit/menu/item.rs diff --git a/src/macos/menu/menu.rs b/src/appkit/menu/menu.rs similarity index 98% rename from src/macos/menu/menu.rs rename to src/appkit/menu/menu.rs index ee24b0f..7984262 100644 --- a/src/macos/menu/menu.rs +++ b/src/appkit/menu/menu.rs @@ -7,7 +7,7 @@ use objc::runtime::Object; use objc::{class, msg_send, sel, sel_impl}; use crate::foundation::{id, NSInteger, NSString}; -use crate::macos::menu::item::MenuItem; +use crate::appkit::menu::item::MenuItem; /// A struct that represents an `NSMenu`. It takes ownership of items, and handles instrumenting /// them throughout the application lifecycle. diff --git a/src/macos/menu/mod.rs b/src/appkit/menu/mod.rs similarity index 100% rename from src/macos/menu/mod.rs rename to src/appkit/menu/mod.rs diff --git a/src/macos/mod.rs b/src/appkit/mod.rs similarity index 100% rename from src/macos/mod.rs rename to src/appkit/mod.rs diff --git a/src/macos/printing/enums.rs b/src/appkit/printing/enums.rs similarity index 100% rename from src/macos/printing/enums.rs rename to src/appkit/printing/enums.rs diff --git a/src/macos/printing/mod.rs b/src/appkit/printing/mod.rs similarity index 100% rename from src/macos/printing/mod.rs rename to src/appkit/printing/mod.rs diff --git a/src/macos/printing/settings.rs b/src/appkit/printing/settings.rs similarity index 100% rename from src/macos/printing/settings.rs rename to src/appkit/printing/settings.rs diff --git a/src/macos/toolbar/class.rs b/src/appkit/toolbar/class.rs similarity index 98% rename from src/macos/toolbar/class.rs rename to src/appkit/toolbar/class.rs index 741afe6..693f5e5 100644 --- a/src/macos/toolbar/class.rs +++ b/src/appkit/toolbar/class.rs @@ -7,7 +7,7 @@ use objc::runtime::{Class, Object, Sel}; use objc::{class, sel, sel_impl, msg_send}; use crate::foundation::{load_or_register_class, id, BOOL, NSArray, NSString}; -use crate::macos::toolbar::{TOOLBAR_PTR, ToolbarDelegate}; +use crate::appkit::toolbar::{TOOLBAR_PTR, ToolbarDelegate}; use crate::utils::load; /// Retrieves and passes the allowed item identifiers for this toolbar. diff --git a/src/macos/toolbar/enums.rs b/src/appkit/toolbar/enums.rs similarity index 100% rename from src/macos/toolbar/enums.rs rename to src/appkit/toolbar/enums.rs diff --git a/src/macos/toolbar/item.rs b/src/appkit/toolbar/item.rs similarity index 97% rename from src/macos/toolbar/item.rs rename to src/appkit/toolbar/item.rs index 3c952e8..884c65c 100644 --- a/src/macos/toolbar/item.rs +++ b/src/appkit/toolbar/item.rs @@ -1,4 +1,4 @@ -//! Implements an NSToolbar wrapper, which is one of those macOS niceties +//! Implements an NSToolbar wrapper, which is one of those AppKit niceties //! that makes it feel... "proper". //! //! UNFORTUNATELY, this is a very old and janky API. So... yeah. diff --git a/src/macos/toolbar/mod.rs b/src/appkit/toolbar/mod.rs similarity index 100% rename from src/macos/toolbar/mod.rs rename to src/appkit/toolbar/mod.rs diff --git a/src/macos/toolbar/traits.rs b/src/appkit/toolbar/traits.rs similarity index 96% rename from src/macos/toolbar/traits.rs rename to src/appkit/toolbar/traits.rs index 22a559b..aa8355d 100644 --- a/src/macos/toolbar/traits.rs +++ b/src/appkit/toolbar/traits.rs @@ -2,7 +2,7 @@ //! go. Currently a bit incomplete in that we don't support the customizing workflow, but feel free //! to pull request it. -use crate::macos::toolbar::{Toolbar, ToolbarItem, ItemIdentifier}; +use crate::appkit::toolbar::{Toolbar, ToolbarItem, ItemIdentifier}; /// A trait that you can implement to have your struct/etc act as an `NSToolbarDelegate`. pub trait ToolbarDelegate { diff --git a/src/macos/window/class.rs b/src/appkit/window/class.rs similarity index 99% rename from src/macos/window/class.rs rename to src/appkit/window/class.rs index 0569a35..dee8917 100644 --- a/src/macos/window/class.rs +++ b/src/appkit/window/class.rs @@ -11,7 +11,7 @@ use objc::{class, sel, sel_impl}; use crate::foundation::{load_or_register_class, id, BOOL, YES, NO, NSUInteger}; use crate::utils::{load, CGSize}; -use crate::macos::window::{WindowDelegate, WINDOW_DELEGATE_PTR}; +use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR}; /// Called when an `NSWindowDelegate` receives a `windowWillClose:` event. /// Good place to clean up memory and what not. diff --git a/src/macos/window/config.rs b/src/appkit/window/config.rs similarity index 97% rename from src/macos/window/config.rs rename to src/appkit/window/config.rs index 2cc0a18..3400000 100644 --- a/src/macos/window/config.rs +++ b/src/appkit/window/config.rs @@ -4,7 +4,7 @@ use crate::foundation::NSUInteger; use crate::geometry::Rect; -use crate::macos::window::enums::{WindowStyle, WindowToolbarStyle}; +use crate::appkit::window::enums::{WindowStyle, WindowToolbarStyle}; #[derive(Debug)] pub struct WindowConfig { diff --git a/src/macos/window/controller/class.rs b/src/appkit/window/controller/class.rs similarity index 93% rename from src/macos/window/controller/class.rs rename to src/appkit/window/controller/class.rs index c597316..05b997e 100644 --- a/src/macos/window/controller/class.rs +++ b/src/appkit/window/controller/class.rs @@ -7,7 +7,7 @@ use objc::declare::ClassDecl; use objc::runtime::Class; use objc::class; -use crate::macos::window::{WindowDelegate, WINDOW_DELEGATE_PTR}; +use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR}; /// Injects an `NSWindowController` subclass, with some callback and pointer ivars for what we /// need to do. diff --git a/src/macos/window/controller/mod.rs b/src/appkit/window/controller/mod.rs similarity index 94% rename from src/macos/window/controller/mod.rs rename to src/appkit/window/controller/mod.rs index fda9cbe..7771c29 100644 --- a/src/macos/window/controller/mod.rs +++ b/src/appkit/window/controller/mod.rs @@ -12,8 +12,8 @@ //! # How to use //! //! ```rust,no_run -//! use cacao::macos::app::AppDelegate; -//! use cacao::macos::window::{WindowController, WindowDelegate}; +//! use cacao::appkit::app::AppDelegate; +//! use cacao::appkit::window::{WindowController, WindowDelegate}; //! //! #[derive(Default)] //! struct MyWindow; @@ -35,7 +35,7 @@ use objc_id::Id; use crate::foundation::{id, nil}; use crate::utils::Controller; -use crate::macos::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR}; +use crate::appkit::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR}; mod class; use class::register_window_controller_class; diff --git a/src/macos/window/enums.rs b/src/appkit/window/enums.rs similarity index 100% rename from src/macos/window/enums.rs rename to src/appkit/window/enums.rs diff --git a/src/macos/window/mod.rs b/src/appkit/window/mod.rs similarity index 99% rename from src/macos/window/mod.rs rename to src/appkit/window/mod.rs index fb40f9f..61b5a04 100644 --- a/src/macos/window/mod.rs +++ b/src/appkit/window/mod.rs @@ -20,7 +20,7 @@ use objc_id::ShareId; use crate::color::Color; use crate::foundation::{id, nil, to_bool, YES, NO, NSString, NSInteger, NSUInteger}; use crate::layout::traits::Layout; -use crate::macos::toolbar::{Toolbar, ToolbarDelegate}; +use crate::appkit::toolbar::{Toolbar, ToolbarDelegate}; use crate::utils::{os, Controller}; mod class; diff --git a/src/macos/window/traits.rs b/src/appkit/window/traits.rs similarity index 98% rename from src/macos/window/traits.rs rename to src/appkit/window/traits.rs index eb0ff62..fd6fae2 100644 --- a/src/macos/window/traits.rs +++ b/src/appkit/window/traits.rs @@ -2,8 +2,8 @@ //! module. There's a few different ones, and it's just... cleaner, if //! it's organized here. -use crate::macos::app::PresentationOption; -use crate::macos::window::Window; +use crate::appkit::app::PresentationOption; +use crate::appkit::window::Window; /// Lifecycle events for anything that `impl Window`'s. These map to the standard Cocoa /// lifecycle methods, but mix in a few extra things to handle offering configuration tools diff --git a/src/button/enums.rs b/src/button/enums.rs index bd3396a..0a033f8 100644 --- a/src/button/enums.rs +++ b/src/button/enums.rs @@ -2,7 +2,7 @@ use crate::foundation::NSUInteger; /// Represents a bezel style for a button. This is a macOS-specific control, and has no effect /// under iOS or tvOS. -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] #[derive(Debug)] pub enum BezelStyle { /// A standard circular button. @@ -49,7 +49,7 @@ pub enum BezelStyle { Unknown(NSUInteger) } -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] impl From for NSUInteger { fn from(style: BezelStyle) -> Self { match style { @@ -71,7 +71,7 @@ impl From for NSUInteger { } } -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] impl From for BezelStyle { fn from(i: NSUInteger) -> Self { match i { diff --git a/src/button/mod.rs b/src/button/mod.rs index 5df9739..00bc849 100644 --- a/src/button/mod.rs +++ b/src/button/mod.rs @@ -1,4 +1,4 @@ -//! Wraps `NSButton` on macOS, and `UIButton` on iOS and tvOS. +//! Wraps `NSButton` on appkit, and `UIButton` on iOS and tvOS. //! //! You'd use this type to create a button that a user can interact with. Buttons can be configured //! a number of ways, and support setting a callback to fire when they're clicked or tapped. @@ -36,13 +36,13 @@ use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension} use crate::text::{AttributedString, Font}; use crate::utils::{load, properties::ObjcProperty}; -#[cfg(target_os = "macos")] -use crate::macos::FocusRingType; +#[cfg(feature = "appkit")] +use crate::appkit::FocusRingType; mod enums; pub use enums::*; -/// Wraps `NSButton` on macOS, and `UIButton` on iOS and tvOS. +/// Wraps `NSButton` on appkit, and `UIButton` on iOS and tvOS. /// /// You'd use this type to create a button that a user can interact with. Buttons can be configured /// a number of ways, and support setting a callback to fire when they're clicked or tapped. @@ -144,8 +144,8 @@ impl Button { self.image = Some(image); } - /// Sets the bezel style for this button. Only supported on macOS. - #[cfg(target_os = "macos")] + /// Sets the bezel style for this button. Only supported on appkit. + #[cfg(feature = "appkit")] pub fn set_bezel_style(&self, bezel_style: BezelStyle) { let style: NSUInteger = bezel_style.into(); @@ -167,7 +167,7 @@ impl Button { pub fn set_background_color>(&self, color: C) { let color: id = color.as_ref().into(); - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] self.objc.with_mut(|obj| unsafe { let cell: id = msg_send![obj, cell]; let _: () = msg_send![cell, setBackgroundColor:color]; @@ -186,9 +186,9 @@ impl Button { /// Sets the text color for this button. /// - /// On macOS, this is done by way of an `AttributedString` under the hood. + /// On appkit, this is done by way of an `AttributedString` under the hood. pub fn set_text_color>(&self, color: C) { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] self.objc.with_mut(move |obj| unsafe { let text: id = msg_send![obj, attributedTitle]; let len: isize = msg_send![text, length]; @@ -201,8 +201,8 @@ impl Button { } // @TODO: Figure out how to handle oddities like this. - /// For buttons on macOS, one might need to disable the border. This does that. - #[cfg(target_os = "macos")] + /// For buttons on appkit, one might need to disable the border. This does that. + #[cfg(feature = "appkit")] pub fn set_bordered(&self, is_bordered: bool) { self.objc.with_mut(|obj| unsafe { let _: () = msg_send![obj, setBordered:match is_bordered { @@ -223,8 +223,8 @@ impl Button { /// Sets how the control should draw a focus ring when a user is focused on it. /// - /// This is a macOS-only method. - #[cfg(target_os = "macos")] + /// This is an appkit-only method. + #[cfg(feature = "appkit")] pub fn set_focus_ring_type(&self, focus_ring_type: FocusRingType) { let ring_type: NSUInteger = focus_ring_type.into(); diff --git a/src/color/macos_dynamic_color.rs b/src/color/appkit_dynamic_color.rs similarity index 97% rename from src/color/macos_dynamic_color.rs rename to src/color/appkit_dynamic_color.rs index cee8521..45fcc6e 100644 --- a/src/color/macos_dynamic_color.rs +++ b/src/color/appkit_dynamic_color.rs @@ -27,6 +27,9 @@ pub(crate) const AQUA_LIGHT_COLOR_HIGH_CONTRAST: &'static str = "AQUA_LIGHT_COLO pub(crate) const AQUA_DARK_COLOR_NORMAL_CONTRAST: &'static str = "AQUA_DARK_COLOR_NORMAL_CONTRAST"; pub(crate) const AQUA_DARK_COLOR_HIGH_CONTRAST: &'static str = "AQUA_DARK_COLOR_HIGH_CONTRAST"; +// Certain platforms we're interested in supporting (airyx) might not have these yet, so this +// will just force the Aqua appearance on that platform. +#[cfg(target_os = "macos")] extern "C" { static NSAppearanceNameAqua: id; static NSAppearanceNameAccessibilityHighContrastAqua: id; @@ -39,8 +42,11 @@ extern "C" { /// contrast checking on systems prior to 10.14: it's not that it couldn't be supported, but the /// ongoing question of how far back to support makes this not worth bothering with right now. /// +/// On non-Apple systems, this returns the light aqua color at all times. +/// /// Pull requests to implement that check would be welcome. fn get_effective_color(this: &Object) -> id { + #[cfg(target_os = "macos")] if os::is_minimum_semversion(10, 14, 0) { unsafe { let mut appearance: id = msg_send![class!(NSAppearance), currentAppearance]; diff --git a/src/color/mod.rs b/src/color/mod.rs index 7453277..7ed9528 100644 --- a/src/color/mod.rs +++ b/src/color/mod.rs @@ -26,11 +26,11 @@ use objc_id::Id; use crate::foundation::id; use crate::utils::os; -#[cfg(target_os = "macos")] -mod macos_dynamic_color; +#[cfg(feature = "appkit")] +mod appkit_dynamic_color; -#[cfg(target_os = "macos")] -use macos_dynamic_color::{ +#[cfg(feature = "appkit")] +use appkit_dynamic_color::{ AQUA_LIGHT_COLOR_NORMAL_CONTRAST, AQUA_LIGHT_COLOR_HIGH_CONTRAST, AQUA_DARK_COLOR_NORMAL_CONTRAST, AQUA_DARK_COLOR_HIGH_CONTRAST }; @@ -41,7 +41,7 @@ use macos_dynamic_color::{ /// default to the `Light` theme. #[derive(Copy, Clone, Debug)] pub enum Theme { - /// The "default" theme on a platform. On macOS, this is Aqua. + /// The "default" theme on a platform. On macOS/Airyx, this is Aqua. /// On iOS and tvOS, this is whatever you call the system defined theme. Light, @@ -230,11 +230,11 @@ pub enum Color { LightText, /// The background color for a given window in the system theme. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] MacOSWindowBackgroundColor, /// The background color that should appear under a page per the system theme. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] MacOSUnderPageBackgroundColor } @@ -248,10 +248,10 @@ impl Color { let a = alpha as CGFloat / 255.0; Color::Custom(Arc::new(RwLock::new(unsafe { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] { Id::from_ptr(msg_send![class!(NSColor), colorWithCalibratedRed:r green:g blue:b alpha:a]) } - #[cfg(target_os = "ios")] + #[cfg(feature = "uikit")] { Id::from_ptr(msg_send![class!(UIColor), colorWithRed:r green:g blue:b alpha:a]) } }))) } @@ -271,10 +271,10 @@ impl Color { let a = alpha as CGFloat / 255.0; Color::Custom(Arc::new(RwLock::new(unsafe { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] { Id::from_ptr(msg_send![class!(NSColor), colorWithCalibratedHue:h saturation:s brightness:b alpha:a]) } - #[cfg(target_os = "ios")] + #[cfg(feature = "uikit")] { Id::from_ptr(msg_send![class!(UIColor), colorWithHue:h saturation:s brightness:b alpha:a]) } }))) } @@ -289,10 +289,10 @@ impl Color { /// specified alpha. pub fn white_alpha(level: CGFloat, alpha: CGFloat) -> Self { Color::Custom(Arc::new(RwLock::new(unsafe { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] { Id::from_ptr(msg_send![class!(NSColor), colorWithCalibratedWhite:level alpha:alpha]) } - #[cfg(target_os = "ios")] + #[cfg(feature = "uikit")] { Id::from_ptr(msg_send![class!(UIColor), colorWithWhite:level alpha:alpha]) } }))) } @@ -319,6 +319,7 @@ impl Color { Color::hexa(hex, 255) } + // @TODO: This is currently appkit-only but should be for uikit as well. /// Creates and returns a dynamic color, which stores a handler and enables returning specific /// colors at appearance time based on device traits (i.e, dark mode vs light mode, contrast /// settings, etc). @@ -327,7 +328,7 @@ impl Color { /// "default" or "light" color. /// /// Returning a dynamic color in your handler is unsupported and may panic. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] pub fn dynamic(handler: F) -> Self where F: Fn(Style) -> Color + 'static @@ -337,9 +338,8 @@ impl Color { // not entirely clear on how expensive the dynamic allocation would be pre-10.15/11.0 and // am happy to do this for now and let someone who needs true dynamic allocation look into // it and PR it. - #[cfg(target_os = "macos")] Color::Custom(Arc::new(RwLock::new(unsafe { - let color: id = msg_send![macos_dynamic_color::register_class(), new]; + let color: id = msg_send![appkit_dynamic_color::register_class(), new]; (&mut *color).set_ivar(AQUA_LIGHT_COLOR_NORMAL_CONTRAST, { let color: id = handler(Style { @@ -421,7 +421,7 @@ impl From<&Color> for id { /// Handles color fallback for system-provided colors. macro_rules! system_color_with_fallback { ($class:ident, $color:ident, $fallback:ident) => ({ - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] { #[cfg(feature = "color-fallbacks")] if os::minimum_semversion(10, 10, 0) { @@ -434,7 +434,7 @@ macro_rules! system_color_with_fallback { msg_send![$class, $color] } - #[cfg(target_os = "ios")] + #[cfg(feature = "uikit")] { msg_send![$class, $color] } @@ -450,10 +450,10 @@ macro_rules! system_color_with_fallback { /// The goal here is to make sure that this can't reasonably break on OS's, as `Color` is kind of /// an important piece. It's not on the framework to make your app look good, though. unsafe fn to_objc(obj: &Color) -> id { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let color = class!(NSColor); - #[cfg(target_os = "ios")] + #[cfg(feature = "uikit")] let color = class!(UIColor); match obj { @@ -500,10 +500,10 @@ unsafe fn to_objc(obj: &Color) -> id { Color::DarkText => system_color_with_fallback!(color, darkTextColor, blackColor), Color::LightText => system_color_with_fallback!(color, lightTextColor, whiteColor), - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] Color::MacOSWindowBackgroundColor => system_color_with_fallback!(color, windowBackgroundColor, clearColor), - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] Color::MacOSUnderPageBackgroundColor => system_color_with_fallback!(color, underPageBackgroundColor, clearColor), } } diff --git a/src/filesystem/select.rs b/src/filesystem/select.rs index f6a7c35..4bc756a 100644 --- a/src/filesystem/select.rs +++ b/src/filesystem/select.rs @@ -13,7 +13,8 @@ use objc_id::ShareId; use crate::foundation::{id, YES, NO, NSInteger, NSString}; use crate::filesystem::enums::ModalResponse; -use crate::macos::window::{Window, WindowDelegate}; +#[cfg(feature = "appkit")] +use crate::appkit::window::{Window, WindowDelegate}; #[derive(Debug)] pub struct FileSelectPanel { diff --git a/src/image/macos.rs b/src/image/appkit.rs similarity index 100% rename from src/image/macos.rs rename to src/image/appkit.rs diff --git a/src/image/icons.rs b/src/image/icons.rs index b1decca..5091ffb 100644 --- a/src/image/icons.rs +++ b/src/image/icons.rs @@ -1,4 +1,3 @@ - /// These icons are system-provided icons that are guaranteed to exist in all versions of macOS /// that Cacao supports. These will use SFSymbols on Big Sur and onwards (11.0+), and the correct /// controls for prior macOS versions. diff --git a/src/image/image.rs b/src/image/image.rs index 974bbd8..d9e8d56 100644 --- a/src/image/image.rs +++ b/src/image/image.rs @@ -118,7 +118,7 @@ pub struct DrawConfig { pub resize: ResizeBehavior } -/// Wraps `NSImage` on macOS, and `UIImage` on iOS and tvOS. Can be used to display images, icons, +/// Wraps `NSImage` under AppKit, and `UIImage` on under UIKit (iOS and tvOS). Can be used to display images, icons, /// and so on. #[derive(Clone, Debug)] pub struct Image(pub ShareId); @@ -131,6 +131,8 @@ impl Image { }) } + // @TODO: for Airyx, unsure if this is supported - and it's somewhat modern macOS-specific, so + // let's keep the os flag here for now. /// Returns a stock system icon. These are guaranteed to exist across all versions of macOS /// supported. #[cfg(target_os = "macos")] diff --git a/src/image/mod.rs b/src/image/mod.rs index 313ad3f..4a0f177 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -7,16 +7,16 @@ use crate::color::Color; use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::utils::properties::ObjcProperty; -#[cfg(target_os = "macos")] -mod macos; +#[cfg(feature = "appkit")] +mod appkit; -#[cfg(target_os = "macos")] -use macos::register_image_view_class; +#[cfg(feature = "appkit")] +use appkit::register_image_view_class; -#[cfg(target_os = "ios")] -mod ios; +#[cfg(feature = "uikit")] +mod uikit; -#[cfg(target_os = "ios")] +#[cfg(feature = "uikit")] use ios::register_image_view_class; mod image; @@ -31,7 +31,7 @@ fn allocate_view(registration_fn: fn() -> *const Class) -> id { let view: id = msg_send![registration_fn(), new]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let _: () = msg_send![view, setWantsLayer:YES]; view diff --git a/src/image/ios.rs b/src/image/uikit.rs similarity index 100% rename from src/image/ios.rs rename to src/image/uikit.rs diff --git a/src/input/macos.rs b/src/input/appkit.rs similarity index 100% rename from src/input/macos.rs rename to src/input/appkit.rs diff --git a/src/input/mod.rs b/src/input/mod.rs index f1230d7..c9c0075 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -50,17 +50,17 @@ use crate::layout::{Layout, LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY} use crate::text::{Font, TextAlign}; use crate::utils::properties::ObjcProperty; -#[cfg(target_os = "macos")] -mod macos; +#[cfg(feature = "appkit")] +mod appkit; -#[cfg(target_os = "macos")] -use macos::{register_view_class, register_view_class_with_delegate}; +#[cfg(feature = "appkit")] +use appkit::{register_view_class, register_view_class_with_delegate}; -#[cfg(target_os = "ios")] -mod ios; +#[cfg(feature = "uikit")] +mod uikit; -#[cfg(target_os = "ios")] -use ios::{register_view_class, register_view_class_with_delegate}; +#[cfg(feature = "uikit")] +use uikit::{register_view_class, register_view_class_with_delegate}; mod traits; pub use traits::TextFieldDelegate; @@ -74,7 +74,7 @@ fn common_init(class: *const Class) -> id { let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints: NO]; - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let _: () = msg_send![view, setWantsLayer: YES]; view diff --git a/src/layout/traits.rs b/src/layout/traits.rs index c2f8815..283611b 100644 --- a/src/layout/traits.rs +++ b/src/layout/traits.rs @@ -10,7 +10,7 @@ use objc_id::ShareId; use crate::foundation::{id, nil, to_bool, YES, NO, NSArray, NSString}; use crate::geometry::Rect; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] use crate::pasteboard::PasteboardType; /// A trait that view wrappers must conform to. Enables managing the subview tree. @@ -105,7 +105,7 @@ pub trait Layout { } /// Returns whether this is hidden, *or* whether an ancestor view is hidden. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] fn is_hidden_or_ancestor_is_hidden(&self) -> bool { self.get_from_backing_node(|obj| { to_bool(unsafe { @@ -115,7 +115,10 @@ pub trait Layout { } /// Register this view for drag and drop operations. - #[cfg(target_os = "macos")] + /// + /// This should be supported under UIKit as well, but is featured gated under AppKit + /// currently to avoid compile issues. + #[cfg(feature = "appkit")] fn register_for_dragged_types(&self, types: &[PasteboardType]) { let types: NSArray = types.into_iter().map(|t| { let x: NSString = (*t).into(); @@ -128,7 +131,10 @@ pub trait Layout { } /// Unregisters this as a target for drag and drop operations. - #[cfg(target_os = "macos")] + /// + /// This should be supported under UIKit as well, but is featured gated under AppKit + /// currently to avoid compile issues. + #[cfg(feature = "appkit")] fn unregister_dragged_types(&self) { self.with_backing_node(|obj| unsafe { let _: () = msg_send![obj, unregisterDraggedTypes]; @@ -139,7 +145,7 @@ pub trait Layout { /// /// If you have a high performance tableview or collectionview that has issues, disabling these /// can be helpful - but always test! - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] fn set_posts_frame_change_notifications(&self, posts: bool) { self.with_backing_node(|obj| unsafe { let _: () = msg_send![obj, setPostsFrameChangedNotifications:match posts { @@ -153,7 +159,7 @@ pub trait Layout { /// /// If you have a high performance tableview or collectionview that has issues, disabling these /// can be helpful - but always test! - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] fn set_posts_bounds_change_notifications(&self, posts: bool) { self.with_backing_node(|obj| unsafe { let _: () = msg_send![obj, setPostsBoundsChangedNotifications:match posts { diff --git a/src/lib.rs b/src/lib.rs index dddef19..477a95b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ //! # Cacao //! -//! This library provides safe Rust bindings for `AppKit` on macOS and (eventually) `UIKit` on iOS and tvOS. +//! This library provides safe Rust bindings for `AppKit` on appkit and (eventually) `UIKit` on uikit and tvOS. //! 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. @@ -28,8 +28,8 @@ //! # Hello World //! //! ```rust,no_run -//! use cacao::macos::app::{App, AppDelegate}; -//! use cacao::macos::window::Window; +//! use cacao::appkit::app::{App, AppDelegate}; +//! use cacao::appkit::window::Window; //! //! #[derive(Default)] //! struct BasicApp { @@ -59,9 +59,9 @@ //! Note that, in order for this framework to be useful, you must always elect one of the following //! features: //! -//! - `macos`: Implements macOS-specific APIs (menus, toolbars, windowing, and so on). -//! - `ios`: Implements iOS-specific APIs (scenes, navigation controllers, and so on). -//! - `tvos`: Implements tvOS-specific APIs. Currently barely implemented. +//! - `appkit`: Implements appkit-specific APIs (menus, toolbars, windowing, and so on). +//! - `uikit`: Implements uikit-specific APIs (scenes, navigation controllers, and so on). +//! - `tvos`: Implements tvOS-specific APIs. Currently not actually implemented. //! //! The rest of the features in this framework attempt to expose a common API across the three //! aforementioned feature platforms; if you need something else, you can often implement it @@ -79,13 +79,13 @@ //! - `quicklook`: Links `QuickLook.framework` and offers methods for generating preview images for //! files. //! - `user-notifications`: Links `UserNotifications.framework` and provides functionality for -//! emitting notifications on macOS and iOS. Note that this _requires_ your application be +//! emitting notifications on appkit and uikit. 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`. -//! This feature is not supported on tvOS, as the platform has no webview control. -//! - `webview-downloading-macos`: Enables downloading files from the `WebView` via a private +//! This feature will not be supported on tvOS, as the platform has no webview control. +//! - `webview-downloading-appkit`: 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. This -//! feature is not supported on iOS (a user would handle downloads very differently) or tvOS +//! feature is not supported on uikit (a user would handle downloads very differently) or tvOS //! (there's no web browser there at all). //! //! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section @@ -96,15 +96,15 @@ pub use objc; pub use url; pub use lazy_static; -#[cfg(target_os = "macos")] -#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] -pub mod macos; +#[cfg(feature = "appkit")] +#[cfg_attr(docsrs, doc(cfg(target_os = "appkit")))] +pub mod appkit; -#[cfg(target_os = "ios")] -#[cfg_attr(docsrs, doc(cfg(target_os = "ios")))] -pub mod ios; +#[cfg(feature = "uikit")] +#[cfg_attr(docsrs, doc(cfg(target_os = "uikit")))] +pub mod uikit; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod button; #[cfg(any(feature = "cloudkit", doc))] @@ -113,50 +113,50 @@ pub mod cloudkit; pub mod color; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod dragdrop; pub mod error; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod events; pub mod defaults; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod filesystem; pub mod foundation; pub mod geometry; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod image; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod input; pub mod layer; pub(crate) mod invoker; pub mod layout; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod listview; pub mod networking; pub mod notification_center; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod pasteboard; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod progress; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod scrollview; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod switch; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub mod text; #[cfg(feature = "quicklook")] diff --git a/src/listview/macos.rs b/src/listview/appkit.rs similarity index 99% rename from src/listview/macos.rs rename to src/listview/appkit.rs index a6c6010..b8ce823 100644 --- a/src/listview/macos.rs +++ b/src/listview/appkit.rs @@ -14,7 +14,7 @@ use objc::runtime::{Class, Object, Sel, BOOL}; use objc::{class, sel, sel_impl, msg_send}; use objc_id::Id; -use crate::macos::menu::{Menu, MenuItem}; +use crate::appkit::menu::{Menu, MenuItem}; use crate::foundation::{load_or_register_class, id, nil, YES, NO, NSArray, NSInteger, NSUInteger}; use crate::dragdrop::DragInfo; use crate::listview::{ diff --git a/src/listview/mod.rs b/src/listview/mod.rs index 16fa1d6..0a60f16 100644 --- a/src/listview/mod.rs +++ b/src/listview/mod.rs @@ -56,20 +56,20 @@ use crate::utils::{os, CellFactory, CGSize}; use crate::utils::properties::{ObjcProperty, PropertyNullable}; use crate::view::ViewDelegate; -#[cfg(target_os = "macos")] -use crate::macos::menu::MenuItem; +#[cfg(feature = "appkit")] +use crate::appkit::menu::MenuItem; -#[cfg(target_os = "macos")] -mod macos; +#[cfg(feature = "appkit")] +mod appkit; -#[cfg(target_os = "macos")] -use macos::{register_listview_class, register_listview_class_with_delegate}; +#[cfg(feature = "appkit")] +use appkit::{register_listview_class, register_listview_class_with_delegate}; -#[cfg(target_os = "ios")] -mod ios; +//#[cfg(target_os = "ios")] +//mod ios; -#[cfg(target_os = "ios")] -use ios::{register_view_class, register_view_class_with_delegate}; +//#[cfg(target_os = "ios")] +//use ios::{register_view_class, register_view_class_with_delegate}; mod enums; pub use enums::{RowAnimation, RowEdge}; @@ -98,7 +98,7 @@ fn common_init(class: *const Class) -> id { let _: () = msg_send![tableview, setTranslatesAutoresizingMaskIntoConstraints:NO]; // Let's... make NSTableView into UITableView-ish. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] { // @TODO: Clean this up in a dealloc method. let menu: id = msg_send![class!(NSMenu), new]; @@ -137,9 +137,9 @@ pub struct ListView { /// A pointer to the Objective-C runtime view controller. pub objc: ObjcProperty, - /// On macOS, we need to manage the NSScrollView ourselves. It's a bit + /// In AppKit, we need to manage the NSScrollView ourselves. It's a bit /// more old school like that... - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] pub scrollview: ScrollView, /// A pointer to the delegate for this view. @@ -188,7 +188,7 @@ impl ListView { let class = register_listview_class(); let view = common_init(class); - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let scrollview = { let sview = ScrollView::new(); @@ -199,9 +199,9 @@ impl ListView { sview }; - // For macOS, we need to use the NSScrollView anchor points, not the NSTableView. + // For AppKit, we need to use the NSScrollView anchor points, not the NSTableView. // @TODO: Fix this with proper mutable access. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let anchor_view: id = scrollview.objc.get(|obj| unsafe { msg_send![obj, self] }); @@ -225,7 +225,7 @@ impl ListView { center_y: LayoutAnchorY::center(anchor_view), objc: ObjcProperty::retain(view), - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] scrollview: scrollview } } @@ -249,7 +249,7 @@ impl ListView where T: ListViewDelegate + 'static { let _: () = msg_send![view, setDataSource:view]; }; - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let scrollview = { let sview = ScrollView::new(); @@ -260,14 +260,14 @@ impl ListView where T: ListViewDelegate + 'static { sview }; - // For macOS, we need to use the NSScrollView anchor points, not the NSTableView. - #[cfg(target_os = "macos")] + // For AppKit, we need to use the NSScrollView anchor points, not the NSTableView. + #[cfg(feature = "appkit")] let anchor_view: id = scrollview.objc.get(|obj| unsafe { msg_send![obj, self] }); - #[cfg(target_os = "ios")] - let anchor_view = view; + //#[cfg(feature = "uikit")] + //let anchor_view = view; let mut view = ListView { cell_factory: cell, @@ -285,7 +285,7 @@ impl ListView where T: ListViewDelegate + 'static { center_y: LayoutAnchorY::center(anchor_view), objc: ObjcProperty::retain(view), - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] scrollview: scrollview }; @@ -317,7 +317,7 @@ impl ListView { center_y: self.center_y.clone(), objc: self.objc.clone(), - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] scrollview: self.scrollview.clone_as_handle() } } @@ -334,7 +334,7 @@ impl ListView { /// Dequeue a reusable cell. If one is not in the queue, will create and cache one for reuse. pub fn dequeue(&self, identifier: &'static str) -> ListViewRow { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] { let key = NSString::new(identifier); let cell: id = self.objc.get(|obj| unsafe { @@ -364,8 +364,11 @@ impl ListView { /// Sets the style for the underlying NSTableView. This property is only supported on macOS /// 11.0+, and will always be `FullWidth` on anything older. - #[cfg(target_os = "macos")] + /// + /// On non-macOS platforms, this method is a noop. + #[cfg(feature = "appkit")] pub fn set_style(&self, style: crate::foundation::NSInteger) { + #[cfg(target_os = "macos")] if os::is_minimum_version(11) { self.objc.with_mut(|obj| unsafe { let _: () = msg_send![obj, setStyle:style]; @@ -375,10 +378,10 @@ impl ListView { /// Set whether this control can appear with no row selected. /// - /// This defaults to `true`, but some macOS pieces (e.g, a sidebar) may want this set to + /// This defaults to `true`, but some AppKit pieces (e.g, a sidebar) may want this set to /// `false`. This can be particularly useful when implementing a Source List style sidebar /// view for navigation purposes. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] pub fn set_allows_empty_selection(&self, allows: bool) { self.objc.with_mut(|obj| unsafe { let _: () = msg_send![obj, setAllowsEmptySelection:match allows { @@ -425,7 +428,7 @@ impl ListView { /// ``` pub fn perform_batch_updates(&self, update: F) { // Note that we need to thread the `with_mut` calls carefully, to avoid deadlocking. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] { self.objc.get(|obj| unsafe { let _: () = msg_send![obj, beginUpdates]; @@ -453,7 +456,7 @@ impl ListView { /// rows at once, you should also run this inside a `perform_batch_updates` call, as that will /// optimize things accordingly. pub fn insert_rows(&self, indexes: &[usize], animation: RowAnimation) { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] unsafe { let index_set: id = msg_send![class!(NSMutableIndexSet), new]; @@ -476,7 +479,7 @@ impl ListView { /// Reload the rows at the specified indexes. pub fn reload_rows(&self, indexes: &[usize]) { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] unsafe { let index_set: id = msg_send![class!(NSMutableIndexSet), new]; @@ -503,7 +506,7 @@ impl ListView { /// rows at once, you should also run this inside a `perform_batch_updates` call, as that will /// optimize things accordingly. pub fn remove_rows(&self, indexes: &[usize], animations: RowAnimation) { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] unsafe { let index_set: id = msg_send![class!(NSMutableIndexSet), new]; @@ -537,7 +540,7 @@ impl ListView { /// /// It can make some scrolling situations much smoother. pub fn set_uses_automatic_row_heights(&self, uses: bool) { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] self.objc.with_mut(|obj| unsafe { let _: () = msg_send![obj, setUsesAutomaticRowHeights:match uses { true => YES, @@ -546,11 +549,11 @@ impl ListView { }); } - /// On macOS, this will instruct the underlying NSTableView to alternate + /// In AppKit, this will instruct the underlying NSTableView to alternate /// background colors automatically. If you set this, you possibly want /// to hard-set a row height as well. pub fn set_uses_alternating_backgrounds(&self, uses: bool) { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] self.objc.with_mut(|obj| unsafe { let _: () = msg_send![obj, setUsesAlternatingRowBackgroundColors:match uses { true => YES, @@ -561,7 +564,7 @@ impl ListView { /// End actions for a row. API subject to change. pub fn set_row_actions_visible(&self, visible: bool) { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] self.objc.with_mut(|obj| unsafe { let _: () = msg_send![obj, setRowActionsVisible:match visible { true => YES, @@ -586,7 +589,7 @@ impl ListView { self.objc.get(|obj| unsafe { msg_send![obj, selectedRow] }) } - /// Returns the currently clicked row. This is macOS-specific, and is generally used in context + /// Returns the currently clicked row. This is AppKit-specific, and is generally used in context /// menu generation to determine what item the context menu should be for. If the clicked area /// is not an actual row, this will return `-1`. /// @@ -614,19 +617,19 @@ impl ListView { impl Layout for ListView { fn with_backing_node(&self, handler: F) { - // On macOS, we need to provide the scrollview for layout purposes - iOS and tvOS will know + // In AppKit, we need to provide the scrollview for layout purposes - iOS and tvOS will know // what to do normally. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] self.scrollview.objc.with_mut(handler); } fn get_from_backing_node R, R>(&self, handler: F) -> R { - // On macOS, we need to provide the scrollview for layout purposes - iOS and tvOS will know + // In AppKit, we need to provide the scrollview for layout purposes - iOS and tvOS will know // what to do normally. // // @TODO: Review this, as property access isn't really used in the same place as layout // stuff... hmm... - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] self.scrollview.objc.get(handler) } } diff --git a/src/listview/row/macos.rs b/src/listview/row/appkit.rs similarity index 100% rename from src/listview/row/macos.rs rename to src/listview/row/appkit.rs diff --git a/src/listview/row/mod.rs b/src/listview/row/mod.rs index 935ed58..f6117ee 100644 --- a/src/listview/row/mod.rs +++ b/src/listview/row/mod.rs @@ -55,20 +55,20 @@ use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension} use crate::view::ViewDelegate; use crate::utils::properties::ObjcProperty; -#[cfg(target_os = "macos")] -mod macos; +#[cfg(feature = "appkit")] +mod appkit; -#[cfg(target_os = "macos")] -use macos::{register_listview_row_class, register_listview_row_class_with_delegate}; +#[cfg(feature = "appkit")] +use appkit::{register_listview_row_class, register_listview_row_class_with_delegate}; -#[cfg(target_os = "ios")] -mod ios; +//#[cfg(feature = "uikit")] +//mod ios; -#[cfg(target_os = "ios")] -use ios::{register_listview_row_view_class, register_listview_row_class_with_delegate}; +//#[cfg(feature = "uikit")] +//use ios::{register_listview_row_view_class, register_listview_row_class_with_delegate}; -pub(crate) static BACKGROUND_COLOR: &str = "alchemyBackgroundColor"; -pub(crate) static LISTVIEW_ROW_DELEGATE_PTR: &str = "rstListViewRowDelegatePtr"; +pub(crate) static BACKGROUND_COLOR: &str = "cacaoBackgroundColor"; +pub(crate) static LISTVIEW_ROW_DELEGATE_PTR: &str = "cacaoListViewRowDelegatePtr"; /// A helper method for instantiating view classes and applying default settings to them. fn allocate_view(registration_fn: fn() -> *const Class) -> id { @@ -76,7 +76,7 @@ fn allocate_view(registration_fn: fn() -> *const Class) -> id { let view: id = msg_send![registration_fn(), new]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let _: () = msg_send![view, setWantsLayer:YES]; view diff --git a/src/listview/row/ios.rs b/src/listview/row/uikit.rs similarity index 100% rename from src/listview/row/ios.rs rename to src/listview/row/uikit.rs diff --git a/src/listview/traits.rs b/src/listview/traits.rs index 1590ffa..bc0c3b3 100644 --- a/src/listview/traits.rs +++ b/src/listview/traits.rs @@ -1,6 +1,6 @@ //! Various traits used for Views. -use crate::macos::menu::MenuItem; +use crate::appkit::menu::MenuItem; use crate::dragdrop::{DragInfo, DragOperation}; use crate::listview::{ListView, ListViewRow, RowAction, RowEdge}; use crate::layout::Layout; diff --git a/src/progress/ios.rs b/src/progress/ios.rs deleted file mode 100644 index 1e835ed..0000000 --- a/src/progress/ios.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::sync::Once; - -use objc::declare::ClassDecl; -use objc::runtime::{Class, Object, Sel, BOOL}; -use objc::{class, sel, sel_impl}; -use objc_id::Id; - -use crate::foundation::{id, YES, NO, NSUInteger}; -use crate::dragdrop::DragInfo; -use crate::view::{VIEW_DELEGATE_PTR, ViewDelegate}; -use crate::utils::load; - -/// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we -/// have separate classes here since we don't want to waste cycles on methods that will never be -/// used if there's no delegates. -pub(crate) fn register_view_class() -> *const Class { - static mut VIEW_CLASS: *const Class = 0 as *const Class; - static INIT: Once = Once::new(); - - INIT.call_once(|| unsafe { - let superclass = class!(UIView); - let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); - VIEW_CLASS = decl.register(); - }); - - unsafe { VIEW_CLASS } -} - -/// Injects an `NSView` subclass, with some callback and pointer ivars for what we -/// need to do. -pub(crate) fn register_view_class_with_delegate() -> *const Class { - static mut VIEW_CLASS: *const Class = 0 as *const Class; - static INIT: Once = Once::new(); - - INIT.call_once(|| unsafe { - let superclass = class!(UIView); - let mut decl = ClassDecl::new("RSTViewWithDelegate", superclass).unwrap(); - decl.add_ivar::(VIEW_DELEGATE_PTR); - VIEW_CLASS = decl.register(); - }); - - unsafe { - VIEW_CLASS - } -} diff --git a/src/progress/mod.rs b/src/progress/mod.rs index 83ef309..2341635 100644 --- a/src/progress/mod.rs +++ b/src/progress/mod.rs @@ -22,12 +22,6 @@ use crate::color::Color; use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::utils::properties::ObjcProperty; -#[cfg(target_os = "ios")] -mod ios; - -#[cfg(target_os = "ios")] -use ios::register_progress_indicator_class; - mod enums; pub use enums::ProgressIndicatorStyle; @@ -79,11 +73,11 @@ impl ProgressIndicator { /// need it to stay around. pub fn new() -> Self { let view = unsafe { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let view: id = msg_send![class!(NSProgressIndicator), new]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let _: () = msg_send![view, setWantsLayer:YES]; view diff --git a/src/scrollview/macos.rs b/src/scrollview/appkit.rs similarity index 100% rename from src/scrollview/macos.rs rename to src/scrollview/appkit.rs diff --git a/src/scrollview/mod.rs b/src/scrollview/mod.rs index 535609e..25d2173 100644 --- a/src/scrollview/mod.rs +++ b/src/scrollview/mod.rs @@ -51,16 +51,16 @@ use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension} use crate::pasteboard::PasteboardType; use crate::utils::properties::ObjcProperty; -#[cfg(target_os = "macos")] -mod macos; +#[cfg(feature = "appkit")] +mod appkit; -#[cfg(target_os = "macos")] -use macos::{register_scrollview_class, register_scrollview_class_with_delegate}; +#[cfg(feature = "appkit")] +use appkit::{register_scrollview_class, register_scrollview_class_with_delegate}; -#[cfg(target_os = "ios")] +#[cfg(feature = "uikit")] mod ios; -#[cfg(target_os = "ios")] +#[cfg(feature = "uikit")] use ios::{register_view_class, register_view_class_with_delegate}; mod traits; @@ -74,7 +74,7 @@ fn allocate_view(registration_fn: fn() -> *const Class) -> id { let view: id = msg_send![registration_fn(), new]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] { let _: () = msg_send![view, setDrawsBackground:NO]; let _: () = msg_send![view, setWantsLayer:YES]; diff --git a/src/text/label/macos.rs b/src/text/label/appkit.rs similarity index 100% rename from src/text/label/macos.rs rename to src/text/label/appkit.rs diff --git a/src/text/label/mod.rs b/src/text/label/mod.rs index 87ffcb8..8a154b1 100644 --- a/src/text/label/mod.rs +++ b/src/text/label/mod.rs @@ -50,17 +50,17 @@ use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension} use crate::text::{Font, TextAlign, LineBreakMode}; use crate::utils::properties::ObjcProperty; -#[cfg(target_os = "macos")] -mod macos; +#[cfg(feature = "appkit")] +mod appkit; -#[cfg(target_os = "macos")] -use macos::{register_view_class, register_view_class_with_delegate}; +#[cfg(feature = "appkit")] +use appkit::{register_view_class, register_view_class_with_delegate}; -#[cfg(target_os = "ios")] -mod ios; +#[cfg(feature = "uikit")] +mod uikit; -#[cfg(target_os = "ios")] -use ios::{register_view_class, register_view_class_with_delegate}; +#[cfg(feature = "uikit")] +use uikit::{register_view_class, register_view_class_with_delegate}; mod traits; pub use traits::LabelDelegate; @@ -70,7 +70,7 @@ pub(crate) static LABEL_DELEGATE_PTR: &str = "rstLabelDelegatePtr"; /// A helper method for instantiating view classes and applying default settings to them. fn allocate_view(registration_fn: fn() -> *const Class) -> id { unsafe { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let view: id = { // This sucks, but for now, sure. let blank = NSString::no_copy(""); @@ -82,7 +82,7 @@ fn allocate_view(registration_fn: fn() -> *const Class) -> id { let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let _: () = msg_send![view, setWantsLayer:YES]; view @@ -331,7 +331,7 @@ impl Label { /// Set the line break mode for this label. pub fn set_line_break_mode(&self, mode: LineBreakMode) { - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] self.objc.with_mut(|obj| unsafe { let cell: id = msg_send![obj, cell]; let mode = mode as NSUInteger; diff --git a/src/ios/app/class.rs b/src/uikit/app/class.rs similarity index 100% rename from src/ios/app/class.rs rename to src/uikit/app/class.rs diff --git a/src/ios/app/delegate.rs b/src/uikit/app/delegate.rs similarity index 95% rename from src/ios/app/delegate.rs rename to src/uikit/app/delegate.rs index f2eba54..61af46b 100644 --- a/src/ios/app/delegate.rs +++ b/src/uikit/app/delegate.rs @@ -18,8 +18,8 @@ use url::Url; use crate::foundation::{id, nil, BOOL, YES, NO, NSUInteger, NSArray, NSString}; //use crate::user_activity::UserActivity; -use crate::ios::app::{AppDelegate, APP_DELEGATE}; -use crate::ios::scene::{SceneConfig, SceneConnectionOptions, SceneSession}; +use crate::uikit::app::{AppDelegate, APP_DELEGATE}; +use crate::uikit::scene::{SceneConfig, SceneConnectionOptions, SceneSession}; #[cfg(feature = "cloudkit")] use crate::cloudkit::share::CKShareMetaData; diff --git a/src/ios/app/enums.rs b/src/uikit/app/enums.rs similarity index 100% rename from src/ios/app/enums.rs rename to src/uikit/app/enums.rs diff --git a/src/ios/app/mod.rs b/src/uikit/app/mod.rs similarity index 98% rename from src/ios/app/mod.rs rename to src/uikit/app/mod.rs index ce47d78..1420c36 100644 --- a/src/ios/app/mod.rs +++ b/src/uikit/app/mod.rs @@ -41,7 +41,7 @@ use objc::runtime::Object; use objc::{class, msg_send, sel, sel_impl}; use crate::foundation::{id, nil, YES, NO, NSString, NSUInteger, AutoReleasePool}; -use crate::ios::scene::{WindowSceneDelegate, register_window_scene_delegate_class}; +use crate::uikit::scene::{WindowSceneDelegate, register_window_scene_delegate_class}; use crate::notification_center::Dispatcher; use crate::utils::activate_cocoa_multithreading; diff --git a/src/ios/app/traits.rs b/src/uikit/app/traits.rs similarity index 93% rename from src/ios/app/traits.rs rename to src/uikit/app/traits.rs index 1f80f59..3032ac4 100644 --- a/src/ios/app/traits.rs +++ b/src/uikit/app/traits.rs @@ -5,7 +5,7 @@ //use crate::error::Error; //use crate::user_activity::UserActivity; -use crate::ios::scene::{SceneConfig, SceneConnectionOptions, SceneSession}; +use crate::uikit::scene::{SceneConfig, SceneConnectionOptions, SceneSession}; #[cfg(feature = "cloudkit")] use crate::cloudkit::share::CKShareMetaData; diff --git a/src/ios/mod.rs b/src/uikit/mod.rs similarity index 100% rename from src/ios/mod.rs rename to src/uikit/mod.rs diff --git a/src/ios/scene/config.rs b/src/uikit/scene/config.rs similarity index 96% rename from src/ios/scene/config.rs rename to src/uikit/scene/config.rs index 20736dc..5be7523 100644 --- a/src/ios/scene/config.rs +++ b/src/uikit/scene/config.rs @@ -3,7 +3,7 @@ use objc::runtime::Object; use objc_id::Id; use crate::foundation::{id, NSString}; -use crate::ios::scene::SessionRole; +use crate::uikit::scene::SessionRole; /// A wrapper for UISceneConfiguration. /// diff --git a/src/ios/scene/delegate.rs b/src/uikit/scene/delegate.rs similarity index 94% rename from src/ios/scene/delegate.rs rename to src/uikit/scene/delegate.rs index 4b1f0b9..9972044 100644 --- a/src/ios/scene/delegate.rs +++ b/src/uikit/scene/delegate.rs @@ -15,8 +15,8 @@ use crate::foundation::{id, nil, BOOL, YES, NO, NSUInteger, NSArray, NSString}; use crate::user_activity::UserActivity; use crate::utils::load; -use crate::ios::app::{SCENE_DELEGATE_VENDOR}; -use crate::ios::scene::{Scene, SceneConfig, SceneConnectionOptions, SceneSession, WindowSceneDelegate}; +use crate::uikit::app::{SCENE_DELEGATE_VENDOR}; +use crate::uikit::scene::{Scene, SceneConfig, SceneConnectionOptions, SceneSession, WindowSceneDelegate}; #[cfg(feature = "cloudkit")] use crate::cloudkit::share::CKShareMetaData; diff --git a/src/ios/scene/enums.rs b/src/uikit/scene/enums.rs similarity index 100% rename from src/ios/scene/enums.rs rename to src/uikit/scene/enums.rs diff --git a/src/ios/scene/mod.rs b/src/uikit/scene/mod.rs similarity index 100% rename from src/ios/scene/mod.rs rename to src/uikit/scene/mod.rs diff --git a/src/ios/scene/options.rs b/src/uikit/scene/options.rs similarity index 100% rename from src/ios/scene/options.rs rename to src/uikit/scene/options.rs diff --git a/src/ios/scene/session.rs b/src/uikit/scene/session.rs similarity index 91% rename from src/ios/scene/session.rs rename to src/uikit/scene/session.rs index 6518098..e10497a 100644 --- a/src/ios/scene/session.rs +++ b/src/uikit/scene/session.rs @@ -3,7 +3,7 @@ use objc::runtime::Object; use objc::{msg_send, sel, sel_impl}; use crate::foundation::{id, NSString}; -use crate::ios::scene::enums::SessionRole; +use crate::uikit::scene::enums::SessionRole; #[derive(Debug)] pub struct SceneSession(pub Id); diff --git a/src/ios/scene/traits.rs b/src/uikit/scene/traits.rs similarity index 70% rename from src/ios/scene/traits.rs rename to src/uikit/scene/traits.rs index f704bc1..be7c6cb 100644 --- a/src/ios/scene/traits.rs +++ b/src/uikit/scene/traits.rs @@ -1,4 +1,4 @@ -use crate::ios::scene::{Scene, SceneSession, SceneConnectionOptions}; +use crate::uikit::scene::{Scene, SceneSession, SceneConnectionOptions}; pub trait WindowSceneDelegate { fn will_connect( diff --git a/src/ios/window/mod.rs b/src/uikit/window/mod.rs similarity index 97% rename from src/ios/window/mod.rs rename to src/uikit/window/mod.rs index 06d8bb3..8a2bfb9 100644 --- a/src/ios/window/mod.rs +++ b/src/uikit/window/mod.rs @@ -7,7 +7,7 @@ use objc_id::Id; use crate::foundation::id; use crate::geometry::Rect; -use crate::ios::Scene; +use crate::uikit::Scene; use crate::utils::Controller; #[derive(Debug)] diff --git a/src/view/macos.rs b/src/view/appkit.rs similarity index 100% rename from src/view/macos.rs rename to src/view/appkit.rs diff --git a/src/view/controller/macos.rs b/src/view/controller/appkit.rs similarity index 100% rename from src/view/controller/macos.rs rename to src/view/controller/appkit.rs diff --git a/src/view/controller/mod.rs b/src/view/controller/mod.rs index 7278a9f..871bb7d 100644 --- a/src/view/controller/mod.rs +++ b/src/view/controller/mod.rs @@ -7,20 +7,20 @@ use crate::layout::Layout; use crate::view::{VIEW_DELEGATE_PTR, View, ViewDelegate}; use crate::utils::Controller; -#[cfg(target_os = "macos")] -mod macos; +#[cfg(feature = "appkit")] +mod appkit; -#[cfg(target_os = "macos")] -use macos::register_view_controller_class; +#[cfg(feature = "appkit")] +use appkit::register_view_controller_class; -#[cfg(target_os = "ios")] -mod ios; +#[cfg(feature = "uikit")] +mod uikit; -#[cfg(target_os = "ios")] -use ios::register_view_controller_class; +#[cfg(feature = "uikit")] +use uikit::register_view_controller_class; -/// A `ViewController` is a wrapper around `NSViewController` on macOS, and `UIViewController` on -/// iOS and tvOS. +/// A `ViewController` is a wrapper around `NSViewController` in AppKit, and `UIViewController` in +/// UIKit /// /// This type is interchangeable with a standard `View`, in that using this simply forwards /// standard view controller lifecycle methods onto your `ViewDelegate`. You would use this if you diff --git a/src/view/controller/ios.rs b/src/view/controller/uikit.rs similarity index 100% rename from src/view/controller/ios.rs rename to src/view/controller/uikit.rs diff --git a/src/view/mod.rs b/src/view/mod.rs index ce64030..3a420e7 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -50,33 +50,33 @@ use crate::layer::Layer; use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::utils::properties::ObjcProperty; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] use crate::pasteboard::PasteboardType; -#[cfg(target_os = "macos")] -mod macos; +#[cfg(feature = "appkit")] +mod appkit; -#[cfg(target_os = "macos")] -use macos::{register_view_class, register_view_class_with_delegate}; +#[cfg(feature = "appkit")] +use appkit::{register_view_class, register_view_class_with_delegate}; -#[cfg(target_os = "ios")] -mod ios; +#[cfg(feature = "uikit")] +mod uikit; -#[cfg(target_os = "ios")] -use ios::{register_view_class, register_view_class_with_delegate}; +#[cfg(feature = "uikit")] +use uikit::{register_view_class, register_view_class_with_delegate}; mod controller; pub use controller::ViewController; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] mod splitviewcontroller; -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] pub use splitviewcontroller::SplitViewController; mod traits; pub use traits::ViewDelegate; -pub(crate) static BACKGROUND_COLOR: &str = "alchemyBackgroundColor"; +pub(crate) static BACKGROUND_COLOR: &str = "cacaoBackgroundColor"; pub(crate) static VIEW_DELEGATE_PTR: &str = "rstViewDelegatePtr"; /// A clone-able handler to a `ViewController` reference in the Objective C runtime. We use this @@ -92,7 +92,7 @@ pub struct View { /// A pointer to the Objective-C runtime view controller. pub objc: ObjcProperty, - /// References the underlying layer. This is consistent across macOS, iOS and tvOS - on macOS + /// References the underlying layer. This is consistent across AppKit & UIKit - in AppKit /// we explicitly opt in to layer backed views. pub layer: Layer, @@ -147,7 +147,7 @@ impl View { unsafe { let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let _: () = msg_send![view, setWantsLayer:YES]; } @@ -231,12 +231,12 @@ impl View { pub fn set_background_color>(&self, color: C) { let color: id = color.as_ref().into(); - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] self.objc.with_mut(|obj| unsafe { (&mut *obj).set_ivar(BACKGROUND_COLOR, color); }); - #[cfg(target_os = "ios")] + #[cfg(feature = "uikit")] self.objc.with_mut(|obj| unsafe { let _: () = msg_send![&*obj, setBackgroundColor:color]; }); diff --git a/src/view/splitviewcontroller/mod.rs b/src/view/splitviewcontroller/mod.rs index b229965..6c11f52 100644 --- a/src/view/splitviewcontroller/mod.rs +++ b/src/view/splitviewcontroller/mod.rs @@ -4,7 +4,7 @@ use objc::{class, msg_send, sel, sel_impl}; use crate::foundation::{id, nil, NSString}; use crate::layout::Layout; -use crate::macos::toolbar::ToolbarItem; +use crate::appkit::toolbar::ToolbarItem; use crate::view::{View, ViewController, ViewDelegate}; use crate::utils::{os, Controller}; @@ -49,21 +49,29 @@ where /// extend to the top of the window provided the other necessary window flags are set. On macOS /// versions prior to Big Sur, this returns a standard SplitViewItem. pub fn sidebar(view: T) -> Self { - if !os::is_minimum_version(11) { - return Self::item(view); + #[cfg(target_os = "macos")] + { + if !os::is_minimum_version(11) { + return Self::item(view); + } + + let view_controller = ViewController::new(view); + + SplitViewItem { + objc: unsafe { + ShareId::from_ptr(msg_send![class!(NSSplitViewItem), + sidebarWithViewController:&*view_controller.objc + ]) + }, + + view_controller + } } - let view_controller = ViewController::new(view); - - SplitViewItem { - objc: unsafe { - ShareId::from_ptr(msg_send![class!(NSSplitViewItem), - sidebarWithViewController:&*view_controller.objc - ]) - }, - - view_controller - } + // Non-macOS platforms default to the old-school API, where everything is just a generic + // item. + #[cfg(not(target_os = "macos"))] + Self::item(view) } /// Sets the titlebar separator style for this `SplitView`. @@ -71,8 +79,9 @@ where /// You'd use this if, say, you wanted a border under one part of the `SplitViewController` but /// not the other. This API was introduced in macOS 11.0 (Big Sur) and is a noop on anything /// prior. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] pub fn set_titlebar_separator_style(&self, style: crate::foundation::NSInteger) { + #[cfg(target_os = "macos")] if os::is_minimum_version(11) { unsafe { let _: () = msg_send![&*self.objc, setTitlebarSeparatorStyle:style]; diff --git a/src/view/traits.rs b/src/view/traits.rs index 6a936c8..0af8130 100644 --- a/src/view/traits.rs +++ b/src/view/traits.rs @@ -1,6 +1,6 @@ //! Various traits used for Views. -#[cfg(target_os = "macos")] +#[cfg(feature = "appkit")] use crate::dragdrop::{DragInfo, DragOperation}; use crate::view::View; @@ -43,27 +43,27 @@ pub trait ViewDelegate { /// Invoked when the dragged image enters destination bounds or frame; returns dragging /// operation to perform. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] fn dragging_entered(&self, info: DragInfo) -> DragOperation { DragOperation::None } /// Invoked when the image is released, allowing the receiver to agree to or refuse /// drag operation. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] fn prepare_for_drag_operation(&self, info: DragInfo) -> bool { false } /// Invoked after the released image has been removed from the screen, signaling the /// receiver to import the pasteboard data. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] fn perform_drag_operation(&self, info: DragInfo) -> bool { false } /// Invoked when the dragging operation is complete, signaling the receiver to perform /// any necessary clean-up. - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] fn conclude_drag_operation(&self, info: DragInfo) {} /// Invoked when the dragged image exits the destination’s bounds rectangle (in the case /// of a view) or its frame rectangle (in the case of a window object). - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] fn dragging_exited(&self, info: DragInfo) {} //fn perform_key_equivalent(&self, event: Event) -> bool { false } diff --git a/src/view/ios.rs b/src/view/uikit.rs similarity index 100% rename from src/view/ios.rs rename to src/view/uikit.rs diff --git a/src/webview/mod.rs b/src/webview/mod.rs index 455e8df..27252b6 100644 --- a/src/webview/mod.rs +++ b/src/webview/mod.rs @@ -79,7 +79,7 @@ fn allocate_webview( let webview_alloc: id = msg_send![register_webview_class(), alloc]; let webview: id = msg_send![webview_alloc, initWithFrame:zero configuration:configuration]; - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let _: () = msg_send![webview, setWantsLayer:YES]; let _: () = msg_send![webview, setTranslatesAutoresizingMaskIntoConstraints:NO]; @@ -159,7 +159,7 @@ impl WebView { unsafe { let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; - #[cfg(target_os = "macos")] + #[cfg(feature = "appkit")] let _: () = msg_send![view, setWantsLayer:YES]; }