- 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.
This commit is contained in:
Ryan McGrath 2021-08-07 22:31:48 -07:00
parent 2a9a8f8635
commit c713194262
No known key found for this signature in database
GPG key ID: DA6CBD9233593DEA
103 changed files with 468 additions and 355 deletions

View file

@ -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 <ryan@rymc.io>"]
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 = []

View file

@ -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

View file

@ -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");

View file

@ -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<AppWindow>
@ -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)]

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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
}

View file

@ -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)]

View file

@ -1,6 +1,6 @@
use std::sync::RwLock;
use cacao::ios::{
use cacao::uikit::{
App, AppDelegate, Scene, SceneConfig, SceneSession,
SceneConnectionOptions, WindowSceneDelegate, Window
};

View file

@ -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

View file

@ -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<AppWindow>
@ -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)]

View file

@ -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};

View file

@ -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;

View file

@ -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;

View file

@ -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};

View file

@ -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;

View file

@ -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};

View file

@ -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;

View file

@ -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;

View file

@ -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
};

View file

@ -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;

View file

@ -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() {

View file

@ -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<MyWindow>
@ -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)]

View file

@ -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<MyWindow>
@ -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)]

View file

@ -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;

View file

@ -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")]

View file

@ -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<F: Fn(id)>(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:

View file

@ -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;

View file

@ -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<FocusRingType> for NSUInteger {
fn from(ring_type: FocusRingType) -> Self {
match ring_type {

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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 {

View file

@ -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.

View file

@ -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 {

View file

@ -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.

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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<BezelStyle> for NSUInteger {
fn from(style: BezelStyle) -> Self {
match style {
@ -71,7 +71,7 @@ impl From<BezelStyle> for NSUInteger {
}
}
#[cfg(target_os = "macos")]
#[cfg(feature = "appkit")]
impl From<NSUInteger> for BezelStyle {
fn from(i: NSUInteger) -> Self {
match i {

View file

@ -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<C: AsRef<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<C: AsRef<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();

View file

@ -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];

View file

@ -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<F>(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),
}
}

View file

@ -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 {

View file

@ -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.

View file

@ -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<Object>);
@ -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")]

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -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")]

View file

@ -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::{

View file

@ -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<T = ()> {
/// 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<T> ListView<T> 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<T> ListView<T> 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<T> ListView<T> 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<T> ListView<T> {
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<T> ListView<T> {
/// Dequeue a reusable cell. If one is not in the queue, will create and cache one for reuse.
pub fn dequeue<R: ViewDelegate + 'static>(&self, identifier: &'static str) -> ListViewRow<R> {
#[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<T> ListView<T> {
/// 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<T> ListView<T> {
/// 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<T> ListView<T> {
/// ```
pub fn perform_batch_updates<F: Fn(ListView)>(&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<T> ListView<T> {
/// 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<T> ListView<T> {
/// 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<T> ListView<T> {
/// 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<T> ListView<T> {
///
/// 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<T> ListView<T> {
});
}
/// 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<T> ListView<T> {
/// 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<T> ListView<T> {
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<T> ListView<T> {
impl<T> Layout for ListView<T> {
fn with_backing_node<F: Fn(id)>(&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<F: Fn(&Object) -> 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)
}
}

View file

@ -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

View file

@ -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;

View file

@ -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<T: ViewDelegate>() -> *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::<usize>(VIEW_DELEGATE_PTR);
VIEW_CLASS = decl.register();
});
unsafe {
VIEW_CLASS
}
}

View file

@ -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

View file

@ -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];

View file

@ -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<T> Label<T> {
/// 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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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.
///

View file

@ -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;

View file

@ -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<Object>);

View file

@ -1,4 +1,4 @@
use crate::ios::scene::{Scene, SceneSession, SceneConnectionOptions};
use crate::uikit::scene::{Scene, SceneSession, SceneConnectionOptions};
pub trait WindowSceneDelegate {
fn will_connect(

View file

@ -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)]

View file

@ -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<T>`, in that using this simply forwards
/// standard view controller lifecycle methods onto your `ViewDelegate`. You would use this if you

View file

@ -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<T = ()> {
/// 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<T> View<T> {
pub fn set_background_color<C: AsRef<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];
});

View file

@ -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];

Some files were not shown because too many files have changed in this diff Show more