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.
This commit is contained in:
parent
2a9a8f8635
commit
c713194262
10
Cargo.toml
10
Cargo.toml
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "cacao"
|
name = "cacao"
|
||||||
description = "Rust bindings for AppKit (macOS, beta) and UIKit (iOS/tvOS, alpha)."
|
description = "Rust bindings for AppKit (macOS/Airyx/GNUStep, beta) and UIKit (iOS/tvOS, alpha)."
|
||||||
version = "0.2.1"
|
version = "0.3.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["Ryan McGrath <ryan@rymc.io>"]
|
authors = ["Ryan McGrath <ryan@rymc.io>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
@ -20,7 +20,7 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
block = "0.1.6"
|
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"
|
core-graphics = "0.22"
|
||||||
dispatch = "0.2.0"
|
dispatch = "0.2.0"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
@ -36,7 +36,9 @@ infer = { version = "0.4", optional = true }
|
||||||
eval = "0.4"
|
eval = "0.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
appkit = ["core-foundation/mac_os_10_8_features"]
|
||||||
|
uikit = []
|
||||||
|
default = ["appkit"]
|
||||||
cloudkit = []
|
cloudkit = []
|
||||||
color_fallbacks = []
|
color_fallbacks = []
|
||||||
quicklook = []
|
quicklook = []
|
||||||
|
|
16
README.md
16
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
|
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.
|
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
|
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
|
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.
|
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**
|
>_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,
|
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
|
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
|
# Hello World
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::appkit::{App, AppDelegate};
|
||||||
use cacao::macos::window::Window;
|
use cacao::appkit::window::Window;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct BasicApp {
|
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.
|
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.
|
- `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.
|
- `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.
|
- `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.
|
- `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).
|
- `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
|
[cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section
|
||||||
|
|
12
build.rs
12
build.rs
|
@ -1,17 +1,13 @@
|
||||||
//! Emits linker flags depending on platforms and features.
|
//! Emits linker flags depending on platforms and features.
|
||||||
//!
|
|
||||||
//! (iOS/macOS only right now... maybe tvOS one day?)
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let target = std::env::var("TARGET").unwrap();
|
|
||||||
|
|
||||||
println!("cargo:rustc-link-lib=framework=Foundation");
|
println!("cargo:rustc-link-lib=framework=Foundation");
|
||||||
|
|
||||||
if target.contains("-ios") {
|
#[cfg(feature = "appkit")]
|
||||||
println!("cargo:rustc-link-lib=framework=UIKit");
|
|
||||||
} else {
|
|
||||||
println!("cargo:rustc-link-lib=framework=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=CoreGraphics");
|
||||||
println!("cargo:rustc-link-lib=framework=QuartzCore");
|
println!("cargo:rustc-link-lib=framework=QuartzCore");
|
||||||
|
|
|
@ -5,8 +5,9 @@ use cacao::color::{Color, Theme};
|
||||||
use cacao::layout::{Layout, LayoutConstraint};
|
use cacao::layout::{Layout, LayoutConstraint};
|
||||||
use cacao::view::View;
|
use cacao::view::View;
|
||||||
|
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::appkit::{App, AppDelegate};
|
||||||
use cacao::macos::window::{Window, WindowConfig, WindowDelegate};
|
use cacao::appkit::menu::{Menu, MenuItem};
|
||||||
|
use cacao::appkit::window::{Window, WindowConfig, WindowDelegate};
|
||||||
|
|
||||||
struct BasicApp {
|
struct BasicApp {
|
||||||
window: Window<AppWindow>
|
window: Window<AppWindow>
|
||||||
|
@ -14,9 +15,41 @@ struct BasicApp {
|
||||||
|
|
||||||
impl AppDelegate for BasicApp {
|
impl AppDelegate for BasicApp {
|
||||||
fn did_finish_launching(&self) {
|
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();
|
App::activate();
|
||||||
|
|
||||||
self.window.show();
|
self.window.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_terminate_after_last_window_closed(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
use cacao::notification_center::Dispatcher;
|
use cacao::notification_center::Dispatcher;
|
||||||
use cacao::webview::{WebView, WebViewConfig, WebViewDelegate};
|
use cacao::webview::{WebView, WebViewConfig, WebViewDelegate};
|
||||||
|
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::appkit::{App, AppDelegate};
|
||||||
use cacao::macos::menu::{Menu, MenuItem};
|
use cacao::appkit::menu::{Menu, MenuItem};
|
||||||
use cacao::macos::toolbar::Toolbar;
|
use cacao::appkit::toolbar::Toolbar;
|
||||||
use cacao::macos::window::{Window, WindowConfig, WindowDelegate, WindowToolbarStyle};
|
use cacao::appkit::window::{Window, WindowConfig, WindowDelegate, WindowToolbarStyle};
|
||||||
|
|
||||||
mod toolbar;
|
mod toolbar;
|
||||||
use toolbar::BrowserToolbar;
|
use toolbar::BrowserToolbar;
|
||||||
|
|
|
@ -4,7 +4,7 @@ use cacao::objc::{msg_send, sel, sel_impl};
|
||||||
use cacao::button::Button;
|
use cacao::button::Button;
|
||||||
use cacao::input::{TextField, TextFieldDelegate};
|
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;
|
use super::Action;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use cacao::lazy_static::lazy_static;
|
use cacao::lazy_static::lazy_static;
|
||||||
use cacao::macos::App;
|
use cacao::appkit::App;
|
||||||
|
|
||||||
use crate::CalculatorApp;
|
use crate::CalculatorApp;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use cacao::text::{Font, Label, TextAlign};
|
||||||
use cacao::layout::{LayoutConstraint, Layout};
|
use cacao::layout::{LayoutConstraint, Layout};
|
||||||
use cacao::button::{Button, BezelStyle};
|
use cacao::button::{Button, BezelStyle};
|
||||||
use cacao::color::Color;
|
use cacao::color::Color;
|
||||||
use cacao::macos::FocusRingType;
|
use cacao::appkit::FocusRingType;
|
||||||
use cacao::view::{View, ViewDelegate};
|
use cacao::view::{View, ViewDelegate};
|
||||||
|
|
||||||
use crate::button_row::ButtonRow;
|
use crate::button_row::ButtonRow;
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
|
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::appkit::{App, AppDelegate};
|
||||||
use cacao::macos::window::{Window, WindowConfig, TitleVisibility};
|
use cacao::appkit::window::{Window, WindowConfig, TitleVisibility};
|
||||||
use cacao::macos::{Event, EventMask, EventMonitor};
|
use cacao::appkit::{Event, EventMask, EventMonitor};
|
||||||
use cacao::color::Color;
|
use cacao::color::Color;
|
||||||
use cacao::notification_center::Dispatcher;
|
use cacao::notification_center::Dispatcher;
|
||||||
use cacao::view::View;
|
use cacao::view::View;
|
||||||
|
@ -48,6 +48,7 @@ impl AppDelegate for CalculatorApp {
|
||||||
self.window.set_content_view(&self.content);
|
self.window.set_content_view(&self.content);
|
||||||
self.window.show();
|
self.window.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_terminate_after_last_window_closed(&self) -> bool {
|
fn should_terminate_after_last_window_closed(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::appkit::{App, AppDelegate};
|
||||||
use cacao::defaults::{UserDefaults, Value};
|
use cacao::defaults::{UserDefaults, Value};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
use cacao::ios::{
|
use cacao::uikit::{
|
||||||
App, AppDelegate, Scene, SceneConfig, SceneSession,
|
App, AppDelegate, Scene, SceneConfig, SceneSession,
|
||||||
SceneConnectionOptions, WindowSceneDelegate, Window
|
SceneConnectionOptions, WindowSceneDelegate, Window
|
||||||
};
|
};
|
||||||
|
|
|
@ -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).
|
- Start a simulator (Simulator.app).
|
||||||
- `cargo install cargo-bundle`
|
- `cargo install cargo-bundle`
|
||||||
- `cargo bundle --example ios-beta --target x86_64-apple-ios`
|
- `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`
|
- `xcrun simctl launch --console booted com.cacao.ios-test`
|
||||||
|
|
||||||
## Current Support
|
## Current Support
|
||||||
|
|
|
@ -5,9 +5,9 @@ use cacao::layout::{Layout, LayoutConstraint};
|
||||||
use cacao::input::{TextField, TextFieldDelegate};
|
use cacao::input::{TextField, TextFieldDelegate};
|
||||||
use cacao::view::View;
|
use cacao::view::View;
|
||||||
|
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::appkit::{App, AppDelegate};
|
||||||
use cacao::macos::menu::{Menu, MenuItem};
|
use cacao::appkit::menu::{Menu, MenuItem};
|
||||||
use cacao::macos::window::{Window, WindowConfig, WindowDelegate};
|
use cacao::appkit::window::{Window, WindowConfig, WindowDelegate};
|
||||||
|
|
||||||
struct BasicApp {
|
struct BasicApp {
|
||||||
window: Window<AppWindow>
|
window: Window<AppWindow>
|
||||||
|
@ -41,7 +41,6 @@ impl AppDelegate for BasicApp {
|
||||||
MenuItem::SelectAll
|
MenuItem::SelectAll
|
||||||
]),
|
]),
|
||||||
|
|
||||||
// Sidebar option is 11.0+ only.
|
|
||||||
Menu::new("View", vec![
|
Menu::new("View", vec![
|
||||||
MenuItem::EnterFullScreen
|
MenuItem::EnterFullScreen
|
||||||
]),
|
]),
|
||||||
|
@ -59,6 +58,10 @@ impl AppDelegate for BasicApp {
|
||||||
App::activate();
|
App::activate();
|
||||||
self.window.show();
|
self.window.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_terminate_after_last_window_closed(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Implements a window for adding a new Todo.
|
//! 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 cacao::view::ViewController;
|
||||||
|
|
||||||
use crate::storage::{dispatch_ui, Message};
|
use crate::storage::{dispatch_ui, Message};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Implements the start of the App lifecycle. Handles creating the required menu and window
|
//! Implements the start of the App lifecycle. Handles creating the required menu and window
|
||||||
//! components and message dispatching.
|
//! components and message dispatching.
|
||||||
|
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::appkit::{App, AppDelegate};
|
||||||
use cacao::notification_center::Dispatcher;
|
use cacao::notification_center::Dispatcher;
|
||||||
|
|
||||||
use crate::menu::menu;
|
use crate::menu::menu;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//!
|
//!
|
||||||
//! This may get extracted into a different repo some day in the future.
|
//! This may get extracted into a different repo some day in the future.
|
||||||
|
|
||||||
use cacao::macos::App;
|
use cacao::appkit::App;
|
||||||
|
|
||||||
mod add;
|
mod add;
|
||||||
mod app;
|
mod app;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//! Correctly functioning menus are a key part of what makes a macOS app feel right, though, so
|
//! 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.
|
//! 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};
|
use crate::storage::{dispatch_ui, Message};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Implements a stock-ish Preferences window.
|
//! Implements a stock-ish Preferences window.
|
||||||
|
|
||||||
use cacao::macos::window::{Window, WindowDelegate};
|
use cacao::appkit::window::{Window, WindowDelegate};
|
||||||
use cacao::macos::toolbar::Toolbar;
|
use cacao::appkit::toolbar::Toolbar;
|
||||||
use cacao::view::ViewController;
|
use cacao::view::ViewController;
|
||||||
|
|
||||||
use crate::storage::Message;
|
use crate::storage::Message;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Implements an example toolbar for a Preferences app. Could be cleaner, probably worth cleaning
|
//! Implements an example toolbar for a Preferences app. Could be cleaner, probably worth cleaning
|
||||||
//! up at some point.
|
//! 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 cacao::image::{Image, MacSystemIcon};
|
||||||
|
|
||||||
use crate::storage::{dispatch_ui, Message};
|
use crate::storage::{dispatch_ui, Message};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Messages that we used to thread control throughout the application.
|
//! Messages that we used to thread control throughout the application.
|
||||||
//! If you come from React/Redux, you can liken it to that world.
|
//! 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;
|
use crate::app::TodosApp;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! The main Todos window.
|
//! The main Todos window.
|
||||||
|
|
||||||
use cacao::macos::window::{Window, WindowDelegate};
|
use cacao::appkit::window::{Window, WindowDelegate};
|
||||||
use cacao::macos::toolbar::Toolbar;
|
use cacao::appkit::toolbar::Toolbar;
|
||||||
use cacao::view::ViewController;
|
use cacao::view::ViewController;
|
||||||
|
|
||||||
use crate::storage::Message;
|
use crate::storage::Message;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! The main Todos window toolbar. Contains a button to enable adding a new task.
|
//! The main Todos window toolbar. Contains a button to enable adding a new task.
|
||||||
|
|
||||||
use cacao::button::Button;
|
use cacao::button::Button;
|
||||||
use cacao::macos::toolbar::{
|
use cacao::appkit::toolbar::{
|
||||||
Toolbar, ToolbarDelegate, ToolbarItem,
|
Toolbar, ToolbarDelegate, ToolbarItem,
|
||||||
ToolbarDisplayMode, ItemIdentifier
|
ToolbarDisplayMode, ItemIdentifier
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use std::sync::RwLock;
|
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 cacao::notification_center::Dispatcher;
|
||||||
|
|
||||||
use crate::storage::Message;
|
use crate::storage::Message;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
//! This example showcases setting up a basic application and window.
|
//! This example showcases setting up a basic application and window.
|
||||||
|
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::appkit::{App, AppDelegate};
|
||||||
use cacao::macos::window::Window;
|
use cacao::appkit::menu::{Menu, MenuItem};
|
||||||
|
use cacao::appkit::window::Window;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct BasicApp {
|
struct BasicApp {
|
||||||
|
@ -10,12 +11,43 @@ struct BasicApp {
|
||||||
|
|
||||||
impl AppDelegate for BasicApp {
|
impl AppDelegate for BasicApp {
|
||||||
fn did_finish_launching(&self) {
|
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();
|
App::activate();
|
||||||
|
|
||||||
self.window.set_minimum_content_size(400., 400.);
|
self.window.set_minimum_content_size(400., 400.);
|
||||||
self.window.set_title("A Basic Window");
|
self.window.set_title("A Basic Window");
|
||||||
self.window.show();
|
self.window.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_terminate_after_last_window_closed(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
//!
|
//!
|
||||||
//! If you're not using that, you can probably get by fine with a standard `NSWindow`.
|
//! If you're not using that, you can probably get by fine with a standard `NSWindow`.
|
||||||
|
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::appkit::{App, AppDelegate};
|
||||||
use cacao::macos::window::{Window, WindowConfig, WindowController, WindowDelegate};
|
use cacao::appkit::menu::{Menu, MenuItem};
|
||||||
|
use cacao::appkit::window::{Window, WindowConfig, WindowController, WindowDelegate};
|
||||||
|
|
||||||
struct BasicApp {
|
struct BasicApp {
|
||||||
window: WindowController<MyWindow>
|
window: WindowController<MyWindow>
|
||||||
|
@ -13,10 +14,41 @@ struct BasicApp {
|
||||||
|
|
||||||
impl AppDelegate for BasicApp {
|
impl AppDelegate for BasicApp {
|
||||||
fn did_finish_launching(&self) {
|
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();
|
App::activate();
|
||||||
|
|
||||||
self.window.show();
|
self.window.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_terminate_after_last_window_closed(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
//! This example showcases setting up a basic application and window delegate.
|
//! This example showcases setting up a basic application and window delegate.
|
||||||
//! Window Delegate's give you lifecycle methods that you can respond to.
|
//! Window Delegate's give you lifecycle methods that you can respond to.
|
||||||
|
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::appkit::{App, AppDelegate};
|
||||||
use cacao::macos::window::{Window, WindowConfig, WindowDelegate};
|
use cacao::appkit::menu::{Menu, MenuItem};
|
||||||
|
use cacao::appkit::window::{Window, WindowConfig, WindowDelegate};
|
||||||
|
|
||||||
struct BasicApp {
|
struct BasicApp {
|
||||||
window: Window<MyWindow>
|
window: Window<MyWindow>
|
||||||
|
@ -10,9 +11,41 @@ struct BasicApp {
|
||||||
|
|
||||||
impl AppDelegate for BasicApp {
|
impl AppDelegate for BasicApp {
|
||||||
fn did_finish_launching(&self) {
|
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();
|
App::activate();
|
||||||
|
|
||||||
self.window.show();
|
self.window.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_terminate_after_last_window_closed(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! A wrapper for `NSAlert`.
|
//! 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
|
//! 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.
|
//! doesn't produce an amazing user experience, and you may want to shy away from using it.
|
||||||
//!
|
//!
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
//! `Sheet`.
|
//! `Sheet`.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use cacao::macos::{App, AppDelegate, Alert};
|
//! use cacao::appkit::{App, AppDelegate, Alert};
|
||||||
//!
|
//!
|
||||||
//! #[derive(Default)]
|
//! #[derive(Default)]
|
||||||
//! struct ExampleApp;
|
//! struct ExampleApp;
|
|
@ -15,8 +15,8 @@ use url::Url;
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::foundation::{id, nil, to_bool, BOOL, YES, NO, NSUInteger, NSArray, NSString};
|
use crate::foundation::{id, nil, to_bool, BOOL, YES, NO, NSUInteger, NSArray, NSString};
|
||||||
use crate::macos::app::{APP_PTR, AppDelegate};
|
use crate::appkit::app::{APP_PTR, AppDelegate};
|
||||||
use crate::macos::printing::PrintSettings;
|
use crate::appkit::printing::PrintSettings;
|
||||||
use crate::user_activity::UserActivity;
|
use crate::user_activity::UserActivity;
|
||||||
|
|
||||||
#[cfg(feature = "cloudkit")]
|
#[cfg(feature = "cloudkit")]
|
|
@ -45,7 +45,7 @@ use objc::{class, msg_send, sel, sel_impl};
|
||||||
|
|
||||||
use crate::foundation::{id, nil, YES, NO, NSUInteger, AutoReleasePool};
|
use crate::foundation::{id, nil, YES, NO, NSUInteger, AutoReleasePool};
|
||||||
use crate::invoker::TargetActionHandler;
|
use crate::invoker::TargetActionHandler;
|
||||||
use crate::macos::menu::Menu;
|
use crate::appkit::menu::Menu;
|
||||||
use crate::notification_center::Dispatcher;
|
use crate::notification_center::Dispatcher;
|
||||||
use crate::utils::activate_cocoa_multithreading;
|
use crate::utils::activate_cocoa_multithreading;
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ fn shared_application<F: Fn(id)>(handler: F) {
|
||||||
handler(app);
|
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
|
/// It holds (retains) a pointer to the Objective-C runtime shared application object, as well as
|
||||||
/// handles setting up a few necessary pieces:
|
/// handles setting up a few necessary pieces:
|
|
@ -6,10 +6,10 @@ use url::Url;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::user_activity::UserActivity;
|
use crate::user_activity::UserActivity;
|
||||||
|
|
||||||
use crate::macos::app::enums::TerminateResponse;
|
use crate::appkit::app::enums::TerminateResponse;
|
||||||
use crate::macos::menu::Menu;
|
use crate::appkit::menu::Menu;
|
||||||
use crate::macos::printing::enums::PrintResponse;
|
use crate::appkit::printing::enums::PrintResponse;
|
||||||
use crate::macos::printing::settings::PrintSettings;
|
use crate::appkit::printing::settings::PrintSettings;
|
||||||
|
|
||||||
#[cfg(feature = "cloudkit")]
|
#[cfg(feature = "cloudkit")]
|
||||||
use crate::cloudkit::share::CKShareMetaData;
|
use crate::cloudkit::share::CKShareMetaData;
|
|
@ -3,7 +3,6 @@
|
||||||
use crate::foundation::{NSUInteger};
|
use crate::foundation::{NSUInteger};
|
||||||
|
|
||||||
/// Used to set whether and/or how a view or cell draws a focus ring.
|
/// Used to set whether and/or how a view or cell draws a focus ring.
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum FocusRingType {
|
pub enum FocusRingType {
|
||||||
/// Whatever the default is.
|
/// Whatever the default is.
|
||||||
|
@ -20,7 +19,6 @@ pub enum FocusRingType {
|
||||||
Unknown(NSUInteger)
|
Unknown(NSUInteger)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
impl From<FocusRingType> for NSUInteger {
|
impl From<FocusRingType> for NSUInteger {
|
||||||
fn from(ring_type: FocusRingType) -> Self {
|
fn from(ring_type: FocusRingType) -> Self {
|
||||||
match ring_type {
|
match ring_type {
|
|
@ -7,7 +7,7 @@ use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel, sel_impl};
|
||||||
|
|
||||||
use crate::foundation::{id, NSInteger, NSString};
|
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
|
/// A struct that represents an `NSMenu`. It takes ownership of items, and handles instrumenting
|
||||||
/// them throughout the application lifecycle.
|
/// them throughout the application lifecycle.
|
|
@ -7,7 +7,7 @@ use objc::runtime::{Class, Object, Sel};
|
||||||
use objc::{class, sel, sel_impl, msg_send};
|
use objc::{class, sel, sel_impl, msg_send};
|
||||||
|
|
||||||
use crate::foundation::{load_or_register_class, id, BOOL, NSArray, NSString};
|
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;
|
use crate::utils::load;
|
||||||
|
|
||||||
/// Retrieves and passes the allowed item identifiers for this toolbar.
|
/// Retrieves and passes the allowed item identifiers for this toolbar.
|
|
@ -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".
|
//! that makes it feel... "proper".
|
||||||
//!
|
//!
|
||||||
//! UNFORTUNATELY, this is a very old and janky API. So... yeah.
|
//! UNFORTUNATELY, this is a very old and janky API. So... yeah.
|
|
@ -2,7 +2,7 @@
|
||||||
//! go. Currently a bit incomplete in that we don't support the customizing workflow, but feel free
|
//! go. Currently a bit incomplete in that we don't support the customizing workflow, but feel free
|
||||||
//! to pull request it.
|
//! 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`.
|
/// A trait that you can implement to have your struct/etc act as an `NSToolbarDelegate`.
|
||||||
pub trait ToolbarDelegate {
|
pub trait ToolbarDelegate {
|
|
@ -11,7 +11,7 @@ use objc::{class, sel, sel_impl};
|
||||||
|
|
||||||
use crate::foundation::{load_or_register_class, id, BOOL, YES, NO, NSUInteger};
|
use crate::foundation::{load_or_register_class, id, BOOL, YES, NO, NSUInteger};
|
||||||
use crate::utils::{load, CGSize};
|
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.
|
/// Called when an `NSWindowDelegate` receives a `windowWillClose:` event.
|
||||||
/// Good place to clean up memory and what not.
|
/// Good place to clean up memory and what not.
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use crate::foundation::NSUInteger;
|
use crate::foundation::NSUInteger;
|
||||||
use crate::geometry::Rect;
|
use crate::geometry::Rect;
|
||||||
use crate::macos::window::enums::{WindowStyle, WindowToolbarStyle};
|
use crate::appkit::window::enums::{WindowStyle, WindowToolbarStyle};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct WindowConfig {
|
pub struct WindowConfig {
|
|
@ -7,7 +7,7 @@ use objc::declare::ClassDecl;
|
||||||
use objc::runtime::Class;
|
use objc::runtime::Class;
|
||||||
use objc::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
|
/// Injects an `NSWindowController` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
|
@ -12,8 +12,8 @@
|
||||||
//! # How to use
|
//! # How to use
|
||||||
//!
|
//!
|
||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! use cacao::macos::app::AppDelegate;
|
//! use cacao::appkit::app::AppDelegate;
|
||||||
//! use cacao::macos::window::{WindowController, WindowDelegate};
|
//! use cacao::appkit::window::{WindowController, WindowDelegate};
|
||||||
//!
|
//!
|
||||||
//! #[derive(Default)]
|
//! #[derive(Default)]
|
||||||
//! struct MyWindow;
|
//! struct MyWindow;
|
||||||
|
@ -35,7 +35,7 @@ use objc_id::Id;
|
||||||
|
|
||||||
use crate::foundation::{id, nil};
|
use crate::foundation::{id, nil};
|
||||||
use crate::utils::Controller;
|
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;
|
mod class;
|
||||||
use class::register_window_controller_class;
|
use class::register_window_controller_class;
|
|
@ -20,7 +20,7 @@ use objc_id::ShareId;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::foundation::{id, nil, to_bool, YES, NO, NSString, NSInteger, NSUInteger};
|
use crate::foundation::{id, nil, to_bool, YES, NO, NSString, NSInteger, NSUInteger};
|
||||||
use crate::layout::traits::Layout;
|
use crate::layout::traits::Layout;
|
||||||
use crate::macos::toolbar::{Toolbar, ToolbarDelegate};
|
use crate::appkit::toolbar::{Toolbar, ToolbarDelegate};
|
||||||
use crate::utils::{os, Controller};
|
use crate::utils::{os, Controller};
|
||||||
|
|
||||||
mod class;
|
mod class;
|
|
@ -2,8 +2,8 @@
|
||||||
//! module. There's a few different ones, and it's just... cleaner, if
|
//! module. There's a few different ones, and it's just... cleaner, if
|
||||||
//! it's organized here.
|
//! it's organized here.
|
||||||
|
|
||||||
use crate::macos::app::PresentationOption;
|
use crate::appkit::app::PresentationOption;
|
||||||
use crate::macos::window::Window;
|
use crate::appkit::window::Window;
|
||||||
|
|
||||||
/// Lifecycle events for anything that `impl Window`'s. These map to the standard Cocoa
|
/// 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
|
/// lifecycle methods, but mix in a few extra things to handle offering configuration tools
|
|
@ -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
|
/// Represents a bezel style for a button. This is a macOS-specific control, and has no effect
|
||||||
/// under iOS or tvOS.
|
/// under iOS or tvOS.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum BezelStyle {
|
pub enum BezelStyle {
|
||||||
/// A standard circular button.
|
/// A standard circular button.
|
||||||
|
@ -49,7 +49,7 @@ pub enum BezelStyle {
|
||||||
Unknown(NSUInteger)
|
Unknown(NSUInteger)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
impl From<BezelStyle> for NSUInteger {
|
impl From<BezelStyle> for NSUInteger {
|
||||||
fn from(style: BezelStyle) -> Self {
|
fn from(style: BezelStyle) -> Self {
|
||||||
match style {
|
match style {
|
||||||
|
@ -71,7 +71,7 @@ impl From<BezelStyle> for NSUInteger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
impl From<NSUInteger> for BezelStyle {
|
impl From<NSUInteger> for BezelStyle {
|
||||||
fn from(i: NSUInteger) -> Self {
|
fn from(i: NSUInteger) -> Self {
|
||||||
match i {
|
match i {
|
||||||
|
|
|
@ -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
|
//! 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.
|
//! 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::text::{AttributedString, Font};
|
||||||
use crate::utils::{load, properties::ObjcProperty};
|
use crate::utils::{load, properties::ObjcProperty};
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use crate::macos::FocusRingType;
|
use crate::appkit::FocusRingType;
|
||||||
|
|
||||||
mod enums;
|
mod enums;
|
||||||
pub use 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
|
/// 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.
|
/// 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);
|
self.image = Some(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the bezel style for this button. Only supported on macOS.
|
/// Sets the bezel style for this button. Only supported on appkit.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub fn set_bezel_style(&self, bezel_style: BezelStyle) {
|
pub fn set_bezel_style(&self, bezel_style: BezelStyle) {
|
||||||
let style: NSUInteger = bezel_style.into();
|
let style: NSUInteger = bezel_style.into();
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ impl Button {
|
||||||
pub fn set_background_color<C: AsRef<Color>>(&self, color: C) {
|
pub fn set_background_color<C: AsRef<Color>>(&self, color: C) {
|
||||||
let color: id = color.as_ref().into();
|
let color: id = color.as_ref().into();
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let cell: id = msg_send![obj, cell];
|
let cell: id = msg_send![obj, cell];
|
||||||
let _: () = msg_send![cell, setBackgroundColor:color];
|
let _: () = msg_send![cell, setBackgroundColor:color];
|
||||||
|
@ -186,9 +186,9 @@ impl Button {
|
||||||
|
|
||||||
/// Sets the text color for this 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) {
|
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 {
|
self.objc.with_mut(move |obj| unsafe {
|
||||||
let text: id = msg_send![obj, attributedTitle];
|
let text: id = msg_send![obj, attributedTitle];
|
||||||
let len: isize = msg_send![text, length];
|
let len: isize = msg_send![text, length];
|
||||||
|
@ -201,8 +201,8 @@ impl Button {
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO: Figure out how to handle oddities like this.
|
// @TODO: Figure out how to handle oddities like this.
|
||||||
/// For buttons on macOS, one might need to disable the border. This does that.
|
/// For buttons on appkit, one might need to disable the border. This does that.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub fn set_bordered(&self, is_bordered: bool) {
|
pub fn set_bordered(&self, is_bordered: bool) {
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let _: () = msg_send![obj, setBordered:match is_bordered {
|
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.
|
/// Sets how the control should draw a focus ring when a user is focused on it.
|
||||||
///
|
///
|
||||||
/// This is a macOS-only method.
|
/// This is an appkit-only method.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub fn set_focus_ring_type(&self, focus_ring_type: FocusRingType) {
|
pub fn set_focus_ring_type(&self, focus_ring_type: FocusRingType) {
|
||||||
let ring_type: NSUInteger = focus_ring_type.into();
|
let ring_type: NSUInteger = focus_ring_type.into();
|
||||||
|
|
||||||
|
|
|
@ -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_NORMAL_CONTRAST: &'static str = "AQUA_DARK_COLOR_NORMAL_CONTRAST";
|
||||||
pub(crate) const AQUA_DARK_COLOR_HIGH_CONTRAST: &'static str = "AQUA_DARK_COLOR_HIGH_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" {
|
extern "C" {
|
||||||
static NSAppearanceNameAqua: id;
|
static NSAppearanceNameAqua: id;
|
||||||
static NSAppearanceNameAccessibilityHighContrastAqua: 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
|
/// 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.
|
/// 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.
|
/// Pull requests to implement that check would be welcome.
|
||||||
fn get_effective_color(this: &Object) -> id {
|
fn get_effective_color(this: &Object) -> id {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
if os::is_minimum_semversion(10, 14, 0) {
|
if os::is_minimum_semversion(10, 14, 0) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut appearance: id = msg_send![class!(NSAppearance), currentAppearance];
|
let mut appearance: id = msg_send![class!(NSAppearance), currentAppearance];
|
|
@ -26,11 +26,11 @@ use objc_id::Id;
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
use crate::utils::os;
|
use crate::utils::os;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
mod macos_dynamic_color;
|
mod appkit_dynamic_color;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use macos_dynamic_color::{
|
use appkit_dynamic_color::{
|
||||||
AQUA_LIGHT_COLOR_NORMAL_CONTRAST, AQUA_LIGHT_COLOR_HIGH_CONTRAST,
|
AQUA_LIGHT_COLOR_NORMAL_CONTRAST, AQUA_LIGHT_COLOR_HIGH_CONTRAST,
|
||||||
AQUA_DARK_COLOR_NORMAL_CONTRAST, AQUA_DARK_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.
|
/// default to the `Light` theme.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Theme {
|
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.
|
/// On iOS and tvOS, this is whatever you call the system defined theme.
|
||||||
Light,
|
Light,
|
||||||
|
|
||||||
|
@ -230,11 +230,11 @@ pub enum Color {
|
||||||
LightText,
|
LightText,
|
||||||
|
|
||||||
/// The background color for a given window in the system theme.
|
/// The background color for a given window in the system theme.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
MacOSWindowBackgroundColor,
|
MacOSWindowBackgroundColor,
|
||||||
|
|
||||||
/// The background color that should appear under a page per the system theme.
|
/// The background color that should appear under a page per the system theme.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
MacOSUnderPageBackgroundColor
|
MacOSUnderPageBackgroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,10 +248,10 @@ impl Color {
|
||||||
let a = alpha as CGFloat / 255.0;
|
let a = alpha as CGFloat / 255.0;
|
||||||
|
|
||||||
Color::Custom(Arc::new(RwLock::new(unsafe {
|
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]) }
|
{ 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]) }
|
{ 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;
|
let a = alpha as CGFloat / 255.0;
|
||||||
|
|
||||||
Color::Custom(Arc::new(RwLock::new(unsafe {
|
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]) }
|
{ 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]) }
|
{ Id::from_ptr(msg_send![class!(UIColor), colorWithHue:h saturation:s brightness:b alpha:a]) }
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -289,10 +289,10 @@ impl Color {
|
||||||
/// specified alpha.
|
/// specified alpha.
|
||||||
pub fn white_alpha(level: CGFloat, alpha: CGFloat) -> Self {
|
pub fn white_alpha(level: CGFloat, alpha: CGFloat) -> Self {
|
||||||
Color::Custom(Arc::new(RwLock::new(unsafe {
|
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]) }
|
{ 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]) }
|
{ Id::from_ptr(msg_send![class!(UIColor), colorWithWhite:level alpha:alpha]) }
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -319,6 +319,7 @@ impl Color {
|
||||||
Color::hexa(hex, 255)
|
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
|
/// 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
|
/// colors at appearance time based on device traits (i.e, dark mode vs light mode, contrast
|
||||||
/// settings, etc).
|
/// settings, etc).
|
||||||
|
@ -327,7 +328,7 @@ impl Color {
|
||||||
/// "default" or "light" color.
|
/// "default" or "light" color.
|
||||||
///
|
///
|
||||||
/// Returning a dynamic color in your handler is unsupported and may panic.
|
/// 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
|
pub fn dynamic<F>(handler: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(Style) -> Color + 'static
|
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
|
// 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
|
// am happy to do this for now and let someone who needs true dynamic allocation look into
|
||||||
// it and PR it.
|
// it and PR it.
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
Color::Custom(Arc::new(RwLock::new(unsafe {
|
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, {
|
(&mut *color).set_ivar(AQUA_LIGHT_COLOR_NORMAL_CONTRAST, {
|
||||||
let color: id = handler(Style {
|
let color: id = handler(Style {
|
||||||
|
@ -421,7 +421,7 @@ impl From<&Color> for id {
|
||||||
/// Handles color fallback for system-provided colors.
|
/// Handles color fallback for system-provided colors.
|
||||||
macro_rules! system_color_with_fallback {
|
macro_rules! system_color_with_fallback {
|
||||||
($class:ident, $color:ident, $fallback:ident) => ({
|
($class:ident, $color:ident, $fallback:ident) => ({
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
{
|
{
|
||||||
#[cfg(feature = "color-fallbacks")]
|
#[cfg(feature = "color-fallbacks")]
|
||||||
if os::minimum_semversion(10, 10, 0) {
|
if os::minimum_semversion(10, 10, 0) {
|
||||||
|
@ -434,7 +434,7 @@ macro_rules! system_color_with_fallback {
|
||||||
msg_send![$class, $color]
|
msg_send![$class, $color]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
{
|
{
|
||||||
msg_send![$class, $color]
|
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
|
/// 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.
|
/// an important piece. It's not on the framework to make your app look good, though.
|
||||||
unsafe fn to_objc(obj: &Color) -> id {
|
unsafe fn to_objc(obj: &Color) -> id {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let color = class!(NSColor);
|
let color = class!(NSColor);
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
let color = class!(UIColor);
|
let color = class!(UIColor);
|
||||||
|
|
||||||
match obj {
|
match obj {
|
||||||
|
@ -500,10 +500,10 @@ unsafe fn to_objc(obj: &Color) -> id {
|
||||||
Color::DarkText => system_color_with_fallback!(color, darkTextColor, blackColor),
|
Color::DarkText => system_color_with_fallback!(color, darkTextColor, blackColor),
|
||||||
Color::LightText => system_color_with_fallback!(color, lightTextColor, whiteColor),
|
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),
|
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),
|
Color::MacOSUnderPageBackgroundColor => system_color_with_fallback!(color, underPageBackgroundColor, clearColor),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ use objc_id::ShareId;
|
||||||
use crate::foundation::{id, YES, NO, NSInteger, NSString};
|
use crate::foundation::{id, YES, NO, NSInteger, NSString};
|
||||||
use crate::filesystem::enums::ModalResponse;
|
use crate::filesystem::enums::ModalResponse;
|
||||||
|
|
||||||
use crate::macos::window::{Window, WindowDelegate};
|
#[cfg(feature = "appkit")]
|
||||||
|
use crate::appkit::window::{Window, WindowDelegate};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FileSelectPanel {
|
pub struct FileSelectPanel {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/// These icons are system-provided icons that are guaranteed to exist in all versions of macOS
|
/// 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
|
/// that Cacao supports. These will use SFSymbols on Big Sur and onwards (11.0+), and the correct
|
||||||
/// controls for prior macOS versions.
|
/// controls for prior macOS versions.
|
||||||
|
|
|
@ -118,7 +118,7 @@ pub struct DrawConfig {
|
||||||
pub resize: ResizeBehavior
|
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.
|
/// and so on.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Image(pub ShareId<Object>);
|
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
|
/// Returns a stock system icon. These are guaranteed to exist across all versions of macOS
|
||||||
/// supported.
|
/// supported.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
|
|
@ -7,16 +7,16 @@ use crate::color::Color;
|
||||||
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
|
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
|
||||||
use crate::utils::properties::ObjcProperty;
|
use crate::utils::properties::ObjcProperty;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
mod macos;
|
mod appkit;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use macos::register_image_view_class;
|
use appkit::register_image_view_class;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
mod ios;
|
mod uikit;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
use ios::register_image_view_class;
|
use ios::register_image_view_class;
|
||||||
|
|
||||||
mod image;
|
mod image;
|
||||||
|
@ -31,7 +31,7 @@ fn allocate_view(registration_fn: fn() -> *const Class) -> id {
|
||||||
let view: id = msg_send![registration_fn(), new];
|
let view: id = msg_send![registration_fn(), new];
|
||||||
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let _: () = msg_send![view, setWantsLayer:YES];
|
let _: () = msg_send![view, setWantsLayer:YES];
|
||||||
|
|
||||||
view
|
view
|
||||||
|
|
|
@ -50,17 +50,17 @@ use crate::layout::{Layout, LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY}
|
||||||
use crate::text::{Font, TextAlign};
|
use crate::text::{Font, TextAlign};
|
||||||
use crate::utils::properties::ObjcProperty;
|
use crate::utils::properties::ObjcProperty;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
mod macos;
|
mod appkit;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use macos::{register_view_class, register_view_class_with_delegate};
|
use appkit::{register_view_class, register_view_class_with_delegate};
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
mod ios;
|
mod uikit;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
use ios::{register_view_class, register_view_class_with_delegate};
|
use uikit::{register_view_class, register_view_class_with_delegate};
|
||||||
|
|
||||||
mod traits;
|
mod traits;
|
||||||
pub use traits::TextFieldDelegate;
|
pub use traits::TextFieldDelegate;
|
||||||
|
@ -74,7 +74,7 @@ fn common_init(class: *const Class) -> id {
|
||||||
|
|
||||||
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints: NO];
|
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints: NO];
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let _: () = msg_send![view, setWantsLayer: YES];
|
let _: () = msg_send![view, setWantsLayer: YES];
|
||||||
|
|
||||||
view
|
view
|
||||||
|
|
|
@ -10,7 +10,7 @@ use objc_id::ShareId;
|
||||||
use crate::foundation::{id, nil, to_bool, YES, NO, NSArray, NSString};
|
use crate::foundation::{id, nil, to_bool, YES, NO, NSArray, NSString};
|
||||||
use crate::geometry::Rect;
|
use crate::geometry::Rect;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use crate::pasteboard::PasteboardType;
|
use crate::pasteboard::PasteboardType;
|
||||||
|
|
||||||
/// A trait that view wrappers must conform to. Enables managing the subview tree.
|
/// 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.
|
/// 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 {
|
fn is_hidden_or_ancestor_is_hidden(&self) -> bool {
|
||||||
self.get_from_backing_node(|obj| {
|
self.get_from_backing_node(|obj| {
|
||||||
to_bool(unsafe {
|
to_bool(unsafe {
|
||||||
|
@ -115,7 +115,10 @@ pub trait Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register this view for drag and drop operations.
|
/// 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]) {
|
fn register_for_dragged_types(&self, types: &[PasteboardType]) {
|
||||||
let types: NSArray = types.into_iter().map(|t| {
|
let types: NSArray = types.into_iter().map(|t| {
|
||||||
let x: NSString = (*t).into();
|
let x: NSString = (*t).into();
|
||||||
|
@ -128,7 +131,10 @@ pub trait Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unregisters this as a target for drag and drop operations.
|
/// 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) {
|
fn unregister_dragged_types(&self) {
|
||||||
self.with_backing_node(|obj| unsafe {
|
self.with_backing_node(|obj| unsafe {
|
||||||
let _: () = msg_send![obj, unregisterDraggedTypes];
|
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
|
/// If you have a high performance tableview or collectionview that has issues, disabling these
|
||||||
/// can be helpful - but always test!
|
/// can be helpful - but always test!
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
fn set_posts_frame_change_notifications(&self, posts: bool) {
|
fn set_posts_frame_change_notifications(&self, posts: bool) {
|
||||||
self.with_backing_node(|obj| unsafe {
|
self.with_backing_node(|obj| unsafe {
|
||||||
let _: () = msg_send![obj, setPostsFrameChangedNotifications:match posts {
|
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
|
/// If you have a high performance tableview or collectionview that has issues, disabling these
|
||||||
/// can be helpful - but always test!
|
/// can be helpful - but always test!
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
fn set_posts_bounds_change_notifications(&self, posts: bool) {
|
fn set_posts_bounds_change_notifications(&self, posts: bool) {
|
||||||
self.with_backing_node(|obj| unsafe {
|
self.with_backing_node(|obj| unsafe {
|
||||||
let _: () = msg_send![obj, setPostsBoundsChangedNotifications:match posts {
|
let _: () = msg_send![obj, setPostsBoundsChangedNotifications:match posts {
|
||||||
|
|
56
src/lib.rs
56
src/lib.rs
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
//! # Cacao
|
//! # 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
|
//! 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
|
//! 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.
|
//! creative coding and assumptions can get us pretty far.
|
||||||
|
@ -28,8 +28,8 @@
|
||||||
//! # Hello World
|
//! # Hello World
|
||||||
//!
|
//!
|
||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! use cacao::macos::app::{App, AppDelegate};
|
//! use cacao::appkit::app::{App, AppDelegate};
|
||||||
//! use cacao::macos::window::Window;
|
//! use cacao::appkit::window::Window;
|
||||||
//!
|
//!
|
||||||
//! #[derive(Default)]
|
//! #[derive(Default)]
|
||||||
//! struct BasicApp {
|
//! struct BasicApp {
|
||||||
|
@ -59,9 +59,9 @@
|
||||||
//! Note that, in order for this framework to be useful, you must always elect one of the following
|
//! Note that, in order for this framework to be useful, you must always elect one of the following
|
||||||
//! features:
|
//! features:
|
||||||
//!
|
//!
|
||||||
//! - `macos`: Implements macOS-specific APIs (menus, toolbars, windowing, and so on).
|
//! - `appkit`: Implements appkit-specific APIs (menus, toolbars, windowing, and so on).
|
||||||
//! - `ios`: Implements iOS-specific APIs (scenes, navigation controllers, and so on).
|
//! - `uikit`: Implements uikit-specific APIs (scenes, navigation controllers, and so on).
|
||||||
//! - `tvos`: Implements tvOS-specific APIs. Currently barely implemented.
|
//! - `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
|
//! 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
|
//! 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
|
//! - `quicklook`: Links `QuickLook.framework` and offers methods for generating preview images for
|
||||||
//! files.
|
//! files.
|
||||||
//! - `user-notifications`: Links `UserNotifications.framework` and provides functionality for
|
//! - `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.
|
//! code-signed, and will not work without it.
|
||||||
//! - `webview`: Links `WebKit.framework` and provides a `WebView` control backed by `WKWebView`.
|
//! - `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 will not be supported on tvOS, as the platform has no webview control.
|
||||||
//! - `webview-downloading-macos`: Enables downloading files from the `WebView` via a private
|
//! - `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
|
//! 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).
|
//! (there's no web browser there at all).
|
||||||
//!
|
//!
|
||||||
//! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section
|
//! [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 url;
|
||||||
pub use lazy_static;
|
pub use lazy_static;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
|
#[cfg_attr(docsrs, doc(cfg(target_os = "appkit")))]
|
||||||
pub mod macos;
|
pub mod appkit;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(target_os = "ios")))]
|
#[cfg_attr(docsrs, doc(cfg(target_os = "uikit")))]
|
||||||
pub mod ios;
|
pub mod uikit;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod button;
|
pub mod button;
|
||||||
|
|
||||||
#[cfg(any(feature = "cloudkit", doc))]
|
#[cfg(any(feature = "cloudkit", doc))]
|
||||||
|
@ -113,50 +113,50 @@ pub mod cloudkit;
|
||||||
|
|
||||||
pub mod color;
|
pub mod color;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod dragdrop;
|
pub mod dragdrop;
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod events;
|
pub mod events;
|
||||||
|
|
||||||
pub mod defaults;
|
pub mod defaults;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod filesystem;
|
pub mod filesystem;
|
||||||
|
|
||||||
pub mod foundation;
|
pub mod foundation;
|
||||||
pub mod geometry;
|
pub mod geometry;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod image;
|
pub mod image;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod input;
|
pub mod input;
|
||||||
|
|
||||||
pub mod layer;
|
pub mod layer;
|
||||||
pub(crate) mod invoker;
|
pub(crate) mod invoker;
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod listview;
|
pub mod listview;
|
||||||
pub mod networking;
|
pub mod networking;
|
||||||
pub mod notification_center;
|
pub mod notification_center;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod pasteboard;
|
pub mod pasteboard;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod progress;
|
pub mod progress;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod scrollview;
|
pub mod scrollview;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod switch;
|
pub mod switch;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
|
||||||
#[cfg(feature = "quicklook")]
|
#[cfg(feature = "quicklook")]
|
||||||
|
|
|
@ -14,7 +14,7 @@ use objc::runtime::{Class, Object, Sel, BOOL};
|
||||||
use objc::{class, sel, sel_impl, msg_send};
|
use objc::{class, sel, sel_impl, msg_send};
|
||||||
use objc_id::Id;
|
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::foundation::{load_or_register_class, id, nil, YES, NO, NSArray, NSInteger, NSUInteger};
|
||||||
use crate::dragdrop::DragInfo;
|
use crate::dragdrop::DragInfo;
|
||||||
use crate::listview::{
|
use crate::listview::{
|
|
@ -56,20 +56,20 @@ use crate::utils::{os, CellFactory, CGSize};
|
||||||
use crate::utils::properties::{ObjcProperty, PropertyNullable};
|
use crate::utils::properties::{ObjcProperty, PropertyNullable};
|
||||||
use crate::view::ViewDelegate;
|
use crate::view::ViewDelegate;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use crate::macos::menu::MenuItem;
|
use crate::appkit::menu::MenuItem;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
mod macos;
|
mod appkit;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use macos::{register_listview_class, register_listview_class_with_delegate};
|
use appkit::{register_listview_class, register_listview_class_with_delegate};
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
//#[cfg(target_os = "ios")]
|
||||||
mod ios;
|
//mod ios;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
//#[cfg(target_os = "ios")]
|
||||||
use ios::{register_view_class, register_view_class_with_delegate};
|
//use ios::{register_view_class, register_view_class_with_delegate};
|
||||||
|
|
||||||
mod enums;
|
mod enums;
|
||||||
pub use enums::{RowAnimation, RowEdge};
|
pub use enums::{RowAnimation, RowEdge};
|
||||||
|
@ -98,7 +98,7 @@ fn common_init(class: *const Class) -> id {
|
||||||
let _: () = msg_send![tableview, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
let _: () = msg_send![tableview, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||||
|
|
||||||
// Let's... make NSTableView into UITableView-ish.
|
// Let's... make NSTableView into UITableView-ish.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
{
|
{
|
||||||
// @TODO: Clean this up in a dealloc method.
|
// @TODO: Clean this up in a dealloc method.
|
||||||
let menu: id = msg_send![class!(NSMenu), new];
|
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.
|
/// A pointer to the Objective-C runtime view controller.
|
||||||
pub objc: ObjcProperty,
|
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...
|
/// more old school like that...
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub scrollview: ScrollView,
|
pub scrollview: ScrollView,
|
||||||
|
|
||||||
/// A pointer to the delegate for this view.
|
/// A pointer to the delegate for this view.
|
||||||
|
@ -188,7 +188,7 @@ impl ListView {
|
||||||
let class = register_listview_class();
|
let class = register_listview_class();
|
||||||
let view = common_init(class);
|
let view = common_init(class);
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let scrollview = {
|
let scrollview = {
|
||||||
let sview = ScrollView::new();
|
let sview = ScrollView::new();
|
||||||
|
|
||||||
|
@ -199,9 +199,9 @@ impl ListView {
|
||||||
sview
|
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.
|
// @TODO: Fix this with proper mutable access.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let anchor_view: id = scrollview.objc.get(|obj| unsafe {
|
let anchor_view: id = scrollview.objc.get(|obj| unsafe {
|
||||||
msg_send![obj, self]
|
msg_send![obj, self]
|
||||||
});
|
});
|
||||||
|
@ -225,7 +225,7 @@ impl ListView {
|
||||||
center_y: LayoutAnchorY::center(anchor_view),
|
center_y: LayoutAnchorY::center(anchor_view),
|
||||||
objc: ObjcProperty::retain(view),
|
objc: ObjcProperty::retain(view),
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
scrollview: scrollview
|
scrollview: scrollview
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ impl<T> ListView<T> where T: ListViewDelegate + 'static {
|
||||||
let _: () = msg_send![view, setDataSource:view];
|
let _: () = msg_send![view, setDataSource:view];
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let scrollview = {
|
let scrollview = {
|
||||||
let sview = ScrollView::new();
|
let sview = ScrollView::new();
|
||||||
|
|
||||||
|
@ -260,14 +260,14 @@ impl<T> ListView<T> where T: ListViewDelegate + 'static {
|
||||||
sview
|
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.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let anchor_view: id = scrollview.objc.get(|obj| unsafe {
|
let anchor_view: id = scrollview.objc.get(|obj| unsafe {
|
||||||
msg_send![obj, self]
|
msg_send![obj, self]
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
//#[cfg(feature = "uikit")]
|
||||||
let anchor_view = view;
|
//let anchor_view = view;
|
||||||
|
|
||||||
let mut view = ListView {
|
let mut view = ListView {
|
||||||
cell_factory: cell,
|
cell_factory: cell,
|
||||||
|
@ -285,7 +285,7 @@ impl<T> ListView<T> where T: ListViewDelegate + 'static {
|
||||||
center_y: LayoutAnchorY::center(anchor_view),
|
center_y: LayoutAnchorY::center(anchor_view),
|
||||||
objc: ObjcProperty::retain(view),
|
objc: ObjcProperty::retain(view),
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
scrollview: scrollview
|
scrollview: scrollview
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ impl<T> ListView<T> {
|
||||||
center_y: self.center_y.clone(),
|
center_y: self.center_y.clone(),
|
||||||
objc: self.objc.clone(),
|
objc: self.objc.clone(),
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
scrollview: self.scrollview.clone_as_handle()
|
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.
|
/// 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> {
|
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 key = NSString::new(identifier);
|
||||||
let cell: id = self.objc.get(|obj| unsafe {
|
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
|
/// Sets the style for the underlying NSTableView. This property is only supported on macOS
|
||||||
/// 11.0+, and will always be `FullWidth` on anything older.
|
/// 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) {
|
pub fn set_style(&self, style: crate::foundation::NSInteger) {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
if os::is_minimum_version(11) {
|
if os::is_minimum_version(11) {
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let _: () = msg_send![obj, setStyle:style];
|
let _: () = msg_send![obj, setStyle:style];
|
||||||
|
@ -375,10 +378,10 @@ impl<T> ListView<T> {
|
||||||
|
|
||||||
/// Set whether this control can appear with no row selected.
|
/// 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
|
/// `false`. This can be particularly useful when implementing a Source List style sidebar
|
||||||
/// view for navigation purposes.
|
/// view for navigation purposes.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub fn set_allows_empty_selection(&self, allows: bool) {
|
pub fn set_allows_empty_selection(&self, allows: bool) {
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let _: () = msg_send![obj, setAllowsEmptySelection:match allows {
|
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) {
|
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.
|
// 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 {
|
self.objc.get(|obj| unsafe {
|
||||||
let _: () = msg_send![obj, beginUpdates];
|
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
|
/// rows at once, you should also run this inside a `perform_batch_updates` call, as that will
|
||||||
/// optimize things accordingly.
|
/// optimize things accordingly.
|
||||||
pub fn insert_rows(&self, indexes: &[usize], animation: RowAnimation) {
|
pub fn insert_rows(&self, indexes: &[usize], animation: RowAnimation) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
unsafe {
|
unsafe {
|
||||||
let index_set: id = msg_send![class!(NSMutableIndexSet), new];
|
let index_set: id = msg_send![class!(NSMutableIndexSet), new];
|
||||||
|
|
||||||
|
@ -476,7 +479,7 @@ impl<T> ListView<T> {
|
||||||
|
|
||||||
/// Reload the rows at the specified indexes.
|
/// Reload the rows at the specified indexes.
|
||||||
pub fn reload_rows(&self, indexes: &[usize]) {
|
pub fn reload_rows(&self, indexes: &[usize]) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
unsafe {
|
unsafe {
|
||||||
let index_set: id = msg_send![class!(NSMutableIndexSet), new];
|
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
|
/// rows at once, you should also run this inside a `perform_batch_updates` call, as that will
|
||||||
/// optimize things accordingly.
|
/// optimize things accordingly.
|
||||||
pub fn remove_rows(&self, indexes: &[usize], animations: RowAnimation) {
|
pub fn remove_rows(&self, indexes: &[usize], animations: RowAnimation) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
unsafe {
|
unsafe {
|
||||||
let index_set: id = msg_send![class!(NSMutableIndexSet), new];
|
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.
|
/// It can make some scrolling situations much smoother.
|
||||||
pub fn set_uses_automatic_row_heights(&self, uses: bool) {
|
pub fn set_uses_automatic_row_heights(&self, uses: bool) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let _: () = msg_send![obj, setUsesAutomaticRowHeights:match uses {
|
let _: () = msg_send![obj, setUsesAutomaticRowHeights:match uses {
|
||||||
true => YES,
|
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
|
/// background colors automatically. If you set this, you possibly want
|
||||||
/// to hard-set a row height as well.
|
/// to hard-set a row height as well.
|
||||||
pub fn set_uses_alternating_backgrounds(&self, uses: bool) {
|
pub fn set_uses_alternating_backgrounds(&self, uses: bool) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let _: () = msg_send![obj, setUsesAlternatingRowBackgroundColors:match uses {
|
let _: () = msg_send![obj, setUsesAlternatingRowBackgroundColors:match uses {
|
||||||
true => YES,
|
true => YES,
|
||||||
|
@ -561,7 +564,7 @@ impl<T> ListView<T> {
|
||||||
|
|
||||||
/// End actions for a row. API subject to change.
|
/// End actions for a row. API subject to change.
|
||||||
pub fn set_row_actions_visible(&self, visible: bool) {
|
pub fn set_row_actions_visible(&self, visible: bool) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let _: () = msg_send![obj, setRowActionsVisible:match visible {
|
let _: () = msg_send![obj, setRowActionsVisible:match visible {
|
||||||
true => YES,
|
true => YES,
|
||||||
|
@ -586,7 +589,7 @@ impl<T> ListView<T> {
|
||||||
self.objc.get(|obj| unsafe { msg_send![obj, selectedRow] })
|
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
|
/// 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`.
|
/// is not an actual row, this will return `-1`.
|
||||||
///
|
///
|
||||||
|
@ -614,19 +617,19 @@ impl<T> ListView<T> {
|
||||||
|
|
||||||
impl<T> Layout for ListView<T> {
|
impl<T> Layout for ListView<T> {
|
||||||
fn with_backing_node<F: Fn(id)>(&self, handler: F) {
|
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.
|
// what to do normally.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
self.scrollview.objc.with_mut(handler);
|
self.scrollview.objc.with_mut(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_from_backing_node<F: Fn(&Object) -> R, R>(&self, handler: F) -> R {
|
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.
|
// what to do normally.
|
||||||
//
|
//
|
||||||
// @TODO: Review this, as property access isn't really used in the same place as layout
|
// @TODO: Review this, as property access isn't really used in the same place as layout
|
||||||
// stuff... hmm...
|
// stuff... hmm...
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
self.scrollview.objc.get(handler)
|
self.scrollview.objc.get(handler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,20 +55,20 @@ use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}
|
||||||
use crate::view::ViewDelegate;
|
use crate::view::ViewDelegate;
|
||||||
use crate::utils::properties::ObjcProperty;
|
use crate::utils::properties::ObjcProperty;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
mod macos;
|
mod appkit;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use macos::{register_listview_row_class, register_listview_row_class_with_delegate};
|
use appkit::{register_listview_row_class, register_listview_row_class_with_delegate};
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
//#[cfg(feature = "uikit")]
|
||||||
mod ios;
|
//mod ios;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
//#[cfg(feature = "uikit")]
|
||||||
use ios::{register_listview_row_view_class, register_listview_row_class_with_delegate};
|
//use ios::{register_listview_row_view_class, register_listview_row_class_with_delegate};
|
||||||
|
|
||||||
pub(crate) static BACKGROUND_COLOR: &str = "alchemyBackgroundColor";
|
pub(crate) static BACKGROUND_COLOR: &str = "cacaoBackgroundColor";
|
||||||
pub(crate) static LISTVIEW_ROW_DELEGATE_PTR: &str = "rstListViewRowDelegatePtr";
|
pub(crate) static LISTVIEW_ROW_DELEGATE_PTR: &str = "cacaoListViewRowDelegatePtr";
|
||||||
|
|
||||||
/// A helper method for instantiating view classes and applying default settings to them.
|
/// A helper method for instantiating view classes and applying default settings to them.
|
||||||
fn allocate_view(registration_fn: fn() -> *const Class) -> id {
|
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 view: id = msg_send![registration_fn(), new];
|
||||||
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let _: () = msg_send![view, setWantsLayer:YES];
|
let _: () = msg_send![view, setWantsLayer:YES];
|
||||||
|
|
||||||
view
|
view
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Various traits used for Views.
|
//! Various traits used for Views.
|
||||||
|
|
||||||
use crate::macos::menu::MenuItem;
|
use crate::appkit::menu::MenuItem;
|
||||||
use crate::dragdrop::{DragInfo, DragOperation};
|
use crate::dragdrop::{DragInfo, DragOperation};
|
||||||
use crate::listview::{ListView, ListViewRow, RowAction, RowEdge};
|
use crate::listview::{ListView, ListViewRow, RowAction, RowEdge};
|
||||||
use crate::layout::Layout;
|
use crate::layout::Layout;
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,12 +22,6 @@ use crate::color::Color;
|
||||||
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
|
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
|
||||||
use crate::utils::properties::ObjcProperty;
|
use crate::utils::properties::ObjcProperty;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
|
||||||
mod ios;
|
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
|
||||||
use ios::register_progress_indicator_class;
|
|
||||||
|
|
||||||
mod enums;
|
mod enums;
|
||||||
pub use enums::ProgressIndicatorStyle;
|
pub use enums::ProgressIndicatorStyle;
|
||||||
|
|
||||||
|
@ -79,11 +73,11 @@ impl ProgressIndicator {
|
||||||
/// need it to stay around.
|
/// need it to stay around.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let view = unsafe {
|
let view = unsafe {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let view: id = msg_send![class!(NSProgressIndicator), new];
|
let view: id = msg_send![class!(NSProgressIndicator), new];
|
||||||
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let _: () = msg_send![view, setWantsLayer:YES];
|
let _: () = msg_send![view, setWantsLayer:YES];
|
||||||
|
|
||||||
view
|
view
|
||||||
|
|
|
@ -51,16 +51,16 @@ use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}
|
||||||
use crate::pasteboard::PasteboardType;
|
use crate::pasteboard::PasteboardType;
|
||||||
use crate::utils::properties::ObjcProperty;
|
use crate::utils::properties::ObjcProperty;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
mod macos;
|
mod appkit;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use macos::{register_scrollview_class, register_scrollview_class_with_delegate};
|
use appkit::{register_scrollview_class, register_scrollview_class_with_delegate};
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
mod ios;
|
mod ios;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
use ios::{register_view_class, register_view_class_with_delegate};
|
use ios::{register_view_class, register_view_class_with_delegate};
|
||||||
|
|
||||||
mod traits;
|
mod traits;
|
||||||
|
@ -74,7 +74,7 @@ fn allocate_view(registration_fn: fn() -> *const Class) -> id {
|
||||||
let view: id = msg_send![registration_fn(), new];
|
let view: id = msg_send![registration_fn(), new];
|
||||||
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
{
|
{
|
||||||
let _: () = msg_send![view, setDrawsBackground:NO];
|
let _: () = msg_send![view, setDrawsBackground:NO];
|
||||||
let _: () = msg_send![view, setWantsLayer:YES];
|
let _: () = msg_send![view, setWantsLayer:YES];
|
||||||
|
|
|
@ -50,17 +50,17 @@ use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}
|
||||||
use crate::text::{Font, TextAlign, LineBreakMode};
|
use crate::text::{Font, TextAlign, LineBreakMode};
|
||||||
use crate::utils::properties::ObjcProperty;
|
use crate::utils::properties::ObjcProperty;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
mod macos;
|
mod appkit;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use macos::{register_view_class, register_view_class_with_delegate};
|
use appkit::{register_view_class, register_view_class_with_delegate};
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
mod ios;
|
mod uikit;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
use ios::{register_view_class, register_view_class_with_delegate};
|
use uikit::{register_view_class, register_view_class_with_delegate};
|
||||||
|
|
||||||
mod traits;
|
mod traits;
|
||||||
pub use traits::LabelDelegate;
|
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.
|
/// A helper method for instantiating view classes and applying default settings to them.
|
||||||
fn allocate_view(registration_fn: fn() -> *const Class) -> id {
|
fn allocate_view(registration_fn: fn() -> *const Class) -> id {
|
||||||
unsafe {
|
unsafe {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let view: id = {
|
let view: id = {
|
||||||
// This sucks, but for now, sure.
|
// This sucks, but for now, sure.
|
||||||
let blank = NSString::no_copy("");
|
let blank = NSString::no_copy("");
|
||||||
|
@ -82,7 +82,7 @@ fn allocate_view(registration_fn: fn() -> *const Class) -> id {
|
||||||
|
|
||||||
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let _: () = msg_send![view, setWantsLayer:YES];
|
let _: () = msg_send![view, setWantsLayer:YES];
|
||||||
|
|
||||||
view
|
view
|
||||||
|
@ -331,7 +331,7 @@ impl<T> Label<T> {
|
||||||
|
|
||||||
/// Set the line break mode for this label.
|
/// Set the line break mode for this label.
|
||||||
pub fn set_line_break_mode(&self, mode: LineBreakMode) {
|
pub fn set_line_break_mode(&self, mode: LineBreakMode) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let cell: id = msg_send![obj, cell];
|
let cell: id = msg_send![obj, cell];
|
||||||
let mode = mode as NSUInteger;
|
let mode = mode as NSUInteger;
|
||||||
|
|
|
@ -18,8 +18,8 @@ use url::Url;
|
||||||
use crate::foundation::{id, nil, BOOL, YES, NO, NSUInteger, NSArray, NSString};
|
use crate::foundation::{id, nil, BOOL, YES, NO, NSUInteger, NSArray, NSString};
|
||||||
//use crate::user_activity::UserActivity;
|
//use crate::user_activity::UserActivity;
|
||||||
|
|
||||||
use crate::ios::app::{AppDelegate, APP_DELEGATE};
|
use crate::uikit::app::{AppDelegate, APP_DELEGATE};
|
||||||
use crate::ios::scene::{SceneConfig, SceneConnectionOptions, SceneSession};
|
use crate::uikit::scene::{SceneConfig, SceneConnectionOptions, SceneSession};
|
||||||
|
|
||||||
#[cfg(feature = "cloudkit")]
|
#[cfg(feature = "cloudkit")]
|
||||||
use crate::cloudkit::share::CKShareMetaData;
|
use crate::cloudkit::share::CKShareMetaData;
|
|
@ -41,7 +41,7 @@ use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel, sel_impl};
|
||||||
|
|
||||||
use crate::foundation::{id, nil, YES, NO, NSString, NSUInteger, AutoReleasePool};
|
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::notification_center::Dispatcher;
|
||||||
use crate::utils::activate_cocoa_multithreading;
|
use crate::utils::activate_cocoa_multithreading;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
//use crate::error::Error;
|
//use crate::error::Error;
|
||||||
//use crate::user_activity::UserActivity;
|
//use crate::user_activity::UserActivity;
|
||||||
use crate::ios::scene::{SceneConfig, SceneConnectionOptions, SceneSession};
|
use crate::uikit::scene::{SceneConfig, SceneConnectionOptions, SceneSession};
|
||||||
|
|
||||||
#[cfg(feature = "cloudkit")]
|
#[cfg(feature = "cloudkit")]
|
||||||
use crate::cloudkit::share::CKShareMetaData;
|
use crate::cloudkit::share::CKShareMetaData;
|
|
@ -3,7 +3,7 @@ use objc::runtime::Object;
|
||||||
use objc_id::Id;
|
use objc_id::Id;
|
||||||
|
|
||||||
use crate::foundation::{id, NSString};
|
use crate::foundation::{id, NSString};
|
||||||
use crate::ios::scene::SessionRole;
|
use crate::uikit::scene::SessionRole;
|
||||||
|
|
||||||
/// A wrapper for UISceneConfiguration.
|
/// A wrapper for UISceneConfiguration.
|
||||||
///
|
///
|
|
@ -15,8 +15,8 @@ use crate::foundation::{id, nil, BOOL, YES, NO, NSUInteger, NSArray, NSString};
|
||||||
use crate::user_activity::UserActivity;
|
use crate::user_activity::UserActivity;
|
||||||
use crate::utils::load;
|
use crate::utils::load;
|
||||||
|
|
||||||
use crate::ios::app::{SCENE_DELEGATE_VENDOR};
|
use crate::uikit::app::{SCENE_DELEGATE_VENDOR};
|
||||||
use crate::ios::scene::{Scene, SceneConfig, SceneConnectionOptions, SceneSession, WindowSceneDelegate};
|
use crate::uikit::scene::{Scene, SceneConfig, SceneConnectionOptions, SceneSession, WindowSceneDelegate};
|
||||||
|
|
||||||
#[cfg(feature = "cloudkit")]
|
#[cfg(feature = "cloudkit")]
|
||||||
use crate::cloudkit::share::CKShareMetaData;
|
use crate::cloudkit::share::CKShareMetaData;
|
|
@ -3,7 +3,7 @@ use objc::runtime::Object;
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, sel, sel_impl};
|
||||||
|
|
||||||
use crate::foundation::{id, NSString};
|
use crate::foundation::{id, NSString};
|
||||||
use crate::ios::scene::enums::SessionRole;
|
use crate::uikit::scene::enums::SessionRole;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SceneSession(pub Id<Object>);
|
pub struct SceneSession(pub Id<Object>);
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::ios::scene::{Scene, SceneSession, SceneConnectionOptions};
|
use crate::uikit::scene::{Scene, SceneSession, SceneConnectionOptions};
|
||||||
|
|
||||||
pub trait WindowSceneDelegate {
|
pub trait WindowSceneDelegate {
|
||||||
fn will_connect(
|
fn will_connect(
|
|
@ -7,7 +7,7 @@ use objc_id::Id;
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
use crate::geometry::Rect;
|
use crate::geometry::Rect;
|
||||||
use crate::ios::Scene;
|
use crate::uikit::Scene;
|
||||||
use crate::utils::Controller;
|
use crate::utils::Controller;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
|
@ -7,20 +7,20 @@ use crate::layout::Layout;
|
||||||
use crate::view::{VIEW_DELEGATE_PTR, View, ViewDelegate};
|
use crate::view::{VIEW_DELEGATE_PTR, View, ViewDelegate};
|
||||||
use crate::utils::Controller;
|
use crate::utils::Controller;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
mod macos;
|
mod appkit;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use macos::register_view_controller_class;
|
use appkit::register_view_controller_class;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
mod ios;
|
mod uikit;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
use ios::register_view_controller_class;
|
use uikit::register_view_controller_class;
|
||||||
|
|
||||||
/// A `ViewController` is a wrapper around `NSViewController` on macOS, and `UIViewController` on
|
/// A `ViewController` is a wrapper around `NSViewController` in AppKit, and `UIViewController` in
|
||||||
/// iOS and tvOS.
|
/// UIKit
|
||||||
///
|
///
|
||||||
/// This type is interchangeable with a standard `View<T>`, in that using this simply forwards
|
/// 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
|
/// standard view controller lifecycle methods onto your `ViewDelegate`. You would use this if you
|
||||||
|
|
|
@ -50,33 +50,33 @@ use crate::layer::Layer;
|
||||||
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
|
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
|
||||||
use crate::utils::properties::ObjcProperty;
|
use crate::utils::properties::ObjcProperty;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use crate::pasteboard::PasteboardType;
|
use crate::pasteboard::PasteboardType;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
mod macos;
|
mod appkit;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
use macos::{register_view_class, register_view_class_with_delegate};
|
use appkit::{register_view_class, register_view_class_with_delegate};
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
mod ios;
|
mod uikit;
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
use ios::{register_view_class, register_view_class_with_delegate};
|
use uikit::{register_view_class, register_view_class_with_delegate};
|
||||||
|
|
||||||
mod controller;
|
mod controller;
|
||||||
pub use controller::ViewController;
|
pub use controller::ViewController;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
mod splitviewcontroller;
|
mod splitviewcontroller;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub use splitviewcontroller::SplitViewController;
|
pub use splitviewcontroller::SplitViewController;
|
||||||
|
|
||||||
mod traits;
|
mod traits;
|
||||||
pub use traits::ViewDelegate;
|
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";
|
pub(crate) static VIEW_DELEGATE_PTR: &str = "rstViewDelegatePtr";
|
||||||
|
|
||||||
/// A clone-able handler to a `ViewController` reference in the Objective C runtime. We use this
|
/// 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.
|
/// A pointer to the Objective-C runtime view controller.
|
||||||
pub objc: ObjcProperty,
|
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.
|
/// we explicitly opt in to layer backed views.
|
||||||
pub layer: Layer,
|
pub layer: Layer,
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ impl View {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
let _: () = msg_send![view, setWantsLayer:YES];
|
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) {
|
pub fn set_background_color<C: AsRef<Color>>(&self, color: C) {
|
||||||
let color: id = color.as_ref().into();
|
let color: id = color.as_ref().into();
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
(&mut *obj).set_ivar(BACKGROUND_COLOR, color);
|
(&mut *obj).set_ivar(BACKGROUND_COLOR, color);
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(feature = "uikit")]
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let _: () = msg_send![&*obj, setBackgroundColor:color];
|
let _: () = msg_send![&*obj, setBackgroundColor:color];
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,7 @@ use objc::{class, msg_send, sel, sel_impl};
|
||||||
|
|
||||||
use crate::foundation::{id, nil, NSString};
|
use crate::foundation::{id, nil, NSString};
|
||||||
use crate::layout::Layout;
|
use crate::layout::Layout;
|
||||||
use crate::macos::toolbar::ToolbarItem;
|
use crate::appkit::toolbar::ToolbarItem;
|
||||||
use crate::view::{View, ViewController, ViewDelegate};
|
use crate::view::{View, ViewController, ViewDelegate};
|
||||||
use crate::utils::{os, Controller};
|
use crate::utils::{os, Controller};
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ where
|
||||||
/// extend to the top of the window provided the other necessary window flags are set. On macOS
|
/// 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.
|
/// versions prior to Big Sur, this returns a standard SplitViewItem.
|
||||||
pub fn sidebar(view: T) -> Self {
|
pub fn sidebar(view: T) -> Self {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
if !os::is_minimum_version(11) {
|
if !os::is_minimum_version(11) {
|
||||||
return Self::item(view);
|
return Self::item(view);
|
||||||
}
|
}
|
||||||
|
@ -66,13 +68,20 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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`.
|
/// Sets the titlebar separator style for this `SplitView`.
|
||||||
///
|
///
|
||||||
/// You'd use this if, say, you wanted a border under one part of the `SplitViewController` but
|
/// 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
|
/// not the other. This API was introduced in macOS 11.0 (Big Sur) and is a noop on anything
|
||||||
/// prior.
|
/// prior.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(feature = "appkit")]
|
||||||
pub fn set_titlebar_separator_style(&self, style: crate::foundation::NSInteger) {
|
pub fn set_titlebar_separator_style(&self, style: crate::foundation::NSInteger) {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
if os::is_minimum_version(11) {
|
if os::is_minimum_version(11) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.objc, setTitlebarSeparatorStyle:style];
|
let _: () = msg_send![&*self.objc, setTitlebarSeparatorStyle:style];
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue